llmz 0.6.0 → 0.6.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 +1 -3
- package/dist/_baseForOwn-CFhWe_W6.js +48 -0
- package/dist/_baseForOwn-buOZDFbK.cjs +103 -0
- package/dist/_baseIteratee-CF4qP2a8.cjs +2377 -0
- package/dist/_baseIteratee-P_firB7b.js +2138 -0
- package/dist/_getPrototype-CG7Dxrrz.js +6 -0
- package/dist/_getPrototype-DQDlNVVM.cjs +10 -0
- package/dist/_overArg-C5Hy7oCi.cjs +196 -0
- package/dist/_overArg-CRYbj1NH.js +155 -0
- package/dist/citations.d.ts +11 -11
- package/dist/component-BwixNVH8.cjs +73 -0
- package/dist/component-DGG7d_Mz.js +44 -0
- package/dist/context.d.ts +8 -8
- package/dist/custom-client-BPmEoWKu.cjs +2618 -0
- package/dist/custom-client-NUoxrFQh.js +2547 -0
- package/dist/dual-modes-D_p-jedw.js +2750 -0
- package/dist/dual-modes-wAOAlaBS.cjs +2840 -0
- package/dist/errors-C962uJdS.cjs +220 -0
- package/dist/errors-Cg1G0Awu.js +161 -0
- package/dist/execute-BEaq3jkV.cjs +1003 -0
- package/dist/execute-DYvFRs54.js +1001 -0
- package/dist/exit-BGi0Kk0y.cjs +428 -0
- package/dist/exit-CDdxDBRT.js +417 -0
- package/dist/index.cjs +1786 -1489
- package/dist/index.d.ts +10 -9
- package/dist/index.js +1721 -1479
- package/dist/index.workerd.js +17534 -16875
- package/dist/isEmpty-BhJRCqIF.js +52 -0
- package/dist/isEmpty-LY533Wmh.cjs +57 -0
- package/dist/isPlainObject-CSxXVKCk.cjs +56 -0
- package/dist/isPlainObject-D39AzPO2.js +51 -0
- package/dist/jsx-BWvT6ukg.cjs +75 -0
- package/dist/jsx-CIgdGGVs.js +52 -0
- package/dist/jsx.d.ts +2 -2
- package/dist/prompts/chat-mode/system.md.d.ts +1 -1
- package/dist/prompts/chat-mode/user.md.d.ts +1 -1
- package/dist/prompts/worker-mode/system.md.d.ts +1 -1
- package/dist/prompts/worker-mode/user.md.d.ts +1 -1
- package/dist/quickjs-variant-BYhMBpwU.js +45 -0
- package/dist/quickjs-variant-CsIwTVFC.cjs +56 -0
- package/dist/quickjs-variant.workerd.d.ts +1 -1
- package/dist/result.d.ts +12 -12
- package/dist/rolldown-runtime-EAsCxrDo.js +14 -0
- package/dist/runtime/interpret-result.d.ts +1 -1
- package/dist/snapshots.d.ts +5 -5
- package/dist/stack-traces-BIE_5Xwf.js +21 -0
- package/dist/stack-traces-ntw_qhoy.cjs +26 -0
- package/dist/tool-CAo-BQHs.js +643 -0
- package/dist/tool-DdPZb0JW.cjs +654 -0
- package/dist/tool.d.ts +3 -3
- package/dist/truncator-B6aaJaN1.cjs +276 -0
- package/dist/truncator-DZqEqnpD.js +253 -0
- package/dist/typings-BwAz_TM9.cjs +784 -0
- package/dist/typings-CrBa7Tyy.js +743 -0
- package/dist/uniq-BYQ7GWwb.js +183 -0
- package/dist/uniq-G872RWmE.cjs +200 -0
- package/dist/utils-UBeAFeEI.js +950 -0
- package/dist/utils-ZpJm00ed.cjs +1075 -0
- package/dist/vm/errors.d.ts +2 -2
- package/dist/vm-BjkJqSQH.cjs +3438 -0
- package/dist/vm-C5vf1LH3.js +3436 -0
- package/package.json +7 -7
- package/dist/chunk-34GJUS6U.js +0 -3266
- package/dist/chunk-3UZKLXAD.cjs +0 -3249
- package/dist/chunk-4POZJQXN.js +0 -1530
- package/dist/chunk-5WBNTV42.cjs +0 -1530
- package/dist/chunk-5ZF6NTYI.cjs +0 -33
- package/dist/chunk-72ZWBNZV.js +0 -173
- package/dist/chunk-DDSJTR6Q.cjs +0 -257
- package/dist/chunk-GDJTKI7J.js +0 -792
- package/dist/chunk-GLXADNTR.js +0 -199
- package/dist/chunk-GOWPACSK.cjs +0 -199
- package/dist/chunk-HB2G32AK.js +0 -257
- package/dist/chunk-HC2QZTVT.cjs +0 -3266
- package/dist/chunk-HEAQAEFZ.cjs +0 -173
- package/dist/chunk-HMMM32RG.cjs +0 -792
- package/dist/chunk-I56MPOVG.cjs +0 -62
- package/dist/chunk-KIN7Y247.cjs +0 -32
- package/dist/chunk-KTDBAJBB.cjs +0 -1685
- package/dist/chunk-KWQTYXAT.js +0 -62
- package/dist/chunk-LOX7GOR6.js +0 -1685
- package/dist/chunk-PK72FAKD.cjs +0 -175
- package/dist/chunk-PZE6PIPG.cjs +0 -621
- package/dist/chunk-RGUG3UMF.cjs +0 -26
- package/dist/chunk-TDALRNGL.js +0 -621
- package/dist/chunk-UGHFNCPD.js +0 -26
- package/dist/chunk-WSVDMGMR.js +0 -175
- package/dist/chunk-XTEHT2TK.js +0 -33
- package/dist/chunk-YEAWWJSJ.js +0 -32
- package/dist/chunk-YRS7KRKP.js +0 -3249
- package/dist/component-2NYFY6CW.cjs +0 -14
- package/dist/component-ASNZHQUR.js +0 -14
- package/dist/dual-modes-S5TJ5JVJ.js +0 -10
- package/dist/dual-modes-TCMWBZIH.cjs +0 -10
- package/dist/execute-FF7D46TY.js +0 -1109
- package/dist/execute-IK6O4SU2.cjs +0 -1109
- package/dist/exit-MX56VN2C.cjs +0 -8
- package/dist/exit-UQ3EUX5D.js +0 -8
- package/dist/jsx-DDZ63UUF.js +0 -13
- package/dist/jsx-ULPWX5TW.cjs +0 -13
- package/dist/tool-KD7FL45V.js +0 -11
- package/dist/tool-VE2YHIY2.cjs +0 -11
- package/dist/truncator-73RCL52Y.js +0 -12
- package/dist/truncator-FZNLYSDL.cjs +0 -12
- package/dist/typings-E2RROCLT.js +0 -10
- package/dist/typings-LQOBZXSO.cjs +0 -10
- package/dist/utils-IATCUNKF.js +0 -43
- package/dist/utils-ITB4NEL7.cjs +0 -43
- package/dist/vm-6D3IIIU7.cjs +0 -12
- package/dist/vm-QO5FSGPN.js +0 -12
|
@@ -0,0 +1,1001 @@
|
|
|
1
|
+
import { a as StreamingMessageParser, d as isEqual, h as toNumber, i as toParsedAssistantResponse } from "./dual-modes-D_p-jedw.js";
|
|
2
|
+
import { d as Snapshot, f as parseExit, l as PartialExecutionResult, n as Context, s as ErrorExecutionResult, t as _CustomModelClient, u as SuccessExecutionResult } from "./custom-client-NUoxrFQh.js";
|
|
3
|
+
import { d as stripInvalidIdentifiers, i as getErrorMessage, s as init } from "./utils-UBeAFeEI.js";
|
|
4
|
+
import { t as createJsxComponent } from "./jsx-CIgdGGVs.js";
|
|
5
|
+
import { t as cleanStackTrace } from "./stack-traces-BIE_5Xwf.js";
|
|
6
|
+
import { a as InvalidCodeError, c as SnapshotSignal, i as CognitiveError, l as ThinkSignal, n as CodeExecutionError, o as LoopExceededError, s as Signals, t as AssignmentError } from "./errors-Cg1G0Awu.js";
|
|
7
|
+
import { n as truncateWrappedContent } from "./truncator-DZqEqnpD.js";
|
|
8
|
+
import { runAsyncFunction, t as hasTopLevelReturn, warmupVM } from "./vm-C5vf1LH3.js";
|
|
9
|
+
import { z } from "@bpinternal/zui";
|
|
10
|
+
import { ulid } from "ulid";
|
|
11
|
+
import { Client } from "@botpress/client";
|
|
12
|
+
import { Cognitive } from "@botpress/cognitive";
|
|
13
|
+
import ms from "ms";
|
|
14
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_baseClamp.js
|
|
15
|
+
/**
|
|
16
|
+
* The base implementation of `_.clamp` which doesn't coerce arguments.
|
|
17
|
+
*
|
|
18
|
+
* @private
|
|
19
|
+
* @param {number} number The number to clamp.
|
|
20
|
+
* @param {number} [lower] The lower bound.
|
|
21
|
+
* @param {number} upper The upper bound.
|
|
22
|
+
* @returns {number} Returns the clamped number.
|
|
23
|
+
*/
|
|
24
|
+
function baseClamp(number, lower, upper) {
|
|
25
|
+
if (number === number) {
|
|
26
|
+
if (upper !== void 0) number = number <= upper ? number : upper;
|
|
27
|
+
if (lower !== void 0) number = number >= lower ? number : lower;
|
|
28
|
+
}
|
|
29
|
+
return number;
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/clamp.js
|
|
33
|
+
/**
|
|
34
|
+
* Clamps `number` within the inclusive `lower` and `upper` bounds.
|
|
35
|
+
*
|
|
36
|
+
* @static
|
|
37
|
+
* @memberOf _
|
|
38
|
+
* @since 4.0.0
|
|
39
|
+
* @category Number
|
|
40
|
+
* @param {number} number The number to clamp.
|
|
41
|
+
* @param {number} [lower] The lower bound.
|
|
42
|
+
* @param {number} upper The upper bound.
|
|
43
|
+
* @returns {number} Returns the clamped number.
|
|
44
|
+
* @example
|
|
45
|
+
*
|
|
46
|
+
* _.clamp(-10, -5, 5);
|
|
47
|
+
* // => -5
|
|
48
|
+
*
|
|
49
|
+
* _.clamp(10, -5, 5);
|
|
50
|
+
* // => 5
|
|
51
|
+
*/
|
|
52
|
+
function clamp(number, lower, upper) {
|
|
53
|
+
if (upper === void 0) {
|
|
54
|
+
upper = lower;
|
|
55
|
+
lower = void 0;
|
|
56
|
+
}
|
|
57
|
+
if (upper !== void 0) {
|
|
58
|
+
upper = toNumber(upper);
|
|
59
|
+
upper = upper === upper ? upper : 0;
|
|
60
|
+
}
|
|
61
|
+
if (lower !== void 0) {
|
|
62
|
+
lower = toNumber(lower);
|
|
63
|
+
lower = lower === lower ? lower : 0;
|
|
64
|
+
}
|
|
65
|
+
return baseClamp(toNumber(number), lower, upper);
|
|
66
|
+
}
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/abort-signal.ts
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new AbortController that aborts when any of the provided signals abort.
|
|
71
|
+
* This is useful for combining multiple abort conditions (e.g., user cancellation, timeout, parent operation abort).
|
|
72
|
+
*
|
|
73
|
+
* @param signals - Array of AbortSignals to listen to. Undefined/null signals are ignored.
|
|
74
|
+
* @returns A new AbortController that will abort if any input signal aborts
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const userController = new AbortController()
|
|
79
|
+
* const timeoutController = new AbortController()
|
|
80
|
+
*
|
|
81
|
+
* // Create a joined controller that aborts if either signal aborts
|
|
82
|
+
* const joinedController = createJoinedAbortController([
|
|
83
|
+
* userController.signal,
|
|
84
|
+
* timeoutController.signal
|
|
85
|
+
* ])
|
|
86
|
+
*
|
|
87
|
+
* // Use the joined signal in operations
|
|
88
|
+
* await fetch('/api/data', { signal: joinedController.signal })
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
function createJoinedAbortController(signals) {
|
|
92
|
+
const controller = new AbortController();
|
|
93
|
+
const validSignals = signals.filter((signal) => signal != null);
|
|
94
|
+
if (validSignals.length === 0) return controller;
|
|
95
|
+
for (const signal of validSignals) if (signal.aborted) {
|
|
96
|
+
controller.abort(signal.reason);
|
|
97
|
+
return controller;
|
|
98
|
+
}
|
|
99
|
+
const abortListeners = [];
|
|
100
|
+
for (const signal of validSignals) {
|
|
101
|
+
const listener = () => {
|
|
102
|
+
controller.abort(signal.reason);
|
|
103
|
+
cleanup();
|
|
104
|
+
};
|
|
105
|
+
signal.addEventListener("abort", listener);
|
|
106
|
+
abortListeners.push(() => signal.removeEventListener("abort", listener));
|
|
107
|
+
}
|
|
108
|
+
const cleanup = () => {
|
|
109
|
+
abortListeners.forEach((removeListener) => removeListener());
|
|
110
|
+
};
|
|
111
|
+
controller.signal.addEventListener("abort", cleanup, { once: true });
|
|
112
|
+
return controller;
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/runtime/generate.ts
|
|
116
|
+
const RESPONSE_LENGTH_BUFFER = {
|
|
117
|
+
MIN_TOKENS: 1e3,
|
|
118
|
+
MAX_TOKENS: 16e3,
|
|
119
|
+
PERCENTAGE: .1
|
|
120
|
+
};
|
|
121
|
+
/** Maximum time to wait between two stream chunks before considering the stream stalled. */
|
|
122
|
+
const STREAM_INACTIVITY_TIMEOUT = 6e4;
|
|
123
|
+
const getModelOutputLimit = (inputLength) => clamp(RESPONSE_LENGTH_BUFFER.PERCENTAGE * inputLength, RESPONSE_LENGTH_BUFFER.MIN_TOKENS, RESPONSE_LENGTH_BUFFER.MAX_TOKENS);
|
|
124
|
+
/**
|
|
125
|
+
* Models sometimes wrap their whole response in a code fence. The fence has to
|
|
126
|
+
* be removed before it reaches the incremental parser, otherwise it would be
|
|
127
|
+
* recovered as an unexpected-text message. Works on arbitrary chunk boundaries
|
|
128
|
+
* by holding content back until the first newline.
|
|
129
|
+
*/
|
|
130
|
+
var LeadingFenceFilter = class {
|
|
131
|
+
_buffer = "";
|
|
132
|
+
_done = false;
|
|
133
|
+
push(text) {
|
|
134
|
+
if (this._done) return text;
|
|
135
|
+
this._buffer += text;
|
|
136
|
+
const newline = this._buffer.indexOf("\n");
|
|
137
|
+
if (newline === -1) return "";
|
|
138
|
+
this._done = true;
|
|
139
|
+
const firstLine = this._buffer.slice(0, newline);
|
|
140
|
+
const rest = this._buffer.slice(newline + 1);
|
|
141
|
+
this._buffer = "";
|
|
142
|
+
return firstLine.trim().startsWith("```") ? rest : `${firstLine}\n${rest}`;
|
|
143
|
+
}
|
|
144
|
+
flush() {
|
|
145
|
+
if (this._done) return "";
|
|
146
|
+
this._done = true;
|
|
147
|
+
const buffered = this._buffer;
|
|
148
|
+
this._buffer = "";
|
|
149
|
+
return buffered.trim().startsWith("```") ? "" : buffered;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
const generateCode = async ({ iteration, ctx, cognitive, controller, metadata, onSend, onSendDelta, onRunStart, onRunComplete }) => {
|
|
153
|
+
const startedAt = Date.now();
|
|
154
|
+
const traces = iteration.traces;
|
|
155
|
+
const modelRef = Array.isArray(iteration.model) ? iteration.model[0] : iteration.model;
|
|
156
|
+
const model = await cognitive.getModelDetails(modelRef).catch((thrown) => {
|
|
157
|
+
throw new CognitiveError(`Failed to fetch model details for model "${modelRef}": ${getErrorMessage(thrown)}`);
|
|
158
|
+
});
|
|
159
|
+
let modelLimit = Math.max(model.input.maxTokens, 8e3);
|
|
160
|
+
if (ctx.maxTokens) modelLimit = Math.min(ctx.maxTokens, modelLimit);
|
|
161
|
+
const responseLengthBuffer = getModelOutputLimit(modelLimit);
|
|
162
|
+
if (iteration.tokens) iteration.tokens.limit = modelLimit;
|
|
163
|
+
let messages;
|
|
164
|
+
try {
|
|
165
|
+
messages = truncateWrappedContent({
|
|
166
|
+
messages: iteration.messages,
|
|
167
|
+
tokenLimit: modelLimit - responseLengthBuffer,
|
|
168
|
+
throwOnFailure: true
|
|
169
|
+
}).filter((x) => typeof x.content !== "string" || x.content.trim().length > 0);
|
|
170
|
+
} catch (thrown) {
|
|
171
|
+
const cap = ctx.maxTokens ? ` (context window capped at ${modelLimit} tokens by options.maxTokens — consider raising or removing it)` : ` (model context window: ${modelLimit} tokens)`;
|
|
172
|
+
throw new CognitiveError(`The prompt does not fit in the context window${cap}: ${getErrorMessage(thrown)}`);
|
|
173
|
+
}
|
|
174
|
+
iteration.messages = messages;
|
|
175
|
+
traces.push({
|
|
176
|
+
type: "llm_call_started",
|
|
177
|
+
started_at: startedAt,
|
|
178
|
+
ended_at: startedAt,
|
|
179
|
+
model: model.id
|
|
180
|
+
});
|
|
181
|
+
const hasAudioParts = messages.some((message) => Array.isArray(message.content) && message.content.some((part) => part.type === "audio"));
|
|
182
|
+
const input = {
|
|
183
|
+
model: iteration.model,
|
|
184
|
+
temperature: iteration.temperature,
|
|
185
|
+
responseFormat: "text",
|
|
186
|
+
reasoningEffort: iteration.reasoningEffort,
|
|
187
|
+
messages,
|
|
188
|
+
stopSequences: ctx.version.getStopTokens(),
|
|
189
|
+
meta: metadata ? { metadata } : void 0,
|
|
190
|
+
options: hasAudioParts ? { transcriptionModel: ctx.transcriptionModel ?? "fast" } : void 0
|
|
191
|
+
};
|
|
192
|
+
let responseMetadata;
|
|
193
|
+
let raw;
|
|
194
|
+
let assistantResponse;
|
|
195
|
+
/** Milliseconds between the stream request and the first/last streamed tokens. */
|
|
196
|
+
let timeToFirstToken;
|
|
197
|
+
let timeToLastToken;
|
|
198
|
+
const liveItems = /* @__PURE__ */ new Map();
|
|
199
|
+
const liveContent = /* @__PURE__ */ new Map();
|
|
200
|
+
let codeGenerationTraced = false;
|
|
201
|
+
let runCompleted = false;
|
|
202
|
+
const dispatchSends = async (events) => {
|
|
203
|
+
for (const event of events) if (event.type === "item-start") {
|
|
204
|
+
liveItems.set(event.item.id, event.item);
|
|
205
|
+
if (event.item.kind === "run" && !codeGenerationTraced) {
|
|
206
|
+
codeGenerationTraced = true;
|
|
207
|
+
traces.push({
|
|
208
|
+
type: "code_generation_started",
|
|
209
|
+
started_at: Date.now()
|
|
210
|
+
});
|
|
211
|
+
onRunStart === null || onRunStart === void 0 || onRunStart();
|
|
212
|
+
}
|
|
213
|
+
} else if (event.type === "body-delta" && onSendDelta) {
|
|
214
|
+
const item = liveItems.get(event.itemId);
|
|
215
|
+
if ((item === null || item === void 0 ? void 0 : item.kind) !== "send") continue;
|
|
216
|
+
const content = (liveContent.get(item.id) ?? "") + event.delta;
|
|
217
|
+
liveContent.set(item.id, content);
|
|
218
|
+
try {
|
|
219
|
+
await onSendDelta({
|
|
220
|
+
id: `${iteration.id}:${item.id}`,
|
|
221
|
+
component: item.name,
|
|
222
|
+
props: item.props,
|
|
223
|
+
delta: event.delta,
|
|
224
|
+
content
|
|
225
|
+
});
|
|
226
|
+
} catch (err) {}
|
|
227
|
+
} else if (event.type === "item-complete") {
|
|
228
|
+
if (event.item.kind === "send" && onSend) await onSend({
|
|
229
|
+
name: event.item.name,
|
|
230
|
+
props: event.item.props,
|
|
231
|
+
body: event.item.body
|
|
232
|
+
});
|
|
233
|
+
else if (event.item.kind === "run" && event.item.status === "complete" && !runCompleted) {
|
|
234
|
+
runCompleted = true;
|
|
235
|
+
onRunComplete === null || onRunComplete === void 0 || onRunComplete((event.item.body ?? "").trim());
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
if (typeof cognitive.generateTextStream === "function") {
|
|
240
|
+
const parser = new StreamingMessageParser();
|
|
241
|
+
const fence = new LeadingFenceFilter();
|
|
242
|
+
const streamController = createJoinedAbortController([controller.signal]);
|
|
243
|
+
const requestedAt = Date.now();
|
|
244
|
+
const stream = cognitive.generateTextStream({
|
|
245
|
+
...input,
|
|
246
|
+
...ctx.maxTimeToFirstToken ? { options: {
|
|
247
|
+
...input.options,
|
|
248
|
+
maxTimeToFirstToken: ctx.maxTimeToFirstToken
|
|
249
|
+
} } : {}
|
|
250
|
+
}, { signal: streamController.signal });
|
|
251
|
+
const inactivityTimeout = Math.max(STREAM_INACTIVITY_TIMEOUT, ctx.maxTimeToFirstToken ?? 0);
|
|
252
|
+
const nextChunk = async () => {
|
|
253
|
+
let timer;
|
|
254
|
+
const stalled = new Promise((_, reject) => {
|
|
255
|
+
timer = setTimeout(() => {
|
|
256
|
+
streamController.abort("LLM stream stalled");
|
|
257
|
+
reject(/* @__PURE__ */ new Error(`LLM stream stalled: no data received for ${inactivityTimeout}ms`));
|
|
258
|
+
}, inactivityTimeout);
|
|
259
|
+
});
|
|
260
|
+
try {
|
|
261
|
+
return await Promise.race([stream.next(), stalled]);
|
|
262
|
+
} finally {
|
|
263
|
+
clearTimeout(timer);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
raw = "";
|
|
267
|
+
while (true) {
|
|
268
|
+
var _chunk$value, _chunk$value2;
|
|
269
|
+
let chunk;
|
|
270
|
+
try {
|
|
271
|
+
chunk = await nextChunk();
|
|
272
|
+
} catch (thrown) {
|
|
273
|
+
throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
|
|
274
|
+
}
|
|
275
|
+
if (chunk.done) break;
|
|
276
|
+
if ((_chunk$value = chunk.value) === null || _chunk$value === void 0 ? void 0 : _chunk$value.metadata) responseMetadata = chunk.value.metadata;
|
|
277
|
+
const delta = (_chunk$value2 = chunk.value) === null || _chunk$value2 === void 0 ? void 0 : _chunk$value2.output;
|
|
278
|
+
if (!delta) continue;
|
|
279
|
+
timeToLastToken = Date.now() - requestedAt;
|
|
280
|
+
timeToFirstToken ??= timeToLastToken;
|
|
281
|
+
raw += delta;
|
|
282
|
+
await dispatchSends(parser.push(fence.push(delta)));
|
|
283
|
+
}
|
|
284
|
+
if (!responseMetadata) throw new CognitiveError("LLM streaming completed without metadata");
|
|
285
|
+
const remaining = fence.flush();
|
|
286
|
+
if (remaining) await dispatchSends(parser.push(remaining));
|
|
287
|
+
await dispatchSends(parser.finish());
|
|
288
|
+
assistantResponse = toParsedAssistantResponse(parser.items, raw);
|
|
289
|
+
} else {
|
|
290
|
+
const response = await cognitive.generateText(input, { signal: controller.signal }).catch((thrown) => {
|
|
291
|
+
throw new CognitiveError(`LLM generation failed: ${getErrorMessage(thrown)}`);
|
|
292
|
+
});
|
|
293
|
+
if (!response.output) throw new CognitiveError("LLM did not return any text output");
|
|
294
|
+
responseMetadata = response.metadata;
|
|
295
|
+
raw = response.output;
|
|
296
|
+
assistantResponse = ctx.version.parseAssistantResponse(raw);
|
|
297
|
+
for (const send of assistantResponse.sends) await (onSend === null || onSend === void 0 ? void 0 : onSend(send));
|
|
298
|
+
}
|
|
299
|
+
iteration.code = assistantResponse.code;
|
|
300
|
+
iteration.sends = assistantResponse.sends;
|
|
301
|
+
iteration.next = assistantResponse.next;
|
|
302
|
+
const usage = responseMetadata.usage;
|
|
303
|
+
iteration.llm = {
|
|
304
|
+
cached: responseMetadata.cached || false,
|
|
305
|
+
ended_at: Date.now(),
|
|
306
|
+
started_at: startedAt,
|
|
307
|
+
status: "success",
|
|
308
|
+
tokens: usage.inputTokens + usage.outputTokens,
|
|
309
|
+
spend: responseMetadata.cost ?? usage.inputCost + usage.outputCost,
|
|
310
|
+
output: assistantResponse.raw,
|
|
311
|
+
model: `${responseMetadata.provider}:${responseMetadata.model}`,
|
|
312
|
+
time_to_first_token: timeToFirstToken,
|
|
313
|
+
time_to_last_token: timeToLastToken,
|
|
314
|
+
usage: {
|
|
315
|
+
inputTokens: usage.inputTokens,
|
|
316
|
+
inputCost: usage.inputCost,
|
|
317
|
+
outputTokens: usage.outputTokens,
|
|
318
|
+
outputCost: usage.outputCost
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
if (iteration.tokens) {
|
|
322
|
+
iteration.tokens.input = usage.inputTokens;
|
|
323
|
+
iteration.tokens.output = usage.outputTokens;
|
|
324
|
+
iteration.tokens.total = usage.inputTokens + usage.outputTokens;
|
|
325
|
+
}
|
|
326
|
+
traces.push({
|
|
327
|
+
type: "llm_call_success",
|
|
328
|
+
started_at: startedAt,
|
|
329
|
+
ended_at: iteration.llm.ended_at,
|
|
330
|
+
model: model.id,
|
|
331
|
+
code: iteration.code ?? ""
|
|
332
|
+
});
|
|
333
|
+
};
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/runtime/interpret-result.ts
|
|
336
|
+
const interpretVMResult = async ({ iteration, result, controller, startedAt, onExit }) => {
|
|
337
|
+
if (result.error && result.error instanceof InvalidCodeError) {
|
|
338
|
+
iteration.end({
|
|
339
|
+
type: "invalid_code_error",
|
|
340
|
+
invalid_code_error: { message: result.error.message }
|
|
341
|
+
});
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
iteration.traces.push({
|
|
345
|
+
type: "code_execution",
|
|
346
|
+
lines_executed: result.lines_executed ?? 0,
|
|
347
|
+
started_at: startedAt,
|
|
348
|
+
ended_at: Date.now()
|
|
349
|
+
});
|
|
350
|
+
if (controller.signal.aborted) {
|
|
351
|
+
iteration.end({
|
|
352
|
+
type: "aborted",
|
|
353
|
+
aborted: { reason: controller.signal.reason ?? "The operation was aborted" }
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (result.error && result.error instanceof CodeExecutionError) {
|
|
358
|
+
iteration.end({
|
|
359
|
+
type: "execution_error",
|
|
360
|
+
execution_error: {
|
|
361
|
+
message: result.error.message,
|
|
362
|
+
stack: cleanStackTrace(result.error.stacktrace ?? result.error.stack ?? "No stack trace available")
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (!result.success) {
|
|
368
|
+
var _result$error;
|
|
369
|
+
iteration.end({
|
|
370
|
+
type: "execution_error",
|
|
371
|
+
execution_error: {
|
|
372
|
+
message: (result === null || result === void 0 || (_result$error = result.error) === null || _result$error === void 0 ? void 0 : _result$error.message) ?? "Unknown error occurred",
|
|
373
|
+
stack: cleanStackTrace(result.error.stack ?? "No stack trace available")
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
if (result.signal instanceof ThinkSignal) {
|
|
379
|
+
iteration.end({
|
|
380
|
+
type: "thinking_requested",
|
|
381
|
+
thinking_requested: {
|
|
382
|
+
variables: result.signal.context,
|
|
383
|
+
reason: result.signal.reason,
|
|
384
|
+
metadata: result.signal.metadata
|
|
385
|
+
}
|
|
386
|
+
});
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (result.signal instanceof SnapshotSignal) {
|
|
390
|
+
iteration.end({
|
|
391
|
+
type: "callback_requested",
|
|
392
|
+
callback_requested: { signal: result.signal }
|
|
393
|
+
});
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
const returnValue = result.return_value;
|
|
397
|
+
const codeRequestsInspection = hasTopLevelReturn(iteration.code ?? "");
|
|
398
|
+
if (iteration.next && !codeRequestsInspection) {
|
|
399
|
+
await applyNextExit({
|
|
400
|
+
iteration,
|
|
401
|
+
controller,
|
|
402
|
+
onExit
|
|
403
|
+
});
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const localVariables = Object.fromEntries(Object.entries(result.variables ?? {}).filter(([, value]) => value !== "[[non-primitive]]"));
|
|
407
|
+
iteration.end({
|
|
408
|
+
type: "thinking_requested",
|
|
409
|
+
thinking_requested: {
|
|
410
|
+
reason: iteration.next ? `Code execution completed. The ■next=${iteration.next.name} exit was NOT applied because your code returns a value — inspect it below, then end your next response with ■next.` : "Code execution completed",
|
|
411
|
+
variables: returnValue !== void 0 ? returnValue : Object.keys(localVariables).length ? localVariables : iteration.variables
|
|
412
|
+
}
|
|
413
|
+
});
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* Applies the `■next=<exit>` block of the current iteration: validates the exit
|
|
417
|
+
* name and props against the available exits, runs the onExit hook, and ends
|
|
418
|
+
* the iteration with exit_success or exit_error.
|
|
419
|
+
*/
|
|
420
|
+
const applyNextExit = async ({ iteration, controller, onExit }) => {
|
|
421
|
+
const next = iteration.next;
|
|
422
|
+
if (!next) throw new Error("applyNextExit called without a ■next block on the iteration");
|
|
423
|
+
const attempt = (props) => parseExit(Object.keys(props).length ? {
|
|
424
|
+
action: next.name,
|
|
425
|
+
value: props
|
|
426
|
+
} : { action: next.name }, iteration.exits);
|
|
427
|
+
let parsedExit = attempt(next.props);
|
|
428
|
+
const keys = Object.keys(next.props);
|
|
429
|
+
if (!parsedExit.success && keys.length === 1 && [
|
|
430
|
+
"props",
|
|
431
|
+
"value",
|
|
432
|
+
"data"
|
|
433
|
+
].includes(keys[0])) {
|
|
434
|
+
const inner = next.props[keys[0]];
|
|
435
|
+
if (inner && typeof inner === "object" && !Array.isArray(inner)) {
|
|
436
|
+
const unwrapped = attempt(inner);
|
|
437
|
+
if (unwrapped.success) parsedExit = unwrapped;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const returnValue = {
|
|
441
|
+
action: next.name,
|
|
442
|
+
value: parsedExit.success ? parsedExit.value : next.props
|
|
443
|
+
};
|
|
444
|
+
if (!parsedExit.success) {
|
|
445
|
+
iteration.end({
|
|
446
|
+
type: "exit_error",
|
|
447
|
+
exit_error: {
|
|
448
|
+
exit: next.name,
|
|
449
|
+
message: parsedExit.error,
|
|
450
|
+
return_value: returnValue
|
|
451
|
+
}
|
|
452
|
+
});
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
const returnExit = parsedExit.exit;
|
|
456
|
+
try {
|
|
457
|
+
await (onExit === null || onExit === void 0 ? void 0 : onExit({
|
|
458
|
+
exit: returnExit,
|
|
459
|
+
result: parsedExit.value
|
|
460
|
+
}, controller));
|
|
461
|
+
} catch (err) {
|
|
462
|
+
iteration.end({
|
|
463
|
+
type: "exit_error",
|
|
464
|
+
exit_error: {
|
|
465
|
+
exit: returnExit.name,
|
|
466
|
+
message: `Error executing exit ${returnExit.name}: ${getErrorMessage(err)}`,
|
|
467
|
+
return_value: returnValue
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
iteration.end({
|
|
473
|
+
type: "exit_success",
|
|
474
|
+
exit_success: {
|
|
475
|
+
exit_name: returnExit.name,
|
|
476
|
+
return_value: parsedExit.value
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
};
|
|
480
|
+
//#endregion
|
|
481
|
+
//#region src/runtime/utils.ts
|
|
482
|
+
const finalizeIteration = async ({ iteration, status, controller, onIterationEnd }) => {
|
|
483
|
+
if (status) iteration.end(status);
|
|
484
|
+
if (iteration.status.type === "pending") return;
|
|
485
|
+
try {
|
|
486
|
+
await (onIterationEnd === null || onIterationEnd === void 0 ? void 0 : onIterationEnd(iteration, controller));
|
|
487
|
+
} catch (err) {
|
|
488
|
+
console.error(err);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
//#endregion
|
|
492
|
+
//#region src/runtime/tool-wrapper.ts
|
|
493
|
+
const SLOW_TOOL_WARNING = ms("15s");
|
|
494
|
+
function wrapTool({ chat, tool, traces, object, iteration, beforeHook, afterHook, controller }) {
|
|
495
|
+
const getToolInput = (input) => tool.zInput.safeParse(input).data ?? input;
|
|
496
|
+
return async function(input) {
|
|
497
|
+
const toolCallId = `tcall_${ulid()}`;
|
|
498
|
+
const originalInput = input;
|
|
499
|
+
let effectiveInput = input;
|
|
500
|
+
const alertSlowTool = setTimeout(() => traces.push({
|
|
501
|
+
type: "tool_slow",
|
|
502
|
+
tool_name: tool.name,
|
|
503
|
+
tool_call_id: toolCallId,
|
|
504
|
+
started_at: Date.now(),
|
|
505
|
+
input: getToolInput(originalInput),
|
|
506
|
+
object,
|
|
507
|
+
duration: SLOW_TOOL_WARNING
|
|
508
|
+
}), SLOW_TOOL_WARNING);
|
|
509
|
+
const toolStart = Date.now();
|
|
510
|
+
let output;
|
|
511
|
+
let error;
|
|
512
|
+
let success = true;
|
|
513
|
+
let signalToThrow;
|
|
514
|
+
const pushToolCallTrace = () => {
|
|
515
|
+
traces.push({
|
|
516
|
+
type: "tool_call",
|
|
517
|
+
tool_call_id: toolCallId,
|
|
518
|
+
started_at: toolStart,
|
|
519
|
+
ended_at: Date.now(),
|
|
520
|
+
tool_name: tool.name,
|
|
521
|
+
object,
|
|
522
|
+
input: getToolInput(originalInput),
|
|
523
|
+
output,
|
|
524
|
+
error,
|
|
525
|
+
success
|
|
526
|
+
});
|
|
527
|
+
};
|
|
528
|
+
const handleSignals = async (err) => {
|
|
529
|
+
if (output === err) return true;
|
|
530
|
+
if (err instanceof SnapshotSignal) {
|
|
531
|
+
err.toolCall = {
|
|
532
|
+
name: tool.name,
|
|
533
|
+
inputSchema: tool.input,
|
|
534
|
+
outputSchema: tool.output,
|
|
535
|
+
input: originalInput
|
|
536
|
+
};
|
|
537
|
+
err.message = Signals.serializeError(err);
|
|
538
|
+
}
|
|
539
|
+
if (err instanceof ThinkSignal) {
|
|
540
|
+
signalToThrow = err;
|
|
541
|
+
traces.push({
|
|
542
|
+
type: "think_signal",
|
|
543
|
+
started_at: Date.now(),
|
|
544
|
+
line: 0,
|
|
545
|
+
ended_at: Date.now()
|
|
546
|
+
});
|
|
547
|
+
success = true;
|
|
548
|
+
output = err;
|
|
549
|
+
const afterRes = await (afterHook === null || afterHook === void 0 ? void 0 : afterHook({
|
|
550
|
+
iteration,
|
|
551
|
+
tool,
|
|
552
|
+
input: originalInput,
|
|
553
|
+
output,
|
|
554
|
+
controller,
|
|
555
|
+
object,
|
|
556
|
+
toolCallId
|
|
557
|
+
}));
|
|
558
|
+
if (typeof (afterRes === null || afterRes === void 0 ? void 0 : afterRes.output) !== "undefined") output = afterRes.output;
|
|
559
|
+
return true;
|
|
560
|
+
}
|
|
561
|
+
return false;
|
|
562
|
+
};
|
|
563
|
+
try {
|
|
564
|
+
const beforeRes = await (beforeHook === null || beforeHook === void 0 ? void 0 : beforeHook({
|
|
565
|
+
iteration,
|
|
566
|
+
tool,
|
|
567
|
+
input: effectiveInput,
|
|
568
|
+
controller,
|
|
569
|
+
object,
|
|
570
|
+
toolCallId
|
|
571
|
+
}));
|
|
572
|
+
if (typeof (beforeRes === null || beforeRes === void 0 ? void 0 : beforeRes.input) !== "undefined") effectiveInput = beforeRes.input;
|
|
573
|
+
output = await tool.execute(effectiveInput, { callId: toolCallId }, chat);
|
|
574
|
+
const afterRes = await (afterHook === null || afterHook === void 0 ? void 0 : afterHook({
|
|
575
|
+
iteration,
|
|
576
|
+
tool,
|
|
577
|
+
input: effectiveInput,
|
|
578
|
+
output,
|
|
579
|
+
controller,
|
|
580
|
+
object,
|
|
581
|
+
toolCallId
|
|
582
|
+
}));
|
|
583
|
+
if (typeof (afterRes === null || afterRes === void 0 ? void 0 : afterRes.output) !== "undefined") output = afterRes.output;
|
|
584
|
+
} catch (err) {
|
|
585
|
+
if (!await handleSignals(err)) {
|
|
586
|
+
success = false;
|
|
587
|
+
error = err;
|
|
588
|
+
}
|
|
589
|
+
} finally {
|
|
590
|
+
clearTimeout(alertSlowTool);
|
|
591
|
+
pushToolCallTrace();
|
|
592
|
+
}
|
|
593
|
+
if (!success) throw error;
|
|
594
|
+
if (signalToThrow) throw signalToThrow;
|
|
595
|
+
return output;
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
//#endregion
|
|
599
|
+
//#region src/runtime/vm-context.ts
|
|
600
|
+
const buildVMContext = ({ ctx, iteration, controller, onBeforeTool, onAfterTool }) => {
|
|
601
|
+
const traces = iteration.traces;
|
|
602
|
+
const vmContext = { ...stripInvalidIdentifiers(iteration.variables) };
|
|
603
|
+
for (const obj of iteration.objects) {
|
|
604
|
+
const internalValues = {};
|
|
605
|
+
const instance = {};
|
|
606
|
+
for (const { name, value, writable, type } of obj.properties ?? []) {
|
|
607
|
+
internalValues[name] = value;
|
|
608
|
+
const initialValue = value;
|
|
609
|
+
const schema = type ?? z.any();
|
|
610
|
+
Object.defineProperty(instance, name, {
|
|
611
|
+
enumerable: true,
|
|
612
|
+
configurable: true,
|
|
613
|
+
get() {
|
|
614
|
+
return internalValues[name];
|
|
615
|
+
},
|
|
616
|
+
set(value) {
|
|
617
|
+
if (isEqual(value, internalValues[name])) return;
|
|
618
|
+
if (!writable) throw new AssignmentError(`Property ${obj.name}.${name} is read-only and cannot be modified`);
|
|
619
|
+
const parsed = schema.safeParse(value);
|
|
620
|
+
if (!parsed.success) throw new AssignmentError(`Invalid value for Object property ${obj.name}.${name}: ${getErrorMessage(parsed.error)}`);
|
|
621
|
+
internalValues[name] = parsed.data;
|
|
622
|
+
traces.push({
|
|
623
|
+
type: "property",
|
|
624
|
+
started_at: Date.now(),
|
|
625
|
+
object: obj.name,
|
|
626
|
+
property: name,
|
|
627
|
+
value: parsed.data
|
|
628
|
+
});
|
|
629
|
+
iteration.trackMutation({
|
|
630
|
+
object: obj.name,
|
|
631
|
+
property: name,
|
|
632
|
+
before: initialValue,
|
|
633
|
+
after: parsed.data
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
for (const tool of obj.tools ?? []) instance[tool.name] = wrapTool({
|
|
639
|
+
chat: ctx.chat,
|
|
640
|
+
tool,
|
|
641
|
+
traces,
|
|
642
|
+
object: obj.name,
|
|
643
|
+
iteration,
|
|
644
|
+
beforeHook: onBeforeTool,
|
|
645
|
+
afterHook: onAfterTool,
|
|
646
|
+
controller
|
|
647
|
+
});
|
|
648
|
+
Object.preventExtensions(instance);
|
|
649
|
+
Object.seal(instance);
|
|
650
|
+
vmContext[obj.name] = instance;
|
|
651
|
+
}
|
|
652
|
+
for (const tool of iteration.tools) {
|
|
653
|
+
const wrapped = wrapTool({
|
|
654
|
+
chat: ctx.chat,
|
|
655
|
+
tool,
|
|
656
|
+
traces,
|
|
657
|
+
iteration,
|
|
658
|
+
beforeHook: onBeforeTool,
|
|
659
|
+
afterHook: onAfterTool,
|
|
660
|
+
controller
|
|
661
|
+
});
|
|
662
|
+
for (const key of [tool.name, ...tool.aliases ?? []]) vmContext[key] = wrapped;
|
|
663
|
+
}
|
|
664
|
+
return vmContext;
|
|
665
|
+
};
|
|
666
|
+
//#endregion
|
|
667
|
+
//#region src/runtime/execute.ts
|
|
668
|
+
const executeContext = async (props) => {
|
|
669
|
+
await init();
|
|
670
|
+
const result = await executeContextInternal(props);
|
|
671
|
+
try {
|
|
672
|
+
var _result$context$chat, _result$context$chat$;
|
|
673
|
+
(_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 || _result$context$chat$.call(_result$context$chat, result);
|
|
674
|
+
} catch (err) {}
|
|
675
|
+
return result;
|
|
676
|
+
};
|
|
677
|
+
const executeContextInternal = async (props) => {
|
|
678
|
+
var _props$options, _props$options2, _props$options3, _props$options4, _props$options5;
|
|
679
|
+
const controller = createJoinedAbortController([props.signal]);
|
|
680
|
+
const { onIterationStart, onIterationEnd, onTrace, onExit, onBeforeExecution, onAfterTool, onBeforeTool } = props;
|
|
681
|
+
const client = props.client ?? new Client();
|
|
682
|
+
const cognitive = Cognitive.isCognitiveClient(client) || _CustomModelClient.isCustomClient(client) ? client : new Cognitive({ client });
|
|
683
|
+
const ctx = new Context({
|
|
684
|
+
chat: props.chat,
|
|
685
|
+
instructions: props.instructions,
|
|
686
|
+
objects: props.objects,
|
|
687
|
+
tools: props.tools,
|
|
688
|
+
loop: (_props$options = props.options) === null || _props$options === void 0 ? void 0 : _props$options.loop,
|
|
689
|
+
timeout: (_props$options2 = props.options) === null || _props$options2 === void 0 ? void 0 : _props$options2.timeout,
|
|
690
|
+
maxTokens: (_props$options3 = props.options) === null || _props$options3 === void 0 ? void 0 : _props$options3.maxTokens,
|
|
691
|
+
maxTimeToFirstToken: (_props$options4 = props.options) === null || _props$options4 === void 0 ? void 0 : _props$options4.maxTimeToFirstToken,
|
|
692
|
+
transcriptionModel: (_props$options5 = props.options) === null || _props$options5 === void 0 ? void 0 : _props$options5.transcriptionModel,
|
|
693
|
+
exits: props.exits,
|
|
694
|
+
snapshot: props.snapshot,
|
|
695
|
+
model: props.model,
|
|
696
|
+
temperature: props.temperature,
|
|
697
|
+
reasoningEffort: props.reasoningEffort
|
|
698
|
+
});
|
|
699
|
+
try {
|
|
700
|
+
while (true) {
|
|
701
|
+
if (ctx.iterations.length >= ctx.loop) return new ErrorExecutionResult(ctx, new LoopExceededError());
|
|
702
|
+
const iteration = await ctx.nextIteration();
|
|
703
|
+
const unsubscribeTrace = iteration.traces.onPush((traces) => {
|
|
704
|
+
for (const trace of traces) onTrace === null || onTrace === void 0 || onTrace({
|
|
705
|
+
trace,
|
|
706
|
+
iteration: ctx.iterations.length,
|
|
707
|
+
controller
|
|
708
|
+
});
|
|
709
|
+
});
|
|
710
|
+
try {
|
|
711
|
+
if ((await executeIterationStartHook({
|
|
712
|
+
ctx,
|
|
713
|
+
iteration,
|
|
714
|
+
controller,
|
|
715
|
+
onIterationStart,
|
|
716
|
+
onIterationEnd
|
|
717
|
+
})).type === "continue") continue;
|
|
718
|
+
if (controller.signal.aborted) {
|
|
719
|
+
await finalizeIteration({
|
|
720
|
+
iteration,
|
|
721
|
+
controller,
|
|
722
|
+
onIterationEnd,
|
|
723
|
+
status: {
|
|
724
|
+
type: "aborted",
|
|
725
|
+
aborted: { reason: controller.signal.reason ?? "The operation was aborted" }
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
return new ErrorExecutionResult(ctx, controller.signal.reason ?? "The operation was aborted");
|
|
729
|
+
}
|
|
730
|
+
const iterationResult = await executeIterationWithErrorHandling({
|
|
731
|
+
iteration,
|
|
732
|
+
ctx,
|
|
733
|
+
cognitive,
|
|
734
|
+
controller,
|
|
735
|
+
onExit,
|
|
736
|
+
onBeforeExecution,
|
|
737
|
+
onAfterTool,
|
|
738
|
+
onBeforeTool,
|
|
739
|
+
onIterationEnd,
|
|
740
|
+
metadata: props.metadata
|
|
741
|
+
});
|
|
742
|
+
if (iterationResult.type === "return") return iterationResult.result;
|
|
743
|
+
const selectedResult = transformIterationResult({
|
|
744
|
+
ctx,
|
|
745
|
+
iteration
|
|
746
|
+
});
|
|
747
|
+
if (selectedResult.type === "continue") continue;
|
|
748
|
+
return selectedResult.result;
|
|
749
|
+
} finally {
|
|
750
|
+
try {
|
|
751
|
+
unsubscribeTrace();
|
|
752
|
+
} catch (err) {}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
} catch (error) {
|
|
756
|
+
return new ErrorExecutionResult(ctx, error ?? "Unknown error");
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
const executeIterationStartHook = async ({ ctx, iteration, controller, onIterationStart, onIterationEnd }) => {
|
|
760
|
+
try {
|
|
761
|
+
const hookRes = await (onIterationStart === null || onIterationStart === void 0 ? void 0 : onIterationStart(iteration, controller, ctx));
|
|
762
|
+
if (hookRes) Object.assign(iteration, hookRes);
|
|
763
|
+
return { type: "proceed" };
|
|
764
|
+
} catch (err) {
|
|
765
|
+
await finalizeIteration({
|
|
766
|
+
iteration,
|
|
767
|
+
controller,
|
|
768
|
+
onIterationEnd,
|
|
769
|
+
status: err instanceof ThinkSignal ? {
|
|
770
|
+
type: "thinking_requested",
|
|
771
|
+
thinking_requested: {
|
|
772
|
+
variables: err.context,
|
|
773
|
+
reason: err.reason
|
|
774
|
+
}
|
|
775
|
+
} : {
|
|
776
|
+
type: "execution_error",
|
|
777
|
+
execution_error: {
|
|
778
|
+
message: `Error in onIterationStart hook: ${getErrorMessage(err)}`,
|
|
779
|
+
stack: cleanStackTrace(err instanceof Error ? err.stack ?? "No stack trace available" : "No stack trace available")
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
return { type: "continue" };
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
const executeIterationWithErrorHandling = async ({ iteration, ctx, cognitive, controller, onExit, onBeforeExecution, onAfterTool, onBeforeTool, onIterationEnd, metadata }) => {
|
|
787
|
+
try {
|
|
788
|
+
await executeIteration({
|
|
789
|
+
iteration,
|
|
790
|
+
ctx,
|
|
791
|
+
cognitive,
|
|
792
|
+
controller,
|
|
793
|
+
onExit,
|
|
794
|
+
onBeforeExecution,
|
|
795
|
+
onAfterTool,
|
|
796
|
+
onBeforeTool,
|
|
797
|
+
metadata
|
|
798
|
+
});
|
|
799
|
+
await finalizeIteration({
|
|
800
|
+
iteration,
|
|
801
|
+
controller,
|
|
802
|
+
onIterationEnd
|
|
803
|
+
});
|
|
804
|
+
return { type: "proceed" };
|
|
805
|
+
} catch (err) {
|
|
806
|
+
if (!(err instanceof CognitiveError)) {
|
|
807
|
+
await finalizeIteration({
|
|
808
|
+
iteration,
|
|
809
|
+
controller,
|
|
810
|
+
onIterationEnd,
|
|
811
|
+
status: iteration.status.type === "pending" ? {
|
|
812
|
+
type: "execution_error",
|
|
813
|
+
execution_error: {
|
|
814
|
+
message: "An unexpected error occurred: " + getErrorMessage(err),
|
|
815
|
+
stack: cleanStackTrace(err instanceof Error ? err.stack ?? "No stack trace available" : "No stack trace available")
|
|
816
|
+
}
|
|
817
|
+
} : void 0
|
|
818
|
+
});
|
|
819
|
+
return { type: "proceed" };
|
|
820
|
+
}
|
|
821
|
+
if (!controller.signal.aborted) return {
|
|
822
|
+
type: "return",
|
|
823
|
+
result: new ErrorExecutionResult(ctx, err)
|
|
824
|
+
};
|
|
825
|
+
await finalizeIteration({
|
|
826
|
+
iteration,
|
|
827
|
+
controller,
|
|
828
|
+
onIterationEnd,
|
|
829
|
+
status: iteration.status.type === "pending" ? {
|
|
830
|
+
type: "aborted",
|
|
831
|
+
aborted: { reason: controller.signal.reason ?? "The operation was aborted" }
|
|
832
|
+
} : void 0
|
|
833
|
+
});
|
|
834
|
+
return {
|
|
835
|
+
type: "return",
|
|
836
|
+
result: new ErrorExecutionResult(ctx, controller.signal.reason ?? "The operation was aborted")
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
const transformIterationResult = ({ ctx, iteration }) => {
|
|
841
|
+
if (iteration.status.type === "exit_success") {
|
|
842
|
+
const exitName = iteration.status.exit_success.exit_name;
|
|
843
|
+
return {
|
|
844
|
+
type: "return",
|
|
845
|
+
result: new SuccessExecutionResult(ctx, {
|
|
846
|
+
exit: iteration.exits.find((x) => x.name === exitName),
|
|
847
|
+
result: iteration.status.exit_success.return_value
|
|
848
|
+
})
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
if (iteration.status.type === "callback_requested") return {
|
|
852
|
+
type: "return",
|
|
853
|
+
result: new PartialExecutionResult(ctx, iteration.status.callback_requested.signal, Snapshot.fromSignal(iteration.status.callback_requested.signal))
|
|
854
|
+
};
|
|
855
|
+
if (iteration.status.type === "aborted") return {
|
|
856
|
+
type: "return",
|
|
857
|
+
result: new ErrorExecutionResult(ctx, iteration.error ?? "The operation was aborted")
|
|
858
|
+
};
|
|
859
|
+
if (iteration.status.type === "thinking_requested" || iteration.status.type === "exit_error" || iteration.status.type === "execution_error" || iteration.status.type === "invalid_code_error") return { type: "continue" };
|
|
860
|
+
return {
|
|
861
|
+
type: "return",
|
|
862
|
+
result: new ErrorExecutionResult(ctx, iteration.error ?? `Unknown error. Status: ${iteration.status.type}`)
|
|
863
|
+
};
|
|
864
|
+
};
|
|
865
|
+
const executeIteration = async ({ iteration, ctx, cognitive, controller, onExit, onBeforeExecution, onBeforeTool, onAfterTool, metadata }) => {
|
|
866
|
+
var _ctx$chat;
|
|
867
|
+
const runCode = (code) => {
|
|
868
|
+
const vmContext = buildVMContext({
|
|
869
|
+
ctx,
|
|
870
|
+
iteration,
|
|
871
|
+
controller,
|
|
872
|
+
onBeforeTool,
|
|
873
|
+
onAfterTool
|
|
874
|
+
});
|
|
875
|
+
return runAsyncFunction(vmContext, code, iteration.traces, controller.signal, ctx.timeout).catch((err) => {
|
|
876
|
+
return {
|
|
877
|
+
success: false,
|
|
878
|
+
error: err instanceof Error ? err : new Error(getErrorMessage(err)),
|
|
879
|
+
lines_executed: [],
|
|
880
|
+
traces: [],
|
|
881
|
+
variables: {}
|
|
882
|
+
};
|
|
883
|
+
});
|
|
884
|
+
};
|
|
885
|
+
const canExecuteEarly = typeof onBeforeExecution !== "function";
|
|
886
|
+
let earlyExecution;
|
|
887
|
+
await generateCode({
|
|
888
|
+
iteration,
|
|
889
|
+
ctx,
|
|
890
|
+
cognitive,
|
|
891
|
+
controller,
|
|
892
|
+
metadata,
|
|
893
|
+
onRunStart: () => warmupVM(),
|
|
894
|
+
onRunComplete: canExecuteEarly ? (code) => {
|
|
895
|
+
if (!code.length || controller.signal.aborted || earlyExecution) return;
|
|
896
|
+
iteration.code = code;
|
|
897
|
+
earlyExecution = {
|
|
898
|
+
code,
|
|
899
|
+
started_at: Date.now(),
|
|
900
|
+
promise: runCode(code)
|
|
901
|
+
};
|
|
902
|
+
} : void 0,
|
|
903
|
+
onSend: async (send) => {
|
|
904
|
+
if (!ctx.chat) return;
|
|
905
|
+
const sendStartedAt = Date.now();
|
|
906
|
+
const component = createJsxComponent({
|
|
907
|
+
type: send.name,
|
|
908
|
+
props: send.props,
|
|
909
|
+
children: send.body ? [send.body] : []
|
|
910
|
+
});
|
|
911
|
+
try {
|
|
912
|
+
await ctx.chat.handler(component);
|
|
913
|
+
} catch (err) {
|
|
914
|
+
throw new Error(`Error while sending message (■send=${send.name}): ${getErrorMessage(err)}`);
|
|
915
|
+
}
|
|
916
|
+
iteration.traces.push({
|
|
917
|
+
type: "yield",
|
|
918
|
+
value: component,
|
|
919
|
+
started_at: sendStartedAt,
|
|
920
|
+
ended_at: Date.now()
|
|
921
|
+
});
|
|
922
|
+
},
|
|
923
|
+
onSendDelta: ((_ctx$chat = ctx.chat) === null || _ctx$chat === void 0 ? void 0 : _ctx$chat.onMessageDelta) ? (delta) => ctx.chat.onMessageDelta(delta) : void 0
|
|
924
|
+
});
|
|
925
|
+
if (earlyExecution) iteration.code = earlyExecution.code;
|
|
926
|
+
if (typeof onBeforeExecution === "function") try {
|
|
927
|
+
const hookRes = await onBeforeExecution(iteration, controller);
|
|
928
|
+
if (typeof (hookRes === null || hookRes === void 0 ? void 0 : hookRes.code) === "string" && hookRes.code.trim().length > 0) iteration.code = hookRes.code.trim();
|
|
929
|
+
} catch (err) {
|
|
930
|
+
if (err instanceof ThinkSignal) {
|
|
931
|
+
iteration.end({
|
|
932
|
+
type: "thinking_requested",
|
|
933
|
+
thinking_requested: {
|
|
934
|
+
variables: err.context,
|
|
935
|
+
reason: err.reason
|
|
936
|
+
}
|
|
937
|
+
});
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
iteration.end({
|
|
941
|
+
type: "execution_error",
|
|
942
|
+
execution_error: {
|
|
943
|
+
message: `Error in onBeforeExecution hook: ${getErrorMessage(err)}`,
|
|
944
|
+
stack: cleanStackTrace(err instanceof Error ? err.stack ?? "No stack trace available" : "No stack trace available")
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
return;
|
|
948
|
+
}
|
|
949
|
+
const traces = iteration.traces;
|
|
950
|
+
if (controller.signal.aborted) {
|
|
951
|
+
traces.push({
|
|
952
|
+
type: "abort_signal",
|
|
953
|
+
started_at: Date.now(),
|
|
954
|
+
reason: "The operation was aborted by user."
|
|
955
|
+
});
|
|
956
|
+
iteration.end({
|
|
957
|
+
type: "aborted",
|
|
958
|
+
aborted: { reason: controller.signal.reason ?? "The operation was aborted" }
|
|
959
|
+
});
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
if (!iteration.code) {
|
|
963
|
+
var _iteration$sends;
|
|
964
|
+
if (iteration.next) {
|
|
965
|
+
await applyNextExit({
|
|
966
|
+
iteration,
|
|
967
|
+
controller,
|
|
968
|
+
onExit
|
|
969
|
+
});
|
|
970
|
+
return;
|
|
971
|
+
}
|
|
972
|
+
if (ctx.chat && ((_iteration$sends = iteration.sends) === null || _iteration$sends === void 0 ? void 0 : _iteration$sends.length)) {
|
|
973
|
+
iteration.next = {
|
|
974
|
+
name: "listen",
|
|
975
|
+
props: {}
|
|
976
|
+
};
|
|
977
|
+
await applyNextExit({
|
|
978
|
+
iteration,
|
|
979
|
+
controller,
|
|
980
|
+
onExit
|
|
981
|
+
});
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
iteration.end({
|
|
985
|
+
type: "invalid_code_error",
|
|
986
|
+
invalid_code_error: { message: "The response did not include a ■run block or a ■next exit. Reply using ■ blocks and end your response with ■run or ■next=<exit>." }
|
|
987
|
+
});
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
const startedAt = (earlyExecution === null || earlyExecution === void 0 ? void 0 : earlyExecution.started_at) ?? Date.now();
|
|
991
|
+
const result = earlyExecution ? await earlyExecution.promise : await runCode(iteration.code ?? "");
|
|
992
|
+
await interpretVMResult({
|
|
993
|
+
iteration,
|
|
994
|
+
result,
|
|
995
|
+
controller,
|
|
996
|
+
startedAt,
|
|
997
|
+
onExit
|
|
998
|
+
});
|
|
999
|
+
};
|
|
1000
|
+
//#endregion
|
|
1001
|
+
export { executeContext };
|