llmz 1.0.1 → 1.0.3

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 (55) hide show
  1. package/DOCS.md +8 -4
  2. package/ERRORS.md +5 -2
  3. package/dist/{component-BpMVZYOa.cjs → component-CMFoCHyu.cjs} +3 -3
  4. package/dist/{component-C27qu6Zv.js → component-DncqP4fB.js} +3 -3
  5. package/dist/context.d.ts +1 -1
  6. package/dist/{custom-client-MytucGI-.cjs → custom-client-BwRYQ4Oa.cjs} +37 -13
  7. package/dist/{custom-client-BDkgBR2w.js → custom-client-JcdoH-47.js} +37 -13
  8. package/dist/errors/catalog.d.ts +7 -0
  9. package/dist/{errors-IhnTKUp7.cjs → errors-C6ppQUZX.cjs} +22 -0
  10. package/dist/{errors-H4JJFH3S.js → errors-Crk5P8jo.js} +17 -1
  11. package/dist/errors.d.ts +6 -0
  12. package/dist/{execute-DLas4V2n.cjs → execute-DJBNrA2H.cjs} +209 -79
  13. package/dist/{execute-BYI_U5sR.js → execute-DoN74Exa.js} +209 -79
  14. package/dist/{exit-BUgJ5qi5.cjs → exit-BOtKWPuT.cjs} +2 -2
  15. package/dist/{exit-CPNk3vbz.js → exit-DMPwCSba.js} +2 -2
  16. package/dist/index.cjs +18 -17
  17. package/dist/index.d.ts +1 -1
  18. package/dist/index.js +18 -18
  19. package/dist/index.workerd.js +404 -88
  20. package/dist/inspection.d.ts +2 -0
  21. package/dist/{native-DvTH9vFe.js → native-BGW5kBlv.js} +136 -10
  22. package/dist/{native-Bm6L9zOb.cjs → native-sbuzbLbY.cjs} +136 -10
  23. package/dist/prompts/native-examples.d.ts +10 -0
  24. package/dist/prompts/native-examples.test.d.ts +1 -0
  25. package/dist/prompts/reasoning.d.ts +2 -0
  26. package/dist/prompts/reasoning.test.d.ts +1 -0
  27. package/dist/{quickjs-variant-DJwYDSsb.cjs → quickjs-variant-21IO97PF.cjs} +15 -8
  28. package/dist/{quickjs-variant-DlPi9-Sx.js → quickjs-variant-CtuGagsb.js} +10 -9
  29. package/dist/runtime/chat-completion.test.d.ts +1 -0
  30. package/dist/runtime/chat-last-speaker.test.d.ts +1 -0
  31. package/dist/runtime/empty-completion.test.d.ts +1 -0
  32. package/dist/runtime/execution-report.d.ts +3 -0
  33. package/dist/runtime/forced-inspection.d.ts +13 -0
  34. package/dist/runtime/forced-inspection.test.d.ts +1 -0
  35. package/dist/runtime/javascript-api.d.ts +3 -0
  36. package/dist/runtime/think-signal.test.d.ts +1 -0
  37. package/dist/runtime/tool-wrapper.d.ts +4 -2
  38. package/dist/runtime/types.d.ts +8 -0
  39. package/dist/{schema-DBkjo0b7.cjs → schema-CXlnbb3n.cjs} +1 -1
  40. package/dist/{schema-Aer_W7Al.js → schema-GE4ISPCR.js} +1 -1
  41. package/dist/session/messages.d.ts +2 -0
  42. package/dist/session/serialization.d.ts +2 -0
  43. package/dist/session/session.d.ts +4 -0
  44. package/dist/session/speaker.test.d.ts +1 -0
  45. package/dist/{tool--gK91eez.js → tool-DstssiAs.js} +4 -4
  46. package/dist/{tool-Da_F-N-5.cjs → tool-_wK9hQOb.cjs} +4 -4
  47. package/dist/{truncate-BSoH2-nY.js → truncate-BEKbdo3t.js} +1 -1
  48. package/dist/{truncate-nV3Mxr6-.cjs → truncate-uomAMGPs.cjs} +1 -1
  49. package/dist/types.d.ts +6 -0
  50. package/dist/{typings-C1ihexWE.cjs → typings-BA_XxAcY.cjs} +1 -1
  51. package/dist/{typings-D9_aC8aq.js → typings-BEVDvtuk.js} +1 -1
  52. package/dist/vm/types.d.ts +2 -0
  53. package/dist/{vm-8jxt8PTK.js → vm-C7SfutHn.js} +28 -3
  54. package/dist/{vm-XuVPuW3Y.cjs → vm-gmekHc0i.cjs} +28 -2
  55. package/package.json +2 -1
