llmz 0.8.0 → 0.9.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 (54) hide show
  1. package/README.md +45 -11
  2. package/dist/chat.d.ts +6 -6
  3. package/dist/{common-pgJjFu2Y.js → common-BlRFtdf2.js} +233 -22
  4. package/dist/{common-DdArNQhl.cjs → common-BnvrDnIT.cjs} +238 -21
  5. package/dist/{component-BXS8vAwO.cjs → component-C6Agl2ns.cjs} +1 -1
  6. package/dist/{component-Dq7ZLdvy.js → component-DGG7d_Mz.js} +1 -1
  7. package/dist/component.default.d.ts +10 -0
  8. package/dist/context.d.ts +4 -8
  9. package/dist/{custom-client-2V9lmzUf.js → custom-client-ChuZ63zp.js} +15 -12
  10. package/dist/{custom-client-HkM1Sdzv.cjs → custom-client-DAsGRnYc.cjs} +18 -15
  11. package/dist/{dual-modes-Cy0_W4O2.js → dual-modes-DDkoCp3R.js} +1246 -1170
  12. package/dist/{dual-modes-Cb7ThvoV.cjs → dual-modes-DPXiuvNe.cjs} +1239 -1169
  13. package/dist/example-format.d.ts +8 -0
  14. package/dist/{execute-Aw4cbIx-.js → execute-BWcdv9so.js} +64 -85
  15. package/dist/{execute-COIHOIKR.cjs → execute-DM2-7y86.cjs} +64 -85
  16. package/dist/index.cjs +254 -11
  17. package/dist/index.js +253 -10
  18. package/dist/index.workerd.js +8646 -8108
  19. package/dist/inspect.d.ts +2 -0
  20. package/dist/isPlainObject-CSxXVKCk.cjs +56 -0
  21. package/dist/isPlainObject-D39AzPO2.js +51 -0
  22. package/dist/{jsx-B0iYyvfr.js → jsx-CIgdGGVs.js} +2 -50
  23. package/dist/{jsx-D5Y2cPo-.cjs → jsx-owqxrquU.cjs} +2 -56
  24. package/dist/message-stream/instructions.d.ts +8 -0
  25. package/dist/message-stream/parser.d.ts +6 -0
  26. package/dist/message-stream/response-parser.d.ts +24 -0
  27. package/dist/message-stream/response-parser.test.d.ts +1 -0
  28. package/dist/message-stream/types.d.ts +3 -2
  29. package/dist/prompts/adherence.test.d.ts +1 -0
  30. package/dist/prompts/catalogue-examples.test.d.ts +1 -0
  31. package/dist/prompts/chat-mode/protocol.d.ts +2 -0
  32. package/dist/prompts/chat-mode/system.d.ts +1 -1
  33. package/dist/prompts/chat-mode/user.d.ts +1 -1
  34. package/dist/prompts/code-examples.d.ts +2 -0
  35. package/dist/prompts/code-examples.test.d.ts +1 -0
  36. package/dist/prompts/common.d.ts +2 -1
  37. package/dist/prompts/concrete-patterns.test.d.ts +1 -0
  38. package/dist/prompts/long-search.test.d.ts +1 -0
  39. package/dist/prompts/prompt.d.ts +5 -2
  40. package/dist/prompts/protocol-basics.d.ts +5 -0
  41. package/dist/prompts/protocol-simple.test.d.ts +1 -0
  42. package/dist/prompts/protocol.d.ts +13 -0
  43. package/dist/prompts/sections.test.d.ts +1 -0
  44. package/dist/prompts/worker-mode/protocol.d.ts +2 -0
  45. package/dist/prompts/worker-mode/system.d.ts +1 -1
  46. package/dist/prompts/worker-mode/user.d.ts +1 -1
  47. package/dist/runtime/citations.test.d.ts +1 -0
  48. package/dist/runtime/fixtures/long-search.d.ts +19 -0
  49. package/dist/runtime/fixtures/protocol-languages.d.ts +74 -0
  50. package/dist/runtime/fixtures/qwen-protocol-failures.d.ts +29 -0
  51. package/dist/runtime/generate.d.ts +2 -9
  52. package/dist/runtime/protocol-adherence.test.d.ts +1 -0
  53. package/dist/runtime/types.d.ts +4 -7
  54. package/package.json +1 -1
