llmz 0.8.0 → 0.9.1

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 (68) hide show
  1. package/README.md +45 -11
  2. package/dist/chat.d.ts +6 -6
  3. package/dist/{common-DdArNQhl.cjs → common-DJkSpeqw.cjs} +239 -22
  4. package/dist/{common-pgJjFu2Y.js → common-DuEhn6u3.js} +234 -23
  5. package/dist/compiler/plugins/variable-extraction.d.ts +1 -7
  6. package/dist/{compiler-C-OI9sim.cjs → compiler-BJJUmNS9.cjs} +34 -68
  7. package/dist/{compiler-CW1VjQsn.js → compiler-BPl-5CXh.js} +34 -68
  8. package/dist/{component-BXS8vAwO.cjs → component-CPKXe6Ca.cjs} +2 -2
  9. package/dist/{component-Dq7ZLdvy.js → component-DGG7d_Mz.js} +1 -1
  10. package/dist/component.default.d.ts +10 -0
  11. package/dist/context.d.ts +4 -8
  12. package/dist/{custom-client-HkM1Sdzv.cjs → custom-client-B_o56CB4.cjs} +22 -19
  13. package/dist/{custom-client-2V9lmzUf.js → custom-client-C-nDKG37.js} +17 -14
  14. package/dist/{dual-modes-Cb7ThvoV.cjs → dual-modes-BNHlj2qM.cjs} +1252 -1181
  15. package/dist/{dual-modes-Cy0_W4O2.js → dual-modes-BNIiNLrR.js} +1257 -1180
  16. package/dist/example-format.d.ts +8 -0
  17. package/dist/{execute-COIHOIKR.cjs → execute-0bvqakr7.cjs} +91 -99
  18. package/dist/{execute-Aw4cbIx-.js → execute-CWFIL5ny.js} +91 -99
  19. package/dist/{exit-DUM96DN1.cjs → exit-CGLXI0BH.cjs} +2 -2
  20. package/dist/index.cjs +265 -22
  21. package/dist/index.js +258 -15
  22. package/dist/index.workerd.js +8565 -8005
  23. package/dist/inspect.d.ts +2 -0
  24. package/dist/isPlainObject-CSxXVKCk.cjs +56 -0
  25. package/dist/isPlainObject-D39AzPO2.js +51 -0
  26. package/dist/{jsx-D5Y2cPo-.cjs → jsx-BJ6GWXI2.cjs} +3 -57
  27. package/dist/{jsx-B0iYyvfr.js → jsx-CIgdGGVs.js} +2 -50
  28. package/dist/message-stream/instructions.d.ts +8 -0
  29. package/dist/message-stream/parser.d.ts +6 -0
  30. package/dist/message-stream/response-parser.d.ts +24 -0
  31. package/dist/message-stream/response-parser.test.d.ts +1 -0
  32. package/dist/message-stream/types.d.ts +3 -2
  33. package/dist/prompts/adherence.test.d.ts +1 -0
  34. package/dist/prompts/catalogue-examples.test.d.ts +1 -0
  35. package/dist/prompts/chat-mode/protocol.d.ts +2 -0
  36. package/dist/prompts/chat-mode/system.d.ts +1 -1
  37. package/dist/prompts/chat-mode/user.d.ts +1 -1
  38. package/dist/prompts/code-examples.d.ts +2 -0
  39. package/dist/prompts/code-examples.test.d.ts +1 -0
  40. package/dist/prompts/common.d.ts +2 -1
  41. package/dist/prompts/concrete-patterns.test.d.ts +1 -0
  42. package/dist/prompts/long-search.test.d.ts +1 -0
  43. package/dist/prompts/prompt.d.ts +5 -2
  44. package/dist/prompts/protocol-basics.d.ts +5 -0
  45. package/dist/prompts/protocol-simple.test.d.ts +1 -0
  46. package/dist/prompts/protocol.d.ts +13 -0
  47. package/dist/prompts/sections.test.d.ts +1 -0
  48. package/dist/prompts/worker-mode/protocol.d.ts +2 -0
  49. package/dist/prompts/worker-mode/system.d.ts +1 -1
  50. package/dist/prompts/worker-mode/user.d.ts +1 -1
  51. package/dist/runtime/citations.test.d.ts +1 -0
  52. package/dist/runtime/fixtures/long-search.d.ts +19 -0
  53. package/dist/runtime/fixtures/protocol-languages.d.ts +74 -0
  54. package/dist/runtime/fixtures/qwen-protocol-failures.d.ts +29 -0
  55. package/dist/runtime/generate.d.ts +2 -9
  56. package/dist/runtime/generate.test.d.ts +1 -0
  57. package/dist/runtime/protocol-adherence.test.d.ts +1 -0
  58. package/dist/runtime/types.d.ts +4 -7
  59. package/dist/{tool-Bv8N4IPj.js → tool-B6Pmuk6K.js} +35 -49
  60. package/dist/{tool-Dy6AJpJH.cjs → tool-BLTrA-sL.cjs} +38 -52
  61. package/dist/tool.d.ts +5 -3
  62. package/dist/{truncator-DZqEqnpD.js → truncator-CD7QtE84.js} +11 -6
  63. package/dist/{truncator-CLkouTCO.cjs → truncator-DmCu9M4m.cjs} +13 -8
  64. package/dist/{typings-3lsqCbkn.cjs → typings-DXJMu59O.cjs} +2 -2
  65. package/dist/{utils-3ESwP3yg.cjs → utils-DGQ4sRke.cjs} +1 -1
  66. package/dist/{vm-BLsHw1da.js → vm-Cn3jvZ00.js} +109 -53
  67. package/dist/{vm-D6s1zF6M.cjs → vm-X0uTj5Aa.cjs} +109 -53
  68. package/package.json +1 -1