@@ -1,13 +1,13 @@
1
1
  const require_utils = require("./utils-CTlsXvdj.cjs");
2
- const require_errors = require("./errors-IhnTKUp7.cjs");
3
- const require_component = require("./component-BpMVZYOa.cjs");
4
- const require_schema = require("./schema-DBkjo0b7.cjs");
5
- const require_truncate = require("./truncate-nV3Mxr6-.cjs");
6
- const require_quickjs_variant = require("./quickjs-variant-DJwYDSsb.cjs");
7
- const require_typings = require("./typings-C1ihexWE.cjs");
8
- const require_custom_client = require("./custom-client-MytucGI-.cjs");
9
- const require_native = require("./native-Bm6L9zOb.cjs");
10
- const require_vm = require("./vm-XuVPuW3Y.cjs");
2
+ const require_errors = require("./errors-C6ppQUZX.cjs");
3
+ const require_component = require("./component-CMFoCHyu.cjs");
4
+ const require_schema = require("./schema-CXlnbb3n.cjs");
5
+ const require_truncate = require("./truncate-uomAMGPs.cjs");
6
+ const require_quickjs_variant = require("./quickjs-variant-21IO97PF.cjs");
7
+ const require_typings = require("./typings-BA_XxAcY.cjs");
8
+ const require_custom_client = require("./custom-client-BwRYQ4Oa.cjs");
9
+ const require_native = require("./native-sbuzbLbY.cjs");
10
+ const require_vm = require("./vm-gmekHc0i.cjs");
11
11
  let _bpinternal_zui = require("@bpinternal/zui");
12
12
  let ulid = require("ulid");
13
13
  let _botpress_cognitive = require("@botpress/cognitive");
@@ -209,10 +209,7 @@ function errorPreview(value, inspector, identity) {
209
209
  //#region src/runtime/execution-diagnostics.ts
210
210
  /** XML-style boundaries keep diagnostic text separate from recovery instructions. */
211
211
  function reportSection(name, content, maxTokens = 2e3, options = {}) {
212
- const escape = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;");
213
- const heading = options.heading ? `${escape(options.heading)}\n` : "";
214
- const body = require_quickjs_variant.limitInspectionOutput(content, maxTokens, false, options.preserve ?? "top");
215
- return `<${name}>\n${heading}${/[<&]|\]\]>/.test(body) ? `<![CDATA[\n${body.replaceAll("]]>", "]]]]><![CDATA[>")}\n]]>` : body}\n</${name}>`;
212
+ return `<${name}>\n${options.heading ? `${options.heading}\n` : ""}${require_quickjs_variant.limitInspectionOutput(content, maxTokens, false, options.preserve ?? "top")}\n</${name}>`;
216
213
  }
217
214
  /** Show the specific failure and guest source, never the host's implementation stack. */
218
215
  function renderExecutionDiagnostics(error, message, inspector, identity) {
@@ -253,11 +250,58 @@ function renderSourceTrace(stack, inspector, identity) {
253
250
  }), 1e3);
254
251
  }
255
252
  //#endregion
253
+ //#region src/runtime/forced-inspection.ts
254
+ /** Keep attribution and content together, using the same display budgets as inspect(). */
255
+ function renderForcedInspection(inspections, inspector, identity, maxTokens, policies) {
256
+ return [
257
+ "<forced_inspection>",
258
+ "Forced inspection: the tools listed below completed successfully and requested review of their results.",
259
+ "This is the equivalent of an inspect() call. Do not repeat these tool calls; use the results below and retained variables.",
260
+ "No exit was applied. Review the evidence before continuing or completing the task.",
261
+ "",
262
+ "Tools requesting inspection (lines refer to the executed JavaScript):",
263
+ ...inspections.map((entry) => {
264
+ const entryIdentity = {
265
+ ...identity,
266
+ tool: entry.tool
267
+ };
268
+ const name = inspector(entry.tool, {
269
+ purpose: "name",
270
+ maxTokens: 80,
271
+ identity: entryIdentity
272
+ });
273
+ const reason = inspector(entry.reason, {
274
+ purpose: "error",
275
+ maxTokens: 1e3,
276
+ identity: entryIdentity
277
+ });
278
+ const budget = require_quickjs_variant.resolveInspectionBudget(entry.value, {
279
+ tokens: maxTokens,
280
+ policies
281
+ });
282
+ const result = inspector(entry.value, {
283
+ purpose: "result",
284
+ maxTokens,
285
+ policies,
286
+ identity: entryIdentity
287
+ });
288
+ return [
289
+ `<tool name="${name}" line="${entry.line ?? "unknown"}">`,
290
+ `<reason>${reason}</reason>`,
291
+ reportSection("result", result, budget.tokens, { preserve: budget.preserve }),
292
+ "</tool>"
293
+ ].join("\n");
294
+ }),
295
+ "</forced_inspection>"
296
+ ].join("\n");
297
+ }
298
+ //#endregion
256
299
  //#region src/runtime/execution-report.ts