@@ -0,0 +1,8 @@
1
+ /** Documentation boundaries only; never part of the response protocol. */
2
+ export declare const quoteExample: (output: string) => string;
3
+ /** A single block excerpt; the omitted response is not part of this example. */
4
+ export declare const quotePartialExample: (output: string) => string;
5
+ export declare const exampleBoundaryInstructions = "Triple quotes (\"\"\") mark the beginning and end of examples only. Do NOT emit these delimiters in your response.";
6
+ /** A complete response example, unlike individual block/syntax examples. */
7
+ export declare const quoteResponseExample: (output: string) => string;
8
+ export declare const responseEnvelopeInstructions = "Every response starts with \u25A0start on its own line and ends with \u25A0end on its own line. Between them write only the documented protocol blocks. Nothing goes before \u25A0start or after \u25A0end. The envelope is protocol, not a code fence.";
@@ -1,8 +1,8 @@
1
- import { a as StreamingMessageParser, i as toParsedAssistantResponse } from "./common-pgJjFu2Y.js";
2
- import { c as isEqual, f as toNumber } from "./dual-modes-Cy0_W4O2.js";
3
- 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-2V9lmzUf.js";
1
+ import { a as isEqual, l as toNumber } from "./dual-modes-DDkoCp3R.js";
2
+ import { a as ResponseParser, i as toParsedAssistantResponse } from "./common-BlRFtdf2.js";
3
+ 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-ChuZ63zp.js";
4
4
  import { d as stripInvalidIdentifiers, i as getErrorMessage, s as init } from "./utils-UBeAFeEI.js";
5
- import { t as createJsxComponent } from "./jsx-B0iYyvfr.js";
5
+ import { t as createJsxComponent } from "./jsx-CIgdGGVs.js";
6
6
  import { t as cleanStackTrace } from "./stack-traces-BIE_5Xwf.js";
7
7
  import { a as InvalidCodeError, c as SnapshotSignal, i as CognitiveError, l as ThinkSignal, n as CodeExecutionError, o as LoopExceededError, s as Signals, t as AssignmentError } from "./errors-Cg1G0Awu.js";
8
8
  import { n as truncateWrappedContent } from "./truncator-DZqEqnpD.js";
@@ -128,35 +128,7 @@ const assertSuccessfulGeneration = (metadata) => {
128
128
  if (metadata.stopReason === "max_tokens" || metadata.stopReason === "content_filter") throw new CognitiveError(`LLM generation did not complete: stopReason=${metadata.stopReason}`);
129
129
  };
130
130
  const getModelOutputLimit = (inputLength) => clamp(RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength, RESPONSE_LENGTH_BUFFER.MIN_TOKENS, RESPONSE_LENGTH_BUFFER.MAX_TOKENS);
