llmz 0.6.4 → 0.6.6

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/DOCS.md CHANGED
@@ -1582,6 +1582,95 @@ await execute({
1582
1582
 
1583
1583
  ---
1584
1584
 
1585
+ ### Mid-Stream Model Fallback (midStreamFallback)
1586
+
1587
+ By default, LLMz streams responses: message bodies (`■send` blocks) and completed `Chat.handler` sends are dispatched as soon as they are produced, and the ■run block starts executing while the model is still generating the rest of the response. This gives the lowest time-to-first-token but runs code before the response is complete.
1588
+
1589
+ Set `options.midStreamFallback: true` to allow Cognitive to restart a failed stream on another model. There is **no buffered delivery and no final delivery queue**: with fallback enabled, delta text and completed `Chat.handler` sends both stream immediately during generation. Only **TOOL/CODE execution** waits for a stream to complete successfully. When Cognitive abandons an attempt, a reset-only delta (`restart: true`) is delivered through the existing `Chat.onMessageDelta`; it invalidates **all** messages of the current iteration — **including messages already committed through `handler`** — so consumers must retract and replace them:
1590
+
1591
+ ```typescript
1592
+ await execute({
1593
+ // ...
1594
+ chat: new MyChat({
1595
+ onMessageDelta: (delta) => {
1596
+ if (delta.restart) {
1597
+ // invalidates ALL current-iteration messages, including completed handler
1598
+ // sends: retract/replace them before the replacement streams
1599
+ return retractIteration(delta.iterationId)
1600
+ } else {
1601
+ // stream this message's text as it arrives (same iterationId as below)
1602
+ updateMessage(delta)
1603
+ }
1604
+ },
1605
+ }),
1606
+ options: { midStreamFallback: true },
1607
+ })
1608
+ ```
1609
+
1610
+ `retractIteration`/`updateMessage` are placeholder names for your consumer's message store. **This option is not safe to enable blindly**: a reset invalidates messages that were already delivered through `handler`. If your transport cannot retract or replace an already-sent message — an external irreversible send such as SMS, email, or a third-party webhook — those sends cannot be undone, so keep `midStreamFallback` disabled unless your consumer can retract and replace invalidated messages.
1611
+
1612
+ #### MessageDelta contract
1613
+
1614
+ `Chat.onMessageDelta` receives a single typed `MessageDelta` discriminated union:
1615
+
1616
+ - **Ordinary text chunk** (`restart: false`) — the next piece of one message's body; all fields are required:
1617
+ ```typescript
1618
+ {
1619
+ restart: false,
1620
+ iterationId: string, // stable across ALL attempts of this LLM generation iteration
1621
+ id: string, // message id — DIFFERENT per attempt (unique when fallback is on)
1622
+ component: string,
1623
+ props: Record<string, unknown>, // final by the time the body starts streaming
1624
+ delta: string, // new chunk of body text
1625
+ content: string, // full body text accumulated so far, including this chunk
1626
+ }
1627
+ ```
1628
+ - **Reset-only delta** (`restart: true`) — carries no text; signals the current generation attempt was abandoned and a replacement is being attempted:
1629
+ ```typescript
1630
+ {
1631
+ restart: true,
1632
+ iterationId: string, // the iteration whose messages (incl. handler sends) must be retracted/replaced
1633
+ attempt: number,
1634
+ fromModel: string,
1635
+ toModel: string,
1636
+ reason: string,
1637
+ }
1638
+ ```
1639
+
1640
+ IDs: `iterationId` is **stable across attempts** — every restart of the same iteration keeps the same `iterationId` — while `id` is **different per attempt**. After a reset, replacement chunks arrive under new `id`s within the same `iterationId`.
1641
+
1642
+ Consumer rules:
1643
+
1644
+ - On `restart: true`, retract/replace **all** current-iteration messages bearing that `iterationId` — streamed text **and** messages already delivered through `handler`.
1645
+ - On an ordinary chunk, update the message for `delta.id` (create it if new, otherwise append).
1646
+ - A reset is emitted and awaited **before** replacement output begins, **even if the replacement yields no message at all**. Return/await the retraction promise in your handler. If it throws or rejects, generation fails without delivering replacement output or executing code; ordinary text-preview errors remain best-effort.
1647
+ - A reset only invalidates the messages of its own `iterationId`; it **never** invalidates messages from earlier, completed iterations.
1648
+ - Only TOOL/CODE execution is gated on a successful stream: generated code and tool calls never run from an abandoned attempt.
1649
+
1650
+ Outside of fallback (the default), `onMessageDelta` behavior is unchanged: ordinary chunks carry `iterationId`/`id`/`component`/`props`/`delta`/`content` with a single stable message id, and no restart/reset deltas are produced.
1651
+
1652
+ #### Completed-send correlation
1653
+
1654
+ `Chat.handler(component, metadata)` receives `{ iterationId: string, id: string }` for **every send**, including empty-body and non-text components, without requiring `onMessageDelta`. For streamed messages, `metadata.id` matches the text delta's `id`; it changes across attempts while `iterationId` stays stable. Existing one-argument handlers continue to work.
1655
+
1656
+ Record **all** persisted message IDs created while awaiting that handler under its metadata (one component may produce multiple persisted messages). A restart can then retract everything for the matching iteration, even after a message's stream tracking has completed. Non-streaming sends also receive metadata. Tool-yielded messages get unique per-yield IDs and the runtime iteration ID; standalone `Tool.execute` calls without an iteration use their `callId` as the scope.
1657
+
1658
+ #### Migrating consumers
1659
+
1660
+ - **No final delivery queue**: messages are not withheld until the stream ends. Deltas and completed `handler` sends arrive during generation; drop any "promote on success" design — treat every delivered message as provisional until the iteration completes without a reset.
1661
+ - **Retract, don't just clear previews**: on `restart: true`, retraction must cascade to every current-iteration message, including ones already committed through `handler`. If your UI or transport cannot do that, keep `midStreamFallback` disabled.
1662
+ - **Clear on errors and cancellation**: a failed or cancelled generation can leave current-iteration messages on screen, incomplete, or unresettable. Explicitly clear/roll back current-iteration state when execution errors or ends — there is no exactly-once guarantee, and caller retries can duplicate effects.
1663
+ - **Irreversible transports**: external sends that cannot be undone (SMS, email, webhooks) must not blindly enable fallback without a reset-capable gateway.
1664
+
1665
+ #### Caveats
1666
+
1667
+ - **No extra retry loop**: Cognitive owns fallback, bounded by the model chain. LLMz does not retry abandoned attempts itself.
1668
+ - **Cancellation**: cancellation still aborts the original generation request as usual; consumers must clear current-iteration state on abort (see above). Cancellation deadlines are not reset, and the existing stream inactivity guard remains active during handoffs.
1669
+
1670
+ This option defaults to false and applies only to streaming clients. Non-streaming Cognitive requests already fall back transparently. It can be combined with `maxTimeToFirstToken` and `transcriptionModel`; do not enable it globally underneath LLMz without also enabling LLMz's fallback option and a reset-capable consumer.
1671
+
1672
+ Restarts emit `llm_call_restarted` traces with the attempt, source/destination models, and reason. Token timings remain relative to the original request and describe the surviving attempt (including time spent on prior attempts). Usage and cost retain Cognitive's final reported metadata; LLMz does not infer or sum abandoned-attempt billing.
1673
+
1585
1674
  ## API Reference
1586
1675
 
1587
1676
  ### Core Functions
package/dist/chat.d.ts CHANGED
@@ -24,7 +24,14 @@ import { TranscriptArray, Transcript } from './transcript.js';
24
24
  * }
25
25
  * ```
26
26
  */
27
- export type MessageHandler = (input: RenderedComponent) => Promise<void> | void;
27
+ /** Correlates every generated send with its deltas and restart scope. */
28
+ export type MessageMetadata = {
29
+ /** Stable across generation attempts; standalone tool calls use their callId. */
30
+ iterationId: string;
31
+ /** Logical send ID; matches MessageDelta.id when text deltas exist. Unique across attempts. */
32
+ id: string;
33
+ };
34
+ export type MessageHandler = (input: RenderedComponent, metadata: MessageMetadata) => Promise<void> | void;
28
35
  /**
29
36
  * A chunk of a message body streamed live from the LLM, before the message is complete.
30
37
  *
@@ -32,10 +39,14 @@ export type MessageHandler = (input: RenderedComponent) => Promise<void> | void;
32
39
  * Each chunk is forwarded to {@link Chat} `onMessageDelta` as soon as it is parsed, so the
33
40
  * client can render the message progressively (e.g. typewriter effect in a chat UI).
34
41
  *
35
- * The complete message is always delivered to the regular `handler` afterwards — deltas
36
- * are a progressive preview, the `handler` call remains the authoritative delivery.
42
+ * In mid-stream fallback mode, both deltas and completed `handler` messages
43
+ * are live and retractable: restart deltas invalidate every message from that
44
+ * iteration. Consumers must retract them; only code execution waits for success.
37
45
  */
38
46
  export type MessageDelta = {
47
+ restart: false;
48
+ /** Generation whose provisional messages must be cleared on a restart. */
49
+ iterationId: string;
39
50
  /** Identifies the message being streamed. Unique within an `execute()` call. */
40
51
  id: string;
41
52
  /** Component name of the message being streamed (e.g. 'message', 'button'). */
@@ -46,10 +57,24 @@ export type MessageDelta = {
46
57
  delta: string;
47
58
  /** The full body text accumulated so far, including this chunk. */
48
59
  content: string;
60
+ } | {
61
+ /**
62
+ * Reset-only delta, emitted before replacement text (even if none follows).
63
+ * Clear ALL messages for iterationId, including completed `handler` sends.
64
+ * Other iterations are unaffected. Irreversible sends cannot be undone.
65
+ */
66
+ restart: true;
67
+ iterationId: string;
68
+ /** 1-based index of the new attempt. */
69
+ attempt: number;
70
+ fromModel: string;
71
+ toModel: string;
72
+ reason: string;
49
73
  };
50
74
  /**
51
75
  * Function type for handling message chunks as they are streamed from the LLM.
52
- * Errors thrown by this handler are ignored — streaming previews are best-effort.
76
+ * Text-preview errors are ignored. Restart-handler errors stop generation:
77
+ * replacement output must not be delivered if retraction fails.
53
78
  */
54
79
  export type MessageDeltaHandler = (delta: MessageDelta) => Promise<void> | void;
55
80
  /**
package/dist/context.d.ts CHANGED
@@ -564,6 +564,17 @@ export declare class Context implements Serializable<Context.JSON> {
564
564
  * before the cognitive service falls back to the next model/provider.
565
565
  */
566
566
  maxTimeToFirstToken?: number;
567
+ /**
568
+ * Allow Cognitive to restart a failed stream on another model. With fallback
569
+ * enabled, there is no buffered delivery and no final delivery queue: delta
570
+ * text and completed Chat.handler sends stream immediately during generation.
571
+ * A reset-only delta (restart: true) on Chat.onMessageDelta invalidates ALL
572
+ * current-iteration messages, including completed sends — consumers must
573
+ * retract/replace them, which is unsafe for irreversible external transports.
574
+ * Only TOOL/CODE execution waits for a successful stream. Streaming-only;
575
+ * defaults to false, which leaves progressive sending unchanged.
576
+ */
577
+ midStreamFallback?: boolean;
567
578
  /**
568
579
  * STT model used by the cognitive service to transcribe audio attachments
569
580
  * when the target LLM does not support audio natively. Defaults to 'fast'.
@@ -600,6 +611,7 @@ export declare class Context implements Serializable<Context.JSON> {
600
611
  timeout?: number;
601
612
  maxTokens?: number;
602
613
  maxTimeToFirstToken?: number;
614
+ midStreamFallback?: boolean;
603
615
  transcriptionModel?: SttModels;
604
616
  });
605
617
  toJSON(): {
@@ -4,7 +4,7 @@ import { f as flatRest, l as extractType, m as baseCreate, p as copyArray, t as
4
4
  import { _ as getSymbolsIn, b as keysIn, g as getAllKeysIn, o as getTokenizer, x as assignValue, y as baseSlice } from "./utils-UBeAFeEI.js";
5
5
  import { t as getPrototype } from "./_getPrototype-CG7Dxrrz.js";
6
6
  import { t as isPlainObject } from "./isPlainObject-D39AzPO2.js";
7
- import { t as Tool } from "./tool-CAo-BQHs.js";
7
+ import { t as Tool } from "./tool-Bv8N4IPj.js";
8
8
  import { o as LoopExceededError } from "./errors-Cg1G0Awu.js";
9
9
  import { t as Exit } from "./exit-CDdxDBRT.js";
10
10
  import { n as assertValidComponent } from "./component-DGG7d_Mz.js";
@@ -2254,6 +2254,17 @@ var Context = class {
2254
2254
  */
2255
2255
  maxTimeToFirstToken;
2256
2256
  /**
2257
+ * Allow Cognitive to restart a failed stream on another model. With fallback
2258
+ * enabled, there is no buffered delivery and no final delivery queue: delta
2259
+ * text and completed Chat.handler sends stream immediately during generation.
2260
+ * A reset-only delta (restart: true) on Chat.onMessageDelta invalidates ALL
2261
+ * current-iteration messages, including completed sends — consumers must
2262
+ * retract/replace them, which is unsafe for irreversible external transports.
2263
+ * Only TOOL/CODE execution waits for a successful stream. Streaming-only;
2264
+ * defaults to false, which leaves progressive sending unchanged.
2265
+ */
2266
+ midStreamFallback;
2267
+ /**
2257
2268
  * STT model used by the cognitive service to transcribe audio attachments
2258
2269
  * when the target LLM does not support audio natively. Defaults to 'fast'.
2259
2270
  */
@@ -2509,10 +2520,12 @@ var Context = class {
2509
2520
  this.snapshot = props.snapshot;
2510
2521
  this.maxTokens = props.maxTokens;
2511
2522
  this.maxTimeToFirstToken = props.maxTimeToFirstToken;
2523
+ this.midStreamFallback = props.midStreamFallback;
2512
2524
  this.transcriptionModel = props.transcriptionModel;
2513
2525
  if (this.loop < 1 || this.loop > 100) throw new Error("Invalid loop. Expected a number between 1 and 100.");
2514
2526
  if (this.maxTokens !== void 0 && (!Number.isFinite(this.maxTokens) || this.maxTokens < 1)) throw new Error("Invalid maxTokens. Expected a positive number.");
2515
2527
  if (this.maxTimeToFirstToken !== void 0 && (!Number.isFinite(this.maxTimeToFirstToken) || this.maxTimeToFirstToken < 1)) throw new Error("Invalid maxTimeToFirstToken. Expected a positive number of milliseconds.");
2528
+ if (this.midStreamFallback !== void 0 && typeof this.midStreamFallback !== "boolean") throw new Error("Invalid midStreamFallback. Expected a boolean.");
2516
2529
  }
2517
2530
  toJSON() {
2518
2531
  var _this$snapshot4;
@@ -4,7 +4,7 @@ const require_dual_modes = require("./dual-modes-wAOAlaBS.cjs");
4
4
  const require_utils = require("./utils-ZpJm00ed.cjs");
5
5
  const require__getPrototype = require("./_getPrototype-DQDlNVVM.cjs");
6
6
  const require_isPlainObject = require("./isPlainObject-CSxXVKCk.cjs");
7
- const require_tool = require("./tool-DdPZb0JW.cjs");
7
+ const require_tool = require("./tool-ReA9gxMp.cjs");
8
8
  const require_errors = require("./errors-C962uJdS.cjs");
9
9
  const require_exit = require("./exit-BGi0Kk0y.cjs");
10
10
  const require_component = require("./component-BwixNVH8.cjs");
@@ -2254,6 +2254,17 @@ var Context = class {
2254
2254
  */
2255
2255
  maxTimeToFirstToken;
2256
2256
  /**
2257
+ * Allow Cognitive to restart a failed stream on another model. With fallback
2258
+ * enabled, there is no buffered delivery and no final delivery queue: delta
2259
+ * text and completed Chat.handler sends stream immediately during generation.
2260
+ * A reset-only delta (restart: true) on Chat.onMessageDelta invalidates ALL
2261
+ * current-iteration messages, including completed sends — consumers must
2262
+ * retract/replace them, which is unsafe for irreversible external transports.
2263
+ * Only TOOL/CODE execution waits for a successful stream. Streaming-only;
2264
+ * defaults to false, which leaves progressive sending unchanged.
2265
+ */
2266
+ midStreamFallback;
2267
+ /**
2257
2268
  * STT model used by the cognitive service to transcribe audio attachments
2258
2269
  * when the target LLM does not support audio natively. Defaults to 'fast'.
2259
2270
  */
@@ -2509,10 +2520,12 @@ var Context = class {
2509
2520
  this.snapshot = props.snapshot;
2510
2521
  this.maxTokens = props.maxTokens;
2511
2522
  this.maxTimeToFirstToken = props.maxTimeToFirstToken;
2523
+ this.midStreamFallback = props.midStreamFallback;
2512
2524
  this.transcriptionModel = props.transcriptionModel;
2513
2525
  if (this.loop < 1 || this.loop > 100) throw new Error("Invalid loop. Expected a number between 1 and 100.");
2514
2526
  if (this.maxTokens !== void 0 && (!Number.isFinite(this.maxTokens) || this.maxTokens < 1)) throw new Error("Invalid maxTokens. Expected a positive number.");
2515
2527
  if (this.maxTimeToFirstToken !== void 0 && (!Number.isFinite(this.maxTimeToFirstToken) || this.maxTimeToFirstToken < 1)) throw new Error("Invalid maxTimeToFirstToken. Expected a positive number of milliseconds.");
2528
+ if (this.midStreamFallback !== void 0 && typeof this.midStreamFallback !== "boolean") throw new Error("Invalid midStreamFallback. Expected a boolean.");
2516
2529
  }
2517
2530
  toJSON() {
2518
2531
  var _this$snapshot4;
@@ -1,6 +1,6 @@
1
1
  const require__baseForOwn = require("./_baseForOwn-buOZDFbK.cjs");
2
2
  const require_dual_modes = require("./dual-modes-wAOAlaBS.cjs");
3
- const require_custom_client = require("./custom-client-BPmEoWKu.cjs");
3
+ const require_custom_client = require("./custom-client-Cr33K60k.cjs");
4
4
  const require_utils = require("./utils-ZpJm00ed.cjs");
5
5
  const require_jsx = require("./jsx-BWvT6ukg.cjs");
6
6
  const require_stack_traces = require("./stack-traces-ntw_qhoy.cjs");
@@ -121,7 +121,7 @@ const RESPONSE_LENGTH_BUFFER = {
121
121
  PERCENTAGE: .1
122
122
  };
123
123
  /** Maximum time to wait between two stream chunks before considering the stream stalled. */
124
- const STREAM_INACTIVITY_TIMEOUT = 6e4;
124
+ const STREAM_INACTIVITY_TIMEOUT = 18e4;
125
125
  const getModelOutputLimit = (inputLength) => clamp(RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength, RESPONSE_LENGTH_BUFFER.MIN_TOKENS, RESPONSE_LENGTH_BUFFER.MAX_TOKENS);
126
126
  /**
127
127
  * Models sometimes wrap their whole response in a code fence. The fence has to
@@ -197,6 +197,19 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
197
197
  /** Milliseconds between the stream request and the first/last streamed tokens. */
198
198
  let timeToFirstToken;
199
199
  let timeToLastToken;
200
+ const midStreamFallback = ctx.midStreamFallback === true;
201
+ let attempt = 1;
202
+ const messageMetadata = (itemId) => ({
203
+ iterationId: iteration.id,
204
+ id: midStreamFallback ? `${iteration.id}:${attempt}:${itemId}` : `${iteration.id}:${itemId}`
205
+ });
206
+ const preview = async (delta) => {
207
+ try {
208
+ await (onSendDelta === null || onSendDelta === void 0 ? void 0 : onSendDelta(delta));
209
+ } catch (err) {
210
+ if (delta.restart) throw new require_errors.CognitiveError(`LLM stream restart handler failed: ${require_utils.getErrorMessage(err)}`);
211
+ }
212
+ };
200
213
  const liveItems = /* @__PURE__ */ new Map();
201
214
  const liveContent = /* @__PURE__ */ new Map();
202
215
  let codeGenerationTraced = false;
@@ -217,37 +230,39 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
217
230
  if ((item === null || item === void 0 ? void 0 : item.kind) !== "send") continue;
218
231
  const content = (liveContent.get(item.id) ?? "") + event.delta;
219
232
  liveContent.set(item.id, content);
220
- try {
221
- await onSendDelta({
222
- id: `${iteration.id}:${item.id}`,
223
- component: item.name,
224
- props: item.props,
225
- delta: event.delta,
226
- content
227
- });
228
- } catch (err) {}
233
+ const delta = {
234
+ restart: false,
235
+ ...messageMetadata(item.id),
236
+ component: item.name,
237
+ props: item.props,
238
+ delta: event.delta,
239
+ content
240
+ };
241
+ await preview(delta);
229
242
  } else if (event.type === "item-complete") {
230
243
  if (event.item.kind === "send" && onSend) await onSend({
231
244
  name: event.item.name,
232
245
  props: event.item.props,
233
246
  body: event.item.body
234
- });
247
+ }, messageMetadata(event.item.id));
235
248
  else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
236
249
  runCompleted = true;
237
- onRunComplete === null || onRunComplete === void 0 || onRunComplete((event.item.body ?? "").trim());
250
+ const code = (event.item.body ?? "").trim();
251
+ onRunComplete === null || onRunComplete === void 0 || onRunComplete(code);
238
252
  }
239
253
  }
240
254
  };
241
255
  if (typeof cognitive.generateTextStream === "function") {
242
- const parser = new require_dual_modes.StreamingMessageParser();
243
- const fence = new LeadingFenceFilter();
256
+ let parser = new require_dual_modes.StreamingMessageParser();
257
+ let fence = new LeadingFenceFilter();
244
258
  const streamController = createJoinedAbortController([controller.signal]);
245
259
  const requestedAt = Date.now();
246
260
  const stream = cognitive.generateTextStream({
247
261
  ...input,
248
- ...ctx.maxTimeToFirstToken ? { options: {
262
+ ...ctx.maxTimeToFirstToken || midStreamFallback ? { options: {
249
263
  ...input.options,
250
- maxTimeToFirstToken: ctx.maxTimeToFirstToken
264
+ ...ctx.maxTimeToFirstToken ? { maxTimeToFirstToken: ctx.maxTimeToFirstToken } : {},
265
+ ...midStreamFallback ? { midStreamFallback: true } : {}
251
266
  } } : {}
252
267
  }, { signal: streamController.signal });
253
268
  const inactivityTimeout = Math.max(STREAM_INACTIVITY_TIMEOUT, ctx.maxTimeToFirstToken ?? 0);
@@ -266,28 +281,66 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
266
281
  }
267
282
  };
268
283
  raw = "";
269
- while (true) {
270
- var _chunk$value, _chunk$value2;
271
- let chunk;
272
- try {
273
- chunk = await nextChunk();
274
- } catch (thrown) {
275
- throw new require_errors.CognitiveError(`LLM generation failed: ${require_utils.getErrorMessage(thrown)}`);
284
+ let streamCompleted = false;
285
+ try {
286
+ while (true) {
287
+ var _chunk$value, _chunk$value2, _chunk$value3, _chunk$value4;
288
+ let chunk;
289
+ try {
290
+ chunk = await nextChunk();
291
+ } catch (thrown) {
292
+ throw new require_errors.CognitiveError(`LLM generation failed: ${require_utils.getErrorMessage(thrown)}`);
293
+ }
294
+ if (chunk.done) {
295
+ streamCompleted = true;
296
+ break;
297
+ }
298
+ if (((_chunk$value = chunk.value) === null || _chunk$value === void 0 ? void 0 : _chunk$value.restart) && !midStreamFallback) {
299
+ streamController.abort("Unexpected LLM stream restart");
300
+ throw new require_errors.CognitiveError("LLM stream restarted without options.midStreamFallback enabled");
301
+ }
302
+ if ((_chunk$value2 = chunk.value) === null || _chunk$value2 === void 0 ? void 0 : _chunk$value2.restart) {
303
+ traces.push({
304
+ type: "llm_call_restarted",
305
+ started_at: Date.now(),
306
+ ...chunk.value.restart
307
+ });
308
+ raw = "";
309
+ parser = new require_dual_modes.StreamingMessageParser();
310
+ fence = new LeadingFenceFilter();
311
+ liveItems.clear();
312
+ liveContent.clear();
313
+ codeGenerationTraced = false;
314
+ runCompleted = false;
315
+ responseMetadata = void 0;
316
+ attempt = chunk.value.restart.attempt;
317
+ await preview({
318
+ ...chunk.value.restart,
319
+ restart: true,
320
+ iterationId: iteration.id
321
+ });
322
+ timeToFirstToken = void 0;
323
+ timeToLastToken = void 0;
324
+ continue;
325
+ }
326
+ if ((_chunk$value3 = chunk.value) === null || _chunk$value3 === void 0 ? void 0 : _chunk$value3.metadata) responseMetadata = chunk.value.metadata;
327
+ const delta = (_chunk$value4 = chunk.value) === null || _chunk$value4 === void 0 ? void 0 : _chunk$value4.output;
328
+ if (!delta) continue;
329
+ timeToLastToken = Date.now() - requestedAt;
330
+ timeToFirstToken ??= timeToLastToken;
331
+ raw += delta;
332
+ await dispatchSends(parser.push(fence.push(delta)));
276
333
  }
277
- if (chunk.done) break;
278
- if ((_chunk$value = chunk.value) === null || _chunk$value === void 0 ? void 0 : _chunk$value.metadata) responseMetadata = chunk.value.metadata;
279
- const delta = (_chunk$value2 = chunk.value) === null || _chunk$value2 === void 0 ? void 0 : _chunk$value2.output;
280
- if (!delta) continue;
281
- timeToLastToken = Date.now() - requestedAt;
282
- timeToFirstToken ??= timeToLastToken;
283
- raw += delta;
284
- await dispatchSends(parser.push(fence.push(delta)));
334
+ if (!responseMetadata) throw new require_errors.CognitiveError("LLM streaming completed without metadata");
335
+ const remaining = fence.flush();
336
+ if (remaining) await dispatchSends(parser.push(remaining));
337
+ await dispatchSends(parser.finish());
338
+ assistantResponse = require_dual_modes.toParsedAssistantResponse(parser.items, raw);
339
+ } finally {
340
+ streamController.abort("LLM stream closed");
341
+ if (!streamCompleted) stream.return(void 0).catch((err) => {});
285
342
  }
286
- if (!responseMetadata) throw new require_errors.CognitiveError("LLM streaming completed without metadata");
287
- const remaining = fence.flush();
288
- if (remaining) await dispatchSends(parser.push(remaining));
289
- await dispatchSends(parser.finish());
290
- assistantResponse = require_dual_modes.toParsedAssistantResponse(parser.items, raw);
343
+ if (midStreamFallback) controller.signal.throwIfAborted();
291
344
  } else {
292
345
  const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
293
346
  throw new require_errors.CognitiveError(`LLM generation failed: ${require_utils.getErrorMessage(thrown)}`);
@@ -296,7 +349,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
296
349
  responseMetadata = response.metadata;
297
350
  raw = response.output;
298
351
  assistantResponse = ctx.version.parseAssistantResponse(raw);
299
- for (const send of assistantResponse.sends) await (onSend === null || onSend === void 0 ? void 0 : onSend(send));
352
+ for (const [index, send] of assistantResponse.sends.entries()) await (onSend === null || onSend === void 0 ? void 0 : onSend(send, messageMetadata(`send-${index}`)));
300
353
  }
301
354
  iteration.code = assistantResponse.code;
302
355
  iteration.sends = assistantResponse.sends;
@@ -329,7 +382,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
329
382
  type: "llm_call_success",
330
383
  started_at: startedAt,
331
384
  ended_at: iteration.llm.ended_at,
332
- model: model.id,
385
+ model: iteration.llm.model,
333
386
  code: iteration.code ?? ""
334
387
  });
335
388
  };
@@ -572,7 +625,10 @@ function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook
572
625
  toolCallId
573
626
  }));
574
627
  if (typeof (beforeRes === null || beforeRes === void 0 ? void 0 : beforeRes.input) !== "undefined") effectiveInput = beforeRes.input;
575
- output = await tool.execute(effectiveInput, { callId: toolCallId }, chat);
628
+ output = await tool.execute(effectiveInput, {
629
+ callId: toolCallId,
630
+ iterationId: iteration.id
631
+ }, chat);
576
632
  const afterRes = await (afterHook === null || afterHook === void 0 ? void 0 : afterHook({
577
633
  iteration,
578
634
  tool,
@@ -677,7 +733,7 @@ const executeContext = async (props) => {
677
733
  return result;
678
734
  };
679
735
  const executeContextInternal = async (props) => {
680
- var _props$options, _props$options2, _props$options3, _props$options4, _props$options5;
736
+ var _props$options, _props$options2, _props$options3, _props$options4, _props$options5, _props$options6;
681
737
  const controller = createJoinedAbortController([props.signal]);
682
738
  const { onIterationStart, onIterationEnd, onTrace, onExit, onBeforeExecution, onAfterTool, onBeforeTool } = props;
683
739
  const client = props.client ?? new _botpress_client.Client();
@@ -691,7 +747,8 @@ const executeContextInternal = async (props) => {
691
747
  timeout: (_props$options2 = props.options) === null || _props$options2 === void 0 ? void 0 : _props$options2.timeout,
692
748
  maxTokens: (_props$options3 = props.options) === null || _props$options3 === void 0 ? void 0 : _props$options3.maxTokens,
693
749
  maxTimeToFirstToken: (_props$options4 = props.options) === null || _props$options4 === void 0 ? void 0 : _props$options4.maxTimeToFirstToken,
694
- transcriptionModel: (_props$options5 = props.options) === null || _props$options5 === void 0 ? void 0 : _props$options5.transcriptionModel,
750
+ midStreamFallback: (_props$options5 = props.options) === null || _props$options5 === void 0 ? void 0 : _props$options5.midStreamFallback,
751
+ transcriptionModel: (_props$options6 = props.options) === null || _props$options6 === void 0 ? void 0 : _props$options6.transcriptionModel,
695
752
  exits: props.exits,
696
753
  snapshot: props.snapshot,
697
754
  model: props.model,
@@ -884,7 +941,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
884
941
  };
885
942
  });
886
943
  };
887
- const canExecuteEarly = typeof onBeforeExecution !== "function";
944
+ const canExecuteEarly = typeof onBeforeExecution !== "function" && !ctx.midStreamFallback;
888
945
  let earlyExecution;
889
946
  await generateCode({
890
947
  iteration,
@@ -902,7 +959,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
902
959
  promise: runCode(code)
903
960
  };
904
961
  } : void 0,
905
- onSend: async (send) => {
962
+ onSend: async (send, messageMetadata) => {
906
963
  if (!ctx.chat) return;
907
964
  const sendStartedAt = Date.now();
908
965
  const component = require_jsx.createJsxComponent({
@@ -911,7 +968,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
911
968
  children: send.body ? [send.body] : []
912
969
  });
913
970
  try {
914
- await ctx.chat.handler(component);
971
+ await ctx.chat.handler(component, messageMetadata);
915
972
  } catch (err) {
916
973
  throw new Error(`Error while sending message (■send=${send.name}): ${require_utils.getErrorMessage(err)}`);
917
974
  }
@@ -1,5 +1,5 @@
1
1
  import { a as StreamingMessageParser, d as isEqual, h as toNumber, i as toParsedAssistantResponse } from "./dual-modes-D_p-jedw.js";
2
- import { d as Snapshot, f as parseExit, l as PartialExecutionResult, n as Context, s as ErrorExecutionResult, t as _CustomModelClient, u as SuccessExecutionResult } from "./custom-client-NUoxrFQh.js";
2
+ import { d as Snapshot, f as parseExit, l as PartialExecutionResult, n as Context, s as ErrorExecutionResult, t as _CustomModelClient, u as SuccessExecutionResult } from "./custom-client-CJIThG2H.js";
3
3
  import { d as stripInvalidIdentifiers, i as getErrorMessage, s as init } from "./utils-UBeAFeEI.js";
4
4
  import { t as createJsxComponent } from "./jsx-CIgdGGVs.js";
5
5
  import { t as cleanStackTrace } from "./stack-traces-BIE_5Xwf.js";
@@ -119,7 +119,7 @@ const RESPONSE_LENGTH_BUFFER = {
119
119
  PERCENTAGE: .1
120
120
  };
121
121
  /** Maximum time to wait between two stream chunks before considering the stream stalled. */
122
- const STREAM_INACTIVITY_TIMEOUT = 6e4;
122
+ const STREAM_INACTIVITY_TIMEOUT = 18e4;
123
123
  const getModelOutputLimit = (inputLength) => clamp(RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength, RESPONSE_LENGTH_BUFFER.MIN_TOKENS, RESPONSE_LENGTH_BUFFER.MAX_TOKENS);
124
124
  /**
125
125
  * Models sometimes wrap their whole response in a code fence. The fence has to
@@ -195,6 +195,19 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
195
195
  /** Milliseconds between the stream request and the first/last streamed tokens. */
196
196
  let timeToFirstToken;
197
197
  let timeToLastToken;
198
+ const midStreamFallback = ctx.midStreamFallback === true;
199
+ let attempt = 1;
200
+ const messageMetadata = (itemId) => ({
201
+ iterationId: iteration.id,
202
+ id: midStreamFallback ? `${iteration.id}:${attempt}:${itemId}` : `${iteration.id}:${itemId}`
203
+ });
204
+ const preview = async (delta) => {
205
+ try {
206
+ await (onSendDelta === null || onSendDelta === void 0 ? void 0 : onSendDelta(delta));
207
+ } catch (err) {
208
+ if (delta.restart) throw new CognitiveError(`LLM stream restart handler failed: ${getErrorMessage(err)}`);
209
+ }
210
+ };
198
211
  const liveItems = /* @__PURE__ */ new Map();
199
212
  const liveContent = /* @__PURE__ */ new Map();
200
213
  let codeGenerationTraced = false;
@@ -215,37 +228,39 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
215
228
  if ((item === null || item === void 0 ? void 0 : item.kind) !== "send") continue;
216
229
  const content = (liveContent.get(item.id) ?? "") + event.delta;
217
230
  liveContent.set(item.id, content);
218
- try {
219
- await onSendDelta({
220
- id: `${iteration.id}:${item.id}`,
221
- component: item.name,
222
- props: item.props,
223
- delta: event.delta,
224
- content
225
- });
226
- } catch (err) {}
231
+ const delta = {
232
+ restart: false,
233
+ ...messageMetadata(item.id),
234
+ component: item.name,
235
+ props: item.props,
236
+ delta: event.delta,
237
+ content
238
+ };
239
+ await preview(delta);
227
240
  } else if (event.type === "item-complete") {
228
241
  if (event.item.kind === "send" && onSend) await onSend({
229
242
  name: event.item.name,
230
243
  props: event.item.props,
231
244
  body: event.item.body
232
- });
245
+ }, messageMetadata(event.item.id));
233
246
  else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
234
247
  runCompleted = true;
235
- onRunComplete === null || onRunComplete === void 0 || onRunComplete((event.item.body ?? "").trim());
248
+ const code = (event.item.body ?? "").trim();
249
+ onRunComplete === null || onRunComplete === void 0 || onRunComplete(code);
236
250
  }
237
251
  }
238
252
  };
239
253
  if (typeof cognitive.generateTextStream === "function") {
240
- const parser = new StreamingMessageParser();
241
- const fence = new LeadingFenceFilter();
254
+ let parser = new StreamingMessageParser();
255
+ let fence = new LeadingFenceFilter();
242
256
  const streamController = createJoinedAbortController([controller.signal]);
243
257
  const requestedAt = Date.now();
244
258
  const stream = cognitive.generateTextStream({
245
259
  ...input,
246
- ...ctx.maxTimeToFirstToken ? { options: {
260
+ ...ctx.maxTimeToFirstToken || midStreamFallback ? { options: {
247
261
  ...input.options,
248
- maxTimeToFirstToken: ctx.maxTimeToFirstToken
262
+ ...ctx.maxTimeToFirstToken ? { maxTimeToFirstToken: ctx.maxTimeToFirstToken } : {},
263
+ ...midStreamFallback ? { midStreamFallback: true } : {}
249
264
  } } : {}
250
265
  }, { signal: streamController.signal });
251
266
  const inactivityTimeout = Math.max(STREAM_INACTIVITY_TIMEOUT, ctx.maxTimeToFirstToken ?? 0);
@@ -264,28 +279,66 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
264
279
  }
265
280
  };
266
281
  raw = "";
267
- while (true) {
268
- var _chunk$value, _chunk$value2;
269
- let chunk;
270
- try {
271
- chunk = await nextChunk();
272
- } catch (thrown) {
273
- throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
282
+ let streamCompleted = false;
283
+ try {
284
+ while (true) {
285
+ var _chunk$value, _chunk$value2, _chunk$value3, _chunk$value4;
286
+ let chunk;
287
+ try {
288
+ chunk = await nextChunk();
289
+ } catch (thrown) {
290
+ throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
291
+ }
292
+ if (chunk.done) {
293
+ streamCompleted = true;
294
+ break;
295
+ }
296
+ if (((_chunk$value = chunk.value) === null || _chunk$value === void 0 ? void 0 : _chunk$value.restart) && !midStreamFallback) {
297
+ streamController.abort("Unexpected LLM stream restart");
298
+ throw new CognitiveError("LLM stream restarted without options.midStreamFallback enabled");
299
+ }
300
+ if ((_chunk$value2 = chunk.value) === null || _chunk$value2 === void 0 ? void 0 : _chunk$value2.restart) {
301
+ traces.push({
302
+ type: "llm_call_restarted",
303
+ started_at: Date.now(),
304
+ ...chunk.value.restart
305
+ });
306
+ raw = "";
307
+ parser = new StreamingMessageParser();
308
+ fence = new LeadingFenceFilter();
309
+ liveItems.clear();
310
+ liveContent.clear();
311
+ codeGenerationTraced = false;
312
+ runCompleted = false;
313
+ responseMetadata = void 0;
314
+ attempt = chunk.value.restart.attempt;
315
+ await preview({
316
+ ...chunk.value.restart,
317
+ restart: true,
318
+ iterationId: iteration.id
319
+ });
320
+ timeToFirstToken = void 0;
321
+ timeToLastToken = void 0;
322
+ continue;
323
+ }
324
+ if ((_chunk$value3 = chunk.value) === null || _chunk$value3 === void 0 ? void 0 : _chunk$value3.metadata) responseMetadata = chunk.value.metadata;
325
+ const delta = (_chunk$value4 = chunk.value) === null || _chunk$value4 === void 0 ? void 0 : _chunk$value4.output;
326
+ if (!delta) continue;
327
+ timeToLastToken = Date.now() - requestedAt;
328
+ timeToFirstToken ??= timeToLastToken;
329
+ raw += delta;
330
+ await dispatchSends(parser.push(fence.push(delta)));
274
331
  }
275
- if (chunk.done) break;
276
- if ((_chunk$value = chunk.value) === null || _chunk$value === void 0 ? void 0 : _chunk$value.metadata) responseMetadata = chunk.value.metadata;
277
- const delta = (_chunk$value2 = chunk.value) === null || _chunk$value2 === void 0 ? void 0 : _chunk$value2.output;
278
- if (!delta) continue;
279
- timeToLastToken = Date.now() - requestedAt;
280
- timeToFirstToken ??= timeToLastToken;
281
- raw += delta;
282
- await dispatchSends(parser.push(fence.push(delta)));
332
+ if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
333
+ const remaining = fence.flush();
334
+ if (remaining) await dispatchSends(parser.push(remaining));
335
+ await dispatchSends(parser.finish());
336
+ assistantResponse = toParsedAssistantResponse(parser.items, raw);
337
+ } finally {
338
+ streamController.abort("LLM stream closed");
339
+ if (!streamCompleted) stream.return(void 0).catch((err) => {});
283
340
  }
284
- if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
285
- const remaining = fence.flush();
286
- if (remaining) await dispatchSends(parser.push(remaining));
287
- await dispatchSends(parser.finish());
288
- assistantResponse = toParsedAssistantResponse(parser.items, raw);
341
+ if (midStreamFallback) controller.signal.throwIfAborted();
289
342
  } else {
290
343
  const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
291
344
  throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
@@ -294,7 +347,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
294
347
  responseMetadata = response.metadata;
295
348
  raw = response.output;
296
349
  assistantResponse = ctx.version.parseAssistantResponse(raw);
297
- for (const send of assistantResponse.sends) await (onSend === null || onSend === void 0 ? void 0 : onSend(send));
350
+ for (const [index, send] of assistantResponse.sends.entries()) await (onSend === null || onSend === void 0 ? void 0 : onSend(send, messageMetadata(`send-${index}`)));
298
351
  }
299
352
  iteration.code = assistantResponse.code;
300
353
  iteration.sends = assistantResponse.sends;
@@ -327,7 +380,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
327
380
  type: "llm_call_success",
328
381
  started_at: startedAt,
329
382
  ended_at: iteration.llm.ended_at,
330
- model: model.id,
383
+ model: iteration.llm.model,
331
384
  code: iteration.code ?? ""
332
385
  });
333
386
  };
@@ -570,7 +623,10 @@ function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook
570
623
  toolCallId
571
624
  }));
572
625
  if (typeof (beforeRes === null || beforeRes === void 0 ? void 0 : beforeRes.input) !== "undefined") effectiveInput = beforeRes.input;
573
- output = await tool.execute(effectiveInput, { callId: toolCallId }, chat);
626
+ output = await tool.execute(effectiveInput, {
627
+ callId: toolCallId,
628
+ iterationId: iteration.id
629
+ }, chat);
574
630
  const afterRes = await (afterHook === null || afterHook === void 0 ? void 0 : afterHook({
575
631
  iteration,
576
632
  tool,
@@ -675,7 +731,7 @@ const executeContext = async (props) => {
675
731
  return result;
676
732
  };
677
733
  const executeContextInternal = async (props) => {
678
- var _props$options, _props$options2, _props$options3, _props$options4, _props$options5;
734
+ var _props$options, _props$options2, _props$options3, _props$options4, _props$options5, _props$options6;
679
735
  const controller = createJoinedAbortController([props.signal]);
680
736
  const { onIterationStart, onIterationEnd, onTrace, onExit, onBeforeExecution, onAfterTool, onBeforeTool } = props;
681
737
  const client = props.client ?? new Client();
@@ -689,7 +745,8 @@ const executeContextInternal = async (props) => {
689
745
  timeout: (_props$options2 = props.options) === null || _props$options2 === void 0 ? void 0 : _props$options2.timeout,
690
746
  maxTokens: (_props$options3 = props.options) === null || _props$options3 === void 0 ? void 0 : _props$options3.maxTokens,
691
747
  maxTimeToFirstToken: (_props$options4 = props.options) === null || _props$options4 === void 0 ? void 0 : _props$options4.maxTimeToFirstToken,
692
- transcriptionModel: (_props$options5 = props.options) === null || _props$options5 === void 0 ? void 0 : _props$options5.transcriptionModel,
748
+ midStreamFallback: (_props$options5 = props.options) === null || _props$options5 === void 0 ? void 0 : _props$options5.midStreamFallback,
749
+ transcriptionModel: (_props$options6 = props.options) === null || _props$options6 === void 0 ? void 0 : _props$options6.transcriptionModel,
693
750
  exits: props.exits,
694
751
  snapshot: props.snapshot,
695
752
  model: props.model,
@@ -882,7 +939,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
882
939
  };
883
940
  });
884
941
  };
885
- const canExecuteEarly = typeof onBeforeExecution !== "function";
942
+ const canExecuteEarly = typeof onBeforeExecution !== "function" && !ctx.midStreamFallback;
886
943
  let earlyExecution;
887
944
  await generateCode({
888
945
  iteration,
@@ -900,7 +957,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
900
957
  promise: runCode(code)
901
958
  };
902
959
  } : void 0,
903
- onSend: async (send) => {
960
+ onSend: async (send, messageMetadata) => {
904
961
  if (!ctx.chat) return;
905
962
  const sendStartedAt = Date.now();
906
963
  const component = createJsxComponent({
@@ -909,7 +966,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
909
966
  children: send.body ? [send.body] : []
910
967
  });
911
968
  try {
912
- await ctx.chat.handler(component);
969
+ await ctx.chat.handler(component, messageMetadata);
913
970
  } catch (err) {
914
971
  throw new Error(`Error while sending message (■send=${send.name}): ${getErrorMessage(err)}`);
915
972
  }
package/dist/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_dual_modes = require("./dual-modes-wAOAlaBS.cjs");
3
- const require_custom_client = require("./custom-client-BPmEoWKu.cjs");
3
+ const require_custom_client = require("./custom-client-Cr33K60k.cjs");
4
4
  const require_utils = require("./utils-ZpJm00ed.cjs");
5
- const require_tool = require("./tool-DdPZb0JW.cjs");
5
+ const require_tool = require("./tool-ReA9gxMp.cjs");
6
6
  const require_errors = require("./errors-C962uJdS.cjs");
7
7
  const require_typings = require("./typings-BwAz_TM9.cjs");
8
8
  const require_exit = require("./exit-BGi0Kk0y.cjs");
@@ -11,7 +11,7 @@ const require_truncator = require("./truncator-B6aaJaN1.cjs");
11
11
  const require_quickjs_variant = require("./quickjs-variant-CsIwTVFC.cjs");
12
12
  let _bpinternal_zui = require("@bpinternal/zui");
13
13
  //#region package.json
14
- var version = "0.6.4";
14
+ var version = "0.6.6";
15
15
  //#endregion
16
16
  //#region src/hoist.ts
17
17
  /**
@@ -1774,7 +1774,7 @@ const utils = {
1774
1774
  * })
1775
1775
  */
1776
1776
  const execute = async (props) => {
1777
- const { executeContext } = await Promise.resolve().then(() => require("./execute-BEaq3jkV.cjs"));
1777
+ const { executeContext } = await Promise.resolve().then(() => require("./execute-BmEjJjka.cjs"));
1778
1778
  return executeContext(props);
1779
1779
  };
1780
1780
  /**
@@ -1783,9 +1783,9 @@ const execute = async (props) => {
1783
1783
  * It's recommended to call this function at the beginning of your application without awaiting it (void init())
1784
1784
  */
1785
1785
  const init = async () => {
1786
- await Promise.resolve().then(() => require("./execute-BEaq3jkV.cjs"));
1786
+ await Promise.resolve().then(() => require("./execute-BmEjJjka.cjs"));
1787
1787
  await Promise.resolve().then(() => require("./component-BwixNVH8.cjs")).then((n) => n.component_exports);
1788
- await Promise.resolve().then(() => require("./tool-DdPZb0JW.cjs")).then((n) => n.tool_exports);
1788
+ await Promise.resolve().then(() => require("./tool-ReA9gxMp.cjs")).then((n) => n.tool_exports);
1789
1789
  await Promise.resolve().then(() => require("./exit-BGi0Kk0y.cjs")).then((n) => n.exit_exports);
1790
1790
  await Promise.resolve().then(() => require("./jsx-BWvT6ukg.cjs")).then((n) => n.jsx_exports);
1791
1791
  await Promise.resolve().then(() => require("./vm-BjkJqSQH.cjs"));
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ export { Component, type RenderedComponent, type LeafComponentDefinition, type C
8
8
  export { type Citation, CitationsManager } from './citations.js';
9
9
  export { DefaultComponents } from './component.default.js';
10
10
  export { Snapshot } from './snapshots.js';
11
- export { Chat, type MessageHandler, type MessageDelta, type MessageDeltaHandler } from './chat.js';
11
+ export { Chat, type MessageHandler, type MessageMetadata, type MessageDelta, type MessageDeltaHandler } from './chat.js';
12
12
  import { ExecutionResult } from './result.js';
13
13
  import { type ExecutionProps } from './runtime/types.js';
14
14
  import { stripTruncationTags, truncateWrappedContent, wrapContent } from './truncator.js';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as StreamingMessageParser, c as NAME_REGEX, o as tryParseJson, r as generateInstructions, s as MARKER } from "./dual-modes-D_p-jedw.js";
2
- import { a as ThinkExit, c as ExecutionResult, d as Snapshot, f as parseExit, i as ListenExit, l as PartialExecutionResult, o as getValue, r as DefaultExit, s as ErrorExecutionResult, t as _CustomModelClient, u as SuccessExecutionResult } from "./custom-client-NUoxrFQh.js";
2
+ import { a as ThinkExit, c as ExecutionResult, d as Snapshot, f as parseExit, i as ListenExit, l as PartialExecutionResult, o as getValue, r as DefaultExit, s as ErrorExecutionResult, t as _CustomModelClient, u as SuccessExecutionResult } from "./custom-client-CJIThG2H.js";
3
3
  import { a as getMultilineComment, c as isJsonSchema, l as isValidIdentifier, m as toValidObjectName, n as escapeString, p as toValidFunctionName, t as configureTokenizer, u as isZuiSchema, v as upperFirst } from "./utils-UBeAFeEI.js";
4
- import { t as Tool } from "./tool-CAo-BQHs.js";
4
+ import { t as Tool } from "./tool-Bv8N4IPj.js";
5
5
  import { c as SnapshotSignal, l as ThinkSignal, o as LoopExceededError, r as CodeFormattingError } from "./errors-Cg1G0Awu.js";
6
6
  import { a as isPunct, i as isGroup, o as parse, r as formatTypings, s as tokenize, t as getTypings } from "./typings-CrBa7Tyy.js";
7
7
  import { t as Exit } from "./exit-CDdxDBRT.js";
@@ -10,7 +10,7 @@ import { i as wrapContent, n as truncateWrappedContent, t as stripTruncationTags
10
10
  import { t as configureQuickJS } from "./quickjs-variant-BYhMBpwU.js";
11
11
  import { transforms, z } from "@bpinternal/zui";
12
12
  //#region package.json
13
- var version = "0.6.4";
13
+ var version = "0.6.6";
14
14
  //#endregion
15
15
  //#region src/hoist.ts
16
16
  /**
@@ -1773,7 +1773,7 @@ const utils = {
1773
1773
  * })
1774
1774
  */
1775
1775
  const execute = async (props) => {
1776
- const { executeContext } = await import("./execute-DYvFRs54.js");
1776
+ const { executeContext } = await import("./execute-sn9RT_IN.js");
1777
1777
  return executeContext(props);
1778
1778
  };
1779
1779
  /**
@@ -1782,9 +1782,9 @@ const execute = async (props) => {
1782
1782
  * It's recommended to call this function at the beginning of your application without awaiting it (void init())
1783
1783
  */
1784
1784
  const init = async () => {
1785
- await import("./execute-DYvFRs54.js");
1785
+ await import("./execute-sn9RT_IN.js");
1786
1786
  await import("./component-DGG7d_Mz.js").then((n) => n.r);
1787
- await import("./tool-CAo-BQHs.js").then((n) => n.n);
1787
+ await import("./tool-Bv8N4IPj.js").then((n) => n.n);
1788
1788
  await import("./exit-CDdxDBRT.js").then((n) => n.n);
1789
1789
  await import("./jsx-CIgdGGVs.js").then((n) => n.i);
1790
1790
  await import("./vm-C5vf1LH3.js");
@@ -52,7 +52,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
52
52
  }) : target, mod));
53
53
  //#endregion
54
54
  //#region package.json
55
- var version = "0.6.4";
55
+ var version = "0.6.6";
56
56
  //#endregion
57
57
  //#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_freeGlobal.js
58
58
  var freeGlobal;
@@ -7682,7 +7682,10 @@ var init_tool = __esmMin((() => {
7682
7682
  if (done) return value;
7683
7683
  if (yieldIndex >= yieldedCount) {
7684
7684
  setYieldedCount(yieldIndex + 1);
7685
- await chat?.handler?.(value);
7685
+ await chat?.handler?.(value, {
7686
+ iterationId: ctx.iterationId ?? ctx.callId,
7687
+ id: `${ctx.callId}:yield-${yieldIndex}`
7688
+ });
7686
7689
  }
7687
7690
  yieldIndex++;
7688
7691
  }
@@ -12215,6 +12218,17 @@ var init_context = __esmMin((() => {
12215
12218
  */
12216
12219
  maxTimeToFirstToken;
12217
12220
  /**
12221
+ * Allow Cognitive to restart a failed stream on another model. With fallback
12222
+ * enabled, there is no buffered delivery and no final delivery queue: delta
12223
+ * text and completed Chat.handler sends stream immediately during generation.
12224
+ * A reset-only delta (restart: true) on Chat.onMessageDelta invalidates ALL
12225
+ * current-iteration messages, including completed sends — consumers must
12226
+ * retract/replace them, which is unsafe for irreversible external transports.
12227
+ * Only TOOL/CODE execution waits for a successful stream. Streaming-only;
12228
+ * defaults to false, which leaves progressive sending unchanged.
12229
+ */
12230
+ midStreamFallback;
12231
+ /**
12218
12232
  * STT model used by the cognitive service to transcribe audio attachments
12219
12233
  * when the target LLM does not support audio natively. Defaults to 'fast'.
12220
12234
  */
@@ -12449,10 +12463,12 @@ var init_context = __esmMin((() => {
12449
12463
  this.snapshot = props.snapshot;
12450
12464
  this.maxTokens = props.maxTokens;
12451
12465
  this.maxTimeToFirstToken = props.maxTimeToFirstToken;
12466
+ this.midStreamFallback = props.midStreamFallback;
12452
12467
  this.transcriptionModel = props.transcriptionModel;
12453
12468
  if (this.loop < 1 || this.loop > 100) throw new Error("Invalid loop. Expected a number between 1 and 100.");
12454
12469
  if (this.maxTokens !== void 0 && (!Number.isFinite(this.maxTokens) || this.maxTokens < 1)) throw new Error("Invalid maxTokens. Expected a positive number.");
12455
12470
  if (this.maxTimeToFirstToken !== void 0 && (!Number.isFinite(this.maxTimeToFirstToken) || this.maxTimeToFirstToken < 1)) throw new Error("Invalid maxTimeToFirstToken. Expected a positive number of milliseconds.");
12471
+ if (this.midStreamFallback !== void 0 && typeof this.midStreamFallback !== "boolean") throw new Error("Invalid midStreamFallback. Expected a boolean.");
12456
12472
  }
12457
12473
  toJSON() {
12458
12474
  return {
@@ -17023,7 +17039,7 @@ var init_generate = __esmMin((() => {
17023
17039
  MAX_TOKENS: 16e3,
17024
17040
  PERCENTAGE: .1
17025
17041
  };
17026
- STREAM_INACTIVITY_TIMEOUT = 6e4;
17042
+ STREAM_INACTIVITY_TIMEOUT = 18e4;
17027
17043
  getModelOutputLimit = (inputLength) => clamp(RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength, RESPONSE_LENGTH_BUFFER.MIN_TOKENS, RESPONSE_LENGTH_BUFFER.MAX_TOKENS);
17028
17044
  LeadingFenceFilter = class {
17029
17045
  _buffer = "";
@@ -17093,6 +17109,19 @@ var init_generate = __esmMin((() => {
17093
17109
  /** Milliseconds between the stream request and the first/last streamed tokens. */
17094
17110
  let timeToFirstToken;
17095
17111
  let timeToLastToken;
17112
+ const midStreamFallback = ctx.midStreamFallback === true;
17113
+ let attempt = 1;
17114
+ const messageMetadata = (itemId) => ({
17115
+ iterationId: iteration.id,
17116
+ id: midStreamFallback ? `${iteration.id}:${attempt}:${itemId}` : `${iteration.id}:${itemId}`
17117
+ });
17118
+ const preview = async (delta) => {
17119
+ try {
17120
+ await onSendDelta?.(delta);
17121
+ } catch (err) {
17122
+ if (delta.restart) throw new CognitiveError(`LLM stream restart handler failed: ${getErrorMessage(err)}`);
17123
+ }
17124
+ };
17096
17125
  const liveItems = /* @__PURE__ */ new Map();
17097
17126
  const liveContent = /* @__PURE__ */ new Map();
17098
17127
  let codeGenerationTraced = false;
@@ -17113,37 +17142,39 @@ var init_generate = __esmMin((() => {
17113
17142
  if (item?.kind !== "send") continue;
17114
17143
  const content = (liveContent.get(item.id) ?? "") + event.delta;
17115
17144
  liveContent.set(item.id, content);
17116
- try {
17117
- await onSendDelta({
17118
- id: `${iteration.id}:${item.id}`,
17119
- component: item.name,
17120
- props: item.props,
17121
- delta: event.delta,
17122
- content
17123
- });
17124
- } catch (err) {}
17145
+ const delta = {
17146
+ restart: false,
17147
+ ...messageMetadata(item.id),
17148
+ component: item.name,
17149
+ props: item.props,
17150
+ delta: event.delta,
17151
+ content
17152
+ };
17153
+ await preview(delta);
17125
17154
  } else if (event.type === "item-complete") {
17126
17155
  if (event.item.kind === "send" && onSend) await onSend({
17127
17156
  name: event.item.name,
17128
17157
  props: event.item.props,
17129
17158
  body: event.item.body
17130
- });
17159
+ }, messageMetadata(event.item.id));
17131
17160
  else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
17132
17161
  runCompleted = true;
17133
- onRunComplete?.((event.item.body ?? "").trim());
17162
+ const code = (event.item.body ?? "").trim();
17163
+ onRunComplete?.(code);
17134
17164
  }
17135
17165
  }
17136
17166
  };
17137
17167
  if (typeof cognitive.generateTextStream === "function") {
17138
- const parser = new StreamingMessageParser();
17139
- const fence = new LeadingFenceFilter();
17168
+ let parser = new StreamingMessageParser();
17169
+ let fence = new LeadingFenceFilter();
17140
17170
  const streamController = createJoinedAbortController([controller.signal]);
17141
17171
  const requestedAt = Date.now();
17142
17172
  const stream = cognitive.generateTextStream({
17143
17173
  ...input,
17144
- ...ctx.maxTimeToFirstToken ? { options: {
17174
+ ...ctx.maxTimeToFirstToken || midStreamFallback ? { options: {
17145
17175
  ...input.options,
17146
- maxTimeToFirstToken: ctx.maxTimeToFirstToken
17176
+ ...ctx.maxTimeToFirstToken ? { maxTimeToFirstToken: ctx.maxTimeToFirstToken } : {},
17177
+ ...midStreamFallback ? { midStreamFallback: true } : {}
17147
17178
  } } : {}
17148
17179
  }, { signal: streamController.signal });
17149
17180
  const inactivityTimeout = Math.max(STREAM_INACTIVITY_TIMEOUT, ctx.maxTimeToFirstToken ?? 0);
@@ -17162,27 +17193,65 @@ var init_generate = __esmMin((() => {
17162
17193
  }
17163
17194
  };
17164
17195
  raw = "";
17165
- while (true) {
17166
- let chunk;
17167
- try {
17168
- chunk = await nextChunk();
17169
- } catch (thrown) {
17170
- throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
17196
+ let streamCompleted = false;
17197
+ try {
17198
+ while (true) {
17199
+ let chunk;
17200
+ try {
17201
+ chunk = await nextChunk();
17202
+ } catch (thrown) {
17203
+ throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
17204
+ }
17205
+ if (chunk.done) {
17206
+ streamCompleted = true;
17207
+ break;
17208
+ }
17209
+ if (chunk.value?.restart && !midStreamFallback) {
17210
+ streamController.abort("Unexpected LLM stream restart");
17211
+ throw new CognitiveError("LLM stream restarted without options.midStreamFallback enabled");
17212
+ }
17213
+ if (chunk.value?.restart) {
17214
+ traces.push({
17215
+ type: "llm_call_restarted",
17216
+ started_at: Date.now(),
17217
+ ...chunk.value.restart
17218
+ });
17219
+ raw = "";
17220
+ parser = new StreamingMessageParser();
17221
+ fence = new LeadingFenceFilter();
17222
+ liveItems.clear();
17223
+ liveContent.clear();
17224
+ codeGenerationTraced = false;
17225
+ runCompleted = false;
17226
+ responseMetadata = void 0;
17227
+ attempt = chunk.value.restart.attempt;
17228
+ await preview({
17229
+ ...chunk.value.restart,
17230
+ restart: true,
17231
+ iterationId: iteration.id
17232
+ });
17233
+ timeToFirstToken = void 0;
17234
+ timeToLastToken = void 0;
17235
+ continue;
17236
+ }
17237
+ if (chunk.value?.metadata) responseMetadata = chunk.value.metadata;
17238
+ const delta = chunk.value?.output;
17239
+ if (!delta) continue;
17240
+ timeToLastToken = Date.now() - requestedAt;
17241
+ timeToFirstToken ??= timeToLastToken;
17242
+ raw += delta;
17243
+ await dispatchSends(parser.push(fence.push(delta)));
17171
17244
  }
17172
- if (chunk.done) break;
17173
- if (chunk.value?.metadata) responseMetadata = chunk.value.metadata;
17174
- const delta = chunk.value?.output;
17175
- if (!delta) continue;
17176
- timeToLastToken = Date.now() - requestedAt;
17177
- timeToFirstToken ??= timeToLastToken;
17178
- raw += delta;
17179
- await dispatchSends(parser.push(fence.push(delta)));
17245
+ if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
17246
+ const remaining = fence.flush();
17247
+ if (remaining) await dispatchSends(parser.push(remaining));
17248
+ await dispatchSends(parser.finish());
17249
+ assistantResponse = toParsedAssistantResponse(parser.items, raw);
17250
+ } finally {
17251
+ streamController.abort("LLM stream closed");
17252
+ if (!streamCompleted) stream.return(void 0).catch((err) => {});
17180
17253
  }
17181
- if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
17182
- const remaining = fence.flush();
17183
- if (remaining) await dispatchSends(parser.push(remaining));
17184
- await dispatchSends(parser.finish());
17185
- assistantResponse = toParsedAssistantResponse(parser.items, raw);
17254
+ if (midStreamFallback) controller.signal.throwIfAborted();
17186
17255
  } else {
17187
17256
  const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
17188
17257
  throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
@@ -17191,7 +17260,7 @@ var init_generate = __esmMin((() => {
17191
17260
  responseMetadata = response.metadata;
17192
17261
  raw = response.output;
17193
17262
  assistantResponse = ctx.version.parseAssistantResponse(raw);
17194
- for (const send of assistantResponse.sends) await onSend?.(send);
17263
+ for (const [index, send] of assistantResponse.sends.entries()) await onSend?.(send, messageMetadata(`send-${index}`));
17195
17264
  }
17196
17265
  iteration.code = assistantResponse.code;
17197
17266
  iteration.sends = assistantResponse.sends;
@@ -17224,7 +17293,7 @@ var init_generate = __esmMin((() => {
17224
17293
  type: "llm_call_success",
17225
17294
  started_at: startedAt,
17226
17295
  ended_at: iteration.llm.ended_at,
17227
- model: model.id,
17296
+ model: iteration.llm.model,
17228
17297
  code: iteration.code ?? ""
17229
17298
  });
17230
17299
  };
@@ -17471,7 +17540,10 @@ function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook
17471
17540
  toolCallId
17472
17541
  });
17473
17542
  if (typeof beforeRes?.input !== "undefined") effectiveInput = beforeRes.input;
17474
- output = await tool.execute(effectiveInput, { callId: toolCallId }, chat);
17543
+ output = await tool.execute(effectiveInput, {
17544
+ callId: toolCallId,
17545
+ iterationId: iteration.id
17546
+ }, chat);
17475
17547
  const afterRes = await afterHook?.({
17476
17548
  iteration,
17477
17549
  tool,
@@ -17614,6 +17686,7 @@ var init_execute = __esmMin((() => {
17614
17686
  timeout: props.options?.timeout,
17615
17687
  maxTokens: props.options?.maxTokens,
17616
17688
  maxTimeToFirstToken: props.options?.maxTimeToFirstToken,
17689
+ midStreamFallback: props.options?.midStreamFallback,
17617
17690
  transcriptionModel: props.options?.transcriptionModel,
17618
17691
  exits: props.exits,
17619
17692
  snapshot: props.snapshot,
@@ -17805,7 +17878,7 @@ var init_execute = __esmMin((() => {
17805
17878
  };
17806
17879
  });
17807
17880
  };
17808
- const canExecuteEarly = typeof onBeforeExecution !== "function";
17881
+ const canExecuteEarly = typeof onBeforeExecution !== "function" && !ctx.midStreamFallback;
17809
17882
  let earlyExecution;
17810
17883
  await generateCode({
17811
17884
  iteration,
@@ -17823,7 +17896,7 @@ var init_execute = __esmMin((() => {
17823
17896
  promise: runCode(code)
17824
17897
  };
17825
17898
  } : void 0,
17826
- onSend: async (send) => {
17899
+ onSend: async (send, messageMetadata) => {
17827
17900
  if (!ctx.chat) return;
17828
17901
  const sendStartedAt = Date.now();
17829
17902
  const component = createJsxComponent({
@@ -17832,7 +17905,7 @@ var init_execute = __esmMin((() => {
17832
17905
  children: send.body ? [send.body] : []
17833
17906
  });
17834
17907
  try {
17835
- await ctx.chat.handler(component);
17908
+ await ctx.chat.handler(component, messageMetadata);
17836
17909
  } catch (err) {
17837
17910
  throw new Error(`Error while sending message (■send=${send.name}): ${getErrorMessage(err)}`);
17838
17911
  }
@@ -1,4 +1,4 @@
1
- import type { MessageDelta } from '../chat.js';
1
+ import type { MessageDelta, MessageMetadata } from '../chat.js';
2
2
  import { Context, Iteration } from '../context.js';
3
3
  import type { ParsedSend } from '../prompts/prompt.js';
4
4
  import { RuntimeCognitive } from './types.js';
@@ -12,10 +12,11 @@ type GenerateCodeProps = {
12
12
  * Called for each completed `■send` block. On streaming clients this fires
13
13
  * while the model is still generating — messages are delivered progressively.
14
14
  */
15
- onSend?: (send: ParsedSend) => Promise<void>;
15
+ onSend?: (send: ParsedSend, metadata: MessageMetadata) => Promise<void>;
16
16
  /**
17
17
  * Called for each `■send` body chunk as it is parsed from the stream
18
- * (streaming clients only). Best-effort: errors are ignored.
18
+ * (streaming clients only), or with a restart delta before replacement output.
19
+ * Text errors are best-effort; restart errors terminate generation.
19
20
  */
20
21
  onSendDelta?: (delta: MessageDelta) => Promise<void> | void;
21
22
  /**
@@ -122,6 +122,16 @@ type Options = Partial<Pick<Context, 'loop' | 'timeout'>> & {
122
122
  * `model` is an array of fallback models.
123
123
  */
124
124
  maxTimeToFirstToken?: number;
125
+ /**
126
+ * Allow Cognitive to restart failed streams on another model. No buffered
127
+ * delivery and no final delivery queue: delta text and completed Chat.handler
128
+ * sends stream immediately during generation. A reset-only delta (restart:
129
+ * true) on Chat.onMessageDelta invalidates ALL current-iteration messages,
130
+ * including completed sends — consumers must retract/replace them (not safe for
131
+ * irreversible transports). Only TOOL/CODE execution waits for a successful
132
+ * stream. Streaming-only; defaults to false, preserving progressive sending.
133
+ */
134
+ midStreamFallback?: boolean;
125
135
  /**
126
136
  * STT model used to transcribe audio attachments (voice messages) when the
127
137
  * target LLM does not support audio natively. Audio-capable models receive
@@ -500,7 +500,10 @@ var Tool = class Tool {
500
500
  if (yieldIndex >= yieldedCount) {
501
501
  var _chat$handler;
502
502
  setYieldedCount(yieldIndex + 1);
503
- await (chat === null || chat === void 0 || (_chat$handler = chat.handler) === null || _chat$handler === void 0 ? void 0 : _chat$handler.call(chat, value));
503
+ await (chat === null || chat === void 0 || (_chat$handler = chat.handler) === null || _chat$handler === void 0 ? void 0 : _chat$handler.call(chat, value, {
504
+ iterationId: ctx.iterationId ?? ctx.callId,
505
+ id: `${ctx.callId}:yield-${yieldIndex}`
506
+ }));
504
507
  }
505
508
  yieldIndex++;
506
509
  }
@@ -500,7 +500,10 @@ var Tool = class Tool {
500
500
  if (yieldIndex >= yieldedCount) {
501
501
  var _chat$handler;
502
502
  setYieldedCount(yieldIndex + 1);
503
- await (chat === null || chat === void 0 || (_chat$handler = chat.handler) === null || _chat$handler === void 0 ? void 0 : _chat$handler.call(chat, value));
503
+ await (chat === null || chat === void 0 || (_chat$handler = chat.handler) === null || _chat$handler === void 0 ? void 0 : _chat$handler.call(chat, value, {
504
+ iterationId: ctx.iterationId ?? ctx.callId,
505
+ id: `${ctx.callId}:yield-${yieldIndex}`
506
+ }));
504
507
  }
505
508
  yieldIndex++;
506
509
  }
package/dist/tool.d.ts CHANGED
@@ -49,6 +49,8 @@ type SmartPartial<T> = IsObject<T> extends true ? Partial<T> : T;
49
49
  type ToolCallContext = {
50
50
  /** Unique identifier for this specific tool call */
51
51
  callId: string;
52
+ /** Set by the runtime; standalone calls use callId as their message scope. */
53
+ iterationId?: string;
52
54
  };
53
55
  export declare namespace Tool {
54
56
  type JSON = {
package/dist/types.d.ts CHANGED
@@ -55,6 +55,13 @@ export declare namespace Traces {
55
55
  model: string;
56
56
  code: string;
57
57
  }>;
58
+ /** Diagnostic only: content and effects from the preceding attempt are discarded. */
59
+ type LLMCallRestart = TraceTemplate<'llm_call_restarted', {
60
+ attempt: number;
61
+ fromModel: string;
62
+ toModel: string;
63
+ reason: string;
64
+ }>;
58
65
  /**
59
66
  * Emitted on streaming clients the moment the model starts writing a `■run`
60
67
  * block — before the code is fully generated. Useful to show a
@@ -77,7 +84,7 @@ export declare namespace Traces {
77
84
  started_at: number;
78
85
  ended_at?: number;
79
86
  } & Content;
80
- type Trace = Comment | Log | ToolCall | ToolSlow | PropertyMutation | YieldTrace | LLMCallStart | LLMCallSuccess | CodeGenerationStart | ThinkSignal | CodeExecution | CodeExecutionException | InvalidCodeExceptionTrace | AbortTrace;
87
+ type Trace = Comment | Log | ToolCall | ToolSlow | PropertyMutation | YieldTrace | LLMCallStart | LLMCallSuccess | LLMCallRestart | CodeGenerationStart | ThinkSignal | CodeExecution | CodeExecutionException | InvalidCodeExceptionTrace | AbortTrace;
81
88
  }
82
89
  export type Trace = Traces.Trace;
83
90
  export type VMExecutionResult = {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "llmz",
3
3
  "type": "module",
4
4
  "description": "LLMz - An LLM-native Typescript VM built on top of Zui",
5
- "version": "0.6.4",
5
+ "version": "0.6.6",
6
6
  "files": [
7
7
  "dist",
8
8
  "DOCS.md"