veryfront 0.1.137 → 0.1.139

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.137",
3
+ "version": "0.1.139",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -12,11 +12,23 @@ export interface StreamingToolCall {
12
12
  id: string;
13
13
  name: string;
14
14
  arguments: string;
15
+ providerExecuted?: boolean;
16
+ dynamic?: boolean;
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;
15
26
  }
16
27
  export interface AIStreamState {
17
28
  accumulatedText: string;
18
29
  finishReason: string | null;
19
30
  toolCalls: Map<string, StreamingToolCall>;
31
+ toolResults: StreamingToolResult[];
20
32
  usage: {
21
33
  promptTokens: number;
22
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;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,CAuIf"}
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,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;AAkED,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,CAoMf"}
@@ -53,6 +53,9 @@ function stringifyToolError(output) {
53
53
  if (typeof output === "string" && output.length > 0) {
54
54
  return output;
55
55
  }
56
+ if (output instanceof Error && typeof output.message === "string" && output.message.length > 0) {
57
+ return output.message;
58
+ }
56
59
  try {
57
60
  return JSON.stringify(output);
58
61
  }
@@ -65,6 +68,7 @@ export function createStreamState() {
65
68
  accumulatedText: "",
66
69
  finishReason: null,
67
70
  toolCalls: new Map(),
71
+ toolResults: [],
68
72
  usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
69
73
  };
70
74
  }
@@ -102,6 +106,8 @@ export function processStream(result, state, controller, encoder, textPartId, ca
102
106
  id: toolId,
103
107
  name: part.toolName,
104
108
  arguments: "",
109
+ providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
110
+ dynamic: "dynamic" in part ? part.dynamic : undefined,
105
111
  });
106
112
  const dynamic = isDynamicTool(part.toolName);
107
113
  sendSSE(controller, encoder, {
@@ -133,6 +139,8 @@ export function processStream(result, state, controller, encoder, textPartId, ca
133
139
  id: toolId,
134
140
  name: part.toolName,
135
141
  arguments: inputStr,
142
+ providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
143
+ dynamic: "dynamic" in part ? part.dynamic : undefined,
136
144
  });
137
145
  const dynamic = isDynamicTool(part.toolName);
138
146
  const inputObj = normalizeToolInputObject(part.input);
@@ -141,6 +149,9 @@ export function processStream(result, state, controller, encoder, textPartId, ca
141
149
  toolCallId: toolId,
142
150
  toolName: part.toolName,
143
151
  input: inputObj,
152
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
153
+ ? { providerExecuted: part.providerExecuted }
154
+ : {}),
144
155
  ...(dynamic ? { dynamic: true } : {}),
145
156
  });
146
157
  break;
@@ -148,17 +159,70 @@ export function processStream(result, state, controller, encoder, textPartId, ca
148
159
  case "tool-result": {
149
160
  const isError = "isError" in part && part.isError === true;
150
161
  if (isError) {
162
+ state.toolResults.push({
163
+ toolCallId: part.toolCallId,
164
+ toolName: part.toolName,
165
+ error: "output" in part ? part.output : undefined,
166
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
167
+ ? { providerExecuted: part.providerExecuted }
168
+ : {}),
169
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
170
+ });
151
171
  sendSSE(controller, encoder, {
152
172
  type: "tool-output-error",
153
173
  toolCallId: part.toolCallId,
154
- errorText: stringifyToolError(part.output),
174
+ errorText: stringifyToolError("output" in part ? part.output : undefined),
175
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
176
+ ? { providerExecuted: part.providerExecuted }
177
+ : {}),
178
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
155
179
  });
156
180
  break;
157
181
  }