131
- /**
132
- * Models sometimes wrap their whole response in a code fence. The fence has to
133
- * be removed before it reaches the incremental parser to avoid a spurious
134
- * unexpected-text diagnostic. Works on arbitrary chunk boundaries
135
- * by holding content back until the first newline.
136
- */
137
- var LeadingFenceFilter = class {
138
- _buffer = "";
139
- _done = false;
140
- push(text) {
141
- if (this._done) return text;
142
- this._buffer += text;
143
- const newline = this._buffer.indexOf("\n");
144
- if (newline === -1) return "";
145
- this._done = true;
146
- const firstLine = this._buffer.slice(0, newline);
147
- const rest = this._buffer.slice(newline + 1);
148
- this._buffer = "";
149
- return firstLine.trim().startsWith("```") ? rest : `${firstLine}\n${rest}`;
150
- }
151
- flush() {
152
- if (this._done) return "";
153
- this._done = true;
154
- const buffered = this._buffer;
155
- this._buffer = "";
156
- return buffered.trim().startsWith("```") ? "" : buffered;
157
- }
158
- };
159
- const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart, onRunComplete }) => {
131
+ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart }) => {
160
132
  const startedAt = Date.now();
161
133
  const traces = iteration.traces;
162
134
  const modelRef = Array.isArray(iteration.model) ? iteration.model[0] : iteration.model;
@@ -219,7 +191,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
219
191
  const liveContent = /* @__PURE__ */ new Map();
220
192
  let codeGenerationTraced = false;
221
193
  let runCompleted = false;
222
- let awaitsRunResult = false;
194
+ let completions = [];
223
195
  const dispatchSends = async (events) => {
224
196
  for (const event of events) if (event.type === "item-start") {
225
197
  liveItems.set(event.item.id, event.item);
@@ -233,7 +205,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
233
205
  }
234
206
  } else if (event.type === "body-delta" && onSendDelta) {
235
207
  const item = liveItems.get(event.itemId);
236
- if ((item === null || item === void 0 ? void 0 : item.kind) !== "send" || awaitsRunResult) continue;
208
+ if ((item === null || item === void 0 ? void 0 : item.kind) !== "send" || runCompleted) continue;
237
209
  const content = (liveContent.get(item.id) ?? "") + event.delta;
238
210
  liveContent.set(item.id, content);
239
211
  const delta = {
@@ -246,22 +218,19 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
246
218
  };
247
219
  await preview(delta);
248
220
  } else if (event.type === "item-complete") {
249
- if (event.item.kind === "send" && onSend && !awaitsRunResult) await onSend({
250
- name: event.item.name,
251
- props: event.item.props,
252
- body: event.item.body
253
- }, messageMetadata(event.item.id));
254
- else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
255
- runCompleted = true;
256
- const code = (event.item.body ?? "").trim();
257
- awaitsRunResult = hasTopLevelReturn(code);
258
- onRunComplete === null || onRunComplete === void 0 || onRunComplete(code);
259
- }
221
+ if (event.item.kind === "send" && onSend && !runCompleted) {
222
+ const send = {
223
+ name: event.item.name,
224
+ props: event.item.props,
225
+ body: event.item.body
226
+ };
227
+ const metadata = messageMetadata(event.item.id);
228
+ completions.push(() => onSend(send, metadata));
229
+ } else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) runCompleted = true;
260
230
  }
261
231
  };
