@botpress/adk-cli
Version:
Command-line interface for the Botpress Agent Development Kit (ADK)
1,169 lines (1,165 loc) • 38.8 kB
JavaScript
// @bun
import {
Tool
} from "./chunk-knvm2anf.js";
import {
Exit
} from "./chunk-65h5trb5.js";
import {
LoopExceededError
} from "./chunk-nn2jb0x0.js";
import {
DualModePrompt,
extractType,
inspect
} from "./chunk-v8xvth6j.js";
import {
wrapContent
} from "./chunk-kkk13rcb.js";
import {
assertValidComponent
} from "./chunk-f4bw8q7c.js";
import {
cloneDeep_default,
exports_exports,
isPlainObject_default,
omit_default
} from "./chunk-54qt5g7m.js";
import {
__require
} from "./chunk-dhs2bg35.js";
// ../../node_modules/.bun/ulid@2.4.0/node_modules/ulid/dist/index.esm.js
function createError(message) {
const err = new Error(message);
err.source = "ulid";
return err;
}
var ENCODING = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
var ENCODING_LEN = ENCODING.length;
var TIME_MAX = Math.pow(2, 48) - 1;
var TIME_LEN = 10;
var RANDOM_LEN = 16;
function randomChar(prng) {
let rand = Math.floor(prng() * ENCODING_LEN);
if (rand === ENCODING_LEN) {
rand = ENCODING_LEN - 1;
}
return ENCODING.charAt(rand);
}
function encodeTime(now, len) {
if (isNaN(now)) {
throw new Error(now + " must be a number");
}
if (now > TIME_MAX) {
throw createError("cannot encode time greater than " + TIME_MAX);
}
if (now < 0) {
throw createError("time must be positive");
}
if (Number.isInteger(Number(now)) === false) {
throw createError("time must be an integer");
}
let mod;
let str = "";
for (;len > 0; len--) {
mod = now % ENCODING_LEN;
str = ENCODING.charAt(mod) + str;
now = (now - mod) / ENCODING_LEN;
}
return str;
}
function encodeRandom(len, prng) {
let str = "";
for (;len > 0; len--) {
str = randomChar(prng) + str;
}
return str;
}
function detectPrng(allowInsecure = false, root) {
if (!root) {
root = typeof window !== "undefined" ? window : null;
}
const browserCrypto = root && (root.crypto || root.msCrypto);
if (browserCrypto) {
return () => {
const buffer = new Uint8Array(1);
browserCrypto.getRandomValues(buffer);
return buffer[0] / 255;
};
} else {
try {
const nodeCrypto = __require("crypto");
return () => nodeCrypto.randomBytes(1).readUInt8() / 255;
} catch (e) {}
}
if (allowInsecure) {
try {
console.error("secure crypto unusable, falling back to insecure Math.random()!");
} catch (e) {}
return () => Math.random();
}
throw createError("secure crypto unusable, insecure Math.random not allowed");
}
function factory(currPrng) {
if (!currPrng) {
currPrng = detectPrng();
}
return function ulid(seedTime) {
if (isNaN(seedTime)) {
seedTime = Date.now();
}
return encodeTime(seedTime, TIME_LEN) + encodeRandom(RANDOM_LEN, currPrng);
};
}
var ulid = factory();
// ../../node_modules/.bun/llmz@0.0.79+b49d396f5ed96e7f/node_modules/llmz/dist/chunk-ESMRQVFC.js
function isValuePrimitive(value) {
return value === null || value === undefined || typeof value !== "object" || Array.isArray(value);
}
function generatePossibleWraps(value, shape, discriminator) {
const possibleWraps = [];
const commonNames = ["result", "value", "data", "message", "error", "output", "response"];
if (shape && typeof shape === "object") {
for (const key of Object.keys(shape)) {
if (key !== discriminator) {
const wrap = discriminator ? { [discriminator]: shape[discriminator]._def.value, [key]: value } : { [key]: value };
possibleWraps.push(wrap);
}
}
}
for (const name of commonNames) {
const hasName = possibleWraps.some((w) => Object.keys(w).includes(name));
if (!hasName) {
const wrap = discriminator && (shape == null ? undefined : shape[discriminator]) ? { [discriminator]: shape[discriminator]._def.value, [name]: value } : { [name]: value };
possibleWraps.push(wrap);
}
}
return possibleWraps;
}
function tryObjectWrapping(schema, candidateValue) {
const possibleWraps = generatePossibleWraps(candidateValue, schema.shape);
for (const wrap of possibleWraps) {
const testParse = schema.safeParse(wrap);
if (testParse.success) {
return { success: true, valueToValidate: wrap, parsed: testParse };
}
}
return { success: false, valueToValidate: candidateValue, parsed: { success: false } };
}
function detectDiscriminator(options) {
if (options.length === 0 || options[0]._def.typeName !== "ZodObject") {
return;
}
const firstShape = options[0].shape;
for (const key in firstShape) {
const firstFieldType = firstShape[key]._def.typeName;
if (firstFieldType === "ZodLiteral") {
const allHaveLiteral = options.every((opt) => {
var _a;
return ((_a = opt.shape[key]) == null ? undefined : _a._def.typeName) === "ZodLiteral";
});
if (allHaveLiteral) {
return key;
}
}
}
return;
}
function tryAddDiscriminator(schema, options, discriminator, valueToValidate) {
const matchingOptions = [];
for (const option of options) {
if (option._def.typeName === "ZodObject" && option.shape[discriminator]) {
const discriminatorValue = option.shape[discriminator]._def.value;
const wrappedValue = { [discriminator]: discriminatorValue, ...valueToValidate };
const testParse = schema.safeParse(wrappedValue);
if (testParse.success) {
matchingOptions.push({ wrappedValue });
}
}
}
if (matchingOptions.length === 1) {
const wrapped = matchingOptions[0].wrappedValue;
return { success: true, valueToValidate: wrapped, parsed: schema.safeParse(wrapped) };
}
return { success: false, valueToValidate, parsed: { success: false } };
}
function tryUnionPrimitiveWrapping(schema, options, discriminator, valueToValidate) {
const allSuccessfulWraps = [];
for (const option of options) {
if (option._def.typeName === "ZodObject" && option.shape[discriminator]) {
const discriminatorValue = option.shape[discriminator]._def.value;
const possibleWraps = generatePossibleWraps(valueToValidate, option.shape, discriminator);
for (const wrap of possibleWraps) {
const finalWrap = { [discriminator]: discriminatorValue, ...wrap };
const testParse = schema.safeParse(finalWrap);
if (testParse.success) {
allSuccessfulWraps.push({ wrap: finalWrap });
break;
}
}
}
}
if (allSuccessfulWraps.length === 1) {
const wrapped = allSuccessfulWraps[0].wrap;
return { success: true, valueToValidate: wrapped, parsed: schema.safeParse(wrapped) };
}
return { success: false, valueToValidate, parsed: { success: false } };
}
function tryUnionWrapping(schema, valueToValidate) {
const options = schema._def.options;
let discriminator = schema._def.discriminator;
if (!discriminator) {
discriminator = detectDiscriminator(options);
}
if (!discriminator) {
return { success: false, valueToValidate, parsed: { success: false } };
}
const isValueObject = valueToValidate !== null && typeof valueToValidate === "object" && !Array.isArray(valueToValidate);
const isPrimitive = isValuePrimitive(valueToValidate);
if (isValueObject && !(discriminator in valueToValidate)) {
const result = tryAddDiscriminator(schema, options, discriminator, valueToValidate);
if (result.success) {
return result;
}
}
if (isPrimitive) {
return tryUnionPrimitiveWrapping(schema, options, discriminator, valueToValidate);
}
return { success: false, valueToValidate, parsed: { success: false } };
}
function trySmartWrapping(schema, schemaType, valueToValidate, alternativeValue) {
const valuesToTry = [valueToValidate];
if (alternativeValue !== undefined && alternativeValue !== valueToValidate) {
valuesToTry.push(alternativeValue);
}
for (const candidateValue of valuesToTry) {
const isPrimitive = isValuePrimitive(candidateValue);
if (schemaType === "ZodObject" && isPrimitive) {
const result = tryObjectWrapping(schema, candidateValue);
if (result.success) {
return result;
}
}
}
if (alternativeValue !== undefined && alternativeValue !== valueToValidate) {
valueToValidate = alternativeValue;
}
if (schemaType === "ZodDiscriminatedUnion" || schemaType === "ZodUnion") {
const result = tryUnionWrapping(schema, valueToValidate);
if (result.success) {
return result;
}
}
return { valueToValidate, parsed: { success: false } };
}
function parseExit(returnValue, exits) {
if (!returnValue) {
return {
success: false,
error: "No return value provided",
returnValue
};
}
const returnAction = returnValue.action;
if (!returnAction) {
return {
success: false,
error: `Code did not return an action. Valid actions are: ${exits.map((x) => x.name).join(", ")}`,
returnValue
};
}
const returnExit = exits.find((x) => x.name.toLowerCase() === returnAction.toLowerCase()) ?? exits.find((x) => x.aliases.some((a) => a.toLowerCase() === returnAction.toLowerCase()));
if (!returnExit) {
return {
success: false,
error: `Exit "${returnAction}" not found. Valid actions are: ${exits.map((x) => x.name).join(", ")}`,
returnValue
};
}
if (!returnExit.zSchema) {
const otherProps = omit_default(returnValue, "action");
const value = Object.keys(otherProps).length === 1 ? Object.values(otherProps)[0] : otherProps;
return {
success: true,
exit: returnExit,
value
};
}
let valueToValidate = returnValue.value;
let alternativeValue = undefined;
if (valueToValidate === undefined) {
const otherProps = omit_default(returnValue, "action");
if (Object.keys(otherProps).length > 0) {
valueToValidate = otherProps;
if (Object.keys(otherProps).length === 1) {
alternativeValue = Object.values(otherProps)[0];
}
}
}
const schema = returnExit.zSchema;
const schemaType = schema._def.typeName;
let parsed = schema.safeParse(valueToValidate);
if (!parsed.success && alternativeValue !== undefined && alternativeValue !== valueToValidate) {
const altParsed = schema.safeParse(alternativeValue);
if (altParsed.success) {
parsed = altParsed;
valueToValidate = alternativeValue;
}
}
if (!parsed.success) {
const result = trySmartWrapping(schema, schemaType, valueToValidate, alternativeValue);
valueToValidate = result.valueToValidate;
parsed = result.parsed;
}
if (!parsed.success) {
const getValueTypeDescription = (val) => {
if (val === null)
return "null";
if (val === undefined)
return "undefined";
if (Array.isArray(val))
return "array";
return typeof val;
};
const generatedType = getValueTypeDescription(valueToValidate);
let generatedStatement = `return { action: '${returnAction}'`;
if (returnValue.value !== undefined) {
generatedStatement += `, value: ${generatedType}`;
} else {
const otherProps = omit_default(returnValue, "action");
const propKeys = Object.keys(otherProps);
if (propKeys.length === 1) {
generatedStatement += `, ${propKeys[0]}: ${generatedType}`;
} else if (propKeys.length > 1) {
generatedStatement += `, ${propKeys.join(", ")}`;
}
}
generatedStatement += " }";
const expectedStatements = [];
for (const exit of exits) {
let statement = `return { action: '${exit.name}'`;
if (exit.zSchema) {
const schema2 = exit.zSchema;
const typeName = schema2._def.typeName;
if (typeName === "ZodObject") {
const shape = schema2.shape;
const properties = Object.keys(shape).map((key) => {
var _a;
const field = shape[key];
const fieldType = field._def.typeName || "unknown";
const isOptional = ((_a = field.isOptional) == null ? undefined : _a.call(field)) || false;
return `${key}${isOptional ? "?" : ""}: ${fieldType.replace("Zod", "").toLowerCase()}`;
});
statement += `, value: { ${properties.join(", ")} }`;
} else if (typeName === "ZodUnion" || typeName === "ZodDiscriminatedUnion") {
const options = schema2._def.options || [];
const variants = options.map((opt) => {
if (opt._def.typeName === "ZodObject") {
const shape = opt.shape;
const properties = Object.keys(shape).map((key) => {
const field = shape[key];
const fieldType = field._def.typeName || "unknown";
return `${key}: ${fieldType.replace("Zod", "").toLowerCase()}`;
});
return `{ ${properties.join(", ")} }`;
}
return "unknown";
});
statement += `, value: ${variants.join(" | ")}`;
} else {
const schemaTypeName = (typeName == null ? undefined : typeName.replace("Zod", "").toLowerCase()) || "unknown";
statement += `, value: ${schemaTypeName}`;
}
}
statement += " }";
expectedStatements.push(statement);
}
const errorMessage = [
`Invalid return value for exit "${returnExit.name}"`,
"",
"You generated:",
` ${generatedStatement}`,
"",
"But expected one of:",
...expectedStatements.map((s) => ` ${s}`)
].join(`
`);
return {
success: false,
error: errorMessage,
returnValue
};
}
return {
success: true,
exit: returnExit,
value: parsed.data
};
}
var MAX_SNAPSHOT_SIZE_BYTES = 4000;
var Snapshot = class _Snapshot {
id;
reason;
stack;
toolCall;
variables;
#status;
get status() {
return Object.freeze({ ...this.#status });
}
constructor(props) {
this.id = props.id;
this.stack = props.stack;
this.reason = props.reason;
this.variables = props.variables;
this.toolCall = props.toolCall;
this.#status = props.status;
}
static fromSignal(signal) {
return new _Snapshot({
id: "snapshot_" + ulid(),
reason: signal.message,
stack: signal.truncatedCode,
variables: parseVariables(signal.variables),
toolCall: signal.toolCall,
status: { type: "pending" }
});
}
toJSON() {
return {
id: this.id,
reason: this.reason,
stack: this.stack,
variables: this.variables,
toolCall: this.toolCall,
status: this.#status
};
}
static fromJSON(json) {
return new _Snapshot({
id: json.id,
reason: json.reason,
stack: json.stack,
variables: json.variables,
toolCall: json.toolCall,
status: json.status
});
}
clone() {
return new _Snapshot({
id: this.id,
reason: this.reason,
stack: this.stack,
variables: this.variables,
toolCall: this.toolCall,
status: this.#status
});
}
reset() {
this.#status = { type: "pending" };
}
resolve(value) {
var _a;
if (this.#status.type !== "pending") {
throw new Error(`Cannot resolve snapshot because it is already settled: ${this.#status.type}`);
}
const assignment = (_a = this.toolCall) == null ? undefined : _a.assignment;
if (assignment) {
try {
const fn = new Function(assignment.evalFn);
const assignmentValue = fn(value);
this.variables = [...this.variables, ...parseVariables(assignmentValue)];
} catch {}
}
this.#status = { type: "resolved", value };
}
reject(error) {
if (this.#status.type !== "pending") {
throw new Error(`Cannot reject snapshot because it is already settled: ${this.#status.type}`);
}
this.#status = { type: "rejected", error };
}
};
function parseVariables(variableMap) {
return Object.entries(variableMap).map(([name, value]) => {
const type = extractType(value);
const bytes = JSON.stringify(value || "").length;
const truncated = bytes > MAX_SNAPSHOT_SIZE_BYTES;
return truncated ? { name, type, bytes, truncated: true, preview: inspect(value, name) ?? "N/A" } : { name, type, bytes, truncated: false, value };
});
}
var MAX_MESSAGE_LENGTH = 5000;
function getMessagePreview(message) {
if (message.role === "assistant" || message.role === "user" || message.role === "summary") {
return message.content;
}
if (message.role === "event") {
return inspect(message.payload, message.name, { tokens: 1000 });
}
return inspect(message, undefined, { tokens: 1000 });
}
function getMessageType(message) {
if (message.role === "assistant" || message.role === "user" || message.role === "summary") {
return message.role;
}
if (message.role === "event") {
return `event:${message.name}`;
}
return "unknown";
}
var TranscriptArray = class extends Array {
constructor(items = []) {
items = Array.isArray(items) ? items : [];
super(...items);
items.forEach((item) => {
if (!["user", "assistant", "event", "summary"].includes(item.role)) {
throw new Error(`Invalid role "${item.role}" in transcript message`);
}
if ("name" in item && item.name && typeof item.name !== "string") {
throw new Error(`Invalid name for transcript message. Expected a string, but got type "${typeof item.name}"`);
}
if ("content" in item && typeof item.content !== "string") {
throw new Error(`Invalid content for transcript message. Expected a string, but got type "${typeof item.content}"`);
}
});
Object.setPrototypeOf(this, new.target.prototype);
}
toString() {
if (!this.length) {
return "";
}
return this.map((item, idx) => {
var _a, _b;
const msgIdx = getMessageType(item) + "-" + String(idx + 1).padStart(3, "0");
let preview = getMessagePreview(item);
if (preview.length > MAX_MESSAGE_LENGTH) {
preview = preview.slice(0, MAX_MESSAGE_LENGTH) + `
... (truncated)`;
}
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
if ((item.role === "event" || item.role === "user") && ((_a = item.attachments) == null ? undefined : _a.length)) {
for (let i = 0;i < item.attachments.length; i++) {
const attachmentIdx = alphabet[i % alphabet.length];
preview += `
[Attachment ${msgIdx}-${attachmentIdx}]`;
}
}
const tags = [];
tags.push({ key: "role", value: item.role });
if ("name" in item && ((_b = item.name) == null ? undefined : _b.length)) {
tags.push({ key: "name", value: item.name });
}
const tagsString = tags.map(({ key, value }) => `${key}="${value}"`).join(" ");
return `<${msgIdx} ${tagsString}>
${preview.trim()}
</${msgIdx}>`;
}).join(`
`);
}
};
var ExecutionResult = class {
status;
context;
constructor(status, context) {
this.status = status;
this.context = context;
}
isSuccess() {
return this.status === "success" && this instanceof SuccessExecutionResult;
}
isError() {
return this.status === "error" && this instanceof ErrorExecutionResult;
}
isInterrupted() {
return this.status === "interrupted" && this instanceof PartialExecutionResult;
}
is(exit) {
return this.status === "success" && this instanceof SuccessExecutionResult && this.result.exit === exit;
}
get output() {
return this.isSuccess() ? this.result.result : null;
}
get iteration() {
return this.context.iterations.at(-1) || null;
}
get iterations() {
return this.context.iterations ?? [];
}
};
var SuccessExecutionResult = class extends ExecutionResult {
result;
constructor(context, result) {
super("success", context);
this.result = result;
}
get output() {
return this.result.result;
}
get iteration() {
return this.context.iterations.at(-1);
}
toJSON() {
return {
status: "success",
context: this.context.toJSON(),
result: {
exit: this.result.exit.toJSON(),
result: this.result.result
}
};
}
};
var ErrorExecutionResult = class extends ExecutionResult {
error;
constructor(context, error) {
super("error", context);
this.error = error;
}
get output() {
return null;
}
toJSON() {
return {
status: "error",
context: this.context.toJSON(),
error: this.error
};
}
};
var PartialExecutionResult = class extends ExecutionResult {
signal;
snapshot;
constructor(context, signal, snapshot) {
super("interrupted", context);
this.signal = signal;
this.snapshot = snapshot;
}
get output() {
return null;
}
toJSON() {
return {
status: "interrupted",
context: this.context.toJSON(),
snapshot: this.snapshot.toJSON(),
signal: {
message: this.signal.message,
truncatedCode: this.signal.truncatedCode,
variables: this.signal.variables
}
};
}
};
var getValue = async (valueOrGetter, ctx) => {
if (typeof valueOrGetter === "function") {
try {
return await valueOrGetter(ctx);
} catch (e) {
throw new Error(`Error while getting value for ${valueOrGetter}: ${e}`);
}
} else {
return valueOrGetter;
}
};
var Emitter = class {
_handlers = [];
subscribe = (fn) => {
this._handlers.push(fn);
return () => {
this._handlers = this._handlers.filter((handler) => handler !== fn);
};
};
emit(event) {
this._handlers.forEach((handler) => handler(event));
}
};
var HookedArray = class extends Array {
#listeners = new Emitter;
constructor(...items) {
super(...items);
Object.setPrototypeOf(this, new.target.prototype);
}
push(...items) {
try {
this.#listeners.emit(items);
} finally {
return super.push(...items);
}
}
onPush(fn) {
return this.#listeners.subscribe(fn);
}
};
var ThinkExit = new Exit({
name: "think",
description: "Think about the current situation and provide a response"
});
var ListenExit = new Exit({
name: "listen",
description: "Listen to the user and provide a response"
});
var DefaultExit = new Exit({
name: "done",
description: "When the execution is sucessfully completed or when error recovery is not possible",
schema: exports_exports.discriminatedUnion("success", [
exports_exports.object({
success: exports_exports.literal(true),
result: exports_exports.any().describe("The result of the execution")
}),
exports_exports.object({
success: exports_exports.literal(false),
error: exports_exports.string().describe("The error message if the execution failed")
})
])
});
var Iteration = class {
id;
messages;
code;
traces;
variables;
started_ts;
ended_ts;
status;
_mutations;
get mutations() {
return [...this._mutations.values()];
}
trackMutation(mutation) {
this._mutations.set(`${mutation.object ?? "global"}:${mutation.property}`, mutation);
}
_parameters;
get transcript() {
return this._parameters.transcript;
}
get tools() {
return this._parameters.tools;
}
get objects() {
return this._parameters.objects;
}
get model() {
return this._parameters.model;
}
set model(value) {
this._parameters.model = value;
}
get temperature() {
return this._parameters.temperature;
}
get reasoningEffort() {
return this._parameters.reasoningEffort;
}
get exits() {
const exits = [...this._parameters.exits, ThinkExit];
if (this.isChatEnabled) {
exits.push(ListenExit);
}
return exits;
}
get instructions() {
return this._parameters.instructions;
}
llm;
hasExited() {
return ["exit_success"].includes(this.status.type);
}
hasExitedWith(exit) {
return this.status.type === "exit_success" && this.status.exit_success.exit_name === exit.name;
}
isSuccessful() {
return ["callback_requested", "exit_success", "thinking_requested"].includes(this.status.type);
}
isFailed() {
return [
"generation_error",
"invalid_code_error",
"execution_error",
"exit_error",
"aborted"
].includes(this.status.type);
}
get duration() {
const ms = (this.ended_ts ?? Date.now()) - this.started_ts;
const trailing = this.ended_ts ? "" : " (still running)";
return ms.toLocaleString("en-US", { style: "unit", unit: "millisecond" }) + trailing;
}
get error() {
if (this.status.type === "generation_error") {
return `CodeGenerationError: ${this.status.generation_error.message}`;
}
if (this.status.type === "invalid_code_error") {
return `InvalidCodeError: ${this.status.invalid_code_error.message}`;
}
if (this.status.type === "execution_error") {
return `CodeExecutionError: ${this.status.execution_error.message}`;
}
if (this.status.type === "exit_error") {
return `ExitError: ${this.status.exit_error.message}`;
}
if (this.status.type === "aborted") {
return `Aborted: ${this.status.aborted.reason}`;
}
return null;
}
get isChatEnabled() {
return this._parameters.tools.find((x) => x.name.toLowerCase() === "message") !== undefined;
}
constructor(props) {
this.id = props.id;
this.status = { type: "pending" };
this.traces = new HookedArray;
this._mutations = /* @__PURE__ */ new Map;
this.messages = props.messages;
this.variables = props.variables;
this._parameters = props.parameters;
this.started_ts = Date.now();
}
end(status) {
if (this.status.type !== "pending") {
throw new Error(`Iteration ${this.id} has already ended with status ${this.status.type}`);
}
this.ended_ts = Date.now();
this.status = status;
}
toJSON() {
return {
id: this.id,
messages: [...this.messages],
code: this.code,
model: this.model,
temperature: this.temperature,
reasoningEffort: this.reasoningEffort,
traces: [...this.traces],
variables: this.variables,
started_ts: this.started_ts,
ended_ts: this.ended_ts,
status: this.status,
mutations: [...this._mutations.values()],
llm: this.llm,
transcript: [...this._parameters.transcript],
tools: this._parameters.tools.map((tool) => tool.toJSON()),
objects: this._parameters.objects.map((obj) => obj.toJSON()),
exits: this._parameters.exits.map((exit) => exit.toJSON()),
instructions: this._parameters.instructions,
duration: this.duration,
error: this.error,
isChatEnabled: this.isChatEnabled
};
}
};
var Context = class {
id;
chat;
instructions;
objects;
tools;
exits;
model;
temperature;
reasoningEffort;
version = DualModePrompt;
timeout = 60000;
loop;
metadata;
snapshot;
iteration = 0;
iterations;
async nextIteration() {
if (this.iterations.length >= this.loop) {
throw new LoopExceededError;
}
if (this.snapshot && this.snapshot.status.type === "pending") {
throw new Error(`Cannot resume execution from a snapshot that is still pending: ${this.snapshot.id}. Please resolve() or reject() it first.`);
}
const parameters = await this._refreshIterationParameters();
const messages = await this._getIterationMessages(parameters);
const iteration = new Iteration({
id: `${this.id}_${this.iterations.length + 1}`,
variables: this._getIterationVariables(),
parameters,
messages
});
this.iterations.push(iteration);
this.iteration = this.iterations.length;
this.snapshot = undefined;
return iteration;
}
_getIterationVariables() {
var _a;
const lastIteration = this.iterations.at(-1);
const variables = {};
if ((lastIteration == null ? undefined : lastIteration.status.type) === "thinking_requested") {
const lastThinkingVariables = lastIteration.status.thinking_requested.variables;
if (isPlainObject_default(lastThinkingVariables)) {
Object.assign(variables, cloneDeep_default(lastThinkingVariables));
}
}
if (isPlainObject_default(lastIteration == null ? undefined : lastIteration.variables)) {
Object.assign(variables, cloneDeep_default((lastIteration == null ? undefined : lastIteration.variables) ?? {}));
}
if (((_a = this.snapshot) == null ? undefined : _a.status.type) === "resolved") {
for (const v of this.snapshot.variables) {
if (!v.truncated && v.value !== undefined) {
variables[v.name] = v.value;
}
}
}
return variables;
}
async _getIterationMessages(parameters) {
var _a, _b, _c, _d, _e, _f;
const lastIteration = this.iterations.at(-1);
if (((_a = this.snapshot) == null ? undefined : _a.status.type) === "resolved") {
return [
await this.version.getSystemMessage({
globalTools: parameters.tools,
objects: parameters.objects,
instructions: parameters.instructions,
transcript: parameters.transcript,
exits: parameters.exits,
components: parameters.components
}),
this.version.getSnapshotResolvedMessage({
snapshot: this.snapshot
})
];
}
if (((_b = this.snapshot) == null ? undefined : _b.status.type) === "rejected") {
return [
await this.version.getSystemMessage({
globalTools: parameters.tools,
objects: parameters.objects,
instructions: parameters.instructions,
transcript: parameters.transcript,
exits: parameters.exits,
components: parameters.components
}),
this.version.getSnapshotRejectedMessage({
snapshot: this.snapshot
})
];
}
if (!lastIteration) {
return [
await this.version.getSystemMessage({
globalTools: parameters.tools,
objects: parameters.objects,
instructions: parameters.instructions,
transcript: parameters.transcript,
exits: parameters.exits,
components: parameters.components
}),
await this.version.getInitialUserMessage({
globalTools: parameters.tools,
objects: parameters.objects,
instructions: parameters.instructions,
transcript: parameters.transcript,
exits: parameters.exits,
components: parameters.components
})
];
}
const lastIterationMessages = [
await this.version.getSystemMessage({
globalTools: parameters.tools,
objects: parameters.objects,
instructions: parameters.instructions,
transcript: parameters.transcript,
exits: parameters.exits,
components: parameters.components
}),
...lastIteration.messages.filter((x) => x.role !== "system")
];
if ((lastIteration == null ? undefined : lastIteration.status.type) === "thinking_requested") {
return [
...lastIterationMessages,
{
role: "assistant",
content: wrapContent(((_c = lastIteration.llm) == null ? undefined : _c.output) ?? "", { preserve: "top", flex: 4, minTokens: 25 })
},
await this.version.getThinkingMessage({
reason: lastIteration.status.thinking_requested.reason,
variables: lastIteration.status.thinking_requested.variables
})
];
}
if ((lastIteration == null ? undefined : lastIteration.status.type) === "exit_error") {
return [
...lastIterationMessages,
{
role: "assistant",
content: wrapContent(((_d = lastIteration.llm) == null ? undefined : _d.output) ?? "", { preserve: "top", flex: 4, minTokens: 25 })
},
await this.version.getInvalidCodeMessage({
code: lastIteration.code ?? "// No code generated",
message: `Invalid return statement (action: ${lastIteration.status.exit_error.exit}): ${lastIteration.status.exit_error.message}`
})
];
}
if ((lastIteration == null ? undefined : lastIteration.status.type) === "invalid_code_error") {
return [
...lastIterationMessages,
{
role: "assistant",
content: wrapContent(((_e = lastIteration.llm) == null ? undefined : _e.output) ?? "", { preserve: "top", flex: 4, minTokens: 25 })
},
await this.version.getInvalidCodeMessage({
code: lastIteration.code ?? "// No code generated",
message: lastIteration.status.invalid_code_error.message
})
];
}
if ((lastIteration == null ? undefined : lastIteration.status.type) === "execution_error") {
return [
...lastIterationMessages,
{
role: "assistant",
content: wrapContent(((_f = lastIteration.llm) == null ? undefined : _f.output) ?? "", { preserve: "top", flex: 4, minTokens: 25 })
},
await this.version.getCodeExecutionErrorMessage({
message: lastIteration.status.execution_error.message,
stacktrace: lastIteration.status.execution_error.stack
})
];
}
throw new Error(`Unexpected iteration status: ${lastIteration == null ? undefined : lastIteration.status.type}. This is likely a bug, please report it.`);
}
async _refreshIterationParameters() {
var _a, _b;
const instructions = await getValue(this.instructions, this);
const transcript = new TranscriptArray(await getValue(((_a = this.chat) == null ? undefined : _a.transcript) ?? [], this));
const tools = Tool.withUniqueNames(await getValue(this.tools, this) ?? []);
const objects = await getValue(this.objects, this) ?? [];
const exits = await getValue(this.exits, this) ?? [];
const components = await getValue(((_b = this.chat) == null ? undefined : _b.components) ?? [], this);
const model = await getValue(this.model, this) ?? "best";
const temperature = await getValue(this.temperature, this);
const reasoningEffort = await getValue(this.reasoningEffort, this);
if (objects && objects.length > 100) {
throw new Error("Too many objects. Expected at most 100 objects.");
}
if (tools && tools.length > 100) {
throw new Error("Too many tools. Expected at most 100 tools.");
}
for (const component of components) {
assertValidComponent(component.definition);
}
const ReservedToolNames = [
"think",
"listen",
"return",
"exit",
"action",
"function",
"callback",
"code",
"execute",
"jsx",
"object",
"string",
"number",
"boolean",
"array"
];
const MessageTool = this.chat && components.length ? new Tool({
name: "Message",
description: "Send a message to the user",
aliases: Array.from(/* @__PURE__ */ new Set(["message", ...components.flatMap((x) => [x.definition.name, ...x.definition.aliases ?? []])])),
handler: async (message) => {
var _a2, _b2;
return await ((_b2 = (_a2 = this.chat) == null ? undefined : _a2.handler) == null ? undefined : _b2.call(_a2, message));
}
}) : null;
const allTools = MessageTool ? [MessageTool, ...tools] : tools;
for (const tool of tools) {
for (let name of [...tool.aliases, tool.name]) {
name = name.toLowerCase();
if (ReservedToolNames.includes(name)) {
throw new Error(`Tool name "${name}" (${tool.name}) is reserved. Please choose a different name.`);
}
if (components.find((x) => {
var _a2;
return x.definition.name.toLowerCase() === name || ((_a2 = x.definition.aliases) == null ? undefined : _a2.map((x2) => x2.toLowerCase()).includes(name));
})) {
throw new Error(`Tool name "${name}" (${tool.name}) is already used by a component. Please choose a different name.`);
}
if (exits.find((x) => x.name.toLowerCase() === name) || exits.find((x) => {
var _a2;
return (_a2 = x.aliases) == null ? undefined : _a2.map((x2) => x2.toLowerCase()).includes(name);
})) {
throw new Error(`Tool name "${name}" (${tool.name}) is already used by an exit. Please choose a different name.`);
}
}
}
if (exits && exits.length > 100) {
throw new Error("Too many exits. Expected at most 100 exits.");
}
if (components && components.length > 100) {
throw new Error("Too many components. Expected at most 100 components.");
}
if (instructions && instructions.length > 1e6) {
throw new Error("Instructions are too long. Expected at most 1,000,000 characters.");
}
if (transcript && transcript.length > 250) {
throw new Error("Too many transcript messages. Expected at most 250 messages.");
}
if (!components.length && !exits.length) {
exits.push(DefaultExit);
}
if (typeof temperature !== "number" || isNaN(temperature) || temperature < 0 || temperature > 2) {
throw new Error("Invalid temperature. Expected a number between 0 and 2.");
}
const isValidModel = (m) => typeof m === "string" && (m === "best" || m === "fast" || m === "auto" || m.includes(":"));
if (Array.isArray(model)) {
if (model.length === 0 || !model.every(isValidModel)) {
throw new Error("Invalid model. Expected a non-empty array of model strings ('best'/'fast'/'auto' or 'provider:model').");
}
} else if (!isValidModel(model)) {
throw new Error("Invalid model. Expected 'best'/'fast'/'auto' or 'provider:model'.");
}
return {
transcript,
tools: allTools,
objects,
exits,
instructions,
components,
model,
temperature,
reasoningEffort
};
}
constructor(props) {
this.id = `llmz_${ulid()}`;
this.instructions = props.instructions;
this.objects = props.objects;
this.tools = props.tools;
this.exits = props.exits;
this.chat = props.chat;
this.timeout = Math.min(999999999, Math.max(0, props.timeout ?? 60000));
this.loop = props.loop ?? 3;
this.temperature = props.temperature ?? 0.7;
this.reasoningEffort = props.reasoningEffort;
this.model = props.model ?? "best";
this.iterations = [];
this.metadata = props.metadata ?? {};
this.snapshot = props.snapshot;
if (this.loop < 1 || this.loop > 100) {
throw new Error("Invalid loop. Expected a number between 1 and 100.");
}
}
toJSON() {
var _a;
return {
id: this.id,
iterations: this.iterations.map((iteration) => iteration.toJSON()),
iteration: this.iteration,
timeout: this.timeout,
loop: this.loop,
metadata: this.metadata,
snapshot: (_a = this.snapshot) == null ? undefined : _a.toJSON()
};
}
};
export { ulid, parseExit, Snapshot, ExecutionResult, SuccessExecutionResult, ErrorExecutionResult, PartialExecutionResult, getValue, ThinkExit, ListenExit, DefaultExit, Context };