182
+ state.toolResults.push({
183
+ toolCallId: part.toolCallId,
184
+ toolName: part.toolName,
185
+ output: part.output,
186
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
187
+ ? { providerExecuted: part.providerExecuted }
188
+ : {}),
189
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
190
+ ...("preliminary" in part && part.preliminary !== undefined
191
+ ? { preliminary: part.preliminary }
192
+ : {}),
193
+ });
158
194
  sendSSE(controller, encoder, {
159
195
  type: "tool-output-available",
160
196
  toolCallId: part.toolCallId,
161
197
  output: part.output,
198
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
199
+ ? { providerExecuted: part.providerExecuted }
200
+ : {}),
201
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
202
+ ...("preliminary" in part && part.preliminary !== undefined
203
+ ? { preliminary: part.preliminary }
204
+ : {}),
205
+ });
206
+ break;
207
+ }
208
+ case "tool-error": {
209
+ state.toolResults.push({
210
+ toolCallId: part.toolCallId,
211
+ toolName: part.toolName,
212
+ error: part.error,
213
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
214
+ ? { providerExecuted: part.providerExecuted }
215
+ : {}),
216
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
217
+ });
218
+ sendSSE(controller, encoder, {
219
+ type: "tool-output-error",
220
+ toolCallId: part.toolCallId,
221
+ errorText: stringifyToolError(part.error),
222
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
223
+ ? { providerExecuted: part.providerExecuted }
224
+ : {}),
225
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
162
226
  });
163
227
  break;
164
228
  }
@@ -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;
@@ -562,6 +598,18 @@ export class AgentRuntime {
562
598
  throwIfAborted(abortSignal);
563
599
  const { args, error: argError } = parseToolArgs(tc.arguments);
564
600
  const toolCall = { id: tc.id, name: tc.name, args, status: "pending" };
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
+ }
611
+ continue;
612
+ }
565
613
  if (argError) {
566
614
  logger.warn("Invalid streamed tool arguments", {
567
615
  toolCallId: tc.id,
@@ -633,9 +681,8 @@ export class AgentRuntime {
633
681
  sendSSE(controller, encoder, { type: "step-end" });
634
682
  this.status = "thinking";
635
683
  }
636
- const lastMessage = currentMessages[currentMessages.length - 1];
637
684
  return {
638
- text: lastMessage ? getTextFromParts(lastMessage.parts) : "",
685
+ text: latestAssistantText,
639
686
  messages: currentMessages,
640
687
  toolCalls,
641
688
  status: "completed",
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.137";
1
+ export declare const VERSION = "0.1.139";
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.137";
3
+ export const VERSION = "0.1.139";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.137",
3
+ "version": "0.1.139",
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.137",
3
+ "version": "0.1.139",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -20,12 +20,25 @@ export interface StreamingToolCall {
20
20
  id: string;
21
21
  name: string;
22
22
  arguments: string;
23
+ providerExecuted?: boolean;
24
+ dynamic?: boolean;
25
+ }
26
+
27
+ export interface StreamingToolResult {
28
+ toolCallId: string;
29
+ toolName: string;
30
+ output?: unknown;
31
+ error?: unknown;
32
+ providerExecuted?: boolean;
33
+ dynamic?: boolean;
34
+ preliminary?: boolean;
23
35
  }
24
36
 
25
37
  export interface AIStreamState {
26
38
  accumulatedText: string;
27
39
  finishReason: string | null;
28
40
  toolCalls: Map<string, StreamingToolCall>;
41
+ toolResults: StreamingToolResult[];
29
42
  usage: { promptTokens: number; completionTokens: number; totalTokens: number };
30
43
  }
31
44
 
@@ -91,6 +104,10 @@ function stringifyToolError(output: unknown): string {
91
104
  return output;
92
105
  }
93
106
 
107
+ if (output instanceof Error && typeof output.message === "string" && output.message.length > 0) {
108
+ return output.message;
109
+ }
110
+
94
111
  try {
95
112
  return JSON.stringify(output);
96
113
  } catch {
@@ -103,6 +120,7 @@ export function createStreamState(): AIStreamState {
103
120
  accumulatedText: "",
104
121
  finishReason: null,
105
122
  toolCalls: new Map(),
123
+ toolResults: [],
106
124
  usage: { promptTokens: 0, completionTokens: 0, totalTokens: 0 },
107
125
  };
108
126
  }
@@ -153,6 +171,8 @@ export function processStream(
153
171
  id: toolId,
154
172
  name: part.toolName,
155
173
  arguments: "",
174
+ providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
175
+ dynamic: "dynamic" in part ? part.dynamic : undefined,
156
176
  });
157
177
 
158
178
  const dynamic = isDynamicTool(part.toolName);
@@ -187,6 +207,8 @@ export function processStream(
187
207
  id: toolId,
188
208
  name: part.toolName,
189
209
  arguments: inputStr,
210
+ providerExecuted: "providerExecuted" in part ? part.providerExecuted : undefined,
211
+ dynamic: "dynamic" in part ? part.dynamic : undefined,
190
212
  });
191
213
 
192
214
  const dynamic = isDynamicTool(part.toolName);
@@ -196,6 +218,9 @@ export function processStream(
196
218
  toolCallId: toolId,
197
219
  toolName: part.toolName,
198
220
  input: inputObj,
221
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
222
+ ? { providerExecuted: part.providerExecuted }
223
+ : {}),
199
224
  ...(dynamic ? { dynamic: true } : {}),
200
225
  });