262
232
  if (typeof cognitive.generateTextStream === "function") {
263
- let parser = new StreamingMessageParser();
264
- let fence = new LeadingFenceFilter();
233
+ let parser = new ResponseParser();
265
234
  const streamController = createJoinedAbortController([controller.signal]);
266
235
  const requestedAt = Date.now();
267
236
  const stream = cognitive.generateTextStream({
@@ -289,6 +258,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
289
258
  };
290
259
  raw = "";
291
260
  let streamCompleted = false;
261
+ let accepted = false;
292
262
  try {
293
263
  while (true) {
294
264
  var _chunk$value, _chunk$value2, _chunk$value3, _chunk$value4;
@@ -313,13 +283,13 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
313
283
  ...chunk.value.restart
314
284
  });
315
285
  raw = "";
316
- parser = new StreamingMessageParser();
317
- fence = new LeadingFenceFilter();
286
+ completions = [];
287
+ accepted = false;
288
+ parser = new ResponseParser();
318
289
  liveItems.clear();
319
290
  liveContent.clear();
320
291
  codeGenerationTraced = false;
321
292
  runCompleted = false;
322
- awaitsRunResult = false;
323
293
  responseMetadata = void 0;
324
294
  attempt = chunk.value.restart.attempt;
325
295
  await preview({
@@ -337,19 +307,52 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
337
307
  timeToLastToken = Date.now() - requestedAt;
338
308
  timeToFirstToken ??= timeToLastToken;
339
309
  raw += delta;
340
- await dispatchSends(parser.push(fence.push(delta)));
310
+ await dispatchSends(parser.push(delta));
341
311
  }
342
312
  if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
343
313
  assertSuccessfulGeneration(responseMetadata);
344
- const remaining = fence.flush();
345
- if (remaining) await dispatchSends(parser.push(remaining));
346
- await dispatchSends(parser.finish());
314
+ await dispatchSends(parser.finish(responseMetadata.stopReason));
315
+ if (parser.valid) {
316
+ for (const complete of completions) await complete();
317
+ accepted = true;
318
+ }
347
319
  assistantResponse = toParsedAssistantResponse(parser.items, raw, parser.diagnostics);
320
+ } catch (error) {
321
+ parser.finish();
322
+ const usage = (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.usage) ?? {
323
+ inputTokens: 0,
324
+ outputTokens: 0,
325
+ inputCost: 0,
326
+ outputCost: 0
327
+ };
328
+ iteration.llm = {
329
+ started_at: startedAt,
330
+ ended_at: Date.now(),
331
+ status: "error",
332
+ cached: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cached) ?? false,
333
+ tokens: usage.inputTokens + usage.outputTokens,
334
+ spend: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cost) ?? usage.inputCost + usage.outputCost,
335
+ output: raw,
336
+ diagnostics: parser.diagnostics,
337
+ model: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.model) ?? model.id,
338
+ time_to_first_token: timeToFirstToken,
339
+ time_to_last_token: timeToLastToken,
340
+ usage
341
+ };
342
+ throw error;
348
343
  } finally {
349
344
  streamController.abort("LLM stream closed");
350
345
  if (!streamCompleted) stream.return(void 0).catch((err) => {});
346
+ if (!accepted && liveContent.size) await preview({
347
+ restart: true,
348
+ iterationId: iteration.id,
349
+ attempt: attempt + 1,
350
+ fromModel: model.id,
351
+ toModel: model.id,
352
+ reason: "invalid or incomplete response envelope"
353
+ });
351
354
  }
352
- if (midStreamFallback) controller.signal.throwIfAborted();
355
+ controller.signal.throwIfAborted();
353
356
  } else {
354
357
  const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
355
358
  throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
@@ -359,7 +362,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
359
362
  responseMetadata = response.metadata;
360
363
  assertSuccessfulGeneration(responseMetadata);
361
364
  raw = response.output;
362
- assistantResponse = ctx.version.parseAssistantResponse(raw);
365
+ assistantResponse = ctx.version.parseAssistantResponse(raw, responseMetadata.stopReason);
363
366
  for (const [index, send] of assistantResponse.sends.entries()) await (onSend === null || onSend === void 0 ? void 0 : onSend(send, messageMetadata(`send-${index}`)));
364
367
  }
365
368
  iteration.code = assistantResponse.code;
@@ -959,8 +962,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
959
962
  };
960
963
  });
961
964
  };
962
- const canExecuteEarly = typeof onBeforeExecution !== "function" && !ctx.midStreamFallback;
963
- let earlyExecution;
964
965
  await generateCode({
965
966
  iteration,
966
967
  ctx,
@@ -968,15 +969,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
968
969
  controller,
969
970
  metadata,
970
971
  onRunStart: () => warmupVM(),
971
- onRunComplete: canExecuteEarly ? (code) => {
972
- if (!code.length || controller.signal.aborted || earlyExecution) return;
973
- iteration.code = code;
974
- earlyExecution = {
975
- code,
976
- started_at: Date.now(),
977
- promise: runCode(code)
978
- };
979
- } : void 0,
980
972
  onSend: async (send, messageMetadata) => {
981
973
  if (!ctx.chat) return;
982
974
  const sendStartedAt = Date.now();
@@ -1001,7 +993,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1001
993
  },
1002
994
  onSendDelta: ((_ctx$chat = ctx.chat) === null || _ctx$chat === void 0 ? void 0 : _ctx$chat.onMessageDelta) ? (delta) => ctx.chat.onMessageDelta(delta) : void 0
1003
995
  });