@@ -1,13 +1,13 @@
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";
4
- import { d as stripInvalidIdentifiers, i as getErrorMessage, s as init } from "./utils-UBeAFeEI.js";
5
- import { t as createJsxComponent } from "./jsx-B0iYyvfr.js";
1
+ import { a as isEqual, l as toNumber } from "./dual-modes-BNIiNLrR.js";
2
+ import { a as ResponseParser, i as toParsedAssistantResponse } from "./common-DuEhn6u3.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-C-nDKG37.js";
4
+ import { d as stripInvalidIdentifiers, i as getErrorMessage, r as fromJSONSchemaCompat, s as init } from "./utils-UBeAFeEI.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
- import { n as truncateWrappedContent } from "./truncator-DZqEqnpD.js";
9
- import { r as hasTopLevelReturn } from "./compiler-CW1VjQsn.js";
10
- import { runAsyncFunction, warmupVM } from "./vm-BLsHw1da.js";
8
+ import { n as truncateWrappedContent } from "./truncator-CD7QtE84.js";
9
+ import { r as hasTopLevelReturn } from "./compiler-BPl-5CXh.js";
10
+ import { runAsyncFunction, warmupVM } from "./vm-Cn3jvZ00.js";
11
11
  import { z } from "@bpinternal/zui";
12
12
  import { ulid } from "ulid";
13
13
  import { Client } from "@botpress/client";
@@ -125,47 +125,21 @@ const STREAM_INACTIVITY_TIMEOUT = 18e4;
125
125
  /** A syntactically valid prefix must not execute when generation did not finish successfully. */
126
126
  const assertSuccessfulGeneration = (metadata) => {
127
127
  if (metadata.provider === "unknown") throw new CognitiveError("LLM generation failed: received error metadata with unknown provider");
128
- if (metadata.stopReason === "max_tokens" || metadata.stopReason === "content_filter") throw new CognitiveError(`LLM generation did not complete: stopReason=${metadata.stopReason}`);
128
+ if (metadata.stopReason === "max_tokens" || metadata.stopReason === "content_filter" || metadata.stopReason === "other") 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
- const modelRef = Array.isArray(iteration.model) ? iteration.model[0] : iteration.model;
163
- const model = await cognitive.getModelDetails(modelRef).catch((thrown) => {
134
+ controller.signal.throwIfAborted();
135
+ const modelRefs = Array.isArray(iteration.model) ? iteration.model : [iteration.model];
136
+ const models = await Promise.all(modelRefs.map((modelRef) => cognitive.getModelDetails(modelRef).catch((thrown) => {
164
137
  throw new CognitiveError(`Failed to fetch model details for model "${modelRef}": ${getErrorMessage(thrown)}`);
165
- });
166
- let modelLimit = Math.max(model.input.maxTokens, 8e3);
167
- if (ctx.maxTokens) modelLimit = Math.min(ctx.maxTokens, modelLimit);
168
- const responseLengthBuffer = getModelOutputLimit(modelLimit);
138
+ })));
139
+ controller.signal.throwIfAborted();
140
+ const model = models[0];
141
+ const modelLimit = Math.min(...models.map((model) => model.input.maxTokens), ctx.maxTokens ?? Infinity);
142
+ const responseLengthBuffer = Math.min(getModelOutputLimit(modelLimit), Math.floor(modelLimit / 2));
169
143
  if (iteration.tokens) iteration.tokens.limit = modelLimit;
170
144
  let messages;
171
145
  try {
@@ -219,7 +193,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
219
193
  const liveContent = /* @__PURE__ */ new Map();
220
194
  let codeGenerationTraced = false;
221
195
  let runCompleted = false;
222
- let awaitsRunResult = false;
196
+ let completions = [];
223
197
  const dispatchSends = async (events) => {
224
198
  for (const event of events) if (event.type === "item-start") {
225
199
  liveItems.set(event.item.id, event.item);
@@ -233,7 +207,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
233
207
  }
234
208
  } else if (event.type === "body-delta" && onSendDelta) {
235
209
  const item = liveItems.get(event.itemId);
236
- if ((item === null || item === void 0 ? void 0 : item.kind) !== "send" || awaitsRunResult) continue;
210
+ if ((item === null || item === void 0 ? void 0 : item.kind) !== "send" || runCompleted) continue;
237
211
  const content = (liveContent.get(item.id) ?? "") + event.delta;
238
212
  liveContent.set(item.id, content);
239
213
  const delta = {
@@ -246,22 +220,19 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
246
220
  };
247
221
  await preview(delta);
248
222
  } 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
- }
223
+ if (event.item.kind === "send" && onSend && !runCompleted) {
224
+ const send = {
225
+ name: event.item.name,
226
+ props: event.item.props,
227
+ body: event.item.body
228
+ };
229
+ const metadata = messageMetadata(event.item.id);
230
+ completions.push(() => onSend(send, metadata));
231
+ } else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) runCompleted = true;
260
232
  }
