@mariozechner/pi-agent-core 0.9.1

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.
@@ -0,0 +1,312 @@
1
+ import { agentLoop } from "@mariozechner/pi-ai";
2
+ import { AssistantMessageEventStream } from "@mariozechner/pi-ai/dist/utils/event-stream.js";
3
+ import { parseStreamingJson } from "@mariozechner/pi-ai/dist/utils/json-parse.js";
4
+ /**
5
+ * Stream function that proxies through a server instead of calling providers directly.
6
+ * The server strips the partial field from delta events to reduce bandwidth.
7
+ * We reconstruct the partial message client-side.
8
+ */
9
+ function streamSimpleProxy(model, context, options, proxyUrl) {
10
+ const stream = new AssistantMessageEventStream();
11
+ (async () => {
12
+ // Initialize the partial message that we'll build up from events
13
+ const partial = {
14
+ role: "assistant",
15
+ stopReason: "stop",
16
+ content: [],
17
+ api: model.api,
18
+ provider: model.provider,
19
+ model: model.id,
20
+ usage: {
21
+ input: 0,
22
+ output: 0,
23
+ cacheRead: 0,
24
+ cacheWrite: 0,
25
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
26
+ },
27
+ timestamp: Date.now(),
28
+ };
29
+ let reader;
30
+ // Set up abort handler to cancel the reader
31
+ const abortHandler = () => {
32
+ if (reader) {
33
+ reader.cancel("Request aborted by user").catch(() => { });
34
+ }
35
+ };
36
+ if (options.signal) {
37
+ options.signal.addEventListener("abort", abortHandler);
38
+ }
39
+ try {
40
+ const response = await fetch(`${proxyUrl}/api/stream`, {
41
+ method: "POST",
42
+ headers: {
43
+ Authorization: `Bearer ${options.authToken}`,
44
+ "Content-Type": "application/json",
45
+ },
46
+ body: JSON.stringify({
47
+ model,
48
+ context,
49
+ options: {
50
+ temperature: options.temperature,
51
+ maxTokens: options.maxTokens,
52
+ reasoning: options.reasoning,
53
+ // Don't send apiKey or signal - those are added server-side
54
+ },
55
+ }),
56
+ signal: options.signal,
57
+ });
58
+ if (!response.ok) {
59
+ let errorMessage = `Proxy error: ${response.status} ${response.statusText}`;
60
+ try {
61
+ const errorData = (await response.json());
62
+ if (errorData.error) {
63
+ errorMessage = `Proxy error: ${errorData.error}`;
64
+ }
65
+ }
66
+ catch {
67
+ // Couldn't parse error response, use default message
68
+ }
69
+ throw new Error(errorMessage);
70
+ }
71
+ // Parse SSE stream
72
+ reader = response.body.getReader();
73
+ const decoder = new TextDecoder();
74
+ let buffer = "";
75
+ while (true) {
76
+ const { done, value } = await reader.read();
77
+ if (done)
78
+ break;
79
+ // Check if aborted after reading
80
+ if (options.signal?.aborted) {
81
+ throw new Error("Request aborted by user");
82
+ }
83
+ buffer += decoder.decode(value, { stream: true });
84
+ const lines = buffer.split("\n");
85
+ buffer = lines.pop() || "";
86
+ for (const line of lines) {
87
+ if (line.startsWith("data: ")) {
88
+ const data = line.slice(6).trim();
89
+ if (data) {
90
+ const proxyEvent = JSON.parse(data);
91
+ let event;
92
+ // Handle different event types
93
+ // Server sends events with partial for non-delta events,
94
+ // and without partial for delta events
95
+ switch (proxyEvent.type) {
96
+ case "start":
97
+ event = { type: "start", partial };
98
+ break;
99
+ case "text_start":
100
+ partial.content[proxyEvent.contentIndex] = {
101
+ type: "text",
102
+ text: "",
103
+ };
104
+ event = { type: "text_start", contentIndex: proxyEvent.contentIndex, partial };
105
+ break;
106
+ case "text_delta": {
107
+ const content = partial.content[proxyEvent.contentIndex];
108
+ if (content?.type === "text") {
109
+ content.text += proxyEvent.delta;
110
+ event = {
111
+ type: "text_delta",
112
+ contentIndex: proxyEvent.contentIndex,
113
+ delta: proxyEvent.delta,
114
+ partial,
115
+ };
116
+ }
117
+ else {
118
+ throw new Error("Received text_delta for non-text content");
119
+ }
120
+ break;
121
+ }
122
+ case "text_end": {
123
+ const content = partial.content[proxyEvent.contentIndex];
124
+ if (content?.type === "text") {
125
+ content.textSignature = proxyEvent.contentSignature;
126
+ event = {
127
+ type: "text_end",
128
+ contentIndex: proxyEvent.contentIndex,
129
+ content: content.text,
130
+ partial,
131
+ };
132
+ }
133
+ else {
134
+ throw new Error("Received text_end for non-text content");
135
+ }
136
+ break;
137
+ }
138
+ case "thinking_start":
139
+ partial.content[proxyEvent.contentIndex] = {
140
+ type: "thinking",
141
+ thinking: "",
142
+ };
143
+ event = { type: "thinking_start", contentIndex: proxyEvent.contentIndex, partial };
144
+ break;
145
+ case "thinking_delta": {
146
+ const content = partial.content[proxyEvent.contentIndex];
147
+ if (content?.type === "thinking") {
148
+ content.thinking += proxyEvent.delta;
149
+ event = {
150
+ type: "thinking_delta",
151
+ contentIndex: proxyEvent.contentIndex,
152
+ delta: proxyEvent.delta,
153
+ partial,
154
+ };
155
+ }
156
+ else {
157
+ throw new Error("Received thinking_delta for non-thinking content");
158
+ }
159
+ break;
160
+ }
161
+ case "thinking_end": {
162
+ const content = partial.content[proxyEvent.contentIndex];
163
+ if (content?.type === "thinking") {
164
+ content.thinkingSignature = proxyEvent.contentSignature;
165
+ event = {
166
+ type: "thinking_end",
167
+ contentIndex: proxyEvent.contentIndex,
168
+ content: content.thinking,
169
+ partial,
170
+ };
171
+ }
172
+ else {
173
+ throw new Error("Received thinking_end for non-thinking content");
174
+ }
175
+ break;
176
+ }
177
+ case "toolcall_start":
178
+ partial.content[proxyEvent.contentIndex] = {
179
+ type: "toolCall",
180
+ id: proxyEvent.id,
181
+ name: proxyEvent.toolName,
182
+ arguments: {},
183
+ partialJson: "",
184
+ };
185
+ event = { type: "toolcall_start", contentIndex: proxyEvent.contentIndex, partial };
186
+ break;
187
+ case "toolcall_delta": {
188
+ const content = partial.content[proxyEvent.contentIndex];
189
+ if (content?.type === "toolCall") {
190
+ content.partialJson += proxyEvent.delta;
191
+ content.arguments = parseStreamingJson(content.partialJson) || {};
192
+ event = {
193
+ type: "toolcall_delta",
194
+ contentIndex: proxyEvent.contentIndex,
195
+ delta: proxyEvent.delta,
196
+ partial,
197
+ };
198
+ partial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity
199
+ }
200
+ else {
201
+ throw new Error("Received toolcall_delta for non-toolCall content");
202
+ }
203
+ break;
204
+ }
205
+ case "toolcall_end": {
206
+ const content = partial.content[proxyEvent.contentIndex];
207
+ if (content?.type === "toolCall") {
208
+ delete content.partialJson;
209
+ event = {
210
+ type: "toolcall_end",
211
+ contentIndex: proxyEvent.contentIndex,
212
+ toolCall: content,
213
+ partial,
214
+ };
215
+ }
216
+ break;
217
+ }
218
+ case "done":
219
+ partial.stopReason = proxyEvent.reason;
220
+ partial.usage = proxyEvent.usage;
221
+ event = { type: "done", reason: proxyEvent.reason, message: partial };
222
+ break;
223
+ case "error":
224
+ partial.stopReason = proxyEvent.reason;
225
+ partial.errorMessage = proxyEvent.errorMessage;
226
+ partial.usage = proxyEvent.usage;
227
+ event = { type: "error", reason: proxyEvent.reason, error: partial };
228
+ break;
229
+ default: {
230
+ // Exhaustive check
231
+ const _exhaustiveCheck = proxyEvent;
232
+ console.warn(`Unhandled event type: ${proxyEvent.type}`);
233
+ break;
234
+ }
235
+ }
236
+ // Push the event to stream
237
+ if (event) {
238
+ stream.push(event);
239
+ }
240
+ else {
241
+ throw new Error("Failed to create event from proxy event");
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }
247
+ // Check if aborted after reading
248
+ if (options.signal?.aborted) {
249
+ throw new Error("Request aborted by user");
250
+ }
251
+ stream.end();
252
+ }
253
+ catch (error) {
254
+ const errorMessage = error instanceof Error ? error.message : String(error);
255
+ partial.stopReason = options.signal?.aborted ? "aborted" : "error";
256
+ partial.errorMessage = errorMessage;
257
+ stream.push({
258
+ type: "error",
259
+ reason: partial.stopReason,
260
+ error: partial,
261
+ });
262
+ stream.end();
263
+ }
264
+ finally {
265
+ // Clean up abort handler
266
+ if (options.signal) {
267
+ options.signal.removeEventListener("abort", abortHandler);
268
+ }
269
+ }
270
+ })();
271
+ return stream;
272
+ }
273
+ /**
274
+ * Transport that uses an app server with user authentication tokens.
275
+ * The server manages user accounts and proxies requests to LLM providers.
276
+ */
277
+ export class AppTransport {
278
+ options;
279
+ constructor(options) {
280
+ this.options = options;
281
+ }
282
+ async *run(messages, userMessage, cfg, signal) {
283
+ const authToken = await this.options.getAuthToken();
284
+ if (!authToken) {
285
+ throw new Error("Auth token is required for AppTransport");
286
+ }
287
+ // Use proxy - no local API key needed
288
+ const streamFn = (model, context, options) => {
289
+ return streamSimpleProxy(model, context, {
290
+ ...options,
291
+ authToken,
292
+ }, this.options.proxyUrl);
293
+ };
294
+ // Messages are already LLM-compatible (filtered by Agent)
295
+ const context = {
296
+ systemPrompt: cfg.systemPrompt,
297
+ messages,
298
+ tools: cfg.tools,
299
+ };
300
+ const pc = {
301
+ model: cfg.model,
302
+ reasoning: cfg.reasoning,
303
+ getQueuedMessages: cfg.getQueuedMessages,
304
+ };
305
+ // Yield events from the upstream agentLoop iterator
306
+ // Pass streamFn as the 5th parameter to use proxy
307
+ for await (const ev of agentLoop(userMessage, context, pc, signal, streamFn)) {
308
+ yield ev;
309
+ }
310
+ }
311
+ }
312
+ //# sourceMappingURL=AppTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppTransport.js","sourceRoot":"","sources":["../../src/transports/AppTransport.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tAgentContext,\n\tAgentLoopConfig,\n\tApi,\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tContext,\n\tMessage,\n\tModel,\n\tSimpleStreamOptions,\n\tToolCall,\n\tUserMessage,\n} from \"@mariozechner/pi-ai\";\nimport { agentLoop } from \"@mariozechner/pi-ai\";\nimport { AssistantMessageEventStream } from \"@mariozechner/pi-ai/dist/utils/event-stream.js\";\nimport { parseStreamingJson } from \"@mariozechner/pi-ai/dist/utils/json-parse.js\";\nimport type { ProxyAssistantMessageEvent } from \"./proxy-types.js\";\nimport type { AgentRunConfig, AgentTransport } from \"./types.js\";\n\n/**\n * Stream function that proxies through a server instead of calling providers directly.\n * The server strips the partial field from delta events to reduce bandwidth.\n * We reconstruct the partial message client-side.\n */\nfunction streamSimpleProxy(\n\tmodel: Model<any>,\n\tcontext: Context,\n\toptions: SimpleStreamOptions & { authToken: string },\n\tproxyUrl: string,\n): AssistantMessageEventStream {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\t// Initialize the partial message that we'll build up from events\n\t\tconst partial: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tstopReason: \"stop\",\n\t\t\tcontent: [],\n\t\t\tapi: model.api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\tlet reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n\n\t\t// Set up abort handler to cancel the reader\n\t\tconst abortHandler = () => {\n\t\t\tif (reader) {\n\t\t\t\treader.cancel(\"Request aborted by user\").catch(() => {});\n\t\t\t}\n\t\t};\n\n\t\tif (options.signal) {\n\t\t\toptions.signal.addEventListener(\"abort\", abortHandler);\n\t\t}\n\n\t\ttry {\n\t\t\tconst response = await fetch(`${proxyUrl}/api/stream`, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${options.authToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel,\n\t\t\t\t\tcontext,\n\t\t\t\t\toptions: {\n\t\t\t\t\t\ttemperature: options.temperature,\n\t\t\t\t\t\tmaxTokens: options.maxTokens,\n\t\t\t\t\t\treasoning: options.reasoning,\n\t\t\t\t\t\t// Don't send apiKey or signal - those are added server-side\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\tsignal: options.signal,\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tlet errorMessage = `Proxy error: ${response.status} ${response.statusText}`;\n\t\t\t\ttry {\n\t\t\t\t\tconst errorData = (await response.json()) as { error?: string };\n\t\t\t\t\tif (errorData.error) {\n\t\t\t\t\t\terrorMessage = `Proxy error: ${errorData.error}`;\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\t// Couldn't parse error response, use default message\n\t\t\t\t}\n\t\t\t\tthrow new Error(errorMessage);\n\t\t\t}\n\n\t\t\t// Parse SSE stream\n\t\t\treader = response.body!.getReader();\n\t\t\tconst decoder = new TextDecoder();\n\t\t\tlet buffer = \"\";\n\n\t\t\twhile (true) {\n\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\tif (done) break;\n\n\t\t\t\t// Check if aborted after reading\n\t\t\t\tif (options.signal?.aborted) {\n\t\t\t\t\tthrow new Error(\"Request aborted by user\");\n\t\t\t\t}\n\n\t\t\t\tbuffer += decoder.decode(value, { stream: true });\n\t\t\t\tconst lines = buffer.split(\"\\n\");\n\t\t\t\tbuffer = lines.pop() || \"\";\n\n\t\t\t\tfor (const line of lines) {\n\t\t\t\t\tif (line.startsWith(\"data: \")) {\n\t\t\t\t\t\tconst data = line.slice(6).trim();\n\t\t\t\t\t\tif (data) {\n\t\t\t\t\t\t\tconst proxyEvent = JSON.parse(data) as ProxyAssistantMessageEvent;\n\t\t\t\t\t\t\tlet event: AssistantMessageEvent | undefined;\n\n\t\t\t\t\t\t\t// Handle different event types\n\t\t\t\t\t\t\t// Server sends events with partial for non-delta events,\n\t\t\t\t\t\t\t// and without partial for delta events\n\t\t\t\t\t\t\tswitch (proxyEvent.type) {\n\t\t\t\t\t\t\t\tcase \"start\":\n\t\t\t\t\t\t\t\t\tevent = { type: \"start\", partial };\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase \"text_start\":\n\t\t\t\t\t\t\t\t\tpartial.content[proxyEvent.contentIndex] = {\n\t\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\tevent = { type: \"text_start\", contentIndex: proxyEvent.contentIndex, partial };\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase \"text_delta\": {\n\t\t\t\t\t\t\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\t\t\t\t\t\t\tif (content?.type === \"text\") {\n\t\t\t\t\t\t\t\t\t\tcontent.text += proxyEvent.delta;\n\t\t\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\t\t\t\t\t\t\tdelta: proxyEvent.delta,\n\t\t\t\t\t\t\t\t\t\t\tpartial,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Received text_delta for non-text content\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tcase \"text_end\": {\n\t\t\t\t\t\t\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\t\t\t\t\t\t\tif (content?.type === \"text\") {\n\t\t\t\t\t\t\t\t\t\tcontent.textSignature = proxyEvent.contentSignature;\n\t\t\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\t\t\t\t\t\t\tcontent: content.text,\n\t\t\t\t\t\t\t\t\t\t\tpartial,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Received text_end for non-text content\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase \"thinking_start\":\n\t\t\t\t\t\t\t\t\tpartial.content[proxyEvent.contentIndex] = {\n\t\t\t\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\t\t\t\tthinking: \"\",\n\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\tevent = { type: \"thinking_start\", contentIndex: proxyEvent.contentIndex, partial };\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase \"thinking_delta\": {\n\t\t\t\t\t\t\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\t\t\t\t\t\t\tif (content?.type === \"thinking\") {\n\t\t\t\t\t\t\t\t\t\tcontent.thinking += proxyEvent.delta;\n\t\t\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\t\t\t\t\t\t\tdelta: proxyEvent.delta,\n\t\t\t\t\t\t\t\t\t\t\tpartial,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Received thinking_delta for non-thinking content\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase \"thinking_end\": {\n\t\t\t\t\t\t\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\t\t\t\t\t\t\tif (content?.type === \"thinking\") {\n\t\t\t\t\t\t\t\t\t\tcontent.thinkingSignature = proxyEvent.contentSignature;\n\t\t\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\t\t\t\t\t\t\tcontent: content.thinking,\n\t\t\t\t\t\t\t\t\t\t\tpartial,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Received thinking_end for non-thinking content\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase \"toolcall_start\":\n\t\t\t\t\t\t\t\t\tpartial.content[proxyEvent.contentIndex] = {\n\t\t\t\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\t\t\t\tid: proxyEvent.id,\n\t\t\t\t\t\t\t\t\t\tname: proxyEvent.toolName,\n\t\t\t\t\t\t\t\t\t\targuments: {},\n\t\t\t\t\t\t\t\t\t\tpartialJson: \"\",\n\t\t\t\t\t\t\t\t\t} satisfies ToolCall & { partialJson: string } as ToolCall;\n\t\t\t\t\t\t\t\t\tevent = { type: \"toolcall_start\", contentIndex: proxyEvent.contentIndex, partial };\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase \"toolcall_delta\": {\n\t\t\t\t\t\t\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\t\t\t\t\t\t\tif (content?.type === \"toolCall\") {\n\t\t\t\t\t\t\t\t\t\t(content as any).partialJson += proxyEvent.delta;\n\t\t\t\t\t\t\t\t\t\tcontent.arguments = parseStreamingJson((content as any).partialJson) || {};\n\t\t\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\t\t\t\t\t\t\tdelta: proxyEvent.delta,\n\t\t\t\t\t\t\t\t\t\t\tpartial,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t\tpartial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity\n\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\tthrow new Error(\"Received toolcall_delta for non-toolCall content\");\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase \"toolcall_end\": {\n\t\t\t\t\t\t\t\t\tconst content = partial.content[proxyEvent.contentIndex];\n\t\t\t\t\t\t\t\t\tif (content?.type === \"toolCall\") {\n\t\t\t\t\t\t\t\t\t\tdelete (content as any).partialJson;\n\t\t\t\t\t\t\t\t\t\tevent = {\n\t\t\t\t\t\t\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\t\t\t\t\t\t\tcontentIndex: proxyEvent.contentIndex,\n\t\t\t\t\t\t\t\t\t\t\ttoolCall: content,\n\t\t\t\t\t\t\t\t\t\t\tpartial,\n\t\t\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tcase \"done\":\n\t\t\t\t\t\t\t\t\tpartial.stopReason = proxyEvent.reason;\n\t\t\t\t\t\t\t\t\tpartial.usage = proxyEvent.usage;\n\t\t\t\t\t\t\t\t\tevent = { type: \"done\", reason: proxyEvent.reason, message: partial };\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tcase \"error\":\n\t\t\t\t\t\t\t\t\tpartial.stopReason = proxyEvent.reason;\n\t\t\t\t\t\t\t\t\tpartial.errorMessage = proxyEvent.errorMessage;\n\t\t\t\t\t\t\t\t\tpartial.usage = proxyEvent.usage;\n\t\t\t\t\t\t\t\t\tevent = { type: \"error\", reason: proxyEvent.reason, error: partial };\n\t\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\t\t\t// Exhaustive check\n\t\t\t\t\t\t\t\t\tconst _exhaustiveCheck: never = proxyEvent;\n\t\t\t\t\t\t\t\t\tconsole.warn(`Unhandled event type: ${(proxyEvent as any).type}`);\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Push the event to stream\n\t\t\t\t\t\t\tif (event) {\n\t\t\t\t\t\t\t\tstream.push(event);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthrow new Error(\"Failed to create event from proxy event\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check if aborted after reading\n\t\t\tif (options.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request aborted by user\");\n\t\t\t}\n\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tconst errorMessage = error instanceof Error ? error.message : String(error);\n\t\t\tpartial.stopReason = options.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\tpartial.errorMessage = errorMessage;\n\t\t\tstream.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\treason: partial.stopReason,\n\t\t\t\terror: partial,\n\t\t\t} satisfies AssistantMessageEvent);\n\t\t\tstream.end();\n\t\t} finally {\n\t\t\t// Clean up abort handler\n\t\t\tif (options.signal) {\n\t\t\t\toptions.signal.removeEventListener(\"abort\", abortHandler);\n\t\t\t}\n\t\t}\n\t})();\n\n\treturn stream;\n}\n\nexport interface AppTransportOptions {\n\t/**\n\t * Proxy server URL. The server manages user accounts and proxies requests to LLM providers.\n\t * Example: \"https://genai.mariozechner.at\"\n\t */\n\tproxyUrl: string;\n\n\t/**\n\t * Function to retrieve auth token for the proxy server.\n\t * The token is used for user authentication and authorization.\n\t */\n\tgetAuthToken: () => Promise<string> | string;\n}\n\n/**\n * Transport that uses an app server with user authentication tokens.\n * The server manages user accounts and proxies requests to LLM providers.\n */\nexport class AppTransport implements AgentTransport {\n\tprivate options: AppTransportOptions;\n\n\tconstructor(options: AppTransportOptions) {\n\t\tthis.options = options;\n\t}\n\n\tasync *run(messages: Message[], userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal) {\n\t\tconst authToken = await this.options.getAuthToken();\n\t\tif (!authToken) {\n\t\t\tthrow new Error(\"Auth token is required for AppTransport\");\n\t\t}\n\n\t\t// Use proxy - no local API key needed\n\t\tconst streamFn = <TApi extends Api>(model: Model<TApi>, context: Context, options?: SimpleStreamOptions) => {\n\t\t\treturn streamSimpleProxy(\n\t\t\t\tmodel,\n\t\t\t\tcontext,\n\t\t\t\t{\n\t\t\t\t\t...options,\n\t\t\t\t\tauthToken,\n\t\t\t\t},\n\t\t\t\tthis.options.proxyUrl,\n\t\t\t);\n\t\t};\n\n\t\t// Messages are already LLM-compatible (filtered by Agent)\n\t\tconst context: AgentContext = {\n\t\t\tsystemPrompt: cfg.systemPrompt,\n\t\t\tmessages,\n\t\t\ttools: cfg.tools,\n\t\t};\n\n\t\tconst pc: AgentLoopConfig = {\n\t\t\tmodel: cfg.model,\n\t\t\treasoning: cfg.reasoning,\n\t\t\tgetQueuedMessages: cfg.getQueuedMessages,\n\t\t};\n\n\t\t// Yield events from the upstream agentLoop iterator\n\t\t// Pass streamFn as the 5th parameter to use proxy\n\t\tfor await (const ev of agentLoop(userMessage as unknown as UserMessage, context, pc, signal, streamFn as any)) {\n\t\t\tyield ev;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import { type Message } from "@mariozechner/pi-ai";
2
+ import type { AgentRunConfig, AgentTransport } from "./types.js";
3
+ export interface ProviderTransportOptions {
4
+ /**
5
+ * Function to retrieve API key for a given provider.
6
+ * If not provided, transport will try to use environment variables.
7
+ */
8
+ getApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;
9
+ /**
10
+ * Optional CORS proxy URL for browser environments.
11
+ * If provided, all requests will be routed through this proxy.
12
+ * Format: "https://proxy.example.com"
13
+ */
14
+ corsProxyUrl?: string;
15
+ }
16
+ /**
17
+ * Transport that calls LLM providers directly.
18
+ * Optionally routes calls through a CORS proxy if configured.
19
+ */
20
+ export declare class ProviderTransport implements AgentTransport {
21
+ private options;
22
+ constructor(options?: ProviderTransportOptions);
23
+ run(messages: Message[], userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal): AsyncGenerator<import("@mariozechner/pi-ai").AgentEvent, void, unknown>;
24
+ }
25
+ //# sourceMappingURL=ProviderTransport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderTransport.d.ts","sourceRoot":"","sources":["../../src/transports/ProviderTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,OAAO,EAEZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,wBAAwB;IACxC;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;IAEnF;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACvD,OAAO,CAAC,OAAO,CAA2B;IAE1C,YAAY,OAAO,GAAE,wBAA6B,EAEjD;IAEM,GAAG,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,WAAW,2EAsC9F;CACD","sourcesContent":["import {\n\ttype AgentContext,\n\ttype AgentLoopConfig,\n\tagentLoop,\n\ttype Message,\n\ttype UserMessage,\n} from \"@mariozechner/pi-ai\";\nimport type { AgentRunConfig, AgentTransport } from \"./types.js\";\n\nexport interface ProviderTransportOptions {\n\t/**\n\t * Function to retrieve API key for a given provider.\n\t * If not provided, transport will try to use environment variables.\n\t */\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\n\t/**\n\t * Optional CORS proxy URL for browser environments.\n\t * If provided, all requests will be routed through this proxy.\n\t * Format: \"https://proxy.example.com\"\n\t */\n\tcorsProxyUrl?: string;\n}\n\n/**\n * Transport that calls LLM providers directly.\n * Optionally routes calls through a CORS proxy if configured.\n */\nexport class ProviderTransport implements AgentTransport {\n\tprivate options: ProviderTransportOptions;\n\n\tconstructor(options: ProviderTransportOptions = {}) {\n\t\tthis.options = options;\n\t}\n\n\tasync *run(messages: Message[], userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal) {\n\t\t// Get API key\n\t\tlet apiKey: string | undefined;\n\t\tif (this.options.getApiKey) {\n\t\t\tapiKey = await this.options.getApiKey(cfg.model.provider);\n\t\t}\n\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(`No API key found for provider: ${cfg.model.provider}`);\n\t\t}\n\n\t\t// Clone model and modify baseUrl if CORS proxy is enabled\n\t\tlet model = cfg.model;\n\t\tif (this.options.corsProxyUrl && cfg.model.baseUrl) {\n\t\t\tmodel = {\n\t\t\t\t...cfg.model,\n\t\t\t\tbaseUrl: `${this.options.corsProxyUrl}/?url=${encodeURIComponent(cfg.model.baseUrl)}`,\n\t\t\t};\n\t\t}\n\n\t\t// Messages are already LLM-compatible (filtered by Agent)\n\t\tconst context: AgentContext = {\n\t\t\tsystemPrompt: cfg.systemPrompt,\n\t\t\tmessages,\n\t\t\ttools: cfg.tools,\n\t\t};\n\n\t\tconst pc: AgentLoopConfig = {\n\t\t\tmodel,\n\t\t\treasoning: cfg.reasoning,\n\t\t\tapiKey,\n\t\t\tgetQueuedMessages: cfg.getQueuedMessages,\n\t\t};\n\n\t\t// Yield events from agentLoop\n\t\tfor await (const ev of agentLoop(userMessage as unknown as UserMessage, context, pc, signal)) {\n\t\t\tyield ev;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,46 @@
1
+ import { agentLoop, } from "@mariozechner/pi-ai";
2
+ /**
3
+ * Transport that calls LLM providers directly.
4
+ * Optionally routes calls through a CORS proxy if configured.
5
+ */
6
+ export class ProviderTransport {
7
+ options;
8
+ constructor(options = {}) {
9
+ this.options = options;
10
+ }
11
+ async *run(messages, userMessage, cfg, signal) {
12
+ // Get API key
13
+ let apiKey;
14
+ if (this.options.getApiKey) {
15
+ apiKey = await this.options.getApiKey(cfg.model.provider);
16
+ }
17
+ if (!apiKey) {
18
+ throw new Error(`No API key found for provider: ${cfg.model.provider}`);
19
+ }
20
+ // Clone model and modify baseUrl if CORS proxy is enabled
21
+ let model = cfg.model;
22
+ if (this.options.corsProxyUrl && cfg.model.baseUrl) {
23
+ model = {
24
+ ...cfg.model,
25
+ baseUrl: `${this.options.corsProxyUrl}/?url=${encodeURIComponent(cfg.model.baseUrl)}`,
26
+ };
27
+ }
28
+ // Messages are already LLM-compatible (filtered by Agent)
29
+ const context = {
30
+ systemPrompt: cfg.systemPrompt,
31
+ messages,
32
+ tools: cfg.tools,
33
+ };
34
+ const pc = {
35
+ model,
36
+ reasoning: cfg.reasoning,
37
+ apiKey,
38
+ getQueuedMessages: cfg.getQueuedMessages,
39
+ };
40
+ // Yield events from agentLoop
41
+ for await (const ev of agentLoop(userMessage, context, pc, signal)) {
42
+ yield ev;
43
+ }
44
+ }
45
+ }
46
+ //# sourceMappingURL=ProviderTransport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderTransport.js","sourceRoot":"","sources":["../../src/transports/ProviderTransport.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,SAAS,GAGT,MAAM,qBAAqB,CAAC;AAkB7B;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACrB,OAAO,CAA2B;IAE1C,YAAY,OAAO,GAA6B,EAAE,EAAE;QACnD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IAAA,CACvB;IAED,KAAK,CAAC,CAAC,GAAG,CAAC,QAAmB,EAAE,WAAoB,EAAE,GAAmB,EAAE,MAAoB,EAAE;QAChG,cAAc;QACd,IAAI,MAA0B,CAAC;QAC/B,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC5B,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,kCAAkC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,0DAA0D;QAC1D,IAAI,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;QACtB,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACpD,KAAK,GAAG;gBACP,GAAG,GAAG,CAAC,KAAK;gBACZ,OAAO,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,SAAS,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;aACrF,CAAC;QACH,CAAC;QAED,0DAA0D;QAC1D,MAAM,OAAO,GAAiB;YAC7B,YAAY,EAAE,GAAG,CAAC,YAAY;YAC9B,QAAQ;YACR,KAAK,EAAE,GAAG,CAAC,KAAK;SAChB,CAAC;QAEF,MAAM,EAAE,GAAoB;YAC3B,KAAK;YACL,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,MAAM;YACN,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;SACxC,CAAC;QAEF,8BAA8B;QAC9B,IAAI,KAAK,EAAE,MAAM,EAAE,IAAI,SAAS,CAAC,WAAqC,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC;YAC9F,MAAM,EAAE,CAAC;QACV,CAAC;IAAA,CACD;CACD","sourcesContent":["import {\n\ttype AgentContext,\n\ttype AgentLoopConfig,\n\tagentLoop,\n\ttype Message,\n\ttype UserMessage,\n} from \"@mariozechner/pi-ai\";\nimport type { AgentRunConfig, AgentTransport } from \"./types.js\";\n\nexport interface ProviderTransportOptions {\n\t/**\n\t * Function to retrieve API key for a given provider.\n\t * If not provided, transport will try to use environment variables.\n\t */\n\tgetApiKey?: (provider: string) => Promise<string | undefined> | string | undefined;\n\n\t/**\n\t * Optional CORS proxy URL for browser environments.\n\t * If provided, all requests will be routed through this proxy.\n\t * Format: \"https://proxy.example.com\"\n\t */\n\tcorsProxyUrl?: string;\n}\n\n/**\n * Transport that calls LLM providers directly.\n * Optionally routes calls through a CORS proxy if configured.\n */\nexport class ProviderTransport implements AgentTransport {\n\tprivate options: ProviderTransportOptions;\n\n\tconstructor(options: ProviderTransportOptions = {}) {\n\t\tthis.options = options;\n\t}\n\n\tasync *run(messages: Message[], userMessage: Message, cfg: AgentRunConfig, signal?: AbortSignal) {\n\t\t// Get API key\n\t\tlet apiKey: string | undefined;\n\t\tif (this.options.getApiKey) {\n\t\t\tapiKey = await this.options.getApiKey(cfg.model.provider);\n\t\t}\n\n\t\tif (!apiKey) {\n\t\t\tthrow new Error(`No API key found for provider: ${cfg.model.provider}`);\n\t\t}\n\n\t\t// Clone model and modify baseUrl if CORS proxy is enabled\n\t\tlet model = cfg.model;\n\t\tif (this.options.corsProxyUrl && cfg.model.baseUrl) {\n\t\t\tmodel = {\n\t\t\t\t...cfg.model,\n\t\t\t\tbaseUrl: `${this.options.corsProxyUrl}/?url=${encodeURIComponent(cfg.model.baseUrl)}`,\n\t\t\t};\n\t\t}\n\n\t\t// Messages are already LLM-compatible (filtered by Agent)\n\t\tconst context: AgentContext = {\n\t\t\tsystemPrompt: cfg.systemPrompt,\n\t\t\tmessages,\n\t\t\ttools: cfg.tools,\n\t\t};\n\n\t\tconst pc: AgentLoopConfig = {\n\t\t\tmodel,\n\t\t\treasoning: cfg.reasoning,\n\t\t\tapiKey,\n\t\t\tgetQueuedMessages: cfg.getQueuedMessages,\n\t\t};\n\n\t\t// Yield events from agentLoop\n\t\tfor await (const ev of agentLoop(userMessage as unknown as UserMessage, context, pc, signal)) {\n\t\t\tyield ev;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,5 @@
1
+ export { AppTransport, type AppTransportOptions } from "./AppTransport.js";
2
+ export { ProviderTransport, type ProviderTransportOptions } from "./ProviderTransport.js";
3
+ export type { ProxyAssistantMessageEvent } from "./proxy-types.js";
4
+ export type { AgentRunConfig, AgentTransport } from "./types.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/transports/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAC1F,YAAY,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AACnE,YAAY,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC","sourcesContent":["export { AppTransport, type AppTransportOptions } from \"./AppTransport.js\";\nexport { ProviderTransport, type ProviderTransportOptions } from \"./ProviderTransport.js\";\nexport type { ProxyAssistantMessageEvent } from \"./proxy-types.js\";\nexport type { AgentRunConfig, AgentTransport } from \"./types.js\";\n"]}
@@ -0,0 +1,3 @@
1
+ export { AppTransport } from "./AppTransport.js";
2
+ export { ProviderTransport } from "./ProviderTransport.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/transports/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA4B,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAiC,MAAM,wBAAwB,CAAC","sourcesContent":["export { AppTransport, type AppTransportOptions } from \"./AppTransport.js\";\nexport { ProviderTransport, type ProviderTransportOptions } from \"./ProviderTransport.js\";\nexport type { ProxyAssistantMessageEvent } from \"./proxy-types.js\";\nexport type { AgentRunConfig, AgentTransport } from \"./types.js\";\n"]}
@@ -0,0 +1,53 @@
1
+ import type { StopReason, Usage } from "@mariozechner/pi-ai";
2
+ /**
3
+ * Event types emitted by the proxy server.
4
+ * The server strips the `partial` field from delta events to reduce bandwidth.
5
+ * Clients reconstruct the partial message from these events.
6
+ */
7
+ export type ProxyAssistantMessageEvent = {
8
+ type: "start";
9
+ } | {
10
+ type: "text_start";
11
+ contentIndex: number;
12
+ } | {
13
+ type: "text_delta";
14
+ contentIndex: number;
15
+ delta: string;
16
+ } | {
17
+ type: "text_end";
18
+ contentIndex: number;
19
+ contentSignature?: string;
20
+ } | {
21
+ type: "thinking_start";
22
+ contentIndex: number;
23
+ } | {
24
+ type: "thinking_delta";
25
+ contentIndex: number;
26
+ delta: string;
27
+ } | {
28
+ type: "thinking_end";
29
+ contentIndex: number;
30
+ contentSignature?: string;
31
+ } | {
32
+ type: "toolcall_start";
33
+ contentIndex: number;
34
+ id: string;
35
+ toolName: string;
36
+ } | {
37
+ type: "toolcall_delta";
38
+ contentIndex: number;
39
+ delta: string;
40
+ } | {
41
+ type: "toolcall_end";
42
+ contentIndex: number;
43
+ } | {
44
+ type: "done";
45
+ reason: Extract<StopReason, "stop" | "length" | "toolUse">;
46
+ usage: Usage;
47
+ } | {
48
+ type: "error";
49
+ reason: Extract<StopReason, "aborted" | "error">;
50
+ errorMessage: string;
51
+ usage: Usage;
52
+ };
53
+ //# sourceMappingURL=proxy-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-types.d.ts","sourceRoot":"","sources":["../../src/transports/proxy-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GACnC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC5C;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACrE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,GACzE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAC9E;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC/D;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC","sourcesContent":["import type { StopReason, Usage } from \"@mariozechner/pi-ai\";\n\n/**\n * Event types emitted by the proxy server.\n * The server strips the `partial` field from delta events to reduce bandwidth.\n * Clients reconstruct the partial message from these events.\n */\nexport type ProxyAssistantMessageEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| { type: \"thinking_end\"; contentIndex: number; contentSignature?: string }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number }\n\t| { type: \"done\"; reason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\">; usage: Usage }\n\t| { type: \"error\"; reason: Extract<StopReason, \"aborted\" | \"error\">; errorMessage: string; usage: Usage };\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=proxy-types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proxy-types.js","sourceRoot":"","sources":["../../src/transports/proxy-types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StopReason, Usage } from \"@mariozechner/pi-ai\";\n\n/**\n * Event types emitted by the proxy server.\n * The server strips the `partial` field from delta events to reduce bandwidth.\n * Clients reconstruct the partial message from these events.\n */\nexport type ProxyAssistantMessageEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| { type: \"thinking_end\"; contentIndex: number; contentSignature?: string }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number }\n\t| { type: \"done\"; reason: Extract<StopReason, \"stop\" | \"length\" | \"toolUse\">; usage: Usage }\n\t| { type: \"error\"; reason: Extract<StopReason, \"aborted\" | \"error\">; errorMessage: string; usage: Usage };\n"]}
@@ -0,0 +1,22 @@
1
+ import type { AgentEvent, AgentTool, Message, Model, QueuedMessage } from "@mariozechner/pi-ai";
2
+ /**
3
+ * The minimal configuration needed to run an agent turn.
4
+ */
5
+ export interface AgentRunConfig {
6
+ systemPrompt: string;
7
+ tools: AgentTool<any>[];
8
+ model: Model<any>;
9
+ reasoning?: "low" | "medium" | "high";
10
+ getQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;
11
+ }
12
+ /**
13
+ * Transport interface for executing agent turns.
14
+ * Transports handle the communication with LLM providers,
15
+ * abstracting away the details of API calls, proxies, etc.
16
+ *
17
+ * Events yielded must match the @mariozechner/pi-ai AgentEvent types.
18
+ */
19
+ export interface AgentTransport {
20
+ run(messages: Message[], userMessage: Message, config: AgentRunConfig, signal?: AbortSignal): AsyncIterable<AgentEvent>;
21
+ }
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEhG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,SAAS,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;IACtC,iBAAiB,CAAC,EAAE,CAAC,CAAC,OAAO,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CACzD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC9B,GAAG,CACF,QAAQ,EAAE,OAAO,EAAE,EACnB,WAAW,EAAE,OAAO,EACpB,MAAM,EAAE,cAAc,EACtB,MAAM,CAAC,EAAE,WAAW,GAClB,aAAa,CAAC,UAAU,CAAC,CAAC;CAC7B","sourcesContent":["import type { AgentEvent, AgentTool, Message, Model, QueuedMessage } from \"@mariozechner/pi-ai\";\n\n/**\n * The minimal configuration needed to run an agent turn.\n */\nexport interface AgentRunConfig {\n\tsystemPrompt: string;\n\ttools: AgentTool<any>[];\n\tmodel: Model<any>;\n\treasoning?: \"low\" | \"medium\" | \"high\";\n\tgetQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;\n}\n\n/**\n * Transport interface for executing agent turns.\n * Transports handle the communication with LLM providers,\n * abstracting away the details of API calls, proxies, etc.\n *\n * Events yielded must match the @mariozechner/pi-ai AgentEvent types.\n */\nexport interface AgentTransport {\n\trun(\n\t\tmessages: Message[],\n\t\tuserMessage: Message,\n\t\tconfig: AgentRunConfig,\n\t\tsignal?: AbortSignal,\n\t): AsyncIterable<AgentEvent>;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { AgentEvent, AgentTool, Message, Model, QueuedMessage } from \"@mariozechner/pi-ai\";\n\n/**\n * The minimal configuration needed to run an agent turn.\n */\nexport interface AgentRunConfig {\n\tsystemPrompt: string;\n\ttools: AgentTool<any>[];\n\tmodel: Model<any>;\n\treasoning?: \"low\" | \"medium\" | \"high\";\n\tgetQueuedMessages?: <T>() => Promise<QueuedMessage<T>[]>;\n}\n\n/**\n * Transport interface for executing agent turns.\n * Transports handle the communication with LLM providers,\n * abstracting away the details of API calls, proxies, etc.\n *\n * Events yielded must match the @mariozechner/pi-ai AgentEvent types.\n */\nexport interface AgentTransport {\n\trun(\n\t\tmessages: Message[],\n\t\tuserMessage: Message,\n\t\tconfig: AgentRunConfig,\n\t\tsignal?: AbortSignal,\n\t): AsyncIterable<AgentEvent>;\n}\n"]}