1004
- if (earlyExecution) iteration.code = earlyExecution.code;
1005
996
  if (typeof onBeforeExecution === "function") try {
1006
997
  const hookRes = await onBeforeExecution(iteration, controller);
1007
998
  if (typeof (hookRes === null || hookRes === void 0 ? void 0 : hookRes.code) === "string" && hookRes.code.trim().length > 0) iteration.code = hookRes.code.trim();
@@ -1039,7 +1030,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1039
1030
  return;
1040
1031
  }
1041
1032
  if (!iteration.code) {
1042
- var _iteration$sends;
1033
+ var _iteration$llm;
1043
1034
  if (iteration.next) {
1044
1035
  await applyNextExit({
1045
1036
  iteration,
@@ -1048,26 +1039,14 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1048
1039
  });
1049
1040
  return;
1050
1041
  }
1051
- if (ctx.chat && ((_iteration$sends = iteration.sends) === null || _iteration$sends === void 0 ? void 0 : _iteration$sends.length)) {
1052
- iteration.next = {
1053
- name: "listen",
1054
- props: {}
1055
- };
1056
- await applyNextExit({
1057
- iteration,
1058
- controller,
1059
- onExit
1060
- });
1061
- return;
1062
- }
1063
1042
  iteration.end({
1064
1043
  type: "invalid_code_error",
1065
- invalid_code_error: { message: "The response did not include a ■run block or a ■next exit. Reply using ■ blocks and end your response with ■run or ■next=<exit>." }
1044
+ invalid_code_error: { message: ((_iteration$llm = iteration.llm) === null || _iteration$llm === void 0 || (_iteration$llm = _iteration$llm.diagnostics) === null || _iteration$llm === void 0 || (_iteration$llm = _iteration$llm.find((diagnostic) => diagnostic.code === "invalid-envelope")) === null || _iteration$llm === void 0 ? void 0 : _iteration$llm.message) ?? "The response did not include a ■run block or a ■next exit. Reply with ■start, the required ■ blocks, and ■end." }
1066
1045
  });
1067
1046
  return;
1068
1047
  }