261
233
  };
262
234
  if (typeof cognitive.generateTextStream === "function") {
263
- let parser = new StreamingMessageParser();
264
- let fence = new LeadingFenceFilter();
235
+ let parser = new ResponseParser();
265
236
  const streamController = createJoinedAbortController([controller.signal]);
266
237
  const requestedAt = Date.now();
267
238
  const stream = cognitive.generateTextStream({
@@ -289,6 +260,7 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
289
260
  };
290
261
  raw = "";
291
262
  let streamCompleted = false;
263
+ let accepted = false;
292
264
  try {
293
265
  while (true) {
294
266
  var _chunk$value, _chunk$value2, _chunk$value3, _chunk$value4;
@@ -313,13 +285,13 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
313
285
  ...chunk.value.restart
314
286
  });
315
287
  raw = "";
316
- parser = new StreamingMessageParser();
317
- fence = new LeadingFenceFilter();
288
+ completions = [];
289
+ accepted = false;
290
+ parser = new ResponseParser();
318
291
  liveItems.clear();
319
292
  liveContent.clear();
320
293
  codeGenerationTraced = false;
321
294
  runCompleted = false;
322
- awaitsRunResult = false;
323
295
  responseMetadata = void 0;
324
296
  attempt = chunk.value.restart.attempt;
325
297
  await preview({
@@ -337,29 +309,63 @@ const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, o
337
309
  timeToLastToken = Date.now() - requestedAt;
338
310
  timeToFirstToken ??= timeToLastToken;
339
311
  raw += delta;
340
- await dispatchSends(parser.push(fence.push(delta)));
312
+ await dispatchSends(parser.push(delta));
341
313
  }
342
314
  if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
343
315
  assertSuccessfulGeneration(responseMetadata);
344
- const remaining = fence.flush();
345
- if (remaining) await dispatchSends(parser.push(remaining));
346
- await dispatchSends(parser.finish());
316
+ await dispatchSends(parser.finish(responseMetadata.stopReason));
317
+ if (parser.valid) {
318
+ for (const complete of completions) await complete();
319
+ accepted = true;
320
+ }
347
321
  assistantResponse = toParsedAssistantResponse(parser.items, raw, parser.diagnostics);
322
+ } catch (error) {
323
+ parser.finish();
324
+ const usage = (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.usage) ?? {
325
+ inputTokens: 0,
326
+ outputTokens: 0,
327
+ inputCost: 0,
328
+ outputCost: 0
329
+ };
330
+ iteration.llm = {
331
+ started_at: startedAt,
332
+ ended_at: Date.now(),
333
+ status: "error",
334
+ cached: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cached) ?? false,
335
+ tokens: usage.inputTokens + usage.outputTokens,
336
+ spend: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cost) ?? usage.inputCost + usage.outputCost,
337
+ output: raw,
338
+ diagnostics: parser.diagnostics,
339
+ model: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.model) ?? model.id,
340
+ time_to_first_token: timeToFirstToken,
341
+ time_to_last_token: timeToLastToken,
342
+ usage
343
+ };
344
+ throw error;
348
345
  } finally {
349
346
  streamController.abort("LLM stream closed");
350
347
  if (!streamCompleted) stream.return(void 0).catch((err) => {});
348
+ if (!accepted && liveContent.size) await preview({
349
+ restart: true,
350
+ iterationId: iteration.id,
351
+ attempt: attempt + 1,
352
+ fromModel: model.id,
353
+ toModel: model.id,
354
+ reason: "invalid or incomplete response envelope"
355
+ });
351
356
  }
