@statelyai/agent 2.0.0-alpha.28 → 2.0.0-alpha.30
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/dist/ai-sdk.cjs +150 -27
- package/dist/ai-sdk.d.cts +59 -36
- package/dist/ai-sdk.d.mts +59 -36
- package/dist/ai-sdk.mjs +148 -24
- package/dist/{decision-RQ0iv0oZ.mjs → decision-BHkvuImD.mjs} +74 -8
- package/dist/{decision-CmM8-HHz.cjs → decision-CIb7ddIv.cjs} +113 -30
- package/dist/{text-logic-f5F5sCdc.cjs → event-log-BZRfBRd7.cjs} +814 -7
- package/dist/{text-logic-CIqHAmBi.mjs → event-log-DJCMHek_.mjs} +680 -4
- package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CIIJohjj.d.mts} +90 -5
- package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-CLAC9q2Y.d.cts} +90 -5
- package/dist/event-log-store-DZR4IIWe.cjs +95 -0
- package/dist/event-log-store-DsP6GCRh.mjs +84 -0
- package/dist/index.cjs +576 -58
- package/dist/index.d.cts +104 -510
- package/dist/index.d.mts +104 -510
- package/dist/index.mjs +547 -32
- package/dist/log.cjs +77 -20
- package/dist/log.d.cts +5 -5
- package/dist/log.d.mts +5 -5
- package/dist/log.mjs +58 -3
- package/dist/machines.cjs +1 -1
- package/dist/machines.d.cts +15 -15
- package/dist/machines.d.mts +15 -15
- package/dist/machines.mjs +1 -1
- package/dist/model-source-BCKg4qJ1.cjs +44 -0
- package/dist/model-source-BaHwJ1wK.mjs +39 -0
- package/dist/openai.cjs +11 -11
- package/dist/openai.d.cts +28 -26
- package/dist/openai.d.mts +28 -26
- package/dist/openai.mjs +3 -3
- package/dist/otel.cjs +5 -4
- package/dist/otel.d.cts +5 -7
- package/dist/otel.d.mts +5 -7
- package/dist/otel.mjs +5 -3
- package/dist/{run-agent-xNTxpt82.mjs → run-agent-BpHqkaZw.mjs} +181 -44
- package/dist/{run-agent-COXXc0RW.d.mts → run-agent-CAVt5R-r.d.mts} +95 -30
- package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CTlMc3Jb.d.cts} +95 -30
- package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-ctLCvNgL.cjs} +230 -88
- package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-7rV_cujV.mjs} +15 -9
- package/dist/setup-agent-CGELn1qZ.d.mts +577 -0
- package/dist/setup-agent-CLPCkXsu.d.cts +577 -0
- package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DoUk7EdC.cjs} +31 -20
- package/dist/tanstack-ai.cjs +627 -0
- package/dist/tanstack-ai.d.cts +204 -0
- package/dist/tanstack-ai.d.mts +204 -0
- package/dist/tanstack-ai.mjs +618 -0
- package/dist/testing.cjs +204 -985
- package/dist/testing.d.cts +132 -347
- package/dist/testing.d.mts +132 -347
- package/dist/testing.mjs +191 -973
- package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-BRYOPWvY.d.mts} +52 -12
- package/dist/{text-logic-D-czVPYp.d.mts → text-logic-DmciuVUQ.d.cts} +52 -12
- package/dist/{types-BgNbNKnJ.d.mts → types-Dp5_Ru4R.d.cts} +2 -2
- package/dist/{types-hR5f5YXa.d.cts → types-Dp5_Ru4R.d.mts} +2 -2
- package/dist/usage-BkM3z02Y.d.mts +17 -0
- package/dist/usage-Cm_ovz9V.d.cts +17 -0
- package/dist/{utils-_q7F-AZu.d.mts → utils-BnXdWih3.d.mts} +1 -2
- package/dist/{utils-o4YRdHJX.d.cts → utils-ebVpCYoF.d.cts} +1 -2
- package/dist/validate.cjs +239 -8
- package/dist/validate.d.cts +110 -3
- package/dist/validate.d.mts +110 -3
- package/dist/validate.mjs +238 -7
- package/dist/verify-COFWyprJ.mjs +1181 -0
- package/dist/verify-CVlsTZ-V.cjs +1222 -0
- package/dist/verify-Cn86rT8l.d.mts +414 -0
- package/dist/verify-Dzwd4Mvk.d.cts +414 -0
- package/package.json +44 -31
- package/readme.md +40 -28
- package/skills/add-evals/SKILL.md +129 -0
- package/skills/add-traces/SKILL.md +135 -0
- package/skills/generate-machine/SKILL.md +143 -69
- package/skills/graph-engineering/SKILL.md +33 -0
- package/skills/improve-machine/SKILL.md +241 -0
- package/skills/improve-machine/reference.md +101 -0
- package/skills/loop-to-machine/SKILL.md +183 -0
- package/skills/loop-to-machine/policy.md +158 -0
- package/dist/event-log-store-2pAFiWuc.mjs +0 -576
- package/dist/event-log-store-C-COhIXP.cjs +0 -702
- package/dist/usage-BdEjFuIi.mjs +0 -5
- package/dist/usage-efOQPdf_.cjs +0 -10
package/dist/index.cjs
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const
|
|
3
|
-
const require_decision = require("./decision-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
2
|
+
const require_event_log = require("./event-log-BZRfBRd7.cjs");
|
|
3
|
+
const require_decision = require("./decision-CIb7ddIv.cjs");
|
|
4
|
+
const require_setup_agent = require("./setup-agent-DoUk7EdC.cjs");
|
|
5
|
+
const require_event_log_store = require("./event-log-store-DZR4IIWe.cjs");
|
|
6
|
+
const require_run_agent = require("./run-agent-ctLCvNgL.cjs");
|
|
7
|
+
let xstate = require("xstate");
|
|
8
8
|
//#region src/messages.ts
|
|
9
|
-
const KNOWN_PART_TYPES = new Set([
|
|
9
|
+
const KNOWN_PART_TYPES = /* @__PURE__ */ new Set([
|
|
10
10
|
"text",
|
|
11
11
|
"image",
|
|
12
12
|
"file",
|
|
13
13
|
"tool-call",
|
|
14
14
|
"tool-result"
|
|
15
15
|
]);
|
|
16
|
-
const USER_PART_TYPES = new Set([
|
|
16
|
+
const USER_PART_TYPES = /* @__PURE__ */ new Set([
|
|
17
17
|
"text",
|
|
18
18
|
"image",
|
|
19
19
|
"file"
|
|
20
20
|
]);
|
|
21
|
-
const ASSISTANT_PART_TYPES = new Set([
|
|
21
|
+
const ASSISTANT_PART_TYPES = /* @__PURE__ */ new Set([
|
|
22
22
|
"text",
|
|
23
23
|
"file",
|
|
24
24
|
"tool-call",
|
|
25
25
|
"tool-result"
|
|
26
26
|
]);
|
|
27
|
-
const TOOL_PART_TYPES = new Set(["tool-result"]);
|
|
28
|
-
const TOOL_RESULT_CONTENT_PART_TYPES = new Set(["text", "image"]);
|
|
27
|
+
const TOOL_PART_TYPES = /* @__PURE__ */ new Set(["tool-result"]);
|
|
28
|
+
const TOOL_RESULT_CONTENT_PART_TYPES = /* @__PURE__ */ new Set(["text", "image"]);
|
|
29
29
|
function isKnownPart(part) {
|
|
30
30
|
const type = part && typeof part === "object" ? part.type : void 0;
|
|
31
31
|
return typeof type === "string" && KNOWN_PART_TYPES.has(type);
|
|
@@ -39,7 +39,7 @@ function isMediaData(value) {
|
|
|
39
39
|
function requireMediaData(part, type, field) {
|
|
40
40
|
return isMediaData(part[field]) ? void 0 : `${type} part requires "${field}" to be a string, Uint8Array, ArrayBuffer, or URL`;
|
|
41
41
|
}
|
|
42
|
-
const TOOL_RESULT_OUTPUT_TYPES = new Set([
|
|
42
|
+
const TOOL_RESULT_OUTPUT_TYPES = /* @__PURE__ */ new Set([
|
|
43
43
|
"text",
|
|
44
44
|
"json",
|
|
45
45
|
"error-text",
|
|
@@ -153,11 +153,22 @@ function validateEventMeta(value, path) {
|
|
|
153
153
|
if (event !== void 0 && (!event || typeof event !== "object" || Array.isArray(event))) issues.push(issue("Expected an object of fixed event fields", [...path, "event"]));
|
|
154
154
|
return issues;
|
|
155
155
|
}
|
|
156
|
+
function validateChoice(value, path) {
|
|
157
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return [issue("Expected a { label, event } choice", path)];
|
|
158
|
+
const choice = value;
|
|
159
|
+
const issues = [];
|
|
160
|
+
if (typeof choice["label"] !== "string") issues.push(issue("Expected a string", [...path, "label"]));
|
|
161
|
+
if (choice["style"] !== void 0 && typeof choice["style"] !== "string") issues.push(issue("Expected a string", [...path, "style"]));
|
|
162
|
+
const event = choice["event"];
|
|
163
|
+
if (!event || typeof event !== "object" || Array.isArray(event) || typeof event.type !== "string") issues.push(issue("Expected an event object with a string `type`", [...path, "event"]));
|
|
164
|
+
return issues;
|
|
165
|
+
}
|
|
156
166
|
/**
|
|
157
167
|
* A {@link StandardSchemaV1} for the state metadata {@link getInteraction}
|
|
158
168
|
* reads: an object whose optional `interaction` declares a `label` (a string
|
|
159
169
|
* with `{context.path}` interpolation, or a function of the context), an
|
|
160
|
-
* `events` map of choices,
|
|
170
|
+
* `events` map of choices, payload `choices` (an array, or a context path to
|
|
171
|
+
* one), and a `textEvent` (a type, or `{ type, field }`) for free-text answers. This is
|
|
161
172
|
* the default `meta` type `setupAgent` gives a machine; pass it to
|
|
162
173
|
* `createAgentSchemas({ meta: interactionMetaSchema })` only when building a
|
|
163
174
|
* schema pack by hand.
|
|
@@ -175,13 +186,27 @@ const interactionMetaSchema = { "~standard": {
|
|
|
175
186
|
const label = descriptor["label"];
|
|
176
187
|
if (label !== void 0 && typeof label !== "string" && typeof label !== "function") issues.push(issue("Expected a string or a (context) => string", ["interaction", "label"]));
|
|
177
188
|
const events = descriptor["events"];
|
|
178
|
-
if (events !== void 0)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
189
|
+
if (events !== void 0) {
|
|
190
|
+
if (!events || typeof events !== "object" || Array.isArray(events)) issues.push(issue("Expected an object keyed by event type", ["interaction", "events"]));
|
|
191
|
+
else for (const [type, config] of Object.entries(events)) issues.push(...validateEventMeta(config, [
|
|
192
|
+
"interaction",
|
|
193
|
+
"events",
|
|
194
|
+
type
|
|
195
|
+
]));
|
|
196
|
+
}
|
|
197
|
+
const choices = descriptor["choices"];
|
|
198
|
+
if (choices !== void 0 && typeof choices !== "string") {
|
|
199
|
+
if (!Array.isArray(choices)) issues.push(issue("Expected an array of choices or a context path string", ["interaction", "choices"]));
|
|
200
|
+
else choices.forEach((choice, index) => {
|
|
201
|
+
issues.push(...validateChoice(choice, [
|
|
202
|
+
"interaction",
|
|
203
|
+
"choices",
|
|
204
|
+
index
|
|
205
|
+
]));
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
const textEvent = descriptor["textEvent"];
|
|
209
|
+
if (textEvent !== void 0 && typeof textEvent !== "string" && !(textEvent && typeof textEvent === "object" && typeof textEvent.type === "string" && typeof textEvent.field === "string")) issues.push(issue("Expected a string or { type, field }", ["interaction", "textEvent"]));
|
|
185
210
|
return issues.length > 0 ? { issues } : { value };
|
|
186
211
|
}
|
|
187
212
|
} };
|
|
@@ -198,13 +223,20 @@ function interpolate(label, context, preserveWhitespace) {
|
|
|
198
223
|
});
|
|
199
224
|
return preserveWhitespace ? interpolated : interpolated.replace(/\s+/g, " ").trim();
|
|
200
225
|
}
|
|
226
|
+
function eventSchemasOf(snapshot) {
|
|
227
|
+
const machine = snapshot.machine;
|
|
228
|
+
return require_event_log.getAgentExecutionOptions(machine)?.schemas?.events ?? (machine?.schemas)?.events;
|
|
229
|
+
}
|
|
230
|
+
function isChoice(value) {
|
|
231
|
+
return validateChoice(value, []).length === 0;
|
|
232
|
+
}
|
|
201
233
|
/** Reads the active state's interaction metadata and filters it through the
|
|
202
234
|
* events XState currently accepts. Returns `undefined` when none is declared. */
|
|
203
235
|
function getInteraction(snapshot, options = {}) {
|
|
204
|
-
const interaction =
|
|
236
|
+
const interaction = require_event_log.getStateMeta(snapshot).interaction;
|
|
205
237
|
if (!interaction) return void 0;
|
|
206
238
|
const preserveWhitespace = options.preserveWhitespace ?? false;
|
|
207
|
-
const
|
|
239
|
+
const eventSchemas = eventSchemasOf(snapshot);
|
|
208
240
|
const accepted = new Set(require_decision.getAcceptedEvents(snapshot).map((event) => event.type));
|
|
209
241
|
const label = typeof interaction.label === "function" ? interaction.label({ context: snapshot.context }) : interaction.label ?? "";
|
|
210
242
|
const events = Object.entries(interaction.events ?? {}).filter((entry) => entry[1] !== void 0 && accepted.has(entry[0])).map(([type, config]) => {
|
|
@@ -214,7 +246,7 @@ function getInteraction(snapshot, options = {}) {
|
|
|
214
246
|
const complete = require_decision.parseAgentEvent(snapshot, {
|
|
215
247
|
...descriptor.event,
|
|
216
248
|
type
|
|
217
|
-
}, {
|
|
249
|
+
}, { events: eventSchemas });
|
|
218
250
|
return snapshot.can(complete);
|
|
219
251
|
} catch {
|
|
220
252
|
return true;
|
|
@@ -227,23 +259,61 @@ function getInteraction(snapshot, options = {}) {
|
|
|
227
259
|
...descriptor.event ? { event: descriptor.event } : {}
|
|
228
260
|
};
|
|
229
261
|
});
|
|
262
|
+
const declaresChoices = interaction.choices !== void 0;
|
|
263
|
+
const declared = typeof interaction.choices === "string" ? readPath(snapshot.context, interaction.choices) : interaction.choices;
|
|
264
|
+
const choices = (Array.isArray(declared) ? declared : []).filter(isChoice).filter((choice) => {
|
|
265
|
+
try {
|
|
266
|
+
const event = require_decision.parseAgentEvent(snapshot, choice.event, { events: eventSchemas });
|
|
267
|
+
return snapshot.can(event);
|
|
268
|
+
} catch {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
}).map((choice) => ({
|
|
272
|
+
label: interpolate(choice.label, snapshot.context, preserveWhitespace),
|
|
273
|
+
event: choice.event,
|
|
274
|
+
...choice.style ? { style: choice.style } : {}
|
|
275
|
+
}));
|
|
276
|
+
const text = typeof interaction.textEvent === "string" ? {
|
|
277
|
+
type: interaction.textEvent,
|
|
278
|
+
field: "text"
|
|
279
|
+
} : interaction.textEvent;
|
|
230
280
|
return {
|
|
231
281
|
label: interpolate(label, snapshot.context, preserveWhitespace),
|
|
232
282
|
events,
|
|
233
|
-
...
|
|
283
|
+
...declaresChoices ? { choices } : {},
|
|
284
|
+
...text && accepted.has(text.type) ? {
|
|
285
|
+
textEvent: text.type,
|
|
286
|
+
...text.field !== "text" ? { textField: text.field } : {}
|
|
287
|
+
} : {}
|
|
234
288
|
};
|
|
235
289
|
}
|
|
236
|
-
/**
|
|
237
|
-
*
|
|
290
|
+
/**
|
|
291
|
+
* Converts a rendered interaction answer back into a schema-validated machine
|
|
292
|
+
* event:
|
|
293
|
+
*
|
|
294
|
+
* - `{ type, ...fields }` — an `events` choice; fixed fields declared in
|
|
295
|
+
* metadata win over user fields.
|
|
296
|
+
* - `{ text }` — free text, placed in the `textEvent` field.
|
|
297
|
+
* - `{ choice }` — a payload choice, by its index in `getInteraction(snapshot).choices`
|
|
298
|
+
* or by its label. A label that several choices share throws; pass the index.
|
|
299
|
+
*/
|
|
238
300
|
function eventFromInteraction(snapshot, choice) {
|
|
239
301
|
const interaction = getInteraction(snapshot);
|
|
240
302
|
if (!interaction) throw new require_decision.AgentInvalidEventPayloadError("(interaction)", "this state renders no interaction, so there is no choice to convert.");
|
|
241
303
|
let event;
|
|
242
|
-
if ("
|
|
304
|
+
if (!("type" in choice) && "choice" in choice) {
|
|
305
|
+
const choices = interaction.choices ?? [];
|
|
306
|
+
const key = choice.choice;
|
|
307
|
+
const labeled = typeof key === "number" ? [] : choices.flatMap((candidate, index) => candidate.label === key ? [index] : []);
|
|
308
|
+
if (labeled.length > 1) throw new require_decision.AgentInvalidEventPayloadError("(choice)", `${labeled.length} choices are labeled ${JSON.stringify(key)} (indexes ${labeled.join(", ")}); pass { choice: <index> } to pick one.`);
|
|
309
|
+
const picked = typeof key === "number" ? choices[key] : choices[labeled[0] ?? -1];
|
|
310
|
+
if (!picked) throw new require_decision.AgentInvalidEventPayloadError("(choice)", `this interaction offers no choice ${JSON.stringify(key)}. Choices: ${choices.map(({ label }) => JSON.stringify(label)).join(", ") || "(none)"}.`);
|
|
311
|
+
event = { ...picked.event };
|
|
312
|
+
} else if ("text" in choice) {
|
|
243
313
|
if (!interaction.textEvent) throw new require_decision.AgentInvalidEventPayloadError("(text)", `this interaction takes no free text. Choices: ${interaction.events.map(({ type }) => type).join(", ") || "(none)"}.`);
|
|
244
314
|
event = {
|
|
245
315
|
type: interaction.textEvent,
|
|
246
|
-
text: choice.text
|
|
316
|
+
[interaction.textField ?? "text"]: choice.text
|
|
247
317
|
};
|
|
248
318
|
} else {
|
|
249
319
|
const descriptor = interaction.events.find(({ type }) => type === choice.type);
|
|
@@ -254,7 +324,452 @@ function eventFromInteraction(snapshot, choice) {
|
|
|
254
324
|
type: choice.type
|
|
255
325
|
};
|
|
256
326
|
}
|
|
257
|
-
return require_decision.parseAgentEvent(snapshot, event);
|
|
327
|
+
return require_decision.parseAgentEvent(snapshot, event, { events: eventSchemasOf(snapshot) });
|
|
328
|
+
}
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region src/describe-machine.ts
|
|
331
|
+
/**
|
|
332
|
+
* A machine, described in plain text for a model to read: the prompt for a
|
|
333
|
+
* model that proposes an improved machine, or extra context for a decider.
|
|
334
|
+
*
|
|
335
|
+
* The text is read from the machine's own definition (`machineToJSON`):
|
|
336
|
+
* for a `setupAgent.fromConfig(...)` machine that is the lowered JSON config,
|
|
337
|
+
* so every target, guard and context patch is data; for a TS-authored machine,
|
|
338
|
+
* transitions written as functions are read from their source.
|
|
339
|
+
*
|
|
340
|
+
* @module
|
|
341
|
+
*/
|
|
342
|
+
const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
343
|
+
const toList = (value) => value === void 0 ? [] : Array.isArray(value) ? value : [value];
|
|
344
|
+
const oneLine = (text) => text.replace(/\s+/g, " ").trim();
|
|
345
|
+
/** The source of a function as serialized (`{ "@code" }`) or as a live function. */
|
|
346
|
+
function codeOf(value) {
|
|
347
|
+
if (typeof value === "function") return String(value);
|
|
348
|
+
if (isObject(value) && typeof value["@code"] === "string") return value["@code"];
|
|
349
|
+
}
|
|
350
|
+
/** The decoded value of a fromConfig `{ "@expr": "<json>" }` slot, or the value itself. */
|
|
351
|
+
function decodeExpr(value) {
|
|
352
|
+
if (isObject(value) && typeof value["@expr"] === "string") try {
|
|
353
|
+
return JSON.parse(value["@expr"]);
|
|
354
|
+
} catch {
|
|
355
|
+
return value["@expr"];
|
|
356
|
+
}
|
|
357
|
+
return value;
|
|
358
|
+
}
|
|
359
|
+
/** A target as written, resolved from the state the transition leaves: `#id`, `.child`, or a sibling (`sibling.child`). */
|
|
360
|
+
function resolveTarget(source, target) {
|
|
361
|
+
if (target.startsWith("#")) try {
|
|
362
|
+
return source.machine.getStateNodeById(target.slice(1));
|
|
363
|
+
} catch {
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const [from, path] = target.startsWith(".") ? [source, target.slice(1)] : [source.parent ?? source, target];
|
|
367
|
+
let node = from;
|
|
368
|
+
for (const key of path.split(".")) node = node?.states[key];
|
|
369
|
+
return node;
|
|
370
|
+
}
|
|
371
|
+
/** A target as said from where the transition starts: a sibling by key, else its path below the machine. */
|
|
372
|
+
const nameOf = (source, target) => target.parent === source.parent ? target.key : target.path.join(".");
|
|
373
|
+
/**
|
|
374
|
+
* The keys of the object literal whose `{` is at `open` in `text`, at its top
|
|
375
|
+
* level: `a`, `b` for `{ a: 1, b, ...c }`, and `…c` for a spread, whose keys
|
|
376
|
+
* cannot be read. Strings, templates and nested brackets are skipped over.
|
|
377
|
+
*/
|
|
378
|
+
function objectKeys(text, open) {
|
|
379
|
+
const keys = [];
|
|
380
|
+
let depth = 0;
|
|
381
|
+
let expectKey = false;
|
|
382
|
+
for (let i = open; i < text.length; i++) {
|
|
383
|
+
const c = text[i];
|
|
384
|
+
if (c === "\"" || c === "'" || c === "`") {
|
|
385
|
+
const end = text.indexOf(c, i + 1);
|
|
386
|
+
if (end < 0) break;
|
|
387
|
+
i = end;
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
if (c === "{" || c === "(" || c === "[") {
|
|
391
|
+
depth++;
|
|
392
|
+
if (depth === 1) expectKey = true;
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (c === "}" || c === ")" || c === "]") {
|
|
396
|
+
if (--depth === 0) break;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (depth !== 1) continue;
|
|
400
|
+
if (c === ",") {
|
|
401
|
+
expectKey = true;
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
if (expectKey && !/\s/.test(c)) {
|
|
405
|
+
expectKey = false;
|
|
406
|
+
if (text.startsWith("...", i)) {
|
|
407
|
+
const spread = /^\.\.\.\s*([\w$.]+)(\()?/.exec(text.slice(i));
|
|
408
|
+
keys.push(`…${spread?.[1] ?? ""}${spread?.[2] ? "()" : ""}`);
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
const key = /^[A-Za-z_$][\w$]*/.exec(text.slice(i))?.[0];
|
|
412
|
+
if (key) {
|
|
413
|
+
keys.push(key);
|
|
414
|
+
i += key.length - 1;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return keys;
|
|
419
|
+
}
|
|
420
|
+
/** Every key of each object literal that follows a match of `at` in `code`; `…name` when what follows is not a literal. */
|
|
421
|
+
function keysInSource(code, at, keys) {
|
|
422
|
+
for (const match of code.matchAll(at)) {
|
|
423
|
+
const open = match.index + match[0].length - 1;
|
|
424
|
+
if (code[open] === "{") for (const key of objectKeys(code, open)) keys.add(key);
|
|
425
|
+
else {
|
|
426
|
+
const from = /^[\w$.]+(\()?/.exec(code.slice(open));
|
|
427
|
+
keys.add(from ? `…${from[0]}${from[1] ? ")" : ""}` : "…");
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/** What a transition sets in context: a declarative patch's keys, or each `context: { … }` in a function's source. */
|
|
432
|
+
function contextKeys(transition, code) {
|
|
433
|
+
const keys = /* @__PURE__ */ new Set();
|
|
434
|
+
if (code) keysInSource(code, /\bcontext\s*:\s*[^\s]/g, keys);
|
|
435
|
+
if (transition) {
|
|
436
|
+
const context = decodeExpr(transition.context);
|
|
437
|
+
const contextCode = codeOf(context);
|
|
438
|
+
if (contextCode) keysInSource(contextCode, /=>\s*\(\s*\{|\breturn\s*\{/g, keys);
|
|
439
|
+
else if (isObject(context)) for (const key of Object.keys(context)) keys.add(key);
|
|
440
|
+
for (const action of toList(transition.actions)) if (isObject(action) && action.type === "@xstate.assign") {
|
|
441
|
+
const assigned = decodeExpr(action.context);
|
|
442
|
+
if (isObject(assigned)) for (const key of Object.keys(assigned)) keys.add(key);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return [...keys];
|
|
446
|
+
}
|
|
447
|
+
/** A guard as said in the text: a template's dotted path, a named guard, or `guarded` when it is code. */
|
|
448
|
+
function guardText(guard) {
|
|
449
|
+
if (guard === void 0 || guard === null) return void 0;
|
|
450
|
+
const decoded = decodeExpr(guard);
|
|
451
|
+
if (typeof decoded === "string") return oneLine(/^\{\{\s*([\s\S]*?)\s*\}\}$/.exec(decoded)?.[1] ?? decoded);
|
|
452
|
+
if (isObject(decoded) && typeof decoded.type === "string") return decoded.type.startsWith("__fromConfigGuard") ? "guarded" : decoded.type;
|
|
453
|
+
return "guarded";
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* True when a transition function's source has a path that returns no
|
|
457
|
+
* transition, so it may not be taken. Matches minified source too: `void 0`
|
|
458
|
+
* for `undefined`, and a ternary `?` with no spaces (but not `?.` or `??`).
|
|
459
|
+
* String and template literals are blanked first, so their text never counts.
|
|
460
|
+
*/
|
|
461
|
+
const mayDecline = (code) => /\bundefined\b|\bnull\b|\bvoid 0\b|\breturn\s*;|\bif\s*\(|(?<!\?)\?(?![.?])|&&/.test(code.replace(/(["'`])(?:\\.|(?!\1)[^\\])*\1/g, "\"\""));
|
|
462
|
+
/**
|
|
463
|
+
* Where a transition written as a function goes: every string literal after a
|
|
464
|
+
* `target:` that names a real state node, `(conditional)` when it may decline
|
|
465
|
+
* or pick among several, `(stays)` when its source has no `target`, `?` when
|
|
466
|
+
* it names none that resolves.
|
|
467
|
+
*/
|
|
468
|
+
function targetsInSource(source, code, choice) {
|
|
469
|
+
const found = /* @__PURE__ */ new Set();
|
|
470
|
+
for (const [, expression] of code.matchAll(/\btarget\s*:\s*(\[[^\]]*\]|[^,}\n]+)/g)) for (const [, , literal] of expression.matchAll(/(['"`])([^'"`$]+)\1/g)) {
|
|
471
|
+
const node = resolveTarget(source, literal);
|
|
472
|
+
if (node) found.add(node);
|
|
473
|
+
}
|
|
474
|
+
const names = [...found].map((node) => nameOf(source, node));
|
|
475
|
+
if (names.length) {
|
|
476
|
+
const conditional = names.length > 1 || !choice && mayDecline(code);
|
|
477
|
+
return `${names.join(", ")}${conditional ? " (conditional)" : ""}`;
|
|
478
|
+
}
|
|
479
|
+
return /\btarget\s*:/.test(code) ? "?" : "(stays)";
|
|
480
|
+
}
|
|
481
|
+
/** One transition, as a line: `on GO if context.ready → review; sets draft — description`. */
|
|
482
|
+
function transitionLine(source, head, transition, options = {}) {
|
|
483
|
+
const code = codeOf(transition);
|
|
484
|
+
let to;
|
|
485
|
+
let guard;
|
|
486
|
+
let description;
|
|
487
|
+
let sets;
|
|
488
|
+
if (typeof transition === "string") {
|
|
489
|
+
const node = resolveTarget(source, transition);
|
|
490
|
+
to = node ? nameOf(source, node) : `${transition} ?`;
|
|
491
|
+
sets = [];
|
|
492
|
+
} else if (code !== void 0) {
|
|
493
|
+
to = targetsInSource(source, code, options.choice ?? false);
|
|
494
|
+
sets = contextKeys(void 0, code);
|
|
495
|
+
} else if (isObject(transition) && !("@expr" in transition)) {
|
|
496
|
+
const targets = toList(transition.target).filter((t) => typeof t === "string");
|
|
497
|
+
to = targets.length ? targets.map((target) => {
|
|
498
|
+
const node = resolveTarget(source, target);
|
|
499
|
+
return node ? nameOf(source, node) : `${target} ?`;
|
|
500
|
+
}).join(", ") : "(stays)";
|
|
501
|
+
guard = guardText(transition[options.guardKey ?? "guard"]);
|
|
502
|
+
description = typeof transition.description === "string" ? transition.description : void 0;
|
|
503
|
+
sets = contextKeys(transition, void 0);
|
|
504
|
+
} else {
|
|
505
|
+
to = "?";
|
|
506
|
+
sets = [];
|
|
507
|
+
}
|
|
508
|
+
return `${head}${guard ? ` if ${guard}` : ""} → ${to}${sets.length ? `; sets ${sets.join(", ")}` : ""}${description ? ` — ${oneLine(description)}` : ""}`;
|
|
509
|
+
}
|
|
510
|
+
function formatMs(ms) {
|
|
511
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
512
|
+
return `${ms / 1e3}s`;
|
|
513
|
+
}
|
|
514
|
+
/** An `after` key as said: `1s`, or a named delay with its duration when it is a number (`slow (5s)`). */
|
|
515
|
+
function delayText(key, delays) {
|
|
516
|
+
if (/^\d+(\.\d+)?$/.test(key)) return formatMs(Number(key));
|
|
517
|
+
const delay = delays[key];
|
|
518
|
+
return typeof delay === "number" ? `${key} (${formatMs(delay)})` : key;
|
|
519
|
+
}
|
|
520
|
+
/** Every transition leaving one state node, as lines at `pad`. */
|
|
521
|
+
function transitionLines(node, json, delays, pad) {
|
|
522
|
+
const lines = [];
|
|
523
|
+
const push = (head, value) => {
|
|
524
|
+
for (const transition of toList(value)) lines.push(`${pad}${transitionLine(node, head, transition)}`);
|
|
525
|
+
};
|
|
526
|
+
for (const [event, value] of Object.entries(isObject(json.on) ? json.on : {})) push(event === "xstate.done.state" ? "onDone" : `on ${event}`, value);
|
|
527
|
+
push("onDone", json.onDone);
|
|
528
|
+
push("always", json.always);
|
|
529
|
+
for (const [key, value] of Object.entries(isObject(json.after) ? json.after : {})) push(`after ${delayText(key, delays)}`, value);
|
|
530
|
+
for (const invoke of toList(json.invoke)) {
|
|
531
|
+
if (!isObject(invoke)) continue;
|
|
532
|
+
const src = typeof invoke.src === "string" ? invoke.src : "(inline)";
|
|
533
|
+
const id = typeof invoke.id === "string" && invoke.id !== src ? ` (${invoke.id})` : "";
|
|
534
|
+
lines.push(`${pad}invoke ${src}${id}`);
|
|
535
|
+
push(" done", invoke.onDone);
|
|
536
|
+
push(" error", invoke.onError);
|
|
537
|
+
}
|
|
538
|
+
if (json.choice !== void 0) toList(json.choice).forEach((branch, index) => {
|
|
539
|
+
const head = isObject(branch) && branch.when !== void 0 || index === 0 ? "choice" : "choice else";
|
|
540
|
+
lines.push(`${pad}${transitionLine(node, head, branch, {
|
|
541
|
+
guardKey: "when",
|
|
542
|
+
choice: true
|
|
543
|
+
})}`);
|
|
544
|
+
});
|
|
545
|
+
return lines;
|
|
546
|
+
}
|
|
547
|
+
/** The state node's line: key, type, tags, interaction label, description. */
|
|
548
|
+
function stateLine(node, json) {
|
|
549
|
+
let marker = "";
|
|
550
|
+
if (node.type === "final" || node.type === "choice" || node.type === "parallel") marker = ` (${node.type})`;
|
|
551
|
+
else if (node.type === "history") marker = json.history === "deep" ? " (history, deep)" : " (history)";
|
|
552
|
+
else if (node.type === "compound" && typeof json.initial === "string") marker = ` (initial: ${json.initial})`;
|
|
553
|
+
const tags = node.tags.length ? ` [tags: ${node.tags.join(", ")}]` : "";
|
|
554
|
+
const interaction = node.meta?.interaction;
|
|
555
|
+
const label = typeof interaction?.label === "string" ? ` [interaction: "${oneLine(interaction.label)}"]` : "";
|
|
556
|
+
const description = node.description ? ` — ${oneLine(node.description)}` : "";
|
|
557
|
+
return `${node.key}${marker}${tags}${label}${description}`;
|
|
558
|
+
}
|
|
559
|
+
/** The machine's events with their schema descriptions and fields, sorted by type. */
|
|
560
|
+
function eventLines(machine) {
|
|
561
|
+
const schemas = require_event_log.getAgentExecutionOptions(machine)?.schemas?.events ?? machine.schemas?.events ?? {};
|
|
562
|
+
const lines = [];
|
|
563
|
+
for (const type of Object.keys(schemas).sort()) {
|
|
564
|
+
if (type.startsWith("@agent.") || type.startsWith("xstate.")) continue;
|
|
565
|
+
let schema;
|
|
566
|
+
try {
|
|
567
|
+
schema = require_event_log.getJsonSchemaSync(schemas[type]);
|
|
568
|
+
} catch {
|
|
569
|
+
schema = void 0;
|
|
570
|
+
}
|
|
571
|
+
const direct = schemas[type].description;
|
|
572
|
+
const description = typeof schema?.description === "string" ? schema.description : typeof direct === "string" ? direct : void 0;
|
|
573
|
+
lines.push(` ${type}${description ? ` — ${oneLine(description)}` : ""}`);
|
|
574
|
+
const properties = isObject(schema?.properties) ? schema.properties : {};
|
|
575
|
+
const required = new Set(Array.isArray(schema?.required) ? schema.required : []);
|
|
576
|
+
for (const [field, property] of Object.entries(properties)) {
|
|
577
|
+
if (!isObject(property)) continue;
|
|
578
|
+
const fieldType = Array.isArray(property.enum) ? property.enum.map((value) => JSON.stringify(value)).join(" | ") : Array.isArray(property.type) ? property.type.join(" | ") : typeof property.type === "string" ? property.type : void 0;
|
|
579
|
+
const fieldDescription = typeof property.description === "string" ? ` — ${oneLine(property.description)}` : "";
|
|
580
|
+
lines.push(` ${field}${required.has(field) ? "" : "?"}${fieldType ? `: ${fieldType}` : ""}${fieldDescription}`);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return lines;
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* Describes a machine in plain text for a model to read. The machine's
|
|
587
|
+
* `description` is its goal, so it leads: `Machine <id>`, then `Goal: …`.
|
|
588
|
+
* Then every state node, indented by depth, with its type, tags, interaction
|
|
589
|
+
* label and description (`*` marks the active ones when `snapshot` is given),
|
|
590
|
+
* and under it every transition leaving it, one per line: `on EVENT`,
|
|
591
|
+
* `always`, `after <delay>`, invoke `done`/`error`, and `choice` branches,
|
|
592
|
+
* each with its guard (`if …`), where it goes (`→ review`), and what it sets
|
|
593
|
+
* in context (`sets draft, attempts`). An `Events` section lists the
|
|
594
|
+
* machine's event schemas with their descriptions and fields.
|
|
595
|
+
*
|
|
596
|
+
* A transition written as a function shows the targets its source names
|
|
597
|
+
* (`→ review (conditional)` when it may decline or pick among several),
|
|
598
|
+
* `(stays)` when its source has no `target`, or `→ ?` when no target can be
|
|
599
|
+
* read. A `setupAgent.fromConfig(...)` machine is read from its config, so
|
|
600
|
+
* its targets, guards and context patches are always known.
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
* ```ts
|
|
604
|
+
* const prompt = `Propose a better machine for this goal.\n\n${describeMachine(machine)}`;
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
function describeMachine(machine, options = {}) {
|
|
608
|
+
const json = (0, xstate.machineToJSON)(machine);
|
|
609
|
+
const delays = isObject(json.delays) ? json.delays : {};
|
|
610
|
+
const active = new Set(options.snapshot?.nodes.map((node) => node.id) ?? []);
|
|
611
|
+
const root = machine.root;
|
|
612
|
+
const lines = [`Machine ${machine.id}`];
|
|
613
|
+
if (root.description) lines.push(`Goal: ${root.description.trim()}`);
|
|
614
|
+
const rootTransitions = transitionLines(root, json, delays, " ");
|
|
615
|
+
if (rootTransitions.length) lines.push("Any state:", ...rootTransitions);
|
|
616
|
+
const initial = typeof json.initial === "string" ? ` (initial: ${json.initial})` : "";
|
|
617
|
+
lines.push(`States${initial}${options.snapshot ? " (* = current)" : ""}:`);
|
|
618
|
+
const walk = (node, nodeJson, depth) => {
|
|
619
|
+
const pad = " ".repeat(depth);
|
|
620
|
+
const mark = active.has(node.id) ? `${pad.slice(2)}* ` : pad;
|
|
621
|
+
lines.push(`${mark}${stateLine(node, nodeJson)}`);
|
|
622
|
+
lines.push(...transitionLines(node, nodeJson, delays, `${pad} `));
|
|
623
|
+
const childJson = isObject(nodeJson.states) ? nodeJson.states : {};
|
|
624
|
+
for (const [key, child] of Object.entries(node.states)) walk(child, isObject(childJson[key]) ? childJson[key] : {}, depth + 1);
|
|
625
|
+
};
|
|
626
|
+
const rootStates = isObject(json.states) ? json.states : {};
|
|
627
|
+
for (const [key, child] of Object.entries(root.states)) walk(child, isObject(rootStates[key]) ? rootStates[key] : {}, 1);
|
|
628
|
+
const events = eventLines(machine);
|
|
629
|
+
if (events.length) lines.push("Events:", ...events);
|
|
630
|
+
return lines.join("\n");
|
|
631
|
+
}
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region src/decide-next.ts
|
|
634
|
+
/**
|
|
635
|
+
* Asks a model to choose the next event for ANY XState snapshot, including a
|
|
636
|
+
* machine built with plain `createMachine`/`setup` that knows nothing about AI.
|
|
637
|
+
* The candidates are the `allowedEvents` an active state handles, one option per
|
|
638
|
+
* payload, kept only where `snapshot.can(event)` is true; the rest come back as
|
|
639
|
+
* `withheld`. Each option is
|
|
640
|
+
* described from the transition's `description`, else the event schema's,
|
|
641
|
+
* plus (with `lookahead`) what it changes. The chosen event must equal one
|
|
642
|
+
* offered option; anything else is retried.
|
|
643
|
+
*
|
|
644
|
+
* It never sends. The host sends the event, re-checking `can` first, because
|
|
645
|
+
* the actor may have moved while the model was thinking. With no options it
|
|
646
|
+
* returns `{ event: null }` without calling the executor. Exhausting retries
|
|
647
|
+
* throws `AgentDecisionExhaustedError`.
|
|
648
|
+
*
|
|
649
|
+
* @example
|
|
650
|
+
* ```ts no-check
|
|
651
|
+
* let busy = false;
|
|
652
|
+
* actor.subscribe(async (snapshot) => {
|
|
653
|
+
* if (busy || !snapshot.matches('reviewing')) return;
|
|
654
|
+
* busy = true;
|
|
655
|
+
* try {
|
|
656
|
+
* const { event } = await decideNext(snapshot, {
|
|
657
|
+
* decide,
|
|
658
|
+
* model: 'quick',
|
|
659
|
+
* allowedEvents: 'desk.*',
|
|
660
|
+
* payloads: (s) => ({ 'desk.refund': [{ amount: s.context.requested }] }),
|
|
661
|
+
* lookahead: true,
|
|
662
|
+
* });
|
|
663
|
+
* if (event && actor.getSnapshot().can(event)) actor.send(event);
|
|
664
|
+
* } finally {
|
|
665
|
+
* busy = false;
|
|
666
|
+
* }
|
|
667
|
+
* });
|
|
668
|
+
* ```
|
|
669
|
+
*/
|
|
670
|
+
async function decideNext(snapshot, options) {
|
|
671
|
+
const patterns = typeof options.allowedEvents === "string" ? [options.allowedEvents] : options.allowedEvents;
|
|
672
|
+
const schemas = snapshot.machine.schemas?.events;
|
|
673
|
+
const events = require_decision.getAcceptedEvents(snapshot, {
|
|
674
|
+
events: schemas,
|
|
675
|
+
eventTypes: patterns
|
|
676
|
+
}).filter((event) => !require_decision.isEventPattern(event.type));
|
|
677
|
+
const payloads = options.payloads?.(snapshot) ?? {};
|
|
678
|
+
const accepted = [];
|
|
679
|
+
const withheld = [];
|
|
680
|
+
for (const { type } of events) for (const payload of payloads[type] ?? [{}]) {
|
|
681
|
+
const event = {
|
|
682
|
+
...payload,
|
|
683
|
+
type
|
|
684
|
+
};
|
|
685
|
+
(safeCan(snapshot, event) ? accepted : withheld).push(event);
|
|
686
|
+
}
|
|
687
|
+
const offered = accepted.map((event) => ({
|
|
688
|
+
event,
|
|
689
|
+
description: describeOption(snapshot, event, schemas?.[event.type], options.lookahead)
|
|
690
|
+
}));
|
|
691
|
+
const request = require_decision.createDecisionRequest({
|
|
692
|
+
name: options.name ?? "decideNext",
|
|
693
|
+
model: options.model,
|
|
694
|
+
system: options.system,
|
|
695
|
+
prompt: options.prompt,
|
|
696
|
+
input: {
|
|
697
|
+
value: snapshot.value,
|
|
698
|
+
context: snapshot.context
|
|
699
|
+
},
|
|
700
|
+
events,
|
|
701
|
+
options: offered,
|
|
702
|
+
withheld
|
|
703
|
+
});
|
|
704
|
+
if (offered.length === 0) return {
|
|
705
|
+
event: null,
|
|
706
|
+
attempts: [],
|
|
707
|
+
request,
|
|
708
|
+
withheld
|
|
709
|
+
};
|
|
710
|
+
let attempts = [];
|
|
711
|
+
return {
|
|
712
|
+
event: await require_decision.resolveDecision(request, { decide: (attemptRequest, info) => {
|
|
713
|
+
attempts = attemptRequest.attempts;
|
|
714
|
+
return options.decide(attemptRequest, info);
|
|
715
|
+
} }, {
|
|
716
|
+
maxRetries: options.maxRetries,
|
|
717
|
+
signal: options.signal,
|
|
718
|
+
canTake: (chosen) => safeCan(snapshot, chosen)
|
|
719
|
+
}),
|
|
720
|
+
attempts,
|
|
721
|
+
request,
|
|
722
|
+
withheld
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
function safeCan(snapshot, event) {
|
|
726
|
+
try {
|
|
727
|
+
return snapshot.can(event);
|
|
728
|
+
} catch {
|
|
729
|
+
return false;
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
function describeOption(snapshot, event, schema, lookahead) {
|
|
733
|
+
const what = (0, xstate.getNextTransitions)(snapshot).find((candidate) => candidate.eventType === event.type && candidate.description)?.description ?? schemaDescription(schema) ?? event.type;
|
|
734
|
+
const fields = Object.entries(event).filter(([key]) => key !== "type").map(([key, value]) => `${key}: ${short(value)}`);
|
|
735
|
+
const base = fields.length ? `${what} (${fields.join("; ")})` : what;
|
|
736
|
+
const effect = lookahead ? describeEffect(snapshot, event, lookahead === true ? void 0 : lookahead) : void 0;
|
|
737
|
+
return effect ? `${base}. Then: ${effect}` : base;
|
|
738
|
+
}
|
|
739
|
+
function schemaDescription(schema) {
|
|
740
|
+
if (!schema) return void 0;
|
|
741
|
+
const direct = schema.description;
|
|
742
|
+
if (typeof direct === "string") return direct;
|
|
743
|
+
try {
|
|
744
|
+
const json = schema["~standard"].jsonSchema?.input?.({ target: "draft-2020-12" });
|
|
745
|
+
return require_decision.isRecord(json) && typeof json.description === "string" ? json.description : void 0;
|
|
746
|
+
} catch {
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
function describeEffect(snapshot, event, keys) {
|
|
751
|
+
const maxLength = 120;
|
|
752
|
+
let next;
|
|
753
|
+
try {
|
|
754
|
+
[next] = (0, xstate.transition)(snapshot.machine, snapshot, event);
|
|
755
|
+
} catch {
|
|
756
|
+
return;
|
|
757
|
+
}
|
|
758
|
+
const changes = [];
|
|
759
|
+
if (require_event_log.canonicalEventJson(snapshot.value) !== require_event_log.canonicalEventJson(next.value)) changes.push(`state: ${short(snapshot.value, maxLength)} → ${short(next.value, maxLength)}`);
|
|
760
|
+
const before = require_decision.isRecord(snapshot.context) ? snapshot.context : {};
|
|
761
|
+
const after = require_decision.isRecord(next.context) ? next.context : {};
|
|
762
|
+
for (const key of keys ?? /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) if (require_event_log.canonicalEventJson(before[key]) !== require_event_log.canonicalEventJson(after[key])) changes.push(`${key}: ${short(before[key], maxLength)} → ${short(after[key], maxLength)}`);
|
|
763
|
+
return changes.length ? changes.join("; ") : "nothing changes";
|
|
764
|
+
}
|
|
765
|
+
function short(value, max = 60) {
|
|
766
|
+
let text;
|
|
767
|
+
try {
|
|
768
|
+
text = value === void 0 ? "(none)" : JSON.stringify(value) ?? String(value);
|
|
769
|
+
} catch {
|
|
770
|
+
text = String(value);
|
|
771
|
+
}
|
|
772
|
+
return text.length > max ? `${text.slice(0, max - 1)}…` : text;
|
|
258
773
|
}
|
|
259
774
|
//#endregion
|
|
260
775
|
//#region src/provide-executors.ts
|
|
@@ -310,8 +825,8 @@ function provideExecutors(machine, executors, options = {}) {
|
|
|
310
825
|
const invokedSrcs = require_run_agent.getConfiguredInvokeSrcs(provided);
|
|
311
826
|
for (const [key, logic] of Object.entries(effectiveSources)) {
|
|
312
827
|
if (require_run_agent.isStateMachineLogic(logic)) {
|
|
313
|
-
if (invokedSrcs.has(key)) assertChildBindable(logic, executors, key, new Set([provided]));
|
|
314
|
-
const rebound = require_run_agent.bindChildMachineForProvide(logic, executors, bindOptions, new Set([provided]));
|
|
828
|
+
if (invokedSrcs.has(key)) assertChildBindable(logic, executors, key, /* @__PURE__ */ new Set([provided]));
|
|
829
|
+
const rebound = require_run_agent.bindChildMachineForProvide(logic, executors, bindOptions, /* @__PURE__ */ new Set([provided]));
|
|
315
830
|
if (rebound !== logic) wrappedSources[key] = rebound;
|
|
316
831
|
continue;
|
|
317
832
|
}
|
|
@@ -321,7 +836,7 @@ function provideExecutors(machine, executors, options = {}) {
|
|
|
321
836
|
...requirement,
|
|
322
837
|
bind: () => require_decision.isDecisionLogic(logic) ? require_run_agent.bindDecisionForProvide(provided, logic, executors, bindOptions) : require_run_agent.bindTextForProvide(provided, logic, executors, bindOptions)
|
|
323
838
|
};
|
|
324
|
-
if (
|
|
839
|
+
if (require_event_log.executorBoundLogics.has(logic)) continue;
|
|
325
840
|
if (!executors[binding.executorKey]) {
|
|
326
841
|
if (invokedSrcs.has(key)) throw missingExecutorError(key, binding.kind, binding.executorKey);
|
|
327
842
|
continue;
|
|
@@ -336,7 +851,7 @@ function executorRequirementOf(logic) {
|
|
|
336
851
|
executorKey: "decide",
|
|
337
852
|
kind: "decision"
|
|
338
853
|
};
|
|
339
|
-
if (
|
|
854
|
+
if (require_event_log.isTextLogic(logic)) return logic.mode === "stream" ? {
|
|
340
855
|
executorKey: "streamText",
|
|
341
856
|
kind: "streaming text"
|
|
342
857
|
} : {
|
|
@@ -352,7 +867,7 @@ function executorRequirementOf(logic) {
|
|
|
352
867
|
*/
|
|
353
868
|
function assertChildBindable(childMachine, executors, path, visited) {
|
|
354
869
|
if (visited.has(childMachine)) return;
|
|
355
|
-
const nextVisited = new Set([...visited, childMachine]);
|
|
870
|
+
const nextVisited = /* @__PURE__ */ new Set([...visited, childMachine]);
|
|
356
871
|
const sources = childMachine.sources.actors;
|
|
357
872
|
for (const src of require_run_agent.getConfiguredInvokeSrcs(childMachine)) {
|
|
358
873
|
const logic = sources[src];
|
|
@@ -362,7 +877,7 @@ function assertChildBindable(childMachine, executors, path, visited) {
|
|
|
362
877
|
continue;
|
|
363
878
|
}
|
|
364
879
|
const requirement = executorRequirementOf(logic);
|
|
365
|
-
if (!requirement ||
|
|
880
|
+
if (!requirement || require_event_log.executorBoundLogics.has(logic)) continue;
|
|
366
881
|
if (!executors[requirement.executorKey]) throw missingExecutorError(`${path} > ${src}`, requirement.kind, requirement.executorKey);
|
|
367
882
|
}
|
|
368
883
|
}
|
|
@@ -371,48 +886,51 @@ function missingExecutorError(src, kind, executor) {
|
|
|
371
886
|
}
|
|
372
887
|
//#endregion
|
|
373
888
|
exports.AGENT_TRACE_SCHEMA_VERSION = require_run_agent.AGENT_TRACE_SCHEMA_VERSION;
|
|
374
|
-
exports.AGENT_USAGE_EVENT_TYPE =
|
|
889
|
+
exports.AGENT_USAGE_EVENT_TYPE = require_event_log.AGENT_USAGE_EVENT_TYPE;
|
|
375
890
|
exports.AgentDecisionExhaustedError = require_decision.AgentDecisionExhaustedError;
|
|
376
|
-
exports.AgentError =
|
|
891
|
+
exports.AgentError = require_event_log.AgentError;
|
|
377
892
|
exports.AgentEventLogConflictError = require_event_log_store.AgentEventLogConflictError;
|
|
378
893
|
exports.AgentInvalidEventPayloadError = require_decision.AgentInvalidEventPayloadError;
|
|
379
|
-
exports.AgentMachineVersionMismatchError =
|
|
894
|
+
exports.AgentMachineVersionMismatchError = require_event_log.AgentMachineVersionMismatchError;
|
|
380
895
|
exports.AgentMaxModelCallsExceededError = require_run_agent.AgentMaxModelCallsExceededError;
|
|
381
896
|
exports.AgentSnapshotDivergedError = require_run_agent.AgentSnapshotDivergedError;
|
|
382
|
-
exports.AgentTruncatedError =
|
|
383
|
-
exports.assistantMessage =
|
|
384
|
-
exports.bindRequestExecutor =
|
|
897
|
+
exports.AgentTruncatedError = require_event_log.AgentTruncatedError;
|
|
898
|
+
exports.assistantMessage = require_event_log.assistantMessage;
|
|
899
|
+
exports.bindRequestExecutor = require_event_log.bindRequestExecutor;
|
|
385
900
|
exports.createAgentRuntime = require_run_agent.createAgentRuntime;
|
|
386
901
|
exports.createAgentSchemas = require_setup_agent.createAgentSchemas;
|
|
387
902
|
exports.createDecisionLogic = require_decision.createDecisionLogic;
|
|
388
903
|
exports.createDecisionRequest = require_decision.createDecisionRequest;
|
|
389
|
-
exports.createTextLogic =
|
|
904
|
+
exports.createTextLogic = require_event_log.createTextLogic;
|
|
905
|
+
exports.decideNext = decideNext;
|
|
906
|
+
exports.describeMachine = describeMachine;
|
|
390
907
|
exports.eventFromInteraction = eventFromInteraction;
|
|
391
908
|
exports.getAcceptedEvents = require_decision.getAcceptedEvents;
|
|
392
|
-
exports.getAgentOutputMode =
|
|
909
|
+
exports.getAgentOutputMode = require_event_log.getAgentOutputMode;
|
|
393
910
|
exports.getAgentSchemas = require_setup_agent.getAgentSchemas;
|
|
394
|
-
exports.getCallFinishReason =
|
|
395
|
-
exports.getCallUsage =
|
|
911
|
+
exports.getCallFinishReason = require_event_log.getCallFinishReason;
|
|
912
|
+
exports.getCallUsage = require_event_log.getCallUsage;
|
|
396
913
|
exports.getInteraction = getInteraction;
|
|
397
|
-
exports.getJsonSchema =
|
|
398
|
-
exports.getJsonSchemaSync =
|
|
399
|
-
exports.getMachineStructuralHash =
|
|
400
|
-
exports.getMessageText =
|
|
401
|
-
exports.getStateMeta =
|
|
402
|
-
exports.getStatePath =
|
|
914
|
+
exports.getJsonSchema = require_event_log.getJsonSchema;
|
|
915
|
+
exports.getJsonSchemaSync = require_event_log.getJsonSchemaSync;
|
|
916
|
+
exports.getMachineStructuralHash = require_event_log.getMachineStructuralHash;
|
|
917
|
+
exports.getMessageText = require_event_log.getMessageText;
|
|
918
|
+
exports.getStateMeta = require_event_log.getStateMeta;
|
|
919
|
+
exports.getStatePath = require_event_log.getStatePath;
|
|
403
920
|
exports.inspectTransitions = require_run_agent.inspectTransitions;
|
|
404
921
|
exports.interactionMetaSchema = interactionMetaSchema;
|
|
405
922
|
exports.isAgentIdle = require_run_agent.isAgentIdle;
|
|
406
923
|
exports.isAgentMessages = isAgentMessages;
|
|
407
|
-
exports.isStandardSchema =
|
|
924
|
+
exports.isStandardSchema = require_event_log.isStandardSchema;
|
|
408
925
|
exports.messagesSchema = messagesSchema;
|
|
409
926
|
exports.parseAgentEvent = require_decision.parseAgentEvent;
|
|
410
|
-
exports.parseOutput =
|
|
411
|
-
exports.parseProviderOutput =
|
|
927
|
+
exports.parseOutput = require_event_log.parseOutput;
|
|
928
|
+
exports.parseProviderOutput = require_event_log.parseProviderOutput;
|
|
412
929
|
exports.provideExecutors = provideExecutors;
|
|
413
|
-
exports.providerOutputSchema =
|
|
930
|
+
exports.providerOutputSchema = require_event_log.providerOutputSchema;
|
|
414
931
|
exports.renderDecisionAttempts = require_decision.renderDecisionAttempts;
|
|
415
932
|
exports.resolveDecision = require_decision.resolveDecision;
|
|
933
|
+
exports.runAgent = require_run_agent.runAgent;
|
|
416
934
|
exports.runToQuiescence = require_run_agent.runToQuiescence;
|
|
417
935
|
exports.serializeTraceEvent = require_run_agent.serializeTraceEvent;
|
|
418
936
|
Object.defineProperty(exports, "setupAgent", {
|
|
@@ -421,7 +939,7 @@ Object.defineProperty(exports, "setupAgent", {
|
|
|
421
939
|
return require_setup_agent.setupAgent;
|
|
422
940
|
}
|
|
423
941
|
});
|
|
424
|
-
exports.systemMessage =
|
|
425
|
-
exports.toolMessage =
|
|
942
|
+
exports.systemMessage = require_event_log.systemMessage;
|
|
943
|
+
exports.toolMessage = require_event_log.toolMessage;
|
|
426
944
|
exports.traceTransitions = require_run_agent.traceTransitions;
|
|
427
|
-
exports.userMessage =
|
|
945
|
+
exports.userMessage = require_event_log.userMessage;
|