1069
- const startedAt = (earlyExecution === null || earlyExecution === void 0 ? void 0 : earlyExecution.started_at) ?? Date.now();
1070
- const result = earlyExecution ? await earlyExecution.promise : await runCode(iteration.code ?? "");
1048
+ const startedAt = Date.now();
1049
+ const result = await runCode(iteration.code);
1071
1050
  await interpretVMResult({
1072
1051
  iteration,
1073
1052
  result,
@@ -1,9 +1,9 @@
1
1
  const require_compiler = require("./compiler-C-OI9sim.cjs");
2
- const require_common = require("./common-DdArNQhl.cjs");
3
- const require_dual_modes = require("./dual-modes-Cb7ThvoV.cjs");
4
- const require_custom_client = require("./custom-client-HkM1Sdzv.cjs");
2
+ const require_dual_modes = require("./dual-modes-DPXiuvNe.cjs");
3
+ const require_common = require("./common-BnvrDnIT.cjs");
4
+ const require_custom_client = require("./custom-client-DAsGRnYc.cjs");
5
5
  const require_utils = require("./utils-3ESwP3yg.cjs");
6
- const require_jsx = require("./jsx-D5Y2cPo-.cjs");
6
+ const require_jsx = require("./jsx-owqxrquU.cjs");
7
7
  const require_stack_traces = require("./stack-traces-ntw_qhoy.cjs");
8
8
  const require_errors = require("./errors-C962uJdS.cjs");
9
9
  const require_truncator = require("./truncator-CLkouTCO.cjs");
@@ -129,35 +129,7 @@ const assertSuccessfulGeneration = (metadata) => {
129
129
  if (metadata.stopReason === "max_tokens" || metadata.stopReason === "content_filter") throw new require_errors.CognitiveError(`LLM generation did not complete: stopReason=${metadata.stopReason}`);
130
130
  };
131
131
  const getModelOutputLimit = (inputLength) => clamp(RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength, RESPONSE_LENGTH_BUFFER.MIN_TOKENS, RESPONSE_LENGTH_BUFFER.MAX_TOKENS);
132
- /**
133
- * Models sometimes wrap their whole response in a code fence. The fence has to
134
- * be removed before it reaches the incremental parser to avoid a spurious
135
- * unexpected-text diagnostic. Works on arbitrary chunk boundaries
136
- * by holding content back until the first newline.
137
- */
138
- var LeadingFenceFilter = class {
139
- _buffer = "";
140
- _done = false;
141
- push(text) {
142
- if (this._done) return text;
143
- this._buffer += text;
144
- const newline = this._buffer.indexOf("\n");
145
- if (newline === -1) return "";
146
- this._done = true;
147
- const firstLine = this._buffer.slice(0, newline);
148
- const rest = this._buffer.slice(newline + 1);
149
- this._buffer = "";
150
- return firstLine.trim().startsWith("```") ? rest : `${firstLine}\n${rest}`;
151
- }
152
- flush() {
153
- if (this._done) return "";
154
- this._done = true;
155
- const buffered = this._buffer;
156
- this._buffer = "";
157
- return buffered.trim().startsWith("```") ? "" : buffered;
158
- }
159
- };
160
- const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart, onRunComplete }) => {
132
+ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart }) => {
161
133
  const startedAt = Date.now();
162
134
  const traces = iteration.traces;
163
135
  const modelRef = Array.isArray(iteration.model) ? iteration.model[0] : iteration.model;
@@ -220,7 +192,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
220
192
  const liveContent = /* @__PURE__ */ new Map();
221
193
  let codeGenerationTraced = false;
222
194
  let runCompleted = false;
223
- let awaitsRunResult = false;
195
+ let completions = [];
224
196
  const dispatchSends = async (events) => {
225
197
  for (const event of events) if (event.type === "item-start") {
226
198
  liveItems.set(event.item.id, event.item);
@@ -234,7 +206,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
234
206
  }
235
207
  } else if (event.type === "body-delta" && onSendDelta) {
236
208
  const item = liveItems.get(event.itemId);
237
- if ((item === null || item === void 0 ? void 0 : item.kind) !== "send" || awaitsRunResult) continue;
209
+ if ((item === null || item === void 0 ? void 0 : item.kind) !== "send" || runCompleted) continue;
238
210
  const content = (liveContent.get(item.id) ?? "") + event.delta;
239
211
  liveContent.set(item.id, content);
240
212
  const delta = {
@@ -247,22 +219,19 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
247
219
  };
248
220
  await preview(delta);
249
221
  } else if (event.type === "item-complete") {
250
- if (event.item.kind === "send" && onSend && !awaitsRunResult) await onSend({
251
- name: event.item.name,
252
- props: event.item.props,
253
- body: event.item.body
254
- }, messageMetadata(event.item.id));
255
- else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
256
- runCompleted = true;
257
- const code = (event.item.body ?? "").trim();
258
- awaitsRunResult = require_compiler.hasTopLevelReturn(code);
259
- onRunComplete === null || onRunComplete === void 0 || onRunComplete(code);
260
- }
222
+ if (event.item.kind === "send" && onSend && !runCompleted) {
223
+ const send = {
224
+ name: event.item.name,
225
+ props: event.item.props,
226
+ body: event.item.body
227
+ };
228
+ const metadata = messageMetadata(event.item.id);
229
+ completions.push(() => onSend(send, metadata));
230
+ } else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) runCompleted = true;
261
231
  }
262
232
  };
