llmz 0.9.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +232 -1794
- package/ERRORS.md +101 -0
- package/README.md +96 -582
- package/dist/chat/chat.d.ts +63 -0
- package/dist/chat/component.d.ts +31 -0
- package/dist/chat/component.default.d.ts +58 -0
- package/dist/chat/response.d.ts +15 -0
- package/dist/compiler/compiler.d.ts +2 -7
- package/dist/compiler/plugins/dynamic-code.d.ts +7 -0
- package/dist/compiler/plugins/replace-comment.d.ts +2 -3
- package/dist/compiler/plugins/return-async.d.ts +5 -4
- package/dist/compiler/plugins/termination.d.ts +8 -0
- package/dist/compiler/plugins/tool-resolution.d.ts +4 -0
- package/dist/compiler/plugins/variable-extraction.d.ts +2 -8
- package/dist/component-CMFoCHyu.cjs +649 -0
- package/dist/component-DncqP4fB.js +614 -0
- package/dist/context.d.ts +71 -378
- package/dist/custom-client-C-WXvLD9.js +1655 -0
- package/dist/custom-client-Cgt9_0r1.cjs +1732 -0
- package/dist/custom-client.d.ts +12 -2
- package/dist/errors/catalog.d.ts +294 -0
- package/dist/errors/hooks.d.ts +2 -0
- package/dist/errors-C6ppQUZX.cjs +893 -0
- package/dist/errors-Crk5P8jo.js +636 -0
- package/dist/errors.d.ts +24 -36
- package/dist/execute-CiYvPs5Q.js +2061 -0
- package/dist/execute-DTTfacsi.cjs +2062 -0
- package/dist/{exit-DUM96DN1.cjs → exit-BOtKWPuT.cjs} +38 -28
- package/dist/{exit-CDdxDBRT.js → exit-DMPwCSba.js} +37 -27
- package/dist/exit.d.ts +19 -16
- package/dist/index.cjs +177 -1237
- package/dist/index.d.ts +25 -28
- package/dist/index.js +137 -1213
- package/dist/index.workerd.js +8974 -11145
- package/dist/inspect.d.ts +18 -4
- package/dist/inspection.d.ts +40 -0
- package/dist/native-0bq5ATZM.cjs +212 -0
- package/dist/native-n_718Z-T.js +177 -0
- package/dist/objects.d.ts +2 -57
- package/dist/prompts/native.d.ts +2 -0
- package/dist/prompts/prompt.d.ts +10 -101
- package/dist/quickjs-variant-21IO97PF.cjs +1080 -0
- package/dist/quickjs-variant-CtuGagsb.js +985 -0
- package/dist/result.d.ts +30 -861
- package/dist/runtime/execute.d.ts +3 -2
- package/dist/runtime/execution-activity.d.ts +11 -0
- package/dist/runtime/execution-diagnostics.d.ts +11 -0
- package/dist/runtime/execution-report.d.ts +51 -0
- package/dist/runtime/fixtures/chat.d.ts +8 -0
- package/dist/runtime/fixtures/long-search.d.ts +1 -1
- package/dist/runtime/fixtures/native-client.d.ts +33 -0
- package/dist/runtime/fixtures/protocol-languages.d.ts +1 -1
- package/dist/runtime/forced-inspection.d.ts +13 -0
- package/dist/runtime/forced-inspection.test.d.ts +1 -0
- package/dist/runtime/generate.d.ts +23 -20
- package/dist/runtime/generate.test.d.ts +1 -0
- package/dist/runtime/hook-provenance.test.d.ts +1 -0
- package/dist/runtime/inspection-hook.test.d.ts +1 -0
- package/dist/runtime/inspection-values.d.ts +14 -0
- package/dist/runtime/inspection-values.test.d.ts +1 -0
- package/dist/runtime/interruption-control-flow.test.d.ts +1 -0
- package/dist/runtime/interruption-settings.test.d.ts +1 -0
- package/dist/runtime/javascript-api.d.ts +62 -0
- package/dist/runtime/javascript-api.test.d.ts +1 -0
- package/dist/runtime/native-review.test.d.ts +1 -0
- package/dist/runtime/native-tools.d.ts +18 -0
- package/dist/runtime/native-tools.test.d.ts +1 -0
- package/dist/runtime/object-memory.test.d.ts +1 -0
- package/dist/runtime/single-tool.test.d.ts +1 -0
- package/dist/runtime/think-signal.test.d.ts +1 -0
- package/dist/runtime/token-budget.d.ts +22 -0
- package/dist/runtime/token-budget.test.d.ts +1 -0
- package/dist/runtime/tool-wrapper.d.ts +6 -5
- package/dist/runtime/traces.test.d.ts +1 -0
- package/dist/runtime/truncation.test.d.ts +1 -0
- package/dist/runtime/types.d.ts +47 -31
- package/dist/runtime/variable-recovery.test.d.ts +1 -0
- package/dist/runtime/vm-context.d.ts +6 -1
- package/dist/runtime/worker-completion.test.d.ts +1 -0
- package/dist/runtime-names.d.ts +4 -0
- package/dist/schema-CXlnbb3n.cjs +68 -0
- package/dist/schema-GE4ISPCR.js +45 -0
- package/dist/schema.d.ts +10 -0
- package/dist/schema.test.d.ts +1 -0
- package/dist/session/compactor.d.ts +51 -0
- package/dist/session/compactor.test.d.ts +1 -0
- package/dist/session/history.d.ts +36 -0
- package/dist/session/history.test.d.ts +1 -0
- package/dist/session/json.d.ts +3 -0
- package/dist/session/json.test.d.ts +1 -0
- package/dist/session/memory-codec.d.ts +9 -0
- package/dist/session/memory-codec.test.d.ts +1 -0
- package/dist/session/memory-render.d.ts +15 -0
- package/dist/session/memory-render.test.d.ts +1 -0
- package/dist/session/memory.d.ts +112 -0
- package/dist/session/memory.test.d.ts +1 -0
- package/dist/session/messages.d.ts +19 -0
- package/dist/session/messages.test.d.ts +1 -0
- package/dist/session/serialization.d.ts +36 -0
- package/dist/session/serialization.test.d.ts +1 -0
- package/dist/session/session-memory.test.d.ts +1 -0
- package/dist/session/session.d.ts +121 -0
- package/dist/session/session.test.d.ts +1 -0
- package/dist/session/speaker.test.d.ts +1 -0
- package/dist/{transcript.d.ts → session/transcript.d.ts} +4 -8
- package/dist/session/transcript.test.d.ts +1 -0
- package/dist/{tool-Bv8N4IPj.js → tool-DstssiAs.js} +144 -92
- package/dist/{tool-Dy6AJpJH.cjs → tool-_wK9hQOb.cjs} +146 -94
- package/dist/tool.d.ts +25 -17
- package/dist/truncate-BEKbdo3t.js +79 -0
- package/dist/truncate-uomAMGPs.cjs +102 -0
- package/dist/truncate.d.ts +24 -0
- package/dist/truncate.test.d.ts +1 -0
- package/dist/types.d.ts +33 -9
- package/dist/{typings-3lsqCbkn.cjs → typings-BA_XxAcY.cjs} +38 -193
- package/dist/{typings-CrBa7Tyy.js → typings-BEVDvtuk.js} +38 -175
- package/dist/typings-formatter.d.ts +1 -1
- package/dist/typings.d.ts +3 -0
- package/dist/{uniq-BYQ7GWwb.js → uniq-DfUeSNaX.js} +2 -2
- package/dist/{uniq-G872RWmE.cjs → uniq-DiXgysNV.cjs} +6 -18
- package/dist/{_baseIteratee-P_firB7b.js → utils-BOFzb8Ok.js} +1134 -16
- package/dist/{_baseIteratee-CF4qP2a8.cjs → utils-CTlsXvdj.cjs} +1281 -84
- package/dist/vm/drivers/node.d.ts +1 -1
- package/dist/vm/drivers/quickjs.d.ts +1 -1
- package/dist/vm/errors.d.ts +4 -4
- package/dist/vm/index.d.ts +3 -4
- package/dist/vm/instrument.d.ts +14 -6
- package/dist/vm/member-proxy.d.ts +4 -0
- package/dist/vm/member-proxy.test.d.ts +1 -0
- package/dist/vm/memory.test.d.ts +1 -0
- package/dist/vm/return-semantics.test.d.ts +1 -0
- package/dist/vm/types.d.ts +20 -3
- package/dist/{vm-BLsHw1da.js → vm-C7SfutHn.js} +1187 -180
- package/dist/{vm-D6s1zF6M.cjs → vm-gmekHc0i.cjs} +1221 -207
- package/package.json +13 -6
- package/dist/_baseForOwn-BfWDTL8L.cjs +0 -53
- package/dist/_baseForOwn-CFhWe_W6.js +0 -48
- package/dist/_getPrototype-CG7Dxrrz.js +0 -6
- package/dist/_getPrototype-DQDlNVVM.cjs +0 -10
- package/dist/_overArg-C5Hy7oCi.cjs +0 -196
- package/dist/_overArg-CRYbj1NH.js +0 -155
- package/dist/chat.d.ts +0 -401
- package/dist/common-BlRFtdf2.js +0 -807
- package/dist/common-BnvrDnIT.cjs +0 -860
- package/dist/compiler/plugins/track-tool-calls.d.ts +0 -33
- package/dist/compiler-C-OI9sim.cjs +0 -547
- package/dist/compiler-CW1VjQsn.js +0 -473
- package/dist/component-C6Agl2ns.cjs +0 -73
- package/dist/component-DGG7d_Mz.js +0 -44
- package/dist/component.d.ts +0 -88
- package/dist/component.default.d.ts +0 -278
- package/dist/custom-client-ChuZ63zp.js +0 -2658
- package/dist/custom-client-DAsGRnYc.cjs +0 -2729
- package/dist/dual-modes-DDkoCp3R.js +0 -3006
- package/dist/dual-modes-DPXiuvNe.cjs +0 -3090
- package/dist/errors-C962uJdS.cjs +0 -220
- package/dist/errors-Cg1G0Awu.js +0 -161
- package/dist/example-format.d.ts +0 -8
- package/dist/example.d.ts +0 -45
- package/dist/execute-BWcdv9so.js +0 -1059
- package/dist/execute-DM2-7y86.cjs +0 -1060
- package/dist/exit-parser.d.ts +0 -39
- package/dist/handlers.d.ts +0 -10
- package/dist/hoist.d.ts +0 -2
- package/dist/isEmpty-BhJRCqIF.js +0 -52
- package/dist/isEmpty-LY533Wmh.cjs +0 -57
- package/dist/isPlainObject-CSxXVKCk.cjs +0 -56
- package/dist/isPlainObject-D39AzPO2.js +0 -51
- package/dist/jsx-CIgdGGVs.js +0 -52
- package/dist/jsx-owqxrquU.cjs +0 -75
- package/dist/jsx.d.ts +0 -11
- package/dist/message-stream/index.d.ts +0 -9
- package/dist/message-stream/instructions.d.ts +0 -30
- package/dist/message-stream/normalizer.d.ts +0 -21
- package/dist/message-stream/parser.d.ts +0 -89
- package/dist/message-stream/registry.d.ts +0 -14
- package/dist/message-stream/replayable.d.ts +0 -27
- package/dist/message-stream/response-parser.d.ts +0 -24
- package/dist/message-stream/sanitize.d.ts +0 -10
- package/dist/message-stream/stream.d.ts +0 -54
- package/dist/message-stream/types.d.ts +0 -97
- package/dist/message-stream/validator.d.ts +0 -23
- package/dist/prompts/chat-mode/protocol.d.ts +0 -2
- package/dist/prompts/chat-mode/system.d.ts +0 -2
- package/dist/prompts/chat-mode/system.md.d.ts +0 -2
- package/dist/prompts/chat-mode/user.d.ts +0 -2
- package/dist/prompts/chat-mode/user.md.d.ts +0 -2
- package/dist/prompts/code-examples.d.ts +0 -2
- package/dist/prompts/common.d.ts +0 -7
- package/dist/prompts/dual-modes.d.ts +0 -2
- package/dist/prompts/execution-history.d.ts +0 -6
- package/dist/prompts/execution-state.d.ts +0 -3
- package/dist/prompts/protocol-basics.d.ts +0 -5
- package/dist/prompts/protocol.d.ts +0 -31
- package/dist/prompts/worker-mode/protocol.d.ts +0 -2
- package/dist/prompts/worker-mode/system.d.ts +0 -2
- package/dist/prompts/worker-mode/system.md.d.ts +0 -2
- package/dist/prompts/worker-mode/user.d.ts +0 -2
- package/dist/prompts/worker-mode/user.md.d.ts +0 -2
- package/dist/quickjs-variant-BYhMBpwU.js +0 -45
- package/dist/quickjs-variant-CsIwTVFC.cjs +0 -56
- package/dist/rolldown-runtime-EAsCxrDo.js +0 -14
- package/dist/runtime/fixtures/qwen-protocol-failures.d.ts +0 -29
- package/dist/runtime/interpret-result.d.ts +0 -22
- package/dist/snapshots.d.ts +0 -249
- package/dist/stack-traces-BIE_5Xwf.js +0 -21
- package/dist/stack-traces-ntw_qhoy.cjs +0 -26
- package/dist/truncator-CLkouTCO.cjs +0 -276
- package/dist/truncator-DZqEqnpD.js +0 -253
- package/dist/truncator.d.ts +0 -118
- package/dist/utils-3ESwP3yg.cjs +0 -1075
- package/dist/utils-UBeAFeEI.js +0 -950
- /package/dist/{citations.d.ts → chat/citations.d.ts} +0 -0
- /package/dist/{citations.test.d.ts → chat/citations.test.d.ts} +0 -0
- /package/dist/{component.default.test.d.ts → chat/component.default.test.d.ts} +0 -0
- /package/dist/{compiler/plugins/track-tool-calls.test.d.ts → chat/component.test.d.ts} +0 -0
- /package/dist/{example.test.d.ts → chat/response.test.d.ts} +0 -0
- /package/dist/{exit-parser.test.d.ts → compiler/plugins/dynamic-code.test.d.ts} +0 -0
- /package/dist/{handlers.test.d.ts → compiler/plugins/tool-resolution.test.d.ts} +0 -0
- /package/dist/{hoist.test.d.ts → errors/catalog.test.d.ts} +0 -0
- /package/dist/{message-stream/instructions.test.d.ts → exit.test.d.ts} +0 -0
- /package/dist/{message-stream/normalizer.test.d.ts → inspection.test.d.ts} +0 -0
- /package/dist/{message-stream/parser.test.d.ts → prompts/native.test.d.ts} +0 -0
- /package/dist/{message-stream/response-parser.test.d.ts → result.test.d.ts} +0 -0
- /package/dist/{message-stream/stream.test.d.ts → runtime/chat-completion.test.d.ts} +0 -0
- /package/dist/{message-stream/validator.test.d.ts → runtime/chat-delivery.test.d.ts} +0 -0
- /package/dist/{prompts/adherence.test.d.ts → runtime/chat-last-speaker.test.d.ts} +0 -0
- /package/dist/{prompts/catalogue-examples.test.d.ts → runtime/compatibility-regressions.test.d.ts} +0 -0
- /package/dist/{prompts/code-examples.test.d.ts → runtime/context-registration.test.d.ts} +0 -0
- /package/dist/{prompts/common.test.d.ts → runtime/empty-completion.test.d.ts} +0 -0
- /package/dist/{prompts/concrete-patterns.test.d.ts → runtime/error-recovery.test.d.ts} +0 -0
- /package/dist/{prompts/long-search.test.d.ts → runtime/errors.test.d.ts} +0 -0
- /package/dist/{prompts/protocol-simple.test.d.ts → runtime/execution-activity.test.d.ts} +0 -0
- /package/dist/{prompts/protocol.test.d.ts → runtime/execution-diagnostics.test.d.ts} +0 -0
- /package/dist/{prompts/sections.test.d.ts → runtime/execution-report.test.d.ts} +0 -0
- /package/dist/runtime/{interpret-result.test.d.ts → execution-safety.test.d.ts} +0 -0
- /package/dist/{transcript.test.d.ts → runtime/exit-control-flow.test.d.ts} +0 -0
- /package/dist/{truncator.test.d.ts → runtime/fixtures/long-search.test.d.ts} +0 -0
|
@@ -0,0 +1,2061 @@
|
|
|
1
|
+
import { g as baseIsEqual, o as init, r as getErrorMessage, u as stripInvalidIdentifiers } from "./utils-BOFzb8Ok.js";
|
|
2
|
+
import { A as MemoryValueError, B as UnknownExitError, F as SessionStateError, H as isCriticalError, I as TokenOverflowError, L as ToolExecutionError, M as NativeProtocolError, N as ObjectPropertyError, O as LoopExceededError, U as isLLMzError, V as UnknownToolError, a as cleanStackTrace, b as InvalidConfigurationError, f as DeliveryError, g as HostOperationError, h as HookError, j as MissingChatResponseError, k as MemoryCapacityError, l as CognitiveError, m as ExitInputError, n as ThinkSignal, o as AssignmentError, p as ExecutionAbortedError, r as VMSignal, s as CodeExecutionError, t as Signals, u as CompactionError, v as InvalidCodeError, z as UnknownComponentError } from "./errors-Crk5P8jo.js";
|
|
3
|
+
import { a as isAnyComponent } from "./component-DncqP4fB.js";
|
|
4
|
+
import { n as parseSchemaSync } from "./schema-GE4ISPCR.js";
|
|
5
|
+
import { i as unwrapTruncated, n as isTruncated, t as DEFAULT_TOOL_RESULT_MAX_TOKENS } from "./truncate-BEKbdo3t.js";
|
|
6
|
+
import { a as cloneMemoryValue, f as createInspector, g as resolveInspectionBudget, h as limitInspectionOutput, p as snapshotInspectionValue } from "./quickjs-variant-CtuGagsb.js";
|
|
7
|
+
import { n as schemaToTypeScript } from "./typings-BEVDvtuk.js";
|
|
8
|
+
import { a as Context, d as prepareAutoCompaction, f as countNativeRequestTokens, i as SuccessExecutionResult, n as ErrorExecutionResult, p as resolveTokenBudget, s as ListenExit, t as _CustomModelClient, u as stableJSON } from "./custom-client-C-WXvLD9.js";
|
|
9
|
+
import { a as validateNativeToolCalls, i as getRunJavaScriptTool, r as WORKER_RESPONSE_INSTRUCTION } from "./native-n_718Z-T.js";
|
|
10
|
+
import { a as VM_TERMINATION, i as VM_PROGRAM_COMPLETE, n as VM_CALL_SITE, o as compile, r as VM_ON_ERROR, runAsyncFunction, t as withMissingMember } from "./vm-C7SfutHn.js";
|
|
11
|
+
import { z } from "@bpinternal/zui";
|
|
12
|
+
import { ulid } from "ulid";
|
|
13
|
+
import { Cognitive } from "@botpress/cognitive";
|
|
14
|
+
import { Client } from "@botpress/client";
|
|
15
|
+
import ms from "ms";
|
|
16
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/isEqual.js
|
|
17
|
+
/**
|
|
18
|
+
* Performs a deep comparison between two values to determine if they are
|
|
19
|
+
* equivalent.
|
|
20
|
+
*
|
|
21
|
+
* **Note:** This method supports comparing arrays, array buffers, booleans,
|
|
22
|
+
* date objects, error objects, maps, numbers, `Object` objects, regexes,
|
|
23
|
+
* sets, strings, symbols, and typed arrays. `Object` objects are compared
|
|
24
|
+
* by their own, not inherited, enumerable properties. Functions and DOM
|
|
25
|
+
* nodes are compared by strict equality, i.e. `===`.
|
|
26
|
+
*
|
|
27
|
+
* @static
|
|
28
|
+
* @memberOf _
|
|
29
|
+
* @since 0.1.0
|
|
30
|
+
* @category Lang
|
|
31
|
+
* @param {*} value The value to compare.
|
|
32
|
+
* @param {*} other The other value to compare.
|
|
33
|
+
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
|
|
34
|
+
* @example
|
|
35
|
+
*
|
|
36
|
+
* var object = { 'a': 1 };
|
|
37
|
+
* var other = { 'a': 1 };
|
|
38
|
+
*
|
|
39
|
+
* _.isEqual(object, other);
|
|
40
|
+
* // => true
|
|
41
|
+
*
|
|
42
|
+
* object === other;
|
|
43
|
+
* // => false
|
|
44
|
+
*/
|
|
45
|
+
function isEqual(value, other) {
|
|
46
|
+
return baseIsEqual(value, other);
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/abort-signal.ts
|
|
50
|
+
/**
|
|
51
|
+
* Creates a new AbortController that aborts when any of the provided signals abort.
|
|
52
|
+
* This is useful for combining multiple abort conditions (e.g., user cancellation, timeout, parent operation abort).
|
|
53
|
+
*
|
|
54
|
+
* @param signals - Array of AbortSignals to listen to. Undefined/null signals are ignored.
|
|
55
|
+
* @returns A new AbortController that will abort if any input signal aborts
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const userController = new AbortController()
|
|
60
|
+
* const timeoutController = new AbortController()
|
|
61
|
+
*
|
|
62
|
+
* // Create a joined controller that aborts if either signal aborts
|
|
63
|
+
* const joinedController = createJoinedAbortController([
|
|
64
|
+
* userController.signal,
|
|
65
|
+
* timeoutController.signal
|
|
66
|
+
* ])
|
|
67
|
+
*
|
|
68
|
+
* // Use the joined signal in operations
|
|
69
|
+
* await fetch('/api/data', { signal: joinedController.signal })
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
function createJoinedAbortController(signals) {
|
|
73
|
+
const controller = new AbortController();
|
|
74
|
+
const validSignals = signals.filter((signal) => signal != null);
|
|
75
|
+
if (validSignals.length === 0) return controller;
|
|
76
|
+
for (const signal of validSignals) if (signal.aborted) {
|
|
77
|
+
controller.abort(signal.reason);
|
|
78
|
+
return controller;
|
|
79
|
+
}
|
|
80
|
+
const abortListeners = [];
|
|
81
|
+
for (const signal of validSignals) {
|
|
82
|
+
const listener = () => {
|
|
83
|
+
controller.abort(signal.reason);
|
|
84
|
+
cleanup();
|
|
85
|
+
};
|
|
86
|
+
signal.addEventListener("abort", listener);
|
|
87
|
+
abortListeners.push(() => signal.removeEventListener("abort", listener));
|
|
88
|
+
}
|
|
89
|
+
const cleanup = () => {
|
|
90
|
+
abortListeners.forEach((removeListener) => removeListener());
|
|
91
|
+
};
|
|
92
|
+
controller.signal.addEventListener("abort", cleanup, { once: true });
|
|
93
|
+
return controller;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
//#region src/errors/hooks.ts
|
|
97
|
+
/** Hooks may reject an iteration to request a correction; explicit critical errors still stop execution. */
|
|
98
|
+
async function callHook(callback) {
|
|
99
|
+
try {
|
|
100
|
+
return await callback();
|
|
101
|
+
} catch (cause) {
|
|
102
|
+
if (isLLMzError(cause) || VMSignal.is(cause)) throw cause;
|
|
103
|
+
throw new HookError(cause instanceof Error ? cause.message : String(cause), { cause });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/runtime/execution-activity.ts
|
|
108
|
+
const MAX_ENTRIES = 20;
|
|
109
|
+
const PAYLOAD_PREVIEW_TOKENS = 80;
|
|
110
|
+
const ERROR_PREVIEW_TOKENS = 60;
|
|
111
|
+
const NAME_PREVIEW_TOKENS = 16;
|
|
112
|
+
/** Collect recorded operations, excluding ordinary assistant text delivery. */
|
|
113
|
+
function getExecutionActivity(iteration) {
|
|
114
|
+
return {
|
|
115
|
+
calls: iteration.traces.filter((trace) => trace.type === "tool_call"),
|
|
116
|
+
deliveries: iteration.traces.filter((trace) => trace.type === "message_delivery" && !!trace.message_id)
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function renderToolCalls(activity, includeRecoveryValues = false, inspector = createInspector(), identity = {}) {
|
|
120
|
+
if (!activity.calls.length) return;
|
|
121
|
+
const lines = activity.calls.slice(0, MAX_ENTRIES).map((call) => {
|
|
122
|
+
const name = call.object ? `${call.object}.${call.tool_name}` : call.tool_name;
|
|
123
|
+
const outcome = getToolOutcome(call);
|
|
124
|
+
const detailsIdentity = {
|
|
125
|
+
...identity,
|
|
126
|
+
tool: call.tool_name,
|
|
127
|
+
object: call.object
|
|
128
|
+
};
|
|
129
|
+
const input = call.input === void 0 ? "" : inspector(call.input, {
|
|
130
|
+
purpose: "tool-input",
|
|
131
|
+
maxTokens: PAYLOAD_PREVIEW_TOKENS,
|
|
132
|
+
compact: true,
|
|
133
|
+
identity: detailsIdentity
|
|
134
|
+
});
|
|
135
|
+
const details = [`- ${inspector(name, {
|
|
136
|
+
purpose: "name",
|
|
137
|
+
maxTokens: NAME_PREVIEW_TOKENS,
|
|
138
|
+
identity: detailsIdentity
|
|
139
|
+
})}(${input}): ${outcome}`];
|
|
140
|
+
if (outcome === "interrupted") {
|
|
141
|
+
const reason = getInterruption(call).reason;
|
|
142
|
+
details.push(`pending; ${errorPreview(reason, inspector, detailsIdentity)}`);
|
|
143
|
+
} else if (!call.success) details.push(`error: ${errorPreview(call.error, inspector, detailsIdentity)}`);
|
|
144
|
+
else if (includeRecoveryValues) details.push(`returned ${inspector(call.output, {
|
|
145
|
+
purpose: "tool-output",
|
|
146
|
+
maxTokens: PAYLOAD_PREVIEW_TOKENS,
|
|
147
|
+
compact: true,
|
|
148
|
+
identity: detailsIdentity
|
|
149
|
+
})}`);
|
|
150
|
+
return details.join("; ");
|
|
151
|
+
});
|
|
152
|
+
if (activity.calls.length > lines.length) lines.push(`- ${activity.calls.length - lines.length} additional calls are recorded in the execution traces.`);
|
|
153
|
+
return `Tools called\n${lines.join("\n")}`;
|
|
154
|
+
}
|
|
155
|
+
function renderMessageDeliveries({ deliveries }, cancelled = false, inspector = createInspector(), identity = {}) {
|
|
156
|
+
if (!deliveries.length) return;
|
|
157
|
+
const lines = deliveries.slice(0, MAX_ENTRIES).map((delivery) => {
|
|
158
|
+
const outcome = delivery.success === true ? "delivered" : "uncertain";
|
|
159
|
+
const details = [`- ${messagePreview(delivery.value, inspector, identity)}: ${outcome}`];
|
|
160
|
+
if (delivery.error !== void 0) details.push(`error: ${errorPreview(delivery.error, inspector, identity)}`);
|
|
161
|
+
return details.join("; ");
|
|
162
|
+
});
|
|
163
|
+
if (deliveries.length > lines.length) lines.push(`- ${deliveries.length - lines.length} additional deliveries are recorded in the execution traces.`);
|
|
164
|
+
if (deliveries.some((delivery) => delivery.success === false)) lines.push("Messages queued after the failed delivery were skipped.");
|
|
165
|
+
else if (cancelled) lines.push("Messages still queued when execution was cancelled were skipped.");
|
|
166
|
+
return `Messages sent\n${lines.join("\n")}`;
|
|
167
|
+
}
|
|
168
|
+
function getInterruption(call) {
|
|
169
|
+
if ("output" in call && ThinkSignal.is(call.output)) return call.output;
|
|
170
|
+
if (!call.success) {
|
|
171
|
+
const error = Signals.maybeDeserializeError(call.error);
|
|
172
|
+
if (ThinkSignal.is(error)) return error;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function getToolOutcome(call) {
|
|
176
|
+
if (getInterruption(call)) return "interrupted";
|
|
177
|
+
return call.success ? "succeeded" : "failed";
|
|
178
|
+
}
|
|
179
|
+
function messagePreview(value, inspector, identity) {
|
|
180
|
+
const component = isAnyComponent(value) ? value : void 0;
|
|
181
|
+
const detailsIdentity = component ? {
|
|
182
|
+
...identity,
|
|
183
|
+
component: component.name
|
|
184
|
+
} : identity;
|
|
185
|
+
const body = inspector(component ? component.props : value, {
|
|
186
|
+
purpose: "message",
|
|
187
|
+
maxTokens: PAYLOAD_PREVIEW_TOKENS,
|
|
188
|
+
compact: true,
|
|
189
|
+
identity: detailsIdentity
|
|
190
|
+
});
|
|
191
|
+
if (!component) return body;
|
|
192
|
+
return `${inspector(component.name, {
|
|
193
|
+
purpose: "name",
|
|
194
|
+
maxTokens: NAME_PREVIEW_TOKENS,
|
|
195
|
+
identity: detailsIdentity
|
|
196
|
+
})} ${body}`;
|
|
197
|
+
}
|
|
198
|
+
function errorPreview(value, inspector, identity) {
|
|
199
|
+
const error = Signals.maybeDeserializeError(value);
|
|
200
|
+
return inspector((error instanceof Error ? error.message : String(error ?? "Unknown error")).replace(/\s+/g, " ").trim(), {
|
|
201
|
+
purpose: "error",
|
|
202
|
+
maxTokens: ERROR_PREVIEW_TOKENS,
|
|
203
|
+
compact: true,
|
|
204
|
+
identity
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
//#endregion
|
|
208
|
+
//#region src/runtime/execution-diagnostics.ts
|
|
209
|
+
/** XML-style boundaries keep diagnostic text separate from recovery instructions. */
|
|
210
|
+
function reportSection(name, content, maxTokens = 2e3, options = {}) {
|
|
211
|
+
return `<${name}>\n${options.heading ? `${options.heading}\n` : ""}${limitInspectionOutput(content, maxTokens, false, options.preserve ?? "top")}\n</${name}>`;
|
|
212
|
+
}
|
|
213
|
+
/** Show the specific failure and guest source, never the host's implementation stack. */
|
|
214
|
+
function renderExecutionDiagnostics(error, message, inspector, identity) {
|
|
215
|
+
const cause = CodeExecutionError.is(error) ? error.cause : error;
|
|
216
|
+
const candidate = isLLMzError(cause) ? cause : error;
|
|
217
|
+
const failure = isLLMzError(candidate) ? candidate : void 0;
|
|
218
|
+
const sections = [reportSection("error", inspector([failure ? `Code: ${failure.code}` : void 0, (failure === null || failure === void 0 ? void 0 : failure.message) ?? message].filter(Boolean).join("\n"), {
|
|
219
|
+
purpose: "error",
|
|
220
|
+
maxTokens: 1e3,
|
|
221
|
+
identity
|
|
222
|
+
}), 1e3)];
|
|
223
|
+
if (CodeExecutionError.is(error) && error.stacktrace) sections.push(renderSourceTrace(error.stacktrace, inspector, identity));
|
|
224
|
+
else if (InvalidCodeError.is(error) && error.source) sections.push(reportSection("invalid_code", inspector(error.source, {
|
|
225
|
+
purpose: "code",
|
|
226
|
+
maxTokens: 800,
|
|
227
|
+
identity
|
|
228
|
+
}), 800));
|
|
229
|
+
return sections;
|
|
230
|
+
}
|
|
231
|
+
/** Keep failure sites visible even when they are near the end of a long program. */
|
|
232
|
+
function renderSourceTrace(stack, inspector, identity) {
|
|
233
|
+
const lines = stack.split("\n");
|
|
234
|
+
const marked = lines.flatMap((line, index) => /^> \d+ \|/.test(line) ? [index] : []);
|
|
235
|
+
const selected = /* @__PURE__ */ new Set();
|
|
236
|
+
for (const index of marked.slice(0, 8)) for (let nearby = Math.max(0, index - 2); nearby <= Math.min(lines.length - 1, index + 3); nearby++) selected.add(nearby);
|
|
237
|
+
const excerpt = [];
|
|
238
|
+
let previous = -1;
|
|
239
|
+
for (const index of [...selected].sort((a, b) => a - b)) {
|
|
240
|
+
if (index > previous + 1) excerpt.push("... omitted source ...");
|
|
241
|
+
excerpt.push(lines[index]);
|
|
242
|
+
previous = index;
|
|
243
|
+
}
|
|
244
|
+
if (selected.size && previous < lines.length - 1) excerpt.push("... omitted source ...");
|
|
245
|
+
return reportSection("stack_trace", inspector(selected.size ? excerpt.join("\n") : stack, {
|
|
246
|
+
purpose: "code",
|
|
247
|
+
maxTokens: 1e3,
|
|
248
|
+
identity
|
|
249
|
+
}), 1e3);
|
|
250
|
+
}
|
|
251
|
+
//#endregion
|
|
252
|
+
//#region src/runtime/forced-inspection.ts
|
|
253
|
+
/** Keep attribution and content together, using the same display budgets as inspect(). */
|
|
254
|
+
function renderForcedInspection(inspections, inspector, identity, maxTokens, policies) {
|
|
255
|
+
return [
|
|
256
|
+
"<forced_inspection>",
|
|
257
|
+
"Forced inspection: the tools listed below completed successfully and requested review of their results.",
|
|
258
|
+
"This is the equivalent of an inspect() call. Do not repeat these tool calls; use the results below and retained variables.",
|
|
259
|
+
"No exit was applied. Review the evidence before continuing or completing the task.",
|
|
260
|
+
"",
|
|
261
|
+
"Tools requesting inspection (lines refer to the executed JavaScript):",
|
|
262
|
+
...inspections.map((entry) => {
|
|
263
|
+
const entryIdentity = {
|
|
264
|
+
...identity,
|
|
265
|
+
tool: entry.tool
|
|
266
|
+
};
|
|
267
|
+
const name = inspector(entry.tool, {
|
|
268
|
+
purpose: "name",
|
|
269
|
+
maxTokens: 80,
|
|
270
|
+
identity: entryIdentity
|
|
271
|
+
});
|
|
272
|
+
const reason = inspector(entry.reason, {
|
|
273
|
+
purpose: "error",
|
|
274
|
+
maxTokens: 1e3,
|
|
275
|
+
identity: entryIdentity
|
|
276
|
+
});
|
|
277
|
+
const budget = resolveInspectionBudget(entry.value, {
|
|
278
|
+
tokens: maxTokens,
|
|
279
|
+
policies
|
|
280
|
+
});
|
|
281
|
+
const result = inspector(entry.value, {
|
|
282
|
+
purpose: "result",
|
|
283
|
+
maxTokens,
|
|
284
|
+
policies,
|
|
285
|
+
identity: entryIdentity
|
|
286
|
+
});
|
|
287
|
+
return [
|
|
288
|
+
`<tool name="${name}" line="${entry.line ?? "unknown"}">`,
|
|
289
|
+
`<reason>${reason}</reason>`,
|
|
290
|
+
reportSection("result", result, budget.tokens, { preserve: budget.preserve }),
|
|
291
|
+
"</tool>"
|
|
292
|
+
].join("\n");
|
|
293
|
+
}),
|
|
294
|
+
"</forced_inspection>"
|
|
295
|
+
].join("\n");
|
|
296
|
+
}
|
|
297
|
+
//#endregion
|
|
298
|
+
//#region src/runtime/execution-report.ts
|
|
299
|
+
const MAX_REPORTED_CHANGES = 40;
|
|
300
|
+
const MAX_OVERRIDE_SOURCE_LENGTH = 3e3;
|
|
301
|
+
/** Format one settled outcome; execution is responsible for deciding what happened. */
|
|
302
|
+
function renderExecutionReport({ outcome, activity, memory, source, requiresExit = false, iteration, identity = { iteration }, inspector = createInspector(), maxTokens = DEFAULT_TOOL_RESULT_MAX_TOKENS, policies }) {
|
|
303
|
+
var _outcome$forcedInspec, _outcome$forcedInspec2;
|
|
304
|
+
const detail = (value) => inspector(value, {
|
|
305
|
+
purpose: "error",
|
|
306
|
+
maxTokens: 1e3,
|
|
307
|
+
identity
|
|
308
|
+
});
|
|
309
|
+
const name = (value) => inspector(value, {
|
|
310
|
+
purpose: "name",
|
|
311
|
+
maxTokens: 40,
|
|
312
|
+
identity
|
|
313
|
+
});
|
|
314
|
+
const resultSection = (tag, heading, value) => {
|
|
315
|
+
const budget = resolveInspectionBudget(value, {
|
|
316
|
+
tokens: maxTokens,
|
|
317
|
+
policies
|
|
318
|
+
});
|
|
319
|
+
return reportSection(tag, inspector(value, {
|
|
320
|
+
purpose: "result",
|
|
321
|
+
maxTokens,
|
|
322
|
+
policies,
|
|
323
|
+
identity
|
|
324
|
+
}), budget.tokens, {
|
|
325
|
+
heading,
|
|
326
|
+
preserve: budget.preserve
|
|
327
|
+
});
|
|
328
|
+
};
|
|
329
|
+
const sections = [renderStatus(outcome, memory)];
|
|
330
|
+
if (outcome.type === "inspect" && ((_outcome$forcedInspec = outcome.forcedInspections) === null || _outcome$forcedInspec === void 0 ? void 0 : _outcome$forcedInspec.length)) {
|
|
331
|
+
sections.push(renderForcedInspection(outcome.forcedInspections, inspector, identity, maxTokens, policies));
|
|
332
|
+
if (outcome.downstreamError) {
|
|
333
|
+
sections.push(...renderExecutionDiagnostics(outcome.downstreamError, getErrorMessage(outcome.downstreamError), inspector, identity));
|
|
334
|
+
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."));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
if (outcome.type === "error") {
|
|
338
|
+
sections.push(...renderExecutionDiagnostics(outcome.error, outcome.message, inspector, identity));
|
|
339
|
+
sections.push(reportSection("recovery", [
|
|
340
|
+
outcome.exitName !== void 0 ? `Completion through ${outcome.exitName} failed; no exit was applied.` : "Fix the error before continuing.",
|
|
341
|
+
"The iteration did not complete successfully. Review the error and recorded outcomes before continuing.",
|
|
342
|
+
"Use retained variables and acknowledged results. Do not repeat completed actions or messages.",
|
|
343
|
+
"Check uncertain external outcomes before retrying an operation."
|
|
344
|
+
].join("\n")));
|
|
345
|
+
} else if (outcome.type === "interrupted") {
|
|
346
|
+
sections.push(reportSection("interruption", detail(outcome.message ?? "The response stream failed after JavaScript started.")));
|
|
347
|
+
if (outcome.stacktrace && /^(?:> | {2})?\d+ \|/m.test(outcome.stacktrace)) sections.push(renderSourceTrace(outcome.stacktrace, inspector, identity));
|
|
348
|
+
sections.push(reportSection("recovery", outcome.reason === "thinking" ? "Execution paused at the thinking request. Remaining statements did not run. Review the context below and continue from retained variables and acknowledged results; do not repeat completed actions or messages." : "The terminal decision was not applied. Earlier actions may have completed. Inspect the recorded outcomes before continuing; do not repeat acknowledged actions or messages."));
|
|
349
|
+
} else if (outcome.type === "cancelled") sections.push(reportSection("cancellation", detail(outcome.message)));
|
|
350
|
+
const override = renderExecutionOverride(source === null || source === void 0 ? void 0 : source.executed, source === null || source === void 0 ? void 0 : source.requested, inspector, identity);
|
|
351
|
+
if (override) {
|
|
352
|
+
sections.push(reportSection("execution_override", override));
|
|
353
|
+
if (outcome.type === "inspect" && requiresExit) sections.push(reportSection("recovery", "No exit was applied. The executed program returned an inspection result; use that result for any required completion. Do not call the originally requested business tools merely to compensate for the hook replacement."));
|
|
354
|
+
}
|
|
355
|
+
if (outcome.type === "error" && isReferenceError(outcome.error)) sections.push(reportSection("reference_recovery", "REFERENCE RECOVERY\nCheck the Memory overview and JavaScript API for the missing name. Declare new variables with const or let; assignment alone never creates a variable. If a preceding business call already returned, reuse its acknowledged result rather than repeating the call. Do not invent values or functions for unknown names."));
|
|
356
|
+
const completed = outcome.type === "inspect" || outcome.type === "exit";
|
|
357
|
+
const calls = renderToolCalls(activity, !!override || !completed, inspector, identity);
|
|
358
|
+
const deliveries = renderMessageDeliveries(activity, outcome.type === "cancelled", inspector, identity);
|
|
359
|
+
if (calls) sections.push(reportSection("tool_calls", calls, 4e3));
|
|
360
|
+
if (deliveries) sections.push(reportSection("messages", deliveries, 4e3));
|
|
361
|
+
const changes = [renderChanges("Created", memory.created, name), renderChanges("Updated", memory.updated, name)].filter(Boolean).join("\n");
|
|
362
|
+
if (changes) sections.push(reportSection("memory_changes", `Memory changes\n${changes}`));
|
|
363
|
+
if (memory.unavailable.length) {
|
|
364
|
+
const failures = memory.unavailable.slice(0, MAX_REPORTED_CHANGES);
|
|
365
|
+
const entries = failures.map((failure) => `- ${name(failure.name)}: ${detail(failure.reason)}`);
|
|
366
|
+
if (memory.unavailable.length > failures.length) entries.push(`- ${memory.unavailable.length - failures.length} additional values could not be retained.`);
|
|
367
|
+
sections.push(reportSection("memory_errors", `Memory errors\n${entries.join("\n")}`));
|
|
368
|
+
}
|
|
369
|
+
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") {
|
|
370
|
+
const heading = outcome.explicit ? "inspect() result" : "Result";
|
|
371
|
+
sections.push(outcome.available ? resultSection("result", heading, outcome.value) : reportSection("result", "Unavailable; see memory errors above.", maxTokens, { heading }));
|
|
372
|
+
} else if (outcome.type === "exit") sections.push(resultSection("completion", `Completion\nExit "${outcome.name}" completed.`, outcome.value === void 0 ? "" : outcome.value));
|
|
373
|
+
else {
|
|
374
|
+
sections.push(reportSection("result", "Not produced; execution did not complete an inspection.", maxTokens, { heading: "inspect() result" }));
|
|
375
|
+
if (outcome.type === "interrupted" && outcome.reason === "thinking" && outcome.context !== void 0) sections.push(resultSection("interruption_context", "Interruption context", outcome.context));
|
|
376
|
+
}
|
|
377
|
+
return sections.join("\n\n");
|
|
378
|
+
}
|
|
379
|
+
function renderStatus(outcome, memory) {
|
|
380
|
+
switch (outcome.type) {
|
|
381
|
+
case "cancelled": return "run_javascript: cancelled";
|
|
382
|
+
case "interrupted": return outcome.reason === "thinking" ? "run_javascript: paused" : "run_javascript: interrupted";
|
|
383
|
+
case "error": return "run_javascript: failed";
|
|
384
|
+
case "inspect":
|
|
385
|
+
case "exit": return memory.unavailable.length ? "run_javascript: completed with memory errors\nJavaScript ran successfully, but some values could not be retained." : "run_javascript: succeeded";
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
function isReferenceError(value) {
|
|
389
|
+
const error = Signals.maybeDeserializeError(value);
|
|
390
|
+
return UnknownToolError.is(error) || UnknownToolError.is(error === null || error === void 0 ? void 0 : error.cause) || (CodeExecutionError.is(error) ? error.originalErrorName : error === null || error === void 0 ? void 0 : error.name) === "ReferenceError";
|
|
391
|
+
}
|
|
392
|
+
/** Keep the requested assistant call intact while disclosing the source the host actually ran. */
|
|
393
|
+
function renderExecutionOverride(executedCode, requestedCode, inspector = createInspector(), identity) {
|
|
394
|
+
if (executedCode === void 0 || requestedCode === void 0 || executedCode === requestedCode) return;
|
|
395
|
+
const source = executedCode.slice(0, MAX_OVERRIDE_SOURCE_LENGTH);
|
|
396
|
+
return [
|
|
397
|
+
"EXECUTION OVERRIDE",
|
|
398
|
+
"The host onBeforeExecution hook replaced the requested JavaScript. The original assistant tool call records the requested program. Replacement source is shown below; the outcomes report what actually executed.",
|
|
399
|
+
"Continue from the actual results and retained variables. Do not replay the requested program to compensate for this intentional replacement.",
|
|
400
|
+
"Replacement JavaScript (bounded preview):",
|
|
401
|
+
inspector(source, {
|
|
402
|
+
purpose: "code",
|
|
403
|
+
maxTokens: 800,
|
|
404
|
+
identity
|
|
405
|
+
}),
|
|
406
|
+
...source.length < executedCode.length ? ["The replacement source preview was truncated."] : []
|
|
407
|
+
].join("\n");
|
|
408
|
+
}
|
|
409
|
+
function renderChanges(label, changes, name) {
|
|
410
|
+
if (!changes.length) return;
|
|
411
|
+
const names = changes.slice(0, MAX_REPORTED_CHANGES).map((change) => name(change.name));
|
|
412
|
+
const lines = [`${label}: ${names.join(", ")}`];
|
|
413
|
+
if (changes.length > names.length) lines.push(`${changes.length - names.length} more changes are retained in memory.`);
|
|
414
|
+
return lines.join("\n");
|
|
415
|
+
}
|
|
416
|
+
//#endregion
|
|
417
|
+
//#region src/runtime/generate.ts
|
|
418
|
+
const STREAM_IDLE_TIMEOUT = 18e4;
|
|
419
|
+
const STATIC_TOKEN_PARTS = [
|
|
420
|
+
"instructions",
|
|
421
|
+
"tools",
|
|
422
|
+
"protocol"
|
|
423
|
+
];
|
|
424
|
+
const staticTokenEstimates = /* @__PURE__ */ new WeakMap();
|
|
425
|
+
function assertSuccessfulGeneration(metadata) {
|
|
426
|
+
if (!metadata || metadata.provider === "unknown") throw new CognitiveError("LLM generation failed: missing successful provider metadata");
|
|
427
|
+
if (metadata.stopReason === "max_tokens") {
|
|
428
|
+
var _metadata$usage;
|
|
429
|
+
throw new TokenOverflowError("LLM generation did not complete: stopReason=max_tokens", (_metadata$usage = metadata.usage) === null || _metadata$usage === void 0 ? void 0 : _metadata$usage.outputTokens, void 0, "output");
|
|
430
|
+
}
|
|
431
|
+
if (metadata.stopReason === "content_filter" || metadata.stopReason === "other") throw new CognitiveError(`LLM generation did not complete: stopReason=${metadata.stopReason}`);
|
|
432
|
+
}
|
|
433
|
+
function measureNativeContextTokens(iteration, messages, tools, total) {
|
|
434
|
+
let estimates = staticTokenEstimates.get(iteration);
|
|
435
|
+
if (!estimates) {
|
|
436
|
+
var _iteration$tokens;
|
|
437
|
+
const initial = (_iteration$tokens = iteration.tokens) === null || _iteration$tokens === void 0 ? void 0 : _iteration$tokens.context;
|
|
438
|
+
estimates = {
|
|
439
|
+
instructions: (initial === null || initial === void 0 ? void 0 : initial.instructions) ?? 0,
|
|
440
|
+
tools: (initial === null || initial === void 0 ? void 0 : initial.tools) ?? 0,
|
|
441
|
+
protocol: (initial === null || initial === void 0 ? void 0 : initial.protocol) ?? 0
|
|
442
|
+
};
|
|
443
|
+
staticTokenEstimates.set(iteration, estimates);
|
|
444
|
+
}
|
|
445
|
+
const history = messages.filter((message) => message.role !== "system");
|
|
446
|
+
const emptyRequestTokens = countNativeRequestTokens([], []);
|
|
447
|
+
const requestWithToolsTokens = countNativeRequestTokens([], tools);
|
|
448
|
+
const requestWithHistoryTokens = countNativeRequestTokens(history, tools);
|
|
449
|
+
const structuralTokens = Math.min(total, emptyRequestTokens);
|
|
450
|
+
const schemaTokens = Math.min(total - structuralTokens, Math.max(0, requestWithToolsTokens - emptyRequestTokens));
|
|
451
|
+
const iterations = Math.min(total - structuralTokens - schemaTokens, Math.max(0, requestWithHistoryTokens - requestWithToolsTokens));
|
|
452
|
+
const systemBudget = total - structuralTokens - schemaTokens - iterations;
|
|
453
|
+
const estimatedSystemParts = STATIC_TOKEN_PARTS.reduce((sum, part) => sum + estimates[part], 0);
|
|
454
|
+
const scale = estimatedSystemParts > 0 ? Math.min(1, systemBudget / estimatedSystemParts) : 0;
|
|
455
|
+
const instructions = Math.floor(estimates.instructions * scale);
|
|
456
|
+
const toolsTokens = Math.floor(estimates.tools * scale) + schemaTokens;
|
|
457
|
+
const protocol = Math.floor(estimates.protocol * scale);
|
|
458
|
+
return {
|
|
459
|
+
total,
|
|
460
|
+
framework: total - instructions - toolsTokens - protocol - iterations,
|
|
461
|
+
instructions,
|
|
462
|
+
tools: toolsTokens,
|
|
463
|
+
protocol,
|
|
464
|
+
iterations
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
/** A client may ignore its AbortSignal; cancellation must still release LLMz. */
|
|
468
|
+
function abortable(operation, signal) {
|
|
469
|
+
return new Promise((resolve, reject) => {
|
|
470
|
+
const aborted = () => reject(signal.reason ?? /* @__PURE__ */ new Error("Generation aborted"));
|
|
471
|
+
operation.then(resolve, reject).finally(() => signal.removeEventListener("abort", aborted));
|
|
472
|
+
if (signal.aborted) {
|
|
473
|
+
aborted();
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
function validateResponse(output, calls, assistant) {
|
|
480
|
+
if (typeof output !== "string") throw new CognitiveError("Provider returned invalid assistant output");
|
|
481
|
+
if (!Array.isArray(calls)) throw new CognitiveError("Provider returned invalid native tool calls");
|
|
482
|
+
const ids = /* @__PURE__ */ new Set();
|
|
483
|
+
for (const call of calls) {
|
|
484
|
+
if (!call || typeof call.id !== "string" || !call.id || ids.has(call.id)) throw new CognitiveError("Provider returned missing or duplicate native call IDs");
|
|
485
|
+
if (typeof call.name !== "string" || !call.name || !call.input || typeof call.input !== "object" || Array.isArray(call.input)) throw new CognitiveError("Provider returned invalid native tool arguments");
|
|
486
|
+
ids.add(call.id);
|
|
487
|
+
}
|
|
488
|
+
if (assistant) {
|
|
489
|
+
var _assistant$content;
|
|
490
|
+
if (assistant.role !== "assistant") throw new CognitiveError("Provider continuation must be an assistant message");
|
|
491
|
+
const normalized = (assistant.toolCalls ?? []).map((call) => ({
|
|
492
|
+
id: call.id,
|
|
493
|
+
name: call.function.name,
|
|
494
|
+
input: call.function.arguments ?? {}
|
|
495
|
+
}));
|
|
496
|
+
if (stableJSON(normalized) !== stableJSON(calls)) throw new CognitiveError("Provider assistant message and normalized tool calls disagree");
|
|
497
|
+
if ((typeof assistant.content === "string" ? assistant.content : ((_assistant$content = assistant.content) === null || _assistant$content === void 0 ? void 0 : _assistant$content.filter((part) => part.type === "text").map((part) => part.text ?? "").join("")) ?? "") !== output) throw new CognitiveError("Provider assistant message and visible output disagree");
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
async function prepareNativeRequest({ iteration, ctx, cognitive, controller, metadata, onBeforeRequest }) {
|
|
501
|
+
const modelRefs = Array.isArray(iteration.model) ? iteration.model : [iteration.model];
|
|
502
|
+
if (!modelRefs.length) throw new CognitiveError("At least one model is required.");
|
|
503
|
+
const models = await Promise.all(modelRefs.map(async (ref) => {
|
|
504
|
+
try {
|
|
505
|
+
return await abortable(cognitive.getModelDetails(ref), controller.signal);
|
|
506
|
+
} catch (error) {
|
|
507
|
+
throw new CognitiveError(`Failed to fetch model details for ${ref}: ${getErrorMessage(error)}`, { cause: error });
|
|
508
|
+
}
|
|
509
|
+
}));
|
|
510
|
+
const model = models[0];
|
|
511
|
+
const { limit, output: reserve } = resolveTokenBudget(models, ctx.maxTokens);
|
|
512
|
+
const tools = [getRunJavaScriptTool(!!ctx.chat)];
|
|
513
|
+
const system = [iteration.systemMessage];
|
|
514
|
+
const budgetInstruction = getBudgetInstruction(ctx, iteration);
|
|
515
|
+
const budget = `\n\nExecution budget: response ${ctx.iterations.length} of ${ctx.loop}. ${budgetInstruction}`;
|
|
516
|
+
const buildMessages = (retainedIds, summary) => {
|
|
517
|
+
const history = ctx.session.requestMessages({
|
|
518
|
+
inspector: ctx.inspector,
|
|
519
|
+
retainedIterationIds: retainedIds,
|
|
520
|
+
summary
|
|
521
|
+
});
|
|
522
|
+
const messages = [...structuredClone(system), ...history];
|
|
523
|
+
const last = messages.at(-1);
|
|
524
|
+
if (last) last.content = typeof last.content === "string" ? last.content + budget : [...last.content ?? [], {
|
|
525
|
+
type: "text",
|
|
526
|
+
text: budget.trim()
|
|
527
|
+
}];
|
|
528
|
+
return messages;
|
|
529
|
+
};
|
|
530
|
+
const compaction = await prepareAutoCompaction(ctx.session, {
|
|
531
|
+
client: cognitive,
|
|
532
|
+
model: iteration.model,
|
|
533
|
+
signal: controller.signal,
|
|
534
|
+
contextWindow: ctx.maxTokens,
|
|
535
|
+
iterationId: iteration.id,
|
|
536
|
+
inputLimit: limit - reserve,
|
|
537
|
+
metadata,
|
|
538
|
+
measure: (ids, summary) => countNativeRequestTokens(buildMessages(ids, summary), tools)
|
|
539
|
+
});
|
|
540
|
+
let messages = buildMessages((compaction === null || compaction === void 0 ? void 0 : compaction.retainedIterationIds) ?? ctx.session.retainedIterationIds, compaction === null || compaction === void 0 ? void 0 : compaction.summary);
|
|
541
|
+
let tokens = countNativeRequestTokens(messages, tools);
|
|
542
|
+
const override = await callHook(() => onBeforeRequest === null || onBeforeRequest === void 0 ? void 0 : onBeforeRequest({
|
|
543
|
+
messages: structuredClone(messages),
|
|
544
|
+
iteration,
|
|
545
|
+
controller
|
|
546
|
+
}));
|
|
547
|
+
if (override) {
|
|
548
|
+
messages = structuredClone(override.messages);
|
|
549
|
+
tokens = countNativeRequestTokens(messages, tools);
|
|
550
|
+
}
|
|
551
|
+
if (tokens > limit - reserve) throw new TokenOverflowError(override ? "The onBeforeRequest messages exceed the context budget. Shorten them or increase options.maxTokens." : "The native prompt exceeds the context budget. Compact session input or increase options.maxTokens.", tokens, limit - reserve);
|
|
552
|
+
controller.signal.throwIfAborted();
|
|
553
|
+
compaction === null || compaction === void 0 || compaction.commit();
|
|
554
|
+
if (iteration.tokens) {
|
|
555
|
+
iteration.tokens.limit = limit;
|
|
556
|
+
iteration.tokens.context = measureNativeContextTokens(iteration, messages, tools, tokens);
|
|
557
|
+
}
|
|
558
|
+
const hasAudio = messages.some((message) => Array.isArray(message.content) && message.content.some((part) => part.type === "audio"));
|
|
559
|
+
return {
|
|
560
|
+
input: {
|
|
561
|
+
model: iteration.model,
|
|
562
|
+
temperature: iteration.temperature,
|
|
563
|
+
responseFormat: "text",
|
|
564
|
+
reasoningEffort: iteration.reasoningEffort,
|
|
565
|
+
messages,
|
|
566
|
+
tools,
|
|
567
|
+
toolControl: {
|
|
568
|
+
mode: ctx.chat ? "auto" : "required",
|
|
569
|
+
parallel: false
|
|
570
|
+
},
|
|
571
|
+
maxTokens: reserve,
|
|
572
|
+
meta: metadata ? { metadata } : void 0,
|
|
573
|
+
options: {
|
|
574
|
+
...hasAudio ? { transcriptionModel: ctx.transcriptionModel ?? "fast" } : {},
|
|
575
|
+
...ctx.maxTimeToFirstToken ? { maxTimeToFirstToken: ctx.maxTimeToFirstToken } : {},
|
|
576
|
+
...ctx.midStreamFallback ? { midStreamFallback: true } : {}
|
|
577
|
+
}
|
|
578
|
+
},
|
|
579
|
+
model
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
function getBudgetInstruction(ctx, iteration) {
|
|
583
|
+
if (ctx.iterations.length < ctx.loop) return `Inspect business results that need interpretation before completing; never guess missing completion fields. Once the required facts are known, complete using retained values without repeating successful calls. ${ctx.chat ? "Component delivery needs no inspection. Keep lookups and retries silent unless progress updates were requested. If requested, include the update alongside the continuing call." : WORKER_RESPONSE_INSTRUCTION}`;
|
|
584
|
+
if (ctx.chat) return "This is the last response. Answer from inspected evidence with normal assistant text, or use JavaScript with an explicit return exit(\"listen\") or another registered named exit. Do not start work that needs another model response.";
|
|
585
|
+
if (!iteration.exits.length) return `${WORKER_RESPONSE_INSTRUCTION} This is the last response. Every JavaScript program must explicitly return inspect(value) with the available evidence. Do not start work that needs another model response.`;
|
|
586
|
+
return `${WORKER_RESPONSE_INSTRUCTION} This is the last response. Finish with return exit("NAME", payload) from run_javascript, using a registered name. Build the payload from inspected $return and retained variables; do not repeat successful lookups to reconstruct it. If the task is incomplete, report it honestly with an incomplete or error payload only when the exit schema permits it. Assistant prose and inspection returns do not complete a worker. Do not start work that requires another model response.`;
|
|
587
|
+
}
|
|
588
|
+
async function consumeNativeStream({ cognitive, input, controller, maxIdleTime, onChunk }) {
|
|
589
|
+
const streamController = createJoinedAbortController([controller.signal]);
|
|
590
|
+
const stream = cognitive.generateTextStream(input, { signal: streamController.signal });
|
|
591
|
+
let completed = false;
|
|
592
|
+
try {
|
|
593
|
+
while (true) {
|
|
594
|
+
controller.signal.throwIfAborted();
|
|
595
|
+
const chunk = await readNextStreamChunk(stream, streamController, maxIdleTime);
|
|
596
|
+
if (chunk.done) {
|
|
597
|
+
completed = true;
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
await onChunk(chunk.value);
|
|
601
|
+
}
|
|
602
|
+
} finally {
|
|
603
|
+
streamController.abort("LLM stream closed");
|
|
604
|
+
if (!completed) stream.return(void 0).catch(() => {});
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
async function readNextStreamChunk(stream, controller, maxIdleTime) {
|
|
608
|
+
let timer;
|
|
609
|
+
const timeout = new Promise((_resolve, reject) => {
|
|
610
|
+
timer = setTimeout(() => {
|
|
611
|
+
controller.abort("LLM stream stalled");
|
|
612
|
+
reject(new CognitiveError("LLM stream stalled"));
|
|
613
|
+
}, maxIdleTime);
|
|
614
|
+
});
|
|
615
|
+
try {
|
|
616
|
+
return await abortable(Promise.race([stream.next(), timeout]), controller.signal);
|
|
617
|
+
} finally {
|
|
618
|
+
clearTimeout(timer);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
async function generateCode({ iteration, ctx, cognitive, controller, metadata, onSendDelta, onToolCalls, onBeforeRequest }) {
|
|
622
|
+
var _toolCalls$find;
|
|
623
|
+
const startedAt = Date.now();
|
|
624
|
+
controller.signal.throwIfAborted();
|
|
625
|
+
const { input, model } = await prepareNativeRequest({
|
|
626
|
+
iteration,
|
|
627
|
+
ctx,
|
|
628
|
+
cognitive,
|
|
629
|
+
controller,
|
|
630
|
+
metadata,
|
|
631
|
+
onBeforeRequest
|
|
632
|
+
});
|
|
633
|
+
iteration.recordTrace({
|
|
634
|
+
type: "llm_call_started",
|
|
635
|
+
started_at: startedAt,
|
|
636
|
+
model: model.id
|
|
637
|
+
});
|
|
638
|
+
let output = "";
|
|
639
|
+
let toolCalls = [];
|
|
640
|
+
let responseMetadata;
|
|
641
|
+
let assistantMessage;
|
|
642
|
+
let continuation;
|
|
643
|
+
let attempt = 1;
|
|
644
|
+
let ttft;
|
|
645
|
+
let ttl;
|
|
646
|
+
let previewed = false;
|
|
647
|
+
let accepted = false;
|
|
648
|
+
let dispatchedCalls;
|
|
649
|
+
let dispatchedFingerprint;
|
|
650
|
+
let offeredFingerprint;
|
|
651
|
+
const messageMetadata = () => ({
|
|
652
|
+
iterationId: iteration.id,
|
|
653
|
+
id: `${iteration.id}:${attempt}:text`
|
|
654
|
+
});
|
|
655
|
+
const preview = async (delta) => {
|
|
656
|
+
try {
|
|
657
|
+
await (onSendDelta === null || onSendDelta === void 0 ? void 0 : onSendDelta(delta));
|
|
658
|
+
} catch (err) {
|
|
659
|
+
if (delta.restart) throw new CognitiveError(`LLM stream restart handler failed: ${getErrorMessage(err)}`, { cause: err });
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
try {
|
|
663
|
+
controller.signal.throwIfAborted();
|
|
664
|
+
if (typeof cognitive.generateTextStream === "function") {
|
|
665
|
+
let finished = false;
|
|
666
|
+
await consumeNativeStream({
|
|
667
|
+
cognitive,
|
|
668
|
+
input,
|
|
669
|
+
controller,
|
|
670
|
+
maxIdleTime: Math.max(STREAM_IDLE_TIMEOUT, ctx.maxTimeToFirstToken ?? 0),
|
|
671
|
+
onChunk: async (value) => {
|
|
672
|
+
if (value.error) throw new CognitiveError(`LLM generation failed: ${value.error}`);
|
|
673
|
+
if (value.restart) {
|
|
674
|
+
if (dispatchedCalls) throw new CognitiveError("The LLM stream restarted after tool execution began; completed work cannot be replayed.");
|
|
675
|
+
if (!ctx.midStreamFallback) throw new CognitiveError("Unexpected LLM stream restart");
|
|
676
|
+
if (!Number.isInteger(value.restart.attempt) || value.restart.attempt <= attempt) throw new CognitiveError("Provider returned an invalid stream restart attempt");
|
|
677
|
+
if (value.output || value.toolCalls || value.finished) throw new CognitiveError("A stream restart must not contain output from either attempt");
|
|
678
|
+
iteration.recordTrace({
|
|
679
|
+
type: "llm_call_restarted",
|
|
680
|
+
started_at: Date.now(),
|
|
681
|
+
...value.restart
|
|
682
|
+
});
|
|
683
|
+
previewed = false;
|
|
684
|
+
await preview({
|
|
685
|
+
restart: true,
|
|
686
|
+
iterationId: iteration.id,
|
|
687
|
+
...value.restart
|
|
688
|
+
});
|
|
689
|
+
attempt = value.restart.attempt;
|
|
690
|
+
output = "";
|
|
691
|
+
toolCalls = [];
|
|
692
|
+
responseMetadata = void 0;
|
|
693
|
+
assistantMessage = void 0;
|
|
694
|
+
continuation = void 0;
|
|
695
|
+
ttft = void 0;
|
|
696
|
+
ttl = void 0;
|
|
697
|
+
finished = false;
|
|
698
|
+
previewed = false;
|
|
699
|
+
offeredFingerprint = void 0;
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
const callsFingerprint = value.toolCalls ? stableJSON(value.toolCalls) : void 0;
|
|
703
|
+
if (dispatchedCalls && callsFingerprint !== void 0 && callsFingerprint !== dispatchedFingerprint) throw new CognitiveError("The LLM stream changed tool calls after execution began; completed work cannot be replayed.");
|
|
704
|
+
const repeatedDispatchedCalls = dispatchedCalls && callsFingerprint === dispatchedFingerprint;
|
|
705
|
+
if (finished && (value.output || value.toolCalls && !repeatedDispatchedCalls || value.assistantMessage || value.continuation !== void 0)) throw new CognitiveError("Received content after stream completion");
|
|
706
|
+
if (value.metadata) responseMetadata = value.metadata;
|
|
707
|
+
if (value.toolCalls) {
|
|
708
|
+
toolCalls = dispatchedCalls ?? value.toolCalls;
|
|
709
|
+
if (onToolCalls && !dispatchedCalls && toolCalls.length && offeredFingerprint !== callsFingerprint) {
|
|
710
|
+
validateResponse(output + (value.output ?? ""), toolCalls, value.assistantMessage ?? assistantMessage);
|
|
711
|
+
if (responseMetadata) assertSuccessfulGeneration(responseMetadata);
|
|
712
|
+
const snapshot = freezeToolCalls(structuredClone(toolCalls));
|
|
713
|
+
offeredFingerprint = callsFingerprint;
|
|
714
|
+
if (onToolCalls(snapshot)) {
|
|
715
|
+
dispatchedCalls = snapshot;
|
|
716
|
+
dispatchedFingerprint = callsFingerprint;
|
|
717
|
+
toolCalls = snapshot;
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
if (value.assistantMessage) assistantMessage = value.assistantMessage;
|
|
722
|
+
if (value.continuation !== void 0) continuation = value.continuation;
|
|
723
|
+
if (value.output) {
|
|
724
|
+
output += value.output;
|
|
725
|
+
ttl = Date.now() - startedAt;
|
|
726
|
+
ttft ??= ttl;
|
|
727
|
+
previewed = true;
|
|
728
|
+
await preview({
|
|
729
|
+
restart: false,
|
|
730
|
+
...messageMetadata(),
|
|
731
|
+
type: "text",
|
|
732
|
+
delta: value.output,
|
|
733
|
+
content: output
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
if (value.finished) finished = true;
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
if (!finished) throw new CognitiveError("LLM stream ended without a completion signal");
|
|
740
|
+
} else {
|
|
741
|
+
const response = await abortable(cognitive.generateText(input, { signal: controller.signal }), controller.signal);
|
|
742
|
+
if (response.error) throw new CognitiveError(`LLM generation failed: ${response.error}`);
|
|
743
|
+
output = response.output ?? "";
|
|
744
|
+
toolCalls = response.toolCalls ?? [];
|
|
745
|
+
assistantMessage = response.assistantMessage;
|
|
746
|
+
continuation = response.continuation;
|
|
747
|
+
responseMetadata = response.metadata;
|
|
748
|
+
}
|
|
749
|
+
controller.signal.throwIfAborted();
|
|
750
|
+
assertSuccessfulGeneration(responseMetadata);
|
|
751
|
+
validateResponse(output, toolCalls, assistantMessage);
|
|
752
|
+
if ((responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.stopReason) === "tool_calls" && !toolCalls.length) throw new CognitiveError("Provider signaled tool calls but returned none");
|
|
753
|
+
accepted = true;
|
|
754
|
+
} catch (err) {
|
|
755
|
+
throw isLLMzError(err) ? err : new CognitiveError(`LLM generation failed: ${getErrorMessage(err)}`, { cause: err });
|
|
756
|
+
} finally {
|
|
757
|
+
const usage = (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.usage) ?? {
|
|
758
|
+
inputTokens: 0,
|
|
759
|
+
outputTokens: 0,
|
|
760
|
+
inputCost: 0,
|
|
761
|
+
outputCost: 0
|
|
762
|
+
};
|
|
763
|
+
iteration.llm = {
|
|
764
|
+
started_at: startedAt,
|
|
765
|
+
ended_at: Date.now(),
|
|
766
|
+
status: accepted ? "success" : "error",
|
|
767
|
+
output,
|
|
768
|
+
cached: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cached) ?? false,
|
|
769
|
+
tokens: usage.inputTokens + usage.outputTokens,
|
|
770
|
+
spend: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.cost) ?? 0,
|
|
771
|
+
model: (responseMetadata === null || responseMetadata === void 0 ? void 0 : responseMetadata.model) ?? model.id,
|
|
772
|
+
time_to_first_token: ttft,
|
|
773
|
+
time_to_last_token: ttl,
|
|
774
|
+
usage
|
|
775
|
+
};
|
|
776
|
+
if (iteration.tokens) Object.assign(iteration.tokens, {
|
|
777
|
+
input: usage.inputTokens,
|
|
778
|
+
output: usage.outputTokens,
|
|
779
|
+
total: usage.inputTokens + usage.outputTokens
|
|
780
|
+
});
|
|
781
|
+
if (!accepted && previewed) await preview({
|
|
782
|
+
restart: true,
|
|
783
|
+
iterationId: iteration.id,
|
|
784
|
+
attempt: attempt + 1,
|
|
785
|
+
fromModel: model.id,
|
|
786
|
+
toModel: model.id,
|
|
787
|
+
reason: "Generation did not complete successfully"
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
const code = (_toolCalls$find = toolCalls.find((call) => call.name === "run_javascript")) === null || _toolCalls$find === void 0 || (_toolCalls$find = _toolCalls$find.input) === null || _toolCalls$find === void 0 ? void 0 : _toolCalls$find.code;
|
|
791
|
+
iteration.recordTrace({
|
|
792
|
+
type: "llm_call_success",
|
|
793
|
+
started_at: startedAt,
|
|
794
|
+
ended_at: Date.now(),
|
|
795
|
+
model: model.id,
|
|
796
|
+
code: typeof code === "string" ? code : ""
|
|
797
|
+
});
|
|
798
|
+
return {
|
|
799
|
+
attempt,
|
|
800
|
+
output,
|
|
801
|
+
toolCalls,
|
|
802
|
+
assistantMessage,
|
|
803
|
+
continuation,
|
|
804
|
+
metadata: responseMetadata,
|
|
805
|
+
messageMetadata: messageMetadata()
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
/** Keep execution's accepted arguments independent of later provider or callback mutations. */
|
|
809
|
+
function freezeToolCalls(calls) {
|
|
810
|
+
const freeze = (value) => {
|
|
811
|
+
if (!value || typeof value !== "object" || Object.isFrozen(value)) return;
|
|
812
|
+
for (const child of Object.values(value)) freeze(child);
|
|
813
|
+
Object.freeze(value);
|
|
814
|
+
};
|
|
815
|
+
freeze(calls);
|
|
816
|
+
return calls;
|
|
817
|
+
}
|
|
818
|
+
//#endregion
|
|
819
|
+
//#region src/runtime/inspection-values.ts
|
|
820
|
+
/** Explicit display policies apply only to unchanged values in this JavaScript execution. */
|
|
821
|
+
var InspectionValues = class {
|
|
822
|
+
_primitives = /* @__PURE__ */ new Map();
|
|
823
|
+
_objects = /* @__PURE__ */ new Map();
|
|
824
|
+
capture(value, policy) {
|
|
825
|
+
this._register(value, policy, true);
|
|
826
|
+
}
|
|
827
|
+
captureDefault(value, maxTokens) {
|
|
828
|
+
this._register(value, {
|
|
829
|
+
maxTokens,
|
|
830
|
+
preserve: "top"
|
|
831
|
+
}, false);
|
|
832
|
+
}
|
|
833
|
+
_register(value, policy, explicit) {
|
|
834
|
+
let captured;
|
|
835
|
+
try {
|
|
836
|
+
captured = cloneMemoryValue(value);
|
|
837
|
+
} catch {
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
if (!captured || typeof captured !== "object") {
|
|
841
|
+
const previous = this._primitives.get(captured);
|
|
842
|
+
this._primitives.set(captured, this._mergePolicy(previous, {
|
|
843
|
+
policy,
|
|
844
|
+
explicit
|
|
845
|
+
}));
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
const key = this._objectKey(captured);
|
|
849
|
+
const candidates = this._objects.get(key) ?? [];
|
|
850
|
+
const previous = candidates.find((candidate) => isEqual(candidate.value, captured));
|
|
851
|
+
if (previous) {
|
|
852
|
+
const selected = this._mergePolicy(previous, {
|
|
853
|
+
policy,
|
|
854
|
+
explicit
|
|
855
|
+
});
|
|
856
|
+
previous.policy = selected.policy;
|
|
857
|
+
previous.explicit = selected.explicit;
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
candidates.push({
|
|
861
|
+
value: captured,
|
|
862
|
+
policy: { ...policy },
|
|
863
|
+
explicit
|
|
864
|
+
});
|
|
865
|
+
this._objects.set(key, candidates);
|
|
866
|
+
}
|
|
867
|
+
/** Match unchanged VM copies without rebuilding a wrapped display graph. */
|
|
868
|
+
getPolicy = (value) => {
|
|
869
|
+
var _candidates$find;
|
|
870
|
+
if (!value || typeof value !== "object") {
|
|
871
|
+
var _this$_primitives$get;
|
|
872
|
+
return (_this$_primitives$get = this._primitives.get(value)) === null || _this$_primitives$get === void 0 ? void 0 : _this$_primitives$get.policy;
|
|
873
|
+
}
|
|
874
|
+
return (_candidates$find = (this._objects.get(this._objectKey(value)) ?? []).find((candidate) => isEqual(candidate.value, value))) === null || _candidates$find === void 0 ? void 0 : _candidates$find.policy;
|
|
875
|
+
};
|
|
876
|
+
_objectKey(value) {
|
|
877
|
+
return Array.isArray(value) ? `array:${value.length}` : `object:${Object.keys(value).length}`;
|
|
878
|
+
}
|
|
879
|
+
_mergePolicy(previous, next) {
|
|
880
|
+
if ((previous === null || previous === void 0 ? void 0 : previous.explicit) && !next.explicit) return previous;
|
|
881
|
+
if (!previous || !previous.explicit && next.explicit || next.policy.maxTokens < previous.policy.maxTokens) return {
|
|
882
|
+
policy: { ...next.policy },
|
|
883
|
+
explicit: next.explicit
|
|
884
|
+
};
|
|
885
|
+
if (next.policy.maxTokens === previous.policy.maxTokens && next.policy.preserve !== previous.policy.preserve) return {
|
|
886
|
+
policy: {
|
|
887
|
+
maxTokens: next.policy.maxTokens,
|
|
888
|
+
preserve: "top"
|
|
889
|
+
},
|
|
890
|
+
explicit: next.explicit
|
|
891
|
+
};
|
|
892
|
+
return previous;
|
|
893
|
+
}
|
|
894
|
+
};
|
|
895
|
+
//#endregion
|
|
896
|
+
//#region src/runtime/javascript-api.ts
|
|
897
|
+
const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
898
|
+
/**
|
|
899
|
+
* Component methods send synchronously; the runtime joins delivery in close().
|
|
900
|
+
* Inspection returns a decision, while exit latches an outcome and stops the program.
|
|
901
|
+
*/
|
|
902
|
+
function createJavaScriptApi({ iteration, components, exits, deliver, signal, onError }) {
|
|
903
|
+
const decisions = /* @__PURE__ */ new Map();
|
|
904
|
+
const pending = /* @__PURE__ */ new Set();
|
|
905
|
+
const inspections = [];
|
|
906
|
+
let open = true;
|
|
907
|
+
let outstanding = [];
|
|
908
|
+
let delivery;
|
|
909
|
+
let nextMessage = 0;
|
|
910
|
+
let terminalOutcome;
|
|
911
|
+
let interruption;
|
|
912
|
+
let criticalFailure;
|
|
913
|
+
const termination = /* @__PURE__ */ new Error("JavaScript execution terminated.");
|
|
914
|
+
const reportError = (error) => {
|
|
915
|
+
onError === null || onError === void 0 || onError(error);
|
|
916
|
+
if (isCriticalError(error)) {
|
|
917
|
+
criticalFailure = error;
|
|
918
|
+
complete();
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
const throwIfTerminated = () => {
|
|
922
|
+
if (criticalFailure) throw criticalFailure;
|
|
923
|
+
if (interruption || terminalOutcome) throw termination;
|
|
924
|
+
};
|
|
925
|
+
const assertOpen = () => {
|
|
926
|
+
throwIfTerminated();
|
|
927
|
+
if (!open) throw new HostOperationError("JavaScript has completed. Host operations and Object writes are closed.");
|
|
928
|
+
signal === null || signal === void 0 || signal.throwIfAborted();
|
|
929
|
+
};
|
|
930
|
+
const resolve = (value) => {
|
|
931
|
+
if (!isRecord(value) || typeof value.__llmz_decision !== "string") return;
|
|
932
|
+
return decisions.get(value.__llmz_decision);
|
|
933
|
+
};
|
|
934
|
+
const issue = (outcome) => {
|
|
935
|
+
assertOpen();
|
|
936
|
+
const token = ulid();
|
|
937
|
+
decisions.set(token, outcome);
|
|
938
|
+
return Object.freeze({ __llmz_decision: token });
|
|
939
|
+
};
|
|
940
|
+
const validateExit = (name = "listen", value) => {
|
|
941
|
+
assertOpen();
|
|
942
|
+
const registered = exits.find((candidate) => candidate.name === name || candidate.aliases.includes(name));
|
|
943
|
+
if (!registered) throw new UnknownExitError(name, exits.map((exit) => exit.name));
|
|
944
|
+
if (!registered.schema && value !== void 0) throw new ExitInputError(registered.name, [{
|
|
945
|
+
path: [],
|
|
946
|
+
message: "This exit takes no payload."
|
|
947
|
+
}], "undefined");
|
|
948
|
+
const schema = registered.zSchema;
|
|
949
|
+
const parsed = schema ? parseSchemaSync(schema, value, `Exit "${registered.name}"`) : void 0;
|
|
950
|
+
if (parsed && !parsed.success) throw new ExitInputError(registered.name, parsed.error.issues, schemaToTypeScript(schema));
|
|
951
|
+
const validated = parsed === null || parsed === void 0 ? void 0 : parsed.data;
|
|
952
|
+
return {
|
|
953
|
+
type: "exit",
|
|
954
|
+
exit: registered,
|
|
955
|
+
value: cloneMemoryValue(validated)
|
|
956
|
+
};
|
|
957
|
+
};
|
|
958
|
+
const exit = (name = "listen", value) => {
|
|
959
|
+
let outcome;
|
|
960
|
+
try {
|
|
961
|
+
outcome = validateExit(name, value);
|
|
962
|
+
} catch (error) {
|
|
963
|
+
reportError(error);
|
|
964
|
+
throw error;
|
|
965
|
+
}
|
|
966
|
+
terminalOutcome = outcome;
|
|
967
|
+
complete();
|
|
968
|
+
throw termination;
|
|
969
|
+
};
|
|
970
|
+
const track = (operation) => {
|
|
971
|
+
assertOpen();
|
|
972
|
+
const tracked = (async () => operation())().then((value) => {
|
|
973
|
+
pending.delete(tracked);
|
|
974
|
+
return value;
|
|
975
|
+
}, (error) => {
|
|
976
|
+
pending.delete(tracked);
|
|
977
|
+
if (isCriticalError(error)) {
|
|
978
|
+
criticalFailure = error;
|
|
979
|
+
complete();
|
|
980
|
+
}
|
|
981
|
+
if (!interruption && ThinkSignal.is(error)) {
|
|
982
|
+
interruption = error;
|
|
983
|
+
complete();
|
|
984
|
+
}
|
|
985
|
+
throw error;
|
|
986
|
+
});
|
|
987
|
+
pending.add(tracked);
|
|
988
|
+
tracked.catch(() => {});
|
|
989
|
+
return tracked;
|
|
990
|
+
};
|
|
991
|
+
const enqueue = (messages) => {
|
|
992
|
+
const dispatch = async () => deliver(messages);
|
|
993
|
+
delivery = delivery ? delivery.then(dispatch) : dispatch();
|
|
994
|
+
delivery.catch(() => {});
|
|
995
|
+
return delivery;
|
|
996
|
+
};
|
|
997
|
+
const complete = () => {
|
|
998
|
+
if (!open) return;
|
|
999
|
+
open = false;
|
|
1000
|
+
outstanding = [...pending];
|
|
1001
|
+
};
|
|
1002
|
+
const close = async () => {
|
|
1003
|
+
var _delivered$;
|
|
1004
|
+
complete();
|
|
1005
|
+
const [, delivered] = await Promise.all([Promise.allSettled(outstanding), Promise.allSettled(delivery ? [delivery] : [])]);
|
|
1006
|
+
if (criticalFailure) throw criticalFailure;
|
|
1007
|
+
if (((_delivered$ = delivered[0]) === null || _delivered$ === void 0 ? void 0 : _delivered$.status) === "rejected") throw delivered[0].reason;
|
|
1008
|
+
if (outstanding.length && !interruption) throw new HostOperationError(`JavaScript completed with ${outstanding.length} unawaited host operation(s). Await all business tools before returning. Started operations have settled and may have completed effects; do not replay them.`);
|
|
1009
|
+
};
|
|
1010
|
+
const inspect = (value) => issue({
|
|
1011
|
+
type: "inspect",
|
|
1012
|
+
value: cloneMemoryValue(value)
|
|
1013
|
+
});
|
|
1014
|
+
const chat = withMissingMember(Object.fromEntries([...components].map(([name, component]) => [name, Object.freeze((input) => {
|
|
1015
|
+
assertOpen();
|
|
1016
|
+
let rendered;
|
|
1017
|
+
try {
|
|
1018
|
+
rendered = component.render(input);
|
|
1019
|
+
} catch (error) {
|
|
1020
|
+
reportError(error);
|
|
1021
|
+
throw error;
|
|
1022
|
+
}
|
|
1023
|
+
enqueue([{
|
|
1024
|
+
id: `${iteration.nativeCallId ?? iteration.id}:message:${++nextMessage}`,
|
|
1025
|
+
component: rendered
|
|
1026
|
+
}]);
|
|
1027
|
+
})])), (name) => {
|
|
1028
|
+
const error = new UnknownComponentError(name, [...components.keys()]);
|
|
1029
|
+
onError === null || onError === void 0 || onError(error);
|
|
1030
|
+
throw error;
|
|
1031
|
+
});
|
|
1032
|
+
return {
|
|
1033
|
+
bindings: Object.freeze({
|
|
1034
|
+
exit: Object.freeze(exit),
|
|
1035
|
+
inspect: Object.freeze(inspect),
|
|
1036
|
+
chat: Object.freeze(chat)
|
|
1037
|
+
}),
|
|
1038
|
+
resolve,
|
|
1039
|
+
isReceipt: (value) => resolve(value) !== void 0,
|
|
1040
|
+
getTerminalOutcome: () => terminalOutcome,
|
|
1041
|
+
getInterruption: () => interruption,
|
|
1042
|
+
requestInspection: (inspection) => {
|
|
1043
|
+
inspections.push(inspection);
|
|
1044
|
+
},
|
|
1045
|
+
getForcedInspections: () => inspections,
|
|
1046
|
+
throwIfTerminated,
|
|
1047
|
+
track,
|
|
1048
|
+
assertOpen,
|
|
1049
|
+
reportError,
|
|
1050
|
+
complete,
|
|
1051
|
+
close
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
//#endregion
|
|
1055
|
+
//#region src/runtime/utils.ts
|
|
1056
|
+
const finalizeIteration = async ({ iteration, status, controller, onIterationEnd }) => {
|
|
1057
|
+
if (status) iteration.end(status);
|
|
1058
|
+
if (iteration.status.type === "pending") return;
|
|
1059
|
+
try {
|
|
1060
|
+
await (onIterationEnd === null || onIterationEnd === void 0 ? void 0 : onIterationEnd(iteration, controller));
|
|
1061
|
+
} catch (err) {
|
|
1062
|
+
if (isCriticalError(err)) {
|
|
1063
|
+
iteration.recordError(err);
|
|
1064
|
+
throw err;
|
|
1065
|
+
}
|
|
1066
|
+
iteration.recordError(new HookError(err instanceof Error ? err.message : String(err), { cause: err }));
|
|
1067
|
+
console.error(err);
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
//#endregion
|
|
1071
|
+
//#region src/runtime/tool-wrapper.ts
|
|
1072
|
+
const SLOW_TOOL_WARNING = ms("15s");
|
|
1073
|
+
function wrapTool({ tool, object, iteration, beforeHook, afterHook, onTruncation, onResult, controller, onThink }) {
|
|
1074
|
+
return async function(input, line) {
|
|
1075
|
+
controller.signal.throwIfAborted();
|
|
1076
|
+
const toolCallId = `tcall_${ulid()}`;
|
|
1077
|
+
const originalInput = input;
|
|
1078
|
+
let reportedInput = originalInput;
|
|
1079
|
+
let effectiveInput = input;
|
|
1080
|
+
const alertSlowTool = setTimeout(() => iteration.recordTrace({
|
|
1081
|
+
type: "tool_slow",
|
|
1082
|
+
tool_name: tool.name,
|
|
1083
|
+
tool_call_id: toolCallId,
|
|
1084
|
+
started_at: Date.now(),
|
|
1085
|
+
input: reportedInput,
|
|
1086
|
+
object,
|
|
1087
|
+
duration: SLOW_TOOL_WARNING
|
|
1088
|
+
}), SLOW_TOOL_WARNING);
|
|
1089
|
+
const toolStart = Date.now();
|
|
1090
|
+
let output;
|
|
1091
|
+
let error;
|
|
1092
|
+
let success = true;
|
|
1093
|
+
const inspections = [];
|
|
1094
|
+
const pushToolCallTrace = () => {
|
|
1095
|
+
iteration.recordTrace({
|
|
1096
|
+
type: "tool_call",
|
|
1097
|
+
tool_call_id: toolCallId,
|
|
1098
|
+
native_call_id: iteration.nativeCallId,
|
|
1099
|
+
started_at: toolStart,
|
|
1100
|
+
ended_at: Date.now(),
|
|
1101
|
+
tool_name: tool.name,
|
|
1102
|
+
object,
|
|
1103
|
+
input: reportedInput,
|
|
1104
|
+
output,
|
|
1105
|
+
error,
|
|
1106
|
+
success
|
|
1107
|
+
});
|
|
1108
|
+
};
|
|
1109
|
+
const unwrapSignal = (value) => {
|
|
1110
|
+
if (!ThinkSignal.is(value)) return value;
|
|
1111
|
+
const context = value.context;
|
|
1112
|
+
const output = unwrapTruncated(context);
|
|
1113
|
+
if (isTruncated(context)) onTruncation === null || onTruncation === void 0 || onTruncation(output, context.$$truncate);
|
|
1114
|
+
const inspection = {
|
|
1115
|
+
tool: object ? `${object}.${tool.name}` : tool.name,
|
|
1116
|
+
toolCallId,
|
|
1117
|
+
line,
|
|
1118
|
+
reason: value.reason,
|
|
1119
|
+
value: output,
|
|
1120
|
+
metadata: value.metadata
|
|
1121
|
+
};
|
|
1122
|
+
inspections.push(inspection);
|
|
1123
|
+
return output;
|
|
1124
|
+
};
|
|
1125
|
+
try {
|
|
1126
|
+
const beforeRes = await callHook(() => beforeHook === null || beforeHook === void 0 ? void 0 : beforeHook({
|
|
1127
|
+
iteration,
|
|
1128
|
+
tool,
|
|
1129
|
+
input: effectiveInput,
|
|
1130
|
+
controller,
|
|
1131
|
+
object,
|
|
1132
|
+
toolCallId,
|
|
1133
|
+
nativeCallId: iteration.nativeCallId
|
|
1134
|
+
}));
|
|
1135
|
+
if (ThinkSignal.is(beforeRes)) throw new HookError("Tool hooks cannot request inspection with ThinkSignal. Return it from the tool handler instead.");
|
|
1136
|
+
if (typeof (beforeRes === null || beforeRes === void 0 ? void 0 : beforeRes.input) !== "undefined") effectiveInput = beforeRes.input;
|
|
1137
|
+
controller.signal.throwIfAborted();
|
|
1138
|
+
try {
|
|
1139
|
+
output = await tool.execute(effectiveInput, {
|
|
1140
|
+
callId: toolCallId,
|
|
1141
|
+
iterationId: iteration.id,
|
|
1142
|
+
nativeCallId: iteration.nativeCallId,
|
|
1143
|
+
onTruncation,
|
|
1144
|
+
onInput: (parsed) => {
|
|
1145
|
+
controller.signal.throwIfAborted();
|
|
1146
|
+
if (effectiveInput === originalInput) reportedInput = parsed;
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
} catch (error) {
|
|
1150
|
+
if (!ThinkSignal.is(error)) throw error;
|
|
1151
|
+
output = error;
|
|
1152
|
+
}
|
|
1153
|
+
output = unwrapSignal(output);
|
|
1154
|
+
const afterRes = await callHook(() => afterHook === null || afterHook === void 0 ? void 0 : afterHook({
|
|
1155
|
+
iteration,
|
|
1156
|
+
tool,
|
|
1157
|
+
input: effectiveInput,
|
|
1158
|
+
output,
|
|
1159
|
+
controller,
|
|
1160
|
+
object,
|
|
1161
|
+
toolCallId,
|
|
1162
|
+
nativeCallId: iteration.nativeCallId
|
|
1163
|
+
}));
|
|
1164
|
+
if (ThinkSignal.is(afterRes) || ThinkSignal.is(afterRes === null || afterRes === void 0 ? void 0 : afterRes.output)) throw new HookError("Tool hooks cannot request inspection with ThinkSignal. Return it from the tool handler instead.");
|
|
1165
|
+
if (typeof (afterRes === null || afterRes === void 0 ? void 0 : afterRes.output) !== "undefined") output = afterRes.output;
|
|
1166
|
+
controller.signal.throwIfAborted();
|
|
1167
|
+
} catch (err) {
|
|
1168
|
+
success = false;
|
|
1169
|
+
output = void 0;
|
|
1170
|
+
if (ThinkSignal.is(err)) error = new HookError("Tool hooks cannot request inspection with ThinkSignal. Return it from the tool handler instead.");
|
|
1171
|
+
else error = isLLMzError(err) ? err : new ToolExecutionError(tool.name, err);
|
|
1172
|
+
iteration.recordError(error);
|
|
1173
|
+
} finally {
|
|
1174
|
+
clearTimeout(alertSlowTool);
|
|
1175
|
+
for (const inspection of success ? inspections : []) {
|
|
1176
|
+
const value = snapshotInspectionValue(output);
|
|
1177
|
+
onThink === null || onThink === void 0 || onThink({
|
|
1178
|
+
...inspection,
|
|
1179
|
+
value
|
|
1180
|
+
});
|
|
1181
|
+
iteration.recordTrace({
|
|
1182
|
+
type: "think_signal",
|
|
1183
|
+
started_at: Date.now(),
|
|
1184
|
+
ended_at: Date.now(),
|
|
1185
|
+
line: line ?? 0,
|
|
1186
|
+
tool_name: tool.name,
|
|
1187
|
+
tool_call_id: toolCallId,
|
|
1188
|
+
object,
|
|
1189
|
+
reason: inspection.reason,
|
|
1190
|
+
context: value,
|
|
1191
|
+
metadata: inspection.metadata
|
|
1192
|
+
});
|
|
1193
|
+
}
|
|
1194
|
+
pushToolCallTrace();
|
|
1195
|
+
}
|
|
1196
|
+
if (!success) throw error;
|
|
1197
|
+
onResult === null || onResult === void 0 || onResult(output);
|
|
1198
|
+
return output;
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
//#endregion
|
|
1202
|
+
//#region src/runtime/vm-context.ts
|
|
1203
|
+
const buildVMContext = ({ ctx, iteration, controller, onBeforeTool, onAfterTool, onTruncation, onToolResult, javascriptApi }) => {
|
|
1204
|
+
const memoryBindings = ctx.session.getBindings();
|
|
1205
|
+
const vmContext = {
|
|
1206
|
+
...stripInvalidIdentifiers(memoryBindings),
|
|
1207
|
+
[VM_ON_ERROR]: (error) => {
|
|
1208
|
+
iteration.recordError(error);
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1211
|
+
const reject = (error) => {
|
|
1212
|
+
iteration.recordError(error);
|
|
1213
|
+
javascriptApi === null || javascriptApi === void 0 || javascriptApi.reportError(error);
|
|
1214
|
+
throw error;
|
|
1215
|
+
};
|
|
1216
|
+
for (const name of ["$return", "$iterations"]) Object.defineProperty(vmContext, name, {
|
|
1217
|
+
value: memoryBindings[name],
|
|
1218
|
+
enumerable: true,
|
|
1219
|
+
writable: false,
|
|
1220
|
+
configurable: false
|
|
1221
|
+
});
|
|
1222
|
+
if (javascriptApi) {
|
|
1223
|
+
for (const [name, value] of Object.entries(javascriptApi.bindings)) Object.defineProperty(vmContext, name, {
|
|
1224
|
+
value,
|
|
1225
|
+
enumerable: true,
|
|
1226
|
+
writable: false,
|
|
1227
|
+
configurable: false
|
|
1228
|
+
});
|
|
1229
|
+
Object.defineProperty(vmContext, VM_PROGRAM_COMPLETE, { value: javascriptApi.complete });
|
|
1230
|
+
Object.defineProperty(vmContext, VM_TERMINATION, { value: {
|
|
1231
|
+
isTerminated: () => javascriptApi.getTerminalOutcome() !== void 0 || javascriptApi.getInterruption() !== void 0,
|
|
1232
|
+
check: javascriptApi.throwIfTerminated,
|
|
1233
|
+
getSignal: javascriptApi.getInterruption
|
|
1234
|
+
} });
|
|
1235
|
+
}
|
|
1236
|
+
for (const obj of iteration.objects) {
|
|
1237
|
+
const internalValues = {};
|
|
1238
|
+
const instance = {};
|
|
1239
|
+
for (const { name, writable, type } of obj.properties ?? []) {
|
|
1240
|
+
const initialValue = ctx.session.memory.getObjectPropertyValue(obj.name, name);
|
|
1241
|
+
internalValues[name] = freezePropertyValue(initialValue);
|
|
1242
|
+
const schema = type ?? z.any();
|
|
1243
|
+
Object.defineProperty(instance, name, {
|
|
1244
|
+
enumerable: true,
|
|
1245
|
+
configurable: true,
|
|
1246
|
+
get() {
|
|
1247
|
+
return internalValues[name];
|
|
1248
|
+
},
|
|
1249
|
+
set(value) {
|
|
1250
|
+
javascriptApi === null || javascriptApi === void 0 || javascriptApi.assertOpen();
|
|
1251
|
+
if (!writable) reject(new AssignmentError(`Property ${obj.name}.${name} is read-only and cannot be modified`));
|
|
1252
|
+
let parsed;
|
|
1253
|
+
try {
|
|
1254
|
+
parsed = parseSchemaSync(schema, value, `Object property ${obj.name}.${name}`);
|
|
1255
|
+
} catch (error) {
|
|
1256
|
+
const failure = iteration.recordError(error);
|
|
1257
|
+
javascriptApi === null || javascriptApi === void 0 || javascriptApi.reportError(failure);
|
|
1258
|
+
throw failure;
|
|
1259
|
+
}
|
|
1260
|
+
if (!parsed.success) reject(new ObjectPropertyError(obj.name, name, parsed.error.issues, schemaToTypeScript(schema)));
|
|
1261
|
+
internalValues[name] = freezePropertyValue(cloneMemoryValue(parsed.data));
|
|
1262
|
+
iteration.recordTrace({
|
|
1263
|
+
type: "property",
|
|
1264
|
+
started_at: Date.now(),
|
|
1265
|
+
object: obj.name,
|
|
1266
|
+
property: name,
|
|
1267
|
+
value: parsed.data
|
|
1268
|
+
});
|
|
1269
|
+
iteration.trackMutation({
|
|
1270
|
+
object: obj.name,
|
|
1271
|
+
property: name,
|
|
1272
|
+
before: initialValue,
|
|
1273
|
+
after: parsed.data
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
for (const tool of obj.tools ?? []) {
|
|
1279
|
+
const wrapped = wrapTool({
|
|
1280
|
+
tool,
|
|
1281
|
+
object: obj.name,
|
|
1282
|
+
iteration,
|
|
1283
|
+
beforeHook: onBeforeTool,
|
|
1284
|
+
afterHook: onAfterTool,
|
|
1285
|
+
onTruncation,
|
|
1286
|
+
onResult: onToolResult,
|
|
1287
|
+
controller,
|
|
1288
|
+
onThink: javascriptApi === null || javascriptApi === void 0 ? void 0 : javascriptApi.requestInspection
|
|
1289
|
+
});
|
|
1290
|
+
instance[tool.name] = javascriptApi ? (input) => {
|
|
1291
|
+
var _vmContext$VM_CALL_SI;
|
|
1292
|
+
const line = (_vmContext$VM_CALL_SI = vmContext[VM_CALL_SITE]) === null || _vmContext$VM_CALL_SI === void 0 ? void 0 : _vmContext$VM_CALL_SI.call(vmContext);
|
|
1293
|
+
return javascriptApi.track(() => wrapped(input, line));
|
|
1294
|
+
} : wrapped;
|
|
1295
|
+
}
|
|
1296
|
+
vmContext[obj.name] = withMissingMember(instance, (name) => {
|
|
1297
|
+
const error = new UnknownToolError(`${obj.name}.${name}`, (obj.tools ?? []).map((tool) => `${obj.name}.${tool.name}`));
|
|
1298
|
+
iteration.recordError(error);
|
|
1299
|
+
throw error;
|
|
1300
|
+
});
|
|
1301
|
+
}
|
|
1302
|
+
for (const tool of iteration.tools) {
|
|
1303
|
+
const wrapped = wrapTool({
|
|
1304
|
+
tool,
|
|
1305
|
+
iteration,
|
|
1306
|
+
beforeHook: onBeforeTool,
|
|
1307
|
+
afterHook: onAfterTool,
|
|
1308
|
+
onTruncation,
|
|
1309
|
+
onResult: onToolResult,
|
|
1310
|
+
controller,
|
|
1311
|
+
onThink: javascriptApi === null || javascriptApi === void 0 ? void 0 : javascriptApi.requestInspection
|
|
1312
|
+
});
|
|
1313
|
+
const callable = javascriptApi ? (input) => {
|
|
1314
|
+
var _vmContext$VM_CALL_SI2;
|
|
1315
|
+
const line = (_vmContext$VM_CALL_SI2 = vmContext[VM_CALL_SITE]) === null || _vmContext$VM_CALL_SI2 === void 0 ? void 0 : _vmContext$VM_CALL_SI2.call(vmContext);
|
|
1316
|
+
return javascriptApi.track(() => wrapped(input, line));
|
|
1317
|
+
} : wrapped;
|
|
1318
|
+
for (const key of [tool.name, ...tool.aliases ?? []]) vmContext[key] = callable;
|
|
1319
|
+
}
|
|
1320
|
+
return vmContext;
|
|
1321
|
+
};
|
|
1322
|
+
/** Nested edits must go through whole-property assignment so its schema always runs. */
|
|
1323
|
+
function freezePropertyValue(value) {
|
|
1324
|
+
if (value && typeof value === "object") {
|
|
1325
|
+
for (const child of Object.values(value)) freezePropertyValue(child);
|
|
1326
|
+
Object.freeze(value);
|
|
1327
|
+
}
|
|
1328
|
+
return value;
|
|
1329
|
+
}
|
|
1330
|
+
//#endregion
|
|
1331
|
+
//#region src/runtime/execute.ts
|
|
1332
|
+
/** Each iteration joins generation and execution before settling its transcript. */
|
|
1333
|
+
async function executeContext(props) {
|
|
1334
|
+
await init();
|
|
1335
|
+
const result = await executeContextInternal(props);
|
|
1336
|
+
try {
|
|
1337
|
+
var _result$context$chat, _result$context$chat$;
|
|
1338
|
+
await ((_result$context$chat = result.context.chat) === null || _result$context$chat === void 0 || (_result$context$chat$ = _result$context$chat.onExecutionDone) === null || _result$context$chat$ === void 0 ? void 0 : _result$context$chat$.call(_result$context$chat, result));
|
|
1339
|
+
} catch {}
|
|
1340
|
+
return result;
|
|
1341
|
+
}
|
|
1342
|
+
async function executeContextInternal(props) {
|
|
1343
|
+
var _props$options, _props$options2, _props$options3, _props$options4, _props$options5, _props$options6, _props$options7;
|
|
1344
|
+
const controller = createJoinedAbortController([props.signal]);
|
|
1345
|
+
const ctx = new Context({
|
|
1346
|
+
...props,
|
|
1347
|
+
loop: (_props$options = props.options) === null || _props$options === void 0 ? void 0 : _props$options.loop,
|
|
1348
|
+
timeout: (_props$options2 = props.options) === null || _props$options2 === void 0 ? void 0 : _props$options2.timeout,
|
|
1349
|
+
maxTokens: (_props$options3 = props.options) === null || _props$options3 === void 0 ? void 0 : _props$options3.maxTokens,
|
|
1350
|
+
toolResultMaxTokens: (_props$options4 = props.options) === null || _props$options4 === void 0 ? void 0 : _props$options4.toolResultMaxTokens,
|
|
1351
|
+
maxTimeToFirstToken: (_props$options5 = props.options) === null || _props$options5 === void 0 ? void 0 : _props$options5.maxTimeToFirstToken,
|
|
1352
|
+
midStreamFallback: (_props$options6 = props.options) === null || _props$options6 === void 0 ? void 0 : _props$options6.midStreamFallback,
|
|
1353
|
+
transcriptionModel: (_props$options7 = props.options) === null || _props$options7 === void 0 ? void 0 : _props$options7.transcriptionModel
|
|
1354
|
+
});
|
|
1355
|
+
let release;
|
|
1356
|
+
try {
|
|
1357
|
+
var _props$options8, _ctx$iterations$at;
|
|
1358
|
+
if ("snapshot" in props) throw new InvalidConfigurationError("Snapshots and external pause/resume are no longer supported. Use a session for conversation history and memory.");
|
|
1359
|
+
if ("messages" in props) throw new InvalidConfigurationError("Append input with session.append(message) before calling execute(). execute.messages is no longer supported.");
|
|
1360
|
+
if (((_props$options8 = props.options) === null || _props$options8 === void 0 ? void 0 : _props$options8.requireChatResponse) !== void 0 && typeof props.options.requireChatResponse !== "boolean") throw new InvalidConfigurationError("Invalid requireChatResponse. Expected a boolean.");
|
|
1361
|
+
release = ctx.session.acquire();
|
|
1362
|
+
prepareSession(ctx);
|
|
1363
|
+
const client = props.client ?? new Client();
|
|
1364
|
+
const execution = {
|
|
1365
|
+
ctx,
|
|
1366
|
+
props,
|
|
1367
|
+
cognitive: Cognitive.isCognitiveClient(client) || _CustomModelClient.isCustomClient(client) ? client : new Cognitive({ client }),
|
|
1368
|
+
controller
|
|
1369
|
+
};
|
|
1370
|
+
while (ctx.iterations.length < ctx.loop) {
|
|
1371
|
+
const result = await executeNextIteration(execution);
|
|
1372
|
+
if (result) {
|
|
1373
|
+
if (result.isSuccess()) ctx.session.completeTurn();
|
|
1374
|
+
return result;
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
const error = new LoopExceededError(ctx.loop);
|
|
1378
|
+
(_ctx$iterations$at = ctx.iterations.at(-1)) === null || _ctx$iterations$at === void 0 || _ctx$iterations$at.recordError(error);
|
|
1379
|
+
return new ErrorExecutionResult(ctx, error);
|
|
1380
|
+
} catch (error) {
|
|
1381
|
+
return new ErrorExecutionResult(ctx, error);
|
|
1382
|
+
} finally {
|
|
1383
|
+
release === null || release === void 0 || release();
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
function prepareSession(ctx) {
|
|
1387
|
+
if (ctx.chat && ctx.session.turn > 0 && !ctx.session.hasActiveTurn && !ctx.session.pendingMessages.length) throw new SessionStateError("No pending input. Append a message to the session before starting another chat turn.");
|
|
1388
|
+
ctx.session.beginTurn();
|
|
1389
|
+
}
|
|
1390
|
+
async function executeNextIteration(execution) {
|
|
1391
|
+
const { ctx, props, controller } = execution;
|
|
1392
|
+
let onTrace = props.onTrace;
|
|
1393
|
+
const iterationNumber = ctx.iterations.length + 1;
|
|
1394
|
+
const iteration = await ctx.nextIteration((trace) => {
|
|
1395
|
+
onTrace === null || onTrace === void 0 || onTrace({
|
|
1396
|
+
trace,
|
|
1397
|
+
iteration: iterationNumber,
|
|
1398
|
+
controller
|
|
1399
|
+
});
|
|
1400
|
+
});
|
|
1401
|
+
const state = {
|
|
1402
|
+
...execution,
|
|
1403
|
+
iteration,
|
|
1404
|
+
inspectionValues: new InspectionValues()
|
|
1405
|
+
};
|
|
1406
|
+
try {
|
|
1407
|
+
await executeIteration(state);
|
|
1408
|
+
} catch (error) {
|
|
1409
|
+
handleIterationFailure(state, error);
|
|
1410
|
+
} finally {
|
|
1411
|
+
try {
|
|
1412
|
+
try {
|
|
1413
|
+
var _state$capture;
|
|
1414
|
+
state.memory ??= commitMemory(state, (_state$capture = state.capture) === null || _state$capture === void 0 ? void 0 : _state$capture.result);
|
|
1415
|
+
} catch (error) {
|
|
1416
|
+
failFinalization(state, error);
|
|
1417
|
+
}
|
|
1418
|
+
const memory = state.memory;
|
|
1419
|
+
for (const failure of memory.unavailable) iteration.recordError(new MemoryValueError(`Memory variable "${failure.name}": ${failure.reason}`));
|
|
1420
|
+
const outcome = getExecutionOutcome(state, memory);
|
|
1421
|
+
if (state.capture) {
|
|
1422
|
+
var _iteration$sessionInf;
|
|
1423
|
+
ctx.session.appendToolResult(iteration.id, state.capture.call.id, renderExecutionReport({
|
|
1424
|
+
outcome,
|
|
1425
|
+
memory,
|
|
1426
|
+
activity: getExecutionActivity(iteration),
|
|
1427
|
+
source: {
|
|
1428
|
+
requested: state.capture.call.code,
|
|
1429
|
+
executed: iteration.code
|
|
1430
|
+
},
|
|
1431
|
+
requiresExit: !iteration.isChatEnabled,
|
|
1432
|
+
identity: {
|
|
1433
|
+
sessionId: ctx.session.id,
|
|
1434
|
+
...iteration.sessionInfo,
|
|
1435
|
+
iterationId: iteration.id,
|
|
1436
|
+
iteration: (_iteration$sessionInf = iteration.sessionInfo) === null || _iteration$sessionInf === void 0 ? void 0 : _iteration$sessionInf.number
|
|
1437
|
+
},
|
|
1438
|
+
inspector: ctx.inspector,
|
|
1439
|
+
maxTokens: ctx.toolResultMaxTokens,
|
|
1440
|
+
policies: state.inspectionValues.getPolicy
|
|
1441
|
+
}));
|
|
1442
|
+
}
|
|
1443
|
+
try {
|
|
1444
|
+
ctx.session.settleIteration(iteration.id, {
|
|
1445
|
+
outcome: iteration.status.type,
|
|
1446
|
+
error: iteration.error ?? void 0
|
|
1447
|
+
});
|
|
1448
|
+
} catch (error) {
|
|
1449
|
+
if (!MemoryCapacityError.is(error)) throw error;
|
|
1450
|
+
failFinalization(state, error);
|
|
1451
|
+
ctx.session.settleIteration(iteration.id, { outcome: "error" });
|
|
1452
|
+
}
|
|
1453
|
+
await finalizeIteration({
|
|
1454
|
+
iteration,
|
|
1455
|
+
controller,
|
|
1456
|
+
onIterationEnd: props.onIterationEnd
|
|
1457
|
+
});
|
|
1458
|
+
} finally {
|
|
1459
|
+
onTrace = void 0;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
return getIterationResult(state);
|
|
1463
|
+
}
|
|
1464
|
+
async function executeIteration(state) {
|
|
1465
|
+
const { ctx, props, iteration, cognitive, controller } = state;
|
|
1466
|
+
await callHook(() => {
|
|
1467
|
+
var _props$onIterationSta;
|
|
1468
|
+
return (_props$onIterationSta = props.onIterationStart) === null || _props$onIterationSta === void 0 ? void 0 : _props$onIterationSta.call(props, iteration, controller, ctx);
|
|
1469
|
+
});
|
|
1470
|
+
controller.signal.throwIfAborted();
|
|
1471
|
+
let execution;
|
|
1472
|
+
let assistantCommitted = false;
|
|
1473
|
+
try {
|
|
1474
|
+
var _iteration$response;
|
|
1475
|
+
const generated = await generateCode({
|
|
1476
|
+
iteration,
|
|
1477
|
+
ctx,
|
|
1478
|
+
cognitive,
|
|
1479
|
+
controller,
|
|
1480
|
+
metadata: props.metadata,
|
|
1481
|
+
onSendDelta: (_iteration$response = iteration.response) === null || _iteration$response === void 0 ? void 0 : _iteration$response.onDelta,
|
|
1482
|
+
onBeforeRequest: props.onBeforeRequest,
|
|
1483
|
+
onToolCalls: (calls) => {
|
|
1484
|
+
var _iteration$response2;
|
|
1485
|
+
if (ctx.chat && !((_iteration$response2 = iteration.response) === null || _iteration$response2 === void 0 ? void 0 : _iteration$response2.onDelta)) return false;
|
|
1486
|
+
const validation = validateNativeToolCalls(calls);
|
|
1487
|
+
const call = validation.valid ? validation.call : void 0;
|
|
1488
|
+
if (!call) return false;
|
|
1489
|
+
if (ctx.session.messages.some((message) => {
|
|
1490
|
+
var _message$toolCalls;
|
|
1491
|
+
return (_message$toolCalls = message.toolCalls) === null || _message$toolCalls === void 0 ? void 0 : _message$toolCalls.some((previous) => previous.id === call.id);
|
|
1492
|
+
})) throw new CognitiveError("Native call IDs must be unique in retained session history.");
|
|
1493
|
+
execution = startJavaScriptCall(state, call);
|
|
1494
|
+
return true;
|
|
1495
|
+
}
|
|
1496
|
+
});
|
|
1497
|
+
await (execution === null || execution === void 0 ? void 0 : execution.result);
|
|
1498
|
+
controller.signal.throwIfAborted();
|
|
1499
|
+
const validation = validateNativeToolCalls(generated.toolCalls);
|
|
1500
|
+
ctx.session.appendAssistant(iteration.id, generated);
|
|
1501
|
+
assistantCommitted = true;
|
|
1502
|
+
if (!validation.valid) {
|
|
1503
|
+
await rejectNativeBatch(state, generated, validation.errors);
|
|
1504
|
+
return;
|
|
1505
|
+
}
|
|
1506
|
+
await deliverAssistantText(state, generated);
|
|
1507
|
+
const call = validation.call;
|
|
1508
|
+
if (call) {
|
|
1509
|
+
execution ??= startJavaScriptCall(state, call);
|
|
1510
|
+
await settleJavaScriptCall(state, execution);
|
|
1511
|
+
}
|
|
1512
|
+
if (iteration.status.type === "pending") await finishNativeResponse(state, generated);
|
|
1513
|
+
} catch (error) {
|
|
1514
|
+
if (execution) await preserveInterruptedExecution(state, execution, error, assistantCommitted);
|
|
1515
|
+
throw error;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
async function rejectNativeBatch({ ctx, iteration }, generated, errors) {
|
|
1519
|
+
var _iteration$response3;
|
|
1520
|
+
const message = [reportSection("error", `Native tool batch rejected before execution:\n${ctx.inspector(errors.join("\n"), {
|
|
1521
|
+
purpose: "error",
|
|
1522
|
+
maxTokens: 500
|
|
1523
|
+
})}`, 500), reportSection("recovery", "No code ran and no actions were performed. Call run_javascript with exactly one non-empty code string.")].join("\n\n");
|
|
1524
|
+
for (const call of generated.toolCalls) ctx.session.appendToolResult(iteration.id, call.id, message);
|
|
1525
|
+
if (generated.output && ((_iteration$response3 = iteration.response) === null || _iteration$response3 === void 0 ? void 0 : _iteration$response3.onDelta)) try {
|
|
1526
|
+
await iteration.response.onDelta({
|
|
1527
|
+
restart: true,
|
|
1528
|
+
iterationId: iteration.id,
|
|
1529
|
+
attempt: generated.attempt + 1,
|
|
1530
|
+
fromModel: generated.metadata.model ?? "unknown",
|
|
1531
|
+
toModel: generated.metadata.model ?? "unknown",
|
|
1532
|
+
reason: message
|
|
1533
|
+
});
|
|
1534
|
+
} catch (error) {
|
|
1535
|
+
throw new CognitiveError(`Could not retract the rejected response: ${getErrorMessage(error)}`);
|
|
1536
|
+
}
|
|
1537
|
+
iteration.end({
|
|
1538
|
+
type: "invalid_code_error",
|
|
1539
|
+
invalid_code_error: { message }
|
|
1540
|
+
}, generated.toolCalls.some((call) => call.name !== "run_javascript") ? new UnknownToolError(generated.toolCalls.find((call) => call.name !== "run_javascript").name, ["run_javascript"], message) : new NativeProtocolError(message));
|
|
1541
|
+
}
|
|
1542
|
+
async function deliverAssistantText(state, generated) {
|
|
1543
|
+
var _iteration$response4;
|
|
1544
|
+
const { ctx, iteration } = state;
|
|
1545
|
+
if (!generated.output.trim() || !ctx.chat || !((_iteration$response4 = iteration.response) === null || _iteration$response4 === void 0 ? void 0 : _iteration$response4.handler)) return;
|
|
1546
|
+
const startedAt = Date.now();
|
|
1547
|
+
const message = {
|
|
1548
|
+
type: "text",
|
|
1549
|
+
text: generated.output
|
|
1550
|
+
};
|
|
1551
|
+
try {
|
|
1552
|
+
await iteration.response.handler(generated.output.trim(), generated.messageMetadata);
|
|
1553
|
+
} catch (cause) {
|
|
1554
|
+
if (isCriticalError(cause)) throw cause;
|
|
1555
|
+
throw new DeliveryError(`Assistant response delivery failed: ${getErrorMessage(cause)}`, { cause });
|
|
1556
|
+
}
|
|
1557
|
+
ctx.session.recordAssistantDelivery(iteration.id);
|
|
1558
|
+
iteration.recordTrace({
|
|
1559
|
+
type: "message_delivery",
|
|
1560
|
+
value: message,
|
|
1561
|
+
started_at: startedAt,
|
|
1562
|
+
ended_at: Date.now()
|
|
1563
|
+
});
|
|
1564
|
+
}
|
|
1565
|
+
function startJavaScriptCall(state, call) {
|
|
1566
|
+
const { iteration, controller } = state;
|
|
1567
|
+
iteration.code = call.code;
|
|
1568
|
+
iteration.nativeCallId = call.id;
|
|
1569
|
+
const api = createJavaScriptApi({
|
|
1570
|
+
iteration,
|
|
1571
|
+
components: iteration.components,
|
|
1572
|
+
exits: iteration.exits,
|
|
1573
|
+
signal: controller.signal,
|
|
1574
|
+
deliver: (messages) => deliverJavaScriptMessages(state, messages),
|
|
1575
|
+
onError: (error) => iteration.recordError(error)
|
|
1576
|
+
});
|
|
1577
|
+
return {
|
|
1578
|
+
call,
|
|
1579
|
+
api,
|
|
1580
|
+
result: executeJavaScript(state, api)
|
|
1581
|
+
};
|
|
1582
|
+
}
|
|
1583
|
+
async function settleJavaScriptCall(state, execution) {
|
|
1584
|
+
const { iteration, controller } = state;
|
|
1585
|
+
const { call, api } = execution;
|
|
1586
|
+
const result = await execution.result;
|
|
1587
|
+
const outcome = result.success && !result.signal ? api.getTerminalOutcome() ?? api.resolve(result.return_value) : void 0;
|
|
1588
|
+
removeCapturedDecisions(result, api);
|
|
1589
|
+
state.capture = {
|
|
1590
|
+
call,
|
|
1591
|
+
result,
|
|
1592
|
+
inspected: (outcome === null || outcome === void 0 ? void 0 : outcome.type) === "inspect"
|
|
1593
|
+
};
|
|
1594
|
+
if ((outcome === null || outcome === void 0 ? void 0 : outcome.type) === "inspect" && result.success) result.return_value = outcome.value;
|
|
1595
|
+
const forcedInspections = api.getForcedInspections();
|
|
1596
|
+
if (forcedInspections.length && !controller.signal.aborted && !isCriticalError(result.error)) {
|
|
1597
|
+
if (!result.success && result.error) {
|
|
1598
|
+
iteration.recordError(result.error);
|
|
1599
|
+
state.capture.downstreamError = result.error;
|
|
1600
|
+
}
|
|
1601
|
+
state.capture.forcedInspections = forcedInspections;
|
|
1602
|
+
let value = forcedInspections.length === 1 ? forcedInspections[0].value : forcedInspections.map((entry) => entry.value);
|
|
1603
|
+
if ((outcome === null || outcome === void 0 ? void 0 : outcome.type) === "inspect") value = outcome.value;
|
|
1604
|
+
state.capture.result = {
|
|
1605
|
+
...result,
|
|
1606
|
+
success: true,
|
|
1607
|
+
signal: void 0,
|
|
1608
|
+
return_value: value
|
|
1609
|
+
};
|
|
1610
|
+
iteration.end({
|
|
1611
|
+
type: "thinking_requested",
|
|
1612
|
+
thinking_requested: {
|
|
1613
|
+
reason: "Tools completed successfully and requested forced inspection.",
|
|
1614
|
+
variables: value,
|
|
1615
|
+
metadata: forcedInspections.length === 1 ? forcedInspections[0].metadata : void 0
|
|
1616
|
+
}
|
|
1617
|
+
});
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
if ((outcome === null || outcome === void 0 ? void 0 : outcome.type) === "exit") {
|
|
1621
|
+
await completeJavaScriptExit(state, result, outcome);
|
|
1622
|
+
return;
|
|
1623
|
+
}
|
|
1624
|
+
if (result.success && containsDecision(result.return_value, api)) {
|
|
1625
|
+
result.captureErrors ??= [];
|
|
1626
|
+
result.captureErrors.push({
|
|
1627
|
+
name: "$return",
|
|
1628
|
+
reason: "Execution decisions cannot be nested inside returned data. Use return inspect(value) with plain values."
|
|
1629
|
+
});
|
|
1630
|
+
}
|
|
1631
|
+
endJavaScriptIteration(iteration, controller, result);
|
|
1632
|
+
}
|
|
1633
|
+
async function preserveInterruptedExecution(state, execution, error, assistantCommitted) {
|
|
1634
|
+
const { ctx, iteration, controller } = state;
|
|
1635
|
+
execution.api.complete();
|
|
1636
|
+
const result = await execution.result;
|
|
1637
|
+
if (state.memory) return;
|
|
1638
|
+
if (!assistantCommitted) ctx.session.appendAssistant(iteration.id, {
|
|
1639
|
+
output: "",
|
|
1640
|
+
toolCalls: [{
|
|
1641
|
+
id: execution.call.id,
|
|
1642
|
+
name: "run_javascript",
|
|
1643
|
+
input: { code: execution.call.code }
|
|
1644
|
+
}]
|
|
1645
|
+
});
|
|
1646
|
+
removeCapturedDecisions(result, execution.api);
|
|
1647
|
+
if (iteration.status.type === "pending") endFailedIteration(iteration, controller, error);
|
|
1648
|
+
const interrupted = {
|
|
1649
|
+
...result,
|
|
1650
|
+
success: false,
|
|
1651
|
+
signal: void 0,
|
|
1652
|
+
error: error instanceof Error ? error : new Error(getErrorMessage(error)),
|
|
1653
|
+
traces: []
|
|
1654
|
+
};
|
|
1655
|
+
state.capture = {
|
|
1656
|
+
call: execution.call,
|
|
1657
|
+
result: interrupted,
|
|
1658
|
+
inspected: false,
|
|
1659
|
+
interrupted: true
|
|
1660
|
+
};
|
|
1661
|
+
}
|
|
1662
|
+
function removeCapturedDecisions(result, api) {
|
|
1663
|
+
for (const [name, value] of Object.entries(result.variables)) if (containsDecision(value, api)) {
|
|
1664
|
+
delete result.variables[name];
|
|
1665
|
+
result.captureErrors ??= [];
|
|
1666
|
+
result.captureErrors.push({
|
|
1667
|
+
name,
|
|
1668
|
+
reason: "Execution decisions cannot be retained as memory variables."
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
function containsDecision(value, api, seen = /* @__PURE__ */ new Set()) {
|
|
1673
|
+
if (api.isReceipt(value)) return true;
|
|
1674
|
+
if (value === null || typeof value !== "object" || seen.has(value)) return false;
|
|
1675
|
+
seen.add(value);
|
|
1676
|
+
return Object.values(value).some((nested) => containsDecision(nested, api, seen));
|
|
1677
|
+
}
|
|
1678
|
+
async function completeJavaScriptExit(state, result, outcome) {
|
|
1679
|
+
const { iteration, controller } = state;
|
|
1680
|
+
state.memory = commitMemory(state, result, false);
|
|
1681
|
+
try {
|
|
1682
|
+
controller.signal.throwIfAborted();
|
|
1683
|
+
await applyNativeExit(state, outcome.exit, outcome.value);
|
|
1684
|
+
} catch (error) {
|
|
1685
|
+
endFailedIteration(iteration, controller, error);
|
|
1686
|
+
}
|
|
1687
|
+
}
|
|
1688
|
+
async function deliverJavaScriptMessages({ ctx, iteration, controller }, messages) {
|
|
1689
|
+
if (!messages.length) return;
|
|
1690
|
+
if (!ctx.chat) throw new DeliveryError("Component delivery requires chat mode.");
|
|
1691
|
+
for (const message of messages) {
|
|
1692
|
+
controller.signal.throwIfAborted();
|
|
1693
|
+
const startedAt = Date.now();
|
|
1694
|
+
try {
|
|
1695
|
+
if (!isAnyComponent(message.component)) throw new DeliveryError("Only registered rich components can be delivered from JavaScript.");
|
|
1696
|
+
const component = iteration.components.get(message.component.name);
|
|
1697
|
+
if (!(component === null || component === void 0 ? void 0 : component.handler)) throw new DeliveryError(`Component "${message.component.name}" has no registered handler.`);
|
|
1698
|
+
await component.handler(message.component.props, {
|
|
1699
|
+
iterationId: iteration.id,
|
|
1700
|
+
id: message.id
|
|
1701
|
+
});
|
|
1702
|
+
} catch (error) {
|
|
1703
|
+
iteration.recordTrace({
|
|
1704
|
+
type: "message_delivery",
|
|
1705
|
+
value: message.component,
|
|
1706
|
+
message_id: message.id,
|
|
1707
|
+
native_call_id: iteration.nativeCallId,
|
|
1708
|
+
success: false,
|
|
1709
|
+
error: getErrorMessage(error),
|
|
1710
|
+
started_at: startedAt,
|
|
1711
|
+
ended_at: Date.now()
|
|
1712
|
+
});
|
|
1713
|
+
throw isCriticalError(error) ? error : new DeliveryError(`Delivery ${message.id} failed: ${getErrorMessage(error)}. Its external outcome is uncertain. Later messages were skipped; earlier acknowledged messages remain delivered.`, { cause: error });
|
|
1714
|
+
}
|
|
1715
|
+
ctx.session.recordAssistantDelivery(iteration.id);
|
|
1716
|
+
iteration.recordTrace({
|
|
1717
|
+
type: "message_delivery",
|
|
1718
|
+
value: message.component,
|
|
1719
|
+
message_id: message.id,
|
|
1720
|
+
native_call_id: iteration.nativeCallId,
|
|
1721
|
+
success: true,
|
|
1722
|
+
started_at: startedAt,
|
|
1723
|
+
ended_at: Date.now()
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
async function finishNativeResponse(state, generated) {
|
|
1728
|
+
const { ctx, iteration } = state;
|
|
1729
|
+
if (!generated.toolCalls.length && ctx.chat && (generated.output.trim() || generated.metadata.stopReason === "stop")) {
|
|
1730
|
+
await applyNativeExit(state, ListenExit, {});
|
|
1731
|
+
if (!iteration.hasExited()) ctx.session.appendContext(ctx.inspector(iteration.error ?? "Completion rejected.", {
|
|
1732
|
+
purpose: "error",
|
|
1733
|
+
maxTokens: 200
|
|
1734
|
+
}));
|
|
1735
|
+
return;
|
|
1736
|
+
}
|
|
1737
|
+
let reason = iteration.exits.length ? "This is a worker task. Every run_javascript program must explicitly return inspect(value) or return exit(name, payload) with a registered name and a valid payload. Assistant prose alone does not complete the task." : "Every run_javascript program must explicitly return inspect(value). To see a business tool result in the next response, return inspect(result).";
|
|
1738
|
+
if (ctx.chat) reason = generated.toolCalls.length ? "Every run_javascript program must explicitly return inspect(value) or return exit(name, payload). Use return exit(\"listen\") to wait for the user." : "Reply with assistant text, or use run_javascript with an explicit return inspect(value) or return exit(name, payload). Use return exit(\"listen\") to wait for the user.";
|
|
1739
|
+
if (!ctx.chat) reason = `${WORKER_RESPONSE_INSTRUCTION} ${reason}`;
|
|
1740
|
+
iteration.end({
|
|
1741
|
+
type: "thinking_requested",
|
|
1742
|
+
thinking_requested: {
|
|
1743
|
+
reason,
|
|
1744
|
+
variables: {}
|
|
1745
|
+
}
|
|
1746
|
+
});
|
|
1747
|
+
if (!generated.toolCalls.length) ctx.session.appendContext(reason);
|
|
1748
|
+
}
|
|
1749
|
+
function commitMemory(state, result, includeReturn = true) {
|
|
1750
|
+
const { ctx, iteration, controller } = state;
|
|
1751
|
+
const report = ctx.session.commitIteration({
|
|
1752
|
+
...iteration.sessionInfo,
|
|
1753
|
+
timestamp: Date.now(),
|
|
1754
|
+
variables: result === null || result === void 0 ? void 0 : result.variables,
|
|
1755
|
+
variableWrites: result === null || result === void 0 ? void 0 : result.variableWrites,
|
|
1756
|
+
captureErrors: result === null || result === void 0 ? void 0 : result.captureErrors,
|
|
1757
|
+
hasResult: includeReturn && !!(result === null || result === void 0 ? void 0 : result.success) && !result.signal && !controller.signal.aborted,
|
|
1758
|
+
result: (result === null || result === void 0 ? void 0 : result.success) ? result.return_value : void 0
|
|
1759
|
+
});
|
|
1760
|
+
state.memory = report;
|
|
1761
|
+
for (const mutation of iteration.mutations) {
|
|
1762
|
+
const trace = [...iteration.traces].reverse().find((trace) => trace.type === "property" && trace.object === mutation.object && trace.property === mutation.property);
|
|
1763
|
+
const changes = ctx.session.memory.recordObjectMutations([mutation], {
|
|
1764
|
+
...iteration.sessionInfo,
|
|
1765
|
+
timestamp: (trace === null || trace === void 0 ? void 0 : trace.started_at) ?? Date.now()
|
|
1766
|
+
});
|
|
1767
|
+
report.updated.push(...changes);
|
|
1768
|
+
}
|
|
1769
|
+
return report;
|
|
1770
|
+
}
|
|
1771
|
+
function failFinalization(state, error) {
|
|
1772
|
+
const { iteration } = state;
|
|
1773
|
+
iteration.status = {
|
|
1774
|
+
type: "execution_error",
|
|
1775
|
+
execution_error: {
|
|
1776
|
+
message: getErrorMessage(error),
|
|
1777
|
+
stack: executionErrorStack(error)
|
|
1778
|
+
}
|
|
1779
|
+
};
|
|
1780
|
+
iteration.ended_ts = Date.now();
|
|
1781
|
+
iteration.exception = iteration.recordError(error);
|
|
1782
|
+
state.terminalError = error;
|
|
1783
|
+
state.memory ??= {
|
|
1784
|
+
created: [],
|
|
1785
|
+
updated: [],
|
|
1786
|
+
unavailable: [],
|
|
1787
|
+
resultAvailable: false
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
function getExecutionOutcome(state, memory) {
|
|
1791
|
+
const { iteration, capture } = state;
|
|
1792
|
+
const status = iteration.status;
|
|
1793
|
+
if (status.type === "aborted") return {
|
|
1794
|
+
type: "cancelled",
|
|
1795
|
+
message: status.aborted.reason
|
|
1796
|
+
};
|
|
1797
|
+
if (capture === null || capture === void 0 ? void 0 : capture.interrupted) return {
|
|
1798
|
+
type: "interrupted",
|
|
1799
|
+
reason: "stream",
|
|
1800
|
+
message: iteration.error ?? void 0
|
|
1801
|
+
};
|
|
1802
|
+
if (status.type === "exit_success") return {
|
|
1803
|
+
type: "exit",
|
|
1804
|
+
name: status.exit_success.exit_name,
|
|
1805
|
+
value: status.exit_success.return_value
|
|
1806
|
+
};
|
|
1807
|
+
if (status.type === "exit_error") return {
|
|
1808
|
+
type: "error",
|
|
1809
|
+
exitName: status.exit_error.exit,
|
|
1810
|
+
message: status.exit_error.message,
|
|
1811
|
+
error: iteration.exception
|
|
1812
|
+
};
|
|
1813
|
+
if (status.type === "thinking_requested") {
|
|
1814
|
+
const thinking = status.thinking_requested;
|
|
1815
|
+
if (thinking.interrupted) {
|
|
1816
|
+
var _capture$result$signa;
|
|
1817
|
+
return {
|
|
1818
|
+
type: "interrupted",
|
|
1819
|
+
reason: "thinking",
|
|
1820
|
+
message: thinking.reason,
|
|
1821
|
+
context: thinking.variables,
|
|
1822
|
+
stacktrace: capture === null || capture === void 0 || (_capture$result$signa = capture.result.signal) === null || _capture$result$signa === void 0 ? void 0 : _capture$result$signa.stack
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
return {
|
|
1826
|
+
type: "inspect",
|
|
1827
|
+
value: (capture === null || capture === void 0 ? void 0 : capture.result.success) ? capture.result.return_value : void 0,
|
|
1828
|
+
available: memory.resultAvailable,
|
|
1829
|
+
explicit: (capture === null || capture === void 0 ? void 0 : capture.inspected) ?? false,
|
|
1830
|
+
forcedInspections: capture === null || capture === void 0 ? void 0 : capture.forcedInspections,
|
|
1831
|
+
downstreamError: capture === null || capture === void 0 ? void 0 : capture.downstreamError
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
return {
|
|
1835
|
+
type: "error",
|
|
1836
|
+
message: iteration.error ?? "Execution failed.",
|
|
1837
|
+
error: iteration.exception ?? (capture === null || capture === void 0 ? void 0 : capture.result.error)
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
function handleIterationFailure(state, error) {
|
|
1841
|
+
const { ctx, iteration, controller } = state;
|
|
1842
|
+
if (iteration.status.type === "pending") endFailedIteration(iteration, controller, error);
|
|
1843
|
+
if (MemoryCapacityError.is(error)) state.memory ??= {
|
|
1844
|
+
created: [],
|
|
1845
|
+
updated: [],
|
|
1846
|
+
unavailable: [],
|
|
1847
|
+
resultAvailable: false
|
|
1848
|
+
};
|
|
1849
|
+
const pending = ctx.session.pendingCalls.filter((call) => call.iterationId === iteration.id);
|
|
1850
|
+
for (const call of pending) {
|
|
1851
|
+
var _state$capture2;
|
|
1852
|
+
if (call.callId === ((_state$capture2 = state.capture) === null || _state$capture2 === void 0 ? void 0 : _state$capture2.call.id)) continue;
|
|
1853
|
+
const outcome = call.callId === iteration.nativeCallId ? "This call failed without a confirmed successful result; its external effects may be incomplete." : "This call was skipped and did not run.";
|
|
1854
|
+
ctx.session.appendToolResult(iteration.id, call.callId, `Execution stopped: ${ctx.inspector(getErrorMessage(error), {
|
|
1855
|
+
purpose: "error",
|
|
1856
|
+
maxTokens: 200
|
|
1857
|
+
})}. ${outcome} Earlier acknowledged calls remain completed.`);
|
|
1858
|
+
}
|
|
1859
|
+
if (isCriticalError(error) || controller.signal.aborted) {
|
|
1860
|
+
state.terminalError = controller.signal.aborted ? new ExecutionAbortedError(getErrorMessage(controller.signal.reason ?? error), { cause: controller.signal.reason ?? error }) : error;
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
if (ctx.session.pendingCalls.length) return;
|
|
1864
|
+
ctx.session.appendContext(`Execution stopped: ${ctx.inspector(getErrorMessage(error), {
|
|
1865
|
+
purpose: "error",
|
|
1866
|
+
maxTokens: 200
|
|
1867
|
+
})}. Continue using the retained state.`);
|
|
1868
|
+
}
|
|
1869
|
+
function endFailedIteration(iteration, controller, error) {
|
|
1870
|
+
if (controller.signal.aborted) {
|
|
1871
|
+
iteration.end({
|
|
1872
|
+
type: "aborted",
|
|
1873
|
+
aborted: { reason: getErrorMessage(controller.signal.reason ?? error) }
|
|
1874
|
+
}, new ExecutionAbortedError(getErrorMessage(controller.signal.reason ?? error), { cause: controller.signal.reason ?? error }));
|
|
1875
|
+
return;
|
|
1876
|
+
}
|
|
1877
|
+
if (CognitiveError.is(error) || TokenOverflowError.is(error) || CompactionError.is(error)) {
|
|
1878
|
+
iteration.end({
|
|
1879
|
+
type: "generation_error",
|
|
1880
|
+
generation_error: { message: error.message }
|
|
1881
|
+
}, error);
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
if (ThinkSignal.is(error)) {
|
|
1885
|
+
iteration.end({
|
|
1886
|
+
type: "thinking_requested",
|
|
1887
|
+
thinking_requested: {
|
|
1888
|
+
reason: error.reason,
|
|
1889
|
+
variables: error.context,
|
|
1890
|
+
interrupted: true
|
|
1891
|
+
}
|
|
1892
|
+
});
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
iteration.end({
|
|
1896
|
+
type: "execution_error",
|
|
1897
|
+
execution_error: {
|
|
1898
|
+
message: getErrorMessage(error),
|
|
1899
|
+
stack: executionErrorStack(error)
|
|
1900
|
+
}
|
|
1901
|
+
}, error);
|
|
1902
|
+
}
|
|
1903
|
+
function executionErrorStack(error) {
|
|
1904
|
+
if (CodeExecutionError.is(error) && error.stacktrace) return error.stacktrace;
|
|
1905
|
+
if (HookError.is(error) && error.cause instanceof Error) return cleanStackTrace(error.cause.stack ?? "");
|
|
1906
|
+
if (error instanceof Error) return cleanStackTrace(error.stack ?? "");
|
|
1907
|
+
return "";
|
|
1908
|
+
}
|
|
1909
|
+
function getIterationResult(state) {
|
|
1910
|
+
const { ctx, iteration } = state;
|
|
1911
|
+
const critical = iteration.errors.find(isCriticalError);
|
|
1912
|
+
state.terminalError ??= critical;
|
|
1913
|
+
if (state.terminalError !== void 0) return new ErrorExecutionResult(ctx, state.terminalError);
|
|
1914
|
+
if (iteration.status.type === "exit_success") {
|
|
1915
|
+
const outcome = iteration.status.exit_success;
|
|
1916
|
+
return new SuccessExecutionResult(ctx, {
|
|
1917
|
+
exit: iteration.exits.find((exit) => exit.name === outcome.exit_name),
|
|
1918
|
+
result: outcome.return_value
|
|
1919
|
+
});
|
|
1920
|
+
}
|
|
1921
|
+
if (iteration.status.type === "aborted") return new ErrorExecutionResult(ctx, iteration.error);
|
|
1922
|
+
}
|
|
1923
|
+
async function applyNativeExit(state, exit, value) {
|
|
1924
|
+
const { ctx, iteration, controller, props } = state;
|
|
1925
|
+
try {
|
|
1926
|
+
var _props$options9;
|
|
1927
|
+
if (ctx.chat && exit === ListenExit && ((_props$options9 = props.options) === null || _props$options9 === void 0 ? void 0 : _props$options9.requireChatResponse) !== false && ctx.session.lastSpeaker !== "assistant") throw new 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.");
|
|
1928
|
+
await callHook(() => {
|
|
1929
|
+
var _props$onExit;
|
|
1930
|
+
return (_props$onExit = props.onExit) === null || _props$onExit === void 0 ? void 0 : _props$onExit.call(props, {
|
|
1931
|
+
exit,
|
|
1932
|
+
result: value
|
|
1933
|
+
}, controller);
|
|
1934
|
+
});
|
|
1935
|
+
controller.signal.throwIfAborted();
|
|
1936
|
+
iteration.end({
|
|
1937
|
+
type: "exit_success",
|
|
1938
|
+
exit_success: {
|
|
1939
|
+
exit_name: exit.name,
|
|
1940
|
+
return_value: value
|
|
1941
|
+
}
|
|
1942
|
+
});
|
|
1943
|
+
} catch (error) {
|
|
1944
|
+
if (controller.signal.aborted) throw error;
|
|
1945
|
+
iteration.end({
|
|
1946
|
+
type: "exit_error",
|
|
1947
|
+
exit_error: {
|
|
1948
|
+
exit: exit.name,
|
|
1949
|
+
message: getErrorMessage(error),
|
|
1950
|
+
return_value: value
|
|
1951
|
+
}
|
|
1952
|
+
}, error);
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
async function executeJavaScript(state, api) {
|
|
1956
|
+
const { iteration, ctx, controller, props } = state;
|
|
1957
|
+
const startedAt = Date.now();
|
|
1958
|
+
let result;
|
|
1959
|
+
try {
|
|
1960
|
+
const override = await callHook(() => {
|
|
1961
|
+
var _props$onBeforeExecut;
|
|
1962
|
+
return (_props$onBeforeExecut = props.onBeforeExecution) === null || _props$onBeforeExecut === void 0 ? void 0 : _props$onBeforeExecut.call(props, iteration, controller);
|
|
1963
|
+
});
|
|
1964
|
+
if (typeof (override === null || override === void 0 ? void 0 : override.code) === "string") iteration.code = override.code;
|
|
1965
|
+
controller.signal.throwIfAborted();
|
|
1966
|
+
const code = iteration.code;
|
|
1967
|
+
ctx.session.memory.assertNamesAvailable(compile(code).variables);
|
|
1968
|
+
const vmContext = buildVMContext({
|
|
1969
|
+
ctx,
|
|
1970
|
+
iteration,
|
|
1971
|
+
controller,
|
|
1972
|
+
onBeforeTool: props.onBeforeTool,
|
|
1973
|
+
onAfterTool: props.onAfterTool,
|
|
1974
|
+
onTruncation: (value, policy) => state.inspectionValues.capture(value, policy),
|
|
1975
|
+
onToolResult: (value) => state.inspectionValues.captureDefault(value, ctx.toolResultMaxTokens),
|
|
1976
|
+
javascriptApi: api
|
|
1977
|
+
});
|
|
1978
|
+
result = await runAsyncFunction(vmContext, code, iteration.traces, controller.signal, ctx.timeout, Object.keys(ctx.session.memory.variables), iteration.recordTrace);
|
|
1979
|
+
} catch (error) {
|
|
1980
|
+
result = interruptedVMResult(error);
|
|
1981
|
+
}
|
|
1982
|
+
try {
|
|
1983
|
+
await api.close();
|
|
1984
|
+
} catch (error) {
|
|
1985
|
+
result = {
|
|
1986
|
+
...result,
|
|
1987
|
+
success: !!result.signal,
|
|
1988
|
+
error: error instanceof Error ? error : new Error(getErrorMessage(error)),
|
|
1989
|
+
traces: []
|
|
1990
|
+
};
|
|
1991
|
+
}
|
|
1992
|
+
const interruption = api.getInterruption();
|
|
1993
|
+
if (interruption && !result.signal) {
|
|
1994
|
+
interruption.variables = result.variables;
|
|
1995
|
+
result = {
|
|
1996
|
+
...result,
|
|
1997
|
+
success: true,
|
|
1998
|
+
signal: interruption,
|
|
1999
|
+
error: void 0,
|
|
2000
|
+
return_value: void 0
|
|
2001
|
+
};
|
|
2002
|
+
}
|
|
2003
|
+
iteration.recordTrace({
|
|
2004
|
+
type: "code_execution",
|
|
2005
|
+
lines_executed: result.lines_executed,
|
|
2006
|
+
started_at: startedAt,
|
|
2007
|
+
ended_at: Date.now()
|
|
2008
|
+
});
|
|
2009
|
+
return result;
|
|
2010
|
+
}
|
|
2011
|
+
function interruptedVMResult(error) {
|
|
2012
|
+
if (ThinkSignal.is(error)) return {
|
|
2013
|
+
success: true,
|
|
2014
|
+
signal: error,
|
|
2015
|
+
return_value: void 0,
|
|
2016
|
+
variables: {},
|
|
2017
|
+
lines_executed: []
|
|
2018
|
+
};
|
|
2019
|
+
return {
|
|
2020
|
+
success: false,
|
|
2021
|
+
error: error instanceof Error ? error : new Error(getErrorMessage(error)),
|
|
2022
|
+
variables: {},
|
|
2023
|
+
lines_executed: [],
|
|
2024
|
+
traces: []
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
2027
|
+
function endJavaScriptIteration(iteration, controller, result) {
|
|
2028
|
+
if (controller.signal.aborted) {
|
|
2029
|
+
endFailedIteration(iteration, controller, controller.signal.reason);
|
|
2030
|
+
return;
|
|
2031
|
+
}
|
|
2032
|
+
if (!result.success) {
|
|
2033
|
+
if (InvalidCodeError.is(result.error)) iteration.end({
|
|
2034
|
+
type: "invalid_code_error",
|
|
2035
|
+
invalid_code_error: { message: result.error.message }
|
|
2036
|
+
}, result.error);
|
|
2037
|
+
else endFailedIteration(iteration, controller, result.error);
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
if (ThinkSignal.is(result.signal)) {
|
|
2041
|
+
iteration.end({
|
|
2042
|
+
type: "thinking_requested",
|
|
2043
|
+
thinking_requested: {
|
|
2044
|
+
reason: result.signal.reason,
|
|
2045
|
+
variables: result.signal.context,
|
|
2046
|
+
metadata: result.signal.metadata,
|
|
2047
|
+
interrupted: true
|
|
2048
|
+
}
|
|
2049
|
+
});
|
|
2050
|
+
return;
|
|
2051
|
+
}
|
|
2052
|
+
iteration.end({
|
|
2053
|
+
type: "thinking_requested",
|
|
2054
|
+
thinking_requested: {
|
|
2055
|
+
reason: "JavaScript completed. Inspect the return value and memory changes.",
|
|
2056
|
+
variables: {}
|
|
2057
|
+
}
|
|
2058
|
+
});
|
|
2059
|
+
}
|
|
2060
|
+
//#endregion
|
|
2061
|
+
export { executeContext };
|