352
- if (midStreamFallback) controller.signal.throwIfAborted();
357
+ controller.signal.throwIfAborted();
353
358
  } else {
354
359
  const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
355
360
  throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
356
361
  });
362
+ controller.signal.throwIfAborted();
357
363
  if (response.error) throw new CognitiveError(`LLM generation failed: ${response.error}`);
358
364
  if (!response.output) throw new CognitiveError("LLM did not return any text output");
359
365
  responseMetadata = response.metadata;
360
366
  assertSuccessfulGeneration(responseMetadata);
361
367
  raw = response.output;
362
- assistantResponse = ctx.version.parseAssistantResponse(raw);
368
+ assistantResponse = ctx.version.parseAssistantResponse(raw, responseMetadata.stopReason);
363
369
  for (const [index, send] of assistantResponse.sends.entries()) await (onSend === null || onSend === void 0 ? void 0 : onSend(send, messageMetadata(`send-${index}`)));
364
370
  }
365
371
  iteration.code = assistantResponse.code;
@@ -564,8 +570,10 @@ const finalizeIteration = async ({ iteration, status, controller, onIterationEnd
564
570
  //#region src/runtime/tool-wrapper.ts
565
571
  const SLOW_TOOL_WARNING = ms("15s");
566
572
  function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook, controller }) {
567
- const getToolInput = (input) => tool.zInput.safeParse(input).data ?? input;
573
+ const traceSchema = tool.input ? fromJSONSchemaCompat(tool.input) : void 0;
574
+ const getToolInput = (input) => (traceSchema === null || traceSchema === void 0 ? void 0 : traceSchema.safeParse(input).data) ?? input;
568
575
  return async function(input) {
576
+ controller.signal.throwIfAborted();
569
577
  const toolCallId = `tcall_${ulid()}`;
570
578
  const originalInput = input;
571
579
  let effectiveInput = input;
@@ -641,6 +649,7 @@ function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook
641
649
  object,
642
650
  toolCallId
643
651
  }));
652
+ controller.signal.throwIfAborted();
644
653
  if (typeof (beforeRes === null || beforeRes === void 0 ? void 0 : beforeRes.input) !== "undefined") effectiveInput = beforeRes.input;
645
654
  output = await tool.execute(effectiveInput, {
646
655
  callId: toolCallId,
@@ -657,9 +666,16 @@ function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook
657
666
  }));
658
667
  if (typeof (afterRes === null || afterRes === void 0 ? void 0 : afterRes.output) !== "undefined") output = afterRes.output;
659
668
  } catch (err) {
660
- if (!await handleSignals(err)) {
669
+ try {
670
+ if (!await handleSignals(err)) {
671
+ success = false;
672
+ error = err;
673
+ output = void 0;
674
+ }
675
+ } catch (hookError) {
661
676
  success = false;
662
- error = err;
677
+ error = hookError;
678
+ output = void 0;
663
679
  }
664
680
  } finally {
665
681
  clearTimeout(alertSlowTool);
@@ -959,8 +975,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
959
975
  };
960
976
  });
961
977
  };
962
- const canExecuteEarly = typeof onBeforeExecution !== "function" && !ctx.midStreamFallback;
963
- let earlyExecution;
964
978
  await generateCode({
965
979
  iteration,
966
980
  ctx,
@@ -968,15 +982,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
968
982
  controller,
969
983
  metadata,
970
984
  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
985
  onSend: async (send, messageMetadata) => {
981
986
  if (!ctx.chat) return;
982
987
  const sendStartedAt = Date.now();
@@ -1001,7 +1006,6 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1001
1006
  },
1002
1007
  onSendDelta: ((_ctx$chat = ctx.chat) === null || _ctx$chat === void 0 ? void 0 : _ctx$chat.onMessageDelta) ? (delta) => ctx.chat.onMessageDelta(delta) : void 0
1003
1008
  });