263
233
  if (typeof cognitive.generateTextStream === "function") {
264
- let parser = new require_common.StreamingMessageParser();
265
- let fence = new LeadingFenceFilter();
234
+ let parser = new require_common.ResponseParser();
266
235
  const streamController = createJoinedAbortController([controller.signal]);
267
236
  const requestedAt = Date.now();
268
237
  const stream = cognitive.generateTextStream({
@@ -290,6 +259,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
290
259
  };
291
260
  raw = "";
292
261
  let streamCompleted = false;
262
+ let accepted = false;
293
263
  try {
294
264
  while (true) {
295
265
  var _chunk$value, _chunk$value2, _chunk$value3, _chunk$value4;
@@ -314,13 +284,13 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
314
284
  ...chunk.value.restart
315
285
  });
316
286
  raw = "";
317
- parser = new require_common.StreamingMessageParser();
318
- fence = new LeadingFenceFilter();
287
+ completions = [];
288
+ accepted = false;
289
+ parser = new require_common.ResponseParser();
319
290
  liveItems.clear();
320
291
  liveContent.clear();
321
292
  codeGenerationTraced = false;
322
293
  runCompleted = false;
323
- awaitsRunResult = false;
324
294
  responseMetadata = void 0;
325
295
  attempt = chunk.value.restart.attempt;
326
296
  await preview({
@@ -338,19 +308,52 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
338
308
  timeToLastToken = Date.now() - requestedAt;
339
309
  timeToFirstToken ??= timeToLastToken;
340
310
  raw += delta;
341
- await dispatchSends(parser.push(fence.push(delta)));
311
+ await dispatchSends(parser.push(delta));
342
312
  }
343
313
  if (!responseMetadata) throw new require_errors.CognitiveError("LLM streaming completed without metadata");
344
314
  assertSuccessfulGeneration(responseMetadata);
345
- const remaining = fence.flush();
346
- if (remaining) await dispatchSends(parser.push(remaining));
347
- await dispatchSends(parser.finish());
315
+ await dispatchSends(parser.finish(responseMetadata.stopReason));
316
+ if (parser.valid) {
317
+ for (const complete of completions) await complete();
318
+ accepted = true;
319
+ }
348
320
  assistantResponse = require_common.toParsedAssistantResponse(parser.items, raw, parser.diagnostics);
321
+ } catch (error) {
322
+ parser.finish();
323
+ const usage = (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.usage) ?? {
324
+ inputTokens: 0,
325
+ outputTokens: 0,
326
+ inputCost: 0,
327
+ outputCost: 0
328
+ };
329
+ iteration.llm = {
330
+ started_at: startedAt,
331
+ ended_at: Date.now(),
332
+ status: "error",
333
+ cached: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cached) ?? false,
334
+ tokens: usage.inputTokens + usage.outputTokens,
335
+ spend: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cost) ?? usage.inputCost + usage.outputCost,
336
+ output: raw,
337
+ diagnostics: parser.diagnostics,
338
+ model: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.model) ?? model.id,
339
+ time_to_first_token: timeToFirstToken,
340
+ time_to_last_token: timeToLastToken,
341
+ usage
342
+ };
343
+ throw error;
349
344
  } finally {
350
345
  streamController.abort("LLM stream closed");
351
346
  if (!streamCompleted) stream.return(void 0).catch((err) => {});
347
+ if (!accepted && liveContent.size) await preview({
348
+ restart: true,
349
+ iterationId: iteration.id,
350
+ attempt: attempt + 1,
351
+ fromModel: model.id,
352
+ toModel: model.id,
353
+ reason: "invalid or incomplete response envelope"
354
+ });
352
355
  }
353
- if (midStreamFallback) controller.signal.throwIfAborted();
356
+ controller.signal.throwIfAborted();
354
357
  } else {
355
358
  const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
356
359
  throw new require_errors.CognitiveError(`LLM generation failed: ${require_utils.getErrorMessage(thrown)}`);
@@ -360,7 +363,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
360
363
  responseMetadata = response.metadata;
361
364
  assertSuccessfulGeneration(responseMetadata);
362
365
  raw = response.output;
363
- assistantResponse = ctx.version.parseAssistantResponse(raw);
366
+ assistantResponse = ctx.version.parseAssistantResponse(raw, responseMetadata.stopReason);
364
367
  for (const [index, send] of assistantResponse.sends.entries()) await (onSend === null || onSend === void 0 ? void 0 : onSend(send, messageMetadata(`send-${index}`)));
365
368
  }
