llmz 0.1.5 → 0.2.0

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.
Files changed (75) hide show
  1. package/README.md +185 -98
  2. package/dist/chat.d.ts +34 -0
  3. package/dist/{chunk-TIZWOIDF.js → chunk-33AB6SVX.js} +134 -76
  4. package/dist/{chunk-EFEF2AL7.js → chunk-DH35WO5G.js} +93 -556
  5. package/dist/chunk-E5NHK3FS.js +1637 -0
  6. package/dist/{chunk-L74UZONX.js → chunk-HM5H556L.js} +3 -1
  7. package/dist/chunk-I56MPOVG.cjs +62 -0
  8. package/dist/{chunk-C7T6OJB4.cjs → chunk-IKLFMVSW.cjs} +144 -86
  9. package/dist/chunk-KWQTYXAT.js +62 -0
  10. package/dist/{chunk-JXD2KJVB.cjs → chunk-WWZ2W4WR.cjs} +103 -566
  11. package/dist/chunk-YGKQEVQQ.cjs +1637 -0
  12. package/dist/{chunk-ZPHRTTQX.cjs → chunk-YQT5G77W.cjs} +3 -1
  13. package/dist/compiler/compiler.d.ts +7 -2
  14. package/dist/compiler/index.d.ts +1 -1
  15. package/dist/compiler/plugins/async-wrapper.d.ts +11 -0
  16. package/dist/component-2NYFY6CW.cjs +14 -0
  17. package/dist/{component-2Z3KLWLX.js → component-ASNZHQUR.js} +3 -7
  18. package/dist/component.d.ts +3 -10
  19. package/dist/context.d.ts +88 -2
  20. package/dist/{dual-modes-HEXPFVUE.js → dual-modes-RMF7V7ZQ.js} +2 -4
  21. package/dist/dual-modes-ZZY6QPYT.cjs +10 -0
  22. package/dist/{execute-22PSGL7P.cjs → execute-BXPFSEVX.cjs} +331 -87
  23. package/dist/{execute-ZENBZBWL.js → execute-HIRXXR6X.js} +321 -77
  24. package/dist/index.cjs +502 -27
  25. package/dist/index.d.ts +8 -5
  26. package/dist/index.js +491 -16
  27. package/dist/message-stream/index.d.ts +9 -0
  28. package/dist/message-stream/instructions.d.ts +22 -0
  29. package/dist/message-stream/normalizer.d.ts +21 -0
  30. package/dist/message-stream/parser.d.ts +81 -0
  31. package/dist/message-stream/registry.d.ts +14 -0
  32. package/dist/message-stream/replayable.d.ts +27 -0
  33. package/dist/message-stream/sanitize.d.ts +10 -0
  34. package/dist/message-stream/stream.d.ts +54 -0
  35. package/dist/message-stream/types.d.ts +96 -0
  36. package/dist/message-stream/validator.d.ts +23 -0
  37. package/dist/message-stream/validator.test.d.ts +1 -0
  38. package/dist/prompts/chat-mode/system.md.d.ts +1 -1
  39. package/dist/prompts/chat-mode/user.md.d.ts +1 -1
  40. package/dist/prompts/common.d.ts +5 -5
  41. package/dist/prompts/prompt.d.ts +43 -6
  42. package/dist/prompts/protocol.d.ts +18 -0
  43. package/dist/prompts/worker-mode/system.md.d.ts +1 -1
  44. package/dist/prompts/worker-mode/user.md.d.ts +1 -1
  45. package/dist/result.d.ts +31 -0
  46. package/dist/runtime/execute.test.d.ts +1 -0
  47. package/dist/runtime/generate.d.ts +24 -1
  48. package/dist/runtime/interpret-result.d.ts +10 -0
  49. package/dist/runtime/types.d.ts +29 -4
  50. package/dist/truncator-7PGEGCHV.cjs +12 -0
  51. package/dist/{truncator-3U2QUUJJ.js → truncator-OZOBNYON.js} +3 -1
  52. package/dist/truncator.d.ts +2 -0
  53. package/dist/types.d.ts +8 -1
  54. package/dist/vm/drivers/quickjs.d.ts +2 -0
  55. package/dist/vm/index.d.ts +7 -0
  56. package/dist/vm/instrument.d.ts +1 -1
  57. package/dist/{vm-PYCKS77H.js → vm-44H4UKI2.js} +5 -4
  58. package/dist/{vm-VHB67FVH.cjs → vm-A3OTQVIR.cjs} +4 -3
  59. package/package.json +5 -5
  60. package/dist/chunk-2O3UTPVH.js +0 -813
  61. package/dist/chunk-3T5IU7OU.js +0 -186
  62. package/dist/chunk-BBX2LDZE.cjs +0 -813
  63. package/dist/chunk-CQ3UJW76.cjs +0 -186
  64. package/dist/compiler/plugins/async-iterator.d.ts +0 -6
  65. package/dist/compiler/plugins/braces-tsx.d.ts +0 -3
  66. package/dist/compiler/plugins/html-to-markdown.d.ts +0 -21
  67. package/dist/compiler/plugins/jsx-preserve-newlines.d.ts +0 -5
  68. package/dist/compiler/plugins/jsx-undefined-vars.d.ts +0 -14
  69. package/dist/component-NNHBHD72.cjs +0 -18
  70. package/dist/dual-modes-LLIWZCHC.cjs +0 -12
  71. package/dist/truncator-3ZN7W6NB.cjs +0 -10
  72. /package/dist/{compiler/plugins/html-to-markdown.test.d.ts → message-stream/instructions.test.d.ts} +0 -0
  73. /package/dist/{compiler/plugins/jsx-undefined-vars.test.d.ts → message-stream/normalizer.test.d.ts} +0 -0
  74. /package/dist/{component.test.d.ts → message-stream/parser.test.d.ts} +0 -0
  75. /package/dist/{vm/vm-jsx.test.d.ts → message-stream/stream.test.d.ts} +0 -0
