@statelyai/agent 2.0.0-alpha.15 → 2.0.0-alpha.17
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 +1 -1
- package/dist/ai-sdk.d.cts +2 -2
- package/dist/ai-sdk.d.mts +2 -2
- package/dist/ai-sdk.mjs +1 -1
- package/dist/{decision-D9Zi7Xi5.mjs → decision-C11xuud2.mjs} +35 -26
- package/dist/{decision-C0cUKvNt.cjs → decision-DnQCQPew.cjs} +46 -31
- package/dist/{event-log-store-D7pWtIhb.mjs → event-log-store-B-1fcfkT.mjs} +149 -141
- package/dist/{event-log-store-BkUNtyOF.d.mts → event-log-store-BrC9Q1xW.d.mts} +14 -12
- package/dist/{event-log-store-CVd2eyRy.d.cts → event-log-store-CQJq8_v4.d.cts} +14 -12
- package/dist/{event-log-store-CNT_7F0V.cjs → event-log-store-yquOV1TX.cjs} +148 -140
- package/dist/index.cjs +498 -520
- package/dist/index.d.cts +130 -104
- package/dist/index.d.mts +130 -104
- package/dist/index.mjs +497 -519
- package/dist/machines.cjs +1 -1
- package/dist/machines.d.cts +1 -1
- package/dist/machines.d.mts +1 -1
- package/dist/machines.mjs +1 -1
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/{run-agent-B_n4Qxye.d.cts → run-agent-BxjGaVpL.d.cts} +49 -109
- package/dist/{run-agent-BWzo4FLv.d.mts → run-agent-COHoCgQd.d.mts} +49 -109
- package/dist/{setup-agent-DeHRW-qX.mjs → setup-agent-CTg57Pa4.mjs} +154 -167
- package/dist/{setup-agent-CpK0ZRWV.cjs → setup-agent-D_EyJ0Ik.cjs} +159 -172
- package/dist/sqlite.cjs +1 -1
- package/dist/sqlite.d.cts +2 -2
- package/dist/sqlite.d.mts +2 -2
- package/dist/sqlite.mjs +1 -1
- package/dist/{text-logic-DZW7XWy9.d.cts → text-logic-BFX5q7fM.d.cts} +23 -2
- package/dist/{text-logic-C7anC7qX.d.mts → text-logic-DQW8_DWW.d.mts} +23 -2
- package/dist/{types-DFD28AWe.d.cts → types-DYpK3QF4.d.mts} +7 -6
- package/dist/{types-CTBhMnFu.d.mts → types-pJ5Hn8fv.d.cts} +7 -6
- package/package.json +28 -28
- package/readme.md +6 -19
- package/schemas/agent-workflow.json +9 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as AgentError } from "./errors-CeSXQx0v.mjs";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { B as getMachineStructuralHash, F as djb2Hex, M as machineSuspensionPredicates, N as missingActor, T as agentExecutionOptions, d as USER_INPUT_ACTOR, g as executeAgentTextRequest, h as createTextLogic, j as machineStaticTransitionTargets, k as getRegisteredAgentExecutionOptions, l as DECIDE_ACTOR, m as builtinTextActors, n as createDecideActor, o as getAcceptedEvents, q as validateSchemaSync, r as isDecisionLogic, w as userInputActor, y as isTextLogic } from "./decision-C11xuud2.mjs";
|
|
3
|
+
import { a as assertJsonSerializable, i as assertAgentLogEntry } from "./event-log-store-B-1fcfkT.mjs";
|
|
4
4
|
import { createMachineFromConfig, initialTransition, setup, transition } from "xstate";
|
|
5
5
|
//#region src/messages.ts
|
|
6
6
|
function addMessages(resolve) {
|
|
@@ -85,7 +85,7 @@ const messagesSchema = { "~standard": {
|
|
|
85
85
|
* The step envelope: an INTERNAL, per-model-call-checkpoint view of an agent
|
|
86
86
|
* machine (`AgentStep` = snapshot + actions + discovered requests + done). It
|
|
87
87
|
* once backed a public step API; the public step path is now the thin
|
|
88
|
-
* effect/replay loop in `./effects.ts` (re-exported from `@statelyai/agent
|
|
88
|
+
* effect/replay loop in `./effects.ts` (re-exported from `@statelyai/agent`).
|
|
89
89
|
* These helpers survive as internals that `runAgent`, `verify.ts`, and the
|
|
90
90
|
* effect path build on — the only symbol still on the public surface is
|
|
91
91
|
* {@link executeAgentRequest} (the `text`-effect resolver).
|
|
@@ -106,17 +106,20 @@ function getInvokeEffectMetadata(action) {
|
|
|
106
106
|
/**
|
|
107
107
|
* Scans a set of executable actions (as returned by xstate's `transition`/
|
|
108
108
|
* `initialTransition`) for spawned `TextLogic`/`DecisionLogic` invokes and
|
|
109
|
-
* lowers each into an {@link AgentStepRequest}.
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
* pre-fills them from the machine's registered `setupAgent` options.
|
|
109
|
+
* lowers each into an {@link AgentStepRequest}. Pass `options.machine` to
|
|
110
|
+
* pre-fill `schemas`/`actors` from the machine's registered `setupAgent`
|
|
111
|
+
* options instead of passing them by hand.
|
|
113
112
|
* `options.snapshot` is required to resolve a decision's candidate events
|
|
114
113
|
* (intersecting declared `allowedEvents` with what's currently legal) — omit
|
|
115
114
|
* it and decision requests report an empty `events` list.
|
|
116
115
|
*
|
|
117
116
|
* @internal
|
|
118
117
|
*/
|
|
119
|
-
function
|
|
118
|
+
function getAgentRequests(actions, { machine, ...options } = {}) {
|
|
119
|
+
if (machine) options = {
|
|
120
|
+
...getRegisteredAgentExecutionOptions(machine),
|
|
121
|
+
...options
|
|
122
|
+
};
|
|
120
123
|
return actions.flatMap((action) => {
|
|
121
124
|
const params = getInvokeEffectMetadata(action);
|
|
122
125
|
if (!params || typeof params.src !== "string") return [];
|
|
@@ -217,7 +220,7 @@ function resolveAgentStep(machine, step, request, output, options) {
|
|
|
217
220
|
const [snapshot, actions] = transitionResult(machine, step.snapshot, request, output);
|
|
218
221
|
return createAgentStep(machine, snapshot, actions, getRegisteredAgentExecutionOptions(machine, options));
|
|
219
222
|
}
|
|
220
|
-
async function executeAgentRequest(requestOrEffect, executors
|
|
223
|
+
async function executeAgentRequest(requestOrEffect, executors) {
|
|
221
224
|
if (requestOrEffect.kind === "decision") throw new Error("executeAgentRequest(...) is text-only. Resolve a 'decision' request with resolveDecision(request, executors.decide, ...) instead.");
|
|
222
225
|
const request = "requestId" in requestOrEffect ? {
|
|
223
226
|
kind: "text",
|
|
@@ -230,11 +233,10 @@ async function executeAgentRequest(requestOrEffect, executors, options) {
|
|
|
230
233
|
} : requestOrEffect;
|
|
231
234
|
assertTextExecutor(request, executors);
|
|
232
235
|
const { output, raw } = await executeAgentTextRequest(request.mode ?? "generate", request.id, request.input, executors, request.tools);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
output: normalizedOutput,
|
|
236
|
+
return {
|
|
237
|
+
output: request.input.outputSchema ? validateSchemaSync(request.input.outputSchema, output) : output,
|
|
236
238
|
raw
|
|
237
|
-
}
|
|
239
|
+
};
|
|
238
240
|
}
|
|
239
241
|
function assertTextExecutor(request, executors) {
|
|
240
242
|
const mode = request.mode ?? "generate";
|
|
@@ -246,7 +248,7 @@ function createAgentStep(machine, snapshot, actions, options) {
|
|
|
246
248
|
return {
|
|
247
249
|
snapshot,
|
|
248
250
|
actions,
|
|
249
|
-
requests:
|
|
251
|
+
requests: getAgentRequests(actions, {
|
|
250
252
|
...options,
|
|
251
253
|
snapshot
|
|
252
254
|
}),
|
|
@@ -327,26 +329,6 @@ const AGENT_INIT_EVENT_TYPE = "@agent.init";
|
|
|
327
329
|
*/
|
|
328
330
|
const AGENT_USAGE_EVENT_TYPE = "@agent.usage";
|
|
329
331
|
/**
|
|
330
|
-
* Reads a settled call's token usage off a RAW executor result — the same
|
|
331
|
-
* normalization `runAgent` applies before it delivers
|
|
332
|
-
* {@link AGENT_USAGE_EVENT_TYPE}. Returns `undefined` when the executor
|
|
333
|
-
* reported none.
|
|
334
|
-
*
|
|
335
|
-
* The seam for the step-loop path, where the host holds the raw result itself:
|
|
336
|
-
*
|
|
337
|
-
* ```ts
|
|
338
|
-
* const { output, raw } = await executeAgentRequest(effect, executors, { verbose: true });
|
|
339
|
-
* const usage = getCallUsage(raw);
|
|
340
|
-
* if (usage) append({ type: AGENT_USAGE_EVENT_TYPE, usage }); // journal + transition, like any event
|
|
341
|
-
* append(effect.toDoneEvent(output));
|
|
342
|
-
* ```
|
|
343
|
-
*
|
|
344
|
-
* See "Token usage on this path" in docs/steps.md for the full loop.
|
|
345
|
-
*/
|
|
346
|
-
function getCallUsage(raw) {
|
|
347
|
-
return extractCallUsage(raw);
|
|
348
|
-
}
|
|
349
|
-
/**
|
|
350
332
|
* Creates a JSON-safe, self-describing entry and records the state/effect
|
|
351
333
|
* hashes produced after replaying it. `entries` must be the complete prefix.
|
|
352
334
|
*/
|
|
@@ -374,7 +356,6 @@ function createReplayEntry(machine, entries, event, options = {}) {
|
|
|
374
356
|
});
|
|
375
357
|
entry.verification = replayVerification(result.snapshot, result.effects);
|
|
376
358
|
}
|
|
377
|
-
assertAgentLogEntry(entry);
|
|
378
359
|
return entry;
|
|
379
360
|
}
|
|
380
361
|
/** Reserved first replay entry carrying machine input and verification hashes. */
|
|
@@ -527,14 +508,15 @@ function buildInvokeEffect(meta, mapped, events, snapshot, options) {
|
|
|
527
508
|
function getAgentEffects(machine, snapshot, actions, options = {}) {
|
|
528
509
|
const resolved = getRegisteredAgentExecutionOptions(machine, options);
|
|
529
510
|
const events = toEvents(options.history);
|
|
530
|
-
const
|
|
511
|
+
const rawActions = actions;
|
|
512
|
+
const requests = getAgentRequests(rawActions, {
|
|
531
513
|
...resolved,
|
|
532
514
|
snapshot
|
|
533
515
|
});
|
|
534
516
|
const requestById = new Map(requests.map((request) => [request.id, request]));
|
|
535
517
|
const effects = [];
|
|
536
518
|
const emitted = /* @__PURE__ */ new Set();
|
|
537
|
-
for (const rawAction of
|
|
519
|
+
for (const rawAction of rawActions) {
|
|
538
520
|
const meta = getInvokeEffectMetadata(rawAction);
|
|
539
521
|
if (meta) {
|
|
540
522
|
const effect = buildInvokeEffect(meta, typeof meta.id === "string" ? requestById.get(meta.id) : void 0, events, snapshot, resolved);
|
|
@@ -626,45 +608,48 @@ var AgentReplayDivergenceError = class extends AgentError {
|
|
|
626
608
|
* Raised/internal events are never in the journal — replay re-derives them
|
|
627
609
|
* deterministically from the machine's own logic.
|
|
628
610
|
*/
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
611
|
+
/**
|
|
612
|
+
* Validates a replay entry sequence: envelope shape, contiguity from index 0,
|
|
613
|
+
* unique event ids, and machine identity.
|
|
614
|
+
*
|
|
615
|
+
* @internal
|
|
616
|
+
*/
|
|
617
|
+
function validateReplayEntries(entries, expected, label) {
|
|
632
618
|
const eventIds = /* @__PURE__ */ new Set();
|
|
633
619
|
for (let index = 0; index < entries.length; index++) {
|
|
634
620
|
const entry = entries[index];
|
|
635
621
|
assertAgentLogEntry(entry);
|
|
636
|
-
if (entry.index !== index) throw new Error(
|
|
637
|
-
if (eventIds.has(entry.id)) throw new Error(
|
|
622
|
+
if (entry.index !== index) throw new Error(`${label} must be contiguous from index 0; found entry.index ${entry.index} at position ${index}.`);
|
|
623
|
+
if (eventIds.has(entry.id)) throw new Error(`${label} contain duplicate event id '${entry.id}'.`);
|
|
638
624
|
eventIds.add(entry.id);
|
|
639
|
-
if (entry.machineId !== machineId || entry.machineVersion !== machineVersion) throw new AgentReplayMachineMismatchError(entry.id, entry.index, {
|
|
640
|
-
machineId,
|
|
641
|
-
machineVersion
|
|
642
|
-
}, {
|
|
625
|
+
if (entry.machineId !== expected.machineId || entry.machineVersion !== expected.machineVersion) throw new AgentReplayMachineMismatchError(entry.id, entry.index, expected, {
|
|
643
626
|
machineId: entry.machineId,
|
|
644
627
|
machineVersion: entry.machineVersion
|
|
645
628
|
});
|
|
646
629
|
}
|
|
630
|
+
}
|
|
631
|
+
function replay(machine, entries, options = {}) {
|
|
632
|
+
validateReplayEntries(entries, {
|
|
633
|
+
machineId: machine.config.id ?? machine.id ?? "(machine)",
|
|
634
|
+
machineVersion: options.machineVersion ?? getMachineStructuralHash(machine)
|
|
635
|
+
}, "Replay entries");
|
|
647
636
|
const events = toEvents(entries);
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
input = events[0].input;
|
|
653
|
-
journal = events.slice(1);
|
|
654
|
-
journalEntries = entries.slice(1);
|
|
655
|
-
}
|
|
637
|
+
const initOffset = events[0]?.type === "@agent.init" ? 1 : 0;
|
|
638
|
+
const input = initOffset ? events[0].input : options.input;
|
|
639
|
+
const journal = events.slice(initOffset);
|
|
640
|
+
const journalEntries = entries.slice(initOffset);
|
|
656
641
|
let [snapshot, actions] = initialTransition(machine, input);
|
|
657
642
|
let effects = getAgentEffects(machine, snapshot, actions, {
|
|
658
643
|
...options,
|
|
659
|
-
history: entries.slice(0,
|
|
644
|
+
history: entries.slice(0, initOffset)
|
|
660
645
|
});
|
|
661
|
-
if (
|
|
646
|
+
if (initOffset) verifyEntry(entries[0], snapshot, effects, options.verify);
|
|
662
647
|
const sessions = /* @__PURE__ */ new Map();
|
|
663
648
|
for (let index = 0; index < journal.length; index++) {
|
|
664
649
|
const event = journal[index];
|
|
665
650
|
const reboundEvent = rebindActorSession(event, snapshot, sessions);
|
|
666
651
|
[snapshot, actions] = transition(machine, snapshot, reboundEvent);
|
|
667
|
-
const consumed = entries.slice(0,
|
|
652
|
+
const consumed = entries.slice(0, initOffset + index + 1);
|
|
668
653
|
effects = getAgentEffects(machine, snapshot, actions, {
|
|
669
654
|
...options,
|
|
670
655
|
history: consumed
|
|
@@ -816,10 +801,7 @@ function sortJson(value) {
|
|
|
816
801
|
return value;
|
|
817
802
|
}
|
|
818
803
|
function hashStableJson(value) {
|
|
819
|
-
|
|
820
|
-
let hash = 5381;
|
|
821
|
-
for (let index = 0; index < input.length; index++) hash = (hash << 5) + hash + input.charCodeAt(index) | 0;
|
|
822
|
-
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
804
|
+
return djb2Hex(stableJson(value));
|
|
823
805
|
}
|
|
824
806
|
function diffJson(before, after, path = "") {
|
|
825
807
|
if (stableJson(before) === stableJson(after)) return [];
|
|
@@ -893,6 +875,9 @@ const DECIDE_SRC = "agent.decide";
|
|
|
893
875
|
const workflowConfigWholeExpressionPattern = /^\{\{\s*([\s\S]*?)\s*\}\}$/;
|
|
894
876
|
const workflowConfigTemplateExpressionPattern = /\{\{\s*([\s\S]*?)\s*\}\}/g;
|
|
895
877
|
const workflowConfigHasTemplatePattern = /\{\{[\s\S]*?\}\}/;
|
|
878
|
+
function toArray(value) {
|
|
879
|
+
return Array.isArray(value) ? value : [value];
|
|
880
|
+
}
|
|
896
881
|
function evaluateWorkflowConfigPath(expression, scope) {
|
|
897
882
|
const parts = expression.trim().split(".").filter(Boolean);
|
|
898
883
|
let current = scope;
|
|
@@ -926,6 +911,7 @@ function createSchemasFromWorkflowConfig(config, compileSchema) {
|
|
|
926
911
|
});
|
|
927
912
|
}
|
|
928
913
|
function createRequestsFromWorkflowConfig(config, compileSchema) {
|
|
914
|
+
const resolver = (value) => value === void 0 ? void 0 : ({ input }) => evaluateWorkflowConfigValue(value, { input });
|
|
929
915
|
return Object.fromEntries(Object.entries(config.requests ?? {}).map(([key, request]) => [key, {
|
|
930
916
|
mode: request.mode,
|
|
931
917
|
description: request.description,
|
|
@@ -934,19 +920,19 @@ function createRequestsFromWorkflowConfig(config, compileSchema) {
|
|
|
934
920
|
output: compileSchema(request.output, `${key}.output`)
|
|
935
921
|
},
|
|
936
922
|
model: ({ input }) => String(evaluateWorkflowConfigValue(request.model, { input }) ?? ""),
|
|
937
|
-
system:
|
|
938
|
-
prompt:
|
|
939
|
-
messages:
|
|
923
|
+
system: resolver(request.system),
|
|
924
|
+
prompt: resolver(request.prompt),
|
|
925
|
+
messages: resolver(request.messages),
|
|
940
926
|
tools: request.tools,
|
|
941
927
|
toolChoice: request.toolChoice,
|
|
942
928
|
reasoning: request.reasoning,
|
|
943
|
-
temperature:
|
|
944
|
-
maxOutputTokens:
|
|
945
|
-
topP:
|
|
946
|
-
topK:
|
|
947
|
-
seed:
|
|
948
|
-
stopSequences:
|
|
949
|
-
metadata:
|
|
929
|
+
temperature: resolver(request.temperature),
|
|
930
|
+
maxOutputTokens: resolver(request.maxOutputTokens),
|
|
931
|
+
topP: resolver(request.topP),
|
|
932
|
+
topK: resolver(request.topK),
|
|
933
|
+
seed: resolver(request.seed),
|
|
934
|
+
stopSequences: resolver(request.stopSequences),
|
|
935
|
+
metadata: resolver(request.metadata)
|
|
950
936
|
}]));
|
|
951
937
|
}
|
|
952
938
|
function createActorPlaceholdersFromWorkflowConfig(config) {
|
|
@@ -1012,7 +998,7 @@ function translateWorkflowAction(action, translation, location) {
|
|
|
1012
998
|
throw new Error(`setupAgent.fromConfig: ${location} action must declare 'assign', 'emit', or 'type'.`);
|
|
1013
999
|
}
|
|
1014
1000
|
function translateWorkflowTransition(transitionConfig, translation, location) {
|
|
1015
|
-
const actionConfigs = transitionConfig.actions ?
|
|
1001
|
+
const actionConfigs = transitionConfig.actions ? toArray(transitionConfig.actions) : [];
|
|
1016
1002
|
const assignConfigs = [...transitionConfig.assign !== void 0 ? [transitionConfig.assign] : [], ...actionConfigs.filter((action) => action.assign !== void 0).map((action) => action.assign)];
|
|
1017
1003
|
const contextPatch = assignConfigs.length ? toWorkflowExpression(Object.assign({}, ...assignConfigs)) : void 0;
|
|
1018
1004
|
const actions = actionConfigs.filter((action) => action.assign === void 0).map((action) => translateWorkflowAction(action, translation, location));
|
|
@@ -1054,9 +1040,8 @@ function translateWorkflowInvoke(invokeConfig, translation, stateKey) {
|
|
|
1054
1040
|
}
|
|
1055
1041
|
function assertValidTransitionTargets(stateKey, location, transitionConfig, siblingKeys, declaredTargets) {
|
|
1056
1042
|
if (!transitionConfig) return;
|
|
1057
|
-
const
|
|
1058
|
-
|
|
1059
|
-
const targets = transition.target === void 0 ? [] : Array.isArray(transition.target) ? transition.target : [transition.target];
|
|
1043
|
+
for (const transition of toArray(transitionConfig)) {
|
|
1044
|
+
const targets = transition.target === void 0 ? [] : toArray(transition.target);
|
|
1060
1045
|
for (const target of targets) {
|
|
1061
1046
|
if (typeof target !== "string") continue;
|
|
1062
1047
|
declaredTargets.push(target);
|
|
@@ -1068,16 +1053,16 @@ function assertValidTransitionTargets(stateKey, location, transitionConfig, sibl
|
|
|
1068
1053
|
}
|
|
1069
1054
|
function assertStateTransitionTargets(stateKey, stateConfig, siblingKeys) {
|
|
1070
1055
|
const declaredTargets = [];
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1056
|
+
const invokes = stateConfig.invoke ? toArray(stateConfig.invoke) : [];
|
|
1057
|
+
const sources = [
|
|
1058
|
+
...Object.entries(stateConfig.on ?? {}).map(([eventType, transition]) => [`'on.${eventType}'`, transition]),
|
|
1059
|
+
...Object.entries(stateConfig.after ?? {}).map(([delay, transition]) => [`'after.${delay}'`, transition]),
|
|
1060
|
+
["'always'", stateConfig.always],
|
|
1061
|
+
["'onDone'", stateConfig.onDone],
|
|
1062
|
+
["'choice'", stateConfig.choice],
|
|
1063
|
+
...invokes.flatMap((invoke) => [["invoke 'onDone'", invoke.onDone], ["invoke 'onError'", invoke.onError]])
|
|
1064
|
+
];
|
|
1065
|
+
for (const [location, transition] of sources) assertValidTransitionTargets(stateKey, location, transition, siblingKeys, declaredTargets);
|
|
1081
1066
|
return declaredTargets;
|
|
1082
1067
|
}
|
|
1083
1068
|
function translateWorkflowState(stateKey, stateConfig, siblingKeys, path, translation) {
|
|
@@ -1097,7 +1082,7 @@ function translateWorkflowState(stateKey, stateConfig, siblingKeys, path, transl
|
|
|
1097
1082
|
...doneStateId ? { id: doneStateId } : {},
|
|
1098
1083
|
...stateConfig.initial !== void 0 ? { initial: stateConfig.initial } : {},
|
|
1099
1084
|
...stateConfig.states !== void 0 ? { states: Object.fromEntries(Object.entries(stateConfig.states).map(([key, child]) => [key, translateWorkflowState(key, child, childKeys, childPath, translation)])) } : {},
|
|
1100
|
-
...stateConfig.choice !== void 0 ? { choice: (
|
|
1085
|
+
...stateConfig.choice !== void 0 ? { choice: toArray(stateConfig.choice).map((branch) => {
|
|
1101
1086
|
if (branch.actions !== void 0) throw new Error(`setupAgent.fromConfig: state '${stateKey}' has a 'choice' branch with 'actions', which is not supported. Use 'assign' on the branch, or move the actions to the target state's 'entry'.`);
|
|
1102
1087
|
const when = translateWorkflowGuard(branch.guard, translation, location);
|
|
1103
1088
|
return {
|
|
@@ -1113,8 +1098,8 @@ function translateWorkflowState(stateKey, stateConfig, siblingKeys, path, transl
|
|
|
1113
1098
|
...Object.keys(translatedOn).length ? { on: translatedOn } : {},
|
|
1114
1099
|
...stateConfig.always !== void 0 ? { always: translateWorkflowTransitions(stateConfig.always, translation, location) } : {},
|
|
1115
1100
|
...stateConfig.after !== void 0 ? { after: Object.fromEntries(Object.entries(stateConfig.after).map(([delay, transitionConfig]) => [delay, translateWorkflowTransitions(transitionConfig, translation, location)])) } : {},
|
|
1116
|
-
...stateConfig.entry !== void 0 ? { entry: (
|
|
1117
|
-
...stateConfig.exit !== void 0 ? { exit: (
|
|
1101
|
+
...stateConfig.entry !== void 0 ? { entry: toArray(stateConfig.entry).map((action) => translateWorkflowAction(action, translation, location)) } : {},
|
|
1102
|
+
...stateConfig.exit !== void 0 ? { exit: toArray(stateConfig.exit).map((action) => translateWorkflowAction(action, translation, location)) } : {},
|
|
1118
1103
|
...stateConfig.tags !== void 0 ? { tags: stateConfig.tags } : {},
|
|
1119
1104
|
...stateConfig.output !== void 0 ? { output: toWorkflowExpression(stateConfig.output) } : {},
|
|
1120
1105
|
...stateConfig.meta !== void 0 ? { meta: stateConfig.meta } : {}
|
|
@@ -1143,6 +1128,22 @@ function translateWorkflowConfig(config, translation) {
|
|
|
1143
1128
|
if (json.output === void 0 && finalOutputs.length === 1) json.output = finalOutputs[0];
|
|
1144
1129
|
return json;
|
|
1145
1130
|
}
|
|
1131
|
+
function collectDeclaredStateTags(states, tags = /* @__PURE__ */ new Set()) {
|
|
1132
|
+
for (const state of Object.values(states ?? {})) {
|
|
1133
|
+
for (const tag of state.tags ?? []) tags.add(tag);
|
|
1134
|
+
collectDeclaredStateTags(state.states, tags);
|
|
1135
|
+
}
|
|
1136
|
+
return tags;
|
|
1137
|
+
}
|
|
1138
|
+
function resolveSuspensionPredicate(config, options) {
|
|
1139
|
+
if (options.isSuspended) return options.isSuspended;
|
|
1140
|
+
const suspendedTags = config.suspendedTags ?? [];
|
|
1141
|
+
if (!suspendedTags.length) return;
|
|
1142
|
+
const declaredTags = collectDeclaredStateTags(config.states);
|
|
1143
|
+
const unknown = suspendedTags.filter((tag) => !declaredTags.has(tag));
|
|
1144
|
+
if (unknown.length) throw new Error(`setupAgent.fromConfig: 'suspendedTags' lists ${unknown.map((tag) => `'${tag}'`).join(", ")}, which no state declares in its 'tags'. Tag the waiting state(s) — e.g. "tags": ["${unknown[0]}"] — or remove the entry.`);
|
|
1145
|
+
return (snapshot) => suspendedTags.some((tag) => snapshot.hasTag(tag));
|
|
1146
|
+
}
|
|
1146
1147
|
function setupAgentFromConfig(config, options) {
|
|
1147
1148
|
if (!options || typeof options.compileSchema !== "function") throw new Error("setupAgent.fromConfig(...) requires a 'compileSchema' option: { compileSchema: (jsonSchema, name) => StandardSchemaV1 }. Bring your own JSON Schema engine (Ajv, @cfworker/json-schema, a compiled-Zod-from-JSON-Schema pipeline, ...). Core intentionally ships no JSON Schema engine.");
|
|
1148
1149
|
const { compileSchema } = options;
|
|
@@ -1173,6 +1174,8 @@ function setupAgentFromConfig(config, options) {
|
|
|
1173
1174
|
models: {}
|
|
1174
1175
|
});
|
|
1175
1176
|
if (machine.config) machineStaticTransitionTargets.set(machine.config, translation.transitionTargets);
|
|
1177
|
+
const isSuspended = resolveSuspensionPredicate(config, options);
|
|
1178
|
+
if (isSuspended && machine.config) machineSuspensionPredicates.set(machine.config, isSuspended);
|
|
1176
1179
|
return {
|
|
1177
1180
|
machine,
|
|
1178
1181
|
schemas
|
|
@@ -1226,7 +1229,7 @@ const agentUsageEventSchema = { "~standard": {
|
|
|
1226
1229
|
path: ["usage", field]
|
|
1227
1230
|
});
|
|
1228
1231
|
}
|
|
1229
|
-
if (event.kind !== void 0 && !USAGE_KINDS.
|
|
1232
|
+
if (event.kind !== void 0 && !USAGE_KINDS.some((kind) => kind === event.kind)) issues.push({
|
|
1230
1233
|
message: `Expected one of ${USAGE_KINDS.join(", ")}`,
|
|
1231
1234
|
path: ["kind"]
|
|
1232
1235
|
});
|
|
@@ -1356,7 +1359,47 @@ function resolveAgentStateSchemas(contextSchema, states) {
|
|
|
1356
1359
|
* ```
|
|
1357
1360
|
*/
|
|
1358
1361
|
function setupAgent(config) {
|
|
1359
|
-
|
|
1362
|
+
const schemas = normalizeAgentSchemas(config);
|
|
1363
|
+
const requestActors = createRequestActors(config.requests ?? {});
|
|
1364
|
+
const actors = createAgentActors(config.actors, requestActors);
|
|
1365
|
+
const base = setup({
|
|
1366
|
+
schemas: {
|
|
1367
|
+
context: schemas.context,
|
|
1368
|
+
events: schemas.events,
|
|
1369
|
+
input: schemas.input,
|
|
1370
|
+
output: schemas.output,
|
|
1371
|
+
meta: schemas.meta,
|
|
1372
|
+
...schemas.emitted && Object.keys(schemas.emitted).length > 0 ? { emitted: schemas.emitted } : {}
|
|
1373
|
+
},
|
|
1374
|
+
...config.states ? { states: resolveAgentStateSchemas(schemas.context, config.states) } : {},
|
|
1375
|
+
actors,
|
|
1376
|
+
actions: config.actions,
|
|
1377
|
+
guards: config.guards,
|
|
1378
|
+
delays: config.delays
|
|
1379
|
+
});
|
|
1380
|
+
const createBaseMachine = base.createMachine.bind(base);
|
|
1381
|
+
const models = config.models ?? {};
|
|
1382
|
+
const machineOptions = {
|
|
1383
|
+
schemas,
|
|
1384
|
+
actors,
|
|
1385
|
+
models
|
|
1386
|
+
};
|
|
1387
|
+
return Object.assign(base, {
|
|
1388
|
+
createMachine(machineConfig) {
|
|
1389
|
+
assertStateSchemaKeysExist(config.states, machineConfig?.states);
|
|
1390
|
+
const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
|
|
1391
|
+
agentExecutionOptions.set(machine, machineOptions);
|
|
1392
|
+
if (config.isSuspended) {
|
|
1393
|
+
const rootConfig = machine.config;
|
|
1394
|
+
if (rootConfig) machineSuspensionPredicates.set(rootConfig, config.isSuspended);
|
|
1395
|
+
}
|
|
1396
|
+
return machine;
|
|
1397
|
+
},
|
|
1398
|
+
schemas,
|
|
1399
|
+
models,
|
|
1400
|
+
requests: requestActors,
|
|
1401
|
+
appendMessages
|
|
1402
|
+
});
|
|
1360
1403
|
}
|
|
1361
1404
|
function collectFinalStateOutputs(states, outputs = []) {
|
|
1362
1405
|
for (const state of Object.values(states ?? {})) {
|
|
@@ -1400,24 +1443,6 @@ function normalizeAgentSchemas(config) {
|
|
|
1400
1443
|
context: loose.context
|
|
1401
1444
|
});
|
|
1402
1445
|
}
|
|
1403
|
-
function normalizeAgentRequestInput(requests) {
|
|
1404
|
-
return requests ?? {};
|
|
1405
|
-
}
|
|
1406
|
-
/**
|
|
1407
|
-
* Runtime guard: a key appearing in both `actors`/`requests` is almost
|
|
1408
|
-
* certainly a mistake (whichever spread applies last would silently win) —
|
|
1409
|
-
* fail fast with a clear message rather than let one implementation shadow
|
|
1410
|
-
* another.
|
|
1411
|
-
*/
|
|
1412
|
-
function assertNoActorKeyCollisions(actors, requests) {
|
|
1413
|
-
const seenIn = /* @__PURE__ */ new Map();
|
|
1414
|
-
const groups = [["actors", actors], ["requests", requests]];
|
|
1415
|
-
for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) {
|
|
1416
|
-
const existingGroup = seenIn.get(key);
|
|
1417
|
-
if (existingGroup) throw new Error(`setupAgent: key '${key}' is defined in both '${existingGroup}' and '${groupName}'. Each actor source key must be unique across 'actors' and 'requests'.`);
|
|
1418
|
-
seenIn.set(key, groupName);
|
|
1419
|
-
}
|
|
1420
|
-
}
|
|
1421
1446
|
/**
|
|
1422
1447
|
* Runtime guard: every key of the `setupAgent({ states })` narrowing map must
|
|
1423
1448
|
* name a real state node in the machine config. A typo'd key is otherwise a
|
|
@@ -1443,20 +1468,30 @@ const RESERVED_AGENT_ACTOR_KEYS = [
|
|
|
1443
1468
|
DECIDE_ACTOR
|
|
1444
1469
|
];
|
|
1445
1470
|
/**
|
|
1446
|
-
*
|
|
1447
|
-
*
|
|
1448
|
-
*
|
|
1449
|
-
*
|
|
1450
|
-
*
|
|
1451
|
-
*
|
|
1471
|
+
* Runtime guards over the user-supplied `actors`/`requests` keys, in one walk
|
|
1472
|
+
* of both groups:
|
|
1473
|
+
*
|
|
1474
|
+
* 1. A key in the reserved `agent.*` builtin namespace is rejected. Without
|
|
1475
|
+
* this, the builtins-first spread in {@link createAgentActors} lets such a
|
|
1476
|
+
* key overwrite the builtin (`agent.decide`, …) silently. Deliberate
|
|
1477
|
+
* override of a builtin is still possible after the machine is created, via
|
|
1478
|
+
* `machine.provide({ actors: { 'agent.decide': ... } })`.
|
|
1479
|
+
* 2. A key appearing in BOTH groups is almost certainly a mistake (whichever
|
|
1480
|
+
* spread applies last would silently win) — fail fast with a clear message
|
|
1481
|
+
* rather than let one implementation shadow another.
|
|
1452
1482
|
*/
|
|
1453
|
-
function
|
|
1483
|
+
function assertActorKeys(actors, requests) {
|
|
1484
|
+
const seenIn = /* @__PURE__ */ new Map();
|
|
1454
1485
|
const groups = [["actors", actors], ["requests", requests]];
|
|
1455
|
-
for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {}))
|
|
1486
|
+
for (const [groupName, group] of groups) for (const key of Object.keys(group ?? {})) {
|
|
1487
|
+
if (RESERVED_AGENT_ACTOR_KEYS.some((reserved) => reserved === key)) throw new Error(`setupAgent: '${groupName}' key '${key}' is a reserved builtin agent actor and cannot be redefined here (it would silently clobber the builtin). Reserved keys: ${RESERVED_AGENT_ACTOR_KEYS.join(", ")}. To deliberately override a builtin, do it on the created machine instead: machine.provide({ actors: { '${key}': ... } }).`);
|
|
1488
|
+
const existingGroup = seenIn.get(key);
|
|
1489
|
+
if (existingGroup) throw new Error(`setupAgent: key '${key}' is defined in both '${existingGroup}' and '${groupName}'. Each actor source key must be unique across 'actors' and 'requests'.`);
|
|
1490
|
+
seenIn.set(key, groupName);
|
|
1491
|
+
}
|
|
1456
1492
|
}
|
|
1457
1493
|
function createAgentActors(actors, requestActors) {
|
|
1458
|
-
|
|
1459
|
-
assertNoReservedAgentKeys(actors, requestActors);
|
|
1494
|
+
assertActorKeys(actors, requestActors);
|
|
1460
1495
|
return {
|
|
1461
1496
|
...builtinTextActors,
|
|
1462
1497
|
[USER_INPUT_ACTOR]: userInputActor,
|
|
@@ -1465,53 +1500,5 @@ function createAgentActors(actors, requestActors) {
|
|
|
1465
1500
|
...requestActors
|
|
1466
1501
|
};
|
|
1467
1502
|
}
|
|
1468
|
-
function createAgentSetupConfig(schemas, actors, config) {
|
|
1469
|
-
return {
|
|
1470
|
-
schemas: {
|
|
1471
|
-
context: schemas.context,
|
|
1472
|
-
events: schemas.events,
|
|
1473
|
-
input: schemas.input,
|
|
1474
|
-
output: schemas.output,
|
|
1475
|
-
meta: schemas.meta,
|
|
1476
|
-
...schemas.emitted && Object.keys(schemas.emitted).length > 0 ? { emitted: schemas.emitted } : {}
|
|
1477
|
-
},
|
|
1478
|
-
...config.states ? { states: resolveAgentStateSchemas(schemas.context, config.states) } : {},
|
|
1479
|
-
actors,
|
|
1480
|
-
actions: config.actions,
|
|
1481
|
-
guards: config.guards,
|
|
1482
|
-
delays: config.delays
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
function createSetupAgent(config) {
|
|
1486
|
-
const schemas = normalizeAgentSchemas(config);
|
|
1487
|
-
const requestActors = createRequestActors(normalizeAgentRequestInput(config.requests));
|
|
1488
|
-
const actors = createAgentActors(config.actors, requestActors);
|
|
1489
|
-
const base = setup(createAgentSetupConfig(schemas, actors, config));
|
|
1490
|
-
const createBaseMachine = base.createMachine.bind(base);
|
|
1491
|
-
const models = config.models ?? {};
|
|
1492
|
-
const machineOptions = {
|
|
1493
|
-
schemas,
|
|
1494
|
-
actors,
|
|
1495
|
-
models
|
|
1496
|
-
};
|
|
1497
|
-
return Object.assign(base, {
|
|
1498
|
-
createMachine(machineConfig) {
|
|
1499
|
-
assertStateSchemaKeysExist(config.states, machineConfig?.states);
|
|
1500
|
-
const machine = createBaseMachine(withRootOutputFromSingleFinal(machineConfig));
|
|
1501
|
-
agentExecutionOptions.set(machine, machineOptions);
|
|
1502
|
-
if (config.isSuspended) {
|
|
1503
|
-
const rootConfig = machine.config;
|
|
1504
|
-
if (rootConfig) machineSuspensionPredicates.set(rootConfig, config.isSuspended);
|
|
1505
|
-
}
|
|
1506
|
-
return machine;
|
|
1507
|
-
},
|
|
1508
|
-
schemas,
|
|
1509
|
-
models,
|
|
1510
|
-
requests: requestActors,
|
|
1511
|
-
appendMessages(resolve) {
|
|
1512
|
-
return appendMessages(resolve);
|
|
1513
|
-
}
|
|
1514
|
-
});
|
|
1515
|
-
}
|
|
1516
1503
|
//#endregion
|
|
1517
|
-
export { resolveAgentStep as _, AgentReplayDivergenceError as a, messagesSchema as b, diffEventLogs as c,
|
|
1504
|
+
export { resolveAgentStep as _, AgentReplayDivergenceError as a, messagesSchema as b, diffEventLogs as c, replay as d, validateReplayEntries as f, initialAgentStep as g, getInvokeEffectMetadata as h, AGENT_USAGE_EVENT_TYPE as i, getAgentEffects as l, executeAgentRequest as m, setupAgent as n, AgentReplayMachineMismatchError as o, verifyReplay as p, AGENT_INIT_EVENT_TYPE as r, createReplayEntry as s, createAgentSchemas as t, initEntry as u, transitionAgentStep as v, appendMessages as y };
|