366
369
  iteration.code = assistantResponse.code;
@@ -960,8 +963,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
960
963
  };
961
964
  });
962
965
  };
963
- const canExecuteEarly = typeof onBeforeExecution !== "function" && !ctx.midStreamFallback;
964
- let earlyExecution;
965
966
  await generateCode({
966
967
  iteration,
967
968
  ctx,
@@ -969,15 +970,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
969
970
  controller,
970
971
  metadata,
971
972
  onRunStart: () => require_vm.warmupVM(),
972
- onRunComplete: canExecuteEarly ? (code) => {
973
- if (!code.length || controller.signal.aborted || earlyExecution) return;
974
- iteration.code = code;
975
- earlyExecution = {
976
- code,
977
- started_at: Date.now(),
978
- promise: runCode(code)
979
- };
980
- } : void 0,
981
973
  onSend: async (send, messageMetadata) => {
982
974
  if (!ctx.chat) return;
983
975
  const sendStartedAt = Date.now();
@@ -1002,7 +994,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1002
994
  },
1003
995
  onSendDelta: ((_ctx$chat = ctx.chat) === null || _ctx$chat === void 0 ? void 0 : _ctx$chat.onMessageDelta) ? (delta) => ctx.chat.onMessageDelta(delta) : void 0
1004
996
  });
1005
- if (earlyExecution) iteration.code = earlyExecution.code;
1006
997
  if (typeof onBeforeExecution === "function") try {
1007
998
  const hookRes = await onBeforeExecution(iteration, controller);
1008
999
  if (typeof (hookRes === null || hookRes === void 0 ? void 0 : hookRes.code) === "string" && hookRes.code.trim().length > 0) iteration.code = hookRes.code.trim();
@@ -1040,7 +1031,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1040
1031
  return;
1041
1032
  }
1042
1033
  if (!iteration.code) {
1043
- var _iteration$sends;
1034
+ var _iteration$llm;
1044
1035
  if (iteration.next) {
1045
1036
  await applyNextExit({
1046
1037
  iteration,
@@ -1049,26 +1040,14 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1049
1040
  });
1050
1041
  return;
1051
1042
  }
1052
- if (ctx.chat && ((_iteration$sends = iteration.sends) === null || _iteration$sends === void 0 ? void 0 : _iteration$sends.length)) {
1053
- iteration.next = {
1054
- name: "listen",
1055
- props: {}
1056
- };
1057
- await applyNextExit({
1058
- iteration,
1059
- controller,
1060
- onExit
1061
- });
1062
- return;
1063
- }
1064
1043
  iteration.end({
1065
1044
  type: "invalid_code_error",
1066
- invalid_code_error: { message: "The response did not include a ■run block or a ■next exit. Reply using ■ blocks and end your response with ■run or ■next=<exit>." }
1045
+ invalid_code_error: { message: ((_iteration$llm = iteration.llm) === null || _iteration$llm === void 0 || (_iteration$llm = _iteration$llm.diagnostics) === null || _iteration$llm === void 0 || (_iteration$llm = _iteration$llm.find((diagnostic) => diagnostic.code === "invalid-envelope")) === null || _iteration$llm === void 0 ? void 0 : _iteration$llm.message) ?? "The response did not include a ■run block or a ■next exit. Reply with ■start, the required ■ blocks, and ■end." }
1067
1046
  });
1068
1047
  return;
1069
1048
  }
1070
- const startedAt = (earlyExecution === null || earlyExecution === void 0 ? void 0 : earlyExecution.started_at) ?? Date.now();
1071
- const result = earlyExecution ? await earlyExecution.promise : await runCode(iteration.code ?? "");
1049
+ const startedAt = Date.now();
1050
+ const result = await runCode(iteration.code);
1072
1051
  await interpretVMResult({
1073
1052
  iteration,
1074
1053
  result,