@tonyclaw/agent-inspector 4.0.7 → 4.0.9
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/.output/backend/nitro.json +1 -1
- package/.output/cli.js +915 -25970
- package/.output/server/_chunks/ssr-renderer.mjs +1 -38
- package/.output/server/_libs/@opentelemetry/semantic-conventions+[...].mjs +1 -2658
- package/.output/server/_libs/agent-base.mjs +2 -234
- package/.output/server/_libs/ajv-formats.mjs +1 -330
- package/.output/server/_libs/ajv.mjs +8 -6080
- package/.output/server/_libs/anthropic-ai__sdk.mjs +19 -6021
- package/.output/server/_libs/atomically.mjs +1 -155
- package/.output/server/_libs/base64-js.mjs +1 -102
- package/.output/server/_libs/bignumber.js.mjs +1 -1353
- package/.output/server/_libs/buffer-equal-constant-time.mjs +1 -38
- package/.output/server/_libs/conf.mjs +1 -635
- package/.output/server/_libs/cookie-es.mjs +1 -44
- package/.output/server/_libs/core-util-is.mjs +1 -75
- package/.output/server/_libs/data-uri-to-buffer.mjs +1 -39
- package/.output/server/_libs/debounce-fn.mjs +1 -69
- package/.output/server/_libs/debug.mjs +5 -547
- package/.output/server/_libs/dot-prop.mjs +1 -265
- package/.output/server/_libs/ecdsa-sig-formatter.mjs +1 -162
- package/.output/server/_libs/env-paths.mjs +1 -57
- package/.output/server/_libs/extend.mjs +1 -94
- package/.output/server/_libs/fast-deep-equal.mjs +1 -38
- package/.output/server/_libs/fast-uri.mjs +1 -812
- package/.output/server/_libs/fetch-blob.mjs +1 -287
- package/.output/server/_libs/formdata-polyfill.mjs +9 -86
- package/.output/server/_libs/gaxios.mjs +5 -926
- package/.output/server/_libs/gcp-metadata.mjs +1 -322
- package/.output/server/_libs/google-auth-library.mjs +16 -6339
- package/.output/server/_libs/google-logging-utils.mjs +1 -385
- package/.output/server/_libs/google__genai.mjs +13 -18034
- package/.output/server/_libs/h3-v2.mjs +2 -287
- package/.output/server/_libs/h3.mjs +2 -408
- package/.output/server/_libs/has-flag.mjs +1 -16
- package/.output/server/_libs/https-proxy-agent.mjs +7 -280
- package/.output/server/_libs/immediate.mjs +1 -74
- package/.output/server/_libs/inherits.mjs +1 -50
- package/.output/server/_libs/isarray.mjs +1 -14
- package/.output/server/_libs/isbot.mjs +1 -20
- package/.output/server/_libs/json-bigint.mjs +8 -413
- package/.output/server/_libs/json-schema-traverse.mjs +1 -91
- package/.output/server/_libs/jszip.mjs +2 -3051
- package/.output/server/_libs/jwa.mjs +3 -233
- package/.output/server/_libs/jws.mjs +1 -298
- package/.output/server/_libs/lie.mjs +1 -273
- package/.output/server/_libs/mariozechner__pi-agent-core.mjs +1 -824
- package/.output/server/_libs/mariozechner__pi-ai.mjs +34 -22887
- package/.output/server/_libs/mimic-function.mjs +2 -47
- package/.output/server/_libs/mistralai__mistralai.mjs +7 -32045
- package/.output/server/_libs/modelcontextprotocol__core.mjs +1 -1121
- package/.output/server/_libs/modelcontextprotocol__server.mjs +13 -13205
- package/.output/server/_libs/ms.mjs +1 -120
- package/.output/server/_libs/node-domexception.mjs +1 -17
- package/.output/server/_libs/node-fetch.mjs +4 -1578
- package/.output/server/_libs/ohash.mjs +1 -1
- package/.output/server/_libs/openai.mjs +23 -6766
- package/.output/server/_libs/opentelemetry__api.mjs +1 -1678
- package/.output/server/_libs/p-retry.mjs +1 -87
- package/.output/server/_libs/pako.mjs +1 -4223
- package/.output/server/_libs/partial-json.mjs +2 -244
- package/.output/server/_libs/process-nextick-args.mjs +1 -48
- package/.output/server/_libs/react-dom.mjs +62 -10778
- package/.output/server/_libs/react.mjs +1 -519
- package/.output/server/_libs/readable-stream.mjs +1 -1518
- package/.output/server/_libs/retry.mjs +1 -236
- package/.output/server/_libs/rou3.mjs +1 -14
- package/.output/server/_libs/safe-buffer.mjs +1 -126
- package/.output/server/_libs/semver.mjs +1 -1938
- package/.output/server/_libs/seroval-plugins.mjs +1 -58
- package/.output/server/_libs/seroval.mjs +3 -1775
- package/.output/server/_libs/setimmediate.mjs +1 -152
- package/.output/server/_libs/srvx.mjs +4 -1390
- package/.output/server/_libs/stubborn-fs.mjs +1 -91
- package/.output/server/_libs/stubborn-utils.mjs +1 -66
- package/.output/server/_libs/supports-color.mjs +1 -108
- package/.output/server/_libs/tanstack__history.mjs +1 -230
- package/.output/server/_libs/tanstack__react-router.mjs +1 -848
- package/.output/server/_libs/tanstack__react-store.mjs +1 -1
- package/.output/server/_libs/tanstack__router-core.mjs +1 -4839
- package/.output/server/_libs/typebox.mjs +3 -6596
- package/.output/server/_libs/ufo.mjs +1 -54
- package/.output/server/_libs/uint8array-extras.mjs +1 -69
- package/.output/server/_libs/util-deprecate.mjs +1 -12
- package/.output/server/_libs/web-streams-polyfill.mjs +1 -4282
- package/.output/server/_libs/when-exit.mjs +1 -53
- package/.output/server/_libs/ws.mjs +7 -3715
- package/.output/server/_libs/zod-to-json-schema.mjs +5 -1207
- package/.output/server/_libs/zod.mjs +59 -9958
- package/.output/server/_ssr/empty-plugin-adapters-C3Q1xu4u.mjs +1 -0
- package/.output/server/_ssr/index.mjs +2 -1512
- package/.output/server/_ssr/publicBasePathContext--TAQS2_5.mjs +1 -0
- package/.output/server/_ssr/router-zSWaME0l.mjs +341 -0
- package/.output/server/_ssr/start-PDVGOqUN.mjs +1 -0
- package/.output/server/_tanstack-start-manifest_v-D7cKwKzM.mjs +1 -0
- package/.output/server/index.mjs +1 -320
- package/.output/ui/assets/{CompareDrawer-fWsmegqc.js → CompareDrawer-C6KvvPtJ.js} +1 -1
- package/.output/ui/assets/{InspectorPet-Z9XIA0t8.js → InspectorPet-CSH6OAhB.js} +1 -1
- package/.output/ui/assets/{ProxyViewerContainer-DhIB_ZAU.js → ProxyViewerContainer-vPd7g0Xn.js} +4 -4
- package/.output/ui/assets/{ReplayDialog-w_3PENIi.js → ReplayDialog-DbXUcT39.js} +1 -1
- package/.output/ui/assets/{RequestAnatomy-Dix0D4G6.js → RequestAnatomy-BWOCIN7J.js} +1 -1
- package/.output/ui/assets/{ResponseView-BtlbxW2o.js → ResponseView-BqDbTzFs.js} +1 -1
- package/.output/ui/assets/{StreamingChunkSequence-BqNQJASb.js → StreamingChunkSequence-UHl2g6w6.js} +1 -1
- package/.output/ui/assets/{_sessionId-DPiw4uu2.js → _sessionId-B2S61lDJ.js} +1 -1
- package/.output/ui/assets/{_sessionId-Bo9J8C5J.js → _sessionId-CS6hqj8-.js} +1 -1
- package/.output/ui/assets/{index-BL5id77_.js → index-C6V66rNI.js} +1 -1
- package/.output/ui/assets/{index-icwV1YtX.js → index-DY5xBYHr.js} +1 -1
- package/.output/ui/assets/{index-Wd6TK76x.js → index-DgyIeqyV.js} +2 -2
- package/.output/ui/assets/{index-CWSVfojK.js → index-HLs5jTyi.js} +1 -1
- package/.output/ui/assets/{json-viewer-Cpr3uw1I.js → json-viewer-i5LcN8e7.js} +1 -1
- package/.output/ui/assets/{jszip.min-Cncg6JOi.js → jszip.min-yNpb9qnf.js} +1 -1
- package/.output/ui/index.html +1 -1
- package/.output/workers/logFinalizer.worker.js +41 -17739
- package/.output/workers/sessionWorkerEntry.js +41 -17735
- package/package.json +7 -7
- package/.output/server/_ssr/empty-plugin-adapters-BFgPZ6_d.mjs +0 -6
- package/.output/server/_ssr/publicBasePathContext-IH2ilOfu.mjs +0 -176
- package/.output/server/_ssr/router-weYHAqCb.mjs +0 -27177
- package/.output/server/_ssr/start-COQu_AgD.mjs +0 -57
- package/.output/server/_tanstack-start-manifest_v-ClTaMkEj.mjs +0 -4
|
@@ -1,824 +1 @@
|
|
|
1
|
-
import "./typebox.mjs";
|
|
2
|
-
import { s as streamSimple, v as validateToolArguments } from "./mariozechner__pi-ai.mjs";
|
|
3
|
-
import "./partial-json.mjs";
|
|
4
|
-
import "./anthropic-ai__sdk.mjs";
|
|
5
|
-
import "./openai.mjs";
|
|
6
|
-
import "./google__genai.mjs";
|
|
7
|
-
import "./p-retry.mjs";
|
|
8
|
-
import "./react.mjs";
|
|
9
|
-
import "./retry.mjs";
|
|
10
|
-
import "./google-auth-library.mjs";
|
|
11
|
-
import "child_process";
|
|
12
|
-
import "path";
|
|
13
|
-
import "querystring";
|
|
14
|
-
import "fs";
|
|
15
|
-
import "./gaxios.mjs";
|
|
16
|
-
import "https";
|
|
17
|
-
import "./extend.mjs";
|
|
18
|
-
import "stream";
|
|
19
|
-
import "./gcp-metadata.mjs";
|
|
20
|
-
import "os";
|
|
21
|
-
import "./json-bigint.mjs";
|
|
22
|
-
import "./bignumber.js.mjs";
|
|
23
|
-
import "./google-logging-utils.mjs";
|
|
24
|
-
import "process";
|
|
25
|
-
import "events";
|
|
26
|
-
import "util";
|
|
27
|
-
import "./base64-js.mjs";
|
|
28
|
-
import "crypto";
|
|
29
|
-
import "./ecdsa-sig-formatter.mjs";
|
|
30
|
-
import "./safe-buffer.mjs";
|
|
31
|
-
import "buffer";
|
|
32
|
-
import "./jws.mjs";
|
|
33
|
-
import "./jwa.mjs";
|
|
34
|
-
import "./buffer-equal-constant-time.mjs";
|
|
35
|
-
import "fs/promises";
|
|
36
|
-
import "node:stream";
|
|
37
|
-
import "node:stream/promises";
|
|
38
|
-
import "./ws.mjs";
|
|
39
|
-
import "http";
|
|
40
|
-
import "net";
|
|
41
|
-
import "tls";
|
|
42
|
-
import "url";
|
|
43
|
-
import "zlib";
|
|
44
|
-
import "./mistralai__mistralai.mjs";
|
|
45
|
-
import "./zod.mjs";
|
|
46
|
-
import "./zod-to-json-schema.mjs";
|
|
47
|
-
import "./opentelemetry__api.mjs";
|
|
48
|
-
import "./@opentelemetry/semantic-conventions+[...].mjs";
|
|
49
|
-
async function runAgentLoop(prompts, context, config, emit, signal, streamFn) {
|
|
50
|
-
const newMessages = [...prompts];
|
|
51
|
-
const currentContext = {
|
|
52
|
-
...context,
|
|
53
|
-
messages: [...context.messages, ...prompts]
|
|
54
|
-
};
|
|
55
|
-
await emit({ type: "agent_start" });
|
|
56
|
-
await emit({ type: "turn_start" });
|
|
57
|
-
for (const prompt of prompts) {
|
|
58
|
-
await emit({ type: "message_start", message: prompt });
|
|
59
|
-
await emit({ type: "message_end", message: prompt });
|
|
60
|
-
}
|
|
61
|
-
await runLoop(currentContext, newMessages, config, signal, emit, streamFn);
|
|
62
|
-
return newMessages;
|
|
63
|
-
}
|
|
64
|
-
async function runAgentLoopContinue(context, config, emit, signal, streamFn) {
|
|
65
|
-
if (context.messages.length === 0) {
|
|
66
|
-
throw new Error("Cannot continue: no messages in context");
|
|
67
|
-
}
|
|
68
|
-
if (context.messages[context.messages.length - 1].role === "assistant") {
|
|
69
|
-
throw new Error("Cannot continue from message role: assistant");
|
|
70
|
-
}
|
|
71
|
-
const newMessages = [];
|
|
72
|
-
const currentContext = { ...context };
|
|
73
|
-
await emit({ type: "agent_start" });
|
|
74
|
-
await emit({ type: "turn_start" });
|
|
75
|
-
await runLoop(currentContext, newMessages, config, signal, emit, streamFn);
|
|
76
|
-
return newMessages;
|
|
77
|
-
}
|
|
78
|
-
async function runLoop(currentContext, newMessages, config, signal, emit, streamFn) {
|
|
79
|
-
let firstTurn = true;
|
|
80
|
-
let pendingMessages = await config.getSteeringMessages?.() || [];
|
|
81
|
-
while (true) {
|
|
82
|
-
let hasMoreToolCalls = true;
|
|
83
|
-
while (hasMoreToolCalls || pendingMessages.length > 0) {
|
|
84
|
-
if (!firstTurn) {
|
|
85
|
-
await emit({ type: "turn_start" });
|
|
86
|
-
} else {
|
|
87
|
-
firstTurn = false;
|
|
88
|
-
}
|
|
89
|
-
if (pendingMessages.length > 0) {
|
|
90
|
-
for (const message2 of pendingMessages) {
|
|
91
|
-
await emit({ type: "message_start", message: message2 });
|
|
92
|
-
await emit({ type: "message_end", message: message2 });
|
|
93
|
-
currentContext.messages.push(message2);
|
|
94
|
-
newMessages.push(message2);
|
|
95
|
-
}
|
|
96
|
-
pendingMessages = [];
|
|
97
|
-
}
|
|
98
|
-
const message = await streamAssistantResponse(currentContext, config, signal, emit, streamFn);
|
|
99
|
-
newMessages.push(message);
|
|
100
|
-
if (message.stopReason === "error" || message.stopReason === "aborted") {
|
|
101
|
-
await emit({ type: "turn_end", message, toolResults: [] });
|
|
102
|
-
await emit({ type: "agent_end", messages: newMessages });
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const toolCalls = message.content.filter((c) => c.type === "toolCall");
|
|
106
|
-
const toolResults = [];
|
|
107
|
-
hasMoreToolCalls = false;
|
|
108
|
-
if (toolCalls.length > 0) {
|
|
109
|
-
const executedToolBatch = await executeToolCalls(currentContext, message, config, signal, emit);
|
|
110
|
-
toolResults.push(...executedToolBatch.messages);
|
|
111
|
-
hasMoreToolCalls = !executedToolBatch.terminate;
|
|
112
|
-
for (const result of toolResults) {
|
|
113
|
-
currentContext.messages.push(result);
|
|
114
|
-
newMessages.push(result);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
await emit({ type: "turn_end", message, toolResults });
|
|
118
|
-
if (await config.shouldStopAfterTurn?.({
|
|
119
|
-
message,
|
|
120
|
-
toolResults,
|
|
121
|
-
context: currentContext,
|
|
122
|
-
newMessages
|
|
123
|
-
})) {
|
|
124
|
-
await emit({ type: "agent_end", messages: newMessages });
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
pendingMessages = await config.getSteeringMessages?.() || [];
|
|
128
|
-
}
|
|
129
|
-
const followUpMessages = await config.getFollowUpMessages?.() || [];
|
|
130
|
-
if (followUpMessages.length > 0) {
|
|
131
|
-
pendingMessages = followUpMessages;
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
await emit({ type: "agent_end", messages: newMessages });
|
|
137
|
-
}
|
|
138
|
-
async function streamAssistantResponse(context, config, signal, emit, streamFn) {
|
|
139
|
-
let messages = context.messages;
|
|
140
|
-
if (config.transformContext) {
|
|
141
|
-
messages = await config.transformContext(messages, signal);
|
|
142
|
-
}
|
|
143
|
-
const llmMessages = await config.convertToLlm(messages);
|
|
144
|
-
const llmContext = {
|
|
145
|
-
systemPrompt: context.systemPrompt,
|
|
146
|
-
messages: llmMessages,
|
|
147
|
-
tools: context.tools
|
|
148
|
-
};
|
|
149
|
-
const streamFunction = streamFn || streamSimple;
|
|
150
|
-
const resolvedApiKey = (config.getApiKey ? await config.getApiKey(config.model.provider) : void 0) || config.apiKey;
|
|
151
|
-
const response = await streamFunction(config.model, llmContext, {
|
|
152
|
-
...config,
|
|
153
|
-
apiKey: resolvedApiKey,
|
|
154
|
-
signal
|
|
155
|
-
});
|
|
156
|
-
let partialMessage = null;
|
|
157
|
-
let addedPartial = false;
|
|
158
|
-
for await (const event of response) {
|
|
159
|
-
switch (event.type) {
|
|
160
|
-
case "start":
|
|
161
|
-
partialMessage = event.partial;
|
|
162
|
-
context.messages.push(partialMessage);
|
|
163
|
-
addedPartial = true;
|
|
164
|
-
await emit({ type: "message_start", message: { ...partialMessage } });
|
|
165
|
-
break;
|
|
166
|
-
case "text_start":
|
|
167
|
-
case "text_delta":
|
|
168
|
-
case "text_end":
|
|
169
|
-
case "thinking_start":
|
|
170
|
-
case "thinking_delta":
|
|
171
|
-
case "thinking_end":
|
|
172
|
-
case "toolcall_start":
|
|
173
|
-
case "toolcall_delta":
|
|
174
|
-
case "toolcall_end":
|
|
175
|
-
if (partialMessage) {
|
|
176
|
-
partialMessage = event.partial;
|
|
177
|
-
context.messages[context.messages.length - 1] = partialMessage;
|
|
178
|
-
await emit({
|
|
179
|
-
type: "message_update",
|
|
180
|
-
assistantMessageEvent: event,
|
|
181
|
-
message: { ...partialMessage }
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
break;
|
|
185
|
-
case "done":
|
|
186
|
-
case "error": {
|
|
187
|
-
const finalMessage2 = await response.result();
|
|
188
|
-
if (addedPartial) {
|
|
189
|
-
context.messages[context.messages.length - 1] = finalMessage2;
|
|
190
|
-
} else {
|
|
191
|
-
context.messages.push(finalMessage2);
|
|
192
|
-
}
|
|
193
|
-
if (!addedPartial) {
|
|
194
|
-
await emit({ type: "message_start", message: { ...finalMessage2 } });
|
|
195
|
-
}
|
|
196
|
-
await emit({ type: "message_end", message: finalMessage2 });
|
|
197
|
-
return finalMessage2;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
const finalMessage = await response.result();
|
|
202
|
-
if (addedPartial) {
|
|
203
|
-
context.messages[context.messages.length - 1] = finalMessage;
|
|
204
|
-
} else {
|
|
205
|
-
context.messages.push(finalMessage);
|
|
206
|
-
await emit({ type: "message_start", message: { ...finalMessage } });
|
|
207
|
-
}
|
|
208
|
-
await emit({ type: "message_end", message: finalMessage });
|
|
209
|
-
return finalMessage;
|
|
210
|
-
}
|
|
211
|
-
async function executeToolCalls(currentContext, assistantMessage, config, signal, emit) {
|
|
212
|
-
const toolCalls = assistantMessage.content.filter((c) => c.type === "toolCall");
|
|
213
|
-
const hasSequentialToolCall = toolCalls.some((tc) => currentContext.tools?.find((t) => t.name === tc.name)?.executionMode === "sequential");
|
|
214
|
-
if (config.toolExecution === "sequential" || hasSequentialToolCall) {
|
|
215
|
-
return executeToolCallsSequential(currentContext, assistantMessage, toolCalls, config, signal, emit);
|
|
216
|
-
}
|
|
217
|
-
return executeToolCallsParallel(currentContext, assistantMessage, toolCalls, config, signal, emit);
|
|
218
|
-
}
|
|
219
|
-
async function executeToolCallsSequential(currentContext, assistantMessage, toolCalls, config, signal, emit) {
|
|
220
|
-
const finalizedCalls = [];
|
|
221
|
-
const messages = [];
|
|
222
|
-
for (const toolCall of toolCalls) {
|
|
223
|
-
await emit({
|
|
224
|
-
type: "tool_execution_start",
|
|
225
|
-
toolCallId: toolCall.id,
|
|
226
|
-
toolName: toolCall.name,
|
|
227
|
-
args: toolCall.arguments
|
|
228
|
-
});
|
|
229
|
-
const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
|
|
230
|
-
let finalized;
|
|
231
|
-
if (preparation.kind === "immediate") {
|
|
232
|
-
finalized = {
|
|
233
|
-
toolCall,
|
|
234
|
-
result: preparation.result,
|
|
235
|
-
isError: preparation.isError
|
|
236
|
-
};
|
|
237
|
-
} else {
|
|
238
|
-
const executed = await executePreparedToolCall(preparation, signal, emit);
|
|
239
|
-
finalized = await finalizeExecutedToolCall(currentContext, assistantMessage, preparation, executed, config, signal);
|
|
240
|
-
}
|
|
241
|
-
await emitToolExecutionEnd(finalized, emit);
|
|
242
|
-
const toolResultMessage = createToolResultMessage(finalized);
|
|
243
|
-
await emitToolResultMessage(toolResultMessage, emit);
|
|
244
|
-
finalizedCalls.push(finalized);
|
|
245
|
-
messages.push(toolResultMessage);
|
|
246
|
-
}
|
|
247
|
-
return {
|
|
248
|
-
messages,
|
|
249
|
-
terminate: shouldTerminateToolBatch(finalizedCalls)
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
async function executeToolCallsParallel(currentContext, assistantMessage, toolCalls, config, signal, emit) {
|
|
253
|
-
const finalizedCalls = [];
|
|
254
|
-
for (const toolCall of toolCalls) {
|
|
255
|
-
await emit({
|
|
256
|
-
type: "tool_execution_start",
|
|
257
|
-
toolCallId: toolCall.id,
|
|
258
|
-
toolName: toolCall.name,
|
|
259
|
-
args: toolCall.arguments
|
|
260
|
-
});
|
|
261
|
-
const preparation = await prepareToolCall(currentContext, assistantMessage, toolCall, config, signal);
|
|
262
|
-
if (preparation.kind === "immediate") {
|
|
263
|
-
const finalized = {
|
|
264
|
-
toolCall,
|
|
265
|
-
result: preparation.result,
|
|
266
|
-
isError: preparation.isError
|
|
267
|
-
};
|
|
268
|
-
await emitToolExecutionEnd(finalized, emit);
|
|
269
|
-
finalizedCalls.push(finalized);
|
|
270
|
-
continue;
|
|
271
|
-
}
|
|
272
|
-
finalizedCalls.push(async () => {
|
|
273
|
-
const executed = await executePreparedToolCall(preparation, signal, emit);
|
|
274
|
-
const finalized = await finalizeExecutedToolCall(currentContext, assistantMessage, preparation, executed, config, signal);
|
|
275
|
-
await emitToolExecutionEnd(finalized, emit);
|
|
276
|
-
return finalized;
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
const orderedFinalizedCalls = await Promise.all(finalizedCalls.map((entry) => typeof entry === "function" ? entry() : Promise.resolve(entry)));
|
|
280
|
-
const messages = [];
|
|
281
|
-
for (const finalized of orderedFinalizedCalls) {
|
|
282
|
-
const toolResultMessage = createToolResultMessage(finalized);
|
|
283
|
-
await emitToolResultMessage(toolResultMessage, emit);
|
|
284
|
-
messages.push(toolResultMessage);
|
|
285
|
-
}
|
|
286
|
-
return {
|
|
287
|
-
messages,
|
|
288
|
-
terminate: shouldTerminateToolBatch(orderedFinalizedCalls)
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
function shouldTerminateToolBatch(finalizedCalls) {
|
|
292
|
-
return finalizedCalls.length > 0 && finalizedCalls.every((finalized) => finalized.result.terminate === true);
|
|
293
|
-
}
|
|
294
|
-
function prepareToolCallArguments(tool, toolCall) {
|
|
295
|
-
if (!tool.prepareArguments) {
|
|
296
|
-
return toolCall;
|
|
297
|
-
}
|
|
298
|
-
const preparedArguments = tool.prepareArguments(toolCall.arguments);
|
|
299
|
-
if (preparedArguments === toolCall.arguments) {
|
|
300
|
-
return toolCall;
|
|
301
|
-
}
|
|
302
|
-
return {
|
|
303
|
-
...toolCall,
|
|
304
|
-
arguments: preparedArguments
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
async function prepareToolCall(currentContext, assistantMessage, toolCall, config, signal) {
|
|
308
|
-
const tool = currentContext.tools?.find((t) => t.name === toolCall.name);
|
|
309
|
-
if (!tool) {
|
|
310
|
-
return {
|
|
311
|
-
kind: "immediate",
|
|
312
|
-
result: createErrorToolResult(`Tool ${toolCall.name} not found`),
|
|
313
|
-
isError: true
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
try {
|
|
317
|
-
const preparedToolCall = prepareToolCallArguments(tool, toolCall);
|
|
318
|
-
const validatedArgs = validateToolArguments(tool, preparedToolCall);
|
|
319
|
-
if (config.beforeToolCall) {
|
|
320
|
-
const beforeResult = await config.beforeToolCall({
|
|
321
|
-
assistantMessage,
|
|
322
|
-
toolCall,
|
|
323
|
-
args: validatedArgs,
|
|
324
|
-
context: currentContext
|
|
325
|
-
}, signal);
|
|
326
|
-
if (beforeResult?.block) {
|
|
327
|
-
return {
|
|
328
|
-
kind: "immediate",
|
|
329
|
-
result: createErrorToolResult(beforeResult.reason || "Tool execution was blocked"),
|
|
330
|
-
isError: true
|
|
331
|
-
};
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
return {
|
|
335
|
-
kind: "prepared",
|
|
336
|
-
toolCall,
|
|
337
|
-
tool,
|
|
338
|
-
args: validatedArgs
|
|
339
|
-
};
|
|
340
|
-
} catch (error) {
|
|
341
|
-
return {
|
|
342
|
-
kind: "immediate",
|
|
343
|
-
result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
|
|
344
|
-
isError: true
|
|
345
|
-
};
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
async function executePreparedToolCall(prepared, signal, emit) {
|
|
349
|
-
const updateEvents = [];
|
|
350
|
-
try {
|
|
351
|
-
const result = await prepared.tool.execute(prepared.toolCall.id, prepared.args, signal, (partialResult) => {
|
|
352
|
-
updateEvents.push(Promise.resolve(emit({
|
|
353
|
-
type: "tool_execution_update",
|
|
354
|
-
toolCallId: prepared.toolCall.id,
|
|
355
|
-
toolName: prepared.toolCall.name,
|
|
356
|
-
args: prepared.toolCall.arguments,
|
|
357
|
-
partialResult
|
|
358
|
-
})));
|
|
359
|
-
});
|
|
360
|
-
await Promise.all(updateEvents);
|
|
361
|
-
return { result, isError: false };
|
|
362
|
-
} catch (error) {
|
|
363
|
-
await Promise.all(updateEvents);
|
|
364
|
-
return {
|
|
365
|
-
result: createErrorToolResult(error instanceof Error ? error.message : String(error)),
|
|
366
|
-
isError: true
|
|
367
|
-
};
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
async function finalizeExecutedToolCall(currentContext, assistantMessage, prepared, executed, config, signal) {
|
|
371
|
-
let result = executed.result;
|
|
372
|
-
let isError = executed.isError;
|
|
373
|
-
if (config.afterToolCall) {
|
|
374
|
-
try {
|
|
375
|
-
const afterResult = await config.afterToolCall({
|
|
376
|
-
assistantMessage,
|
|
377
|
-
toolCall: prepared.toolCall,
|
|
378
|
-
args: prepared.args,
|
|
379
|
-
result,
|
|
380
|
-
isError,
|
|
381
|
-
context: currentContext
|
|
382
|
-
}, signal);
|
|
383
|
-
if (afterResult) {
|
|
384
|
-
result = {
|
|
385
|
-
content: afterResult.content ?? result.content,
|
|
386
|
-
details: afterResult.details ?? result.details,
|
|
387
|
-
terminate: afterResult.terminate ?? result.terminate
|
|
388
|
-
};
|
|
389
|
-
isError = afterResult.isError ?? isError;
|
|
390
|
-
}
|
|
391
|
-
} catch (error) {
|
|
392
|
-
result = createErrorToolResult(error instanceof Error ? error.message : String(error));
|
|
393
|
-
isError = true;
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
return {
|
|
397
|
-
toolCall: prepared.toolCall,
|
|
398
|
-
result,
|
|
399
|
-
isError
|
|
400
|
-
};
|
|
401
|
-
}
|
|
402
|
-
function createErrorToolResult(message) {
|
|
403
|
-
return {
|
|
404
|
-
content: [{ type: "text", text: message }],
|
|
405
|
-
details: {}
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
async function emitToolExecutionEnd(finalized, emit) {
|
|
409
|
-
await emit({
|
|
410
|
-
type: "tool_execution_end",
|
|
411
|
-
toolCallId: finalized.toolCall.id,
|
|
412
|
-
toolName: finalized.toolCall.name,
|
|
413
|
-
result: finalized.result,
|
|
414
|
-
isError: finalized.isError
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
function createToolResultMessage(finalized) {
|
|
418
|
-
return {
|
|
419
|
-
role: "toolResult",
|
|
420
|
-
toolCallId: finalized.toolCall.id,
|
|
421
|
-
toolName: finalized.toolCall.name,
|
|
422
|
-
content: finalized.result.content,
|
|
423
|
-
details: finalized.result.details,
|
|
424
|
-
isError: finalized.isError,
|
|
425
|
-
timestamp: Date.now()
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
async function emitToolResultMessage(toolResultMessage, emit) {
|
|
429
|
-
await emit({ type: "message_start", message: toolResultMessage });
|
|
430
|
-
await emit({ type: "message_end", message: toolResultMessage });
|
|
431
|
-
}
|
|
432
|
-
function defaultConvertToLlm(messages) {
|
|
433
|
-
return messages.filter((message) => message.role === "user" || message.role === "assistant" || message.role === "toolResult");
|
|
434
|
-
}
|
|
435
|
-
const EMPTY_USAGE = {
|
|
436
|
-
input: 0,
|
|
437
|
-
output: 0,
|
|
438
|
-
cacheRead: 0,
|
|
439
|
-
cacheWrite: 0,
|
|
440
|
-
totalTokens: 0,
|
|
441
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
|
|
442
|
-
};
|
|
443
|
-
const DEFAULT_MODEL = {
|
|
444
|
-
id: "unknown",
|
|
445
|
-
name: "unknown",
|
|
446
|
-
api: "unknown",
|
|
447
|
-
provider: "unknown",
|
|
448
|
-
baseUrl: "",
|
|
449
|
-
reasoning: false,
|
|
450
|
-
input: [],
|
|
451
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
452
|
-
contextWindow: 0,
|
|
453
|
-
maxTokens: 0
|
|
454
|
-
};
|
|
455
|
-
function createMutableAgentState(initialState) {
|
|
456
|
-
let tools = initialState?.tools?.slice() ?? [];
|
|
457
|
-
let messages = initialState?.messages?.slice() ?? [];
|
|
458
|
-
return {
|
|
459
|
-
systemPrompt: initialState?.systemPrompt ?? "",
|
|
460
|
-
model: initialState?.model ?? DEFAULT_MODEL,
|
|
461
|
-
thinkingLevel: initialState?.thinkingLevel ?? "off",
|
|
462
|
-
get tools() {
|
|
463
|
-
return tools;
|
|
464
|
-
},
|
|
465
|
-
set tools(nextTools) {
|
|
466
|
-
tools = nextTools.slice();
|
|
467
|
-
},
|
|
468
|
-
get messages() {
|
|
469
|
-
return messages;
|
|
470
|
-
},
|
|
471
|
-
set messages(nextMessages) {
|
|
472
|
-
messages = nextMessages.slice();
|
|
473
|
-
},
|
|
474
|
-
isStreaming: false,
|
|
475
|
-
streamingMessage: void 0,
|
|
476
|
-
pendingToolCalls: /* @__PURE__ */ new Set(),
|
|
477
|
-
errorMessage: void 0
|
|
478
|
-
};
|
|
479
|
-
}
|
|
480
|
-
class PendingMessageQueue {
|
|
481
|
-
mode;
|
|
482
|
-
messages = [];
|
|
483
|
-
constructor(mode) {
|
|
484
|
-
this.mode = mode;
|
|
485
|
-
}
|
|
486
|
-
enqueue(message) {
|
|
487
|
-
this.messages.push(message);
|
|
488
|
-
}
|
|
489
|
-
hasItems() {
|
|
490
|
-
return this.messages.length > 0;
|
|
491
|
-
}
|
|
492
|
-
drain() {
|
|
493
|
-
if (this.mode === "all") {
|
|
494
|
-
const drained = this.messages.slice();
|
|
495
|
-
this.messages = [];
|
|
496
|
-
return drained;
|
|
497
|
-
}
|
|
498
|
-
const first = this.messages[0];
|
|
499
|
-
if (!first) {
|
|
500
|
-
return [];
|
|
501
|
-
}
|
|
502
|
-
this.messages = this.messages.slice(1);
|
|
503
|
-
return [first];
|
|
504
|
-
}
|
|
505
|
-
clear() {
|
|
506
|
-
this.messages = [];
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
class Agent {
|
|
510
|
-
_state;
|
|
511
|
-
listeners = /* @__PURE__ */ new Set();
|
|
512
|
-
steeringQueue;
|
|
513
|
-
followUpQueue;
|
|
514
|
-
convertToLlm;
|
|
515
|
-
transformContext;
|
|
516
|
-
streamFn;
|
|
517
|
-
getApiKey;
|
|
518
|
-
onPayload;
|
|
519
|
-
onResponse;
|
|
520
|
-
beforeToolCall;
|
|
521
|
-
afterToolCall;
|
|
522
|
-
activeRun;
|
|
523
|
-
/** Session identifier forwarded to providers for cache-aware backends. */
|
|
524
|
-
sessionId;
|
|
525
|
-
/** Optional per-level thinking token budgets forwarded to the stream function. */
|
|
526
|
-
thinkingBudgets;
|
|
527
|
-
/** Preferred transport forwarded to the stream function. */
|
|
528
|
-
transport;
|
|
529
|
-
/** Optional cap for provider-requested retry delays. */
|
|
530
|
-
maxRetryDelayMs;
|
|
531
|
-
/** Tool execution strategy for assistant messages that contain multiple tool calls. */
|
|
532
|
-
toolExecution;
|
|
533
|
-
constructor(options = {}) {
|
|
534
|
-
this._state = createMutableAgentState(options.initialState);
|
|
535
|
-
this.convertToLlm = options.convertToLlm ?? defaultConvertToLlm;
|
|
536
|
-
this.transformContext = options.transformContext;
|
|
537
|
-
this.streamFn = options.streamFn ?? streamSimple;
|
|
538
|
-
this.getApiKey = options.getApiKey;
|
|
539
|
-
this.onPayload = options.onPayload;
|
|
540
|
-
this.onResponse = options.onResponse;
|
|
541
|
-
this.beforeToolCall = options.beforeToolCall;
|
|
542
|
-
this.afterToolCall = options.afterToolCall;
|
|
543
|
-
this.steeringQueue = new PendingMessageQueue(options.steeringMode ?? "one-at-a-time");
|
|
544
|
-
this.followUpQueue = new PendingMessageQueue(options.followUpMode ?? "one-at-a-time");
|
|
545
|
-
this.sessionId = options.sessionId;
|
|
546
|
-
this.thinkingBudgets = options.thinkingBudgets;
|
|
547
|
-
this.transport = options.transport ?? "auto";
|
|
548
|
-
this.maxRetryDelayMs = options.maxRetryDelayMs;
|
|
549
|
-
this.toolExecution = options.toolExecution ?? "parallel";
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Subscribe to agent lifecycle events.
|
|
553
|
-
*
|
|
554
|
-
* Listener promises are awaited in subscription order and are included in
|
|
555
|
-
* the current run's settlement. Listeners also receive the active abort
|
|
556
|
-
* signal for the current run.
|
|
557
|
-
*
|
|
558
|
-
* `agent_end` is the final emitted event for a run, but the agent does not
|
|
559
|
-
* become idle until all awaited listeners for that event have settled.
|
|
560
|
-
*/
|
|
561
|
-
subscribe(listener) {
|
|
562
|
-
this.listeners.add(listener);
|
|
563
|
-
return () => this.listeners.delete(listener);
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* Current agent state.
|
|
567
|
-
*
|
|
568
|
-
* Assigning `state.tools` or `state.messages` copies the provided top-level array.
|
|
569
|
-
*/
|
|
570
|
-
get state() {
|
|
571
|
-
return this._state;
|
|
572
|
-
}
|
|
573
|
-
/** Controls how queued steering messages are drained. */
|
|
574
|
-
set steeringMode(mode) {
|
|
575
|
-
this.steeringQueue.mode = mode;
|
|
576
|
-
}
|
|
577
|
-
get steeringMode() {
|
|
578
|
-
return this.steeringQueue.mode;
|
|
579
|
-
}
|
|
580
|
-
/** Controls how queued follow-up messages are drained. */
|
|
581
|
-
set followUpMode(mode) {
|
|
582
|
-
this.followUpQueue.mode = mode;
|
|
583
|
-
}
|
|
584
|
-
get followUpMode() {
|
|
585
|
-
return this.followUpQueue.mode;
|
|
586
|
-
}
|
|
587
|
-
/** Queue a message to be injected after the current assistant turn finishes. */
|
|
588
|
-
steer(message) {
|
|
589
|
-
this.steeringQueue.enqueue(message);
|
|
590
|
-
}
|
|
591
|
-
/** Queue a message to run only after the agent would otherwise stop. */
|
|
592
|
-
followUp(message) {
|
|
593
|
-
this.followUpQueue.enqueue(message);
|
|
594
|
-
}
|
|
595
|
-
/** Remove all queued steering messages. */
|
|
596
|
-
clearSteeringQueue() {
|
|
597
|
-
this.steeringQueue.clear();
|
|
598
|
-
}
|
|
599
|
-
/** Remove all queued follow-up messages. */
|
|
600
|
-
clearFollowUpQueue() {
|
|
601
|
-
this.followUpQueue.clear();
|
|
602
|
-
}
|
|
603
|
-
/** Remove all queued steering and follow-up messages. */
|
|
604
|
-
clearAllQueues() {
|
|
605
|
-
this.clearSteeringQueue();
|
|
606
|
-
this.clearFollowUpQueue();
|
|
607
|
-
}
|
|
608
|
-
/** Returns true when either queue still contains pending messages. */
|
|
609
|
-
hasQueuedMessages() {
|
|
610
|
-
return this.steeringQueue.hasItems() || this.followUpQueue.hasItems();
|
|
611
|
-
}
|
|
612
|
-
/** Active abort signal for the current run, if any. */
|
|
613
|
-
get signal() {
|
|
614
|
-
return this.activeRun?.abortController.signal;
|
|
615
|
-
}
|
|
616
|
-
/** Abort the current run, if one is active. */
|
|
617
|
-
abort() {
|
|
618
|
-
this.activeRun?.abortController.abort();
|
|
619
|
-
}
|
|
620
|
-
/**
|
|
621
|
-
* Resolve when the current run and all awaited event listeners have finished.
|
|
622
|
-
*
|
|
623
|
-
* This resolves after `agent_end` listeners settle.
|
|
624
|
-
*/
|
|
625
|
-
waitForIdle() {
|
|
626
|
-
return this.activeRun?.promise ?? Promise.resolve();
|
|
627
|
-
}
|
|
628
|
-
/** Clear transcript state, runtime state, and queued messages. */
|
|
629
|
-
reset() {
|
|
630
|
-
this._state.messages = [];
|
|
631
|
-
this._state.isStreaming = false;
|
|
632
|
-
this._state.streamingMessage = void 0;
|
|
633
|
-
this._state.pendingToolCalls = /* @__PURE__ */ new Set();
|
|
634
|
-
this._state.errorMessage = void 0;
|
|
635
|
-
this.clearFollowUpQueue();
|
|
636
|
-
this.clearSteeringQueue();
|
|
637
|
-
}
|
|
638
|
-
async prompt(input, images) {
|
|
639
|
-
if (this.activeRun) {
|
|
640
|
-
throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");
|
|
641
|
-
}
|
|
642
|
-
const messages = this.normalizePromptInput(input, images);
|
|
643
|
-
await this.runPromptMessages(messages);
|
|
644
|
-
}
|
|
645
|
-
/** Continue from the current transcript. The last message must be a user or tool-result message. */
|
|
646
|
-
async continue() {
|
|
647
|
-
if (this.activeRun) {
|
|
648
|
-
throw new Error("Agent is already processing. Wait for completion before continuing.");
|
|
649
|
-
}
|
|
650
|
-
const lastMessage = this._state.messages[this._state.messages.length - 1];
|
|
651
|
-
if (!lastMessage) {
|
|
652
|
-
throw new Error("No messages to continue from");
|
|
653
|
-
}
|
|
654
|
-
if (lastMessage.role === "assistant") {
|
|
655
|
-
const queuedSteering = this.steeringQueue.drain();
|
|
656
|
-
if (queuedSteering.length > 0) {
|
|
657
|
-
await this.runPromptMessages(queuedSteering, { skipInitialSteeringPoll: true });
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
const queuedFollowUps = this.followUpQueue.drain();
|
|
661
|
-
if (queuedFollowUps.length > 0) {
|
|
662
|
-
await this.runPromptMessages(queuedFollowUps);
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
665
|
-
throw new Error("Cannot continue from message role: assistant");
|
|
666
|
-
}
|
|
667
|
-
await this.runContinuation();
|
|
668
|
-
}
|
|
669
|
-
normalizePromptInput(input, images) {
|
|
670
|
-
if (Array.isArray(input)) {
|
|
671
|
-
return input;
|
|
672
|
-
}
|
|
673
|
-
if (typeof input !== "string") {
|
|
674
|
-
return [input];
|
|
675
|
-
}
|
|
676
|
-
const content = [{ type: "text", text: input }];
|
|
677
|
-
if (images && images.length > 0) {
|
|
678
|
-
content.push(...images);
|
|
679
|
-
}
|
|
680
|
-
return [{ role: "user", content, timestamp: Date.now() }];
|
|
681
|
-
}
|
|
682
|
-
async runPromptMessages(messages, options = {}) {
|
|
683
|
-
await this.runWithLifecycle(async (signal) => {
|
|
684
|
-
await runAgentLoop(messages, this.createContextSnapshot(), this.createLoopConfig(options), (event) => this.processEvents(event), signal, this.streamFn);
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
async runContinuation() {
|
|
688
|
-
await this.runWithLifecycle(async (signal) => {
|
|
689
|
-
await runAgentLoopContinue(this.createContextSnapshot(), this.createLoopConfig(), (event) => this.processEvents(event), signal, this.streamFn);
|
|
690
|
-
});
|
|
691
|
-
}
|
|
692
|
-
createContextSnapshot() {
|
|
693
|
-
return {
|
|
694
|
-
systemPrompt: this._state.systemPrompt,
|
|
695
|
-
messages: this._state.messages.slice(),
|
|
696
|
-
tools: this._state.tools.slice()
|
|
697
|
-
};
|
|
698
|
-
}
|
|
699
|
-
createLoopConfig(options = {}) {
|
|
700
|
-
let skipInitialSteeringPoll = options.skipInitialSteeringPoll === true;
|
|
701
|
-
return {
|
|
702
|
-
model: this._state.model,
|
|
703
|
-
reasoning: this._state.thinkingLevel === "off" ? void 0 : this._state.thinkingLevel,
|
|
704
|
-
sessionId: this.sessionId,
|
|
705
|
-
onPayload: this.onPayload,
|
|
706
|
-
onResponse: this.onResponse,
|
|
707
|
-
transport: this.transport,
|
|
708
|
-
thinkingBudgets: this.thinkingBudgets,
|
|
709
|
-
maxRetryDelayMs: this.maxRetryDelayMs,
|
|
710
|
-
toolExecution: this.toolExecution,
|
|
711
|
-
beforeToolCall: this.beforeToolCall,
|
|
712
|
-
afterToolCall: this.afterToolCall,
|
|
713
|
-
convertToLlm: this.convertToLlm,
|
|
714
|
-
transformContext: this.transformContext,
|
|
715
|
-
getApiKey: this.getApiKey,
|
|
716
|
-
getSteeringMessages: async () => {
|
|
717
|
-
if (skipInitialSteeringPoll) {
|
|
718
|
-
skipInitialSteeringPoll = false;
|
|
719
|
-
return [];
|
|
720
|
-
}
|
|
721
|
-
return this.steeringQueue.drain();
|
|
722
|
-
},
|
|
723
|
-
getFollowUpMessages: async () => this.followUpQueue.drain()
|
|
724
|
-
};
|
|
725
|
-
}
|
|
726
|
-
async runWithLifecycle(executor) {
|
|
727
|
-
if (this.activeRun) {
|
|
728
|
-
throw new Error("Agent is already processing.");
|
|
729
|
-
}
|
|
730
|
-
const abortController = new AbortController();
|
|
731
|
-
let resolvePromise = () => {
|
|
732
|
-
};
|
|
733
|
-
const promise = new Promise((resolve) => {
|
|
734
|
-
resolvePromise = resolve;
|
|
735
|
-
});
|
|
736
|
-
this.activeRun = { promise, resolve: resolvePromise, abortController };
|
|
737
|
-
this._state.isStreaming = true;
|
|
738
|
-
this._state.streamingMessage = void 0;
|
|
739
|
-
this._state.errorMessage = void 0;
|
|
740
|
-
try {
|
|
741
|
-
await executor(abortController.signal);
|
|
742
|
-
} catch (error) {
|
|
743
|
-
await this.handleRunFailure(error, abortController.signal.aborted);
|
|
744
|
-
} finally {
|
|
745
|
-
this.finishRun();
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
async handleRunFailure(error, aborted) {
|
|
749
|
-
const failureMessage = {
|
|
750
|
-
role: "assistant",
|
|
751
|
-
content: [{ type: "text", text: "" }],
|
|
752
|
-
api: this._state.model.api,
|
|
753
|
-
provider: this._state.model.provider,
|
|
754
|
-
model: this._state.model.id,
|
|
755
|
-
usage: EMPTY_USAGE,
|
|
756
|
-
stopReason: aborted ? "aborted" : "error",
|
|
757
|
-
errorMessage: error instanceof Error ? error.message : String(error),
|
|
758
|
-
timestamp: Date.now()
|
|
759
|
-
};
|
|
760
|
-
this._state.messages.push(failureMessage);
|
|
761
|
-
this._state.errorMessage = failureMessage.errorMessage;
|
|
762
|
-
await this.processEvents({ type: "agent_end", messages: [failureMessage] });
|
|
763
|
-
}
|
|
764
|
-
finishRun() {
|
|
765
|
-
this._state.isStreaming = false;
|
|
766
|
-
this._state.streamingMessage = void 0;
|
|
767
|
-
this._state.pendingToolCalls = /* @__PURE__ */ new Set();
|
|
768
|
-
this.activeRun?.resolve();
|
|
769
|
-
this.activeRun = void 0;
|
|
770
|
-
}
|
|
771
|
-
/**
|
|
772
|
-
* Reduce internal state for a loop event, then await listeners.
|
|
773
|
-
*
|
|
774
|
-
* `agent_end` only means no further loop events will be emitted. The run is
|
|
775
|
-
* considered idle later, after all awaited listeners for `agent_end` finish
|
|
776
|
-
* and `finishRun()` clears runtime-owned state.
|
|
777
|
-
*/
|
|
778
|
-
async processEvents(event) {
|
|
779
|
-
switch (event.type) {
|
|
780
|
-
case "message_start":
|
|
781
|
-
this._state.streamingMessage = event.message;
|
|
782
|
-
break;
|
|
783
|
-
case "message_update":
|
|
784
|
-
this._state.streamingMessage = event.message;
|
|
785
|
-
break;
|
|
786
|
-
case "message_end":
|
|
787
|
-
this._state.streamingMessage = void 0;
|
|
788
|
-
this._state.messages.push(event.message);
|
|
789
|
-
break;
|
|
790
|
-
case "tool_execution_start": {
|
|
791
|
-
const pendingToolCalls = new Set(this._state.pendingToolCalls);
|
|
792
|
-
pendingToolCalls.add(event.toolCallId);
|
|
793
|
-
this._state.pendingToolCalls = pendingToolCalls;
|
|
794
|
-
break;
|
|
795
|
-
}
|
|
796
|
-
case "tool_execution_end": {
|
|
797
|
-
const pendingToolCalls = new Set(this._state.pendingToolCalls);
|
|
798
|
-
pendingToolCalls.delete(event.toolCallId);
|
|
799
|
-
this._state.pendingToolCalls = pendingToolCalls;
|
|
800
|
-
break;
|
|
801
|
-
}
|
|
802
|
-
case "turn_end":
|
|
803
|
-
if (event.message.role === "assistant" && event.message.errorMessage) {
|
|
804
|
-
this._state.errorMessage = event.message.errorMessage;
|
|
805
|
-
}
|
|
806
|
-
break;
|
|
807
|
-
case "agent_end":
|
|
808
|
-
this._state.streamingMessage = void 0;
|
|
809
|
-
break;
|
|
810
|
-
}
|
|
811
|
-
const signal = this.activeRun?.abortController.signal;
|
|
812
|
-
if (!signal) {
|
|
813
|
-
throw new Error("Agent listener invoked outside active run");
|
|
814
|
-
}
|
|
815
|
-
for (const listener of this.listeners) {
|
|
816
|
-
await listener(event, signal);
|
|
817
|
-
}
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
export {
|
|
821
|
-
Agent,
|
|
822
|
-
runAgentLoop,
|
|
823
|
-
runAgentLoopContinue
|
|
824
|
-
};
|
|
1
|
+
import"./typebox.mjs";import{s as _,v as b}from"./mariozechner__pi-ai.mjs";import"./partial-json.mjs";import"./anthropic-ai__sdk.mjs";import"./openai.mjs";import"./google__genai.mjs";import"./p-retry.mjs";import"./react.mjs";import"./retry.mjs";import"./google-auth-library.mjs";import"child_process";import"path";import"querystring";import"fs";import"./gaxios.mjs";import"https";import"./extend.mjs";import"stream";import"./gcp-metadata.mjs";import"os";import"./json-bigint.mjs";import"./bignumber.js.mjs";import"./google-logging-utils.mjs";import"process";import"events";import"util";import"./base64-js.mjs";import"crypto";import"./ecdsa-sig-formatter.mjs";import"./safe-buffer.mjs";import"buffer";import"./jws.mjs";import"./jwa.mjs";import"./buffer-equal-constant-time.mjs";import"fs/promises";import"node:stream";import"node:stream/promises";import"./ws.mjs";import"http";import"net";import"tls";import"url";import"zlib";import"./mistralai__mistralai.mjs";import"./zod.mjs";import"./zod-to-json-schema.mjs";import"./opentelemetry__api.mjs";import"./@opentelemetry/semantic-conventions+[...].mjs";async function x(t,e,s,a,o,r){const n=[...t],l={...e,messages:[...e.messages,...t]};await a({type:"agent_start"}),await a({type:"turn_start"});for(const i of t)await a({type:"message_start",message:i}),await a({type:"message_end",message:i});return await C(l,n,s,o,a,r),n}async function P(t,e,s,a,o){if(t.messages.length===0)throw new Error("Cannot continue: no messages in context");if(t.messages[t.messages.length-1].role==="assistant")throw new Error("Cannot continue from message role: assistant");const r=[],n={...t};return await s({type:"agent_start"}),await s({type:"turn_start"}),await C(n,r,e,a,s,o),r}async function C(t,e,s,a,o,r){let n=!0,l=await s.getSteeringMessages?.()||[];for(;;){let i=!0;for(;i||l.length>0;){if(n?n=!1:await o({type:"turn_start"}),l.length>0){for(const c of l)await o({type:"message_start",message:c}),await o({type:"message_end",message:c}),t.messages.push(c),e.push(c);l=[]}const u=await A(t,s,a,o,r);if(e.push(u),u.stopReason==="error"||u.stopReason==="aborted"){await o({type:"turn_end",message:u,toolResults:[]}),await o({type:"agent_end",messages:e});return}const g=u.content.filter(c=>c.type==="toolCall"),p=[];if(i=!1,g.length>0){const c=await S(t,u,s,a,o);p.push(...c.messages),i=!c.terminate;for(const h of p)t.messages.push(h),e.push(h)}if(await o({type:"turn_end",message:u,toolResults:p}),await s.shouldStopAfterTurn?.({message:u,toolResults:p,context:t,newMessages:e})){await o({type:"agent_end",messages:e});return}l=await s.getSteeringMessages?.()||[]}const m=await s.getFollowUpMessages?.()||[];if(m.length>0){l=m;continue}break}await o({type:"agent_end",messages:e})}async function A(t,e,s,a,o){let r=t.messages;e.transformContext&&(r=await e.transformContext(r,s));const n=await e.convertToLlm(r),l={systemPrompt:t.systemPrompt,messages:n,tools:t.tools},i=o||_,m=(e.getApiKey?await e.getApiKey(e.model.provider):void 0)||e.apiKey,u=await i(e.model,l,{...e,apiKey:m,signal:s});let g=null,p=!1;for await(const h of u)switch(h.type){case"start":g=h.partial,t.messages.push(g),p=!0,await a({type:"message_start",message:{...g}});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":g&&(g=h.partial,t.messages[t.messages.length-1]=g,await a({type:"message_update",assistantMessageEvent:h,message:{...g}}));break;case"done":case"error":{const d=await u.result();return p?t.messages[t.messages.length-1]=d:t.messages.push(d),p||await a({type:"message_start",message:{...d}}),await a({type:"message_end",message:d}),d}}const c=await u.result();return p?t.messages[t.messages.length-1]=c:(t.messages.push(c),await a({type:"message_start",message:{...c}})),await a({type:"message_end",message:c}),c}async function S(t,e,s,a,o){const r=e.content.filter(l=>l.type==="toolCall"),n=r.some(l=>t.tools?.find(i=>i.name===l.name)?.executionMode==="sequential");return s.toolExecution==="sequential"||n?Q(t,e,r,s,a,o):U(t,e,r,s,a,o)}async function Q(t,e,s,a,o,r){const n=[],l=[];for(const i of s){await r({type:"tool_execution_start",toolCallId:i.id,toolName:i.name,args:i.arguments});const m=await E(t,e,i,a,o);let u;if(m.kind==="immediate")u={toolCall:i,result:m.result,isError:m.isError};else{const p=await M(m,o,r);u=await R(t,e,m,p,a,o)}await w(u,r);const g=k(u);await v(g,r),n.push(u),l.push(g)}return{messages:l,terminate:T(n)}}async function U(t,e,s,a,o,r){const n=[];for(const m of s){await r({type:"tool_execution_start",toolCallId:m.id,toolName:m.name,args:m.arguments});const u=await E(t,e,m,a,o);if(u.kind==="immediate"){const g={toolCall:m,result:u.result,isError:u.isError};await w(g,r),n.push(g);continue}n.push(async()=>{const g=await M(u,o,r),p=await R(t,e,u,g,a,o);return await w(p,r),p})}const l=await Promise.all(n.map(m=>typeof m=="function"?m():Promise.resolve(m))),i=[];for(const m of l){const u=k(m);await v(u,r),i.push(u)}return{messages:i,terminate:T(l)}}function T(t){return t.length>0&&t.every(e=>e.result.terminate===!0)}function L(t,e){if(!t.prepareArguments)return e;const s=t.prepareArguments(e.arguments);return s===e.arguments?e:{...e,arguments:s}}async function E(t,e,s,a,o){const r=t.tools?.find(n=>n.name===s.name);if(!r)return{kind:"immediate",result:f(`Tool ${s.name} not found`),isError:!0};try{const n=L(r,s),l=b(r,n);if(a.beforeToolCall){const i=await a.beforeToolCall({assistantMessage:e,toolCall:s,args:l,context:t},o);if(i?.block)return{kind:"immediate",result:f(i.reason||"Tool execution was blocked"),isError:!0}}return{kind:"prepared",toolCall:s,tool:r,args:l}}catch(n){return{kind:"immediate",result:f(n instanceof Error?n.message:String(n)),isError:!0}}}async function M(t,e,s){const a=[];try{const o=await t.tool.execute(t.toolCall.id,t.args,e,r=>{a.push(Promise.resolve(s({type:"tool_execution_update",toolCallId:t.toolCall.id,toolName:t.toolCall.name,args:t.toolCall.arguments,partialResult:r})))});return await Promise.all(a),{result:o,isError:!1}}catch(o){return await Promise.all(a),{result:f(o instanceof Error?o.message:String(o)),isError:!0}}}async function R(t,e,s,a,o,r){let n=a.result,l=a.isError;if(o.afterToolCall)try{const i=await o.afterToolCall({assistantMessage:e,toolCall:s.toolCall,args:s.args,result:n,isError:l,context:t},r);i&&(n={content:i.content??n.content,details:i.details??n.details,terminate:i.terminate??n.terminate},l=i.isError??l)}catch(i){n=f(i instanceof Error?i.message:String(i)),l=!0}return{toolCall:s.toolCall,result:n,isError:l}}function f(t){return{content:[{type:"text",text:t}],details:{}}}async function w(t,e){await e({type:"tool_execution_end",toolCallId:t.toolCall.id,toolName:t.toolCall.name,result:t.result,isError:t.isError})}function k(t){return{role:"toolResult",toolCallId:t.toolCall.id,toolName:t.toolCall.name,content:t.result.content,details:t.result.details,isError:t.isError,timestamp:Date.now()}}async function v(t,e){await e({type:"message_start",message:t}),await e({type:"message_end",message:t})}function I(t){return t.filter(e=>e.role==="user"||e.role==="assistant"||e.role==="toolResult")}const F={input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},q={id:"unknown",name:"unknown",api:"unknown",provider:"unknown",baseUrl:"",reasoning:!1,input:[],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:0,maxTokens:0};function D(t){let e=t?.tools?.slice()??[],s=t?.messages?.slice()??[];return{systemPrompt:t?.systemPrompt??"",model:t?.model??q,thinkingLevel:t?.thinkingLevel??"off",get tools(){return e},set tools(a){e=a.slice()},get messages(){return s},set messages(a){s=a.slice()},isStreaming:!1,streamingMessage:void 0,pendingToolCalls:new Set,errorMessage:void 0}}class y{mode;messages=[];constructor(e){this.mode=e}enqueue(e){this.messages.push(e)}hasItems(){return this.messages.length>0}drain(){if(this.mode==="all"){const s=this.messages.slice();return this.messages=[],s}const e=this.messages[0];return e?(this.messages=this.messages.slice(1),[e]):[]}clear(){this.messages=[]}}class Ue{_state;listeners=new Set;steeringQueue;followUpQueue;convertToLlm;transformContext;streamFn;getApiKey;onPayload;onResponse;beforeToolCall;afterToolCall;activeRun;sessionId;thinkingBudgets;transport;maxRetryDelayMs;toolExecution;constructor(e={}){this._state=D(e.initialState),this.convertToLlm=e.convertToLlm??I,this.transformContext=e.transformContext,this.streamFn=e.streamFn??_,this.getApiKey=e.getApiKey,this.onPayload=e.onPayload,this.onResponse=e.onResponse,this.beforeToolCall=e.beforeToolCall,this.afterToolCall=e.afterToolCall,this.steeringQueue=new y(e.steeringMode??"one-at-a-time"),this.followUpQueue=new y(e.followUpMode??"one-at-a-time"),this.sessionId=e.sessionId,this.thinkingBudgets=e.thinkingBudgets,this.transport=e.transport??"auto",this.maxRetryDelayMs=e.maxRetryDelayMs,this.toolExecution=e.toolExecution??"parallel"}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}get state(){return this._state}set steeringMode(e){this.steeringQueue.mode=e}get steeringMode(){return this.steeringQueue.mode}set followUpMode(e){this.followUpQueue.mode=e}get followUpMode(){return this.followUpQueue.mode}steer(e){this.steeringQueue.enqueue(e)}followUp(e){this.followUpQueue.enqueue(e)}clearSteeringQueue(){this.steeringQueue.clear()}clearFollowUpQueue(){this.followUpQueue.clear()}clearAllQueues(){this.clearSteeringQueue(),this.clearFollowUpQueue()}hasQueuedMessages(){return this.steeringQueue.hasItems()||this.followUpQueue.hasItems()}get signal(){return this.activeRun?.abortController.signal}abort(){this.activeRun?.abortController.abort()}waitForIdle(){return this.activeRun?.promise??Promise.resolve()}reset(){this._state.messages=[],this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this._state.errorMessage=void 0,this.clearFollowUpQueue(),this.clearSteeringQueue()}async prompt(e,s){if(this.activeRun)throw new Error("Agent is already processing a prompt. Use steer() or followUp() to queue messages, or wait for completion.");const a=this.normalizePromptInput(e,s);await this.runPromptMessages(a)}async continue(){if(this.activeRun)throw new Error("Agent is already processing. Wait for completion before continuing.");const e=this._state.messages[this._state.messages.length-1];if(!e)throw new Error("No messages to continue from");if(e.role==="assistant"){const s=this.steeringQueue.drain();if(s.length>0){await this.runPromptMessages(s,{skipInitialSteeringPoll:!0});return}const a=this.followUpQueue.drain();if(a.length>0){await this.runPromptMessages(a);return}throw new Error("Cannot continue from message role: assistant")}await this.runContinuation()}normalizePromptInput(e,s){if(Array.isArray(e))return e;if(typeof e!="string")return[e];const a=[{type:"text",text:e}];return s&&s.length>0&&a.push(...s),[{role:"user",content:a,timestamp:Date.now()}]}async runPromptMessages(e,s={}){await this.runWithLifecycle(async a=>{await x(e,this.createContextSnapshot(),this.createLoopConfig(s),o=>this.processEvents(o),a,this.streamFn)})}async runContinuation(){await this.runWithLifecycle(async e=>{await P(this.createContextSnapshot(),this.createLoopConfig(),s=>this.processEvents(s),e,this.streamFn)})}createContextSnapshot(){return{systemPrompt:this._state.systemPrompt,messages:this._state.messages.slice(),tools:this._state.tools.slice()}}createLoopConfig(e={}){let s=e.skipInitialSteeringPoll===!0;return{model:this._state.model,reasoning:this._state.thinkingLevel==="off"?void 0:this._state.thinkingLevel,sessionId:this.sessionId,onPayload:this.onPayload,onResponse:this.onResponse,transport:this.transport,thinkingBudgets:this.thinkingBudgets,maxRetryDelayMs:this.maxRetryDelayMs,toolExecution:this.toolExecution,beforeToolCall:this.beforeToolCall,afterToolCall:this.afterToolCall,convertToLlm:this.convertToLlm,transformContext:this.transformContext,getApiKey:this.getApiKey,getSteeringMessages:async()=>s?(s=!1,[]):this.steeringQueue.drain(),getFollowUpMessages:async()=>this.followUpQueue.drain()}}async runWithLifecycle(e){if(this.activeRun)throw new Error("Agent is already processing.");const s=new AbortController;let a=()=>{};const o=new Promise(r=>{a=r});this.activeRun={promise:o,resolve:a,abortController:s},this._state.isStreaming=!0,this._state.streamingMessage=void 0,this._state.errorMessage=void 0;try{await e(s.signal)}catch(r){await this.handleRunFailure(r,s.signal.aborted)}finally{this.finishRun()}}async handleRunFailure(e,s){const a={role:"assistant",content:[{type:"text",text:""}],api:this._state.model.api,provider:this._state.model.provider,model:this._state.model.id,usage:F,stopReason:s?"aborted":"error",errorMessage:e instanceof Error?e.message:String(e),timestamp:Date.now()};this._state.messages.push(a),this._state.errorMessage=a.errorMessage,await this.processEvents({type:"agent_end",messages:[a]})}finishRun(){this._state.isStreaming=!1,this._state.streamingMessage=void 0,this._state.pendingToolCalls=new Set,this.activeRun?.resolve(),this.activeRun=void 0}async processEvents(e){switch(e.type){case"message_start":this._state.streamingMessage=e.message;break;case"message_update":this._state.streamingMessage=e.message;break;case"message_end":this._state.streamingMessage=void 0,this._state.messages.push(e.message);break;case"tool_execution_start":{const a=new Set(this._state.pendingToolCalls);a.add(e.toolCallId),this._state.pendingToolCalls=a;break}case"tool_execution_end":{const a=new Set(this._state.pendingToolCalls);a.delete(e.toolCallId),this._state.pendingToolCalls=a;break}case"turn_end":e.message.role==="assistant"&&e.message.errorMessage&&(this._state.errorMessage=e.message.errorMessage);break;case"agent_end":this._state.streamingMessage=void 0;break}const s=this.activeRun?.abortController.signal;if(!s)throw new Error("Agent listener invoked outside active run");for(const a of this.listeners)await a(e,s)}}export{Ue as Agent,x as runAgentLoop,P as runAgentLoopContinue};
|