257
300
  const MAX_REPORTED_CHANGES = 40;
258
301
  const MAX_OVERRIDE_SOURCE_LENGTH = 3e3;
259
302
  /** Format one settled outcome; execution is responsible for deciding what happened. */
260
303
  function renderExecutionReport({ outcome, activity, memory, source, requiresExit = false, iteration, identity = { iteration }, inspector = require_quickjs_variant.createInspector(), maxTokens = require_truncate.DEFAULT_TOOL_RESULT_MAX_TOKENS, policies }) {
304
+ var _outcome$forcedInspec, _outcome$forcedInspec2;
261
305
  const detail = (value) => inspector(value, {
262
306
  purpose: "error",
263
307
  maxTokens: 1e3,
@@ -284,6 +328,13 @@ function renderExecutionReport({ outcome, activity, memory, source, requiresExit
284
328
  });
285
329
  };
286
330
  const sections = [renderStatus(outcome, memory)];
331
+ if (outcome.type === "inspect" && ((_outcome$forcedInspec = outcome.forcedInspections) === null || _outcome$forcedInspec === void 0 ? void 0 : _outcome$forcedInspec.length)) {
332
+ sections.push(renderForcedInspection(outcome.forcedInspections, inspector, identity, maxTokens, policies));
333
+ if (outcome.downstreamError) {
334
+ sections.push(...renderExecutionDiagnostics(outcome.downstreamError, require_utils.getErrorMessage(outcome.downstreamError), inspector, identity));
335
+ sections.push(reportSection("recovery", "A later operation failed. The tool results above were successfully retrieved; inspect them and repair only the failed work. Do not repeat successful calls."));
336
+ }
337
+ }
287
338
  if (outcome.type === "error") {
288
339
  sections.push(...renderExecutionDiagnostics(outcome.error, outcome.message, inspector, identity));
289
340
  sections.push(reportSection("recovery", [
@@ -316,7 +367,7 @@ function renderExecutionReport({ outcome, activity, memory, source, requiresExit
316
367
  if (memory.unavailable.length > failures.length) entries.push(`- ${memory.unavailable.length - failures.length} additional values could not be retained.`);
317
368
  sections.push(reportSection("memory_errors", `Memory errors\n${entries.join("\n")}`));
318
369
  }
319
- if (outcome.type === "inspect") {
370
+ if (outcome.type === "inspect" && ((_outcome$forcedInspec2 = outcome.forcedInspections) === null || _outcome$forcedInspec2 === void 0 ? void 0 : _outcome$forcedInspec2.length) && (!outcome.explicit || outcome.forcedInspections.some((entry) => isEqual(entry.value, outcome.value)))) {} else if (outcome.type === "inspect") {
320
371
  const heading = outcome.explicit ? "inspect() result" : "Result";
321
372
  sections.push(outcome.available ? resultSection("result", heading, outcome.value) : reportSection("result", "Unavailable; see memory errors above.", maxTokens, { heading }));
322
373
  } else if (outcome.type === "exit") sections.push(resultSection("completion", `Completion\nExit "${outcome.name}" completed.`, outcome.value === void 0 ? "" : outcome.value));
@@ -364,6 +415,12 @@ function renderChanges(label, changes, name) {
364
415
  return lines.join("\n");
365
416
  }
366
417
  //#endregion
418
+ //#region src/prompts/reasoning.ts
419
+ /** Supplement explicit reasoning disablement consistently across providers and fallbacks. */
420
+ function getReasoningHint(reasoningEffort) {
421
+ return reasoningEffort === "none" ? "/no_think" : void 0;
422
+ }
423
+ //#endregion
367
424
  //#region src/runtime/generate.ts
368
425
  const STREAM_IDLE_TIMEOUT = 18e4;
369
426
  const STATIC_TOKEN_PARTS = [
@@ -460,7 +517,13 @@ async function prepareNativeRequest({ iteration, ctx, cognitive, controller, met
460
517
  const model = models[0];
461
518
  const { limit, output: reserve } = require_custom_client.resolveTokenBudget(models, ctx.maxTokens);
462
519
  const tools = [require_native.getRunJavaScriptTool(!!ctx.chat)];
463
- const system = [iteration.systemMessage];
520
+ const systemMessage = structuredClone(iteration.systemMessage);
521
+ const reasoningHint = getReasoningHint(iteration.reasoningEffort);
522
+ if (reasoningHint) systemMessage.content = typeof systemMessage.content === "string" ? `${systemMessage.content}\n\n${reasoningHint}` : [...systemMessage.content ?? [], {
523
+ type: "text",
524
+ text: reasoningHint
525
+ }];
526
+ const system = [systemMessage];
464
527
  const budgetInstruction = getBudgetInstruction(ctx, iteration);
465
528
  const budget = `\n\nExecution budget: response ${ctx.iterations.length} of ${ctx.loop}. ${budgetInstruction}`;
466
529
  const buildMessages = (retainedIds, summary) => {
@@ -852,6 +915,7 @@ const isRecord = (value) => value !== null && typeof value === "object" && !Arra
852
915
  function createJavaScriptApi({ iteration, components, exits, deliver, signal, onError }) {
853
916
  const decisions = /* @__PURE__ */ new Map();
854
917
  const pending = /* @__PURE__ */ new Set();
918
+ const inspections = [];
855
919
  let open = true;
856
920
  let outstanding = [];
857
921
  let delivery;
@@ -988,6 +1052,10 @@ function createJavaScriptApi({ iteration, components, exits, deliver, signal, on
988
1052
  isReceipt: (value) => resolve(value) !== void 0,
989
1053
  getTerminalOutcome: () => terminalOutcome,
990
1054
  getInterruption: () => interruption,
1055
+ requestInspection: (inspection) => {
1056
+ inspections.push(inspection);
1057
+ },
1058
+ getForcedInspections: () => inspections,
991
1059
  throwIfTerminated,
992
1060
  track,
993
1061
  assertOpen,
@@ -1015,8 +1083,8 @@ const finalizeIteration = async ({ iteration, status, controller, onIterationEnd
1015
1083
  //#endregion
1016
1084
  //#region src/runtime/tool-wrapper.ts
1017
1085
  const SLOW_TOOL_WARNING = (0, ms.default)("15s");
1018
- function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation, onResult, controller }) {
1019
- return async function(input) {
1086
+ function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation, onResult, controller, onThink }) {
1087
+ return async function(input, line) {
1020
1088
  controller.signal.throwIfAborted();
1021
1089
  const toolCallId = `tcall_${(0, ulid.ulid)()}`;
1022
1090
  const originalInput = input;
@@ -1035,7 +1103,7 @@ function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation
1035
1103
  let output;
1036
1104
  let error;
1037
1105
  let success = true;
1038
- let signalToThrow;
1106
+ const inspections = [];
1039
1107
  const pushToolCallTrace = () => {
1040
1108
  iteration.recordTrace({
1041
1109
  type: "tool_call",
@@ -1051,32 +1119,21 @@ function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation
1051
1119
  success
1052
1120
  });
1053
1121
  };
1054
- const handleSignals = async (err) => {
1055
- if (output === err) return true;
1056
- if (require_errors.ThinkSignal.is(err)) {
1057
- signalToThrow = err;
1058
- iteration.recordTrace({
1059
- type: "think_signal",
1060
- started_at: Date.now(),
1061
- line: 0,
1062
- ended_at: Date.now()
1063
- });
1064
- success = true;
1065
- output = err;
1066
- const afterRes = await callHook(() => afterHook === null || afterHook === void 0 ? void 0 : afterHook({
1067
- iteration,
1068
- tool,
1069
- input: originalInput,
1070
- output,
1071
- controller,
1072
- object,
1073
- toolCallId,
1074
- nativeCallId: iteration.nativeCallId
1075
- }));
1076
- if (typeof (afterRes === null || afterRes === void 0 ? void 0 : afterRes.output) !== "undefined") output = afterRes.output;
1077
- return true;
1078
- }
1079
- return false;
1122
+ const unwrapSignal = (value) => {
1123
+ if (!require_errors.ThinkSignal.is(value)) return value;
1124
+ const context = value.context;
1125
+ const output = require_truncate.unwrapTruncated(context);
1126
+ if (require_truncate.isTruncated(context)) onTruncation === null || onTruncation === void 0 || onTruncation(output, context.$$truncate);
1127
+ const inspection = {
1128
+ tool: object ? `${object}.${tool.name}` : tool.name,
1129
+ toolCallId,
1130
+ line,
1131
+ reason: value.reason,
1132
+ value: output,
1133
+ metadata: value.metadata
1134
+ };
1135
+ inspections.push(inspection);
1136
+ return output;
1080
1137
  };
1081
1138
  try {
1082
1139
  const beforeRes = await callHook(() => beforeHook === null || beforeHook === void 0 ? void 0 : beforeHook({
@@ -1088,18 +1145,25 @@ function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation
1088
1145
  toolCallId,
1089
1146
  nativeCallId: iteration.nativeCallId
1090
1147
  }));
1148
+ if (require_errors.ThinkSignal.is(beforeRes)) throw new require_errors.HookError("Tool hooks cannot request inspection with ThinkSignal. Return it from the tool handler instead.");
1091
1149
  if (typeof (beforeRes === null || beforeRes === void 0 ? void 0 : beforeRes.input) !== "undefined") effectiveInput = beforeRes.input;
1092
1150
  controller.signal.throwIfAborted();
1093
- output = await tool.execute(effectiveInput, {
1094
- callId: toolCallId,
1095
- iterationId: iteration.id,
1096
- nativeCallId: iteration.nativeCallId,
1097
- onTruncation,
1098
- onInput: (parsed) => {
1099
- controller.signal.throwIfAborted();
1100
- if (effectiveInput === originalInput) reportedInput = parsed;
1101
- }
1102
- });
1151
+ try {
1152
+ output = await tool.execute(effectiveInput, {
1153
+ callId: toolCallId,
1154
+ iterationId: iteration.id,
1155
+ nativeCallId: iteration.nativeCallId,
1156
+ onTruncation,
1157
+ onInput: (parsed) => {
1158
+ controller.signal.throwIfAborted();
1159
+ if (effectiveInput === originalInput) reportedInput = parsed;
1160
+ }
1161
+ });
1162
+ } catch (error) {
1163
+ if (!require_errors.ThinkSignal.is(error)) throw error;
1164
+ output = error;
1165
+ }
1166
+ output = unwrapSignal(output);
1103
1167
  const afterRes = await callHook(() => afterHook === null || afterHook === void 0 ? void 0 : afterHook({
1104
1168
  iteration,
1105
1169
  tool,
@@ -1110,19 +1174,39 @@ function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation
1110
1174
  toolCallId,
1111
1175
  nativeCallId: iteration.nativeCallId
1112
1176
  }));
1177
+ if (require_errors.ThinkSignal.is(afterRes) || require_errors.ThinkSignal.is(afterRes === null || afterRes === void 0 ? void 0 : afterRes.output)) throw new require_errors.HookError("Tool hooks cannot request inspection with ThinkSignal. Return it from the tool handler instead.");
1113
1178
  if (typeof (afterRes === null || afterRes === void 0 ? void 0 : afterRes.output) !== "undefined") output = afterRes.output;
1179
+ controller.signal.throwIfAborted();
1114
1180
  } catch (err) {
1115
- if (!await handleSignals(err)) {
1116
- success = false;
1117
- error = require_errors.isLLMzError(err) ? err : new require_errors.ToolExecutionError(tool.name, err);
1118
- iteration.recordError(error);
1119
- }
1181
+ success = false;
1182
+ output = void 0;
1183
+ if (require_errors.ThinkSignal.is(err)) error = new require_errors.HookError("Tool hooks cannot request inspection with ThinkSignal. Return it from the tool handler instead.");
1184
+ else error = require_errors.isLLMzError(err) ? err : new require_errors.ToolExecutionError(tool.name, err);
1185
+ iteration.recordError(error);
1120
1186
  } finally {
1121
1187
  clearTimeout(alertSlowTool);
1188
+ for (const inspection of success ? inspections : []) {
1189
+ const value = require_quickjs_variant.snapshotInspectionValue(output);
1190
+ onThink === null || onThink === void 0 || onThink({
1191
+ ...inspection,
1192
+ value
1193
+ });
1194
+ iteration.recordTrace({
1195
+ type: "think_signal",
1196
+ started_at: Date.now(),
1197
+ ended_at: Date.now(),
1198
+ line: line ?? 0,
1199
+ tool_name: tool.name,
1200
+ tool_call_id: toolCallId,
1201
+ object,
1202
+ reason: inspection.reason,
1203
+ context: value,
1204
+ metadata: inspection.metadata
1205
+ });
1206
+ }
1122
1207
  pushToolCallTrace();
1123
1208
  }
1124
1209
  if (!success) throw error;
1125
- if (signalToThrow) throw signalToThrow;
1126
1210
  onResult === null || onResult === void 0 || onResult(output);
1127
1211
  return output;
1128
1212
  };
@@ -1213,9 +1297,14 @@ const buildVMContext = ({ ctx, iteration, controller, onBeforeTool, onAfterTool,
1213
1297
  afterHook: onAfterTool,
1214
1298
  onTruncation,
1215
1299
  onResult: onToolResult,
1216
- controller
1300
+ controller,
1301
+ onThink: javascriptApi === null || javascriptApi === void 0 ? void 0 : javascriptApi.requestInspection
1217
1302
  });
1218
- instance[tool.name] = javascriptApi ? (input) => javascriptApi.track(() => wrapped(input)) : wrapped;
1303
+ instance[tool.name] = javascriptApi ? (input) => {
1304
+ var _vmContext$VM_CALL_SI;
1305
+ const line = (_vmContext$VM_CALL_SI = vmContext[require_vm.VM_CALL_SITE]) === null || _vmContext$VM_CALL_SI === void 0 ? void 0 : _vmContext$VM_CALL_SI.call(vmContext);
1306
+ return javascriptApi.track(() => wrapped(input, line));
1307
+ } : wrapped;
1219
1308
  }
1220
1309
  vmContext[obj.name] = require_vm.withMissingMember(instance, (name) => {
1221
1310
  const error = new require_errors.UnknownToolError(`${obj.name}.${name}`, (obj.tools ?? []).map((tool) => `${obj.name}.${tool.name}`));
@@ -1231,9 +1320,14 @@ const buildVMContext = ({ ctx, iteration, controller, onBeforeTool, onAfterTool,
1231
1320
  afterHook: onAfterTool,
1232
1321
  onTruncation,
1233
1322
  onResult: onToolResult,
1234
- controller
1323
+ controller,
1324
+ onThink: javascriptApi === null || javascriptApi === void 0 ? void 0 : javascriptApi.requestInspection
1235
1325
  });
1236
- const callable = javascriptApi ? (input) => javascriptApi.track(() => wrapped(input)) : wrapped;
1326
+ const callable = javascriptApi ? (input) => {
1327
+ var _vmContext$VM_CALL_SI2;
1328
+ const line = (_vmContext$VM_CALL_SI2 = vmContext[require_vm.VM_CALL_SITE]) === null || _vmContext$VM_CALL_SI2 === void 0 ? void 0 : _vmContext$VM_CALL_SI2.call(vmContext);
1329
+ return javascriptApi.track(() => wrapped(input, line));
1330
+ } : wrapped;
1237
1331
  for (const key of [tool.name, ...tool.aliases ?? []]) vmContext[key] = callable;
1238
1332
  }
1239
1333
  return vmContext;
@@ -1273,9 +1367,10 @@ async function executeContextInternal(props) {
1273
1367
  });
1274
1368
  let release;
1275
1369
  try {
1276
- var _ctx$iterations$at;
1370
+ var _props$options8, _ctx$iterations$at;
1277
1371
  if ("snapshot" in props) throw new require_errors.InvalidConfigurationError("Snapshots and external pause/resume are no longer supported. Use a session for conversation history and memory.");
1278
1372
  if ("messages" in props) throw new require_errors.InvalidConfigurationError("Append input with session.append(message) before calling execute(). execute.messages is no longer supported.");
1373
+ if (((_props$options8 = props.options) === null || _props$options8 === void 0 ? void 0 : _props$options8.requireChatResponse) !== void 0 && typeof props.options.requireChatResponse !== "boolean") throw new require_errors.InvalidConfigurationError("Invalid requireChatResponse. Expected a boolean.");
1279
1374
  release = ctx.session.acquire();
1280
1375
  prepareSession(ctx);
1281
1376
  const client = props.client ?? new _botpress_client.Client();
@@ -1458,20 +1553,21 @@ async function rejectNativeBatch({ ctx, iteration }, generated, errors) {
1458
1553
  }, generated.toolCalls.some((call) => call.name !== "run_javascript") ? new require_errors.UnknownToolError(generated.toolCalls.find((call) => call.name !== "run_javascript").name, ["run_javascript"], message) : new require_errors.NativeProtocolError(message));
1459
1554
  }
1460
1555
  async function deliverAssistantText(state, generated) {
1556
+ var _iteration$response4;
1461
1557
  const { ctx, iteration } = state;
1462
- if (!generated.output.trim() || !ctx.chat) return;
1558
+ if (!generated.output.trim() || !ctx.chat || !((_iteration$response4 = iteration.response) === null || _iteration$response4 === void 0 ? void 0 : _iteration$response4.handler)) return;
1463
1559
  const startedAt = Date.now();
1464
1560
  const message = {
1465
1561
  type: "text",
1466
1562
  text: generated.output
1467
1563
  };
1468
1564
  try {
1469
- var _iteration$response4, _iteration$response4$;
1470
- await ((_iteration$response4 = iteration.response) === null || _iteration$response4 === void 0 || (_iteration$response4$ = _iteration$response4.handler) === null || _iteration$response4$ === void 0 ? void 0 : _iteration$response4$.call(_iteration$response4, generated.output.trim(), generated.messageMetadata));
1565
+ await iteration.response.handler(generated.output.trim(), generated.messageMetadata);
1471
1566
  } catch (cause) {
1472
1567
  if (require_errors.isCriticalError(cause)) throw cause;
1473
1568
  throw new require_errors.DeliveryError(`Assistant response delivery failed: ${require_utils.getErrorMessage(cause)}`, { cause });
1474
1569
  }
1570
+ ctx.session.recordAssistantDelivery(iteration.id);
1475
1571
  iteration.recordTrace({
1476
1572
  type: "message_delivery",
1477
1573
  value: message,
@@ -1509,6 +1605,31 @@ async function settleJavaScriptCall(state, execution) {
1509
1605
  inspected: (outcome === null || outcome === void 0 ? void 0 : outcome.type) === "inspect"
1510
1606
  };
1511
1607
  if ((outcome === null || outcome === void 0 ? void 0 : outcome.type) === "inspect" && result.success) result.return_value = outcome.value;
1608
+ const forcedInspections = api.getForcedInspections();
1609
+ if (forcedInspections.length && !controller.signal.aborted && !require_errors.isCriticalError(result.error)) {
1610
+ if (!result.success && result.error) {
1611
+ iteration.recordError(result.error);
1612
+ state.capture.downstreamError = result.error;
1613
+ }
1614
+ state.capture.forcedInspections = forcedInspections;
1615
+ let value = forcedInspections.length === 1 ? forcedInspections[0].value : forcedInspections.map((entry) => entry.value);
1616
+ if ((outcome === null || outcome === void 0 ? void 0 : outcome.type) === "inspect") value = outcome.value;
1617
+ state.capture.result = {
1618
+ ...result,
1619
+ success: true,
1620
+ signal: void 0,
1621
+ return_value: value
1622
+ };
1623
+ iteration.end({
1624
+ type: "thinking_requested",
1625
+ thinking_requested: {
1626
+ reason: "Tools completed successfully and requested forced inspection.",
1627
+ variables: value,
1628
+ metadata: forcedInspections.length === 1 ? forcedInspections[0].metadata : void 0
1629
+ }
1630
+ });
1631
+ return;
1632
+ }
1512
1633
  if ((outcome === null || outcome === void 0 ? void 0 : outcome.type) === "exit") {
1513
1634
  await completeJavaScriptExit(state, result, outcome);
1514
1635
  return;
@@ -1568,11 +1689,11 @@ function containsDecision(value, api, seen = /* @__PURE__ */ new Set()) {
1568
1689
  return Object.values(value).some((nested) => containsDecision(nested, api, seen));
1569
1690
  }
1570
1691
  async function completeJavaScriptExit(state, result, outcome) {
1571
- const { iteration, controller, props } = state;
1692
+ const { iteration, controller } = state;
1572
1693
  state.memory = commitMemory(state, result, false);
1573
1694
  try {
1574
1695
  controller.signal.throwIfAborted();
1575
- await applyNativeExit(iteration, outcome.exit, outcome.value, controller, props.onExit);
1696
+ await applyNativeExit(state, outcome.exit, outcome.value);
1576
1697
  } catch (error) {
1577
1698
  endFailedIteration(iteration, controller, error);
1578
1699
  }
@@ -1604,6 +1725,7 @@ async function deliverJavaScriptMessages({ ctx, iteration, controller }, message
1604
1725
  });
1605
1726
  throw require_errors.isCriticalError(error) ? error : new require_errors.DeliveryError(`Delivery ${message.id} failed: ${require_utils.getErrorMessage(error)}. Its external outcome is uncertain. Later messages were skipped; earlier acknowledged messages remain delivered.`, { cause: error });
1606
1727
  }
1728
+ ctx.session.recordAssistantDelivery(iteration.id);
1607
1729
  iteration.recordTrace({
1608
1730
  type: "message_delivery",
1609
1731
  value: message.component,
@@ -1616,9 +1738,9 @@ async function deliverJavaScriptMessages({ ctx, iteration, controller }, message
1616
1738
  }
1617
1739
  }
1618
1740
  async function finishNativeResponse(state, generated) {
1619
- const { ctx, iteration, controller, props } = state;
1620
- if (!generated.toolCalls.length && generated.output.trim() && ctx.chat) {
1621
- await applyNativeExit(iteration, require_custom_client.ListenExit, {}, controller, props.onExit);
1741
+ const { ctx, iteration } = state;
1742
+ if (!generated.toolCalls.length && ctx.chat && (generated.output.trim() || generated.metadata.stopReason === "stop")) {
1743
+ await applyNativeExit(state, require_custom_client.ListenExit, {});
1622
1744
  if (!iteration.hasExited()) ctx.session.appendContext(ctx.inspector(iteration.error ?? "Completion rejected.", {
1623
1745
  purpose: "error",
1624
1746
  maxTokens: 200
@@ -1717,7 +1839,9 @@ function getExecutionOutcome(state, memory) {
1717
1839
  type: "inspect",
1718
1840
  value: (capture === null || capture === void 0 ? void 0 : capture.result.success) ? capture.result.return_value : void 0,
1719
1841
  available: memory.resultAvailable,
1720
- explicit: (capture === null || capture === void 0 ? void 0 : capture.inspected) ?? false
1842
+ explicit: (capture === null || capture === void 0 ? void 0 : capture.inspected) ?? false,
1843
+ forcedInspections: capture === null || capture === void 0 ? void 0 : capture.forcedInspections,
1844
+ downstreamError: capture === null || capture === void 0 ? void 0 : capture.downstreamError
1721
1845
  };
1722
1846
  }
1723
1847
  return {
@@ -1809,12 +1933,18 @@ function getIterationResult(state) {
1809
1933
  }
1810
1934
  if (iteration.status.type === "aborted") return new require_custom_client.ErrorExecutionResult(ctx, iteration.error);
1811
1935
  }
1812
- async function applyNativeExit(iteration, exit, value, controller, onExit) {
1936
+ async function applyNativeExit(state, exit, value) {
1937
+ const { ctx, iteration, controller, props } = state;
1813
1938
  try {
1814
- await callHook(() => onExit === null || onExit === void 0 ? void 0 : onExit({
1815
- exit,
1816
- result: value
1817
- }, controller));
1939
+ var _props$options9;
1940
+ if (ctx.chat && exit === require_custom_client.ListenExit && ((_props$options9 = props.options) === null || _props$options9 === void 0 ? void 0 : _props$options9.requireChatResponse) !== false && ctx.session.lastSpeaker !== "assistant") throw new require_errors.MissingChatResponseError("The assistant has not delivered a message since the last user message. Send a response using the inspected results before waiting for the user. Do not repeat completed tool calls.");
1941
+ await callHook(() => {
1942
+ var _props$onExit;
1943
+ return (_props$onExit = props.onExit) === null || _props$onExit === void 0 ? void 0 : _props$onExit.call(props, {
1944
+ exit,
1945
+ result: value
1946
+ }, controller);
1947
+ });
1818
1948
  controller.signal.throwIfAborted();
1819
1949
  iteration.end({
1820
1950
  type: "exit_success",