@spfunctions/cli 1.7.39 → 2.0.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.
- package/dist/101.index.js +1 -451
- package/dist/12.index.js +1 -536
- package/dist/160.index.js +1 -709
- package/dist/174.index.js +1 -44
- package/dist/278.index.js +2 -15129
- package/dist/582.index.js +1 -1066
- package/dist/641.index.js +67 -122146
- package/dist/669.index.js +1 -556
- package/dist/722.index.js +1 -843
- package/dist/788.index.js +1 -6677
- package/dist/816.index.js +4 -7496
- package/dist/830.index.js +1 -1199
- package/dist/921.index.js +1 -10683
- package/dist/index.js +1 -1
- package/package.json +2 -2
- package/dist/package.json +0 -52
package/dist/582.index.js
CHANGED
|
@@ -1,1066 +1 @@
|
|
|
1
|
-
exports.id = 582;
|
|
2
|
-
exports.ids = [582,174];
|
|
3
|
-
exports.modules = {
|
|
4
|
-
|
|
5
|
-
/***/ 84005:
|
|
6
|
-
/***/ ((module) => {
|
|
7
|
-
|
|
8
|
-
function webpackEmptyAsyncContext(req) {
|
|
9
|
-
try { return Promise.resolve(require(req)); } catch(_) {
|
|
10
|
-
return Promise.resolve().then(() => {
|
|
11
|
-
var e = new Error("Cannot find module '" + req + "'");
|
|
12
|
-
e.code = 'MODULE_NOT_FOUND';
|
|
13
|
-
throw e;
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
webpackEmptyAsyncContext.keys = () => ([]);
|
|
18
|
-
webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
|
|
19
|
-
webpackEmptyAsyncContext.id = 84005;
|
|
20
|
-
module.exports = webpackEmptyAsyncContext;
|
|
21
|
-
|
|
22
|
-
/***/ }),
|
|
23
|
-
|
|
24
|
-
/***/ 70162:
|
|
25
|
-
/***/ ((module) => {
|
|
26
|
-
|
|
27
|
-
function webpackEmptyAsyncContext(req) {
|
|
28
|
-
try { return Promise.resolve(require(req)); } catch(_) {
|
|
29
|
-
return Promise.resolve().then(() => {
|
|
30
|
-
var e = new Error("Cannot find module '" + req + "'");
|
|
31
|
-
e.code = 'MODULE_NOT_FOUND';
|
|
32
|
-
throw e;
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
webpackEmptyAsyncContext.keys = () => ([]);
|
|
37
|
-
webpackEmptyAsyncContext.resolve = webpackEmptyAsyncContext;
|
|
38
|
-
webpackEmptyAsyncContext.id = 70162;
|
|
39
|
-
module.exports = webpackEmptyAsyncContext;
|
|
40
|
-
|
|
41
|
-
/***/ }),
|
|
42
|
-
|
|
43
|
-
/***/ 65653:
|
|
44
|
-
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
45
|
-
|
|
46
|
-
"use strict";
|
|
47
|
-
// ESM COMPAT FLAG
|
|
48
|
-
__webpack_require__.r(__webpack_exports__);
|
|
49
|
-
|
|
50
|
-
// EXPORTS
|
|
51
|
-
__webpack_require__.d(__webpack_exports__, {
|
|
52
|
-
Agent: () => (/* reexport */ Agent),
|
|
53
|
-
agentLoop: () => (/* reexport */ agentLoop),
|
|
54
|
-
agentLoopContinue: () => (/* reexport */ agentLoopContinue),
|
|
55
|
-
streamProxy: () => (/* reexport */ streamProxy)
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// EXTERNAL MODULE: ./node_modules/@mariozechner/pi-ai/dist/index.js + 194 modules
|
|
59
|
-
var dist = __webpack_require__(99641);
|
|
60
|
-
;// CONCATENATED MODULE: ./node_modules/@mariozechner/pi-agent-core/dist/agent-loop.js
|
|
61
|
-
/**
|
|
62
|
-
* Agent loop that works with AgentMessage throughout.
|
|
63
|
-
* Transforms to Message[] only at the LLM call boundary.
|
|
64
|
-
*/
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Start an agent loop with a new prompt message.
|
|
68
|
-
* The prompt is added to the context and events are emitted for it.
|
|
69
|
-
*/
|
|
70
|
-
function agentLoop(prompts, context, config, signal, streamFn) {
|
|
71
|
-
const stream = createAgentStream();
|
|
72
|
-
(async () => {
|
|
73
|
-
const newMessages = [...prompts];
|
|
74
|
-
const currentContext = {
|
|
75
|
-
...context,
|
|
76
|
-
messages: [...context.messages, ...prompts],
|
|
77
|
-
};
|
|
78
|
-
stream.push({ type: "agent_start" });
|
|
79
|
-
stream.push({ type: "turn_start" });
|
|
80
|
-
for (const prompt of prompts) {
|
|
81
|
-
stream.push({ type: "message_start", message: prompt });
|
|
82
|
-
stream.push({ type: "message_end", message: prompt });
|
|
83
|
-
}
|
|
84
|
-
await runLoop(currentContext, newMessages, config, signal, stream, streamFn);
|
|
85
|
-
})();
|
|
86
|
-
return stream;
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* Continue an agent loop from the current context without adding a new message.
|
|
90
|
-
* Used for retries - context already has user message or tool results.
|
|
91
|
-
*
|
|
92
|
-
* **Important:** The last message in context must convert to a `user` or `toolResult` message
|
|
93
|
-
* via `convertToLlm`. If it doesn't, the LLM provider will reject the request.
|
|
94
|
-
* This cannot be validated here since `convertToLlm` is only called once per turn.
|
|
95
|
-
*/
|
|
96
|
-
function agentLoopContinue(context, config, signal, streamFn) {
|
|
97
|
-
if (context.messages.length === 0) {
|
|
98
|
-
throw new Error("Cannot continue: no messages in context");
|
|
99
|
-
}
|
|
100
|
-
if (context.messages[context.messages.length - 1].role === "assistant") {
|
|
101
|
-
throw new Error("Cannot continue from message role: assistant");
|
|
102
|
-
}
|
|
103
|
-
const stream = createAgentStream();
|
|
104
|
-
(async () => {
|
|
105
|
-
const newMessages = [];
|
|
106
|
-
const currentContext = { ...context };
|
|
107
|
-
stream.push({ type: "agent_start" });
|
|
108
|
-
stream.push({ type: "turn_start" });
|
|
109
|
-
await runLoop(currentContext, newMessages, config, signal, stream, streamFn);
|
|
110
|
-
})();
|
|
111
|
-
return stream;
|
|
112
|
-
}
|
|
113
|
-
function createAgentStream() {
|
|
114
|
-
return new dist.EventStream((event) => event.type === "agent_end", (event) => (event.type === "agent_end" ? event.messages : []));
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Main loop logic shared by agentLoop and agentLoopContinue.
|
|
118
|
-
*/
|
|
119
|
-
async function runLoop(currentContext, newMessages, config, signal, stream, streamFn) {
|
|
120
|
-
let firstTurn = true;
|
|
121
|
-
// Check for steering messages at start (user may have typed while waiting)
|
|
122
|
-
let pendingMessages = (await config.getSteeringMessages?.()) || [];
|
|
123
|
-
// Outer loop: continues when queued follow-up messages arrive after agent would stop
|
|
124
|
-
while (true) {
|
|
125
|
-
let hasMoreToolCalls = true;
|
|
126
|
-
let steeringAfterTools = null;
|
|
127
|
-
// Inner loop: process tool calls and steering messages
|
|
128
|
-
while (hasMoreToolCalls || pendingMessages.length > 0) {
|
|
129
|
-
if (!firstTurn) {
|
|
130
|
-
stream.push({ type: "turn_start" });
|
|
131
|
-
}
|
|
132
|
-
else {
|
|
133
|
-
firstTurn = false;
|
|
134
|
-
}
|
|
135
|
-
// Process pending messages (inject before next assistant response)
|
|
136
|
-
if (pendingMessages.length > 0) {
|
|
137
|
-
for (const message of pendingMessages) {
|
|
138
|
-
stream.push({ type: "message_start", message });
|
|
139
|
-
stream.push({ type: "message_end", message });
|
|
140
|
-
currentContext.messages.push(message);
|
|
141
|
-
newMessages.push(message);
|
|
142
|
-
}
|
|
143
|
-
pendingMessages = [];
|
|
144
|
-
}
|
|
145
|
-
// Stream assistant response
|
|
146
|
-
const message = await streamAssistantResponse(currentContext, config, signal, stream, streamFn);
|
|
147
|
-
newMessages.push(message);
|
|
148
|
-
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
|
149
|
-
stream.push({ type: "turn_end", message, toolResults: [] });
|
|
150
|
-
stream.push({ type: "agent_end", messages: newMessages });
|
|
151
|
-
stream.end(newMessages);
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
// Check for tool calls
|
|
155
|
-
const toolCalls = message.content.filter((c) => c.type === "toolCall");
|
|
156
|
-
hasMoreToolCalls = toolCalls.length > 0;
|
|
157
|
-
const toolResults = [];
|
|
158
|
-
if (hasMoreToolCalls) {
|
|
159
|
-
const toolExecution = await executeToolCalls(currentContext.tools, message, signal, stream, config.getSteeringMessages);
|
|
160
|
-
toolResults.push(...toolExecution.toolResults);
|
|
161
|
-
steeringAfterTools = toolExecution.steeringMessages ?? null;
|
|
162
|
-
for (const result of toolResults) {
|
|
163
|
-
currentContext.messages.push(result);
|
|
164
|
-
newMessages.push(result);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
stream.push({ type: "turn_end", message, toolResults });
|
|
168
|
-
// Get steering messages after turn completes
|
|
169
|
-
if (steeringAfterTools && steeringAfterTools.length > 0) {
|
|
170
|
-
pendingMessages = steeringAfterTools;
|
|
171
|
-
steeringAfterTools = null;
|
|
172
|
-
}
|
|
173
|
-
else {
|
|
174
|
-
pendingMessages = (await config.getSteeringMessages?.()) || [];
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
// Agent would stop here. Check for follow-up messages.
|
|
178
|
-
const followUpMessages = (await config.getFollowUpMessages?.()) || [];
|
|
179
|
-
if (followUpMessages.length > 0) {
|
|
180
|
-
// Set as pending so inner loop processes them
|
|
181
|
-
pendingMessages = followUpMessages;
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
// No more messages, exit
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
stream.push({ type: "agent_end", messages: newMessages });
|
|
188
|
-
stream.end(newMessages);
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Stream an assistant response from the LLM.
|
|
192
|
-
* This is where AgentMessage[] gets transformed to Message[] for the LLM.
|
|
193
|
-
*/
|
|
194
|
-
async function streamAssistantResponse(context, config, signal, stream, streamFn) {
|
|
195
|
-
// Apply context transform if configured (AgentMessage[] → AgentMessage[])
|
|
196
|
-
let messages = context.messages;
|
|
197
|
-
if (config.transformContext) {
|
|
198
|
-
messages = await config.transformContext(messages, signal);
|
|
199
|
-
}
|
|
200
|
-
// Convert to LLM-compatible messages (AgentMessage[] → Message[])
|
|
201
|
-
const llmMessages = await config.convertToLlm(messages);
|
|
202
|
-
// Build LLM context
|
|
203
|
-
const llmContext = {
|
|
204
|
-
systemPrompt: context.systemPrompt,
|
|
205
|
-
messages: llmMessages,
|
|
206
|
-
tools: context.tools,
|
|
207
|
-
};
|
|
208
|
-
const streamFunction = streamFn || dist.streamSimple;
|
|
209
|
-
// Resolve API key (important for expiring tokens)
|
|
210
|
-
const resolvedApiKey = (config.getApiKey ? await config.getApiKey(config.model.provider) : undefined) || config.apiKey;
|
|
211
|
-
const response = await streamFunction(config.model, llmContext, {
|
|
212
|
-
...config,
|
|
213
|
-
apiKey: resolvedApiKey,
|
|
214
|
-
signal,
|
|
215
|
-
});
|
|
216
|
-
let partialMessage = null;
|
|
217
|
-
let addedPartial = false;
|
|
218
|
-
for await (const event of response) {
|
|
219
|
-
switch (event.type) {
|
|
220
|
-
case "start":
|
|
221
|
-
partialMessage = event.partial;
|
|
222
|
-
context.messages.push(partialMessage);
|
|
223
|
-
addedPartial = true;
|
|
224
|
-
stream.push({ type: "message_start", message: { ...partialMessage } });
|
|
225
|
-
break;
|
|
226
|
-
case "text_start":
|
|
227
|
-
case "text_delta":
|
|
228
|
-
case "text_end":
|
|
229
|
-
case "thinking_start":
|
|
230
|
-
case "thinking_delta":
|
|
231
|
-
case "thinking_end":
|
|
232
|
-
case "toolcall_start":
|
|
233
|
-
case "toolcall_delta":
|
|
234
|
-
case "toolcall_end":
|
|
235
|
-
if (partialMessage) {
|
|
236
|
-
partialMessage = event.partial;
|
|
237
|
-
context.messages[context.messages.length - 1] = partialMessage;
|
|
238
|
-
stream.push({
|
|
239
|
-
type: "message_update",
|
|
240
|
-
assistantMessageEvent: event,
|
|
241
|
-
message: { ...partialMessage },
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
break;
|
|
245
|
-
case "done":
|
|
246
|
-
case "error": {
|
|
247
|
-
const finalMessage = await response.result();
|
|
248
|
-
if (addedPartial) {
|
|
249
|
-
context.messages[context.messages.length - 1] = finalMessage;
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
context.messages.push(finalMessage);
|
|
253
|
-
}
|
|
254
|
-
if (!addedPartial) {
|
|
255
|
-
stream.push({ type: "message_start", message: { ...finalMessage } });
|
|
256
|
-
}
|
|
257
|
-
stream.push({ type: "message_end", message: finalMessage });
|
|
258
|
-
return finalMessage;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
return await response.result();
|
|
263
|
-
}
|
|
264
|
-
/**
|
|
265
|
-
* Execute tool calls from an assistant message.
|
|
266
|
-
*/
|
|
267
|
-
async function executeToolCalls(tools, assistantMessage, signal, stream, getSteeringMessages) {
|
|
268
|
-
const toolCalls = assistantMessage.content.filter((c) => c.type === "toolCall");
|
|
269
|
-
const results = [];
|
|
270
|
-
let steeringMessages;
|
|
271
|
-
for (let index = 0; index < toolCalls.length; index++) {
|
|
272
|
-
const toolCall = toolCalls[index];
|
|
273
|
-
const tool = tools?.find((t) => t.name === toolCall.name);
|
|
274
|
-
stream.push({
|
|
275
|
-
type: "tool_execution_start",
|
|
276
|
-
toolCallId: toolCall.id,
|
|
277
|
-
toolName: toolCall.name,
|
|
278
|
-
args: toolCall.arguments,
|
|
279
|
-
});
|
|
280
|
-
let result;
|
|
281
|
-
let isError = false;
|
|
282
|
-
try {
|
|
283
|
-
if (!tool)
|
|
284
|
-
throw new Error(`Tool ${toolCall.name} not found`);
|
|
285
|
-
const validatedArgs = (0,dist.validateToolArguments)(tool, toolCall);
|
|
286
|
-
result = await tool.execute(toolCall.id, validatedArgs, signal, (partialResult) => {
|
|
287
|
-
stream.push({
|
|
288
|
-
type: "tool_execution_update",
|
|
289
|
-
toolCallId: toolCall.id,
|
|
290
|
-
toolName: toolCall.name,
|
|
291
|
-
args: toolCall.arguments,
|
|
292
|
-
partialResult,
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
catch (e) {
|
|
297
|
-
result = {
|
|
298
|
-
content: [{ type: "text", text: e instanceof Error ? e.message : String(e) }],
|
|
299
|
-
details: {},
|
|
300
|
-
};
|
|
301
|
-
isError = true;
|
|
302
|
-
}
|
|
303
|
-
stream.push({
|
|
304
|
-
type: "tool_execution_end",
|
|
305
|
-
toolCallId: toolCall.id,
|
|
306
|
-
toolName: toolCall.name,
|
|
307
|
-
result,
|
|
308
|
-
isError,
|
|
309
|
-
});
|
|
310
|
-
const toolResultMessage = {
|
|
311
|
-
role: "toolResult",
|
|
312
|
-
toolCallId: toolCall.id,
|
|
313
|
-
toolName: toolCall.name,
|
|
314
|
-
content: result.content,
|
|
315
|
-
details: result.details,
|
|
316
|
-
isError,
|
|
317
|
-
timestamp: Date.now(),
|
|
318
|
-
};
|
|
319
|
-
results.push(toolResultMessage);
|
|
320
|
-
stream.push({ type: "message_start", message: toolResultMessage });
|
|
321
|
-
stream.push({ type: "message_end", message: toolResultMessage });
|
|
322
|
-
// Check for steering messages - skip remaining tools if user interrupted
|
|
323
|
-
if (getSteeringMessages) {
|
|
324
|
-
const steering = await getSteeringMessages();
|
|
325
|
-
if (steering.length > 0) {
|
|
326
|
-
steeringMessages = steering;
|
|
327
|
-
const remainingCalls = toolCalls.slice(index + 1);
|
|
328
|
-
for (const skipped of remainingCalls) {
|
|
329
|
-
results.push(skipToolCall(skipped, stream));
|
|
330
|
-
}
|
|
331
|
-
break;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return { toolResults: results, steeringMessages };
|
|
336
|
-
}
|
|
337
|
-
function skipToolCall(toolCall, stream) {
|
|
338
|
-
const result = {
|
|
339
|
-
content: [{ type: "text", text: "Skipped due to queued user message." }],
|
|
340
|
-
details: {},
|
|
341
|
-
};
|
|
342
|
-
stream.push({
|
|
343
|
-
type: "tool_execution_start",
|
|
344
|
-
toolCallId: toolCall.id,
|
|
345
|
-
toolName: toolCall.name,
|
|
346
|
-
args: toolCall.arguments,
|
|
347
|
-
});
|
|
348
|
-
stream.push({
|
|
349
|
-
type: "tool_execution_end",
|
|
350
|
-
toolCallId: toolCall.id,
|
|
351
|
-
toolName: toolCall.name,
|
|
352
|
-
result,
|
|
353
|
-
isError: true,
|
|
354
|
-
});
|
|
355
|
-
const toolResultMessage = {
|
|
356
|
-
role: "toolResult",
|
|
357
|
-
toolCallId: toolCall.id,
|
|
358
|
-
toolName: toolCall.name,
|
|
359
|
-
content: result.content,
|
|
360
|
-
details: {},
|
|
361
|
-
isError: true,
|
|
362
|
-
timestamp: Date.now(),
|
|
363
|
-
};
|
|
364
|
-
stream.push({ type: "message_start", message: toolResultMessage });
|
|
365
|
-
stream.push({ type: "message_end", message: toolResultMessage });
|
|
366
|
-
return toolResultMessage;
|
|
367
|
-
}
|
|
368
|
-
//# sourceMappingURL=agent-loop.js.map
|
|
369
|
-
;// CONCATENATED MODULE: ./node_modules/@mariozechner/pi-agent-core/dist/agent.js
|
|
370
|
-
/**
|
|
371
|
-
* Agent class that uses the agent-loop directly.
|
|
372
|
-
* No transport abstraction - calls streamSimple via the loop.
|
|
373
|
-
*/
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
/**
|
|
377
|
-
* Default convertToLlm: Keep only LLM-compatible messages, convert attachments.
|
|
378
|
-
*/
|
|
379
|
-
function defaultConvertToLlm(messages) {
|
|
380
|
-
return messages.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult");
|
|
381
|
-
}
|
|
382
|
-
class Agent {
|
|
383
|
-
_state = {
|
|
384
|
-
systemPrompt: "",
|
|
385
|
-
model: (0,dist.getModel)("google", "gemini-2.5-flash-lite-preview-06-17"),
|
|
386
|
-
thinkingLevel: "off",
|
|
387
|
-
tools: [],
|
|
388
|
-
messages: [],
|
|
389
|
-
isStreaming: false,
|
|
390
|
-
streamMessage: null,
|
|
391
|
-
pendingToolCalls: new Set(),
|
|
392
|
-
error: undefined,
|
|
393
|
-
};
|
|
394
|
-
listeners = new Set();
|
|
395
|
-
abortController;
|
|
396
|
-
convertToLlm;
|
|
397
|
-
transformContext;
|
|
398
|
-
steeringQueue = [];
|
|
399
|
-
followUpQueue = [];
|
|
400
|
-
steeringMode;
|
|
401
|
-
followUpMode;
|
|
402
|
-
streamFn;
|
|
403
|
-
_sessionId;
|
|
404
|
-
getApiKey;
|
|
405
|
-
_onPayload;
|
|
406
|
-
runningPrompt;
|
|
407
|
-
resolveRunningPrompt;
|
|
408
|
-
_thinkingBudgets;
|
|
409
|
-
_transport;
|
|
410
|
-
_maxRetryDelayMs;
|
|
411
|
-
constructor(opts = {}) {
|
|
412
|
-
this._state = { ...this._state, ...opts.initialState };
|
|
413
|
-
this.convertToLlm = opts.convertToLlm || defaultConvertToLlm;
|
|
414
|
-
this.transformContext = opts.transformContext;
|
|
415
|
-
this.steeringMode = opts.steeringMode || "one-at-a-time";
|
|
416
|
-
this.followUpMode = opts.followUpMode || "one-at-a-time";
|
|
417
|
-
this.streamFn = opts.streamFn || dist.streamSimple;
|
|
418
|
-
this._sessionId = opts.sessionId;
|
|
419
|
-
this.getApiKey = opts.getApiKey;
|
|
420
|
-
this._onPayload = opts.onPayload;
|
|
421
|
-
this._thinkingBudgets = opts.thinkingBudgets;
|
|
422
|
-
this._transport = opts.transport ?? "sse";
|
|
423
|
-
this._maxRetryDelayMs = opts.maxRetryDelayMs;
|
|
424
|
-
}
|
|
425
|
-
/**
|
|
426
|
-
* Get the current session ID used for provider caching.
|
|
427
|
-
*/
|
|
428
|
-
get sessionId() {
|
|
429
|
-
return this._sessionId;
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Set the session ID for provider caching.
|
|
433
|
-
* Call this when switching sessions (new session, branch, resume).
|
|
434
|
-
*/
|
|
435
|
-
set sessionId(value) {
|
|
436
|
-
this._sessionId = value;
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Get the current thinking budgets.
|
|
440
|
-
*/
|
|
441
|
-
get thinkingBudgets() {
|
|
442
|
-
return this._thinkingBudgets;
|
|
443
|
-
}
|
|
444
|
-
/**
|
|
445
|
-
* Set custom thinking budgets for token-based providers.
|
|
446
|
-
*/
|
|
447
|
-
set thinkingBudgets(value) {
|
|
448
|
-
this._thinkingBudgets = value;
|
|
449
|
-
}
|
|
450
|
-
/**
|
|
451
|
-
* Get the current preferred transport.
|
|
452
|
-
*/
|
|
453
|
-
get transport() {
|
|
454
|
-
return this._transport;
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Set the preferred transport.
|
|
458
|
-
*/
|
|
459
|
-
setTransport(value) {
|
|
460
|
-
this._transport = value;
|
|
461
|
-
}
|
|
462
|
-
/**
|
|
463
|
-
* Get the current max retry delay in milliseconds.
|
|
464
|
-
*/
|
|
465
|
-
get maxRetryDelayMs() {
|
|
466
|
-
return this._maxRetryDelayMs;
|
|
467
|
-
}
|
|
468
|
-
/**
|
|
469
|
-
* Set the maximum delay to wait for server-requested retries.
|
|
470
|
-
* Set to 0 to disable the cap.
|
|
471
|
-
*/
|
|
472
|
-
set maxRetryDelayMs(value) {
|
|
473
|
-
this._maxRetryDelayMs = value;
|
|
474
|
-
}
|
|
475
|
-
get state() {
|
|
476
|
-
return this._state;
|
|
477
|
-
}
|
|
478
|
-
subscribe(fn) {
|
|
479
|
-
this.listeners.add(fn);
|
|
480
|
-
return () => this.listeners.delete(fn);
|
|
481
|
-
}
|
|
482
|
-
// State mutators
|
|
483
|
-
setSystemPrompt(v) {
|
|
484
|
-
this._state.systemPrompt = v;
|
|
485
|
-
}
|
|
486
|
-
setModel(m) {
|
|
487
|
-
this._state.model = m;
|
|
488
|
-
}
|
|
489
|
-
setThinkingLevel(l) {
|
|
490
|
-
this._state.thinkingLevel = l;
|
|
491
|
-
}
|
|
492
|
-
setSteeringMode(mode) {
|
|
493
|
-
this.steeringMode = mode;
|
|
494
|
-
}
|
|
495
|
-
getSteeringMode() {
|
|
496
|
-
return this.steeringMode;
|
|
497
|
-
}
|
|
498
|
-
setFollowUpMode(mode) {
|
|
499
|
-
this.followUpMode = mode;
|
|
500
|
-
}
|
|
501
|
-
getFollowUpMode() {
|
|
502
|
-
return this.followUpMode;
|
|
503
|
-
}
|
|
504
|
-
setTools(t) {
|
|
505
|
-
this._state.tools = t;
|
|
506
|
-
}
|
|
507
|
-
replaceMessages(ms) {
|
|
508
|
-
this._state.messages = ms.slice();
|
|
509
|
-
}
|
|
510
|
-
appendMessage(m) {
|
|
511
|
-
this._state.messages = [...this._state.messages, m];
|
|
512
|
-
}
|
|
513
|
-
/**
|
|
514
|
-
* Queue a steering message to interrupt the agent mid-run.
|
|
515
|
-
* Delivered after current tool execution, skips remaining tools.
|
|
516
|
-
*/
|
|
517
|
-
steer(m) {
|
|
518
|
-
this.steeringQueue.push(m);
|
|
519
|
-
}
|
|
520
|
-
/**
|
|
521
|
-
* Queue a follow-up message to be processed after the agent finishes.
|
|
522
|
-
* Delivered only when agent has no more tool calls or steering messages.
|
|
523
|
-
*/
|
|
524
|
-
followUp(m) {
|
|
525
|
-
this.followUpQueue.push(m);
|
|
526
|
-
}
|
|
527
|
-
clearSteeringQueue() {
|
|
528
|
-
this.steeringQueue = [];
|
|
529
|
-
}
|
|
530
|
-
clearFollowUpQueue() {
|
|
531
|
-
this.followUpQueue = [];
|
|
532
|
-
}
|
|
533
|
-
clearAllQueues() {
|
|
534
|
-
this.steeringQueue = [];
|
|
535
|
-
this.followUpQueue = [];
|
|
536
|
-
}
|
|
537
|
-
hasQueuedMessages() {
|
|
538
|
-
return this.steeringQueue.length > 0 || this.followUpQueue.length > 0;
|
|
539
|
-
}
|
|
540
|
-
dequeueSteeringMessages() {
|
|
541
|
-
if (this.steeringMode === "one-at-a-time") {
|
|
542
|
-
if (this.steeringQueue.length > 0) {
|
|
543
|
-
const first = this.steeringQueue[0];
|
|
544
|
-
this.steeringQueue = this.steeringQueue.slice(1);
|
|
545
|
-
return [first];
|
|
546
|
-
}
|
|
547
|
-
return [];
|
|
548
|
-
}
|
|
549
|
-
const steering = this.steeringQueue.slice();
|
|
550
|
-
this.steeringQueue = [];
|
|
551
|
-
return steering;
|
|
552
|
-
}
|
|
553
|
-
dequeueFollowUpMessages() {
|
|
554
|
-
if (this.followUpMode === "one-at-a-time") {
|
|
555
|
-
if (this.followUpQueue.length > 0) {
|
|
556
|
-
const first = this.followUpQueue[0];
|
|
557
|
-
this.followUpQueue = this.followUpQueue.slice(1);
|
|
558
|
-
return [first];
|
|
559
|
-
}
|
|
560
|
-
return [];
|
|
561
|
-
}
|
|
562
|
-
const followUp = this.followUpQueue.slice();
|
|
563
|
-
this.followUpQueue = [];
|
|
564
|
-
return followUp;
|
|
565
|
-
}
|
|
566
|
-
clearMessages() {
|
|
567
|
-
this._state.messages = [];
|
|
568
|
-
}
|
|
569
|
-
abort() {
|
|
570
|
-
this.abortController?.abort();
|
|
571
|
-
}
|
|
572
|
-
waitForIdle() {
|
|
573
|
-
return this.runningPrompt ?? Promise.resolve();
|
|
574
|
-
}
|
|
575
|
-
reset() {
|
|
576
|
-
this._state.messages = [];
|
|
577
|
-
this._state.isStreaming = false;
|
|
578
|
-
this._state.streamMessage = null;
|
|
579
|
-
this._state.pendingToolCalls = new Set();
|
|
580
|
-
this._state.error = undefined;
|
|
581
|
-
this.steeringQueue = [];
|
|
582
|
-
this.followUpQueue = [];
|
|
583
|
-
}
|
|
584
|
-
async prompt(input, images) {
|
|
585
|
-
if (this._state.isStreaming) {
|
|
586
|
-
throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");
|
|
587
|
-
}
|
|
588
|
-
const model = this._state.model;
|
|
589
|
-
if (!model)
|
|
590
|
-
throw new Error("No model configured");
|
|
591
|
-
let msgs;
|
|
592
|
-
if (Array.isArray(input)) {
|
|
593
|
-
msgs = input;
|
|
594
|
-
}
|
|
595
|
-
else if (typeof input === "string") {
|
|
596
|
-
const content = [{ type: "text", text: input }];
|
|
597
|
-
if (images && images.length > 0) {
|
|
598
|
-
content.push(...images);
|
|
599
|
-
}
|
|
600
|
-
msgs = [
|
|
601
|
-
{
|
|
602
|
-
role: "user",
|
|
603
|
-
content,
|
|
604
|
-
timestamp: Date.now(),
|
|
605
|
-
},
|
|
606
|
-
];
|
|
607
|
-
}
|
|
608
|
-
else {
|
|
609
|
-
msgs = [input];
|
|
610
|
-
}
|
|
611
|
-
await this._runLoop(msgs);
|
|
612
|
-
}
|
|
613
|
-
/**
|
|
614
|
-
* Continue from current context (used for retries and resuming queued messages).
|
|
615
|
-
*/
|
|
616
|
-
async continue() {
|
|
617
|
-
if (this._state.isStreaming) {
|
|
618
|
-
throw new Error("Agent is already processing. Wait for completion before continuing.");
|
|
619
|
-
}
|
|
620
|
-
const messages = this._state.messages;
|
|
621
|
-
if (messages.length === 0) {
|
|
622
|
-
throw new Error("No messages to continue from");
|
|
623
|
-
}
|
|
624
|
-
if (messages[messages.length - 1].role === "assistant") {
|
|
625
|
-
const queuedSteering = this.dequeueSteeringMessages();
|
|
626
|
-
if (queuedSteering.length > 0) {
|
|
627
|
-
await this._runLoop(queuedSteering, { skipInitialSteeringPoll: true });
|
|
628
|
-
return;
|
|
629
|
-
}
|
|
630
|
-
const queuedFollowUp = this.dequeueFollowUpMessages();
|
|
631
|
-
if (queuedFollowUp.length > 0) {
|
|
632
|
-
await this._runLoop(queuedFollowUp);
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
|
-
throw new Error("Cannot continue from message role: assistant");
|
|
636
|
-
}
|
|
637
|
-
await this._runLoop(undefined);
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
* Run the agent loop.
|
|
641
|
-
* If messages are provided, starts a new conversation turn with those messages.
|
|
642
|
-
* Otherwise, continues from existing context.
|
|
643
|
-
*/
|
|
644
|
-
async _runLoop(messages, options) {
|
|
645
|
-
const model = this._state.model;
|
|
646
|
-
if (!model)
|
|
647
|
-
throw new Error("No model configured");
|
|
648
|
-
this.runningPrompt = new Promise((resolve) => {
|
|
649
|
-
this.resolveRunningPrompt = resolve;
|
|
650
|
-
});
|
|
651
|
-
this.abortController = new AbortController();
|
|
652
|
-
this._state.isStreaming = true;
|
|
653
|
-
this._state.streamMessage = null;
|
|
654
|
-
this._state.error = undefined;
|
|
655
|
-
const reasoning = this._state.thinkingLevel === "off" ? undefined : this._state.thinkingLevel;
|
|
656
|
-
const context = {
|
|
657
|
-
systemPrompt: this._state.systemPrompt,
|
|
658
|
-
messages: this._state.messages.slice(),
|
|
659
|
-
tools: this._state.tools,
|
|
660
|
-
};
|
|
661
|
-
let skipInitialSteeringPoll = options?.skipInitialSteeringPoll === true;
|
|
662
|
-
const config = {
|
|
663
|
-
model,
|
|
664
|
-
reasoning,
|
|
665
|
-
sessionId: this._sessionId,
|
|
666
|
-
onPayload: this._onPayload,
|
|
667
|
-
transport: this._transport,
|
|
668
|
-
thinkingBudgets: this._thinkingBudgets,
|
|
669
|
-
maxRetryDelayMs: this._maxRetryDelayMs,
|
|
670
|
-
convertToLlm: this.convertToLlm,
|
|
671
|
-
transformContext: this.transformContext,
|
|
672
|
-
getApiKey: this.getApiKey,
|
|
673
|
-
getSteeringMessages: async () => {
|
|
674
|
-
if (skipInitialSteeringPoll) {
|
|
675
|
-
skipInitialSteeringPoll = false;
|
|
676
|
-
return [];
|
|
677
|
-
}
|
|
678
|
-
return this.dequeueSteeringMessages();
|
|
679
|
-
},
|
|
680
|
-
getFollowUpMessages: async () => this.dequeueFollowUpMessages(),
|
|
681
|
-
};
|
|
682
|
-
let partial = null;
|
|
683
|
-
try {
|
|
684
|
-
const stream = messages
|
|
685
|
-
? agentLoop(messages, context, config, this.abortController.signal, this.streamFn)
|
|
686
|
-
: agentLoopContinue(context, config, this.abortController.signal, this.streamFn);
|
|
687
|
-
for await (const event of stream) {
|
|
688
|
-
// Update internal state based on events
|
|
689
|
-
switch (event.type) {
|
|
690
|
-
case "message_start":
|
|
691
|
-
partial = event.message;
|
|
692
|
-
this._state.streamMessage = event.message;
|
|
693
|
-
break;
|
|
694
|
-
case "message_update":
|
|
695
|
-
partial = event.message;
|
|
696
|
-
this._state.streamMessage = event.message;
|
|
697
|
-
break;
|
|
698
|
-
case "message_end":
|
|
699
|
-
partial = null;
|
|
700
|
-
this._state.streamMessage = null;
|
|
701
|
-
this.appendMessage(event.message);
|
|
702
|
-
break;
|
|
703
|
-
case "tool_execution_start": {
|
|
704
|
-
const s = new Set(this._state.pendingToolCalls);
|
|
705
|
-
s.add(event.toolCallId);
|
|
706
|
-
this._state.pendingToolCalls = s;
|
|
707
|
-
break;
|
|
708
|
-
}
|
|
709
|
-
case "tool_execution_end": {
|
|
710
|
-
const s = new Set(this._state.pendingToolCalls);
|
|
711
|
-
s.delete(event.toolCallId);
|
|
712
|
-
this._state.pendingToolCalls = s;
|
|
713
|
-
break;
|
|
714
|
-
}
|
|
715
|
-
case "turn_end":
|
|
716
|
-
if (event.message.role === "assistant" && event.message.errorMessage) {
|
|
717
|
-
this._state.error = event.message.errorMessage;
|
|
718
|
-
}
|
|
719
|
-
break;
|
|
720
|
-
case "agent_end":
|
|
721
|
-
this._state.isStreaming = false;
|
|
722
|
-
this._state.streamMessage = null;
|
|
723
|
-
break;
|
|
724
|
-
}
|
|
725
|
-
// Emit to listeners
|
|
726
|
-
this.emit(event);
|
|
727
|
-
}
|
|
728
|
-
// Handle any remaining partial message
|
|
729
|
-
if (partial && partial.role === "assistant" && partial.content.length > 0) {
|
|
730
|
-
const onlyEmpty = !partial.content.some((c) => (c.type === "thinking" && c.thinking.trim().length > 0) ||
|
|
731
|
-
(c.type === "text" && c.text.trim().length > 0) ||
|
|
732
|
-
(c.type === "toolCall" && c.name.trim().length > 0));
|
|
733
|
-
if (!onlyEmpty) {
|
|
734
|
-
this.appendMessage(partial);
|
|
735
|
-
}
|
|
736
|
-
else {
|
|
737
|
-
if (this.abortController?.signal.aborted) {
|
|
738
|
-
throw new Error("Request was aborted");
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
}
|
|
743
|
-
catch (err) {
|
|
744
|
-
const errorMsg = {
|
|
745
|
-
role: "assistant",
|
|
746
|
-
content: [{ type: "text", text: "" }],
|
|
747
|
-
api: model.api,
|
|
748
|
-
provider: model.provider,
|
|
749
|
-
model: model.id,
|
|
750
|
-
usage: {
|
|
751
|
-
input: 0,
|
|
752
|
-
output: 0,
|
|
753
|
-
cacheRead: 0,
|
|
754
|
-
cacheWrite: 0,
|
|
755
|
-
totalTokens: 0,
|
|
756
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
757
|
-
},
|
|
758
|
-
stopReason: this.abortController?.signal.aborted ? "aborted" : "error",
|
|
759
|
-
errorMessage: err?.message || String(err),
|
|
760
|
-
timestamp: Date.now(),
|
|
761
|
-
};
|
|
762
|
-
this.appendMessage(errorMsg);
|
|
763
|
-
this._state.error = err?.message || String(err);
|
|
764
|
-
this.emit({ type: "agent_end", messages: [errorMsg] });
|
|
765
|
-
}
|
|
766
|
-
finally {
|
|
767
|
-
this._state.isStreaming = false;
|
|
768
|
-
this._state.streamMessage = null;
|
|
769
|
-
this._state.pendingToolCalls = new Set();
|
|
770
|
-
this.abortController = undefined;
|
|
771
|
-
this.resolveRunningPrompt?.();
|
|
772
|
-
this.runningPrompt = undefined;
|
|
773
|
-
this.resolveRunningPrompt = undefined;
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
emit(e) {
|
|
777
|
-
for (const listener of this.listeners) {
|
|
778
|
-
listener(e);
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
//# sourceMappingURL=agent.js.map
|
|
783
|
-
;// CONCATENATED MODULE: ./node_modules/@mariozechner/pi-agent-core/dist/proxy.js
|
|
784
|
-
/**
|
|
785
|
-
* Proxy stream function for apps that route LLM calls through a server.
|
|
786
|
-
* The server manages auth and proxies requests to LLM providers.
|
|
787
|
-
*/
|
|
788
|
-
// Internal import for JSON parsing utility
|
|
789
|
-
|
|
790
|
-
// Create stream class matching ProxyMessageEventStream
|
|
791
|
-
class ProxyMessageEventStream extends dist.EventStream {
|
|
792
|
-
constructor() {
|
|
793
|
-
super((event) => event.type === "done" || event.type === "error", (event) => {
|
|
794
|
-
if (event.type === "done")
|
|
795
|
-
return event.message;
|
|
796
|
-
if (event.type === "error")
|
|
797
|
-
return event.error;
|
|
798
|
-
throw new Error("Unexpected event type");
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
}
|
|
802
|
-
/**
|
|
803
|
-
* Stream function that proxies through a server instead of calling LLM providers directly.
|
|
804
|
-
* The server strips the partial field from delta events to reduce bandwidth.
|
|
805
|
-
* We reconstruct the partial message client-side.
|
|
806
|
-
*
|
|
807
|
-
* Use this as the `streamFn` option when creating an Agent that needs to go through a proxy.
|
|
808
|
-
*
|
|
809
|
-
* @example
|
|
810
|
-
* ```typescript
|
|
811
|
-
* const agent = new Agent({
|
|
812
|
-
* streamFn: (model, context, options) =>
|
|
813
|
-
* streamProxy(model, context, {
|
|
814
|
-
* ...options,
|
|
815
|
-
* authToken: await getAuthToken(),
|
|
816
|
-
* proxyUrl: "https://genai.example.com",
|
|
817
|
-
* }),
|
|
818
|
-
* });
|
|
819
|
-
* ```
|
|
820
|
-
*/
|
|
821
|
-
function streamProxy(model, context, options) {
|
|
822
|
-
const stream = new ProxyMessageEventStream();
|
|
823
|
-
(async () => {
|
|
824
|
-
// Initialize the partial message that we'll build up from events
|
|
825
|
-
const partial = {
|
|
826
|
-
role: "assistant",
|
|
827
|
-
stopReason: "stop",
|
|
828
|
-
content: [],
|
|
829
|
-
api: model.api,
|
|
830
|
-
provider: model.provider,
|
|
831
|
-
model: model.id,
|
|
832
|
-
usage: {
|
|
833
|
-
input: 0,
|
|
834
|
-
output: 0,
|
|
835
|
-
cacheRead: 0,
|
|
836
|
-
cacheWrite: 0,
|
|
837
|
-
totalTokens: 0,
|
|
838
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
839
|
-
},
|
|
840
|
-
timestamp: Date.now(),
|
|
841
|
-
};
|
|
842
|
-
let reader;
|
|
843
|
-
const abortHandler = () => {
|
|
844
|
-
if (reader) {
|
|
845
|
-
reader.cancel("Request aborted by user").catch(() => { });
|
|
846
|
-
}
|
|
847
|
-
};
|
|
848
|
-
if (options.signal) {
|
|
849
|
-
options.signal.addEventListener("abort", abortHandler);
|
|
850
|
-
}
|
|
851
|
-
try {
|
|
852
|
-
const response = await fetch(`${options.proxyUrl}/api/stream`, {
|
|
853
|
-
method: "POST",
|
|
854
|
-
headers: {
|
|
855
|
-
Authorization: `Bearer ${options.authToken}`,
|
|
856
|
-
"Content-Type": "application/json",
|
|
857
|
-
},
|
|
858
|
-
body: JSON.stringify({
|
|
859
|
-
model,
|
|
860
|
-
context,
|
|
861
|
-
options: {
|
|
862
|
-
temperature: options.temperature,
|
|
863
|
-
maxTokens: options.maxTokens,
|
|
864
|
-
reasoning: options.reasoning,
|
|
865
|
-
},
|
|
866
|
-
}),
|
|
867
|
-
signal: options.signal,
|
|
868
|
-
});
|
|
869
|
-
if (!response.ok) {
|
|
870
|
-
let errorMessage = `Proxy error: ${response.status} ${response.statusText}`;
|
|
871
|
-
try {
|
|
872
|
-
const errorData = (await response.json());
|
|
873
|
-
if (errorData.error) {
|
|
874
|
-
errorMessage = `Proxy error: ${errorData.error}`;
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
catch {
|
|
878
|
-
// Couldn't parse error response
|
|
879
|
-
}
|
|
880
|
-
throw new Error(errorMessage);
|
|
881
|
-
}
|
|
882
|
-
reader = response.body.getReader();
|
|
883
|
-
const decoder = new TextDecoder();
|
|
884
|
-
let buffer = "";
|
|
885
|
-
while (true) {
|
|
886
|
-
const { done, value } = await reader.read();
|
|
887
|
-
if (done)
|
|
888
|
-
break;
|
|
889
|
-
if (options.signal?.aborted) {
|
|
890
|
-
throw new Error("Request aborted by user");
|
|
891
|
-
}
|
|
892
|
-
buffer += decoder.decode(value, { stream: true });
|
|
893
|
-
const lines = buffer.split("\n");
|
|
894
|
-
buffer = lines.pop() || "";
|
|
895
|
-
for (const line of lines) {
|
|
896
|
-
if (line.startsWith("data: ")) {
|
|
897
|
-
const data = line.slice(6).trim();
|
|
898
|
-
if (data) {
|
|
899
|
-
const proxyEvent = JSON.parse(data);
|
|
900
|
-
const event = processProxyEvent(proxyEvent, partial);
|
|
901
|
-
if (event) {
|
|
902
|
-
stream.push(event);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
if (options.signal?.aborted) {
|
|
909
|
-
throw new Error("Request aborted by user");
|
|
910
|
-
}
|
|
911
|
-
stream.end();
|
|
912
|
-
}
|
|
913
|
-
catch (error) {
|
|
914
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
915
|
-
const reason = options.signal?.aborted ? "aborted" : "error";
|
|
916
|
-
partial.stopReason = reason;
|
|
917
|
-
partial.errorMessage = errorMessage;
|
|
918
|
-
stream.push({
|
|
919
|
-
type: "error",
|
|
920
|
-
reason,
|
|
921
|
-
error: partial,
|
|
922
|
-
});
|
|
923
|
-
stream.end();
|
|
924
|
-
}
|
|
925
|
-
finally {
|
|
926
|
-
if (options.signal) {
|
|
927
|
-
options.signal.removeEventListener("abort", abortHandler);
|
|
928
|
-
}
|
|
929
|
-
}
|
|
930
|
-
})();
|
|
931
|
-
return stream;
|
|
932
|
-
}
|
|
933
|
-
/**
|
|
934
|
-
* Process a proxy event and update the partial message.
|
|
935
|
-
*/
|
|
936
|
-
function processProxyEvent(proxyEvent, partial) {
|
|
937
|
-
switch (proxyEvent.type) {
|
|
938
|
-
case "start":
|
|
939
|
-
return { type: "start", partial };
|
|
940
|
-
case "text_start":
|
|
941
|
-
partial.content[proxyEvent.contentIndex] = { type: "text", text: "" };
|
|
942
|
-
return { type: "text_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
943
|
-
case "text_delta": {
|
|
944
|
-
const content = partial.content[proxyEvent.contentIndex];
|
|
945
|
-
if (content?.type === "text") {
|
|
946
|
-
content.text += proxyEvent.delta;
|
|
947
|
-
return {
|
|
948
|
-
type: "text_delta",
|
|
949
|
-
contentIndex: proxyEvent.contentIndex,
|
|
950
|
-
delta: proxyEvent.delta,
|
|
951
|
-
partial,
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
throw new Error("Received text_delta for non-text content");
|
|
955
|
-
}
|
|
956
|
-
case "text_end": {
|
|
957
|
-
const content = partial.content[proxyEvent.contentIndex];
|
|
958
|
-
if (content?.type === "text") {
|
|
959
|
-
content.textSignature = proxyEvent.contentSignature;
|
|
960
|
-
return {
|
|
961
|
-
type: "text_end",
|
|
962
|
-
contentIndex: proxyEvent.contentIndex,
|
|
963
|
-
content: content.text,
|
|
964
|
-
partial,
|
|
965
|
-
};
|
|
966
|
-
}
|
|
967
|
-
throw new Error("Received text_end for non-text content");
|
|
968
|
-
}
|
|
969
|
-
case "thinking_start":
|
|
970
|
-
partial.content[proxyEvent.contentIndex] = { type: "thinking", thinking: "" };
|
|
971
|
-
return { type: "thinking_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
972
|
-
case "thinking_delta": {
|
|
973
|
-
const content = partial.content[proxyEvent.contentIndex];
|
|
974
|
-
if (content?.type === "thinking") {
|
|
975
|
-
content.thinking += proxyEvent.delta;
|
|
976
|
-
return {
|
|
977
|
-
type: "thinking_delta",
|
|
978
|
-
contentIndex: proxyEvent.contentIndex,
|
|
979
|
-
delta: proxyEvent.delta,
|
|
980
|
-
partial,
|
|
981
|
-
};
|
|
982
|
-
}
|
|
983
|
-
throw new Error("Received thinking_delta for non-thinking content");
|
|
984
|
-
}
|
|
985
|
-
case "thinking_end": {
|
|
986
|
-
const content = partial.content[proxyEvent.contentIndex];
|
|
987
|
-
if (content?.type === "thinking") {
|
|
988
|
-
content.thinkingSignature = proxyEvent.contentSignature;
|
|
989
|
-
return {
|
|
990
|
-
type: "thinking_end",
|
|
991
|
-
contentIndex: proxyEvent.contentIndex,
|
|
992
|
-
content: content.thinking,
|
|
993
|
-
partial,
|
|
994
|
-
};
|
|
995
|
-
}
|
|
996
|
-
throw new Error("Received thinking_end for non-thinking content");
|
|
997
|
-
}
|
|
998
|
-
case "toolcall_start":
|
|
999
|
-
partial.content[proxyEvent.contentIndex] = {
|
|
1000
|
-
type: "toolCall",
|
|
1001
|
-
id: proxyEvent.id,
|
|
1002
|
-
name: proxyEvent.toolName,
|
|
1003
|
-
arguments: {},
|
|
1004
|
-
partialJson: "",
|
|
1005
|
-
};
|
|
1006
|
-
return { type: "toolcall_start", contentIndex: proxyEvent.contentIndex, partial };
|
|
1007
|
-
case "toolcall_delta": {
|
|
1008
|
-
const content = partial.content[proxyEvent.contentIndex];
|
|
1009
|
-
if (content?.type === "toolCall") {
|
|
1010
|
-
content.partialJson += proxyEvent.delta;
|
|
1011
|
-
content.arguments = (0,dist.parseStreamingJson)(content.partialJson) || {};
|
|
1012
|
-
partial.content[proxyEvent.contentIndex] = { ...content }; // Trigger reactivity
|
|
1013
|
-
return {
|
|
1014
|
-
type: "toolcall_delta",
|
|
1015
|
-
contentIndex: proxyEvent.contentIndex,
|
|
1016
|
-
delta: proxyEvent.delta,
|
|
1017
|
-
partial,
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
throw new Error("Received toolcall_delta for non-toolCall content");
|
|
1021
|
-
}
|
|
1022
|
-
case "toolcall_end": {
|
|
1023
|
-
const content = partial.content[proxyEvent.contentIndex];
|
|
1024
|
-
if (content?.type === "toolCall") {
|
|
1025
|
-
delete content.partialJson;
|
|
1026
|
-
return {
|
|
1027
|
-
type: "toolcall_end",
|
|
1028
|
-
contentIndex: proxyEvent.contentIndex,
|
|
1029
|
-
toolCall: content,
|
|
1030
|
-
partial,
|
|
1031
|
-
};
|
|
1032
|
-
}
|
|
1033
|
-
return undefined;
|
|
1034
|
-
}
|
|
1035
|
-
case "done":
|
|
1036
|
-
partial.stopReason = proxyEvent.reason;
|
|
1037
|
-
partial.usage = proxyEvent.usage;
|
|
1038
|
-
return { type: "done", reason: proxyEvent.reason, message: partial };
|
|
1039
|
-
case "error":
|
|
1040
|
-
partial.stopReason = proxyEvent.reason;
|
|
1041
|
-
partial.errorMessage = proxyEvent.errorMessage;
|
|
1042
|
-
partial.usage = proxyEvent.usage;
|
|
1043
|
-
return { type: "error", reason: proxyEvent.reason, error: partial };
|
|
1044
|
-
default: {
|
|
1045
|
-
const _exhaustiveCheck = proxyEvent;
|
|
1046
|
-
console.warn(`Unhandled proxy event type: ${proxyEvent.type}`);
|
|
1047
|
-
return undefined;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
//# sourceMappingURL=proxy.js.map
|
|
1052
|
-
;// CONCATENATED MODULE: ./node_modules/@mariozechner/pi-agent-core/dist/index.js
|
|
1053
|
-
// Core Agent
|
|
1054
|
-
|
|
1055
|
-
// Loop functions
|
|
1056
|
-
|
|
1057
|
-
// Proxy utilities
|
|
1058
|
-
|
|
1059
|
-
// Types
|
|
1060
|
-
|
|
1061
|
-
//# sourceMappingURL=index.js.map
|
|
1062
|
-
|
|
1063
|
-
/***/ })
|
|
1064
|
-
|
|
1065
|
-
};
|
|
1066
|
-
;
|
|
1
|
+
exports.id=582,exports.ids=[582,174],exports.modules={84005:e=>{function t(e){try{return Promise.resolve(require(e))}catch(t){return Promise.resolve().then(()=>{var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t})}}t.keys=()=>[],t.resolve=t,t.id=84005,e.exports=t},70162:e=>{function t(e){try{return Promise.resolve(require(e))}catch(t){return Promise.resolve().then(()=>{var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t})}}t.keys=()=>[],t.resolve=t,t.id=70162,e.exports=t},65653:(e,t,s)=>{"use strict";s.r(t),s.d(t,{Agent:()=>p,agentLoop:()=>o,agentLoopContinue:()=>r,streamProxy:()=>d});var n=s(99641);function o(e,t,s,n,o){const r=a();return(async()=>{const a=[...e],l={...t,messages:[...t.messages,...e]};r.push({type:"agent_start"}),r.push({type:"turn_start"});for(const t of e)r.push({type:"message_start",message:t}),r.push({type:"message_end",message:t});await i(l,a,s,n,r,o)})(),r}function r(e,t,s,n){if(0===e.messages.length)throw new Error("Cannot continue: no messages in context");if("assistant"===e.messages[e.messages.length-1].role)throw new Error("Cannot continue from message role: assistant");const o=a();return(async()=>{const r={...e};o.push({type:"agent_start"}),o.push({type:"turn_start"}),await i(r,[],t,s,o,n)})(),o}function a(){return new n.EventStream(e=>"agent_end"===e.type,e=>"agent_end"===e.type?e.messages:[])}async function i(e,t,s,n,o,r){let a=!0,i=await(s.getSteeringMessages?.())||[];for(;;){let u=!0,c=null;for(;u||i.length>0;){if(a?a=!1:o.push({type:"turn_start"}),i.length>0){for(const s of i)o.push({type:"message_start",message:s}),o.push({type:"message_end",message:s}),e.messages.push(s),t.push(s);i=[]}const p=await l(e,s,n,o,r);if(t.push(p),"error"===p.stopReason||"aborted"===p.stopReason)return o.push({type:"turn_end",message:p,toolResults:[]}),o.push({type:"agent_end",messages:t}),void o.end(t);u=p.content.filter(e=>"toolCall"===e.type).length>0;const h=[];if(u){const r=await g(e.tools,p,n,o,s.getSteeringMessages);h.push(...r.toolResults),c=r.steeringMessages??null;for(const s of h)e.messages.push(s),t.push(s)}o.push({type:"turn_end",message:p,toolResults:h}),c&&c.length>0?(i=c,c=null):i=await(s.getSteeringMessages?.())||[]}const p=await(s.getFollowUpMessages?.())||[];if(!(p.length>0))break;i=p}o.push({type:"agent_end",messages:t}),o.end(t)}async function l(e,t,s,o,r){let a=e.messages;t.transformContext&&(a=await t.transformContext(a,s));const i=await t.convertToLlm(a),l={systemPrompt:e.systemPrompt,messages:i,tools:e.tools},g=r||n.streamSimple,u=(t.getApiKey?await t.getApiKey(t.model.provider):void 0)||t.apiKey,c=await g(t.model,l,{...t,apiKey:u,signal:s});let p=null,h=!1;for await(const t of c)switch(t.type){case"start":p=t.partial,e.messages.push(p),h=!0,o.push({type:"message_start",message:{...p}});break;case"text_start":case"text_delta":case"text_end":case"thinking_start":case"thinking_delta":case"thinking_end":case"toolcall_start":case"toolcall_delta":case"toolcall_end":p&&(p=t.partial,e.messages[e.messages.length-1]=p,o.push({type:"message_update",assistantMessageEvent:t,message:{...p}}));break;case"done":case"error":{const t=await c.result();return h?e.messages[e.messages.length-1]=t:e.messages.push(t),h||o.push({type:"message_start",message:{...t}}),o.push({type:"message_end",message:t}),t}}return await c.result()}async function g(e,t,s,o,r){const a=t.content.filter(e=>"toolCall"===e.type),i=[];let l;for(let t=0;t<a.length;t++){const g=a[t],c=e?.find(e=>e.name===g.name);let p;o.push({type:"tool_execution_start",toolCallId:g.id,toolName:g.name,args:g.arguments});let h=!1;try{if(!c)throw new Error(`Tool ${g.name} not found`);const e=(0,n.validateToolArguments)(c,g);p=await c.execute(g.id,e,s,e=>{o.push({type:"tool_execution_update",toolCallId:g.id,toolName:g.name,args:g.arguments,partialResult:e})})}catch(e){p={content:[{type:"text",text:e instanceof Error?e.message:String(e)}],details:{}},h=!0}o.push({type:"tool_execution_end",toolCallId:g.id,toolName:g.name,result:p,isError:h});const d={role:"toolResult",toolCallId:g.id,toolName:g.name,content:p.content,details:p.details,isError:h,timestamp:Date.now()};if(i.push(d),o.push({type:"message_start",message:d}),o.push({type:"message_end",message:d}),r){const e=await r();if(e.length>0){l=e;const s=a.slice(t+1);for(const e of s)i.push(u(e,o));break}}}return{toolResults:i,steeringMessages:l}}function u(e,t){const s={content:[{type:"text",text:"Skipped due to queued user message."}],details:{}};t.push({type:"tool_execution_start",toolCallId:e.id,toolName:e.name,args:e.arguments}),t.push({type:"tool_execution_end",toolCallId:e.id,toolName:e.name,result:s,isError:!0});const n={role:"toolResult",toolCallId:e.id,toolName:e.name,content:s.content,details:{},isError:!0,timestamp:Date.now()};return t.push({type:"message_start",message:n}),t.push({type:"message_end",message:n}),n}function c(e){return e.filter(e=>"user"===e.role||"assistant"===e.role||"toolResult"===e.role)}class p{_state={systemPrompt:"",model:(0,n.getModel)("google","gemini-2.5-flash-lite-preview-06-17"),thinkingLevel:"off",tools:[],messages:[],isStreaming:!1,streamMessage:null,pendingToolCalls:new Set,error:void 0};listeners=new Set;abortController;convertToLlm;transformContext;steeringQueue=[];followUpQueue=[];steeringMode;followUpMode;streamFn;_sessionId;getApiKey;_onPayload;runningPrompt;resolveRunningPrompt;_thinkingBudgets;_transport;_maxRetryDelayMs;constructor(e={}){this._state={...this._state,...e.initialState},this.convertToLlm=e.convertToLlm||c,this.transformContext=e.transformContext,this.steeringMode=e.steeringMode||"one-at-a-time",this.followUpMode=e.followUpMode||"one-at-a-time",this.streamFn=e.streamFn||n.streamSimple,this._sessionId=e.sessionId,this.getApiKey=e.getApiKey,this._onPayload=e.onPayload,this._thinkingBudgets=e.thinkingBudgets,this._transport=e.transport??"sse",this._maxRetryDelayMs=e.maxRetryDelayMs}get sessionId(){return this._sessionId}set sessionId(e){this._sessionId=e}get thinkingBudgets(){return this._thinkingBudgets}set thinkingBudgets(e){this._thinkingBudgets=e}get transport(){return this._transport}setTransport(e){this._transport=e}get maxRetryDelayMs(){return this._maxRetryDelayMs}set maxRetryDelayMs(e){this._maxRetryDelayMs=e}get state(){return this._state}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}setSystemPrompt(e){this._state.systemPrompt=e}setModel(e){this._state.model=e}setThinkingLevel(e){this._state.thinkingLevel=e}setSteeringMode(e){this.steeringMode=e}getSteeringMode(){return this.steeringMode}setFollowUpMode(e){this.followUpMode=e}getFollowUpMode(){return this.followUpMode}setTools(e){this._state.tools=e}replaceMessages(e){this._state.messages=e.slice()}appendMessage(e){this._state.messages=[...this._state.messages,e]}steer(e){this.steeringQueue.push(e)}followUp(e){this.followUpQueue.push(e)}clearSteeringQueue(){this.steeringQueue=[]}clearFollowUpQueue(){this.followUpQueue=[]}clearAllQueues(){this.steeringQueue=[],this.followUpQueue=[]}hasQueuedMessages(){return this.steeringQueue.length>0||this.followUpQueue.length>0}dequeueSteeringMessages(){if("one-at-a-time"===this.steeringMode){if(this.steeringQueue.length>0){const e=this.steeringQueue[0];return this.steeringQueue=this.steeringQueue.slice(1),[e]}return[]}const e=this.steeringQueue.slice();return this.steeringQueue=[],e}dequeueFollowUpMessages(){if("one-at-a-time"===this.followUpMode){if(this.followUpQueue.length>0){const e=this.followUpQueue[0];return this.followUpQueue=this.followUpQueue.slice(1),[e]}return[]}const e=this.followUpQueue.slice();return this.followUpQueue=[],e}clearMessages(){this._state.messages=[]}abort(){this.abortController?.abort()}waitForIdle(){return this.runningPrompt??Promise.resolve()}reset(){this._state.messages=[],this._state.isStreaming=!1,this._state.streamMessage=null,this._state.pendingToolCalls=new Set,this._state.error=void 0,this.steeringQueue=[],this.followUpQueue=[]}async prompt(e,t){if(this._state.isStreaming)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");if(!this._state.model)throw new Error("No model configured");let s;if(Array.isArray(e))s=e;else if("string"==typeof e){const n=[{type:"text",text:e}];t&&t.length>0&&n.push(...t),s=[{role:"user",content:n,timestamp:Date.now()}]}else s=[e];await this._runLoop(s)}async continue(){if(this._state.isStreaming)throw new Error("Agent is already processing. Wait for completion before continuing.");const e=this._state.messages;if(0===e.length)throw new Error("No messages to continue from");if("assistant"===e[e.length-1].role){const e=this.dequeueSteeringMessages();if(e.length>0)return void await this._runLoop(e,{skipInitialSteeringPoll:!0});const t=this.dequeueFollowUpMessages();if(t.length>0)return void await this._runLoop(t);throw new Error("Cannot continue from message role: assistant")}await this._runLoop(void 0)}async _runLoop(e,t){const s=this._state.model;if(!s)throw new Error("No model configured");this.runningPrompt=new Promise(e=>{this.resolveRunningPrompt=e}),this.abortController=new AbortController,this._state.isStreaming=!0,this._state.streamMessage=null,this._state.error=void 0;const n="off"===this._state.thinkingLevel?void 0:this._state.thinkingLevel,a={systemPrompt:this._state.systemPrompt,messages:this._state.messages.slice(),tools:this._state.tools};let i=!0===t?.skipInitialSteeringPoll;const l={model:s,reasoning:n,sessionId:this._sessionId,onPayload:this._onPayload,transport:this._transport,thinkingBudgets:this._thinkingBudgets,maxRetryDelayMs:this._maxRetryDelayMs,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>i?(i=!1,[]):this.dequeueSteeringMessages(),getFollowUpMessages:async()=>this.dequeueFollowUpMessages()};let g=null;try{const t=e?o(e,a,l,this.abortController.signal,this.streamFn):r(a,l,this.abortController.signal,this.streamFn);for await(const e of t){switch(e.type){case"message_start":case"message_update":g=e.message,this._state.streamMessage=e.message;break;case"message_end":g=null,this._state.streamMessage=null,this.appendMessage(e.message);break;case"tool_execution_start":{const t=new Set(this._state.pendingToolCalls);t.add(e.toolCallId),this._state.pendingToolCalls=t;break}case"tool_execution_end":{const t=new Set(this._state.pendingToolCalls);t.delete(e.toolCallId),this._state.pendingToolCalls=t;break}case"turn_end":"assistant"===e.message.role&&e.message.errorMessage&&(this._state.error=e.message.errorMessage);break;case"agent_end":this._state.isStreaming=!1,this._state.streamMessage=null}this.emit(e)}if(g&&"assistant"===g.role&&g.content.length>0){if(!g.content.some(e=>"thinking"===e.type&&e.thinking.trim().length>0||"text"===e.type&&e.text.trim().length>0||"toolCall"===e.type&&e.name.trim().length>0)){if(this.abortController?.signal.aborted)throw new Error("Request was aborted")}else this.appendMessage(g)}}catch(e){const t={role:"assistant",content:[{type:"text",text:""}],api:s.api,provider:s.provider,model:s.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:this.abortController?.signal.aborted?"aborted":"error",errorMessage:e?.message||String(e),timestamp:Date.now()};this.appendMessage(t),this._state.error=e?.message||String(e),this.emit({type:"agent_end",messages:[t]})}finally{this._state.isStreaming=!1,this._state.streamMessage=null,this._state.pendingToolCalls=new Set,this.abortController=void 0,this.resolveRunningPrompt?.(),this.runningPrompt=void 0,this.resolveRunningPrompt=void 0}}emit(e){for(const t of this.listeners)t(e)}}class h extends n.EventStream{constructor(){super(e=>"done"===e.type||"error"===e.type,e=>{if("done"===e.type)return e.message;if("error"===e.type)return e.error;throw new Error("Unexpected event type")})}}function d(e,t,s){const n=new h;return(async()=>{const o={role:"assistant",stopReason:"stop",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},timestamp:Date.now()};let r;const a=()=>{r&&r.cancel("Request aborted by user").catch(()=>{})};s.signal&&s.signal.addEventListener("abort",a);try{const a=await fetch(`${s.proxyUrl}/api/stream`,{method:"POST",headers:{Authorization:`Bearer ${s.authToken}`,"Content-Type":"application/json"},body:JSON.stringify({model:e,context:t,options:{temperature:s.temperature,maxTokens:s.maxTokens,reasoning:s.reasoning}}),signal:s.signal});if(!a.ok){let e=`Proxy error: ${a.status} ${a.statusText}`;try{const t=await a.json();t.error&&(e=`Proxy error: ${t.error}`)}catch{}throw new Error(e)}r=a.body.getReader();const i=new TextDecoder;let l="";for(;;){const{done:e,value:t}=await r.read();if(e)break;if(s.signal?.aborted)throw new Error("Request aborted by user");l+=i.decode(t,{stream:!0});const a=l.split("\n");l=a.pop()||"";for(const e of a)if(e.startsWith("data: ")){const t=e.slice(6).trim();if(t){const e=m(JSON.parse(t),o);e&&n.push(e)}}}if(s.signal?.aborted)throw new Error("Request aborted by user");n.end()}catch(e){const t=e instanceof Error?e.message:String(e),r=s.signal?.aborted?"aborted":"error";o.stopReason=r,o.errorMessage=t,n.push({type:"error",reason:r,error:o}),n.end()}finally{s.signal&&s.signal.removeEventListener("abort",a)}})(),n}function m(e,t){switch(e.type){case"start":return{type:"start",partial:t};case"text_start":return t.content[e.contentIndex]={type:"text",text:""},{type:"text_start",contentIndex:e.contentIndex,partial:t};case"text_delta":{const s=t.content[e.contentIndex];if("text"===s?.type)return s.text+=e.delta,{type:"text_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received text_delta for non-text content")}case"text_end":{const s=t.content[e.contentIndex];if("text"===s?.type)return s.textSignature=e.contentSignature,{type:"text_end",contentIndex:e.contentIndex,content:s.text,partial:t};throw new Error("Received text_end for non-text content")}case"thinking_start":return t.content[e.contentIndex]={type:"thinking",thinking:""},{type:"thinking_start",contentIndex:e.contentIndex,partial:t};case"thinking_delta":{const s=t.content[e.contentIndex];if("thinking"===s?.type)return s.thinking+=e.delta,{type:"thinking_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received thinking_delta for non-thinking content")}case"thinking_end":{const s=t.content[e.contentIndex];if("thinking"===s?.type)return s.thinkingSignature=e.contentSignature,{type:"thinking_end",contentIndex:e.contentIndex,content:s.thinking,partial:t};throw new Error("Received thinking_end for non-thinking content")}case"toolcall_start":return t.content[e.contentIndex]={type:"toolCall",id:e.id,name:e.toolName,arguments:{},partialJson:""},{type:"toolcall_start",contentIndex:e.contentIndex,partial:t};case"toolcall_delta":{const s=t.content[e.contentIndex];if("toolCall"===s?.type)return s.partialJson+=e.delta,s.arguments=(0,n.parseStreamingJson)(s.partialJson)||{},t.content[e.contentIndex]={...s},{type:"toolcall_delta",contentIndex:e.contentIndex,delta:e.delta,partial:t};throw new Error("Received toolcall_delta for non-toolCall content")}case"toolcall_end":{const s=t.content[e.contentIndex];return"toolCall"===s?.type?(delete s.partialJson,{type:"toolcall_end",contentIndex:e.contentIndex,toolCall:s,partial:t}):void 0}case"done":return t.stopReason=e.reason,t.usage=e.usage,{type:"done",reason:e.reason,message:t};case"error":return t.stopReason=e.reason,t.errorMessage=e.errorMessage,t.usage=e.usage,{type:"error",reason:e.reason,error:t};default:return void console.warn(`Unhandled proxy event type: ${e.type}`)}}}};
|