1004
- if (earlyExecution) iteration.code = earlyExecution.code;
1005
1009
  if (typeof onBeforeExecution === "function") try {
1006
1010
  const hookRes = await onBeforeExecution(iteration, controller);
1007
1011
  if (typeof (hookRes === null || hookRes === void 0 ? void 0 : hookRes.code) === "string" && hookRes.code.trim().length > 0) iteration.code = hookRes.code.trim();
@@ -1039,7 +1043,7 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1039
1043
  return;
1040
1044
  }
1041
1045
  if (!iteration.code) {
1042
- var _iteration$sends;
1046
+ var _iteration$llm;
1043
1047
  if (iteration.next) {
1044
1048
  await applyNextExit({
1045
1049
  iteration,
@@ -1048,26 +1052,14 @@ const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit,
1048
1052
  });
1049
1053
  return;
1050
1054
  }
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
1055
  iteration.end({
1064
1056
  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>." }
1057
+ 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
1058
  });
1067
1059
  return;
1068
1060
  }
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 ?? "");
1061
+ const startedAt = Date.now();
1062
+ const result = await runCode(iteration.code);
1071
1063
  await interpretVMResult({
1072
1064
  iteration,
1073
1065
  result,
@@ -1,6 +1,6 @@
1
- const require_compiler = require("./compiler-C-OI9sim.cjs");
1
+ const require_compiler = require("./compiler-BJJUmNS9.cjs");
2
2
  const require_uniq = require("./uniq-G872RWmE.cjs");
3
- const require_utils = require("./utils-3ESwP3yg.cjs");
3
+ const require_utils = require("./utils-DGQ4sRke.cjs");
4
4
  let _bpinternal_zui = require("@bpinternal/zui");
5
5
  //#region src/exit.ts
6
6
  var exit_exports = /* @__PURE__ */ require_compiler.__exportAll({ Exit: () => Exit });
package/dist/index.cjs CHANGED
@@ -1,18 +1,18 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
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");
5
- const require_utils = require("./utils-3ESwP3yg.cjs");
6
- const require_component = require("./component-BXS8vAwO.cjs");
7
- const require_tool = require("./tool-Dy6AJpJH.cjs");
2
+ const require_dual_modes = require("./dual-modes-BNHlj2qM.cjs");
3
+ const require_common = require("./common-DJkSpeqw.cjs");
4
+ const require_custom_client = require("./custom-client-B_o56CB4.cjs");
5
+ const require_utils = require("./utils-DGQ4sRke.cjs");
6
+ const require_tool = require("./tool-BLTrA-sL.cjs");
8
7
  const require_errors = require("./errors-C962uJdS.cjs");
9
- const require_typings = require("./typings-3lsqCbkn.cjs");
10
- const require_exit = require("./exit-DUM96DN1.cjs");
11
- const require_truncator = require("./truncator-CLkouTCO.cjs");
8
+ const require_typings = require("./typings-DXJMu59O.cjs");
9
+ const require_exit = require("./exit-CGLXI0BH.cjs");
10
+ const require_component = require("./component-CPKXe6Ca.cjs");
11
+ const require_truncator = require("./truncator-DmCu9M4m.cjs");
12
12
  const require_quickjs_variant = require("./quickjs-variant-CsIwTVFC.cjs");
13
13
  let _bpinternal_zui = require("@bpinternal/zui");
14
14
  //#region package.json
15
- var version = "0.8.0";
15
+ var version = "0.9.1";
16
16
  //#endregion
17
17
  //#region src/hoist.ts
18
18
  /**
@@ -792,6 +792,249 @@ var CitationsManager = class {
792
792
  }
793
793
  };
794
794
  //#endregion
795
+ //#region src/component.default.ts
796
+ const Button = new require_component.Component({
797
+ type: "leaf",
798
+ description: "A button component that can perform actions when clicked",
799
+ name: "Button",
800
+ aliases: ["btn"],
801
+ generation: {
802
+ usage: "Offer quick actions or choices after a message. It is common to send several buttons together: write one separate ■send=button block per choice in the SAME response. Each button has its own props and no body. Send all the choices before the final exit; do not wait for a user reply between buttons.",
803
+ examples: [
804
+ { props: {
805
+ action: "say",
806
+ label: "Track my order"
807
+ } },
808
+ { props: {
809
+ action: "url",
810
+ label: "View guide",
811
+ url: "https://example.com/guide"
812
+ } },
813
+ { props: {
814
+ action: "postback",
815
+ label: "Choose Standard",
816
+ value: "plan_standard"
817
+ } },
818
+ [
819
+ { props: {
820
+ action: "say",
821
+ label: "Track my order"
822
+ } },
823
+ { props: {
824
+ action: "say",
825
+ label: "Return an item"
826
+ } },
827
+ { props: {
828
+ action: "say",
829
+ label: "Contact support"
830
+ } }
831
+ ]
832
+ ]
833
+ },
834
+ leaf: { props: _bpinternal_zui.z.object({
835
+ action: _bpinternal_zui.z.enum([
836
+ "say",
837
+ "url",
838
+ "postback"
839
+ ]).default("say").describe("The action to perform when the button is clicked. Can be \"say\", \"url\", or \"postback\""),
840
+ label: _bpinternal_zui.z.string().describe("The text displayed on the button (min 1 character, max 250 characters)"),
841
+ value: _bpinternal_zui.z.string().optional().describe("The postback value to send when the button is clicked. Required if action is \"postback\""),
842
+ url: _bpinternal_zui.z.string().optional().describe("The URL to open when the button is clicked. Required if action is \"url\"")
843
+ }) }
844
+ });
845
+ const Image = new require_component.Component({
846
+ type: "leaf",
847
+ name: "Image",
848
+ description: "Displays an image from a URL.",
849
+ aliases: [],
850
+ generation: {
851
+ usage: "Use a known image URL from the user or tool results; never invent an image URL. No body.",
852
+ examples: [{ props: {
853
+ url: "https://example.com/trail.jpg",
854
+ alt: "Forest trail beside a lake"
855
+ } }]
856
+ },
857
+ leaf: { props: _bpinternal_zui.z.object({
858
+ url: _bpinternal_zui.z.string().describe("The URL of the image (must be valid)"),
859
+ alt: _bpinternal_zui.z.string().optional().describe("Alternative text describing the image")
860
+ }) }
861
+ });
862
+ const File = new require_component.Component({
863
+ type: "leaf",
864
+ name: "File",
865
+ description: "Sends a downloadable file to the user.",
866
+ aliases: [],
867
+ generation: { examples: [{ props: {
868
+ url: "https://example.com/report.pdf",
869
+ name: "Report.pdf"
870
+ } }] },
871
+ leaf: { props: _bpinternal_zui.z.object({
872
+ url: _bpinternal_zui.z.string().describe("The URL of the file (must be valid)"),
873
+ name: _bpinternal_zui.z.string().optional().describe("The display name of the file")
874
+ }) }
875
+ });
876
+ const Video = new require_component.Component({
877
+ type: "leaf",
878
+ name: "Video",
879
+ description: "Embeds a video from a URL.",
880
+ aliases: [],
881
+ generation: { examples: [{ props: {
882
+ url: "https://example.com/intro.mp4",
883
+ title: "Welcome"
884
+ } }] },
885
+ leaf: { props: _bpinternal_zui.z.object({
886
+ url: _bpinternal_zui.z.string().describe("The URL of the video (must be valid)"),
887
+ title: _bpinternal_zui.z.string().optional().describe("Title for the video")
888
+ }) }
889
+ });
890
+ const Audio = new require_component.Component({
891
+ type: "leaf",
892
+ name: "Audio",
893
+ description: "Plays an audio clip from a URL.",
894
+ aliases: [],
895
+ generation: { examples: [{ props: {
896
+ url: "https://example.com/audio.mp3",
897
+ title: "Sample"
898
+ } }] },
899
+ leaf: { props: _bpinternal_zui.z.object({
900
+ url: _bpinternal_zui.z.string().describe("The URL of the audio clip (must be valid)"),
901
+ title: _bpinternal_zui.z.string().optional().describe("Title for the audio clip")
902
+ }) }
903
+ });
904
+ const Card = new require_component.Component({
905
+ type: "container",
906
+ name: "Card",
907
+ description: "A card with a title, optional subtitle, and Markdown body.",
908
+ aliases: [],
909
+ generation: {
910
+ usage: "Present one item. The block body is Markdown, not nested component blocks or JSX.",
911
+ examples: [{
912
+ props: {
913
+ title: "Standard plan",
914
+ subtitle: "$20/month"
915
+ },
916
+ body: "Includes 5 projects and email support."
917
+ }]
918
+ },
919
+ container: {
920
+ props: _bpinternal_zui.z.object({
921
+ title: _bpinternal_zui.z.string().min(1).max(250).describe("Title text (1–250 characters)"),
922
+ subtitle: _bpinternal_zui.z.string().optional().describe("Optional subtitle for the card")
923
+ }),
924
+ children: [{
925
+ description: "Image (optional, max 1)",
926
+ component: Image.definition
927
+ }, {
928
+ description: "Button (optional, up to 5)",
929
+ component: Button.definition
930
+ }]
931
+ }
932
+ });
933
+ const carouselProps = _bpinternal_zui.z.object({ cards: _bpinternal_zui.z.array(Card.definition.container.props.extend({
934
+ body: _bpinternal_zui.z.string().optional().describe("Markdown text for this card"),
935
+ image: Image.definition.leaf.props.optional().describe("Optional image for this card; use a known URL"),
936
+ buttons: _bpinternal_zui.z.array(Button.definition.leaf.props).max(5).optional().describe("Up to 5 actions for this card")
937
+ })).min(1).max(10).describe("1–10 cards, in display order. Each card has its own title, optional subtitle, body, image, and buttons") });
938
+ var CarouselComponent = class extends require_component.Component {
939
+ render(props, children = []) {
940
+ if (!("cards" in props) && children.length && children.every((child) => require_component.isComponent(child, Card))) return super.render(props, children);
941
+ const { cards } = carouselProps.parse(props);
942
+ const renderedCards = cards.map(({ body, image, buttons, ...cardProps }) => Card.render(cardProps, [
943
+ ...body ? [body] : [],
944
+ ...image ? [Image.render(image)] : [],
945
+ ...(buttons ?? []).map((button) => Button.render(button))
946
+ ]));
947
+ return super.render({}, renderedCards);
948
+ }
949
+ };
950
+ const DefaultComponents = {
951
+ Button,
952
+ Image,
953
+ File,
954
+ Video,
955
+ Audio,
956
+ Card,
957
+ Carousel: new CarouselComponent({
958
+ type: "container",
959
+ name: "Carousel",
960
+ description: "Displays a horizontally scrollable collection of cards, each with its own content and actions.",
961
+ aliases: [],
962
+ body: false,
963
+ generation: {
964
+ usage: "Use for several comparable items. Put ALL cards in the cards array of ONE send block. Each card can include title, subtitle, body, image {url, alt?}, and buttons [{action, label, value?, url?}]. Do not write a Markdown list or separate Card blocks; those do not form a carousel.",
965
+ examples: [{ props: { cards: [{
966
+ title: "Standard plan",
967
+ subtitle: "$20/month",
968
+ body: "5 projects and email support.",
969
+ image: {
970
+ url: "https://example.com/standard.jpg",
971
+ alt: "Standard plan"
972
+ },
973
+ buttons: [{
974
+ action: "postback",
975
+ label: "Choose Standard",
976
+ value: "plan_standard"
977
+ }]
978
+ }, {
979
+ title: "Team plan",
980
+ subtitle: "$50/month",
981
+ body: "20 projects and priority support.",
982
+ image: {
983
+ url: "https://example.com/team.jpg",
984
+ alt: "Team plan"
985
+ },
986
+ buttons: [{
987
+ action: "postback",
988
+ label: "Choose Team",
989
+ value: "plan_team"
990
+ }]
991
+ }] } }]
992
+ },
993
+ container: {
994
+ props: carouselProps,
995
+ children: [{
996
+ description: "Card component (required, 1–10 allowed)",
997
+ component: Card.definition
998
+ }]
999
+ }
1000
+ }),
1001
+ Text: new require_component.Component({
1002
+ type: "default",
1003
+ name: "Message",
1004
+ aliases: ["Text", "Markdown"],
1005
+ description: "A Markdown-formatted text message. Long answers are written the same way: plain Markdown prose.",
1006
+ generation: { examples: [{ body: `To reset your password:
1007
+
1008
+ 1. Open the sign-in page and select **Forgot password?**
1009
+ 2. Enter the email address you use for your account.
1010
+ 3. Open the reset link in your email and choose a new password.
1011
+
1012
+ If the email does not arrive, check your spam folder. If you sign in through your organization, use its password reset process.` }, { body: "How do you currently manage board meetings?" }] },
1013
+ default: {
1014
+ props: _bpinternal_zui.z.object({}),
1015
+ children: []
1016
+ }
1017
+ }),
1018
+ Speech: new require_component.Component({
1019
+ type: "default",
1020
+ name: "Speech",
1021
+ aliases: ["speak", "spoken"],
1022
+ description: "A message spoken aloud to the user via text-to-speech.",
1023
+ body: {
1024
+ format: "text",
1025
+ description: "Plain conversational prose only, written to be read aloud: no Markdown, no links or URLs, no emojis, no code, no bullet points, tables or headings. Write everything the way it should be pronounced — spell out numbers, dates, units and abbreviations (e.g. \"June third at three thirty PM\", not \"06/03 @ 3:30pm\")."
1026
+ },
1027
+ generation: {
1028
+ usage: "Use when the reply will be played back as audio (voice conversations).",
1029
+ examples: [{ body: "Sure! Your order shipped this morning and should arrive on Tuesday, June third, around noon." }]
1030
+ },
1031
+ default: {
1032
+ props: _bpinternal_zui.z.object({}),
1033
+ children: []
1034
+ }
1035
+ })
1036
+ };
1037
+ //#endregion
795
1038
  //#region src/chat.ts
796
1039
  /**
797
1040
  * Base class for implementing chat interfaces in LLMz agents.
@@ -1450,7 +1693,7 @@ const utils = {
1450
1693
  * })
1451
1694
  */
1452
1695
  const execute = async (props) => {
1453
- const { executeContext } = await Promise.resolve().then(() => require("./execute-COIHOIKR.cjs"));
1696
+ const { executeContext } = await Promise.resolve().then(() => require("./execute-0bvqakr7.cjs"));
1454
1697
  return executeContext(props);
1455
1698
  };
1456
1699
  /**
@@ -1459,16 +1702,16 @@ const execute = async (props) => {
1459
1702
  * It's recommended to call this function at the beginning of your application without awaiting it (void init())
1460
1703
  */
1461
1704
  const init = async () => {
1462
- await Promise.resolve().then(() => require("./execute-COIHOIKR.cjs"));
1463
- await Promise.resolve().then(() => require("./component-BXS8vAwO.cjs")).then((n) => n.component_exports);
1464
- await Promise.resolve().then(() => require("./tool-Dy6AJpJH.cjs")).then((n) => n.tool_exports);
1465
- await Promise.resolve().then(() => require("./exit-DUM96DN1.cjs")).then((n) => n.exit_exports);
1466
- await Promise.resolve().then(() => require("./jsx-D5Y2cPo-.cjs")).then((n) => n.jsx_exports);
1467
- await Promise.resolve().then(() => require("./vm-D6s1zF6M.cjs"));
1468
- await Promise.resolve().then(() => require("./utils-3ESwP3yg.cjs")).then((n) => n.utils_exports);
1469
- await Promise.resolve().then(() => require("./truncator-CLkouTCO.cjs")).then((n) => n.truncator_exports);
1470
- await Promise.resolve().then(() => require("./typings-3lsqCbkn.cjs")).then((n) => n.typings_exports);
1471
- await Promise.resolve().then(() => require("./dual-modes-Cb7ThvoV.cjs")).then((n) => n.dual_modes_exports);
1705
+ await Promise.resolve().then(() => require("./execute-0bvqakr7.cjs"));
1706
+ await Promise.resolve().then(() => require("./component-CPKXe6Ca.cjs")).then((n) => n.component_exports);
1707
+ await Promise.resolve().then(() => require("./tool-BLTrA-sL.cjs")).then((n) => n.tool_exports);
1708
+ await Promise.resolve().then(() => require("./exit-CGLXI0BH.cjs")).then((n) => n.exit_exports);
1709
+ await Promise.resolve().then(() => require("./jsx-BJ6GWXI2.cjs")).then((n) => n.jsx_exports);
1710
+ await Promise.resolve().then(() => require("./vm-X0uTj5Aa.cjs"));
1711
+ await Promise.resolve().then(() => require("./utils-DGQ4sRke.cjs")).then((n) => n.utils_exports);
1712
+ await Promise.resolve().then(() => require("./truncator-DmCu9M4m.cjs")).then((n) => n.truncator_exports);
1713
+ await Promise.resolve().then(() => require("./typings-DXJMu59O.cjs")).then((n) => n.typings_exports);
1714
+ await Promise.resolve().then(() => require("./dual-modes-BNHlj2qM.cjs")).then((n) => n.dual_modes_exports);
1472
1715
  };
1473
1716
  //#endregion
1474
1717
  exports.BaseResponse = BaseResponse;
@@ -1476,7 +1719,7 @@ exports.Chat = Chat;
1476
1719
  exports.CitationsManager = CitationsManager;
1477
1720
  exports.Component = require_component.Component;
1478
1721
  exports.ComponentRegistry = require_dual_modes.ComponentRegistry;
1479
- exports.DefaultComponents = require_dual_modes.DefaultComponents;
1722
+ exports.DefaultComponents = DefaultComponents;
1480
1723
  exports.DefaultExit = require_custom_client.DefaultExit;
1481
1724
  exports.ErrorExecutionResult = require_custom_client.ErrorExecutionResult;
1482
1725
  exports.Example = require_dual_modes.Example;