veryfront 0.1.138 → 0.1.140
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/esm/deno.js +1 -1
- package/esm/src/agent/runtime/ai-stream-handler.d.ts +10 -0
- package/esm/src/agent/runtime/ai-stream-handler.d.ts.map +1 -1
- package/esm/src/agent/runtime/ai-stream-handler.js +93 -0
- package/esm/src/agent/runtime/index.d.ts.map +1 -1
- package/esm/src/agent/runtime/index.js +46 -2
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/deno.js +1 -1
- package/src/src/agent/runtime/ai-stream-handler.ts +125 -0
- package/src/src/agent/runtime/index.ts +53 -2
- package/src/src/utils/version-constant.ts +1 -1
package/esm/deno.js
CHANGED
|
@@ -15,10 +15,20 @@ export interface StreamingToolCall {
|
|
|
15
15
|
providerExecuted?: boolean;
|
|
16
16
|
dynamic?: boolean;
|
|
17
17
|
}
|
|
18
|
+
export interface StreamingToolResult {
|
|
19
|
+
toolCallId: string;
|
|
20
|
+
toolName: string;
|
|
21
|
+
output?: unknown;
|
|
22
|
+
error?: unknown;
|
|
23
|
+
providerExecuted?: boolean;
|
|
24
|
+
dynamic?: boolean;
|
|
25
|
+
preliminary?: boolean;
|
|
26
|
+
}
|
|
18
27
|
export interface AIStreamState {
|
|
19
28
|
accumulatedText: string;
|
|
20
29
|
finishReason: string | null;
|
|
21
30
|
toolCalls: Map<string, StreamingToolCall>;
|
|
31
|
+
toolResults: StreamingToolResult[];
|
|
22
32
|
usage: {
|
|
23
33
|
promptTokens: number;
|
|
24
34
|
completionTokens: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-stream-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/ai-stream-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ai-stream-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/ai-stream-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAUpD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC1C,WAAW,EAAE,mBAAmB,EAAE,CAAC;IACnC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CAChF;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE;QAChB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,KAAK,IAAI,CAAC;CACZ;AA6HD,wBAAgB,iBAAiB,IAAI,aAAa,CAQjD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,EACxC,KAAK,EAAE,aAAa,EACpB,UAAU,EAAE,+BAA+B,EAC3C,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,CAAC,EAAE,iBAAiB,EAC7B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,IAAI,CAAC,CAsNf"}
|
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
import { sendSSE } from "./sse-utils.js";
|
|
11
11
|
import { isDynamicTool } from "./tool-helpers.js";
|
|
12
12
|
import { serverLogger } from "../../utils/index.js";
|
|
13
|
+
import { isAnyDebugEnabled } from "../../utils/constants/env.js";
|
|
13
14
|
import { setActiveSpanAttributes, withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
15
|
+
import { getHostEnv } from "../../platform/compat/process.js";
|
|
14
16
|
const logger = serverLogger.component("agent");
|
|
15
17
|
function isRecord(value) {
|
|
16
18
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -53,6 +55,9 @@ function stringifyToolError(output) {
|
|
|
53
55
|
if (typeof output === "string" && output.length > 0) {
|
|
54
56
|
return output;
|
|
55
57
|
}
|
|
58
|
+
if (output instanceof Error && typeof output.message === "string" && output.message.length > 0) {
|
|
59
|
+
return output.message;
|
|
60
|
+
}
|
|
56
61
|
try {
|
|
57
62
|
return JSON.stringify(output);
|
|
58
63
|
}
|
|
@@ -60,11 +65,51 @@ function stringifyToolError(output) {
|
|
|
60
65
|
return String(output);
|
|
61
66
|
}
|
|
62
67
|
}
|
|
68
|
+
function summarizeDebugValue(value) {
|
|
69
|
+
if (value instanceof Error) {
|
|
70
|
+
return {
|
|
71
|
+
name: value.name,
|
|
72
|
+
message: value.message,
|
|
73
|
+
stack: value.stack,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (typeof value === "string") {
|
|
77
|
+
return value.length > 500 ? `${value.slice(0, 500)}…` : value;
|
|
78
|
+
}
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
function logProviderToolPart(partType, part) {
|
|
82
|
+
if (!isAnyDebugEnabled({ get: getHostEnv })) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (part.providerExecuted !== true) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (part.toolName !== "web_search" && part.toolName !== "web_fetch") {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
logger.debug("Provider tool stream part observed", {
|
|
92
|
+
partType,
|
|
93
|
+
toolCallId: part.toolCallId,
|
|
94
|
+
toolName: part.toolName,
|
|
95
|
+
providerExecuted: part.providerExecuted,
|
|
96
|
+
dynamic: part.dynamic,
|
|
97
|
+
preliminary: part.preliminary,
|
|
98
|
+
isError: part.isError,
|
|
99
|
+
outputType: typeof part.output,
|
|
100
|
+
errorType: typeof part.error,
|
|
101
|
+
inputType: typeof part.input,
|
|
102
|
+
output: summarizeDebugValue(part.output),
|
|
103
|
+
error: summarizeDebugValue(part.error),
|
|
104
|
+
input: summarizeDebugValue(part.input),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
63
107
|
export function createStreamState() {
|
|
64
108
|
return {
|
|
65
109
|
accumulatedText: "",
|
|
66
110
|
finishReason: null,
|
|
67
111
|
toolCalls: new Map(),
|
|
112
|
+
toolResults: [],
|
|
68
113
|
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
69
114
|
};
|
|
70
115
|
}
|
|
@@ -154,7 +199,26 @@ export function processStream(result, state, controller, encoder, textPartId, ca
|
|
|
154
199
|
}
|
|
155
200
|
case "tool-result": {
|
|
156
201
|
const isError = "isError" in part && part.isError === true;
|
|
202
|
+
logProviderToolPart("tool-result", {
|
|
203
|
+
toolCallId: part.toolCallId,
|
|
204
|
+
toolName: part.toolName,
|
|
205
|
+
providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
|
|
206
|
+
dynamic: "dynamic" in part ? part.dynamic : undefined,
|
|
207
|
+
output: part.output,
|
|
208
|
+
input: "input" in part ? part.input : undefined,
|
|
209
|
+
preliminary: "preliminary" in part ? part.preliminary : undefined,
|
|
210
|
+
isError,
|
|
211
|
+
});
|
|
157
212
|
if (isError) {
|
|
213
|
+
state.toolResults.push({
|
|
214
|
+
toolCallId: part.toolCallId,
|
|
215
|
+
toolName: part.toolName,
|
|
216
|
+
error: "output" in part ? part.output : undefined,
|
|
217
|
+
...("providerExecuted" in part && part.providerExecuted !== undefined
|
|
218
|
+
? { providerExecuted: part.providerExecuted }
|
|
219
|
+
: {}),
|
|
220
|
+
...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
|
|
221
|
+
});
|
|
158
222
|
sendSSE(controller, encoder, {
|
|
159
223
|
type: "tool-output-error",
|
|
160
224
|
toolCallId: part.toolCallId,
|
|
@@ -166,6 +230,18 @@ export function processStream(result, state, controller, encoder, textPartId, ca
|
|
|
166
230
|
});
|
|
167
231
|
break;
|
|
168
232
|
}
|
|
233
|
+
state.toolResults.push({
|
|
234
|
+
toolCallId: part.toolCallId,
|
|
235
|
+
toolName: part.toolName,
|
|
236
|
+
output: part.output,
|
|
237
|
+
...("providerExecuted" in part && part.providerExecuted !== undefined
|
|
238
|
+
? { providerExecuted: part.providerExecuted }
|
|
239
|
+
: {}),
|
|
240
|
+
...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
|
|
241
|
+
...("preliminary" in part && part.preliminary !== undefined
|
|
242
|
+
? { preliminary: part.preliminary }
|
|
243
|
+
: {}),
|
|
244
|
+
});
|
|
169
245
|
sendSSE(controller, encoder, {
|
|
170
246
|
type: "tool-output-available",
|
|
171
247
|
toolCallId: part.toolCallId,
|
|
@@ -181,6 +257,23 @@ export function processStream(result, state, controller, encoder, textPartId, ca
|
|
|
181
257
|
break;
|
|
182
258
|
}
|
|
183
259
|
case "tool-error": {
|
|
260
|
+
logProviderToolPart("tool-error", {
|
|
261
|
+
toolCallId: part.toolCallId,
|
|
262
|
+
toolName: part.toolName,
|
|
263
|
+
providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
|
|
264
|
+
dynamic: "dynamic" in part ? part.dynamic : undefined,
|
|
265
|
+
error: part.error,
|
|
266
|
+
input: "input" in part ? part.input : undefined,
|
|
267
|
+
});
|
|
268
|
+
state.toolResults.push({
|
|
269
|
+
toolCallId: part.toolCallId,
|
|
270
|
+
toolName: part.toolName,
|
|
271
|
+
error: part.error,
|
|
272
|
+
...("providerExecuted" in part && part.providerExecuted !== undefined
|
|
273
|
+
? { providerExecuted: part.providerExecuted }
|
|
274
|
+
: {}),
|
|
275
|
+
...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
|
|
276
|
+
});
|
|
184
277
|
sendSSE(controller, encoder, {
|
|
185
278
|
type: "tool-output-error",
|
|
186
279
|
toolCallId: part.toolCallId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,WAAW,EAEhB,KAAK,aAAa,EAGlB,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAiB/D,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,aAAa,EACb,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC1E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -56,6 +56,20 @@ function isAbortError(error, abortSignal) {
|
|
|
56
56
|
}
|
|
57
57
|
return error instanceof DOMException && error.name === "AbortError";
|
|
58
58
|
}
|
|
59
|
+
function stringifyToolError(error) {
|
|
60
|
+
if (typeof error === "string" && error.length > 0) {
|
|
61
|
+
return error;
|
|
62
|
+
}
|
|
63
|
+
if (error instanceof Error && typeof error.message === "string" && error.message.length > 0) {
|
|
64
|
+
return error.message;
|
|
65
|
+
}
|
|
66
|
+
try {
|
|
67
|
+
return JSON.stringify(error);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return String(error);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
59
73
|
function getSkillActivationRequiredError(toolName) {
|
|
60
74
|
return `Tool "${toolName}" cannot run before load-skill succeeds in the same step. ` +
|
|
61
75
|
`Call "${LOAD_SKILL_TOOL_ID}" first to establish the active skill context.`;
|
|
@@ -491,6 +505,7 @@ export class AgentRuntime {
|
|
|
491
505
|
// Request-scoped skill policy (not class-level mutable state)
|
|
492
506
|
let activeSkillPolicy;
|
|
493
507
|
let finalFinishReason;
|
|
508
|
+
let latestAssistantText = "";
|
|
494
509
|
const allowedRemoteToolNames = getRuntimeAllowedRemoteTools(this.config);
|
|
495
510
|
for (let step = 0; step < maxSteps; step++) {
|
|
496
511
|
throwIfAborted(abortSignal);
|
|
@@ -547,8 +562,29 @@ export class AgentRuntime {
|
|
|
547
562
|
parts: streamParts,
|
|
548
563
|
timestamp: Date.now(),
|
|
549
564
|
};
|
|
565
|
+
latestAssistantText = getTextFromParts(assistantMessage.parts);
|
|
550
566
|
currentMessages.push(assistantMessage);
|
|
551
567
|
await this.memory.add(assistantMessage);
|
|
568
|
+
for (const tr of state.toolResults) {
|
|
569
|
+
if (tr.preliminary) {
|
|
570
|
+
continue;
|
|
571
|
+
}
|
|
572
|
+
const toolResultMessage = {
|
|
573
|
+
id: `tool_${tr.toolCallId}`,
|
|
574
|
+
role: "tool",
|
|
575
|
+
parts: [
|
|
576
|
+
{
|
|
577
|
+
type: "tool-result",
|
|
578
|
+
toolCallId: tr.toolCallId,
|
|
579
|
+
toolName: tr.toolName,
|
|
580
|
+
result: tr.error === undefined ? tr.output : { error: stringifyToolError(tr.error) },
|
|
581
|
+
},
|
|
582
|
+
],
|
|
583
|
+
timestamp: Date.now(),
|
|
584
|
+
};
|
|
585
|
+
currentMessages.push(toolResultMessage);
|
|
586
|
+
await this.memory.add(toolResultMessage);
|
|
587
|
+
}
|
|
552
588
|
if (state.finishReason !== "tool-calls" || !state.toolCalls.size) {
|
|
553
589
|
sendSSE(controller, encoder, { type: "step-end" });
|
|
554
590
|
break;
|
|
@@ -563,6 +599,15 @@ export class AgentRuntime {
|
|
|
563
599
|
const { args, error: argError } = parseToolArgs(tc.arguments);
|
|
564
600
|
const toolCall = { id: tc.id, name: tc.name, args, status: "pending" };
|
|
565
601
|
if (tc.providerExecuted === true) {
|
|
602
|
+
const matchingResult = state.toolResults.find((result) => result.toolCallId === tc.id && result.preliminary !== true);
|
|
603
|
+
if (matchingResult) {
|
|
604
|
+
toolCall.status = matchingResult.error === undefined ? "completed" : "error";
|
|
605
|
+
toolCall.result = matchingResult.output;
|
|
606
|
+
toolCall.error = matchingResult.error === undefined
|
|
607
|
+
? undefined
|
|
608
|
+
: stringifyToolError(matchingResult.error);
|
|
609
|
+
toolCalls.push(toolCall);
|
|
610
|
+
}
|
|
566
611
|
continue;
|
|
567
612
|
}
|
|
568
613
|
if (argError) {
|
|
@@ -636,9 +681,8 @@ export class AgentRuntime {
|
|
|
636
681
|
sendSSE(controller, encoder, { type: "step-end" });
|
|
637
682
|
this.status = "thinking";
|
|
638
683
|
}
|
|
639
|
-
const lastMessage = currentMessages[currentMessages.length - 1];
|
|
640
684
|
return {
|
|
641
|
-
text:
|
|
685
|
+
text: latestAssistantText,
|
|
642
686
|
messages: currentMessages,
|
|
643
687
|
toolCalls,
|
|
644
688
|
status: "completed",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.
|
|
1
|
+
export declare const VERSION = "0.1.140";
|
|
2
2
|
//# sourceMappingURL=version-constant.d.ts.map
|
package/package.json
CHANGED
package/src/deno.js
CHANGED
|
@@ -12,7 +12,9 @@ import type { StreamTextResult, ToolSet } from "ai";
|
|
|
12
12
|
import { sendSSE } from "./sse-utils.js";
|
|
13
13
|
import { isDynamicTool } from "./tool-helpers.js";
|
|
14
14
|
import { serverLogger } from "../../utils/index.js";
|
|
15
|
+
import { isAnyDebugEnabled } from "../../utils/constants/env.js";
|
|
15
16
|
import { setActiveSpanAttributes, withSpan } from "../../observability/tracing/otlp-setup.js";
|
|
17
|
+
import { getHostEnv } from "../../platform/compat/process.js";
|
|
16
18
|
|
|
17
19
|
const logger = serverLogger.component("agent");
|
|
18
20
|
|
|
@@ -24,10 +26,21 @@ export interface StreamingToolCall {
|
|
|
24
26
|
dynamic?: boolean;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
export interface StreamingToolResult {
|
|
30
|
+
toolCallId: string;
|
|
31
|
+
toolName: string;
|
|
32
|
+
output?: unknown;
|
|
33
|
+
error?: unknown;
|
|
34
|
+
providerExecuted?: boolean;
|
|
35
|
+
dynamic?: boolean;
|
|
36
|
+
preliminary?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
export interface AIStreamState {
|
|
28
40
|
accumulatedText: string;
|
|
29
41
|
finishReason: string | null;
|
|
30
42
|
toolCalls: Map<string, StreamingToolCall>;
|
|
43
|
+
toolResults: StreamingToolResult[];
|
|
31
44
|
usage: { promptTokens: number; completionTokens: number; totalTokens: number };
|
|
32
45
|
}
|
|
33
46
|
|
|
@@ -93,6 +106,10 @@ function stringifyToolError(output: unknown): string {
|
|
|
93
106
|
return output;
|
|
94
107
|
}
|
|
95
108
|
|
|
109
|
+
if (output instanceof Error && typeof output.message === "string" && output.message.length > 0) {
|
|
110
|
+
return output.message;
|
|
111
|
+
}
|
|
112
|
+
|
|
96
113
|
try {
|
|
97
114
|
return JSON.stringify(output);
|
|
98
115
|
} catch {
|
|
@@ -100,11 +117,71 @@ function stringifyToolError(output: unknown): string {
|
|
|
100
117
|
}
|
|
101
118
|
}
|
|
102
119
|
|
|
120
|
+
function summarizeDebugValue(value: unknown): unknown {
|
|
121
|
+
if (value instanceof Error) {
|
|
122
|
+
return {
|
|
123
|
+
name: value.name,
|
|
124
|
+
message: value.message,
|
|
125
|
+
stack: value.stack,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (typeof value === "string") {
|
|
130
|
+
return value.length > 500 ? `${value.slice(0, 500)}…` : value;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return value;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function logProviderToolPart(
|
|
137
|
+
partType: "tool-result" | "tool-error",
|
|
138
|
+
part: {
|
|
139
|
+
toolCallId: string;
|
|
140
|
+
toolName: string;
|
|
141
|
+
providerExecuted?: boolean;
|
|
142
|
+
dynamic?: boolean;
|
|
143
|
+
output?: unknown;
|
|
144
|
+
error?: unknown;
|
|
145
|
+
input?: unknown;
|
|
146
|
+
preliminary?: boolean;
|
|
147
|
+
isError?: boolean;
|
|
148
|
+
},
|
|
149
|
+
): void {
|
|
150
|
+
if (!isAnyDebugEnabled({ get: getHostEnv })) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (part.providerExecuted !== true) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (part.toolName !== "web_search" && part.toolName !== "web_fetch") {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
logger.debug("Provider tool stream part observed", {
|
|
163
|
+
partType,
|
|
164
|
+
toolCallId: part.toolCallId,
|
|
165
|
+
toolName: part.toolName,
|
|
166
|
+
providerExecuted: part.providerExecuted,
|
|
167
|
+
dynamic: part.dynamic,
|
|
168
|
+
preliminary: part.preliminary,
|
|
169
|
+
isError: part.isError,
|
|
170
|
+
outputType: typeof part.output,
|
|
171
|
+
errorType: typeof part.error,
|
|
172
|
+
inputType: typeof part.input,
|
|
173
|
+
output: summarizeDebugValue(part.output),
|
|
174
|
+
error: summarizeDebugValue(part.error),
|
|
175
|
+
input: summarizeDebugValue(part.input),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
103
179
|
export function createStreamState(): AIStreamState {
|
|
104
180
|
return {
|
|
105
181
|
accumulatedText: "",
|
|
106
182
|
finishReason: null,
|
|
107
183
|
toolCalls: new Map(),
|
|
184
|
+
toolResults: [],
|
|
108
185
|
usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
|
|
109
186
|
};
|
|
110
187
|
}
|
|
@@ -212,7 +289,26 @@ export function processStream(
|
|
|
212
289
|
|
|
213
290
|
case "tool-result": {
|
|
214
291
|
const isError = "isError" in part && part.isError === true;
|
|
292
|
+
logProviderToolPart("tool-result", {
|
|
293
|
+
toolCallId: part.toolCallId,
|
|
294
|
+
toolName: part.toolName,
|
|
295
|
+
providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
|
|
296
|
+
dynamic: "dynamic" in part ? part.dynamic : undefined,
|
|
297
|
+
output: part.output,
|
|
298
|
+
input: "input" in part ? part.input : undefined,
|
|
299
|
+
preliminary: "preliminary" in part ? part.preliminary : undefined,
|
|
300
|
+
isError,
|
|
301
|
+
});
|
|
215
302
|
if (isError) {
|
|
303
|
+
state.toolResults.push({
|
|
304
|
+
toolCallId: part.toolCallId,
|
|
305
|
+
toolName: part.toolName,
|
|
306
|
+
error: "output" in part ? part.output : undefined,
|
|
307
|
+
...("providerExecuted" in part && part.providerExecuted !== undefined
|
|
308
|
+
? { providerExecuted: part.providerExecuted }
|
|
309
|
+
: {}),
|
|
310
|
+
...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
|
|
311
|
+
});
|
|
216
312
|
sendSSE(controller, encoder, {
|
|
217
313
|
type: "tool-output-error",
|
|
218
314
|
toolCallId: part.toolCallId,
|
|
@@ -225,6 +321,18 @@ export function processStream(
|
|
|
225
321
|
break;
|
|
226
322
|
}
|
|
227
323
|
|
|
324
|
+
state.toolResults.push({
|
|
325
|
+
toolCallId: part.toolCallId,
|
|
326
|
+
toolName: part.toolName,
|
|
327
|
+
output: part.output,
|
|
328
|
+
...("providerExecuted" in part && part.providerExecuted !== undefined
|
|
329
|
+
? { providerExecuted: part.providerExecuted }
|
|
330
|
+
: {}),
|
|
331
|
+
...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
|
|
332
|
+
...("preliminary" in part && part.preliminary !== undefined
|
|
333
|
+
? { preliminary: part.preliminary }
|
|
334
|
+
: {}),
|
|
335
|
+
});
|
|
228
336
|
sendSSE(controller, encoder, {
|
|
229
337
|
type: "tool-output-available",
|
|
230
338
|
toolCallId: part.toolCallId,
|
|
@@ -241,6 +349,23 @@ export function processStream(
|
|
|
241
349
|
}
|
|
242
350
|
|
|
243
351
|
case "tool-error": {
|
|
352
|
+
logProviderToolPart("tool-error", {
|
|
353
|
+
toolCallId: part.toolCallId,
|
|
354
|
+
toolName: part.toolName,
|
|
355
|
+
providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
|
|
356
|
+
dynamic: "dynamic" in part ? part.dynamic : undefined,
|
|
357
|
+
error: part.error,
|
|
358
|
+
input: "input" in part ? part.input : undefined,
|
|
359
|
+
});
|
|
360
|
+
state.toolResults.push({
|
|
361
|
+
toolCallId: part.toolCallId,
|
|
362
|
+
toolName: part.toolName,
|
|
363
|
+
error: part.error,
|
|
364
|
+
...("providerExecuted" in part && part.providerExecuted !== undefined
|
|
365
|
+
? { providerExecuted: part.providerExecuted }
|
|
366
|
+
: {}),
|
|
367
|
+
...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
|
|
368
|
+
});
|
|
244
369
|
sendSSE(controller, encoder, {
|
|
245
370
|
type: "tool-output-error",
|
|
246
371
|
toolCallId: part.toolCallId,
|
|
@@ -107,6 +107,22 @@ function isAbortError(error: unknown, abortSignal?: AbortSignal): boolean {
|
|
|
107
107
|
return error instanceof DOMException && error.name === "AbortError";
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function stringifyToolError(error: unknown): string {
|
|
111
|
+
if (typeof error === "string" && error.length > 0) {
|
|
112
|
+
return error;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (error instanceof Error && typeof error.message === "string" && error.message.length > 0) {
|
|
116
|
+
return error.message;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
return JSON.stringify(error);
|
|
121
|
+
} catch {
|
|
122
|
+
return String(error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
110
126
|
function getSkillActivationRequiredError(toolName: string): string {
|
|
111
127
|
return `Tool "${toolName}" cannot run before load-skill succeeds in the same step. ` +
|
|
112
128
|
`Call "${LOAD_SKILL_TOOL_ID}" first to establish the active skill context.`;
|
|
@@ -686,6 +702,7 @@ export class AgentRuntime {
|
|
|
686
702
|
// Request-scoped skill policy (not class-level mutable state)
|
|
687
703
|
let activeSkillPolicy: string[] | undefined;
|
|
688
704
|
let finalFinishReason: string | undefined;
|
|
705
|
+
let latestAssistantText = "";
|
|
689
706
|
const allowedRemoteToolNames = getRuntimeAllowedRemoteTools(this.config);
|
|
690
707
|
|
|
691
708
|
for (let step = 0; step < maxSteps; step++) {
|
|
@@ -749,9 +766,32 @@ export class AgentRuntime {
|
|
|
749
766
|
parts: streamParts,
|
|
750
767
|
timestamp: Date.now(),
|
|
751
768
|
};
|
|
769
|
+
latestAssistantText = getTextFromParts(assistantMessage.parts);
|
|
752
770
|
currentMessages.push(assistantMessage);
|
|
753
771
|
await this.memory.add(assistantMessage);
|
|
754
772
|
|
|
773
|
+
for (const tr of state.toolResults) {
|
|
774
|
+
if (tr.preliminary) {
|
|
775
|
+
continue;
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
const toolResultMessage: Message = {
|
|
779
|
+
id: `tool_${tr.toolCallId}`,
|
|
780
|
+
role: "tool",
|
|
781
|
+
parts: [
|
|
782
|
+
{
|
|
783
|
+
type: "tool-result",
|
|
784
|
+
toolCallId: tr.toolCallId,
|
|
785
|
+
toolName: tr.toolName,
|
|
786
|
+
result: tr.error === undefined ? tr.output : { error: stringifyToolError(tr.error) },
|
|
787
|
+
},
|
|
788
|
+
],
|
|
789
|
+
timestamp: Date.now(),
|
|
790
|
+
};
|
|
791
|
+
currentMessages.push(toolResultMessage);
|
|
792
|
+
await this.memory.add(toolResultMessage);
|
|
793
|
+
}
|
|
794
|
+
|
|
755
795
|
if (state.finishReason !== "tool-calls" || !state.toolCalls.size) {
|
|
756
796
|
sendSSE(controller, encoder, { type: "step-end" });
|
|
757
797
|
break;
|
|
@@ -769,6 +809,18 @@ export class AgentRuntime {
|
|
|
769
809
|
const toolCall: ToolCall = { id: tc.id, name: tc.name, args, status: "pending" };
|
|
770
810
|
|
|
771
811
|
if (tc.providerExecuted === true) {
|
|
812
|
+
const matchingResult = state.toolResults.find((result) =>
|
|
813
|
+
result.toolCallId === tc.id && result.preliminary !== true
|
|
814
|
+
);
|
|
815
|
+
|
|
816
|
+
if (matchingResult) {
|
|
817
|
+
toolCall.status = matchingResult.error === undefined ? "completed" : "error";
|
|
818
|
+
toolCall.result = matchingResult.output;
|
|
819
|
+
toolCall.error = matchingResult.error === undefined
|
|
820
|
+
? undefined
|
|
821
|
+
: stringifyToolError(matchingResult.error);
|
|
822
|
+
toolCalls.push(toolCall);
|
|
823
|
+
}
|
|
772
824
|
continue;
|
|
773
825
|
}
|
|
774
826
|
|
|
@@ -881,9 +933,8 @@ export class AgentRuntime {
|
|
|
881
933
|
this.status = "thinking";
|
|
882
934
|
}
|
|
883
935
|
|
|
884
|
-
const lastMessage = currentMessages[currentMessages.length - 1];
|
|
885
936
|
return {
|
|
886
|
-
text:
|
|
937
|
+
text: latestAssistantText,
|
|
887
938
|
messages: currentMessages,
|
|
888
939
|
toolCalls,
|
|
889
940
|
status: "completed",
|