WIP: Remove global state from pi-ai OAuth/API key handling

- Remove setApiKey, resolveApiKey, and global apiKeys Map from stream.ts
- Rename getApiKey to getApiKeyFromEnv (only checks env vars)
- Remove OAuth storage layer (storage.ts deleted)
- OAuth login/refresh functions now return credentials instead of saving
- getOAuthApiKey/refreshOAuthToken now take credentials as params
- Add test/oauth.ts helper for ai package tests
- Simplify root npm run check (single biome + tsgo pass)
- Remove redundant check scripts from most packages
- Add web-ui and coding-agent examples to biome/tsgo includes

coding-agent still has compile errors - needs refactoring for new API
This commit is contained in:
Mario Zechner 2025-12-25 01:01:03 +01:00
parent d93cbf8c32
commit 030788140a
51 changed files with 646 additions and 570 deletions

View file

@ -1,8 +1,8 @@
import type { Message } from "@mariozechner/pi-ai";
import { html } from "lit";
import { registerMessageRenderer } from "@mariozechner/pi-web-ui";
import type { AppMessage, MessageRenderer } from "@mariozechner/pi-web-ui";
import { Alert } from "@mariozechner/mini-lit/dist/Alert.js";
import type { Message } from "@mariozechner/pi-ai";
import type { AppMessage, MessageRenderer } from "@mariozechner/pi-web-ui";
import { registerMessageRenderer } from "@mariozechner/pi-web-ui";
import { html } from "lit";
// ============================================================================
// 1. EXTEND AppMessage TYPE VIA DECLARATION MERGING
@ -85,10 +85,7 @@ export function customMessageTransformer(messages: AppMessage[]): Message[] {
// Keep LLM-compatible messages + custom messages
return (
m.role === "user" ||
m.role === "assistant" ||
m.role === "toolResult" ||
m.role === "system-notification"
m.role === "user" || m.role === "assistant" || m.role === "toolResult" || m.role === "system-notification"
);
})
.map((m) => {
@ -103,7 +100,7 @@ export function customMessageTransformer(messages: AppMessage[]): Message[] {
// Strip attachments from user messages
if (m.role === "user") {
const { attachments, ...rest } = m as any;
const { attachments: _, ...rest } = m as any;
return rest as Message;
}

View file

@ -7,27 +7,31 @@ import {
type AppMessage,
AppStorage,
ChatPanel,
createJavaScriptReplTool,
CustomProvidersStore,
createJavaScriptReplTool,
IndexedDBStorageBackend,
// PersistentStorageDialog, // TODO: Fix - currently broken
ProviderKeysStore,
ProviderTransport,
ProvidersModelsTab,
ProviderTransport,
ProxyTab,
SessionListDialog,
SessionsStore,
setAppStorage,
SettingsDialog,
SettingsStore,
setAppStorage,
} from "@mariozechner/pi-web-ui";
import { html, render } from "lit";
import { Bell, History, Plus, Settings } from "lucide";
import "./app.css";
import { createSystemNotification, customMessageTransformer, registerCustomMessageRenderers } from "./custom-messages.js";
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
import { icon } from "@mariozechner/mini-lit";
import { Button } from "@mariozechner/mini-lit/dist/Button.js";
import { Input } from "@mariozechner/mini-lit/dist/Input.js";
import {
createSystemNotification,
customMessageTransformer,
registerCustomMessageRenderers,
} from "./custom-messages.js";
// Register custom message renderers
registerCustomMessageRenderers();
@ -92,7 +96,7 @@ const generateTitle = (messages: AppMessage[]): string => {
if (sentenceEnd > 0 && sentenceEnd <= 50) {
return text.substring(0, sentenceEnd + 1);
}
return text.length <= 50 ? text : text.substring(0, 47) + "...";
return text.length <= 50 ? text : `${text.substring(0, 47)}...`;
};
const shouldSaveSession = (messages: AppMessage[]): boolean => {
@ -211,12 +215,12 @@ Feel free to use these tools when needed to provide accurate and helpful respons
onApiKeyRequired: async (provider: string) => {
return await ApiKeyPromptDialog.prompt(provider);
},
toolsFactory: (agent, agentInterface, artifactsPanel, runtimeProvidersFactory) => {
toolsFactory: (_agent, _agentInterface, _artifactsPanel, runtimeProvidersFactory) => {
// Create javascript_repl tool with access to attachments + artifacts
const replTool = createJavaScriptReplTool();
replTool.runtimeProvidersFactory = runtimeProvidersFactory;
return [replTool];
}
},
});
};
@ -290,9 +294,10 @@ const renderApp = () => {
title: "New Session",
})}
${currentTitle
? isEditingTitle
? html`<div class="flex items-center gap-2">
${
currentTitle
? isEditingTitle
? html`<div class="flex items-center gap-2">
${Input({
type: "text",
value: currentTitle,
@ -322,7 +327,7 @@ const renderApp = () => {
},
})}
</div>`
: html`<button
: html`<button
class="px-2 py-1 text-sm text-foreground hover:bg-secondary rounded transition-colors"
@click=${() => {
isEditingTitle = true;
@ -339,7 +344,8 @@ const renderApp = () => {
>
${currentTitle}
</button>`
: html`<span class="text-base font-semibold text-foreground">Pi Web UI Example</span>`}
: html`<span class="text-base font-semibold text-foreground">Pi Web UI Example</span>`
}
</div>
<div class="flex items-center gap-1 px-2">
${Button({
@ -350,7 +356,9 @@ const renderApp = () => {
// Demo: Inject custom message
if (agent) {
agent.appendMessage(
createSystemNotification("This is a custom message! It appears in the UI but is never sent to the LLM."),
createSystemNotification(
"This is a custom message! It appears in the UI but is never sent to the LLM.",
),
);
}
},