@statelyai/agent 2.0.0-alpha.10 → 2.0.0-alpha.12
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 +62 -99
- package/dist/ai-sdk.d.cts +10 -117
- package/dist/ai-sdk.d.mts +10 -117
- package/dist/ai-sdk.mjs +63 -91
- package/dist/{decision-CQdrKc8k.mjs → decision-BezSD_YC.mjs} +120 -32
- package/dist/{decision-b-lkcs4L.cjs → decision-dWGhBh0P.cjs} +141 -53
- package/dist/errors-BQRk9eiZ.d.cts +19 -0
- package/dist/errors-C9rxnWbX.d.mts +19 -0
- package/dist/errors-CeSXQx0v.mjs +23 -0
- package/dist/errors-DUBBzRLP.cjs +28 -0
- package/dist/event-log-store-CNT_7F0V.cjs +452 -0
- package/dist/event-log-store-CriMgX1D.d.mts +144 -0
- package/dist/event-log-store-D7pWtIhb.mjs +411 -0
- package/dist/event-log-store-Ruq18mGp.d.cts +144 -0
- package/dist/index.cjs +2844 -30
- package/dist/index.d.cts +1005 -12
- package/dist/index.d.mts +1005 -12
- package/dist/index.mjs +2799 -4
- package/dist/machines.cjs +752 -0
- package/dist/machines.d.cts +372 -0
- package/dist/machines.d.mts +372 -0
- package/dist/machines.mjs +741 -0
- package/dist/otel.cjs +268 -0
- package/dist/otel.d.cts +67 -0
- package/dist/otel.d.mts +67 -0
- package/dist/otel.mjs +267 -0
- package/dist/run-agent-B1nBa7aV.d.mts +1111 -0
- package/dist/run-agent-qkg0evvW.d.cts +1111 -0
- package/dist/setup-agent-DAZZSjDS.mjs +1711 -0
- package/dist/setup-agent-DP95MFrI.cjs +1836 -0
- package/dist/sqlite.cjs +135 -0
- package/dist/sqlite.d.cts +57 -0
- package/dist/sqlite.d.mts +57 -0
- package/dist/sqlite.mjs +133 -0
- package/dist/{text-logic-C7WJpCIc.d.mts → text-logic-CorGzucG.d.cts} +110 -66
- package/dist/{text-logic-CZjyACzQ.d.cts → text-logic-DjR5PUVz.d.mts} +110 -66
- package/dist/{types-C9QiMjre.d.cts → types-QbEfCVny.d.cts} +1 -1
- package/dist/{types-qm00QF91.d.mts → types-_FXoFBGO.d.mts} +1 -1
- package/package.json +55 -27
- package/readme.md +40 -9
- package/schemas/agent-workflow.json +44 -26
- package/skills/generate-machine/SKILL.md +267 -0
- package/dist/cli.cjs +0 -64
- package/dist/cli.d.cts +0 -1
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +0 -65
- package/dist/openai-compat.cjs +0 -319
- package/dist/openai-compat.d.cts +0 -98
- package/dist/openai-compat.d.mts +0 -98
- package/dist/openai-compat.mjs +0 -312
- package/dist/run-agent-BFMkuI1F.cjs +0 -1599
- package/dist/run-agent-BVMd--1l.d.cts +0 -1103
- package/dist/run-agent-BoAOq_0Z.mjs +0 -1540
- package/dist/run-agent-DzYJb3CK.d.mts +0 -1103
- package/dist/src-D-77Ha5p.cjs +0 -1087
- package/dist/src-DUeIFjv-.mjs +0 -1016
- package/dist/utils-Dri7aeEG.d.cts +0 -108
- package/dist/utils-Y6GDRGGE.d.mts +0 -108
- package/dist/zod.cjs +0 -31
- package/dist/zod.d.cts +0 -30
- package/dist/zod.d.mts +0 -30
- package/dist/zod.mjs +0 -30
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,618 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { A as
|
|
4
|
-
import { a as
|
|
5
|
-
import {
|
|
1
|
+
import { C as UserMessage, S as ToolResultPart, _ as StandardSchemaV1, a as AgentToolChoice, b as ToolCallPart, c as AgentTools, d as ChosenEvent, f as EventUnion, g as NormalizedEventSchemas, h as InferOutput, i as AgentTool, l as AllowedEvents, m as ImagePart, n as AgentMessage, o as AgentToolDescriptor, p as FilePart, r as AgentSnapshotStore, s as AgentToolExecute, t as AgentEventSchemaInputMap, u as AssistantMessage, v as SystemMessage, x as ToolMessage, y as TextPart } from "./types-_FXoFBGO.mjs";
|
|
2
|
+
import { t as AgentError } from "./errors-C9rxnWbX.mjs";
|
|
3
|
+
import { A as AgentDecisionInput, B as resolveDecision, C as createTextLogic, D as parseStructuredEnvelope, E as parseOutput, F as DecisionLogicConfig, G as getAcceptedEvents, H as AgentEventToolNameResolver, I as PLAN_DONE_EVENT_TYPE, K as parseAgentEvent, L as PlanLogic, M as AgentPlanInput, N as AgentPlanOutput, O as AgentDecisionExecutor, P as DecisionAttempt, R as ResolveDecisionOptions, S as buildEnvelopeSchema, T as parseModelRef, U as AgentRequestOptions, V as AgentEventDescriptor, W as AgentRequestSource, _ as TextLogic, a as AgentRequestExecutor, b as TextLogicExecutor, c as AgentRequestExecutors, d as AgentUsage, f as AgentUserInput, g as StructuredOutputEnvelope, h as BuiltinAgentActors, i as AgentOutputMode, j as AgentDecisionRequest, k as AgentDecisionExhaustedError, l as AgentRequestMode, m as AiSdkShapedTextResult, n as AgentModelMap, o as AgentRequestExecutorInfo, p as AiSdkShapedStreamResult, r as AgentModelRef, s as AgentRequestExecutorResult, t as AgentCallUsage, u as AgentTextRequest, v as TextLogicConfig, w as getAgentOutputMode, x as bindRequestExecutor, y as TextLogicExecuteArgs, z as renderDecisionAttempts } from "./text-logic-DjR5PUVz.mjs";
|
|
4
|
+
import { A as AgentReplayDivergenceError, B as getCallUsage, C as AgentStateRequest, D as AgentEffectDiff, E as AgentEffect, F as ReplayOptions, G as AgentRequest, H as replay, I as ReplayResult, K as AgentStepRequest, L as createReplayEntry, M as AgentUsageEvent, N as CreateReplayEntryOptions, O as AgentEventLogDiff, P as GetAgentEffectsOptions, R as diffEventLogs, S as traceTransitions, T as AGENT_USAGE_EVENT_TYPE, U as verifyReplay, V as initEntry, W as AgentPlanRequest, _ as createAgentActor, a as AgentMessageInfo, b as runAgent, c as AgentTraceEvent, d as InspectedActorRef, f as JsonSerializableTraceEvent, g as RunAgentResult, h as RunAgentOptions, i as AgentIllegalResumeEventError, j as AgentReplayMachineMismatchError, k as AgentLogPatchOperation, l as AgentUserInputExecutor, m as RunAgentErrorCause, n as AgentActorSession, o as AgentRunMeta, p as PendingUserInput, q as executeAgentRequest, r as AgentIdleError, s as AgentSnapshotVersionMismatchError, t as AGENT_TRACE_SCHEMA_VERSION, u as GenerateResult, v as generateResult, w as AGENT_INIT_EVENT_TYPE, x as serializeTraceEvent, y as inspectTransitions, z as getAgentEffects } from "./run-agent-B1nBa7aV.mjs";
|
|
5
|
+
import { a as AgentLogVerification, c as assertAgentLogEntry, d as createInMemoryEventLogStore, i as AgentLogEntry, l as assertEventLogStoreConformance, n as AgentEventLogConflictError, o as JsonValue, r as AgentEventLogStore, s as NonSerializableAgentEventError, t as AGENT_EVENT_SCHEMA_VERSION, u as assertJsonSerializable } from "./event-log-store-CriMgX1D.mjs";
|
|
6
|
+
import { AnyActorLogic, AnyMachineSnapshot, AnySetupConfig, AnyStateMachine, AsyncActorLogic, EventFromLogic, EventObject, InputFrom, MachineContext, MetaObject, NonReducibleUnknown, SetupReturnFromConfig, SetupStateSchema, SnapshotFrom, StateValue } from "xstate";
|
|
6
7
|
|
|
8
|
+
//#region src/messages.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Builds a transition-function result that appends one or more
|
|
11
|
+
* {@link AgentMessage}s to a context's `messages` array. `resolve` is either
|
|
12
|
+
* a message (or array of messages) or a function of `{ context, event }`
|
|
13
|
+
* returning them; the returned function is meant to be used directly as (or
|
|
14
|
+
* composed into) a transition's result, e.g. `on: { USER_REPLIED:
|
|
15
|
+
* agent.appendMessages(({ event }) => userMessage(event.text)) }`. Requires
|
|
16
|
+
* `messages: AgentMessage[]` on context — see {@link messagesSchema} for a
|
|
17
|
+
* ready-made schema for that field.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* on: {
|
|
22
|
+
* USER_REPLIED: appendMessages(({ event }) => userMessage(event.text)),
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
declare function appendMessages<TContext extends {
|
|
27
|
+
messages: AgentMessage[];
|
|
28
|
+
}, TEvent extends EventObject>(resolve: AgentMessage | AgentMessage[] | ((args: {
|
|
29
|
+
context: TContext;
|
|
30
|
+
event: TEvent;
|
|
31
|
+
}) => AgentMessage | AgentMessage[])): (args: {
|
|
32
|
+
context: TContext;
|
|
33
|
+
event: TEvent;
|
|
34
|
+
}) => {
|
|
35
|
+
context: {
|
|
36
|
+
messages: AgentMessage[];
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* A {@link StandardSchemaV1} validating an `AgentMessage[]` context field —
|
|
41
|
+
* checks that every message has a known `role` (`system`/`user`/`assistant`/
|
|
42
|
+
* `tool`) and that `content` is either a string (where the role allows it) or
|
|
43
|
+
* an array of parts with a known `type`. Use it directly as a context
|
|
44
|
+
* schema's `messages` field when authoring with `createAgentSchemas`.
|
|
45
|
+
*/
|
|
46
|
+
declare const messagesSchema: StandardSchemaV1<AgentMessage[]>;
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/workflow-config.d.ts
|
|
49
|
+
type JsonSchemaObject = {
|
|
50
|
+
type?: string | string[];
|
|
51
|
+
properties?: Record<string, JsonSchemaObject>;
|
|
52
|
+
required?: string[];
|
|
53
|
+
items?: JsonSchemaObject;
|
|
54
|
+
enum?: unknown[];
|
|
55
|
+
const?: unknown;
|
|
56
|
+
additionalProperties?: unknown;
|
|
57
|
+
[key: string]: unknown;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Compiles a JSON Schema object (from an `AgentWorkflowConfig`) into a
|
|
61
|
+
* runtime `StandardSchemaV1` validator. `setupAgent.fromConfig(...)` calls
|
|
62
|
+
* this once per schema in the config (context/events/input/output/meta,
|
|
63
|
+
* request input/output) — bring your own engine (Ajv, @cfworker/json-schema,
|
|
64
|
+
* a compiled-Zod-from-JSON-Schema pipeline, ...). Core intentionally ships no
|
|
65
|
+
* JSON Schema engine.
|
|
66
|
+
*/
|
|
67
|
+
type SchemaCompiler = (jsonSchema: Record<string, unknown>, name: string) => StandardSchemaV1;
|
|
68
|
+
/**
|
|
69
|
+
* Serializable JSON/YAML machine definition — the config a database, visual
|
|
70
|
+
* editor, or LLM could produce and hand to `setupAgent.fromConfig(config, {
|
|
71
|
+
* compileSchema })` to get back the same kind of `AnyStateMachine`
|
|
72
|
+
* TypeScript `setupAgent(...)` authoring would build. JS/TS authoring should
|
|
73
|
+
* use `setupAgent(...)` directly instead of this JSON form. Any `unknown`-
|
|
74
|
+
* typed field here (`model`, `guard`, action `params`, …) accepts either a
|
|
75
|
+
* literal JSON value or a `"{{ path.to.value }}"` template-expression string
|
|
76
|
+
* resolved against `{ context, event, input, output }` at machine-build/
|
|
77
|
+
* transition time — see the sibling `evaluateWorkflowConfigValue` lowering.
|
|
78
|
+
*/
|
|
79
|
+
interface AgentWorkflowConfig {
|
|
80
|
+
/** JSON Schema reference (`"$schema"`) editors attach to a config file. Ignored by the lowering. */
|
|
81
|
+
$schema?: string;
|
|
82
|
+
key?: string;
|
|
83
|
+
id?: string;
|
|
84
|
+
version?: string;
|
|
85
|
+
description?: string;
|
|
86
|
+
schemas?: {
|
|
87
|
+
input?: JsonSchemaObject;
|
|
88
|
+
context?: JsonSchemaObject;
|
|
89
|
+
events?: Record<string, JsonSchemaObject>;
|
|
90
|
+
emitted?: Record<string, JsonSchemaObject>;
|
|
91
|
+
output?: JsonSchemaObject;
|
|
92
|
+
meta?: JsonSchemaObject;
|
|
93
|
+
};
|
|
94
|
+
context?: Record<string, unknown>;
|
|
95
|
+
requests?: Record<string, AgentWorkflowRequestConfig>;
|
|
96
|
+
actors?: Record<string, AgentWorkflowActorConfig>;
|
|
97
|
+
initial: string;
|
|
98
|
+
states: Record<string, AgentWorkflowStateConfig>;
|
|
99
|
+
meta?: Record<string, unknown>;
|
|
100
|
+
}
|
|
101
|
+
/** A `requests` entry in {@link AgentWorkflowConfig} — the JSON equivalent of a `setupAgent({ requests })` `TextLogicConfig`. Fields beyond `input`/`output`/`tools`/`mode`/`description` are `unknown` because they accept template-expression strings (see {@link AgentWorkflowConfig}). */
|
|
102
|
+
interface AgentWorkflowRequestConfig {
|
|
103
|
+
mode?: AgentRequestMode;
|
|
104
|
+
description?: string;
|
|
105
|
+
model: unknown;
|
|
106
|
+
system?: unknown;
|
|
107
|
+
prompt?: unknown;
|
|
108
|
+
messages?: unknown;
|
|
109
|
+
input: JsonSchemaObject;
|
|
110
|
+
output: JsonSchemaObject;
|
|
111
|
+
tools?: AgentTools;
|
|
112
|
+
toolChoice?: AgentToolChoice | unknown;
|
|
113
|
+
/** Opt into the structured-output envelope's `reasoning` field (see `AgentTextRequest.reasoning`). */
|
|
114
|
+
reasoning?: boolean;
|
|
115
|
+
temperature?: unknown;
|
|
116
|
+
maxOutputTokens?: unknown;
|
|
117
|
+
topP?: unknown;
|
|
118
|
+
topK?: unknown;
|
|
119
|
+
seed?: unknown;
|
|
120
|
+
stopSequences?: unknown;
|
|
121
|
+
metadata?: unknown;
|
|
122
|
+
}
|
|
123
|
+
/** An `actors` entry in {@link AgentWorkflowConfig} — declares a placeholder actor source (by key) with no host execution wired from JSON; provide it via `machine.provide({ actors })` after `setupAgent.fromConfig(...)`. */
|
|
124
|
+
interface AgentWorkflowActorConfig {
|
|
125
|
+
input?: JsonSchemaObject;
|
|
126
|
+
output?: JsonSchemaObject;
|
|
127
|
+
description?: string;
|
|
128
|
+
}
|
|
129
|
+
/** A `states` entry in {@link AgentWorkflowConfig} — the JSON equivalent of an XState state node config. */
|
|
130
|
+
interface AgentWorkflowStateConfig {
|
|
131
|
+
description?: string;
|
|
132
|
+
type?: "parallel" | "history" | "final" | "choice";
|
|
133
|
+
initial?: string;
|
|
134
|
+
states?: Record<string, AgentWorkflowStateConfig>;
|
|
135
|
+
choice?: AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[];
|
|
136
|
+
invoke?: AgentWorkflowInvokeConfig | AgentWorkflowInvokeConfig[];
|
|
137
|
+
on?: Record<string, AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[]>;
|
|
138
|
+
always?: AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[];
|
|
139
|
+
onDone?: AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[];
|
|
140
|
+
after?: Record<string, AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[]>;
|
|
141
|
+
entry?: AgentWorkflowActionConfig | AgentWorkflowActionConfig[];
|
|
142
|
+
exit?: AgentWorkflowActionConfig | AgentWorkflowActionConfig[];
|
|
143
|
+
tags?: string[];
|
|
144
|
+
output?: unknown;
|
|
145
|
+
meta?: Record<string, unknown>;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* An `invoke` entry in {@link AgentWorkflowStateConfig}. For `src:
|
|
149
|
+
* 'agent.decide'`, the chosen event is delivered automatically and handled by
|
|
150
|
+
* the state's `on` transitions — a decision has no output of its own, so an
|
|
151
|
+
* `onDone` there is always a config error and is rejected at
|
|
152
|
+
* `setupAgent.fromConfig(...)` time. `onError` handles retries-exhausted.
|
|
153
|
+
*/
|
|
154
|
+
interface AgentWorkflowInvokeConfig {
|
|
155
|
+
id?: string;
|
|
156
|
+
src: string;
|
|
157
|
+
input?: unknown;
|
|
158
|
+
onDone?: AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[];
|
|
159
|
+
onError?: AgentWorkflowTransitionConfig | AgentWorkflowTransitionConfig[];
|
|
160
|
+
meta?: Record<string, unknown>;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* A transition target in {@link AgentWorkflowConfig}
|
|
164
|
+
* (`on`/`always`/`onDone`/`after`/invoke `onDone`/`onError`) — the JSON
|
|
165
|
+
* equivalent of an XState transition config. A string `guard` containing
|
|
166
|
+
* `{{ ... }}` is a template expression evaluated as truthy/falsy; any other
|
|
167
|
+
* string is a named guard reference resolved against the `guards` passed to
|
|
168
|
+
* `setupAgent.fromConfig(config, { guards })` (unresolvable references throw
|
|
169
|
+
* at build time).
|
|
170
|
+
*/
|
|
171
|
+
interface AgentWorkflowTransitionConfig {
|
|
172
|
+
target?: string | string[];
|
|
173
|
+
guard?: unknown;
|
|
174
|
+
assign?: Record<string, unknown>;
|
|
175
|
+
actions?: AgentWorkflowActionConfig | AgentWorkflowActionConfig[];
|
|
176
|
+
description?: string;
|
|
177
|
+
reenter?: boolean;
|
|
178
|
+
meta?: Record<string, unknown>;
|
|
179
|
+
}
|
|
180
|
+
/** An `entry`/`exit`/transition `actions` entry in {@link AgentWorkflowConfig} — a bare context `assign`, an `emit`, or a named action `type` (with template-expression `params`) resolved against the `actions` passed to `setupAgent.fromConfig(config, { actions })`. */
|
|
181
|
+
interface AgentWorkflowActionConfig {
|
|
182
|
+
type?: string;
|
|
183
|
+
params?: unknown;
|
|
184
|
+
assign?: Record<string, unknown>;
|
|
185
|
+
emit?: unknown;
|
|
186
|
+
[key: string]: unknown;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* What `setupAgent.fromConfig(...)` returns: the built machine plus the
|
|
190
|
+
* schema pack compiled from the config's `schemas` (with `compileSchema`).
|
|
191
|
+
* The pack is what hosts need for the runtime work the machine's types can't
|
|
192
|
+
* do for a JSON-authored agent — e.g. validating an inbound raw event:
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* const { machine, schemas } = setupAgent.fromConfig(config, { compileSchema });
|
|
197
|
+
* const event = parseAgentEvent(snapshot, raw, { events: schemas.events });
|
|
198
|
+
* ```
|
|
199
|
+
*/
|
|
200
|
+
interface FromConfigResult {
|
|
201
|
+
machine: AnyStateMachine;
|
|
202
|
+
/** Compiled `context`/`events`/`input`/`output`/`meta`/`emitted` schemas — the same pack `runAgent` executes this machine with. */
|
|
203
|
+
schemas: AgentSchemaPack<StandardSchemaV1<Record<string, unknown>>, Record<string, StandardSchemaV1>, StandardSchemaV1, StandardSchemaV1, StandardSchemaV1<MetaObject>>;
|
|
204
|
+
}
|
|
205
|
+
/** Options for `setupAgent.fromConfig(...)`. */
|
|
206
|
+
interface FromConfigOptions {
|
|
207
|
+
/**
|
|
208
|
+
* Compile a JSON Schema from the config into a runtime validator. Bring
|
|
209
|
+
* your own engine (Ajv, @cfworker/json-schema, a compiled-Zod-from-JSON-Schema
|
|
210
|
+
* pipeline, ...). Core intentionally ships no JSON Schema engine.
|
|
211
|
+
*/
|
|
212
|
+
compileSchema: SchemaCompiler;
|
|
213
|
+
/**
|
|
214
|
+
* Host guard implementations for named guard references in the config
|
|
215
|
+
* (`guard: "isFromHuman"`). Each is called with `{ context, event }` and
|
|
216
|
+
* returns a boolean. A named guard reference with no implementation here is
|
|
217
|
+
* a build-time error — a guard is never silently dropped.
|
|
218
|
+
*/
|
|
219
|
+
guards?: Record<string, (args: {
|
|
220
|
+
context: any;
|
|
221
|
+
event: any;
|
|
222
|
+
}) => boolean>;
|
|
223
|
+
/**
|
|
224
|
+
* Host action implementations for named action types in the config
|
|
225
|
+
* (`{ type: "notify", params: ... }`). Each is called with the
|
|
226
|
+
* template-resolved `params` as its only argument — pull context/event data
|
|
227
|
+
* into `params` via `{{ ... }}` templates. A named action type with no
|
|
228
|
+
* implementation here is a build-time error.
|
|
229
|
+
*/
|
|
230
|
+
actions?: Record<string, (params: any) => unknown>;
|
|
231
|
+
}
|
|
232
|
+
//#endregion
|
|
233
|
+
//#region src/setup-agent.d.ts
|
|
234
|
+
type Constrain<T, TConstraint> = T extends TConstraint ? T : TConstraint;
|
|
235
|
+
type ContextOf<TContextSchema extends StandardSchemaV1> = Constrain<InferOutput<TContextSchema>, MachineContext>;
|
|
236
|
+
type EventsOf<TEventSchemas extends AgentEventSchemaInputMap> = Constrain<EventUnion<TEventSchemas>, EventObject>;
|
|
237
|
+
type SetupActors<TActors extends { [K in keyof TActors]: AnyActorLogic }> = { [K in keyof TActors]: TActors[K] extends AsyncActorLogic<infer TOutput, infer TInput> ? AsyncActorLogic<TOutput, TInput> : TActors[K] };
|
|
238
|
+
type AgentSetupActors<TActors extends { [K in keyof TActors]: AnyActorLogic }, TEvent extends string = string, TModel extends string = string> = TActors & BuiltinAgentActors<TEvent, TModel>;
|
|
239
|
+
/**
|
|
240
|
+
* A machine's full schema set — context, event payloads, machine input/
|
|
241
|
+
* output, and state/transition meta — as returned by {@link createAgentSchemas}
|
|
242
|
+
* and retained on `setupAgent(...)`'s `result.schemas` for runtime
|
|
243
|
+
* validation (e.g. by the step path to validate `initialAgentStep` input, or
|
|
244
|
+
* by `getAcceptedEvents` to attach event payload schemas). Unlike
|
|
245
|
+
* `AgentSchemaConfig` (the input to `createAgentSchemas`), every field here
|
|
246
|
+
* is required — `events`/`input`/`output`/`meta` default to empty/unknown
|
|
247
|
+
* schemas when not supplied.
|
|
248
|
+
*/
|
|
249
|
+
interface AgentSchemaPack<TContextSchema extends StandardSchemaV1<Record<string, unknown>> = StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap = AgentEventSchemaInputMap, TInputSchema extends StandardSchemaV1 = StandardSchemaV1<NonReducibleUnknown>, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1<NonReducibleUnknown>, TMetaSchema extends StandardSchemaV1 = StandardSchemaV1<MetaObject>, TEmittedSchemas extends Record<string, StandardSchemaV1> = Record<string, StandardSchemaV1>> {
|
|
250
|
+
context: TContextSchema;
|
|
251
|
+
events: NormalizedEventSchemas<TEventSchemas>;
|
|
252
|
+
input: TInputSchema;
|
|
253
|
+
output: TOutputSchema;
|
|
254
|
+
meta: TMetaSchema;
|
|
255
|
+
/** Schemas for events the machine emits (`enq.emit(...)`), keyed by event type — they type `enq.emit` in the machine and the `on` handlers of {@link runAgent}. Optional: omitted means emitted events stay untyped. */
|
|
256
|
+
emitted?: TEmittedSchemas;
|
|
257
|
+
}
|
|
258
|
+
type AgentSchemaConfig<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap, TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetaSchema extends StandardSchemaV1, TEmittedSchemas extends Record<string, StandardSchemaV1> = Record<string, StandardSchemaV1>> = {
|
|
259
|
+
context: TContextSchema;
|
|
260
|
+
events?: TEventSchemas;
|
|
261
|
+
input?: TInputSchema;
|
|
262
|
+
output?: TOutputSchema;
|
|
263
|
+
meta?: TMetaSchema;
|
|
264
|
+
emitted?: TEmittedSchemas;
|
|
265
|
+
};
|
|
266
|
+
/**
|
|
267
|
+
* The payload of the reserved `'@agent.usage'` event — {@link AgentUsageEvent}
|
|
268
|
+
* without its `type`. It is what a machine's `'@agent.usage'` handler receives
|
|
269
|
+
* alongside `type`, since event schemas describe payloads only.
|
|
270
|
+
*/
|
|
271
|
+
type AgentUsageEventPayload = Omit<AgentUsageEvent, "type">;
|
|
272
|
+
/**
|
|
273
|
+
* An authored event schema map with the reserved `'@agent.usage'` entry added —
|
|
274
|
+
* every agent machine's event union includes it, so `on: { '@agent.usage': … }`
|
|
275
|
+
* is typed (and autocompletes) without the machine declaring anything.
|
|
276
|
+
* Idempotent: re-applying it to an already-registered map is a no-op.
|
|
277
|
+
*/
|
|
278
|
+
type WithAgentUsageEvent<T extends AgentEventSchemaInputMap> = Omit<T, typeof AGENT_USAGE_EVENT_TYPE> & {
|
|
279
|
+
[AGENT_USAGE_EVENT_TYPE]: StandardSchemaV1<AgentUsageEventPayload>;
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Builds a machine's {@link AgentSchemaPack} from a partial schema
|
|
283
|
+
* declaration — only `context` is required; `events`/`input`/`output`/`meta`
|
|
284
|
+
* default to empty/unknown schemas when omitted. Pass the result as
|
|
285
|
+
* `setupAgent({ schemas })`'s `schemas` (or spread the individual fields
|
|
286
|
+
* directly into `setupAgent({ context, events, ... })` — both forms are
|
|
287
|
+
* accepted).
|
|
288
|
+
*/
|
|
289
|
+
declare function createAgentSchemas<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap = {}, TInputSchema extends StandardSchemaV1 = StandardSchemaV1<NonReducibleUnknown>, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1<NonReducibleUnknown>, TMetaSchema extends StandardSchemaV1 = StandardSchemaV1<MetaObject>, TEmittedSchemas extends Record<string, StandardSchemaV1> = {}>(schemas: AgentSchemaConfig<TContextSchema, TEventSchemas, TInputSchema, TOutputSchema, TMetaSchema, TEmittedSchemas>): AgentSchemaPack<TContextSchema, WithAgentUsageEvent<TEventSchemas>, TInputSchema, TOutputSchema, TMetaSchema, TEmittedSchemas>;
|
|
290
|
+
type AgentRequestSchemaMap = Record<string, {
|
|
291
|
+
input?: StandardSchemaV1;
|
|
292
|
+
output?: StandardSchemaV1;
|
|
293
|
+
}>;
|
|
294
|
+
type ResolvedRequestSchema<TSchema, TFallback> = [NonNullable<TSchema>] extends [never] ? TFallback : [NonNullable<TSchema>] extends [StandardSchemaV1] ? NonNullable<TSchema> : TFallback;
|
|
295
|
+
type RequestInputSchema<TSchemas extends {
|
|
296
|
+
input?: StandardSchemaV1;
|
|
297
|
+
}> = ResolvedRequestSchema<TSchemas["input"], StandardSchemaV1<undefined>>;
|
|
298
|
+
type RequestOutputSchema<TSchemas extends {
|
|
299
|
+
output?: StandardSchemaV1;
|
|
300
|
+
}> = ResolvedRequestSchema<TSchemas["output"], StandardSchemaV1<string>>;
|
|
301
|
+
type AgentRequestInput<TRequestSchemas extends AgentRequestSchemaMap, TModel extends string = string> = { [K in keyof TRequestSchemas]: Omit<TextLogicConfig<RequestInputSchema<TRequestSchemas[K]>, RequestOutputSchema<TRequestSchemas[K]>, Record<string, unknown>, TModel>, "schemas"> & {
|
|
302
|
+
schemas: TRequestSchemas[K];
|
|
303
|
+
} };
|
|
304
|
+
type RequestActors<TRequestSchemas extends AgentRequestSchemaMap> = { [K in keyof TRequestSchemas]: TextLogic<RequestInputSchema<TRequestSchemas[K]>, RequestOutputSchema<TRequestSchemas[K]>> };
|
|
305
|
+
type AgentAllActors<TActors extends { [K in keyof TActors]: AnyActorLogic }, TRequestSchemas extends AgentRequestSchemaMap> = TActors & RequestActors<TRequestSchemas>;
|
|
306
|
+
type AgentSetupEventsSchema<TEventSchemas extends AgentEventSchemaInputMap> = {
|
|
307
|
+
events: NormalizedEventSchemas<WithAgentUsageEvent<TEventSchemas>>;
|
|
308
|
+
};
|
|
309
|
+
type AgentSetupEmittedSchema<TEmittedSchemas extends Record<string, StandardSchemaV1>> = [keyof TEmittedSchemas] extends [never] ? {} : {
|
|
310
|
+
emitted: TEmittedSchemas;
|
|
311
|
+
};
|
|
312
|
+
type AgentSetupXStateConfig<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap, TActors extends { [K in keyof TActors]: AnyActorLogic }, TRequestSchemas extends AgentRequestSchemaMap, TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetaSchema extends StandardSchemaV1, TModels extends AgentModelMap, TEmittedSchemas extends Record<string, StandardSchemaV1> = {}, TStateSchemas extends Record<string, SetupStateSchema> = Record<string, SetupStateSchema>> = {
|
|
313
|
+
schemas: {
|
|
314
|
+
context: TContextSchema;
|
|
315
|
+
input: TInputSchema;
|
|
316
|
+
output: TOutputSchema;
|
|
317
|
+
meta: TMetaSchema;
|
|
318
|
+
} & AgentSetupEventsSchema<TEventSchemas> & AgentSetupEmittedSchema<TEmittedSchemas>;
|
|
319
|
+
states?: TStateSchemas;
|
|
320
|
+
actors: SetupActors<AgentSetupActors<AgentAllActors<TActors, TRequestSchemas>, Exclude<keyof TEventSchemas & string, typeof AGENT_USAGE_EVENT_TYPE>, AgentModelRef<TModels>>>;
|
|
321
|
+
actions?: NonNullable<AnySetupConfig["actions"]>;
|
|
322
|
+
guards?: NonNullable<AnySetupConfig["guards"]>;
|
|
323
|
+
delays?: NonNullable<AnySetupConfig["delays"]>;
|
|
324
|
+
};
|
|
325
|
+
/**
|
|
326
|
+
* Field-level context-narrowing sugar for one `setupAgent({ states })` entry:
|
|
327
|
+
* each `context` entry overrides that field's schema inside the state; every
|
|
328
|
+
* other field keeps the base context schema. Sugar for the full xstate form —
|
|
329
|
+
* `{ context: { draft: z.string() } }` resolves to
|
|
330
|
+
* `{ schemas: { context: <base with draft: string> } }` — so only the fields
|
|
331
|
+
* that change are declared, not the whole context schema.
|
|
332
|
+
*/
|
|
333
|
+
interface AgentStateNarrowing {
|
|
334
|
+
context: Record<string, StandardSchemaV1>;
|
|
335
|
+
states?: Record<string, AgentSetupStateSchema>;
|
|
336
|
+
}
|
|
337
|
+
/** One `setupAgent({ states })` entry: xstate's {@link SetupStateSchema} full form, or the {@link AgentStateNarrowing} field-level sugar. */
|
|
338
|
+
type AgentSetupStateSchema = SetupStateSchema | AgentStateNarrowing;
|
|
339
|
+
type NarrowedContext<TContextSchema extends StandardSchemaV1, TFields extends Record<string, StandardSchemaV1>> = Omit<InferOutput<TContextSchema>, keyof TFields> & { [K in keyof TFields]: InferOutput<TFields[K]> };
|
|
340
|
+
type ResolveAgentStateSchema<TContextSchema extends StandardSchemaV1, T> = T extends {
|
|
341
|
+
context: infer TFields extends Record<string, StandardSchemaV1>;
|
|
342
|
+
} ? {
|
|
343
|
+
schemas: {
|
|
344
|
+
context: StandardSchemaV1<NarrowedContext<TContextSchema, TFields>>;
|
|
345
|
+
};
|
|
346
|
+
} & (T extends {
|
|
347
|
+
states: infer TChildren extends Record<string, AgentSetupStateSchema>;
|
|
348
|
+
} ? {
|
|
349
|
+
states: ResolveAgentStateSchemas<TContextSchema, TChildren>;
|
|
350
|
+
} : {}) : T extends {
|
|
351
|
+
states: infer TChildren extends Record<string, AgentSetupStateSchema>;
|
|
352
|
+
} ? Omit<T, "states"> & {
|
|
353
|
+
states: ResolveAgentStateSchemas<TContextSchema, TChildren>;
|
|
354
|
+
} : T;
|
|
355
|
+
type ResolveAgentStateSchemas<TContextSchema extends StandardSchemaV1, TStates extends Record<string, AgentSetupStateSchema>> = Constrain<{ [K in keyof TStates]: ResolveAgentStateSchema<TContextSchema, TStates[K]> }, Record<string, SetupStateSchema>>;
|
|
356
|
+
type SetupAgentBaseConfig<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap, TActors extends { [K in keyof TActors]: AnyActorLogic }, TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetaSchema extends StandardSchemaV1, TRequestSchemas extends AgentRequestSchemaMap, TModels extends AgentModelMap, TEmittedSchemas extends Record<string, StandardSchemaV1> = {}, TStateSchemas extends Record<string, AgentSetupStateSchema> = Record<string, AgentSetupStateSchema>> = ({
|
|
357
|
+
schemas: AgentSchemaPack<TContextSchema, TEventSchemas, TInputSchema, TOutputSchema, TMetaSchema, TEmittedSchemas>;
|
|
358
|
+
} | AgentSchemaConfig<TContextSchema, TEventSchemas, TInputSchema, TOutputSchema, TMetaSchema, TEmittedSchemas>) & {
|
|
359
|
+
models?: TModels;
|
|
360
|
+
actors?: TActors;
|
|
361
|
+
/**
|
|
362
|
+
* Per-state schemas, mirroring xstate's `setup({ states })`: narrow
|
|
363
|
+
* `context` inside a state (invoke `input`, transition fns, final `output`)
|
|
364
|
+
* — e.g. mark a field non-null in states only reachable after it is set.
|
|
365
|
+
* Two forms per state: the {@link AgentStateNarrowing} sugar
|
|
366
|
+
* (`{ context: { draft: z.string() } }` — only the fields that change) or
|
|
367
|
+
* xstate's full `{ schemas: { context } }` with a complete context schema.
|
|
368
|
+
*/
|
|
369
|
+
states?: TStateSchemas;
|
|
370
|
+
requests?: AgentRequestInput<TRequestSchemas, AgentModelRef<TModels>>;
|
|
371
|
+
actions?: NonNullable<AnySetupConfig["actions"]>;
|
|
372
|
+
guards?: NonNullable<AnySetupConfig["guards"]>;
|
|
373
|
+
delays?: NonNullable<AnySetupConfig["delays"]>;
|
|
374
|
+
/**
|
|
375
|
+
* Detects a snapshot that is an INTENTIONAL wait for an external event (a
|
|
376
|
+
* human approval, an inbound webhook, …) — the machine's own declaration of
|
|
377
|
+
* what "suspended" means for it, so `runAgent` settles those snapshots idle
|
|
378
|
+
* deterministically instead of using its timing heuristic. Travels with the
|
|
379
|
+
* machine through `machine.provide(...)`. A `runAgent({ isSuspended })` host
|
|
380
|
+
* override takes precedence; with neither, `runAgent` falls back to the timing
|
|
381
|
+
* heuristic. Declare your own signal — e.g. `(s) => s.hasTag('awaiting-review')`
|
|
382
|
+
* or `(s) => getStateMeta(s).interaction !== undefined`.
|
|
383
|
+
*/
|
|
384
|
+
isSuspended?: (snapshot: AnyMachineSnapshot) => boolean;
|
|
385
|
+
};
|
|
386
|
+
type SetupAgentXStateResult<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap, TActors extends { [K in keyof TActors]: AnyActorLogic }, TRequestSchemas extends AgentRequestSchemaMap, TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetaSchema extends StandardSchemaV1, TModels extends AgentModelMap, TEmittedSchemas extends Record<string, StandardSchemaV1> = {}, TStateSchemas extends Record<string, AgentSetupStateSchema> = Record<string, AgentSetupStateSchema>> = SetupReturnFromConfig<AgentSetupXStateConfig<TContextSchema, TEventSchemas, TActors, TRequestSchemas, TInputSchema, TOutputSchema, TMetaSchema, TModels, TEmittedSchemas, ResolveAgentStateSchemas<TContextSchema, TStateSchemas>>>;
|
|
387
|
+
/**
|
|
388
|
+
* The object returned by {@link setupAgent}: an xstate `setup(...)` result
|
|
389
|
+
* (`createMachine`, `assign`, …) extended with `schemas` (the resolved
|
|
390
|
+
* {@link AgentSchemaPack}), `models`, `requests` (the built request actors),
|
|
391
|
+
* and {@link appendMessages}. Machines created here are registered so
|
|
392
|
+
* `runAgent` and the free step helpers can resolve their schemas/actors
|
|
393
|
+
* without re-passing them each call.
|
|
394
|
+
*/
|
|
395
|
+
type SetupAgentResult<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap, TActors extends { [K in keyof TActors]: AnyActorLogic }, TRequestSchemas extends AgentRequestSchemaMap, TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetaSchema extends StandardSchemaV1, TModels extends AgentModelMap, TEmittedSchemas extends Record<string, StandardSchemaV1> = {}, TStateSchemas extends Record<string, AgentSetupStateSchema> = Record<string, AgentSetupStateSchema>> = Omit<SetupAgentXStateResult<TContextSchema, TEventSchemas, TActors, TRequestSchemas, TInputSchema, TOutputSchema, TMetaSchema, TModels, TEmittedSchemas, TStateSchemas>, "createMachine"> & {
|
|
396
|
+
/**
|
|
397
|
+
* Creates the agent machine — XState's own `createMachine`, plus: the
|
|
398
|
+
* machine is registered so step helpers and {@link runAgent} can resolve
|
|
399
|
+
* its schemas/actors without re-passing them, and a single final state's
|
|
400
|
+
* `output` is copied to the machine root when the root declares none.
|
|
401
|
+
*/
|
|
402
|
+
createMachine: SetupAgentXStateResult<TContextSchema, TEventSchemas, TActors, TRequestSchemas, TInputSchema, TOutputSchema, TMetaSchema, TModels, TEmittedSchemas, TStateSchemas>["createMachine"]; /** The retained schema pack ({@link AgentSchemaPack}) for host-side validation and tooling. Its `events` include the reserved `'@agent.usage'` entry setupAgent registers by default. */
|
|
403
|
+
schemas: AgentSchemaPack<TContextSchema, WithAgentUsageEvent<TEventSchemas>, TInputSchema, TOutputSchema, TMetaSchema, TEmittedSchemas>; /** The `models` registry passed to `setupAgent(...)`, if any (used to type-narrow `AgentModelRef`). */
|
|
404
|
+
readonly models: TModels; /** The {@link TextLogic} actors built from `setupAgent({ requests })`, keyed the same way. */
|
|
405
|
+
readonly requests: RequestActors<TRequestSchemas>; /** {@link appendMessages}, typed against this agent's context/event schemas. */
|
|
406
|
+
appendMessages(resolve: AgentMessage | AgentMessage[] | ((args: {
|
|
407
|
+
context: ContextOf<TContextSchema> & {
|
|
408
|
+
messages: AgentMessage[];
|
|
409
|
+
};
|
|
410
|
+
event: any;
|
|
411
|
+
}) => AgentMessage | AgentMessage[])): ReturnType<typeof appendMessages<ContextOf<TContextSchema> & {
|
|
412
|
+
messages: AgentMessage[];
|
|
413
|
+
}, EventsOf<WithAgentUsageEvent<TEventSchemas>>>>;
|
|
414
|
+
};
|
|
415
|
+
/**
|
|
416
|
+
* Schema-first `setup(...)` for agent machines — the standard entry point
|
|
417
|
+
* for authoring a machine (the blueprint) that this library then runs (via
|
|
418
|
+
* {@link runAgent} or the step helpers) against host-supplied model/decision
|
|
419
|
+
* executors. Context, events, machine input, machine output, and
|
|
420
|
+
* state/transition meta are all standard schemas — no `{} as Type` casts —
|
|
421
|
+
* and are retained on `result.schemas` for runtime validation. Also
|
|
422
|
+
* registers the `agent.generateText`/`agent.streamText`/`agent.userInput`/
|
|
423
|
+
* `agent.decide`/`agent.plan` builtin actors and lowers `requests`/`actors` into the
|
|
424
|
+
* machine's actor sources. The result is the xstate `setup(...)` object with
|
|
425
|
+
* a wrapped `result.createMachine(...)` plus `result.schemas`/`models`/
|
|
426
|
+
* `requests`/`appendMessages` attached. Also has a
|
|
427
|
+
* `setupAgent.fromConfig(...)` namespace member for building a machine from
|
|
428
|
+
* a serializable {@link AgentWorkflowConfig} instead of this TS API.
|
|
429
|
+
*
|
|
430
|
+
* @example
|
|
431
|
+
* ```ts
|
|
432
|
+
* const schemas = createAgentSchemas({
|
|
433
|
+
* context: z.object({ topic: z.string(), joke: z.string().nullable() }),
|
|
434
|
+
* input: z.object({ topic: z.string() }),
|
|
435
|
+
* output: z.object({ joke: z.string() }),
|
|
436
|
+
* });
|
|
437
|
+
*
|
|
438
|
+
* const agent = setupAgent({
|
|
439
|
+
* schemas,
|
|
440
|
+
* actors: { tellJoke },
|
|
441
|
+
* });
|
|
442
|
+
*
|
|
443
|
+
* const jokeMachine = agent.createMachine({
|
|
444
|
+
* context: ({ input }) => ({ topic: input.topic, joke: null }),
|
|
445
|
+
* initial: 'telling',
|
|
446
|
+
* states: {
|
|
447
|
+
* telling: {
|
|
448
|
+
* invoke: {
|
|
449
|
+
* id: 'joke',
|
|
450
|
+
* src: 'tellJoke',
|
|
451
|
+
* input: ({ context }) => ({ topic: context.topic }),
|
|
452
|
+
* onDone: ({ output }) => ({ target: 'done', context: { joke: output } }),
|
|
453
|
+
* },
|
|
454
|
+
* },
|
|
455
|
+
* done: { type: 'final', output: ({ context }) => ({ joke: context.joke ?? '' }) },
|
|
456
|
+
* },
|
|
457
|
+
* });
|
|
458
|
+
* ```
|
|
459
|
+
*/
|
|
460
|
+
declare function setupAgent<TContextSchema extends StandardSchemaV1<Record<string, unknown>>, TEventSchemas extends AgentEventSchemaInputMap, TActors extends { [K in keyof TActors]: AnyActorLogic }, TRequestSchemas extends AgentRequestSchemaMap = {}, TInputSchema extends StandardSchemaV1 = StandardSchemaV1<NonReducibleUnknown>, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1<NonReducibleUnknown>, TMetaSchema extends StandardSchemaV1 = StandardSchemaV1<MetaObject>, TModels extends AgentModelMap = {}, TEmittedSchemas extends Record<string, StandardSchemaV1> = {}, const TStateSchemas extends Record<string, AgentSetupStateSchema> = Record<string, AgentSetupStateSchema>>(config: SetupAgentBaseConfig<TContextSchema, TEventSchemas, TActors, TInputSchema, TOutputSchema, TMetaSchema, TRequestSchemas, TModels, TEmittedSchemas, TStateSchemas>): SetupAgentResult<TContextSchema, TEventSchemas, TActors, TRequestSchemas, TInputSchema, TOutputSchema, TMetaSchema, TModels, TEmittedSchemas, TStateSchemas>;
|
|
461
|
+
declare namespace setupAgent {
|
|
462
|
+
/**
|
|
463
|
+
* Builds a state machine from a serializable {@link AgentWorkflowConfig}
|
|
464
|
+
* (JSON/YAML) instead of the TypeScript `setupAgent(...)` API — the same
|
|
465
|
+
* kind of machine a database, visual editor, or LLM could produce and hand
|
|
466
|
+
* back. Requires a `compileSchema` (see {@link FromConfigOptions}) since
|
|
467
|
+
* the library bundles no JSON Schema engine itself; bring Ajv,
|
|
468
|
+
* @cfworker/json-schema, or another compiler that returns Standard Schema.
|
|
469
|
+
*
|
|
470
|
+
* Returns the built `machine` plus the compiled `schemas` pack (context,
|
|
471
|
+
* events, input, output, meta, emitted) — a JSON-authored agent has no
|
|
472
|
+
* TypeScript types, so hosts need the runtime schemas for things like
|
|
473
|
+
* validating an inbound raw event with `parseAgentEvent`.
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```ts
|
|
477
|
+
* const { machine, schemas } = setupAgent.fromConfig(workflowConfig, {
|
|
478
|
+
* compileSchema,
|
|
479
|
+
* });
|
|
480
|
+
* const result = await runAgent(machine, { input: { ticket }, executors: { generateText, decide } });
|
|
481
|
+
* const event = parseAgentEvent(result.snapshot, raw, { events: schemas.events });
|
|
482
|
+
* ```
|
|
483
|
+
*/
|
|
484
|
+
function fromConfig(config: AgentWorkflowConfig, options: FromConfigOptions): FromConfigResult;
|
|
485
|
+
}
|
|
486
|
+
//#endregion
|
|
487
|
+
//#region src/agent-run.d.ts
|
|
488
|
+
/**
|
|
489
|
+
* A live handle over a single {@link runAgent} call: its trace events as an
|
|
490
|
+
* async stream, plus the same result promise `runAgent` returns.
|
|
491
|
+
*
|
|
492
|
+
* Build it with {@link createAgentRun}. Use `events` for a pull-based feed
|
|
493
|
+
* (SSE, a JSONL logger, a progress UI) and `result` for the final outcome —
|
|
494
|
+
* either, both, or neither; nothing about consuming one is required to consume
|
|
495
|
+
* the other.
|
|
496
|
+
*/
|
|
497
|
+
interface AgentRun<TMachine extends AnyStateMachine = AnyStateMachine> {
|
|
498
|
+
/**
|
|
499
|
+
* Single-consumer async stream of the run's trace events, in `runAgent`'s
|
|
500
|
+
* emission order (`run.start` → request/chunk/transition/emit events →
|
|
501
|
+
* `run.end`). Completes right after `run.end` is delivered. Events are
|
|
502
|
+
* buffered unboundedly, so a slow or absent consumer never blocks the run
|
|
503
|
+
* (see {@link createAgentRun}). Single-consumer: a second `for await` over the
|
|
504
|
+
* same iterator picks up only the events not yet pulled — it is one shared
|
|
505
|
+
* cursor, not a fresh replay.
|
|
506
|
+
*/
|
|
507
|
+
events: AsyncIterableIterator<AgentTraceEvent<TMachine>>;
|
|
508
|
+
/**
|
|
509
|
+
* Settles exactly like {@link runAgent}'s return value: resolves with the
|
|
510
|
+
* `done | idle | error` {@link RunAgentResult}, and rejects only where
|
|
511
|
+
* `runAgent` itself rejects (bind-time programmer errors — a missing
|
|
512
|
+
* executor, an illegal resume event, a version mismatch). A run-level failure
|
|
513
|
+
* still resolves with `{ status: 'error' }`, never rejects.
|
|
514
|
+
*/
|
|
515
|
+
result: Promise<RunAgentResult<TMachine>>;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Wraps {@link runAgent} in a canonical run-stream handle: the run's trace
|
|
519
|
+
* events as a pull-based {@link AgentRun.events} async iterator, alongside the
|
|
520
|
+
* unchanged {@link AgentRun.result} promise.
|
|
521
|
+
*
|
|
522
|
+
* Semantics:
|
|
523
|
+
*
|
|
524
|
+
* 1. **Starts immediately.** The underlying `runAgent` is invoked on this call,
|
|
525
|
+
* not on the first `events` iteration — work is already in flight when
|
|
526
|
+
* `createAgentRun` returns.
|
|
527
|
+
* 2. **Buffer, don't stall.** Events are queued in an unbounded in-memory
|
|
528
|
+
* buffer as the run emits them; a slow or absent consumer never applies
|
|
529
|
+
* backpressure to the run. Once `run.end` is delivered, the iterator
|
|
530
|
+
* completes.
|
|
531
|
+
* 3. **Composes `onTrace`.** If `options.onTrace` is passed, it still fires for
|
|
532
|
+
* every event — the wrapper adds queue delivery, it does not replace the
|
|
533
|
+
* caller's sink.
|
|
534
|
+
* 4. **`result` mirrors `runAgent`.** Same resolution and rejection behavior
|
|
535
|
+
* (see {@link AgentRun.result}). A no-op rejection handler is attached
|
|
536
|
+
* internally so a caller who reads only `events` never trips an unhandled
|
|
537
|
+
* rejection on a bind-time throw; the returned promise still rejects for a
|
|
538
|
+
* caller who awaits it.
|
|
539
|
+
* 5. **Resume is identical.** Options pass straight through, so starting from a
|
|
540
|
+
* persisted `snapshot` (+ resume `event`) streams that run's events from its
|
|
541
|
+
* own `run.start`, exactly as `runAgent` would run it.
|
|
542
|
+
* 6. **Early termination does not cancel the run.** Breaking out of a
|
|
543
|
+
* `for await` (or calling `events.return()`) stops delivery, but the run
|
|
544
|
+
* keeps going and `result` still settles. Cancelling the run itself is
|
|
545
|
+
* future work — pass `options.signal` to abort it.
|
|
546
|
+
* 7. **`events` is single-consumer.** See {@link AgentRun.events}.
|
|
547
|
+
*/
|
|
548
|
+
declare function createAgentRun<TMachine extends AnyStateMachine>(machine: TMachine, options: RunAgentOptions<TMachine>): AgentRun<TMachine>;
|
|
549
|
+
//#endregion
|
|
550
|
+
//#region src/provide-executors.d.ts
|
|
551
|
+
/** Options for {@link provideExecutors}. */
|
|
552
|
+
interface ProvideExecutorsOptions<TMachine extends AnyStateMachine = AnyStateMachine> {
|
|
553
|
+
/**
|
|
554
|
+
* Extra actor-source overrides merged onto the machine BEFORE binding — the
|
|
555
|
+
* same shape as `machine.provide({ actors })`. Use it to supply the
|
|
556
|
+
* `agent.userInput` handler, a custom non-agent actor, or to shadow an agent
|
|
557
|
+
* source with your own executor-bound logic. Merged first, so an override
|
|
558
|
+
* that already carries its own executor is left untouched by the binding pass.
|
|
559
|
+
*/
|
|
560
|
+
actors?: Record<string, AnyActorLogic>;
|
|
561
|
+
/** Chunk sink threaded to every bound `mode: 'stream'` text source. */
|
|
562
|
+
onChunk?: (chunk: string) => void;
|
|
563
|
+
/**
|
|
564
|
+
* A single ordered stream of request-level trace events
|
|
565
|
+
* (`request.start`/`request.end`/`request.error`/`stream.chunk`) with the
|
|
566
|
+
* SAME versioned envelope {@link runAgent} emits. Because one bound machine can
|
|
567
|
+
* back many concurrent root actors, envelope state (`runId`, monotonic `seq`)
|
|
568
|
+
* is minted per ROOT actor at runtime — two concurrent actors get distinct
|
|
569
|
+
* `runId`s and independent `seq`. Pair with {@link traceTransitions} on the
|
|
570
|
+
* actor's `inspect` to fold `machine.transition` events into the same stream.
|
|
571
|
+
* Unlike `runAgent` there are NO `run.start`/`run.end` events (no run
|
|
572
|
+
* boundary).
|
|
573
|
+
*/
|
|
574
|
+
onTrace?: (event: AgentTraceEvent<TMachine>) => void;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Binds a machine's agent actor sources to a set of host `executors` in one
|
|
578
|
+
* call, returning a `machine.provide(...)`-ed copy ready for a plain
|
|
579
|
+
* `createActor(...)` — the uncontrolled-mode counterpart to {@link runAgent}.
|
|
580
|
+
* No run loop, no idle settling: the returned machine drives itself, so
|
|
581
|
+
*
|
|
582
|
+
* ```ts
|
|
583
|
+
* const actor = createActor(provideExecutors(machine, { generateText, decide }), { input });
|
|
584
|
+
* actor.start();
|
|
585
|
+
* ```
|
|
586
|
+
*
|
|
587
|
+
* behaves like a normal XState actor whose agent invokes now reach real models.
|
|
588
|
+
*
|
|
589
|
+
* Binding pass over `machine.sources.actors` (after merging
|
|
590
|
+
* `options.actors`):
|
|
591
|
+
* - `mode: 'generate'` text source → `executors.generateText`
|
|
592
|
+
* - `mode: 'stream'` text source → `executors.streamText`
|
|
593
|
+
* - decision / `agent.decide` source → `executors.decide` (snapshot-driven
|
|
594
|
+
* candidate events, guard `canTake`, and auto-delivery of the chosen event,
|
|
595
|
+
* mirroring `runAgent` but without its model-call counting)
|
|
596
|
+
* - `agent.plan` source → `executors.decide` (iterated, same semantics)
|
|
597
|
+
*
|
|
598
|
+
* Pass `options.onTrace` to observe request-level trace events (identical in
|
|
599
|
+
* shape to `runAgent`'s); pair it with {@link traceTransitions} on the actor's
|
|
600
|
+
* `inspect` to also capture `machine.transition` events in the same stream.
|
|
601
|
+
*
|
|
602
|
+
* A source that already carries its own executor (`.withExecutor(...)`) is left
|
|
603
|
+
* as-is. `agent.userInput` is left UNBOUND — an uncontrolled host handles idle
|
|
604
|
+
* itself, so supply a handler via `options.actors` if the machine uses it.
|
|
605
|
+
* Non-agent actors are untouched.
|
|
606
|
+
*
|
|
607
|
+
* Throws at bind time if a source needs an executor kind that `executors` does
|
|
608
|
+
* not provide.
|
|
609
|
+
*
|
|
610
|
+
* v1 does NOT descend into invoked child state machines: a string-keyed child
|
|
611
|
+
* machine source is left untouched, so a child with its own agent invokes needs
|
|
612
|
+
* its own `provideExecutors(...)` (or `runAgent`, which does rebind children).
|
|
613
|
+
*/
|
|
614
|
+
declare function provideExecutors<TMachine extends AnyStateMachine>(machine: TMachine, executors: AgentRequestExecutors, options?: ProvideExecutorsOptions<TMachine>): TMachine;
|
|
615
|
+
//#endregion
|
|
7
616
|
//#region src/verify.d.ts
|
|
8
617
|
/** Severity of an {@link AgentLintDiagnostic}. `error` findings fail CI/the CLI; `warning`s are advisory. */
|
|
9
618
|
type AgentLintSeverity = "error" | "warning";
|
|
@@ -13,7 +622,7 @@ type AgentLintSeverity = "error" | "warning";
|
|
|
13
622
|
* or config location, and `message` explains the problem and its remedy.
|
|
14
623
|
*/
|
|
15
624
|
interface AgentLintDiagnostic {
|
|
16
|
-
code: "unreachable-state" | "decide-without-events" | "unserializable-context" | "direct-object-src" | "final-without-output" | "final-output-reads-event" | "missing-final";
|
|
625
|
+
code: "unreachable-state" | "decide-without-events" | "unserializable-context" | "direct-object-src" | "final-without-output" | "final-output-reads-event" | "undeclared-event" | "missing-final";
|
|
17
626
|
severity: AgentLintSeverity;
|
|
18
627
|
/** State path (`parent.child`) or config pointer (e.g. `(root)`, `context`) the finding is about. */
|
|
19
628
|
path: string;
|
|
@@ -52,8 +661,8 @@ interface AssertAgentMachineOptions extends LintAgentMachineOptions {
|
|
|
52
661
|
* `diagnostics` holds the findings; the message lists them one per finding,
|
|
53
662
|
* so a test runner's failure output reads like the CLI's lint report.
|
|
54
663
|
*/
|
|
55
|
-
declare class AgentLintError extends
|
|
56
|
-
diagnostics: AgentLintDiagnostic[];
|
|
664
|
+
declare class AgentLintError extends AgentError {
|
|
665
|
+
readonly diagnostics: AgentLintDiagnostic[];
|
|
57
666
|
constructor(machineId: string, diagnostics: AgentLintDiagnostic[]);
|
|
58
667
|
}
|
|
59
668
|
/**
|
|
@@ -78,13 +687,13 @@ declare function assertAgentMachine(machine: AnyStateMachine, options?: AssertAg
|
|
|
78
687
|
* `setupAgent({ requests })` key, or `agent.generateText`/`agent.streamText`).
|
|
79
688
|
* - `decisions` — the {@link ChosenEvent} to apply for a decision request,
|
|
80
689
|
* keyed by decision src (usually `agent.decide`).
|
|
81
|
-
* - `
|
|
82
|
-
*
|
|
690
|
+
* - `invokes` — output values for scripted invokes (notably `agent.userInput`,
|
|
691
|
+
* and any other actor whose output must be canned), keyed by src.
|
|
83
692
|
*/
|
|
84
693
|
interface SimulationScript {
|
|
85
694
|
text?: Record<string, unknown[]>;
|
|
86
695
|
decisions?: Record<string, ChosenEvent[]>;
|
|
87
|
-
|
|
696
|
+
invokes?: Record<string, unknown[]>;
|
|
88
697
|
}
|
|
89
698
|
/** One entry in a {@link SimulateAgentResult.trail}: the state after this step, plus what drove the step. */
|
|
90
699
|
interface SimulationTrailEntry {
|
|
@@ -209,4 +818,388 @@ interface CanReachResult {
|
|
|
209
818
|
*/
|
|
210
819
|
declare function canReach(machine: AnyStateMachine, statePath: string, options?: ExplorePathsOptions): Promise<CanReachResult>;
|
|
211
820
|
//#endregion
|
|
212
|
-
|
|
821
|
+
//#region src/trajectory.d.ts
|
|
822
|
+
/** An event-shaped trajectory item: anything with a string `type`. */
|
|
823
|
+
interface TrajectoryEvent {
|
|
824
|
+
type: string;
|
|
825
|
+
[key: string]: unknown;
|
|
826
|
+
}
|
|
827
|
+
/**
|
|
828
|
+
* One item in a trajectory, on either side of the comparison:
|
|
829
|
+
*
|
|
830
|
+
* - a state value — `'drafting'`, a dot path `'review.editing'`, or the nested
|
|
831
|
+
* object XState reports (`{ review: 'editing' }`),
|
|
832
|
+
* - an event — an {@link AgentLogEntry} from `result.events`, a bare event
|
|
833
|
+
* object, or just the event type as a string,
|
|
834
|
+
* - a machine snapshot, whose `value` is used.
|
|
835
|
+
*/
|
|
836
|
+
type TrajectoryItem = StateValue | AgentLogEntry | TrajectoryEvent | {
|
|
837
|
+
value: StateValue;
|
|
838
|
+
};
|
|
839
|
+
/** Options for {@link matchesTrajectory}. */
|
|
840
|
+
interface MatchTrajectoryOptions {
|
|
841
|
+
/**
|
|
842
|
+
* Require the trajectories to be equal: same length, item for item. Default
|
|
843
|
+
* `false` — expected items must appear in `actual` in order, gaps allowed.
|
|
844
|
+
*/
|
|
845
|
+
exact?: boolean;
|
|
846
|
+
}
|
|
847
|
+
/** The first expected item that could not be found. */
|
|
848
|
+
interface TrajectoryMiss {
|
|
849
|
+
/** Its position in `expected`. */
|
|
850
|
+
index: number;
|
|
851
|
+
/** The expected item itself. */
|
|
852
|
+
expected: TrajectoryItem;
|
|
853
|
+
/** Where the search for it started in `actual` (everything before was already consumed). */
|
|
854
|
+
searchedFrom: number;
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* The result of {@link matchesTrajectory}: a boolean for tests, plus enough
|
|
858
|
+
* detail for a scorer's partial credit and a failure message's diagnosis.
|
|
859
|
+
*/
|
|
860
|
+
interface TrajectoryMatch {
|
|
861
|
+
/** Every expected item was found, in order (and, in `exact` mode, nothing else). */
|
|
862
|
+
matched: boolean;
|
|
863
|
+
/** How many expected items were matched before the first miss. */
|
|
864
|
+
matchedCount: number;
|
|
865
|
+
/** `expected.length`, so a scorer can compute its own ratio. */
|
|
866
|
+
expectedCount: number;
|
|
867
|
+
/** Partial credit, 0..1. `1` for an empty expectation. */
|
|
868
|
+
score: number;
|
|
869
|
+
/** Absent when `matched`. */
|
|
870
|
+
firstMiss?: TrajectoryMiss;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Matches a run's trajectory against an expected one.
|
|
874
|
+
*
|
|
875
|
+
* Both trajectories may be state values (collected from `onTransition`) or
|
|
876
|
+
* events (`result.events`, whose {@link AgentLogEntry} envelopes are unwrapped);
|
|
877
|
+
* items are compared by shape, so `['prompting', 'drafting']` scores a state
|
|
878
|
+
* path and `['PROMPT_SUBMITTED', 'SEND']` scores an event log with the same
|
|
879
|
+
* call.
|
|
880
|
+
*
|
|
881
|
+
* Semantics are an ordered subsequence: every expected item must appear in
|
|
882
|
+
* `actual`, in order, with gaps allowed. Pass `{ exact: true }` to require
|
|
883
|
+
* equality instead.
|
|
884
|
+
*
|
|
885
|
+
* @example Trajectory assertions in a test
|
|
886
|
+
* ```ts
|
|
887
|
+
* const statePath: unknown[] = [];
|
|
888
|
+
* const result = await runAgent(machine, {
|
|
889
|
+
* input,
|
|
890
|
+
* executors,
|
|
891
|
+
* onTransition: (snapshot) => statePath.push(snapshot.value),
|
|
892
|
+
* });
|
|
893
|
+
*
|
|
894
|
+
* const path = matchesTrajectory(statePath, ['prompting', 'drafting', 'sent']);
|
|
895
|
+
* expect(path.matched, JSON.stringify(path.firstMiss)).toBe(true);
|
|
896
|
+
* expect(matchesTrajectory(result.events, ['PROMPT_SUBMITTED', 'SEND']).matched).toBe(true);
|
|
897
|
+
* ```
|
|
898
|
+
*
|
|
899
|
+
* @example Partial credit in an eval scorer
|
|
900
|
+
* ```ts
|
|
901
|
+
* const match = matchesTrajectory(output.statePath, expected.statePath);
|
|
902
|
+
* return { name: 'state_path', score: match.score, metadata: { ...match.firstMiss } };
|
|
903
|
+
* ```
|
|
904
|
+
*/
|
|
905
|
+
declare function matchesTrajectory(actual: readonly unknown[], expected: readonly TrajectoryItem[], options?: MatchTrajectoryOptions): TrajectoryMatch;
|
|
906
|
+
//#endregion
|
|
907
|
+
//#region src/scripted-executors.d.ts
|
|
908
|
+
/**
|
|
909
|
+
* A scripted `decide` answer: either the {@link ChosenEvent} itself (an object
|
|
910
|
+
* with a string `type`), or the executor envelope `{ event, reason?, usage? }`
|
|
911
|
+
* when the entry also reports a `reason` or token `usage`.
|
|
912
|
+
*/
|
|
913
|
+
type ScriptedDecisionValue = ChosenEvent | {
|
|
914
|
+
event: ChosenEvent;
|
|
915
|
+
reason?: string;
|
|
916
|
+
usage?: AgentCallUsage;
|
|
917
|
+
[key: string]: unknown;
|
|
918
|
+
};
|
|
919
|
+
/**
|
|
920
|
+
* One entry in the `decisions` queue: a scripted answer, or a function of the
|
|
921
|
+
* {@link AgentDecisionRequest} returning one (for choices that depend on the
|
|
922
|
+
* prompt, the candidate `events`, or the prior failed `attempts`).
|
|
923
|
+
*/
|
|
924
|
+
type ScriptedDecisionEntry = ScriptedDecisionValue | ((request: AgentDecisionRequest) => ScriptedDecisionValue | PromiseLike<ScriptedDecisionValue>);
|
|
925
|
+
/**
|
|
926
|
+
* One entry in the `text` queue: the request's output value (a string, or the
|
|
927
|
+
* object a structured request declares), or a function of the
|
|
928
|
+
* {@link AgentTextRequest} returning one.
|
|
929
|
+
*
|
|
930
|
+
* An entry is taken as the raw executor envelope (instead of the value itself)
|
|
931
|
+
* only when its OWN keys are an `output` plus, optionally, `usage`/`raw` —
|
|
932
|
+
* that is how an entry reports token `usage`. Anything else, including an
|
|
933
|
+
* object that merely happens to have an `output` key alongside its own data
|
|
934
|
+
* (`{ output: 'draft', confidence: 0.9 }`), is the output value. For a
|
|
935
|
+
* structured request whose declared output is exactly `{ output }` (or
|
|
936
|
+
* `{ output, usage }`), wrap it once more: `{ output: { output: '…' } }`.
|
|
937
|
+
*/
|
|
938
|
+
type ScriptedTextEntry = ((request: AgentTextRequest, info?: AgentRequestExecutorInfo) => unknown) | string | number | boolean | null | object;
|
|
939
|
+
/** The script {@link createScriptedExecutors} plays back. */
|
|
940
|
+
interface ScriptedExecutorsScript {
|
|
941
|
+
/** Answers for `decide` (and `agent.plan`) requests, consumed in order. */
|
|
942
|
+
decisions?: ScriptedDecisionEntry[];
|
|
943
|
+
/** Answers for text requests, consumed in order. `generateText` and `streamText` share this one queue. */
|
|
944
|
+
text?: ScriptedTextEntry[];
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Keyless executors that replay a script instead of calling a model. Every
|
|
948
|
+
* slot is provided, so any machine binds; a request with no entry left throws a
|
|
949
|
+
* descriptive error naming what was pending.
|
|
950
|
+
*
|
|
951
|
+
* Queues are consumed FIFO and are copied on creation, so the caller's arrays
|
|
952
|
+
* are never mutated and each call builds a fresh, independent playthrough.
|
|
953
|
+
* Entries may be plain values or functions of the request, which is how one
|
|
954
|
+
* script serves a machine that loops or branches: route on `request.name` (the
|
|
955
|
+
* `setupAgent({ requests })` key) or on the decision's candidate `events`.
|
|
956
|
+
*
|
|
957
|
+
* @example
|
|
958
|
+
* ```ts
|
|
959
|
+
* const result = await runAgent(moderationMachine, {
|
|
960
|
+
* input: { comment: 'honestly this update is terrible', trust: 20 },
|
|
961
|
+
* executors: createScriptedExecutors({
|
|
962
|
+
* decisions: [{ type: 'FLAG', reason: 'Borderline tone.' }],
|
|
963
|
+
* }),
|
|
964
|
+
* });
|
|
965
|
+
* ```
|
|
966
|
+
*
|
|
967
|
+
* @example Dynamic entries
|
|
968
|
+
* ```ts
|
|
969
|
+
* createScriptedExecutors({
|
|
970
|
+
* text: [(request) => `Draft about ${request.prompt}`],
|
|
971
|
+
* decisions: [(request) => ({ type: request.events[0]!.type })],
|
|
972
|
+
* });
|
|
973
|
+
* ```
|
|
974
|
+
*/
|
|
975
|
+
declare function createScriptedExecutors(script?: ScriptedExecutorsScript): Required<AgentRequestExecutors>;
|
|
976
|
+
//#endregion
|
|
977
|
+
//#region src/seam.d.ts
|
|
978
|
+
/**
|
|
979
|
+
* Which model call is under test: the Nth call addressed either by request
|
|
980
|
+
* `name` (the `setupAgent({ requests })` key or `createTextLogic({ name })`,
|
|
981
|
+
* the better developer handle) or by `model` key (the `defineModels` key) for
|
|
982
|
+
* requests that carry no name.
|
|
983
|
+
*/
|
|
984
|
+
type SeamRef = {
|
|
985
|
+
/** The request's registered `name`. */request: string;
|
|
986
|
+
model?: undefined; /** 0-based occurrence among the calls matching this key. Default `0`. */
|
|
987
|
+
occurrence?: number;
|
|
988
|
+
} | {
|
|
989
|
+
/** The `defineModels` key the request names. */model: string;
|
|
990
|
+
request?: undefined; /** 0-based occurrence among the calls matching this key. Default `0`. */
|
|
991
|
+
occurrence?: number;
|
|
992
|
+
};
|
|
993
|
+
/**
|
|
994
|
+
* One idle pause, handed to {@link RunSeamOptions.respond} so the simulated
|
|
995
|
+
* user answers off the machine's own state rather than a fixed transcript — a
|
|
996
|
+
* live seam may branch differently, and a reactive policy scores that run
|
|
997
|
+
* instead of crashing on it.
|
|
998
|
+
*/
|
|
999
|
+
interface SeamTurn<TMachine extends AnyStateMachine> {
|
|
1000
|
+
/** The idle snapshot to answer. */
|
|
1001
|
+
snapshot: SnapshotFrom<TMachine>;
|
|
1002
|
+
/** Its state value, for a `switch` on flat machines. */
|
|
1003
|
+
state: StateValue;
|
|
1004
|
+
/** The merged `meta` of the active state(s) — e.g. a declared `interaction`. */
|
|
1005
|
+
meta: Record<string, unknown>;
|
|
1006
|
+
/** 0-based index of this pause within the run. */
|
|
1007
|
+
turn: number;
|
|
1008
|
+
/** The `idle` result that produced the pause. */
|
|
1009
|
+
result: RunAgentResult<TMachine>;
|
|
1010
|
+
}
|
|
1011
|
+
/** One side of the seam: a trajectory pair ready for `matchesTrajectory`. */
|
|
1012
|
+
interface SeamSlice {
|
|
1013
|
+
/** State values entered on this side of the seam, in order. */
|
|
1014
|
+
statePath: StateValue[];
|
|
1015
|
+
/** Replayable log entries on this side of the seam, in order. */
|
|
1016
|
+
events: AgentLogEntry[];
|
|
1017
|
+
}
|
|
1018
|
+
/** Options for {@link runSeam}. */
|
|
1019
|
+
interface RunSeamOptions<TMachine extends AnyStateMachine> {
|
|
1020
|
+
/** Machine input, passed straight through to `runAgent`. */
|
|
1021
|
+
input?: InputFrom<TMachine>;
|
|
1022
|
+
/**
|
|
1023
|
+
* The call plan: scripted answers per key, consumed in order. A key is a
|
|
1024
|
+
* request `name` when one is scripted under it, else a `model` key, so a
|
|
1025
|
+
* machine whose requests are named routes by name and an unnamed one routes
|
|
1026
|
+
* by model.
|
|
1027
|
+
*
|
|
1028
|
+
* Entries follow {@link ScriptedTextEntry} conventions (a value, an
|
|
1029
|
+
* `{ output, usage? }` envelope, or a function of the request). The LAST
|
|
1030
|
+
* entry of a queue repeats, so a live seam that sends the run down a longer
|
|
1031
|
+
* branch still finds an answer instead of running dry.
|
|
1032
|
+
*/
|
|
1033
|
+
scripts?: Record<string, ScriptedTextEntry[]>;
|
|
1034
|
+
/** The call under test. */
|
|
1035
|
+
seam: SeamRef;
|
|
1036
|
+
/**
|
|
1037
|
+
* The executor for the seam — the real model, a candidate prompt, anything
|
|
1038
|
+
* request-shaped. Omit to run the seam scripted too: the whole seam run is
|
|
1039
|
+
* then keyless and deterministic.
|
|
1040
|
+
*/
|
|
1041
|
+
candidate?: AgentRequestExecutors["generateText"];
|
|
1042
|
+
/**
|
|
1043
|
+
* The simulated user. Called at every idle pause; return the event to send,
|
|
1044
|
+
* or `null`/`undefined` to stop the run there. Omitted, the run stops at the
|
|
1045
|
+
* first idle pause.
|
|
1046
|
+
*/
|
|
1047
|
+
respond?: (turn: SeamTurn<TMachine>) => EventFromLogic<TMachine> | null | undefined;
|
|
1048
|
+
/** Maximum idle pauses to answer before stopping. Default `12`. */
|
|
1049
|
+
maxTurns?: number;
|
|
1050
|
+
/**
|
|
1051
|
+
* Base executors merged UNDER the seam routing — supply `decide` (e.g. from
|
|
1052
|
+
* `createScriptedExecutors({ decisions })`) for a machine that also decides.
|
|
1053
|
+
* Text slots are always owned by the routing.
|
|
1054
|
+
*/
|
|
1055
|
+
executors?: Partial<AgentRequestExecutors>;
|
|
1056
|
+
/** Passed through to `runAgent`: the deterministic idle-state predicate. */
|
|
1057
|
+
isSuspended?: RunAgentOptions<TMachine>["isSuspended"];
|
|
1058
|
+
/** Passed through to `runAgent`: actor implementations merged onto the machine. */
|
|
1059
|
+
actors?: RunAgentOptions<TMachine>["actors"];
|
|
1060
|
+
}
|
|
1061
|
+
/** What {@link runSeam} returns: the seam's own answer, plus the run it caused. */
|
|
1062
|
+
interface RunSeamResult<TMachine extends AnyStateMachine> {
|
|
1063
|
+
/**
|
|
1064
|
+
* The final `runAgent` result. Its `events` are the WHOLE run's log (every
|
|
1065
|
+
* leg's entries), while `usage` accounts only for the last leg.
|
|
1066
|
+
*/
|
|
1067
|
+
result: RunAgentResult<TMachine>;
|
|
1068
|
+
/** What the seam call returned, or `undefined` when the run never reached it. */
|
|
1069
|
+
seamOutput: unknown;
|
|
1070
|
+
/** Model calls made before the seam, or `-1` when the run never reached it. */
|
|
1071
|
+
callsBeforeSeam: number;
|
|
1072
|
+
/** Everything up to the seam's own effect completion. */
|
|
1073
|
+
before: SeamSlice;
|
|
1074
|
+
/**
|
|
1075
|
+
* Everything from the seam's own effect completion onward — the branch the
|
|
1076
|
+
* seam caused, and the score. Empty when the run never reached the seam.
|
|
1077
|
+
*/
|
|
1078
|
+
after: SeamSlice;
|
|
1079
|
+
}
|
|
1080
|
+
/**
|
|
1081
|
+
* Runs a machine end to end with one model call under test, and slices the run
|
|
1082
|
+
* at that call.
|
|
1083
|
+
*
|
|
1084
|
+
* The `before`/`after` slices are the point: `after.statePath` is the branch
|
|
1085
|
+
* the seam chose and `after.events` is the same question against the durable
|
|
1086
|
+
* log, both ready for `matchesTrajectory`. The state slice splits where the
|
|
1087
|
+
* state path stood when the seam answered; the event slice splits at the
|
|
1088
|
+
* seam's own effect completion (the first `xstate.done.*`/`xstate.error.*`
|
|
1089
|
+
* entry appended after the call was made).
|
|
1090
|
+
*
|
|
1091
|
+
* @example Keyless: the seam is scripted too, so the whole thing runs offline.
|
|
1092
|
+
* ```ts
|
|
1093
|
+
* const run = await runSeam(emailDrafter, {
|
|
1094
|
+
* scripts: { promptEvaluator: [vague, complete], emailDrafter: [draft] },
|
|
1095
|
+
* seam: { request: 'evaluatePrompt' },
|
|
1096
|
+
* respond: ({ state }) => (state === 'prompting' ? { type: 'PROMPT_SUBMITTED', prompt } : null),
|
|
1097
|
+
* });
|
|
1098
|
+
*
|
|
1099
|
+
* matchesTrajectory(run.after.statePath, ['needsMoreInfo', 'drafting']);
|
|
1100
|
+
* ```
|
|
1101
|
+
*
|
|
1102
|
+
* @example A candidate prompt at the seam, scored against the same rows.
|
|
1103
|
+
* ```ts
|
|
1104
|
+
* const { generateText } = createAiSdkExecutors({ models });
|
|
1105
|
+
* const run = await runSeam(emailDrafter, { ...row, candidate: generateText });
|
|
1106
|
+
* ```
|
|
1107
|
+
*/
|
|
1108
|
+
declare function runSeam<TMachine extends AnyStateMachine>(machine: TMachine, options: RunSeamOptions<TMachine>): Promise<RunSeamResult<TMachine>>;
|
|
1109
|
+
//#endregion
|
|
1110
|
+
//#region src/utils.d.ts
|
|
1111
|
+
/**
|
|
1112
|
+
* Deep-clones a snapshot to a plain-JSON value via a `JSON` round-trip, the
|
|
1113
|
+
* shape you persist and later feed back to `runAgent({ snapshot })`. Asserts
|
|
1114
|
+
* JSON-serializability: functions, `undefined`, and other non-JSON values are
|
|
1115
|
+
* dropped or throw exactly as `JSON.stringify`/`JSON.parse` would. Returns a
|
|
1116
|
+
* plain-JSON deep clone, not a live snapshot.
|
|
1117
|
+
*/
|
|
1118
|
+
declare function persistSnapshot<TSnapshot>(snapshot: TSnapshot): TSnapshot;
|
|
1119
|
+
/**
|
|
1120
|
+
* A stable, dependency-free structural fingerprint of a machine — a short hex
|
|
1121
|
+
* `djb2` hash over its **structural** config only: state ids/nesting, transition
|
|
1122
|
+
* event types and targets, invoke `src`s, `initial`, and any other serializable
|
|
1123
|
+
* config fields. Function values (context/output builders, prompts, inline
|
|
1124
|
+
* guards/actions) are excluded entirely, so two machines that differ only in
|
|
1125
|
+
* their prompts or executors hash identically; adding/removing/retargeting a
|
|
1126
|
+
* state or transition changes the hash.
|
|
1127
|
+
*
|
|
1128
|
+
* Used by {@link runAgent} to stamp settled snapshots with a `version` and to
|
|
1129
|
+
* detect a structurally-edited machine on resume. It is a change detector, not
|
|
1130
|
+
* a cryptographic digest — collisions are possible but unlikely for real
|
|
1131
|
+
* configs. Pass an explicit `machineVersion` to `runAgent` to override it.
|
|
1132
|
+
*/
|
|
1133
|
+
declare function getMachineStructuralHash(machine: AnyStateMachine): string;
|
|
1134
|
+
/** Builds a {@link UserMessage} from a string or multimodal content parts. */
|
|
1135
|
+
declare function userMessage(content: string | Array<TextPart | ImagePart | FilePart>): UserMessage;
|
|
1136
|
+
/** Builds an {@link AssistantMessage} from a string or content parts (text, files, tool calls/results). */
|
|
1137
|
+
declare function assistantMessage(content: string | Array<TextPart | FilePart | ToolCallPart | ToolResultPart>): AssistantMessage;
|
|
1138
|
+
/** Builds a {@link SystemMessage}. */
|
|
1139
|
+
declare function systemMessage(content: string): SystemMessage;
|
|
1140
|
+
/** Builds a {@link ToolMessage} from one or more tool-result parts. */
|
|
1141
|
+
declare function toolMessage(content: Array<ToolResultPart>): ToolMessage;
|
|
1142
|
+
type MetaOfSnapshot<TSnapshot extends {
|
|
1143
|
+
getMeta(): Record<string, unknown>;
|
|
1144
|
+
}> = NonNullable<ReturnType<TSnapshot["getMeta"]>[keyof ReturnType<TSnapshot["getMeta"]>]>;
|
|
1145
|
+
/**
|
|
1146
|
+
* Returns the merged `meta` of a snapshot's active state(s) — the typed
|
|
1147
|
+
* replacement for the `Object.values(snapshot.getMeta())[0]` dance.
|
|
1148
|
+
*
|
|
1149
|
+
* `snapshot.getMeta()` is keyed by state id; a leaf machine has one active
|
|
1150
|
+
* state, but parallel/nested machines can have several. This shallow-merges
|
|
1151
|
+
* every active state's meta into one object (later/deeper entries win) and
|
|
1152
|
+
* returns `{}` when no active state declares meta.
|
|
1153
|
+
*
|
|
1154
|
+
* The return type is recovered from the snapshot's own `getMeta()` type, so a
|
|
1155
|
+
* schema-typed machine (`setupAgent({ meta })`) yields the meta schema's
|
|
1156
|
+
* output type. Pass an explicit `TMeta` to override when the snapshot is
|
|
1157
|
+
* untyped (e.g. `AnyMachineSnapshot`).
|
|
1158
|
+
*
|
|
1159
|
+
* @example HITL: read the current state's interaction protocol off an idle
|
|
1160
|
+
* snapshot to render for a human.
|
|
1161
|
+
* ```ts
|
|
1162
|
+
* const { interaction } = getStateMeta(result.snapshot);
|
|
1163
|
+
* ```
|
|
1164
|
+
*/
|
|
1165
|
+
declare function getStateMeta<TSnapshot extends {
|
|
1166
|
+
getMeta(): Record<string, unknown>;
|
|
1167
|
+
} = AnyMachineSnapshot, TMeta = MetaOfSnapshot<TSnapshot>>(snapshot: TSnapshot): Partial<TMeta>;
|
|
1168
|
+
/**
|
|
1169
|
+
* Reads the run-owned message log off a snapshot settled by a `runAgent` call
|
|
1170
|
+
* that used `getRequests` (or `options.messages`) — the typed replacement for
|
|
1171
|
+
* the `(snapshot as { messages?: AgentMessage[] }).messages` cast. runAgent
|
|
1172
|
+
* stamps the log as a plain enumerable `messages` property (like `agentMeta`),
|
|
1173
|
+
* so it survives a JSON persist/resume round-trip; this accessor works on the
|
|
1174
|
+
* live settled snapshot and on a JSON-parsed persisted one alike. Returns `[]`
|
|
1175
|
+
* when no log was stamped (e.g. a default invoke-driven run).
|
|
1176
|
+
*
|
|
1177
|
+
* The write path is `runAgent(..., { messages })`: an explicit seed that
|
|
1178
|
+
* overrides the resume snapshot's stamped log (fold in a user reply on
|
|
1179
|
+
* resume, or start a run with prior history).
|
|
1180
|
+
*/
|
|
1181
|
+
declare function getAgentMessages(snapshot: unknown): AgentMessage[];
|
|
1182
|
+
/**
|
|
1183
|
+
* Structural guard for a {@link StandardSchemaV1}: `true` when `value` carries
|
|
1184
|
+
* the `~standard` marker. Used to tell an already-schema'd tool `inputSchema`
|
|
1185
|
+
* (a Zod/Valibot/… schema) apart from an SDK-specific schema wrapper that core
|
|
1186
|
+
* can't read directly — see the `ai-sdk` tool pass-through.
|
|
1187
|
+
*/
|
|
1188
|
+
declare function isStandardSchema(value: unknown): value is StandardSchemaV1;
|
|
1189
|
+
/**
|
|
1190
|
+
* Pulls the JSON Schema off a {@link StandardSchemaV1} via its optional
|
|
1191
|
+
* `~standard.jsonSchema.input()` extension (implemented by e.g. Zod v4's
|
|
1192
|
+
* `z.toJSONSchema`), awaiting it when the producer is async. Returns
|
|
1193
|
+
* `undefined` when the schema doesn't expose the extension. Use this to build
|
|
1194
|
+
* a provider request's `response_format`/tool `parameters` from a schema.
|
|
1195
|
+
*/
|
|
1196
|
+
declare function getJsonSchema(schema?: StandardSchemaV1): Promise<Record<string, unknown> | undefined>;
|
|
1197
|
+
/**
|
|
1198
|
+
* Synchronous variant of {@link getJsonSchema}, for call sites that can't
|
|
1199
|
+
* await (building tool/event descriptors inline). An async JSON Schema
|
|
1200
|
+
* producer is treated as absent (returns `undefined`) — in practice Zod's
|
|
1201
|
+
* `z.toJSONSchema` resolves synchronously.
|
|
1202
|
+
*/
|
|
1203
|
+
declare function getJsonSchemaSync(schema?: StandardSchemaV1): Record<string, unknown> | undefined;
|
|
1204
|
+
//#endregion
|
|
1205
|
+
export { AGENT_EVENT_SCHEMA_VERSION, AGENT_INIT_EVENT_TYPE, AGENT_TRACE_SCHEMA_VERSION, AGENT_USAGE_EVENT_TYPE, type AgentActorSession, type AgentCallUsage, type AgentDecisionExecutor, AgentDecisionExhaustedError, type AgentDecisionInput, type AgentDecisionRequest, type AgentEffect, type AgentEffectDiff, AgentError, type AgentEventDescriptor, AgentEventLogConflictError, type AgentEventLogDiff, type AgentEventLogStore, type AgentEventToolNameResolver, AgentIdleError, AgentIllegalResumeEventError, type AgentLintDiagnostic, AgentLintError, type AgentLintSeverity, type AgentLogEntry, type AgentLogPatchOperation, type AgentLogVerification, type AgentMessage, type AgentMessageInfo, type AgentModelRef, type AgentOutputMode, type AgentPathReport, type AgentPathTerminal, type AgentPlanInput, type AgentPlanOutput, type AgentPlanRequest, AgentReplayDivergenceError, AgentReplayMachineMismatchError, type AgentRequest, type AgentRequestExecutor, type AgentRequestExecutorInfo, type AgentRequestExecutorResult, type AgentRequestExecutors, type AgentRequestOptions, type AgentRequestSource, type AgentRun, type AgentRunMeta, type AgentSchemaPack, type AgentSnapshotStore, AgentSnapshotVersionMismatchError, type AgentStateRequest, type AgentStepRequest, type AgentTextRequest, type AgentTool, type AgentToolChoice, type AgentToolDescriptor, type AgentToolExecute, type AgentTools, type AgentTraceEvent, type AgentUsage, type AgentUsageEvent, type AgentUsageEventPayload, type AgentUserInput, type AgentUserInputExecutor, type AgentWorkflowActionConfig, type AgentWorkflowActorConfig, type AgentWorkflowConfig, type AgentWorkflowInvokeConfig, type AgentWorkflowRequestConfig, type AgentWorkflowStateConfig, type AgentWorkflowTransitionConfig, type AiSdkShapedStreamResult, type AiSdkShapedTextResult, type AllowedEvents, type AssertAgentMachineOptions, type AssistantMessage, type CanReachResult, type ChosenEvent, type CreateReplayEntryOptions, type DecisionAttempt, type DecisionLogicConfig, type ExplorePathsOptions, type FilePart, type FromConfigOptions, type FromConfigResult, type GenerateResult, type GetAgentEffectsOptions, type ImagePart, type InferOutput, type InspectedActorRef, type JsonSerializableTraceEvent, type JsonValue, type LintAgentMachineOptions, type MatchTrajectoryOptions, NonSerializableAgentEventError, PLAN_DONE_EVENT_TYPE, type PendingUserInput, type PlanLogic, type ProvideExecutorsOptions, type ReplayOptions, type ReplayResult, type ResolveDecisionOptions, type RunAgentErrorCause, type RunAgentOptions, type RunAgentResult, type RunSeamOptions, type RunSeamResult, type SchemaCompiler, type ScriptedDecisionEntry, type ScriptedDecisionValue, type ScriptedExecutorsScript, type ScriptedTextEntry, type SeamRef, type SeamSlice, type SeamTurn, type SimulateAgentOptions, type SimulateAgentResult, type SimulationScript, type SimulationTrailEntry, type StandardSchemaV1, type StructuredOutputEnvelope, type SystemMessage, type TextLogic, type TextLogicConfig, type TextLogicExecuteArgs, type TextLogicExecutor, type TextPart, type ToolCallPart, type ToolMessage, type ToolResultPart, type TrajectoryEvent, type TrajectoryItem, type TrajectoryMatch, type TrajectoryMiss, type UserMessage, type WithAgentUsageEvent, appendMessages, assertAgentLogEntry, assertAgentMachine, assertEventLogStoreConformance, assertJsonSerializable, assistantMessage, bindRequestExecutor, buildEnvelopeSchema, canReach, createAgentActor, createAgentRun, createAgentSchemas, createInMemoryEventLogStore, createReplayEntry, createScriptedExecutors, createTextLogic, diffEventLogs, executeAgentRequest, explorePaths, generateResult, getAcceptedEvents, getAgentEffects, getAgentMessages, getAgentOutputMode, getCallUsage, getJsonSchema, getJsonSchemaSync, getMachineStructuralHash, getStateMeta, initEntry, inspectTransitions, isStandardSchema, lintAgentMachine, matchesTrajectory, messagesSchema, parseAgentEvent, parseModelRef, parseOutput, parseStructuredEnvelope, persistSnapshot, provideExecutors, renderDecisionAttempts, replay, resolveDecision, runAgent, runSeam, serializeTraceEvent, setupAgent, simulateAgent, systemMessage, toolMessage, traceTransitions, userMessage, verifyReplay };
|