veryfront 0.1.199 → 0.1.200

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.199",
3
+ "version": "0.1.200",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -1 +1 @@
1
- {"version":3,"file":"ag-ui-browser-encoder.d.ts","sourceRoot":"","sources":["../../../src/src/agent/ag-ui-browser-encoder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,8BAA8B,CAAC;CAC1C;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wBAAgB,6BAA6B,IAAI,uBAAuB,CAYvE;AAiMD,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,uBAAuB,EAC9B,KAAK,EAAE,sBAAsB,GAC5B,uBAAuB,EAAE,CAoJ3B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,uBAAuB,EAAE,CAmC3B"}
1
+ {"version":3,"file":"ag-ui-browser-encoder.d.ts","sourceRoot":"","sources":["../../../src/src/agent/ag-ui-browser-encoder.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,OAAO,CAAC;IAClB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,8BAA8B,CAAC;CAC1C;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,wBAAgB,6BAA6B,IAAI,uBAAuB,CAYvE;AAuND,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,uBAAuB,EAC9B,KAAK,EAAE,sBAAsB,GAC5B,uBAAuB,EAAE,CAyM3B;AAED,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,uBAAuB,EAC9B,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,uBAAuB,EAAE,CA8B3B"}
@@ -153,6 +153,24 @@ function createTextEvent(messageId, type, delta = "") {
153
153
  : { messageId },
154
154
  };
155
155
  }
156
+ function closeOpenTextEvent(state) {
157
+ if (!state.textOpen) {
158
+ return [];
159
+ }
160
+ state.textOpen = false;
161
+ return [createTextEvent(getMessageId(state, { type: "text-end" }), "TextMessageEnd")];
162
+ }
163
+ function closeOpenReasoningEvent(state) {
164
+ if (state.reasoningMessageId === null) {
165
+ return [];
166
+ }
167
+ const messageId = state.reasoningMessageId;
168
+ state.reasoningMessageId = null;
169
+ return [{
170
+ event: "ReasoningMessageEnd",
171
+ payload: { messageId },
172
+ }];
173
+ }
156
174
  export function mapRuntimeStreamEventToAgUiBrowserEvents(state, event) {
157
175
  if (event.type.startsWith("data-")) {
158
176
  const name = event.type.slice("data-".length);
@@ -167,24 +185,26 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(state, event) {
167
185
  getMessageId(state, event);
168
186
  return [];
169
187
  case "text-start": {
188
+ const events = closeOpenReasoningEvent(state);
170
189
  if (state.textOpen)
171
190
  return [];
172
191
  const messageId = getMessageId(state, event);
173
192
  state.textOpen = true;
174
193
  state.sawVisibleOutput = true;
175
- return [createTextEvent(messageId, "TextMessageStart")];
194
+ events.push(createTextEvent(messageId, "TextMessageStart"));
195
+ return events;
176
196
  }
177
197
  case "text-delta": {
198
+ const events = closeOpenReasoningEvent(state);
178
199
  const messageId = getMessageId(state, event);
179
200
  state.sawVisibleOutput = true;
180
201
  if (!state.textOpen) {
181
202
  state.textOpen = true;
182
- return [
183
- createTextEvent(messageId, "TextMessageStart"),
184
- createTextEvent(messageId, "TextMessageContent", typeof event.delta === "string" ? event.delta : ""),
185
- ];
203
+ events.push(createTextEvent(messageId, "TextMessageStart"), createTextEvent(messageId, "TextMessageContent", typeof event.delta === "string" ? event.delta : ""));
204
+ return events;
186
205
  }
187
- return [createTextEvent(messageId, "TextMessageContent", typeof event.delta === "string" ? event.delta : "")];
206
+ events.push(createTextEvent(messageId, "TextMessageContent", typeof event.delta === "string" ? event.delta : ""));
207
+ return events;
188
208
  }
189
209
  case "text-end": {
190
210
  if (!state.textOpen)
@@ -192,26 +212,42 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(state, event) {
192
212
  state.textOpen = false;
193
213
  return [createTextEvent(getMessageId(state, event), "TextMessageEnd")];
194
214
  }
195
- case "reasoning-start":
215
+ case "reasoning-start": {
216
+ const events = closeOpenTextEvent(state);
217
+ events.push(...closeOpenReasoningEvent(state));
196
218
  state.sawVisibleOutput = true;
197
- return [createReasoningEvent(state, event, "ReasoningMessageStart")];
198
- case "reasoning-delta":
219
+ events.push(createReasoningEvent(state, event, "ReasoningMessageStart"));
220
+ return events;
221
+ }
222
+ case "reasoning-delta": {
223
+ const events = closeOpenTextEvent(state);
199
224
  state.sawVisibleOutput = true;
200
- return [createReasoningEvent(state, event, "ReasoningMessageContent")];
225
+ if (state.reasoningMessageId === null) {
226
+ events.push(createReasoningEvent(state, event, "ReasoningMessageStart"));
227
+ }
228
+ events.push(createReasoningEvent(state, event, "ReasoningMessageContent"));
229
+ return events;
230
+ }
201
231
  case "reasoning-end": {
202
232
  const reasoningEvent = createReasoningEvent(state, event, "ReasoningMessageEnd");
203
233
  state.reasoningMessageId = null;
204
234
  return [reasoningEvent];
205
235
  }
206
- case "tool-input-start":
236
+ case "tool-input-start": {
237
+ const events = [
238
+ ...closeOpenTextEvent(state),
239
+ ...closeOpenReasoningEvent(state),
240
+ ];
207
241
  state.sawVisibleOutput = true;
208
- return [{
209
- event: "ToolCallStart",
210
- payload: {
211
- toolCallId: event.toolCallId,
212
- toolCallName: event.toolName,
213
- },
214
- }];
242
+ events.push({
243
+ event: "ToolCallStart",
244
+ payload: {
245
+ toolCallId: event.toolCallId,
246
+ toolCallName: event.toolName,
247
+ },
248
+ });
249
+ return events;
250
+ }
215
251
  case "tool-input-delta":
216
252
  state.sawVisibleOutput = true;
217
253
  if (typeof event.toolCallId === "string") {
@@ -226,11 +262,19 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(state, event) {
226
262
  }];
227
263
  case "tool-input-available": {
228
264
  state.sawVisibleOutput = true;
229
- return completeToolInput(state, event);
265
+ return [
266
+ ...closeOpenTextEvent(state),
267
+ ...closeOpenReasoningEvent(state),
268
+ ...completeToolInput(state, event),
269
+ ];
230
270
  }
231
271
  case "tool-input-error": {
232
272
  state.sawVisibleOutput = true;
233
- const events = completeToolInput(state, event);
273
+ const events = [
274
+ ...closeOpenTextEvent(state),
275
+ ...closeOpenReasoningEvent(state),
276
+ ...completeToolInput(state, event),
277
+ ];
234
278
  events.push({
235
279
  event: "ToolCallResult",
236
280
  payload: {
@@ -245,32 +289,56 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(state, event) {
245
289
  }
246
290
  case "tool-output-available":
247
291
  state.sawVisibleOutput = true;
248
- return [createToolResultEvent(event.toolCallId, event.output)];
292
+ return [
293
+ ...closeOpenTextEvent(state),
294
+ ...closeOpenReasoningEvent(state),
295
+ createToolResultEvent(event.toolCallId, event.output),
296
+ ];
249
297
  case "tool-output-error":
250
298
  state.sawVisibleOutput = true;
251
- return [createToolResultEvent(event.toolCallId, { error: event.errorText }, true)];
299
+ return [
300
+ ...closeOpenTextEvent(state),
301
+ ...closeOpenReasoningEvent(state),
302
+ createToolResultEvent(event.toolCallId, { error: event.errorText }, true),
303
+ ];
252
304
  case "tool-output-denied":
253
305
  state.sawVisibleOutput = true;
254
- return [createToolResultEvent(event.toolCallId, { error: "Tool output denied" }, true)];
306
+ return [
307
+ ...closeOpenTextEvent(state),
308
+ ...closeOpenReasoningEvent(state),
309
+ createToolResultEvent(event.toolCallId, { error: "Tool output denied" }, true),
310
+ ];
255
311
  case "step-start":
256
312
  case "start-step":
257
313
  state.sawVisibleOutput = true;
258
- return [createStepEvent(state, "StepStarted")];
314
+ return [
315
+ ...closeOpenTextEvent(state),
316
+ ...closeOpenReasoningEvent(state),
317
+ createStepEvent(state, "StepStarted"),
318
+ ];
259
319
  case "step-end":
260
320
  case "finish-step":
261
321
  state.sawVisibleOutput = true;
262
- return [createStepEvent(state, "StepFinished")];
322
+ return [
323
+ ...closeOpenTextEvent(state),
324
+ ...closeOpenReasoningEvent(state),
325
+ createStepEvent(state, "StepFinished"),
326
+ ];
263
327
  case "data":
264
328
  applyDataMetadata(state, event);
265
329
  return [];
266
330
  case "error":
267
331
  state.sawTerminalError = true;
268
- return [{
332
+ return [
333
+ ...closeOpenTextEvent(state),
334
+ ...closeOpenReasoningEvent(state),
335
+ {
269
336
  event: "RunError",
270
337
  payload: {
271
338
  message: typeof event.error === "string" ? event.error : "Agent run failed",
272
339
  },
273
- }];
340
+ },
341
+ ];
274
342
  default:
275
343
  return [];
276
344
  }
@@ -291,13 +359,8 @@ export function finalizeAgUiBrowserEvents(state, response) {
291
359
  }];
292
360
  }
293
361
  const events = [];
294
- if (state.textOpen) {
295
- state.textOpen = false;
296
- events.push({
297
- event: "TextMessageEnd",
298
- payload: { messageId: getMessageId(state, { type: "text-end" }) },
299
- });
300
- }
362
+ events.push(...closeOpenTextEvent(state));
363
+ events.push(...closeOpenReasoningEvent(state));
301
364
  events.push({
302
365
  event: "RunFinished",
303
366
  payload: {
@@ -12,6 +12,7 @@ export interface StreamingToolCall {
12
12
  id: string;
13
13
  name: string;
14
14
  arguments: string;
15
+ inputAvailable?: boolean;
15
16
  providerExecuted?: boolean;
16
17
  dynamic?: boolean;
17
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"chat-stream-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/chat-stream-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAqB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAYtF,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,eAAe;IAC9B,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,mBAAmB;IAClC,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;AAyED,wBAAgB,iBAAiB,IAAI,eAAe,CAQnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,+BAA+B,EAC3C,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,CAAC,EAAE,mBAAmB,EAC/B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,IAAI,CAAC,CAqPf"}
1
+ {"version":3,"file":"chat-stream-handler.d.ts","sourceRoot":"","sources":["../../../../src/src/agent/runtime/chat-stream-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAqB,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAYtF,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,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,eAAe;IAC9B,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,mBAAmB;IAClC,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;AAyED,wBAAgB,iBAAiB,IAAI,eAAe,CAQnD;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,mBAAmB,EAC3B,KAAK,EAAE,eAAe,EACtB,UAAU,EAAE,+BAA+B,EAC3C,OAAO,EAAE,WAAW,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,CAAC,EAAE,mBAAmB,EAC/B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,IAAI,CAAC,CAuZf"}
@@ -86,6 +86,114 @@ export function createStreamState() {
86
86
  export function processStream(result, state, controller, encoder, textPartId, callbacks, abortSignal) {
87
87
  return withSpan("agent.runtime.processStream", async () => {
88
88
  let eventCount = 0;
89
+ let textOpen = false;
90
+ let activeReasoningId = null;
91
+ const normalizeReasoningId = (part) => typeof part.id === "string" && part.id.length > 0 ? part.id : "reasoning";
92
+ const openTextSegment = () => {
93
+ if (textOpen) {
94
+ return;
95
+ }
96
+ textOpen = true;
97
+ sendSSE(controller, encoder, {
98
+ type: "text-start",
99
+ id: textPartId,
100
+ });
101
+ };
102
+ const closeTextSegment = () => {
103
+ if (!textOpen) {
104
+ return;
105
+ }
106
+ textOpen = false;
107
+ sendSSE(controller, encoder, {
108
+ type: "text-end",
109
+ id: textPartId,
110
+ });
111
+ };
112
+ const openReasoningSegment = (reasoningId) => {
113
+ if (activeReasoningId === reasoningId) {
114
+ return;
115
+ }
116
+ if (activeReasoningId !== null) {
117
+ sendSSE(controller, encoder, {
118
+ type: "reasoning-end",
119
+ id: activeReasoningId,
120
+ });
121
+ }
122
+ activeReasoningId = reasoningId;
123
+ sendSSE(controller, encoder, {
124
+ type: "reasoning-start",
125
+ id: reasoningId,
126
+ });
127
+ };
128
+ const closeReasoningSegment = () => {
129
+ if (activeReasoningId === null) {
130
+ return;
131
+ }
132
+ sendSSE(controller, encoder, {
133
+ type: "reasoning-end",
134
+ id: activeReasoningId,
135
+ });
136
+ activeReasoningId = null;
137
+ };
138
+ const ensureToolLifecycle = (part) => {
139
+ const dynamic = part.dynamic ?? isDynamicTool(part.toolName);
140
+ const existing = state.toolCalls.get(part.toolCallId);
141
+ if (!existing) {
142
+ const normalizedInput = parseToolInputObject(part.input);
143
+ state.toolCalls.set(part.toolCallId, {
144
+ id: part.toolCallId,
145
+ name: part.toolName,
146
+ arguments: normalizeToolInputString(part.input),
147
+ inputAvailable: true,
148
+ ...(part.providerExecuted !== undefined
149
+ ? { providerExecuted: part.providerExecuted }
150
+ : {}),
151
+ ...(dynamic ? { dynamic: true } : {}),
152
+ });
153
+ sendSSE(controller, encoder, {
154
+ type: "tool-input-start",
155
+ toolCallId: part.toolCallId,
156
+ toolName: part.toolName,
157
+ ...(dynamic ? { dynamic: true } : {}),
158
+ });
159
+ sendSSE(controller, encoder, {
160
+ type: "tool-input-available",
161
+ toolCallId: part.toolCallId,
162
+ toolName: part.toolName,
163
+ input: normalizedInput,
164
+ ...(part.providerExecuted !== undefined
165
+ ? { providerExecuted: part.providerExecuted }
166
+ : {}),
167
+ ...(dynamic ? { dynamic: true } : {}),
168
+ });
169
+ return;
170
+ }
171
+ if (existing.inputAvailable) {
172
+ return;
173
+ }
174
+ const resolvedArguments = part.input !== undefined
175
+ ? mergeToolCallInput(existing.arguments, normalizeToolInputString(part.input))
176
+ : existing.arguments;
177
+ const resolvedInput = parseToolInputObject(resolvedArguments);
178
+ existing.arguments = resolvedArguments;
179
+ existing.inputAvailable = true;
180
+ if (part.providerExecuted !== undefined) {
181
+ existing.providerExecuted = part.providerExecuted;
182
+ }
183
+ if (dynamic) {
184
+ existing.dynamic = true;
185
+ }
186
+ sendSSE(controller, encoder, {
187
+ type: "tool-input-available",
188
+ toolCallId: part.toolCallId,
189
+ toolName: existing.name,
190
+ input: resolvedInput,
191
+ ...(existing.providerExecuted !== undefined
192
+ ? { providerExecuted: existing.providerExecuted }
193
+ : {}),
194
+ ...(existing.dynamic ? { dynamic: true } : {}),
195
+ });
196
+ };
89
197
  throwIfAborted(abortSignal);
90
198
  for await (const part of result.fullStream) {
91
199
  throwIfAborted(abortSignal);
@@ -96,6 +204,8 @@ export function processStream(result, state, controller, encoder, textPartId, ca
96
204
  const typedPart = part;
97
205
  switch (typedPart.type) {
98
206
  case "text-delta": {
207
+ closeReasoningSegment();
208
+ openTextSegment();
99
209
  state.accumulatedText += typedPart.text;
100
210
  sendSSE(controller, encoder, {
101
211
  type: "text-delta",
@@ -106,33 +216,37 @@ export function processStream(result, state, controller, encoder, textPartId, ca
106
216
  break;
107
217
  }
108
218
  case "reasoning-start": {
109
- sendSSE(controller, encoder, {
110
- type: "reasoning-start",
111
- id: typeof typedPart.id === "string" ? typedPart.id : "reasoning",
112
- });
219
+ closeTextSegment();
220
+ openReasoningSegment(normalizeReasoningId(typedPart));
113
221
  break;
114
222
  }
115
223
  case "reasoning-delta": {
224
+ closeTextSegment();
225
+ openReasoningSegment(normalizeReasoningId(typedPart));
116
226
  sendSSE(controller, encoder, {
117
227
  type: "reasoning-delta",
118
- id: typeof typedPart.id === "string" ? typedPart.id : "reasoning",
228
+ id: normalizeReasoningId(typedPart),
119
229
  delta: typeof typedPart.delta === "string" ? typedPart.delta : "",
120
230
  });
121
231
  break;
122
232
  }
123
233
  case "reasoning-end": {
124
- sendSSE(controller, encoder, {
125
- type: "reasoning-end",
126
- id: typeof typedPart.id === "string" ? typedPart.id : "reasoning",
127
- });
234
+ closeTextSegment();
235
+ if (activeReasoningId === null) {
236
+ activeReasoningId = normalizeReasoningId(typedPart);
237
+ }
238
+ closeReasoningSegment();
128
239
  break;
129
240
  }
130
241
  case "tool-input-start": {
242
+ closeTextSegment();
243
+ closeReasoningSegment();
131
244
  const toolId = typedPart.id;
132
245
  state.toolCalls.set(toolId, {
133
246
  id: toolId,
134
247
  name: typedPart.toolName,
135
248
  arguments: "",
249
+ inputAvailable: false,
136
250
  providerExecuted: typedPart.providerExecuted,
137
251
  dynamic: typedPart.dynamic,
138
252
  });
@@ -146,6 +260,7 @@ export function processStream(result, state, controller, encoder, textPartId, ca
146
260
  break;
147
261
  }
148
262
  case "tool-input-delta": {
263
+ closeReasoningSegment();
149
264
  const toolId = typedPart.id;
150
265
  const tc = state.toolCalls.get(toolId);
151
266
  if (!tc)
@@ -159,6 +274,8 @@ export function processStream(result, state, controller, encoder, textPartId, ca
159
274
  break;
160
275
  }
161
276
  case "tool-call": {
277
+ closeTextSegment();
278
+ closeReasoningSegment();
162
279
  // tool-call fires when the full tool call is available
163
280
  const toolId = typedPart.toolCallId;
164
281
  const inputStr = normalizeToolInputString(typedPart.input);
@@ -168,6 +285,7 @@ export function processStream(result, state, controller, encoder, textPartId, ca
168
285
  id: toolId,
169
286
  name: typedPart.toolName,
170
287
  arguments: resolvedArguments,
288
+ inputAvailable: true,
171
289
  providerExecuted: typedPart.providerExecuted,
172
290
  dynamic: typedPart.dynamic,
173
291
  });
@@ -186,6 +304,15 @@ export function processStream(result, state, controller, encoder, textPartId, ca
186
304
  break;
187
305
  }
188
306
  case "tool-result": {
307
+ closeTextSegment();
308
+ closeReasoningSegment();
309
+ ensureToolLifecycle({
310
+ toolCallId: typedPart.toolCallId,
311
+ toolName: typedPart.toolName,
312
+ input: typedPart.input,
313
+ providerExecuted: typedPart.providerExecuted,
314
+ dynamic: typedPart.dynamic,
315
+ });
189
316
  const isError = typedPart.isError === true;
190
317
  logProviderToolPart("tool-result", {
191
318
  toolCallId: typedPart.toolCallId,
@@ -241,6 +368,15 @@ export function processStream(result, state, controller, encoder, textPartId, ca
241
368
  break;
242
369
  }
243
370
  case "tool-error": {
371
+ closeTextSegment();
372
+ closeReasoningSegment();
373
+ ensureToolLifecycle({
374
+ toolCallId: typedPart.toolCallId,
375
+ toolName: typedPart.toolName,
376
+ input: typedPart.input,
377
+ providerExecuted: typedPart.providerExecuted,
378
+ dynamic: typedPart.dynamic,
379
+ });
244
380
  logProviderToolPart("tool-error", {
245
381
  toolCallId: typedPart.toolCallId,
246
382
  toolName: typedPart.toolName,
@@ -270,6 +406,8 @@ export function processStream(result, state, controller, encoder, textPartId, ca
270
406
  break;
271
407
  }
272
408
  case "finish": {
409
+ closeTextSegment();
410
+ closeReasoningSegment();
273
411
  state.finishReason = typedPart.finishReason ?? null;
274
412
  if (typedPart.totalUsage) {
275
413
  const input = typedPart.totalUsage.inputTokens ?? 0;
@@ -284,6 +422,8 @@ export function processStream(result, state, controller, encoder, textPartId, ca
284
422
  break;
285
423
  }
286
424
  case "error": {
425
+ closeTextSegment();
426
+ closeReasoningSegment();
287
427
  logger.warn("Runtime stream error:", typedPart.error);
288
428
  sendSSE(controller, encoder, {
289
429
  type: "error",
@@ -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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"}
@@ -299,12 +299,10 @@ export class AgentRuntime {
299
299
  model: effectiveModel,
300
300
  },
301
301
  });
302
- sendSSE(controller, encoder, { type: "text-start", id: textPartId });
303
302
  const response = await this.executeAgentLoopStreaming(systemPrompt, memoryMessages, controller, encoder, callbacks, textPartId, toolContext, context, resolvedModelString, languageModel, transport.headers, transport.providerOptions, maxOutputTokensOverride, streamAbortSignal);
304
303
  throwIfAborted(streamAbortSignal);
305
304
  callbacks?.onFinish?.(response);
306
305
  throwIfAborted(streamAbortSignal);
307
- sendSSE(controller, encoder, { type: "text-end", id: textPartId });
308
306
  sendSSE(controller, encoder, { type: "message-finish" });
309
307
  closeSSEStream(controller);
310
308
  }
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.199";
1
+ export declare const VERSION = "0.1.200";
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.199";
3
+ export const VERSION = "0.1.200";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veryfront",
3
- "version": "0.1.199",
3
+ "version": "0.1.200",
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.199",
3
+ "version": "0.1.200",
4
4
  "license": "Apache-2.0",
5
5
  "nodeModulesDir": "auto",
6
6
  "exclude": [
@@ -234,6 +234,28 @@ function createTextEvent(
234
234
  };
235
235
  }
236
236
 
237
+ function closeOpenTextEvent(state: AgUiBrowserEncoderState): AgUiBrowserEncodedEvent[] {
238
+ if (!state.textOpen) {
239
+ return [];
240
+ }
241
+
242
+ state.textOpen = false;
243
+ return [createTextEvent(getMessageId(state, { type: "text-end" }), "TextMessageEnd")];
244
+ }
245
+
246
+ function closeOpenReasoningEvent(state: AgUiBrowserEncoderState): AgUiBrowserEncodedEvent[] {
247
+ if (state.reasoningMessageId === null) {
248
+ return [];
249
+ }
250
+
251
+ const messageId = state.reasoningMessageId;
252
+ state.reasoningMessageId = null;
253
+ return [{
254
+ event: "ReasoningMessageEnd",
255
+ payload: { messageId },
256
+ }];
257
+ }
258
+
237
259
  export function mapRuntimeStreamEventToAgUiBrowserEvents(
238
260
  state: AgUiBrowserEncoderState,
239
261
  event: AgUiRuntimeStreamEvent,
@@ -254,33 +276,38 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(
254
276
  return [];
255
277
 
256
278
  case "text-start": {
279
+ const events = closeOpenReasoningEvent(state);
257
280
  if (state.textOpen) return [];
258
281
  const messageId = getMessageId(state, event);
259
282
  state.textOpen = true;
260
283
  state.sawVisibleOutput = true;
261
- return [createTextEvent(messageId, "TextMessageStart")];
284
+ events.push(createTextEvent(messageId, "TextMessageStart"));
285
+ return events;
262
286
  }
263
287
 
264
288
  case "text-delta": {
289
+ const events = closeOpenReasoningEvent(state);
265
290
  const messageId = getMessageId(state, event);
266
291
  state.sawVisibleOutput = true;
267
292
  if (!state.textOpen) {
268
293
  state.textOpen = true;
269
- return [
294
+ events.push(
270
295
  createTextEvent(messageId, "TextMessageStart"),
271
296
  createTextEvent(
272
297
  messageId,
273
298
  "TextMessageContent",
274
299
  typeof event.delta === "string" ? event.delta : "",
275
300
  ),
276
- ];
301
+ );
302
+ return events;
277
303
  }
278
304
 
279
- return [createTextEvent(
305
+ events.push(createTextEvent(
280
306
  messageId,
281
307
  "TextMessageContent",
282
308
  typeof event.delta === "string" ? event.delta : "",
283
- )];
309
+ ));
310
+ return events;
284
311
  }
285
312
 
286
313
  case "text-end": {
@@ -289,13 +316,23 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(
289
316
  return [createTextEvent(getMessageId(state, event), "TextMessageEnd")];
290
317
  }
291
318
 
292
- case "reasoning-start":
319
+ case "reasoning-start": {
320
+ const events = closeOpenTextEvent(state);
321
+ events.push(...closeOpenReasoningEvent(state));
293
322
  state.sawVisibleOutput = true;
294
- return [createReasoningEvent(state, event, "ReasoningMessageStart")];
323
+ events.push(createReasoningEvent(state, event, "ReasoningMessageStart"));
324
+ return events;
325
+ }
295
326
 
296
- case "reasoning-delta":
327
+ case "reasoning-delta": {
328
+ const events = closeOpenTextEvent(state);
297
329
  state.sawVisibleOutput = true;
298
- return [createReasoningEvent(state, event, "ReasoningMessageContent")];
330
+ if (state.reasoningMessageId === null) {
331
+ events.push(createReasoningEvent(state, event, "ReasoningMessageStart"));
332
+ }
333
+ events.push(createReasoningEvent(state, event, "ReasoningMessageContent"));
334
+ return events;
335
+ }
299
336
 
300
337
  case "reasoning-end": {
301
338
  const reasoningEvent = createReasoningEvent(state, event, "ReasoningMessageEnd");
@@ -303,15 +340,21 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(
303
340
  return [reasoningEvent];
304
341
  }
305
342
 
306
- case "tool-input-start":
343
+ case "tool-input-start": {
344
+ const events = [
345
+ ...closeOpenTextEvent(state),
346
+ ...closeOpenReasoningEvent(state),
347
+ ];
307
348
  state.sawVisibleOutput = true;
308
- return [{
349
+ events.push({
309
350
  event: "ToolCallStart",
310
351
  payload: {
311
352
  toolCallId: event.toolCallId,
312
353
  toolCallName: event.toolName,
313
354
  },
314
- }];
355
+ });
356
+ return events;
357
+ }
315
358
 
316
359
  case "tool-input-delta":
317
360
  state.sawVisibleOutput = true;
@@ -328,12 +371,20 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(
328
371
 
329
372
  case "tool-input-available": {
330
373
  state.sawVisibleOutput = true;
331
- return completeToolInput(state, event);
374
+ return [
375
+ ...closeOpenTextEvent(state),
376
+ ...closeOpenReasoningEvent(state),
377
+ ...completeToolInput(state, event),
378
+ ];
332
379
  }
333
380
 
334
381
  case "tool-input-error": {
335
382
  state.sawVisibleOutput = true;
336
- const events = completeToolInput(state, event);
383
+ const events = [
384
+ ...closeOpenTextEvent(state),
385
+ ...closeOpenReasoningEvent(state),
386
+ ...completeToolInput(state, event),
387
+ ];
337
388
  events.push({
338
389
  event: "ToolCallResult",
339
390
  payload: {
@@ -349,25 +400,45 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(
349
400
 
350
401
  case "tool-output-available":
351
402
  state.sawVisibleOutput = true;
352
- return [createToolResultEvent(event.toolCallId, event.output)];
403
+ return [
404
+ ...closeOpenTextEvent(state),
405
+ ...closeOpenReasoningEvent(state),
406
+ createToolResultEvent(event.toolCallId, event.output),
407
+ ];
353
408
 
354
409
  case "tool-output-error":
355
410
  state.sawVisibleOutput = true;
356
- return [createToolResultEvent(event.toolCallId, { error: event.errorText }, true)];
411
+ return [
412
+ ...closeOpenTextEvent(state),
413
+ ...closeOpenReasoningEvent(state),
414
+ createToolResultEvent(event.toolCallId, { error: event.errorText }, true),
415
+ ];
357
416
 
358
417
  case "tool-output-denied":
359
418
  state.sawVisibleOutput = true;
360
- return [createToolResultEvent(event.toolCallId, { error: "Tool output denied" }, true)];
419
+ return [
420
+ ...closeOpenTextEvent(state),
421
+ ...closeOpenReasoningEvent(state),
422
+ createToolResultEvent(event.toolCallId, { error: "Tool output denied" }, true),
423
+ ];
361
424
 
362
425
  case "step-start":
363
426
  case "start-step":
364
427
  state.sawVisibleOutput = true;
365
- return [createStepEvent(state, "StepStarted")];
428
+ return [
429
+ ...closeOpenTextEvent(state),
430
+ ...closeOpenReasoningEvent(state),
431
+ createStepEvent(state, "StepStarted"),
432
+ ];
366
433
 
367
434
  case "step-end":
368
435
  case "finish-step":
369
436
  state.sawVisibleOutput = true;
370
- return [createStepEvent(state, "StepFinished")];
437
+ return [
438
+ ...closeOpenTextEvent(state),
439
+ ...closeOpenReasoningEvent(state),
440
+ createStepEvent(state, "StepFinished"),
441
+ ];
371
442
 
372
443
  case "data":
373
444
  applyDataMetadata(state, event);
@@ -375,12 +446,16 @@ export function mapRuntimeStreamEventToAgUiBrowserEvents(
375
446
 
376
447
  case "error":
377
448
  state.sawTerminalError = true;
378
- return [{
379
- event: "RunError",
380
- payload: {
381
- message: typeof event.error === "string" ? event.error : "Agent run failed",
449
+ return [
450
+ ...closeOpenTextEvent(state),
451
+ ...closeOpenReasoningEvent(state),
452
+ {
453
+ event: "RunError",
454
+ payload: {
455
+ message: typeof event.error === "string" ? event.error : "Agent run failed",
456
+ },
382
457
  },
383
- }];
458
+ ];
384
459
 
385
460
  default:
386
461
  return [];
@@ -409,13 +484,8 @@ export function finalizeAgUiBrowserEvents(
409
484
  }
410
485
 
411
486
  const events: AgUiBrowserEncodedEvent[] = [];
412
- if (state.textOpen) {
413
- state.textOpen = false;
414
- events.push({
415
- event: "TextMessageEnd",
416
- payload: { messageId: getMessageId(state, { type: "text-end" }) },
417
- });
418
- }
487
+ events.push(...closeOpenTextEvent(state));
488
+ events.push(...closeOpenReasoningEvent(state));
419
489
 
420
490
  events.push({
421
491
  event: "RunFinished",
@@ -24,6 +24,7 @@ export interface StreamingToolCall {
24
24
  id: string;
25
25
  name: string;
26
26
  arguments: string;
27
+ inputAvailable?: boolean;
27
28
  providerExecuted?: boolean;
28
29
  dynamic?: boolean;
29
30
  }
@@ -157,6 +158,136 @@ export function processStream(
157
158
  ): Promise<void> {
158
159
  return withSpan("agent.runtime.processStream", async () => {
159
160
  let eventCount = 0;
161
+ let textOpen = false;
162
+ let activeReasoningId: string | null = null;
163
+
164
+ const normalizeReasoningId = (part: { id?: string }) =>
165
+ typeof part.id === "string" && part.id.length > 0 ? part.id : "reasoning";
166
+
167
+ const openTextSegment = () => {
168
+ if (textOpen) {
169
+ return;
170
+ }
171
+
172
+ textOpen = true;
173
+ sendSSE(controller, encoder, {
174
+ type: "text-start",
175
+ id: textPartId,
176
+ });
177
+ };
178
+
179
+ const closeTextSegment = () => {
180
+ if (!textOpen) {
181
+ return;
182
+ }
183
+
184
+ textOpen = false;
185
+ sendSSE(controller, encoder, {
186
+ type: "text-end",
187
+ id: textPartId,
188
+ });
189
+ };
190
+
191
+ const openReasoningSegment = (reasoningId: string) => {
192
+ if (activeReasoningId === reasoningId) {
193
+ return;
194
+ }
195
+
196
+ if (activeReasoningId !== null) {
197
+ sendSSE(controller, encoder, {
198
+ type: "reasoning-end",
199
+ id: activeReasoningId,
200
+ });
201
+ }
202
+
203
+ activeReasoningId = reasoningId;
204
+ sendSSE(controller, encoder, {
205
+ type: "reasoning-start",
206
+ id: reasoningId,
207
+ });
208
+ };
209
+
210
+ const closeReasoningSegment = () => {
211
+ if (activeReasoningId === null) {
212
+ return;
213
+ }
214
+
215
+ sendSSE(controller, encoder, {
216
+ type: "reasoning-end",
217
+ id: activeReasoningId,
218
+ });
219
+ activeReasoningId = null;
220
+ };
221
+
222
+ const ensureToolLifecycle = (part: {
223
+ toolCallId: string;
224
+ toolName: string;
225
+ input?: unknown;
226
+ providerExecuted?: boolean;
227
+ dynamic?: boolean;
228
+ }) => {
229
+ const dynamic = part.dynamic ?? isDynamicTool(part.toolName);
230
+ const existing = state.toolCalls.get(part.toolCallId);
231
+
232
+ if (!existing) {
233
+ const normalizedInput = parseToolInputObject(part.input);
234
+ state.toolCalls.set(part.toolCallId, {
235
+ id: part.toolCallId,
236
+ name: part.toolName,
237
+ arguments: normalizeToolInputString(part.input),
238
+ inputAvailable: true,
239
+ ...(part.providerExecuted !== undefined
240
+ ? { providerExecuted: part.providerExecuted }
241
+ : {}),
242
+ ...(dynamic ? { dynamic: true } : {}),
243
+ });
244
+ sendSSE(controller, encoder, {
245
+ type: "tool-input-start",
246
+ toolCallId: part.toolCallId,
247
+ toolName: part.toolName,
248
+ ...(dynamic ? { dynamic: true } : {}),
249
+ });
250
+ sendSSE(controller, encoder, {
251
+ type: "tool-input-available",
252
+ toolCallId: part.toolCallId,
253
+ toolName: part.toolName,
254
+ input: normalizedInput,
255
+ ...(part.providerExecuted !== undefined
256
+ ? { providerExecuted: part.providerExecuted }
257
+ : {}),
258
+ ...(dynamic ? { dynamic: true } : {}),
259
+ });
260
+ return;
261
+ }
262
+
263
+ if (existing.inputAvailable) {
264
+ return;
265
+ }
266
+
267
+ const resolvedArguments = part.input !== undefined
268
+ ? mergeToolCallInput(existing.arguments, normalizeToolInputString(part.input))
269
+ : existing.arguments;
270
+ const resolvedInput = parseToolInputObject(resolvedArguments);
271
+ existing.arguments = resolvedArguments;
272
+ existing.inputAvailable = true;
273
+ if (part.providerExecuted !== undefined) {
274
+ existing.providerExecuted = part.providerExecuted;
275
+ }
276
+ if (dynamic) {
277
+ existing.dynamic = true;
278
+ }
279
+
280
+ sendSSE(controller, encoder, {
281
+ type: "tool-input-available",
282
+ toolCallId: part.toolCallId,
283
+ toolName: existing.name,
284
+ input: resolvedInput,
285
+ ...(existing.providerExecuted !== undefined
286
+ ? { providerExecuted: existing.providerExecuted }
287
+ : {}),
288
+ ...(existing.dynamic ? { dynamic: true } : {}),
289
+ });
290
+ };
160
291
 
161
292
  throwIfAborted(abortSignal);
162
293
 
@@ -172,6 +303,8 @@ export function processStream(
172
303
 
173
304
  switch (typedPart.type) {
174
305
  case "text-delta": {
306
+ closeReasoningSegment();
307
+ openTextSegment();
175
308
  state.accumulatedText += typedPart.text;
176
309
  sendSSE(controller, encoder, {
177
310
  type: "text-delta",
@@ -183,36 +316,40 @@ export function processStream(
183
316
  }
184
317
 
185
318
  case "reasoning-start": {
186
- sendSSE(controller, encoder, {
187
- type: "reasoning-start",
188
- id: typeof typedPart.id === "string" ? typedPart.id : "reasoning",
189
- });
319
+ closeTextSegment();
320
+ openReasoningSegment(normalizeReasoningId(typedPart));
190
321
  break;
191
322
  }
192
323
 
193
324
  case "reasoning-delta": {
325
+ closeTextSegment();
326
+ openReasoningSegment(normalizeReasoningId(typedPart));
194
327
  sendSSE(controller, encoder, {
195
328
  type: "reasoning-delta",
196
- id: typeof typedPart.id === "string" ? typedPart.id : "reasoning",
329
+ id: normalizeReasoningId(typedPart),
197
330
  delta: typeof typedPart.delta === "string" ? typedPart.delta : "",
198
331
  });
199
332
  break;
200
333
  }
201
334
 
202
335
  case "reasoning-end": {
203
- sendSSE(controller, encoder, {
204
- type: "reasoning-end",
205
- id: typeof typedPart.id === "string" ? typedPart.id : "reasoning",
206
- });
336
+ closeTextSegment();
337
+ if (activeReasoningId === null) {
338
+ activeReasoningId = normalizeReasoningId(typedPart);
339
+ }
340
+ closeReasoningSegment();
207
341
  break;
208
342
  }
209
343
 
210
344
  case "tool-input-start": {
345
+ closeTextSegment();
346
+ closeReasoningSegment();
211
347
  const toolId = typedPart.id;
212
348
  state.toolCalls.set(toolId, {
213
349
  id: toolId,
214
350
  name: typedPart.toolName,
215
351
  arguments: "",
352
+ inputAvailable: false,
216
353
  providerExecuted: typedPart.providerExecuted,
217
354
  dynamic: typedPart.dynamic,
218
355
  });
@@ -228,6 +365,7 @@ export function processStream(
228
365
  }
229
366
 
230
367
  case "tool-input-delta": {
368
+ closeReasoningSegment();
231
369
  const toolId = typedPart.id;
232
370
  const tc = state.toolCalls.get(toolId);
233
371
  if (!tc) break;
@@ -242,6 +380,8 @@ export function processStream(
242
380
  }
243
381
 
244
382
  case "tool-call": {
383
+ closeTextSegment();
384
+ closeReasoningSegment();
245
385
  // tool-call fires when the full tool call is available
246
386
  const toolId = typedPart.toolCallId;
247
387
  const inputStr = normalizeToolInputString(typedPart.input);
@@ -251,6 +391,7 @@ export function processStream(
251
391
  id: toolId,
252
392
  name: typedPart.toolName,
253
393
  arguments: resolvedArguments,
394
+ inputAvailable: true,
254
395
  providerExecuted: typedPart.providerExecuted,
255
396
  dynamic: typedPart.dynamic,
256
397
  });
@@ -271,6 +412,15 @@ export function processStream(
271
412
  }
272
413
 
273
414
  case "tool-result": {
415
+ closeTextSegment();
416
+ closeReasoningSegment();
417
+ ensureToolLifecycle({
418
+ toolCallId: typedPart.toolCallId,
419
+ toolName: typedPart.toolName,
420
+ input: typedPart.input,
421
+ providerExecuted: typedPart.providerExecuted,
422
+ dynamic: typedPart.dynamic,
423
+ });
274
424
  const isError = typedPart.isError === true;
275
425
  logProviderToolPart("tool-result", {
276
426
  toolCallId: typedPart.toolCallId,
@@ -328,6 +478,15 @@ export function processStream(
328
478
  }
329
479
 
330
480
  case "tool-error": {
481
+ closeTextSegment();
482
+ closeReasoningSegment();
483
+ ensureToolLifecycle({
484
+ toolCallId: typedPart.toolCallId,
485
+ toolName: typedPart.toolName,
486
+ input: typedPart.input,
487
+ providerExecuted: typedPart.providerExecuted,
488
+ dynamic: typedPart.dynamic,
489
+ });
331
490
  logProviderToolPart("tool-error", {
332
491
  toolCallId: typedPart.toolCallId,
333
492
  toolName: typedPart.toolName,
@@ -358,6 +517,8 @@ export function processStream(
358
517
  }
359
518
 
360
519
  case "finish": {
520
+ closeTextSegment();
521
+ closeReasoningSegment();
361
522
  state.finishReason = typedPart.finishReason ?? null;
362
523
  if (typedPart.totalUsage) {
363
524
  const input = typedPart.totalUsage.inputTokens ?? 0;
@@ -373,6 +534,8 @@ export function processStream(
373
534
  }
374
535
 
375
536
  case "error": {
537
+ closeTextSegment();
538
+ closeReasoningSegment();
376
539
  logger.warn("Runtime stream error:", typedPart.error);
377
540
  sendSSE(controller, encoder, {
378
541
  type: "error",
@@ -488,8 +488,6 @@ export class AgentRuntime {
488
488
  model: effectiveModel,
489
489
  },
490
490
  });
491
- sendSSE(controller, encoder, { type: "text-start", id: textPartId });
492
-
493
491
  const response = await this.executeAgentLoopStreaming(
494
492
  systemPrompt,
495
493
  memoryMessages,
@@ -510,7 +508,6 @@ export class AgentRuntime {
510
508
  callbacks?.onFinish?.(response);
511
509
  throwIfAborted(streamAbortSignal);
512
510
 
513
- sendSSE(controller, encoder, { type: "text-end", id: textPartId });
514
511
  sendSSE(controller, encoder, { type: "message-finish" });
515
512
  closeSSEStream(controller);
516
513
  } catch (error) {
@@ -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.199";
3
+ export const VERSION = "0.1.200";