201
226
  break;
@@ -204,18 +229,72 @@ export function processStream(
204
229
  case "tool-result": {
205
230
  const isError = "isError" in part && part.isError === true;
206
231
  if (isError) {
232
+ state.toolResults.push({
233
+ toolCallId: part.toolCallId,
234
+ toolName: part.toolName,
235
+ error: "output" in part ? part.output : undefined,
236
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
237
+ ? { providerExecuted: part.providerExecuted }
238
+ : {}),
239
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
240
+ });
207
241
  sendSSE(controller, encoder, {
208
242
  type: "tool-output-error",
209
243
  toolCallId: part.toolCallId,
210
- errorText: stringifyToolError(part.output),
244
+ errorText: stringifyToolError("output" in part ? part.output : undefined),
245
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
246
+ ? { providerExecuted: part.providerExecuted }
247
+ : {}),
248
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
211
249
  });
212
250
  break;
213
251
  }
214
252
 
253
+ state.toolResults.push({
254
+ toolCallId: part.toolCallId,
255
+ toolName: part.toolName,
256
+ output: part.output,
257
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
258
+ ? { providerExecuted: part.providerExecuted }
259
+ : {}),
260
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
261
+ ...("preliminary" in part && part.preliminary !== undefined
262
+ ? { preliminary: part.preliminary }
263
+ : {}),
264
+ });
215
265
  sendSSE(controller, encoder, {
216
266
  type: "tool-output-available",
217
267
  toolCallId: part.toolCallId,
218
268
  output: part.output,
269
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
270
+ ? { providerExecuted: part.providerExecuted }
271
+ : {}),
272
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
273
+ ...("preliminary" in part && part.preliminary !== undefined
274
+ ? { preliminary: part.preliminary }
275
+ : {}),
276
+ });
277
+ break;
278
+ }
279
+
280
+ case "tool-error": {
281
+ state.toolResults.push({
282
+ toolCallId: part.toolCallId,
283
+ toolName: part.toolName,
284
+ error: part.error,
285
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
286
+ ? { providerExecuted: part.providerExecuted }
287
+ : {}),
288
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
289
+ });
290
+ sendSSE(controller, encoder, {
291
+ type: "tool-output-error",
292
+ toolCallId: part.toolCallId,
293
+ errorText: stringifyToolError(part.error),
294
+ ...("providerExecuted" in part && part.providerExecuted !== undefined
295
+ ? { providerExecuted: part.providerExecuted }
296
+ : {}),
297
+ ...("dynamic" in part && part.dynamic ? { dynamic: true } : {}),
219
298
  });
220
299
  break;
221
300
  }
@@ -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;
@@ -768,6 +808,22 @@ export class AgentRuntime {
768
808
  const { args, error: argError } = parseToolArgs(tc.arguments);
769
809
  const toolCall: ToolCall = { id: tc.id, name: tc.name, args, status: "pending" };
770
810
 
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
+ }
824
+ continue;
825
+ }
826
+
771
827
  if (argError) {
772
828
  logger.warn("Invalid streamed tool arguments", {
773
829
  toolCallId: tc.id,
@@ -877,9 +933,8 @@ export class AgentRuntime {
877
933
  this.status = "thinking";
878
934
  }
879
935
 
880
- const lastMessage = currentMessages[currentMessages.length - 1];
881
936
  return {
882
- text: lastMessage ? getTextFromParts(lastMessage.parts) : "",
937
+ text: latestAssistantText,
883
938
  messages: currentMessages,
884
939
  toolCalls,
885
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.137";
3
+ export const VERSION = "0.1.139";