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 CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.138",
3
+ "version": "0.1.140",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -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;AAQpD,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,aAAa;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAC1C,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;AA8DD,wBAAgB,iBAAiB,IAAI,aAAa,CAOjD;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,CAsKf"}
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":"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"}
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: lastMessage ? getTextFromParts(lastMessage.parts) : "",
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.138";
1
+ export declare const VERSION = "0.1.140";
2
2
  //# sourceMappingURL=version-constant.d.ts.map
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.138";
3
+ export const VERSION = "0.1.140";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.138",
3
+ "version": "0.1.140",
4
4
  "description": "The simplest way to build AI-powered apps",
5
5
  "keywords": [
6
6
  "react",
package/src/deno.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export default {
2
2
  "name": "veryfront",
3
- "version": "0.1.138",
3
+ "version": "0.1.140",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -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: lastMessage ? getTextFromParts(lastMessage.parts) : "",
937
+ text: latestAssistantText,
887
938
  messages: currentMessages,
888
939
  toolCalls,
889
940
  status: "completed",
@@ -1,3 +1,3 @@
1
1
  // Keep in sync with deno.json version.
2
2
  // scripts/release.ts updates this constant during releases.
3
- export const VERSION = "0.1.138";
3
+ export const VERSION = "0.1.140";