@@ -1,6 +1,8 @@
1
1
  import {
2
- runAsyncFunction
3
- } from "./chunk-EFEF2AL7.js";
2
+ hasTopLevelReturn,
3
+ runAsyncFunction,
4
+ warmupVM
5
+ } from "./chunk-DH35WO5G.js";
4
6
  import {
5
7
  Context,
6
8
  ErrorExecutionResult,
@@ -9,8 +11,11 @@ import {
9
11
  SuccessExecutionResult,
10
12
  _CustomModelClient,
11
13
  parseExit
12
- } from "./chunk-TIZWOIDF.js";
13
- import "./chunk-2O3UTPVH.js";
14
+ } from "./chunk-33AB6SVX.js";
15
+ import {
16
+ StreamingMessageParser,
17
+ toParsedAssistantResponse
18
+ } from "./chunk-E5NHK3FS.js";
14
19
  import "./chunk-IRCB4FRM.js";
15
20
  import "./chunk-TOGYDN6U.js";
16
21
  import {
@@ -27,11 +32,13 @@ import {
27
32
  cleanStackTrace
28
33
  } from "./chunk-YEAWWJSJ.js";
29
34
  import "./chunk-XVVYNOTX.js";
30
- import "./chunk-3T5IU7OU.js";
31
- import "./chunk-XTEHT2TK.js";
35
+ import "./chunk-KWQTYXAT.js";
36
+ import {
37
+ createJsxComponent
38
+ } from "./chunk-XTEHT2TK.js";
32
39
  import {
33
40
  truncateWrappedContent
34
- } from "./chunk-L74UZONX.js";
41
+ } from "./chunk-HM5H556L.js";
35
42
  import {
36
43
  getErrorMessage,
37
44
  init,
@@ -39,9 +46,7 @@ import {
39
46
  } from "./chunk-YX27XM67.js";
40
47
  import {
41
48
  clamp_default,
42
- isEqual_default,
43
- isPlainObject_default,
44
- omit_default
49
+ isEqual_default
45
50
  } from "./chunk-34GJUS6U.js";
46
51
 
47
52
  // src/runtime/execute.ts
@@ -83,26 +88,78 @@ var RESPONSE_LENGTH_BUFFER = {
83
88
  MAX_TOKENS: 16e3,
84
89
  PERCENTAGE: 0.1
85
90
  };
91
+ var STREAM_INACTIVITY_TIMEOUT = 6e4;
86
92
  var getModelOutputLimit = (inputLength) => clamp_default(
87
93
  RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength,
88
94
  RESPONSE_LENGTH_BUFFER.MIN_TOKENS,
89
95
  RESPONSE_LENGTH_BUFFER.MAX_TOKENS
90
96
  );
91
- var generateCode = async ({ iteration, ctx, cognitive, controller, metadata }) => {
92
- var _a, _b, _c;
97
+ var LeadingFenceFilter = class {
98
+ _buffer = "";
99
+ _done = false;
100
+ push(text) {
101
+ if (this._done) {
102
+ return text;
103
+ }
104
+ this._buffer += text;
105
+ const newline = this._buffer.indexOf("\n");
106
+ if (newline === -1) {
107
+ return "";
108
+ }
109
+ this._done = true;
110
+ const firstLine = this._buffer.slice(0, newline);
111
+ const rest = this._buffer.slice(newline + 1);
112
+ this._buffer = "";
113
+ return firstLine.trim().startsWith("```") ? rest : `${firstLine}
114
+ ${rest}`;
115
+ }
116
+ flush() {
117
+ if (this._done) {
118
+ return "";
119
+ }
120
+ this._done = true;
121
+ const buffered = this._buffer;
122
+ this._buffer = "";
123
+ return buffered.trim().startsWith("```") ? "" : buffered;
124
+ }
125
+ };
126
+ var generateCode = async ({
127
+ iteration,
128
+ ctx,
129
+ cognitive,
130
+ controller,
131
+ metadata,
132
+ onSend,
133
+ onSendDelta,
134
+ onRunStart,
135
+ onRunComplete
136
+ }) => {
137
+ var _a, _b, _c, _d;
93
138
  const startedAt = Date.now();
94
139
  const traces = iteration.traces;
95
140
  const modelRef = Array.isArray(iteration.model) ? iteration.model[0] : iteration.model;
96
141
  const model = await cognitive.getModelDetails(modelRef).catch((thrown) => {
97
142
  throw new CognitiveError(`Failed to fetch model details for model "${modelRef}": ${getErrorMessage(thrown)}`);
98
143
  });
99
- const modelLimit = Math.max(model.input.maxTokens, 8e3);
144
+ let modelLimit = Math.max(model.input.maxTokens, 8e3);
145
+ if (ctx.maxTokens) {
146
+ modelLimit = Math.min(ctx.maxTokens, modelLimit);
147
+ }
100
148
  const responseLengthBuffer = getModelOutputLimit(modelLimit);
101
- const messages = truncateWrappedContent({
102
- messages: iteration.messages,
103
- tokenLimit: modelLimit - responseLengthBuffer,
104
- throwOnFailure: true
105
- }).filter((x) => typeof x.content !== "string" || x.content.trim().length > 0);
149
+ if (iteration.tokens) {
150
+ iteration.tokens.limit = modelLimit;
151
+ }
152
+ let messages;
153
+ try {
154
+ messages = truncateWrappedContent({
155
+ messages: iteration.messages,
156
+ tokenLimit: modelLimit - responseLengthBuffer,
157
+ throwOnFailure: true
158
+ }).filter((x) => typeof x.content !== "string" || x.content.trim().length > 0);
159
+ } catch (thrown) {
160
+ const cap = ctx.maxTokens ? ` (context window capped at ${modelLimit} tokens by options.maxTokens \u2014 consider raising or removing it)` : ` (model context window: ${modelLimit} tokens)`;
161
+ throw new CognitiveError(`The prompt does not fit in the context window${cap}: ${getErrorMessage(thrown)}`);
162
+ }
106
163
  iteration.messages = messages;
107
164
  traces.push({
108
165
  type: "llm_call_started",
@@ -110,7 +167,7 @@ var generateCode = async ({ iteration, ctx, cognitive, controller, metadata }) =
110
167
  ended_at: startedAt,
111
168
  model: model.ref
112
169
  });
113
- const output = await cognitive.generateContent({
170
+ const input = {
114
171
  signal: controller.signal,
115
172
  systemPrompt: (_a = messages.find((x) => x.role === "system")) == null ? void 0 : _a.content,
116
173
  model: iteration.model,
@@ -120,15 +177,123 @@ var generateCode = async ({ iteration, ctx, cognitive, controller, metadata }) =
120
177
  messages: messages.filter((x) => x.role !== "system"),
121
178
  stopSequences: ctx.version.getStopTokens(),
122
179
  meta: metadata ? { metadata } : void 0
123
- }).catch((thrown) => {
124
- throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
125
- });
126
- const out = typeof ((_c = (_b = output.output.choices) == null ? void 0 : _b[0]) == null ? void 0 : _c.content) === "string" ? output.output.choices[0].content : null;
127
- if (!out) {
128
- throw new CognitiveError("LLM did not return any text output");
180
+ };
181
+ let output;
182
+ let raw;
183
+ let assistantResponse;
184
+ let timeToFirstToken;
185
+ let timeToLastToken;
186
+ const liveItems = /* @__PURE__ */ new Map();
187
+ const liveContent = /* @__PURE__ */ new Map();
188
+ let codeGenerationTraced = false;
189
+ let runCompleted = false;
190
+ const dispatchSends = async (events) => {
191
+ for (const event of events) {
192
+ if (event.type === "item-start") {
193
+ liveItems.set(event.item.id, event.item);
194
+ if (event.item.kind === "run" && !codeGenerationTraced) {
195
+ codeGenerationTraced = true;
196
+ traces.push({ type: "code_generation_started", started_at: Date.now() });
197
+ onRunStart == null ? void 0 : onRunStart();
198
+ }
199
+ } else if (event.type === "body-delta" && onSendDelta) {
200
+ const item = liveItems.get(event.itemId);
201
+ if ((item == null ? void 0 : item.kind) !== "send") {
202
+ continue;
203
+ }
204
+ const content = (liveContent.get(item.id) ?? "") + event.delta;
205
+ liveContent.set(item.id, content);
206
+ try {
207
+ await onSendDelta({
208
+ id: `${iteration.id}:${item.id}`,
209
+ component: item.name,
210
+ props: item.props,
211
+ delta: event.delta,
212
+ content
213
+ });
214
+ } catch (err) {
215
+ }
216
+ } else if (event.type === "item-complete") {
217
+ if (event.item.kind === "send" && onSend) {
218
+ await onSend({ name: event.item.name, props: event.item.props, body: event.item.body });
219
+ } else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
220
+ runCompleted = true;
221
+ onRunComplete == null ? void 0 : onRunComplete((event.item.body ?? "").trim());
222
+ }
223
+ }
224
+ }
225
+ };
226
+ if (typeof cognitive.generateContentStream === "function") {
227
+ const parser = new StreamingMessageParser();
228
+ const fence = new LeadingFenceFilter();
229
+ const streamController = createJoinedAbortController([controller.signal]);
230
+ const requestedAt = Date.now();
231
+ const stream = cognitive.generateContentStream({
232
+ ...input,
233
+ signal: streamController.signal,
234
+ // Passed through to the cognitive v2 request: fall back to the next
235
+ // model/provider when the first token takes too long
236
+ ...ctx.maxTimeToFirstToken ? { options: { maxTimeToFirstToken: ctx.maxTimeToFirstToken } } : {}
237
+ });
238
+ const inactivityTimeout = Math.max(STREAM_INACTIVITY_TIMEOUT, ctx.maxTimeToFirstToken ?? 0);
239
+ const nextChunk = async () => {
240
+ let timer;
241
+ const stalled = new Promise((_, reject) => {
242
+ timer = setTimeout(() => {
243
+ streamController.abort("LLM stream stalled");
244
+ reject(new Error(`LLM stream stalled: no data received for ${inactivityTimeout}ms`));
245
+ }, inactivityTimeout);
246
+ });
247
+ try {
248
+ return await Promise.race([stream.next(), stalled]);
249
+ } finally {
250
+ clearTimeout(timer);
251
+ }
252
+ };
253
+ raw = "";
254
+ while (true) {
255
+ let chunk;
256
+ try {
257
+ chunk = await nextChunk();
258
+ } catch (thrown) {
259
+ throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
260
+ }
261
+ if (chunk.done) {
262
+ output = chunk.value;
263
+ break;
264
+ }
265
+ const delta = (_b = chunk.value) == null ? void 0 : _b.output;
266
+ if (!delta) {
267
+ continue;
268
+ }
269
+ timeToLastToken = Date.now() - requestedAt;
270
+ timeToFirstToken ??= timeToLastToken;
271
+ raw += delta;
272
+ await dispatchSends(parser.push(fence.push(delta)));
273
+ }
274
+ const remaining = fence.flush();
275
+ if (remaining) {
276
+ await dispatchSends(parser.push(remaining));
277
+ }
278
+ await dispatchSends(parser.finish());
279
+ assistantResponse = toParsedAssistantResponse(parser.items, raw);
280
+ } else {
281
+ output = await cognitive.generateContent(input).catch((thrown) => {
282
+ throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
283
+ });
284
+ const out = typeof ((_d = (_c = output.output.choices) == null ? void 0 : _c[0]) == null ? void 0 : _d.content) === "string" ? output.output.choices[0].content : null;
285
+ if (!out) {
286
+ throw new CognitiveError("LLM did not return any text output");
287
+ }
288
+ raw = out;
289
+ assistantResponse = ctx.version.parseAssistantResponse(out);
290
+ for (const send of assistantResponse.sends) {
291
+ await (onSend == null ? void 0 : onSend(send));
292
+ }
129
293
  }
130
- const assistantResponse = ctx.version.parseAssistantResponse(out);
131
- iteration.code = assistantResponse.code.trim();
294
+ iteration.code = assistantResponse.code;
295
+ iteration.sends = assistantResponse.sends;
296
+ iteration.next = assistantResponse.next;
132
297
  iteration.llm = {
133
298
  cached: output.meta.cached || false,
134
299
  ended_at: Date.now(),
@@ -138,14 +303,21 @@ var generateCode = async ({ iteration, ctx, cognitive, controller, metadata }) =
138
303
  spend: output.meta.cost.input + output.meta.cost.output,
139
304
  output: assistantResponse.raw,
140
305
  model: `${output.meta.model.integration}:${output.meta.model.model}`,
306
+ time_to_first_token: timeToFirstToken,
307
+ time_to_last_token: timeToLastToken,
141
308
  usage: output.output.usage
142
309
  };
310
+ if (iteration.tokens) {
311
+ iteration.tokens.input = output.meta.tokens.input;
312
+ iteration.tokens.output = output.meta.tokens.output;
313
+ iteration.tokens.total = output.meta.tokens.input + output.meta.tokens.output;
314
+ }
143
315
  traces.push({
144
316
  type: "llm_call_success",
145
317
  started_at: startedAt,
146
318
  ended_at: iteration.llm.ended_at,
147
319
  model: model.ref,
148
- code: iteration.code
320
+ code: iteration.code ?? ""
149
321
  });
150
322
  };
151
323
 
@@ -222,35 +394,50 @@ var interpretVMResult = async ({
222
394
  });
223
395
  return;
224
396
  }
225
- let returnValue = result.success && result.return_value ? result.return_value : null;
226
- const returnAction = returnValue == null ? void 0 : returnValue.action;
227
- if (returnAction === "think") {
228
- const variables = omit_default(returnValue ?? {}, "action");
229
- if (isPlainObject_default(variables) && Object.keys(variables).length > 0) {
230
- iteration.end({
231
- type: "thinking_requested",
232
- thinking_requested: {
233
- variables,
234
- reason: "Thinking requested"
235
- }
236
- });
237
- return;
397
+ const returnValue = result.return_value;
398
+ const codeRequestsInspection = hasTopLevelReturn(iteration.code ?? "");
399
+ if (iteration.next && !codeRequestsInspection) {
400
+ await applyNextExit({ iteration, controller, onExit });
401
+ return;
402
+ }
403
+ const localVariables = Object.fromEntries(
404
+ Object.entries(result.variables ?? {}).filter(([, value]) => value !== "[[non-primitive]]")
405
+ );
406
+ iteration.end({
407
+ type: "thinking_requested",
408
+ thinking_requested: {
409
+ reason: iteration.next ? `Code execution completed. The \u25A0next=${iteration.next.name} exit was NOT applied because your code returns a value \u2014 inspect it below, then end your next response with \u25A0next.` : "Code execution completed",
410
+ variables: returnValue !== void 0 ? returnValue : Object.keys(localVariables).length ? localVariables : iteration.variables
238
411
  }
239
- iteration.end({
240
- type: "thinking_requested",
241
- thinking_requested: {
242
- reason: "Thinking requested",
243
- variables: iteration.variables
412
+ });
413
+ };
414
+ var applyNextExit = async ({
415
+ iteration,
416
+ controller,
417
+ onExit
418
+ }) => {
419
+ const next = iteration.next;
420
+ if (!next) {
421
+ throw new Error("applyNextExit called without a \u25A0next block on the iteration");
422
+ }
423
+ const attempt = (props) => parseExit(Object.keys(props).length ? { action: next.name, value: props } : { action: next.name }, iteration.exits);
424
+ let parsedExit = attempt(next.props);
425
+ const keys = Object.keys(next.props);
426
+ if (!parsedExit.success && keys.length === 1 && ["props", "value", "data"].includes(keys[0])) {
427
+ const inner = next.props[keys[0]];
428
+ if (inner && typeof inner === "object" && !Array.isArray(inner)) {
429
+ const unwrapped = attempt(inner);
430
+ if (unwrapped.success) {
431
+ parsedExit = unwrapped;
244
432
  }
245
- });
246
- return;
433
+ }
247
434
  }
248
- const parsedExit = parseExit(returnValue, iteration.exits);
435
+ const returnValue = { action: next.name, value: parsedExit.success ? parsedExit.value : next.props };
249
436
  if (!parsedExit.success) {
250
437
  iteration.end({
251
438
  type: "exit_error",
252
439
  exit_error: {
253
- exit: (returnValue == null ? void 0 : returnValue.action) ?? "n/a",
440
+ exit: next.name,
254
441
  message: parsedExit.error,
255
442
  return_value: returnValue
256
443
  }
@@ -258,12 +445,14 @@ var interpretVMResult = async ({
258
445
  return;
259
446
  }
260
447
  const returnExit = parsedExit.exit;
261
- returnValue = { action: returnExit.name, value: parsedExit.value };
262
448
  try {
263
- await (onExit == null ? void 0 : onExit({
264
- exit: returnExit,
265
- result: returnValue == null ? void 0 : returnValue.value
266
- }));
449
+ await (onExit == null ? void 0 : onExit(
450
+ {
451
+ exit: returnExit,
452
+ result: parsedExit.value
453
+ },
454
+ controller
455
+ ));
267
456
  } catch (err) {
268
457
  iteration.end({
269
458
  type: "exit_error",
@@ -279,10 +468,9 @@ var interpretVMResult = async ({
279
468
  type: "exit_success",
280
469
  exit_success: {
281
470
  exit_name: returnExit.name,
282
- return_value: returnValue == null ? void 0 : returnValue.value
471
+ return_value: parsedExit.value
283
472
  }
284
473
  });
285
- return;
286
474
  };
287
475
 
288
476
  // src/runtime/utils.ts
@@ -535,7 +723,7 @@ var executeContext = async (props) => {
535
723
  return result;
536
724
  };
537
725
  var executeContextInternal = async (props) => {
538
- var _a, _b;
726
+ var _a, _b, _c, _d;
539
727
  const controller = createJoinedAbortController([props.signal]);
540
728
  const { onIterationStart, onIterationEnd, onTrace, onExit, onBeforeExecution, onAfterTool, onBeforeTool } = props;
541
729
  const client = props.client ?? new Client();
@@ -547,6 +735,8 @@ var executeContextInternal = async (props) => {
547
735
  tools: props.tools,
548
736
  loop: (_a = props.options) == null ? void 0 : _a.loop,
549
737
  timeout: (_b = props.options) == null ? void 0 : _b.timeout,
738
+ maxTokens: (_c = props.options) == null ? void 0 : _c.maxTokens,
739
+ maxTimeToFirstToken: (_d = props.options) == null ? void 0 : _d.maxTimeToFirstToken,
550
740
  exits: props.exits,
551
741
  snapshot: props.snapshot,
552
742
  model: props.model,
@@ -561,7 +751,7 @@ var executeContextInternal = async (props) => {
561
751
  const iteration = await ctx.nextIteration();
562
752
  const unsubscribeTrace = iteration.traces.onPush((traces) => {
563
753
  for (const trace of traces) {
564
- onTrace == null ? void 0 : onTrace({ trace, iteration: ctx.iterations.length });
754
+ onTrace == null ? void 0 : onTrace({ trace, iteration: ctx.iterations.length, controller });
565
755
  }
566
756
  });
567
757
  try {
@@ -773,7 +963,58 @@ var executeIteration = async ({
773
963
  onAfterTool,
774
964
  metadata
775
965
  }) => {
776
- await generateCode({ iteration, ctx, cognitive, controller, metadata });
966
+ var _a, _b;
967
+ const runCode = (code) => {
968
+ const vmContext = buildVMContext({ ctx, iteration, controller, onBeforeTool, onAfterTool });
969
+ return runAsyncFunction(vmContext, code, iteration.traces, controller.signal, ctx.timeout).catch((err) => {
970
+ return {
971
+ success: false,
972
+ error: err instanceof Error ? err : new Error(getErrorMessage(err)),
973
+ lines_executed: [],
974
+ traces: [],
975
+ variables: {}
976
+ };
977
+ });
978
+ };
979
+ const canExecuteEarly = typeof onBeforeExecution !== "function";
980
+ let earlyExecution;
981
+ await generateCode({
982
+ iteration,
983
+ ctx,
984
+ cognitive,
985
+ controller,
986
+ metadata,
987
+ // Pre-warm the VM while the model is still writing the ■run block
988
+ onRunStart: () => warmupVM(),
989
+ onRunComplete: canExecuteEarly ? (code) => {
990
+ if (!code.length || controller.signal.aborted || earlyExecution) {
991
+ return;
992
+ }
993
+ iteration.code = code;
994
+ earlyExecution = { code, started_at: Date.now(), promise: runCode(code) };
995
+ } : void 0,
996
+ onSend: async (send) => {
997
+ if (!ctx.chat) {
998
+ return;
999
+ }
1000
+ const sendStartedAt = Date.now();
1001
+ const component = createJsxComponent({
1002
+ type: send.name,
1003
+ props: send.props,
1004
+ children: send.body ? [send.body] : []
1005
+ });
1006
+ try {
1007
+ await ctx.chat.handler(component);
1008
+ } catch (err) {
1009
+ throw new Error(`Error while sending message (\u25A0send=${send.name}): ${getErrorMessage(err)}`);
1010
+ }
1011
+ iteration.traces.push({ type: "yield", value: component, started_at: sendStartedAt, ended_at: Date.now() });
1012
+ },
1013
+ onSendDelta: ((_a = ctx.chat) == null ? void 0 : _a.onMessageDelta) ? (delta) => ctx.chat.onMessageDelta(delta) : void 0
1014
+ });
1015
+ if (earlyExecution) {
1016
+ iteration.code = earlyExecution.code;
1017
+ }
777
1018
  if (typeof onBeforeExecution === "function") {
778
1019
  try {
779
1020
  const hookRes = await onBeforeExecution(iteration, controller);
@@ -804,7 +1045,6 @@ var executeIteration = async ({
804
1045
  }
805
1046
  }
806
1047
  const traces = iteration.traces;
807
- const vmContext = buildVMContext({ ctx, iteration, controller, onBeforeTool, onAfterTool });
808
1048
  if (controller.signal.aborted) {
809
1049
  traces.push({
810
1050
  type: "abort_signal",
@@ -819,22 +1059,26 @@ var executeIteration = async ({
819
1059
  });
820
1060
  return;
821
1061
  }
822
- const startedAt = Date.now();
823
- const result = await runAsyncFunction(
824
- vmContext,
825
- iteration.code ?? "",
826
- traces,
827
- controller.signal,
828
- ctx.timeout
829
- ).catch((err) => {
830
- return {
831
- success: false,
832
- error: err instanceof Error ? err : new Error(getErrorMessage(err)),
833
- lines_executed: [],
834
- traces: [],
835
- variables: {}
836
- };
837
- });
1062
+ if (!iteration.code) {
1063
+ if (iteration.next) {
1064
+ await applyNextExit({ iteration, controller, onExit });
1065
+ return;
1066
+ }
1067
+ if (ctx.chat && ((_b = iteration.sends) == null ? void 0 : _b.length)) {
1068
+ iteration.next = { name: "listen", props: {} };
1069
+ await applyNextExit({ iteration, controller, onExit });
1070
+ return;
1071
+ }
1072
+ iteration.end({
1073
+ type: "invalid_code_error",
1074
+ invalid_code_error: {
1075
+ message: "The response did not include a \u25A0run block or a \u25A0next exit. Reply using \u25A0 blocks and end your response with \u25A0run or \u25A0next=<exit>."
1076
+ }
1077
+ });
1078
+ return;
1079
+ }
1080
+ const startedAt = (earlyExecution == null ? void 0 : earlyExecution.started_at) ?? Date.now();
1081
+ const result = earlyExecution ? await earlyExecution.promise : await runCode(iteration.code ?? "");
838
1082
  await interpretVMResult({
839
1083
  iteration,
840
1084
  result,