@mariozechner/pi-web-ui 0.5.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +252 -0
- package/dist/ChatPanel.d.ts +23 -0
- package/dist/ChatPanel.d.ts.map +1 -0
- package/dist/ChatPanel.js +224 -0
- package/dist/ChatPanel.js.map +1 -0
- package/dist/app.css +2 -0
- package/dist/components/AgentInterface.d.ts +35 -0
- package/dist/components/AgentInterface.d.ts.map +1 -0
- package/dist/components/AgentInterface.js +308 -0
- package/dist/components/AgentInterface.js.map +1 -0
- package/dist/components/AttachmentTile.d.ts +12 -0
- package/dist/components/AttachmentTile.d.ts.map +1 -0
- package/dist/components/AttachmentTile.js +114 -0
- package/dist/components/AttachmentTile.js.map +1 -0
- package/dist/components/ConsoleBlock.d.ts +11 -0
- package/dist/components/ConsoleBlock.d.ts.map +1 -0
- package/dist/components/ConsoleBlock.js +77 -0
- package/dist/components/ConsoleBlock.js.map +1 -0
- package/dist/components/Input.d.ts +26 -0
- package/dist/components/Input.d.ts.map +1 -0
- package/dist/components/Input.js +56 -0
- package/dist/components/Input.js.map +1 -0
- package/dist/components/MessageEditor.d.ts +38 -0
- package/dist/components/MessageEditor.d.ts.map +1 -0
- package/dist/components/MessageEditor.js +296 -0
- package/dist/components/MessageEditor.js.map +1 -0
- package/dist/components/MessageList.d.ts +13 -0
- package/dist/components/MessageList.d.ts.map +1 -0
- package/dist/components/MessageList.js +88 -0
- package/dist/components/MessageList.js.map +1 -0
- package/dist/components/Messages.d.ts +53 -0
- package/dist/components/Messages.d.ts.map +1 -0
- package/dist/components/Messages.js +323 -0
- package/dist/components/Messages.js.map +1 -0
- package/dist/components/ProviderKeyInput.d.ts +16 -0
- package/dist/components/ProviderKeyInput.d.ts.map +1 -0
- package/dist/components/ProviderKeyInput.js +183 -0
- package/dist/components/ProviderKeyInput.js.map +1 -0
- package/dist/components/SandboxedIframe.d.ts +63 -0
- package/dist/components/SandboxedIframe.d.ts.map +1 -0
- package/dist/components/SandboxedIframe.js +435 -0
- package/dist/components/SandboxedIframe.js.map +1 -0
- package/dist/components/StreamingMessageContainer.d.ts +17 -0
- package/dist/components/StreamingMessageContainer.d.ts.map +1 -0
- package/dist/components/StreamingMessageContainer.js +114 -0
- package/dist/components/StreamingMessageContainer.js.map +1 -0
- package/dist/dialogs/ApiKeyPromptDialog.d.ts +15 -0
- package/dist/dialogs/ApiKeyPromptDialog.d.ts.map +1 -0
- package/dist/dialogs/ApiKeyPromptDialog.js +80 -0
- package/dist/dialogs/ApiKeyPromptDialog.js.map +1 -0
- package/dist/dialogs/AttachmentOverlay.d.ts +32 -0
- package/dist/dialogs/AttachmentOverlay.d.ts.map +1 -0
- package/dist/dialogs/AttachmentOverlay.js +575 -0
- package/dist/dialogs/AttachmentOverlay.js.map +1 -0
- package/dist/dialogs/ModelSelector.d.ts +27 -0
- package/dist/dialogs/ModelSelector.d.ts.map +1 -0
- package/dist/dialogs/ModelSelector.js +334 -0
- package/dist/dialogs/ModelSelector.js.map +1 -0
- package/dist/dialogs/SettingsDialog.d.ts +31 -0
- package/dist/dialogs/SettingsDialog.d.ts.map +1 -0
- package/dist/dialogs/SettingsDialog.js +228 -0
- package/dist/dialogs/SettingsDialog.js.map +1 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/state/agent-session.d.ts +58 -0
- package/dist/state/agent-session.d.ts.map +1 -0
- package/dist/state/agent-session.js +252 -0
- package/dist/state/agent-session.js.map +1 -0
- package/dist/state/transports/AppTransport.d.ts +13 -0
- package/dist/state/transports/AppTransport.d.ts.map +1 -0
- package/dist/state/transports/AppTransport.js +316 -0
- package/dist/state/transports/AppTransport.js.map +1 -0
- package/dist/state/transports/ProviderTransport.d.ts +12 -0
- package/dist/state/transports/ProviderTransport.d.ts.map +1 -0
- package/dist/state/transports/ProviderTransport.js +44 -0
- package/dist/state/transports/ProviderTransport.js.map +1 -0
- package/dist/state/transports/index.d.ts +4 -0
- package/dist/state/transports/index.d.ts.map +1 -0
- package/dist/state/transports/index.js +4 -0
- package/dist/state/transports/index.js.map +1 -0
- package/dist/state/transports/proxy-types.d.ts +48 -0
- package/dist/state/transports/proxy-types.d.ts.map +1 -0
- package/dist/state/transports/proxy-types.js +2 -0
- package/dist/state/transports/proxy-types.js.map +1 -0
- package/dist/state/transports/types.d.ts +11 -0
- package/dist/state/transports/types.d.ts.map +1 -0
- package/dist/state/transports/types.js +2 -0
- package/dist/state/transports/types.js.map +1 -0
- package/dist/state/types.d.ts +15 -0
- package/dist/state/types.d.ts.map +1 -0
- package/dist/state/types.js +2 -0
- package/dist/state/types.js.map +1 -0
- package/dist/storage/app-storage.d.ts +26 -0
- package/dist/storage/app-storage.d.ts.map +1 -0
- package/dist/storage/app-storage.js +44 -0
- package/dist/storage/app-storage.js.map +1 -0
- package/dist/storage/backends/chrome-storage-backend.d.ts +18 -0
- package/dist/storage/backends/chrome-storage-backend.d.ts.map +1 -0
- package/dist/storage/backends/chrome-storage-backend.js +67 -0
- package/dist/storage/backends/chrome-storage-backend.js.map +1 -0
- package/dist/storage/backends/indexeddb-backend.d.ts +20 -0
- package/dist/storage/backends/indexeddb-backend.d.ts.map +1 -0
- package/dist/storage/backends/indexeddb-backend.js +89 -0
- package/dist/storage/backends/indexeddb-backend.js.map +1 -0
- package/dist/storage/backends/local-storage-backend.d.ts +18 -0
- package/dist/storage/backends/local-storage-backend.d.ts.map +1 -0
- package/dist/storage/backends/local-storage-backend.js +69 -0
- package/dist/storage/backends/local-storage-backend.js.map +1 -0
- package/dist/storage/repositories/provider-keys-repository.d.ts +34 -0
- package/dist/storage/repositories/provider-keys-repository.d.ts.map +1 -0
- package/dist/storage/repositories/provider-keys-repository.js +50 -0
- package/dist/storage/repositories/provider-keys-repository.js.map +1 -0
- package/dist/storage/repositories/settings-repository.d.ts +34 -0
- package/dist/storage/repositories/settings-repository.d.ts.map +1 -0
- package/dist/storage/repositories/settings-repository.js +46 -0
- package/dist/storage/repositories/settings-repository.js.map +1 -0
- package/dist/storage/types.d.ts +43 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +2 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/tools/artifacts/ArtifactElement.d.ts +10 -0
- package/dist/tools/artifacts/ArtifactElement.d.ts.map +1 -0
- package/dist/tools/artifacts/ArtifactElement.js +12 -0
- package/dist/tools/artifacts/ArtifactElement.js.map +1 -0
- package/dist/tools/artifacts/HtmlArtifact.d.ts +30 -0
- package/dist/tools/artifacts/HtmlArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/HtmlArtifact.js +217 -0
- package/dist/tools/artifacts/HtmlArtifact.js.map +1 -0
- package/dist/tools/artifacts/MarkdownArtifact.d.ts +20 -0
- package/dist/tools/artifacts/MarkdownArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/MarkdownArtifact.js +84 -0
- package/dist/tools/artifacts/MarkdownArtifact.js.map +1 -0
- package/dist/tools/artifacts/SvgArtifact.d.ts +19 -0
- package/dist/tools/artifacts/SvgArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/SvgArtifact.js +80 -0
- package/dist/tools/artifacts/SvgArtifact.js.map +1 -0
- package/dist/tools/artifacts/TextArtifact.d.ts +20 -0
- package/dist/tools/artifacts/TextArtifact.d.ts.map +1 -0
- package/dist/tools/artifacts/TextArtifact.js +147 -0
- package/dist/tools/artifacts/TextArtifact.js.map +1 -0
- package/dist/tools/artifacts/artifacts.d.ts +67 -0
- package/dist/tools/artifacts/artifacts.d.ts.map +1 -0
- package/dist/tools/artifacts/artifacts.js +836 -0
- package/dist/tools/artifacts/artifacts.js.map +1 -0
- package/dist/tools/artifacts/index.d.ts +7 -0
- package/dist/tools/artifacts/index.d.ts.map +1 -0
- package/dist/tools/artifacts/index.js +7 -0
- package/dist/tools/artifacts/index.js.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +29 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/javascript-repl.d.ts +43 -0
- package/dist/tools/javascript-repl.d.ts.map +1 -0
- package/dist/tools/javascript-repl.js +252 -0
- package/dist/tools/javascript-repl.js.map +1 -0
- package/dist/tools/renderer-registry.d.ts +11 -0
- package/dist/tools/renderer-registry.d.ts.map +1 -0
- package/dist/tools/renderer-registry.js +15 -0
- package/dist/tools/renderer-registry.js.map +1 -0
- package/dist/tools/renderers/BashRenderer.d.ts +12 -0
- package/dist/tools/renderers/BashRenderer.d.ts.map +1 -0
- package/dist/tools/renderers/BashRenderer.js +35 -0
- package/dist/tools/renderers/BashRenderer.js.map +1 -0
- package/dist/tools/renderers/CalculateRenderer.d.ts +12 -0
- package/dist/tools/renderers/CalculateRenderer.d.ts.map +1 -0
- package/dist/tools/renderers/CalculateRenderer.js +38 -0
- package/dist/tools/renderers/CalculateRenderer.js.map +1 -0
- package/dist/tools/renderers/DefaultRenderer.d.ts +8 -0
- package/dist/tools/renderers/DefaultRenderer.d.ts.map +1 -0
- package/dist/tools/renderers/DefaultRenderer.js +31 -0
- package/dist/tools/renderers/DefaultRenderer.js.map +1 -0
- package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts +12 -0
- package/dist/tools/renderers/GetCurrentTimeRenderer.d.ts.map +1 -0
- package/dist/tools/renderers/GetCurrentTimeRenderer.js +30 -0
- package/dist/tools/renderers/GetCurrentTimeRenderer.js.map +1 -0
- package/dist/tools/types.d.ts +7 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/utils/attachment-utils.d.ts +19 -0
- package/dist/utils/attachment-utils.d.ts.map +1 -0
- package/dist/utils/attachment-utils.js +415 -0
- package/dist/utils/attachment-utils.js.map +1 -0
- package/dist/utils/auth-token.d.ts +3 -0
- package/dist/utils/auth-token.d.ts.map +1 -0
- package/dist/utils/auth-token.js +19 -0
- package/dist/utils/auth-token.js.map +1 -0
- package/dist/utils/format.d.ts +6 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +47 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/i18n.d.ts +111 -0
- package/dist/utils/i18n.d.ts.map +1 -0
- package/dist/utils/i18n.js +224 -0
- package/dist/utils/i18n.js.map +1 -0
- package/dist/utils/test-sessions.d.ts +347 -0
- package/dist/utils/test-sessions.d.ts.map +1 -0
- package/dist/utils/test-sessions.js +2215 -0
- package/dist/utils/test-sessions.js.map +1 -0
- package/example/README.md +61 -0
- package/example/index.html +13 -0
- package/example/package-lock.json +1965 -0
- package/example/package.json +22 -0
- package/example/src/app.css +1 -0
- package/example/src/main.ts +57 -0
- package/example/src/test-sessions.ts +104 -0
- package/example/tsconfig.json +15 -0
- package/example/vite.config.ts +6 -0
- package/package.json +45 -0
- package/src/ChatPanel.ts +214 -0
- package/src/app.css +44 -0
- package/src/components/AgentInterface.ts +316 -0
- package/src/components/AttachmentTile.ts +112 -0
- package/src/components/ConsoleBlock.ts +67 -0
- package/src/components/Input.ts +112 -0
- package/src/components/MessageEditor.ts +272 -0
- package/src/components/MessageList.ts +82 -0
- package/src/components/Messages.ts +310 -0
- package/src/components/ProviderKeyInput.ts +170 -0
- package/src/components/SandboxedIframe.ts +525 -0
- package/src/components/StreamingMessageContainer.ts +101 -0
- package/src/dialogs/ApiKeyPromptDialog.ts +76 -0
- package/src/dialogs/AttachmentOverlay.ts +635 -0
- package/src/dialogs/ModelSelector.ts +324 -0
- package/src/dialogs/SettingsDialog.ts +223 -0
- package/src/index.ts +63 -0
- package/src/state/agent-session.ts +311 -0
- package/src/state/transports/AppTransport.ts +363 -0
- package/src/state/transports/ProviderTransport.ts +49 -0
- package/src/state/transports/index.ts +3 -0
- package/src/state/transports/proxy-types.ts +15 -0
- package/src/state/transports/types.ts +16 -0
- package/src/state/types.ts +11 -0
- package/src/storage/app-storage.ts +53 -0
- package/src/storage/backends/chrome-storage-backend.ts +82 -0
- package/src/storage/backends/indexeddb-backend.ts +107 -0
- package/src/storage/backends/local-storage-backend.ts +74 -0
- package/src/storage/repositories/provider-keys-repository.ts +55 -0
- package/src/storage/repositories/settings-repository.ts +51 -0
- package/src/storage/types.ts +48 -0
- package/src/tools/artifacts/ArtifactElement.ts +15 -0
- package/src/tools/artifacts/HtmlArtifact.ts +221 -0
- package/src/tools/artifacts/MarkdownArtifact.ts +81 -0
- package/src/tools/artifacts/SvgArtifact.ts +77 -0
- package/src/tools/artifacts/TextArtifact.ts +148 -0
- package/src/tools/artifacts/artifacts.ts +888 -0
- package/src/tools/artifacts/index.ts +6 -0
- package/src/tools/index.ts +35 -0
- package/src/tools/javascript-repl.ts +309 -0
- package/src/tools/renderer-registry.ts +18 -0
- package/src/tools/renderers/BashRenderer.ts +45 -0
- package/src/tools/renderers/CalculateRenderer.ts +49 -0
- package/src/tools/renderers/DefaultRenderer.ts +36 -0
- package/src/tools/renderers/GetCurrentTimeRenderer.ts +39 -0
- package/src/tools/types.ts +7 -0
- package/src/utils/attachment-utils.ts +472 -0
- package/src/utils/auth-token.ts +22 -0
- package/src/utils/format.ts +42 -0
- package/src/utils/i18n.ts +343 -0
- package/src/utils/test-sessions.ts +2247 -0
- package/tsconfig.build.json +20 -0
- package/tsconfig.json +7 -0
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import type { Context } from "@mariozechner/pi-ai";
|
|
2
|
+
import {
|
|
3
|
+
type AgentTool,
|
|
4
|
+
type AssistantMessage as AssistantMessageType,
|
|
5
|
+
getModel,
|
|
6
|
+
type ImageContent,
|
|
7
|
+
type Message,
|
|
8
|
+
type Model,
|
|
9
|
+
type TextContent,
|
|
10
|
+
} from "@mariozechner/pi-ai";
|
|
11
|
+
import type { AppMessage } from "../components/Messages.js";
|
|
12
|
+
import type { Attachment } from "../utils/attachment-utils.js";
|
|
13
|
+
import { AppTransport } from "./transports/AppTransport.js";
|
|
14
|
+
import { ProviderTransport } from "./transports/ProviderTransport.js";
|
|
15
|
+
import type { AgentRunConfig, AgentTransport } from "./transports/types.js";
|
|
16
|
+
import type { DebugLogEntry } from "./types.js";
|
|
17
|
+
|
|
18
|
+
export type ThinkingLevel = "off" | "minimal" | "low" | "medium" | "high";
|
|
19
|
+
|
|
20
|
+
export interface AgentSessionState {
|
|
21
|
+
id: string;
|
|
22
|
+
systemPrompt: string;
|
|
23
|
+
model: Model<any> | null;
|
|
24
|
+
thinkingLevel: ThinkingLevel;
|
|
25
|
+
tools: AgentTool<any>[];
|
|
26
|
+
messages: AppMessage[];
|
|
27
|
+
isStreaming: boolean;
|
|
28
|
+
streamMessage: Message | null;
|
|
29
|
+
pendingToolCalls: Set<string>;
|
|
30
|
+
error?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type AgentSessionEvent =
|
|
34
|
+
| { type: "state-update"; state: AgentSessionState }
|
|
35
|
+
| { type: "error-no-model" }
|
|
36
|
+
| { type: "error-no-api-key"; provider: string };
|
|
37
|
+
|
|
38
|
+
export type TransportMode = "provider" | "app";
|
|
39
|
+
|
|
40
|
+
export interface AgentSessionOptions {
|
|
41
|
+
initialState?: Partial<AgentSessionState>;
|
|
42
|
+
messagePreprocessor?: (messages: AppMessage[]) => Promise<Message[]>;
|
|
43
|
+
debugListener?: (entry: DebugLogEntry) => void;
|
|
44
|
+
transportMode?: TransportMode;
|
|
45
|
+
authTokenProvider?: () => Promise<string | undefined>;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class AgentSession {
|
|
49
|
+
private _state: AgentSessionState = {
|
|
50
|
+
id: "default",
|
|
51
|
+
systemPrompt: "",
|
|
52
|
+
model: getModel("google", "gemini-2.5-flash-lite-preview-06-17"),
|
|
53
|
+
thinkingLevel: "off",
|
|
54
|
+
tools: [],
|
|
55
|
+
messages: [],
|
|
56
|
+
isStreaming: false,
|
|
57
|
+
streamMessage: null,
|
|
58
|
+
pendingToolCalls: new Set<string>(),
|
|
59
|
+
error: undefined,
|
|
60
|
+
};
|
|
61
|
+
private listeners = new Set<(e: AgentSessionEvent) => void>();
|
|
62
|
+
private abortController?: AbortController;
|
|
63
|
+
private transport: AgentTransport;
|
|
64
|
+
private messagePreprocessor?: (messages: AppMessage[]) => Promise<Message[]>;
|
|
65
|
+
private debugListener?: (entry: DebugLogEntry) => void;
|
|
66
|
+
|
|
67
|
+
constructor(opts: AgentSessionOptions = {}) {
|
|
68
|
+
this._state = { ...this._state, ...opts.initialState };
|
|
69
|
+
this.messagePreprocessor = opts.messagePreprocessor;
|
|
70
|
+
this.debugListener = opts.debugListener;
|
|
71
|
+
|
|
72
|
+
const mode = opts.transportMode || "provider";
|
|
73
|
+
|
|
74
|
+
if (mode === "app") {
|
|
75
|
+
this.transport = new AppTransport(async () => this.preprocessMessages());
|
|
76
|
+
} else {
|
|
77
|
+
this.transport = new ProviderTransport(async () => this.preprocessMessages());
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private async preprocessMessages(): Promise<Message[]> {
|
|
82
|
+
const filtered = this._state.messages.map((m) => {
|
|
83
|
+
if (m.role === "user") {
|
|
84
|
+
const { attachments, ...rest } = m as AppMessage & { attachments?: Attachment[] };
|
|
85
|
+
return rest;
|
|
86
|
+
}
|
|
87
|
+
return m;
|
|
88
|
+
});
|
|
89
|
+
return this.messagePreprocessor ? this.messagePreprocessor(filtered as AppMessage[]) : (filtered as Message[]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get state(): AgentSessionState {
|
|
93
|
+
return this._state;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
subscribe(fn: (e: AgentSessionEvent) => void): () => void {
|
|
97
|
+
this.listeners.add(fn);
|
|
98
|
+
fn({ type: "state-update", state: this._state });
|
|
99
|
+
return () => this.listeners.delete(fn);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Mutators
|
|
103
|
+
setSystemPrompt(v: string) {
|
|
104
|
+
this.patch({ systemPrompt: v });
|
|
105
|
+
}
|
|
106
|
+
setModel(m: Model<any> | null) {
|
|
107
|
+
this.patch({ model: m });
|
|
108
|
+
}
|
|
109
|
+
setThinkingLevel(l: ThinkingLevel) {
|
|
110
|
+
this.patch({ thinkingLevel: l });
|
|
111
|
+
}
|
|
112
|
+
setTools(t: AgentTool<any>[]) {
|
|
113
|
+
this.patch({ tools: t });
|
|
114
|
+
}
|
|
115
|
+
replaceMessages(ms: AppMessage[]) {
|
|
116
|
+
this.patch({ messages: ms.slice() });
|
|
117
|
+
}
|
|
118
|
+
appendMessage(m: AppMessage) {
|
|
119
|
+
this.patch({ messages: [...this._state.messages, m] });
|
|
120
|
+
}
|
|
121
|
+
clearMessages() {
|
|
122
|
+
this.patch({ messages: [] });
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
abort() {
|
|
126
|
+
this.abortController?.abort();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
async prompt(input: string, attachments?: Attachment[]) {
|
|
130
|
+
const model = this._state.model;
|
|
131
|
+
if (!model) {
|
|
132
|
+
this.emit({ type: "error-no-model" });
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Build user message with attachments
|
|
137
|
+
const content: Array<TextContent | ImageContent> = [{ type: "text", text: input }];
|
|
138
|
+
if (attachments?.length) {
|
|
139
|
+
for (const a of attachments) {
|
|
140
|
+
if (a.type === "image") {
|
|
141
|
+
content.push({ type: "image", data: a.content, mimeType: a.mimeType });
|
|
142
|
+
} else if (a.type === "document" && a.extractedText) {
|
|
143
|
+
content.push({
|
|
144
|
+
type: "text",
|
|
145
|
+
text: `\n\n[Document: ${a.fileName}]\n${a.extractedText}`,
|
|
146
|
+
isDocument: true,
|
|
147
|
+
} as TextContent);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const userMessage: AppMessage = {
|
|
153
|
+
role: "user",
|
|
154
|
+
content,
|
|
155
|
+
attachments: attachments?.length ? attachments : undefined,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
this.abortController = new AbortController();
|
|
159
|
+
this.patch({ isStreaming: true, streamMessage: null, error: undefined });
|
|
160
|
+
|
|
161
|
+
const reasoning =
|
|
162
|
+
this._state.thinkingLevel === "off"
|
|
163
|
+
? undefined
|
|
164
|
+
: this._state.thinkingLevel === "minimal"
|
|
165
|
+
? "low"
|
|
166
|
+
: this._state.thinkingLevel;
|
|
167
|
+
const cfg: AgentRunConfig = {
|
|
168
|
+
systemPrompt: this._state.systemPrompt,
|
|
169
|
+
tools: this._state.tools,
|
|
170
|
+
model,
|
|
171
|
+
reasoning,
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
let partial: Message | null = null;
|
|
176
|
+
let turnDebug: DebugLogEntry | null = null;
|
|
177
|
+
let turnStart = 0;
|
|
178
|
+
for await (const ev of this.transport.run(userMessage as Message, cfg, this.abortController.signal)) {
|
|
179
|
+
switch (ev.type) {
|
|
180
|
+
case "turn_start": {
|
|
181
|
+
turnStart = performance.now();
|
|
182
|
+
// Build request context snapshot
|
|
183
|
+
const existing = this._state.messages as Message[];
|
|
184
|
+
const ctx: Context = {
|
|
185
|
+
systemPrompt: this._state.systemPrompt,
|
|
186
|
+
messages: [...existing],
|
|
187
|
+
tools: this._state.tools,
|
|
188
|
+
};
|
|
189
|
+
turnDebug = {
|
|
190
|
+
timestamp: new Date().toISOString(),
|
|
191
|
+
request: {
|
|
192
|
+
provider: cfg.model.provider,
|
|
193
|
+
model: cfg.model.id,
|
|
194
|
+
context: { ...ctx },
|
|
195
|
+
},
|
|
196
|
+
sseEvents: [],
|
|
197
|
+
};
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case "message_start":
|
|
201
|
+
case "message_update": {
|
|
202
|
+
partial = ev.message;
|
|
203
|
+
// Collect SSE-like events for debug (drop heavy partial)
|
|
204
|
+
if (ev.type === "message_update" && ev.assistantMessageEvent && turnDebug) {
|
|
205
|
+
const copy: any = { ...ev.assistantMessageEvent };
|
|
206
|
+
if (copy && "partial" in copy) delete copy.partial;
|
|
207
|
+
turnDebug.sseEvents.push(JSON.stringify(copy));
|
|
208
|
+
if (!turnDebug.ttft) turnDebug.ttft = performance.now() - turnStart;
|
|
209
|
+
}
|
|
210
|
+
this.patch({ streamMessage: ev.message });
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
case "message_end": {
|
|
214
|
+
partial = null;
|
|
215
|
+
this.appendMessage(ev.message as AppMessage);
|
|
216
|
+
this.patch({ streamMessage: null });
|
|
217
|
+
if (turnDebug) {
|
|
218
|
+
if (ev.message.role !== "assistant" && ev.message.role !== "toolResult") {
|
|
219
|
+
turnDebug.request.context.messages.push(ev.message);
|
|
220
|
+
}
|
|
221
|
+
if (ev.message.role === "assistant") turnDebug.response = ev.message as any;
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case "tool_execution_start": {
|
|
226
|
+
const s = new Set(this._state.pendingToolCalls);
|
|
227
|
+
s.add(ev.toolCallId);
|
|
228
|
+
this.patch({ pendingToolCalls: s });
|
|
229
|
+
break;
|
|
230
|
+
}
|
|
231
|
+
case "tool_execution_end": {
|
|
232
|
+
const s = new Set(this._state.pendingToolCalls);
|
|
233
|
+
s.delete(ev.toolCallId);
|
|
234
|
+
this.patch({ pendingToolCalls: s });
|
|
235
|
+
break;
|
|
236
|
+
}
|
|
237
|
+
case "turn_end": {
|
|
238
|
+
// finalize current turn
|
|
239
|
+
if (turnDebug) {
|
|
240
|
+
turnDebug.totalTime = performance.now() - turnStart;
|
|
241
|
+
this.debugListener?.(turnDebug);
|
|
242
|
+
turnDebug = null;
|
|
243
|
+
}
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
case "agent_end": {
|
|
247
|
+
this.patch({ streamMessage: null });
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (partial && partial.role === "assistant" && partial.content.length > 0) {
|
|
254
|
+
const onlyEmpty = !partial.content.some(
|
|
255
|
+
(c) =>
|
|
256
|
+
(c.type === "thinking" && c.thinking.trim().length > 0) ||
|
|
257
|
+
(c.type === "text" && c.text.trim().length > 0) ||
|
|
258
|
+
(c.type === "toolCall" && c.name.trim().length > 0),
|
|
259
|
+
);
|
|
260
|
+
if (!onlyEmpty) {
|
|
261
|
+
this.appendMessage(partial as AppMessage);
|
|
262
|
+
} else {
|
|
263
|
+
if (this.abortController?.signal.aborted) {
|
|
264
|
+
throw new Error("Request was aborted");
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} catch (err: any) {
|
|
269
|
+
if (String(err?.message || err) === "no-api-key") {
|
|
270
|
+
this.emit({ type: "error-no-api-key", provider: model.provider });
|
|
271
|
+
} else {
|
|
272
|
+
const msg: AssistantMessageType = {
|
|
273
|
+
role: "assistant",
|
|
274
|
+
content: [{ type: "text", text: "" }],
|
|
275
|
+
api: model.api,
|
|
276
|
+
provider: model.provider,
|
|
277
|
+
model: model.id,
|
|
278
|
+
usage: {
|
|
279
|
+
input: 0,
|
|
280
|
+
output: 0,
|
|
281
|
+
cacheRead: 0,
|
|
282
|
+
cacheWrite: 0,
|
|
283
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
284
|
+
},
|
|
285
|
+
stopReason: this.abortController?.signal.aborted ? "aborted" : "error",
|
|
286
|
+
errorMessage: err?.message || String(err),
|
|
287
|
+
};
|
|
288
|
+
this.appendMessage(msg as AppMessage);
|
|
289
|
+
this.patch({ error: err?.message || String(err) });
|
|
290
|
+
}
|
|
291
|
+
} finally {
|
|
292
|
+
this.patch({ isStreaming: false, streamMessage: null, pendingToolCalls: new Set<string>() });
|
|
293
|
+
this.abortController = undefined;
|
|
294
|
+
}
|
|
295
|
+
{
|
|
296
|
+
const { systemPrompt, model, messages } = this._state;
|
|
297
|
+
console.log("final state:", { systemPrompt, model, messages });
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
private patch(p: Partial<AgentSessionState>): void {
|
|
302
|
+
this._state = { ...this._state, ...p };
|
|
303
|
+
this.emit({ type: "state-update", state: this._state });
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
private emit(e: AgentSessionEvent) {
|
|
307
|
+
for (const listener of this.listeners) {
|
|
308
|
+
listener(e);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentContext,
|
|
3
|
+
Api,
|
|
4
|
+
AssistantMessage,
|
|
5
|
+
AssistantMessageEvent,
|
|
6
|
+
Context,
|
|
7
|
+
Message,
|
|
8
|
+
Model,
|
|
9
|
+
PromptConfig,
|
|
10
|
+
SimpleStreamOptions,
|
|
11
|
+
ToolCall,
|
|
12
|
+
UserMessage,
|
|
13
|
+
} from "@mariozechner/pi-ai";
|
|
14
|
+
import { agentLoop } from "@mariozechner/pi-ai";
|
|
15
|
+
import { AssistantMessageEventStream } from "@mariozechner/pi-ai/dist/utils/event-stream.js";
|
|
16
|
+
import { parseStreamingJson } from "@mariozechner/pi-ai/dist/utils/json-parse.js";
|
|
17
|
+
import { clearAuthToken, getAuthToken } from "../../utils/auth-token.js";
|
|
18
|
+
import { i18n } from "../../utils/i18n.js";
|
|
19
|
+
import type { ProxyAssistantMessageEvent } from "./proxy-types.js";
|
|
20
|
+
import type { AgentRunConfig, AgentTransport } from "./types.js";
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Stream function that proxies through a server instead of calling providers directly.
|
|
24
|
+
* The server strips the partial field from delta events to reduce bandwidth.
|
|
25
|
+
* We reconstruct the partial message client-side.
|
|
26
|
+
*/
|
|
27
|
+
function streamSimpleProxy(
|
|
28
|
+
model: Model<any>,
|
|
29
|
+
context: Context,
|
|
30
|
+
options: SimpleStreamOptions & { authToken: string },
|
|
31
|
+
proxyUrl: string,
|
|
32
|
+
): AssistantMessageEventStream {
|
|
33
|
+
const stream = new AssistantMessageEventStream();
|
|
34
|
+
|
|
35
|
+
(async () => {
|
|
36
|
+
// Initialize the partial message that we'll build up from events
|
|
37
|
+
const partial: AssistantMessage = {
|
|
38
|
+
role: "assistant",
|
|
39
|
+
stopReason: "stop",
|
|
40
|
+
content: [],
|
|
41
|
+
api: model.api,
|
|
42
|
+
provider: model.provider,
|
|
43
|
+
model: model.id,
|
|
44
|
+
usage: {
|
|
45
|
+
input: 0,
|
|
46
|
+
output: 0,
|
|
47
|
+
cacheRead: 0,
|
|
48
|
+
cacheWrite: 0,
|
|
49
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;
|
|
54
|
+
|
|
55
|
+
// Set up abort handler to cancel the reader
|
|
56
|
+
const abortHandler = () => {
|
|
57
|
+
if (reader) {
|
|
58
|
+
reader.cancel("Request aborted by user").catch(() => {});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
if (options.signal) {
|
|
63
|
+
options.signal.addEventListener("abort", abortHandler);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(`${proxyUrl}/api/stream`, {
|
|
68
|
+
method: "POST",
|
|
69
|
+
headers: {
|
|
70
|
+
Authorization: `Bearer ${options.authToken}`,
|
|
71
|
+
"Content-Type": "application/json",
|
|
72
|
+
},
|
|
73
|
+
body: JSON.stringify({
|
|
74
|
+
model,
|
|
75
|
+
context,
|
|
76
|
+
options: {
|
|
77
|
+
temperature: options.temperature,
|
|
78
|
+
maxTokens: options.maxTokens,
|
|
79
|
+
reasoning: options.reasoning,
|
|
80
|
+
// Don't send apiKey or signal - those are added server-side
|
|
81
|
+
},
|
|
82
|
+
}),
|
|
83
|
+
signal: options.signal,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
if (!response.ok) {
|
|
87
|
+
let errorMessage = `Proxy error: ${response.status} ${response.statusText}`;
|
|
88
|
+
try {
|
|
89
|
+
const errorData = await response.json();
|
|
90
|
+
if (errorData.error) {
|
|
91
|
+
errorMessage = `Proxy error: ${errorData.error}`;
|
|
92
|
+
}
|
|
93
|
+
} catch {
|
|
94
|
+
// Couldn't parse error response, use default message
|
|
95
|
+
}
|
|
96
|
+
throw new Error(errorMessage);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Parse SSE stream
|
|
100
|
+
reader = response.body!.getReader();
|
|
101
|
+
const decoder = new TextDecoder();
|
|
102
|
+
let buffer = "";
|
|
103
|
+
|
|
104
|
+
while (true) {
|
|
105
|
+
const { done, value } = await reader.read();
|
|
106
|
+
if (done) break;
|
|
107
|
+
|
|
108
|
+
// Check if aborted after reading
|
|
109
|
+
if (options.signal?.aborted) {
|
|
110
|
+
throw new Error("Request aborted by user");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
buffer += decoder.decode(value, { stream: true });
|
|
114
|
+
const lines = buffer.split("\n");
|
|
115
|
+
buffer = lines.pop() || "";
|
|
116
|
+
|
|
117
|
+
for (const line of lines) {
|
|
118
|
+
if (line.startsWith("data: ")) {
|
|
119
|
+
const data = line.slice(6).trim();
|
|
120
|
+
if (data) {
|
|
121
|
+
const proxyEvent = JSON.parse(data) as ProxyAssistantMessageEvent;
|
|
122
|
+
let event: AssistantMessageEvent | undefined;
|
|
123
|
+
|
|
124
|
+
// Handle different event types
|
|
125
|
+
// Server sends events with partial for non-delta events,
|
|
126
|
+
// and without partial for delta events
|
|
127
|
+
switch (proxyEvent.type) {
|
|
128
|
+
case "start":
|
|
129
|
+
event = { type: "start", partial };
|
|
130
|
+
break;
|
|
131
|
+
|
|
132
|
+
case "text_start":
|
|
133
|
+
partial.content[proxyEvent.contentIndex] = {
|
|
134
|
+
type: "text",
|
|
135
|
+
text: "",
|
|
136
|
+
};
|
|
137
|
+
event = { type: "text_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
138
|
+
break;
|
|
139
|
+
|
|
140
|
+
case "text_delta": {
|
|
141
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
142
|
+
if (content?.type === "text") {
|
|
143
|
+
content.text += proxyEvent.delta;
|
|
144
|
+
event = {
|
|
145
|
+
type: "text_delta",
|
|
146
|
+
contentIndex: proxyEvent.contentIndex,
|
|
147
|
+
delta: proxyEvent.delta,
|
|
148
|
+
partial,
|
|
149
|
+
};
|
|
150
|
+
} else {
|
|
151
|
+
throw new Error("Received text_delta for non-text content");
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case "text_end": {
|
|
156
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
157
|
+
if (content?.type === "text") {
|
|
158
|
+
content.textSignature = proxyEvent.contentSignature;
|
|
159
|
+
event = {
|
|
160
|
+
type: "text_end",
|
|
161
|
+
contentIndex: proxyEvent.contentIndex,
|
|
162
|
+
content: content.text,
|
|
163
|
+
partial,
|
|
164
|
+
};
|
|
165
|
+
} else {
|
|
166
|
+
throw new Error("Received text_end for non-text content");
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
case "thinking_start":
|
|
172
|
+
partial.content[proxyEvent.contentIndex] = {
|
|
173
|
+
type: "thinking",
|
|
174
|
+
thinking: "",
|
|
175
|
+
};
|
|
176
|
+
event = { type: "thinking_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
177
|
+
break;
|
|
178
|
+
|
|
179
|
+
case "thinking_delta": {
|
|
180
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
181
|
+
if (content?.type === "thinking") {
|
|
182
|
+
content.thinking += proxyEvent.delta;
|
|
183
|
+
event = {
|
|
184
|
+
type: "thinking_delta",
|
|
185
|
+
contentIndex: proxyEvent.contentIndex,
|
|
186
|
+
delta: proxyEvent.delta,
|
|
187
|
+
partial,
|
|
188
|
+
};
|
|
189
|
+
} else {
|
|
190
|
+
throw new Error("Received thinking_delta for non-thinking content");
|
|
191
|
+
}
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
case "thinking_end": {
|
|
196
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
197
|
+
if (content?.type === "thinking") {
|
|
198
|
+
content.thinkingSignature = proxyEvent.contentSignature;
|
|
199
|
+
event = {
|
|
200
|
+
type: "thinking_end",
|
|
201
|
+
contentIndex: proxyEvent.contentIndex,
|
|
202
|
+
content: content.thinking,
|
|
203
|
+
partial,
|
|
204
|
+
};
|
|
205
|
+
} else {
|
|
206
|
+
throw new Error("Received thinking_end for non-thinking content");
|
|
207
|
+
}
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
case "toolcall_start":
|
|
212
|
+
partial.content[proxyEvent.contentIndex] = {
|
|
213
|
+
type: "toolCall",
|
|
214
|
+
id: proxyEvent.id,
|
|
215
|
+
name: proxyEvent.toolName,
|
|
216
|
+
arguments: {},
|
|
217
|
+
partialJson: "",
|
|
218
|
+
} satisfies ToolCall & { partialJson: string } as ToolCall;
|
|
219
|
+
event = { type: "toolcall_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
220
|
+
break;
|
|
221
|
+
|
|
222
|
+
case "toolcall_delta": {
|
|
223
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
224
|
+
if (content?.type === "toolCall") {
|
|
225
|
+
(content as any).partialJson += proxyEvent.delta;
|
|
226
|
+
content.arguments = parseStreamingJson((content as any).partialJson) || {};
|
|
227
|
+
event = {
|
|
228
|
+
type: "toolcall_delta",
|
|
229
|
+
contentIndex: proxyEvent.contentIndex,
|
|
230
|
+
delta: proxyEvent.delta,
|
|
231
|
+
partial,
|
|
232
|
+
};
|
|
233
|
+
partial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity
|
|
234
|
+
} else {
|
|
235
|
+
throw new Error("Received toolcall_delta for non-toolCall content");
|
|
236
|
+
}
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
case "toolcall_end": {
|
|
241
|
+
const content = partial.content[proxyEvent.contentIndex];
|
|
242
|
+
if (content?.type === "toolCall") {
|
|
243
|
+
delete (content as any).partialJson;
|
|
244
|
+
event = {
|
|
245
|
+
type: "toolcall_end",
|
|
246
|
+
contentIndex: proxyEvent.contentIndex,
|
|
247
|
+
toolCall: content,
|
|
248
|
+
partial,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
case "done":
|
|
255
|
+
partial.stopReason = proxyEvent.reason;
|
|
256
|
+
partial.usage = proxyEvent.usage;
|
|
257
|
+
event = { type: "done", reason: proxyEvent.reason, message: partial };
|
|
258
|
+
break;
|
|
259
|
+
|
|
260
|
+
case "error":
|
|
261
|
+
partial.stopReason = proxyEvent.reason;
|
|
262
|
+
partial.errorMessage = proxyEvent.errorMessage;
|
|
263
|
+
partial.usage = proxyEvent.usage;
|
|
264
|
+
event = { type: "error", reason: proxyEvent.reason, error: partial };
|
|
265
|
+
break;
|
|
266
|
+
|
|
267
|
+
default: {
|
|
268
|
+
// Exhaustive check
|
|
269
|
+
const _exhaustiveCheck: never = proxyEvent;
|
|
270
|
+
console.warn(`Unhandled event type: ${(proxyEvent as any).type}`);
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Push the event to stream
|
|
276
|
+
if (event) {
|
|
277
|
+
stream.push(event);
|
|
278
|
+
} else {
|
|
279
|
+
throw new Error("Failed to create event from proxy event");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Check if aborted after reading
|
|
287
|
+
if (options.signal?.aborted) {
|
|
288
|
+
throw new Error("Request aborted by user");
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
stream.end();
|
|
292
|
+
} catch (error) {
|
|
293
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
294
|
+
if (errorMessage.toLowerCase().includes("proxy") && errorMessage.includes("Unauthorized")) {
|
|
295
|
+
clearAuthToken();
|
|
296
|
+
}
|
|
297
|
+
partial.stopReason = options.signal?.aborted ? "aborted" : "error";
|
|
298
|
+
partial.errorMessage = errorMessage;
|
|
299
|
+
stream.push({
|
|
300
|
+
type: "error",
|
|
301
|
+
reason: partial.stopReason,
|
|
302
|
+
error: partial,
|
|
303
|
+
} satisfies AssistantMessageEvent);
|
|
304
|
+
stream.end();
|
|
305
|
+
} finally {
|
|
306
|
+
// Clean up abort handler
|
|
307
|
+
if (options.signal) {
|
|
308
|
+
options.signal.removeEventListener("abort", abortHandler);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
})();
|
|
312
|
+
|
|
313
|
+
return stream;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Proxy transport executes the turn using a remote proxy server
|
|
317
|
+
/**
|
|
318
|
+
* Transport that uses an app server with user authentication tokens.
|
|
319
|
+
* The server manages user accounts and proxies requests to LLM providers.
|
|
320
|
+
*/
|
|
321
|
+
export class AppTransport implements AgentTransport {
|
|
322
|
+
// Hardcoded proxy URL for now - will be made configurable later
|
|
323
|
+
private readonly proxyUrl = "https://genai.mariozechner.at";
|
|
324
|
+
|
|
325
|
+
constructor(private readonly getMessages: () => Promise<Message[]>) {}
|
|
326
|
+
|
|
327
|
+
async *run(userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal) {
|
|
328
|
+
const authToken = await getAuthToken();
|
|
329
|
+
if (!authToken) {
|
|
330
|
+
throw new Error(i18n("Auth token is required for proxy transport"));
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Use proxy - no local API key needed
|
|
334
|
+
const streamFn = <TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions) => {
|
|
335
|
+
return streamSimpleProxy(
|
|
336
|
+
model,
|
|
337
|
+
context,
|
|
338
|
+
{
|
|
339
|
+
...options,
|
|
340
|
+
authToken,
|
|
341
|
+
},
|
|
342
|
+
this.proxyUrl,
|
|
343
|
+
);
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
const context: AgentContext = {
|
|
347
|
+
systemPrompt: cfg.systemPrompt,
|
|
348
|
+
messages: await this.getMessages(),
|
|
349
|
+
tools: cfg.tools,
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const pc: PromptConfig = {
|
|
353
|
+
model: cfg.model,
|
|
354
|
+
reasoning: cfg.reasoning,
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
// Yield events from the upstream agentLoop iterator
|
|
358
|
+
// Pass streamFn as the 5th parameter to use proxy
|
|
359
|
+
for await (const ev of agentLoop(userMessage as unknown as UserMessage, context, pc, signal, streamFn as any)) {
|
|
360
|
+
yield ev;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|