@statelyai/agent 1.1.5 → 2.0.0-alpha.5
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/LICENSE +21 -0
- package/dist/ai-sdk.cjs +249 -0
- package/dist/ai-sdk.d.cts +168 -0
- package/dist/ai-sdk.d.mts +168 -0
- package/dist/ai-sdk.mjs +241 -0
- package/dist/cli.cjs +63 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +64 -0
- package/dist/decision-FTmbqSEe.mjs +938 -0
- package/dist/decision-pC-bY2DE.cjs +1231 -0
- package/dist/index.cjs +54 -0
- package/dist/index.d.cts +1217 -0
- package/dist/index.d.mts +1194 -405
- package/dist/index.mjs +3 -583
- package/dist/openai-compat.cjs +319 -0
- package/dist/openai-compat.d.cts +98 -0
- package/dist/openai-compat.d.mts +98 -0
- package/dist/openai-compat.mjs +312 -0
- package/dist/src-CjpHDU8F.mjs +2445 -0
- package/dist/src-DcRsWPfV.cjs +2564 -0
- package/dist/text-logic-1ZQkO3zr.d.cts +682 -0
- package/dist/text-logic-2EMJIS-n.d.mts +682 -0
- package/dist/types-BHjeDdch.d.cts +208 -0
- package/dist/types-Cq1YlAQ6.d.mts +208 -0
- package/dist/utils-CWUCa3pF.d.mts +108 -0
- package/dist/utils-lK1wnL2i.d.cts +108 -0
- package/dist/zod.cjs +31 -0
- package/dist/zod.d.cts +30 -0
- package/dist/zod.d.mts +30 -0
- package/dist/zod.mjs +30 -0
- package/package.json +110 -29
- package/readme.md +144 -6
- package/schemas/agent-workflow.json +527 -0
- package/.changeset/README.md +0 -8
- package/.changeset/config.json +0 -11
- package/.env.template +0 -3
- package/.github/actions/ci-setup/action.yml +0 -24
- package/.github/workflows/release.yml +0 -46
- package/.vscode/launch.json +0 -28
- package/CHANGELOG.md +0 -215
- package/dist/index.d.ts +0 -428
- package/dist/index.js +0 -616
- package/examples/chatbot.ts +0 -71
- package/examples/cot.ts +0 -89
- package/examples/email.ts +0 -118
- package/examples/example.ts +0 -81
- package/examples/goal.ts +0 -94
- package/examples/helpers/helpers.ts +0 -17
- package/examples/helpers/loader.ts +0 -32
- package/examples/helpers/runner.ts +0 -27
- package/examples/joke.ts +0 -225
- package/examples/multi.ts +0 -103
- package/examples/newspaper.ts +0 -324
- package/examples/number.ts +0 -102
- package/examples/raffle.ts +0 -105
- package/examples/sandbox.ts +0 -28
- package/examples/simple.ts +0 -39
- package/examples/support.ts +0 -147
- package/examples/ticTacToe.ts +0 -224
- package/examples/todo.ts +0 -137
- package/examples/tutor.ts +0 -100
- package/examples/verify.ts +0 -120
- package/examples/weather.ts +0 -178
- package/examples/wiki.ts +0 -30
- package/examples/word.ts +0 -171
- package/src/adapters/vercel.ts +0 -7
- package/src/agent-experimental.ts +0 -221
- package/src/agent.test.ts +0 -506
- package/src/agent.ts +0 -300
- package/src/decision.test.ts +0 -179
- package/src/decision.ts +0 -84
- package/src/index.ts +0 -4
- package/src/memory.ts +0 -25
- package/src/planners/shortestPathPlanner.ts +0 -22
- package/src/planners/simplePlanner.ts +0 -139
- package/src/schemas.ts +0 -11
- package/src/strategies/chain-of-note.ts +0 -155
- package/src/templates/defaultText.ts +0 -18
- package/src/text.ts +0 -236
- package/src/types.ts +0 -499
- package/src/utils.ts +0 -72
- package/tsconfig.json +0 -109
- package/vitest.config.ts +0 -9
|
@@ -0,0 +1,682 @@
|
|
|
1
|
+
import { b as StandardSchemaV1, c as AgentTools, f as ChosenEvent, i as AgentToolChoice, t as AgentMessage, u as AllowedEvents, v as InferOutput } from "./types-Cq1YlAQ6.mjs";
|
|
2
|
+
import { AnyMachineSnapshot, AsyncActorLogic, EventObject, LogicActorLogic, MachineSnapshot } from "xstate";
|
|
3
|
+
|
|
4
|
+
//#region src/events.d.ts
|
|
5
|
+
/** The invoke `src` of an {@link AgentRequest}/{@link AgentDecisionRequest} — a plain string, widened so literal `src` values still narrow in editor hints. */
|
|
6
|
+
type AgentRequestSource = string & {};
|
|
7
|
+
/** Default prefix for the synthetic tool name generated per candidate event (e.g. `send_event_ASK`). Override per-request with {@link AgentEventToolNameResolver}. */
|
|
8
|
+
declare const EVENT_TOOL_PREFIX: "send_event_";
|
|
9
|
+
/** Customizes the tool name generated for a candidate event; see {@link AgentRequestOptions.eventToolName}. */
|
|
10
|
+
type AgentEventToolNameResolver = (args: {
|
|
11
|
+
eventType: string;
|
|
12
|
+
defaultToolName: string;
|
|
13
|
+
}) => string;
|
|
14
|
+
/**
|
|
15
|
+
* True when an event type matches an `allowedEvents` entry: an exact type,
|
|
16
|
+
* `'*'` (every event), or a `'prefix.*'` wildcard matching any deeper
|
|
17
|
+
* segment (`'todo.*'` matches `'todo.add'` and `'todo.list.clear'`, not
|
|
18
|
+
* `'todo'` itself — mirroring xstate's partial wildcard events).
|
|
19
|
+
*/
|
|
20
|
+
declare function matchesEventPattern(eventType: string, pattern: string): boolean;
|
|
21
|
+
/** One candidate event a decision (or {@link getAcceptedEvents} caller) may choose: its type, the synthetic tool name a model can call to pick it, and its payload schema if one is registered. */
|
|
22
|
+
interface AgentEventDescriptor {
|
|
23
|
+
type: string;
|
|
24
|
+
toolName: string;
|
|
25
|
+
inputSchema?: StandardSchemaV1;
|
|
26
|
+
}
|
|
27
|
+
/** Registered event payload schemas, as attached to a machine by `setupAgent`/`createAgentSchemas`. */
|
|
28
|
+
interface AgentSchemas {
|
|
29
|
+
events?: Record<string, StandardSchemaV1>;
|
|
30
|
+
}
|
|
31
|
+
/** Shared options threaded through step discovery ({@link getAgentRequests}/{@link getAcceptedEvents}) — snapshot for event legality, event schemas for payload validation/tool schemas, and registered actor source logics. */
|
|
32
|
+
interface AgentRequestOptions {
|
|
33
|
+
snapshot?: AnyMachineSnapshot;
|
|
34
|
+
events?: Record<string, StandardSchemaV1>;
|
|
35
|
+
schemas?: AgentSchemas;
|
|
36
|
+
actorSources?: Record<string, unknown>;
|
|
37
|
+
/** Customize machine-event tool names. Defaults to send_event_<TYPE>. */
|
|
38
|
+
eventToolName?: AgentEventToolNameResolver;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Lists the events a snapshot can currently accept, as {@link AgentEventDescriptor}s
|
|
42
|
+
* a model can be offered (via `resolveDecision`/an adapter's tool-per-event
|
|
43
|
+
* mapping). **Filters by event TYPE only** — it does not evaluate guards, so
|
|
44
|
+
* a type-legal-but-guard-rejected event can still appear here. Guard
|
|
45
|
+
* legality is checked separately, at decision-resolution time, via
|
|
46
|
+
* `snapshot.can(event)` (the `canTake` option of {@link resolveDecision} /
|
|
47
|
+
* {@link ResolveDecisionOptions}). Pass `eventTypes` to further narrow to a
|
|
48
|
+
* declared `allowedEvents` set — entries may be exact types or wildcard
|
|
49
|
+
* patterns (`'*'`, `'todo.*'`; see {@link matchesEventPattern}).
|
|
50
|
+
*/
|
|
51
|
+
/** Recovers a machine's event union from its snapshot type, so {@link parseAgentEvent} returns the machine-typed event without a downstream cast. @internal */
|
|
52
|
+
type EventFromSnapshot<TSnapshot> = TSnapshot extends MachineSnapshot<any, infer TEvent, any, any, any, any, any, any> ? TEvent : EventObject;
|
|
53
|
+
/**
|
|
54
|
+
* Runtime-validates a dynamically-built `{ type, ...payload }` event against a
|
|
55
|
+
* snapshot's currently-accepted events (via {@link getAcceptedEvents}) and,
|
|
56
|
+
* when one is registered, the event type's payload schema — returning the
|
|
57
|
+
* event typed as the machine's event union (recovered from the snapshot type)
|
|
58
|
+
* so it can be sent to `runAgent({ event })` / `actor.send(...)` without an
|
|
59
|
+
* `as never` cast. For generic, meta-driven hosts that assemble events from
|
|
60
|
+
* user input or a wire message.
|
|
61
|
+
*
|
|
62
|
+
* Throws a descriptive error when `event.type` is not currently accepted
|
|
63
|
+
* (listing the accepted types) or when its payload fails the registered schema.
|
|
64
|
+
* Pass event payload schemas via `options.events`/`options.schemas` (the same
|
|
65
|
+
* shape {@link getAcceptedEvents} takes) — the accepted TYPES always come from
|
|
66
|
+
* the live snapshot; the schemas only add payload validation.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* const event = parseAgentEvent(result.snapshot, rawEvent, { events: schemas.events });
|
|
71
|
+
* result = await runAgent(machine, { snapshot: result.snapshot, event, executors });
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
declare function parseAgentEvent<TSnapshot extends AnyMachineSnapshot>(snapshot: TSnapshot, event: {
|
|
75
|
+
type: string;
|
|
76
|
+
} & Record<string, unknown>, options?: Pick<AgentRequestOptions, "events" | "schemas" | "eventToolName">): EventFromSnapshot<TSnapshot>;
|
|
77
|
+
declare function getAcceptedEvents(snapshot: AnyMachineSnapshot, options?: Pick<AgentRequestOptions, "events" | "schemas" | "eventToolName"> & {
|
|
78
|
+
eventTypes?: readonly string[];
|
|
79
|
+
}): AgentEventDescriptor[];
|
|
80
|
+
//#endregion
|
|
81
|
+
//#region src/decision.d.ts
|
|
82
|
+
/**
|
|
83
|
+
* Inline input for the `agent.decide` builtin actor — the zero-config
|
|
84
|
+
* counterpart to {@link createDecisionLogic}, invoked directly from a
|
|
85
|
+
* state's `invoke.input` (typed against the machine's own event schemas).
|
|
86
|
+
* See {@link AgentDecisionRequest} for the request shape this lowers to.
|
|
87
|
+
*/
|
|
88
|
+
interface AgentDecisionInput<TEvent extends string = string, TMetadata = Record<string, unknown>, TModel extends string = string> {
|
|
89
|
+
model: TModel;
|
|
90
|
+
system?: string;
|
|
91
|
+
prompt?: string;
|
|
92
|
+
messages?: AgentMessage[];
|
|
93
|
+
allowedEvents?: AllowedEvents<TEvent>;
|
|
94
|
+
maxRetries?: number;
|
|
95
|
+
temperature?: number;
|
|
96
|
+
maxOutputTokens?: number;
|
|
97
|
+
topP?: number;
|
|
98
|
+
topK?: number;
|
|
99
|
+
seed?: number;
|
|
100
|
+
stopSequences?: string[];
|
|
101
|
+
metadata?: TMetadata;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Inline input for the `agent.plan` builtin actor — a multi-event decision.
|
|
105
|
+
* Where `agent.decide` picks exactly one currently-legal event, `agent.plan`
|
|
106
|
+
* applies an ordered sequence of them: each step re-reads the live snapshot,
|
|
107
|
+
* asks the `decide` executor for one legal event (same validation and
|
|
108
|
+
* `rejected-by-guard` retry loop as a decision), sends it to the machine,
|
|
109
|
+
* and repeats until a `stopOn` event is chosen, `maxSteps` is reached, no
|
|
110
|
+
* legal candidate remains, or an applied event exits the invoking state
|
|
111
|
+
* (which cancels the invoke — the machine simply moves on).
|
|
112
|
+
*
|
|
113
|
+
* Requires a snapshot-aware host: {@link runAgent}, or the step path (where an
|
|
114
|
+
* `agent.plan` invoke re-surfaces as a `kind: 'plan'` request that
|
|
115
|
+
* `resolveAgentRequests` drives one step per call).
|
|
116
|
+
*/
|
|
117
|
+
interface AgentPlanInput<TEvent extends string = string, TMetadata = Record<string, unknown>, TModel extends string = string> extends AgentDecisionInput<TEvent, TMetadata, TModel> {
|
|
118
|
+
/** Maximum events applied in one plan. Default 8. */
|
|
119
|
+
maxSteps?: number;
|
|
120
|
+
/**
|
|
121
|
+
* Machine events that end the plan once chosen: the event is still
|
|
122
|
+
* validated and sent, then the loop stops. Usually unnecessary — every
|
|
123
|
+
* plan step already offers the built-in {@link PLAN_DONE_EVENT_TYPE}
|
|
124
|
+
* "done" option, which ends the plan without touching the machine.
|
|
125
|
+
* Declare `stopOn` only for "send this real event AND stop" semantics.
|
|
126
|
+
*/
|
|
127
|
+
stopOn?: readonly TEvent[];
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Reserved event type the `agent.plan` builtin adds to every step's
|
|
131
|
+
* candidates as the explicit "no further action needed" move. Choosing it
|
|
132
|
+
* ends the plan (`stopped: 'done'`); it is never sent to the machine, so
|
|
133
|
+
* machines need no no-op sentinel event of their own.
|
|
134
|
+
*/
|
|
135
|
+
declare const PLAN_DONE_EVENT_TYPE: "agent.plan.done";
|
|
136
|
+
/** What an `agent.plan` invoke resolves with (its `onDone` output). */
|
|
137
|
+
interface AgentPlanOutput {
|
|
138
|
+
/** The events applied, in order (possibly empty). */
|
|
139
|
+
steps: ChosenEvent[];
|
|
140
|
+
/** Why the loop ended. */
|
|
141
|
+
stopped: "done" | "stop-event" | "max-steps" | "no-legal-events";
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* The in-progress state of a plan, held in the `agent.plan` invoke child's own
|
|
145
|
+
* `createLogic` snapshot `context`. Because a `createLogic` snapshot serializes
|
|
146
|
+
* (and restores) by identity, this lands at
|
|
147
|
+
* `children.<planId>.snapshot.context` in a machine's persisted snapshot for
|
|
148
|
+
* free — so a step-path host that persists after every event resumes a plan
|
|
149
|
+
* mid-flight without a bespoke carrier.
|
|
150
|
+
*/
|
|
151
|
+
interface PlanLedgerContext {
|
|
152
|
+
/** The events applied so far in this plan, in order (the trail). */
|
|
153
|
+
applied: ChosenEvent[];
|
|
154
|
+
/** How many more events the plan may apply (`maxSteps - applied.length`). */
|
|
155
|
+
stepsRemaining: number;
|
|
156
|
+
/** Set once the plan terminates; `null` while in flight. */
|
|
157
|
+
stopped: AgentPlanOutput["stopped"] | null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The two ledger events that drive a {@link PlanLedgerContext} forward:
|
|
161
|
+
* `plan.applied` appends one event to the trail and decrements the budget;
|
|
162
|
+
* `plan.ended` records the stop reason and completes the ledger (its snapshot
|
|
163
|
+
* goes `done` with the {@link AgentPlanOutput}).
|
|
164
|
+
*/
|
|
165
|
+
type PlanLedgerEvent = {
|
|
166
|
+
type: "plan.applied";
|
|
167
|
+
event: ChosenEvent;
|
|
168
|
+
} | {
|
|
169
|
+
type: "plan.ended";
|
|
170
|
+
stopped: AgentPlanOutput["stopped"];
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Actor logic for the `agent.plan` builtin: a stateful, transition-based
|
|
174
|
+
* ledger. Its snapshot `context` ({@link PlanLedgerContext}) IS the plan's
|
|
175
|
+
* in-progress state — the applied trail plus remaining budget — advanced one
|
|
176
|
+
* {@link PlanLedgerEvent} at a time. On the step path the invoke child runs this
|
|
177
|
+
* logic directly (so its context persists at `children.<id>.snapshot.context`);
|
|
178
|
+
* runAgent swaps in an async implementation that drives the SAME ledger via the
|
|
179
|
+
* shared {@link initialPlanLedger}/{@link advancePlanLedger} drivers.
|
|
180
|
+
*/
|
|
181
|
+
interface PlanLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1<AgentPlanInput>> extends LogicActorLogic<PlanLedgerContext, AgentPlanOutput, PlanLedgerEvent, InferOutput<TInputSchema>> {
|
|
182
|
+
readonly kind: "statelyai.planLogic";
|
|
183
|
+
readonly maxRetries: number;
|
|
184
|
+
/** Builds the per-step base {@link AgentDecisionRequest} (id/events filled in per step). */
|
|
185
|
+
request(input: InferOutput<TInputSchema>): AgentDecisionRequest;
|
|
186
|
+
/** @internal Resolves declared `allowedEvents` (undefined = all currently legal). */
|
|
187
|
+
allowedEventTypes(input: InferOutput<TInputSchema>): readonly string[] | undefined;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Config for {@link createDecisionLogic}: how to build an
|
|
191
|
+
* {@link AgentDecisionRequest} from typed input. Each field mirrors
|
|
192
|
+
* {@link TextLogicConfig} (static value or a `({ input }) => value`
|
|
193
|
+
* resolver), plus `allowedEvents` to narrow the candidate event set (see
|
|
194
|
+
* {@link AllowedEvents}) and `maxRetries` for {@link resolveDecision}.
|
|
195
|
+
*/
|
|
196
|
+
interface DecisionLogicConfig<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TEvent extends string = string, TMetadata extends Record<string, unknown> = Record<string, unknown>, TModel extends string = string> {
|
|
197
|
+
schemas?: {
|
|
198
|
+
input: TInputSchema;
|
|
199
|
+
};
|
|
200
|
+
model: ResolveTextLogicValue<TModel, InferOutput<TInputSchema>>;
|
|
201
|
+
system?: ResolveTextLogicValue<string | undefined, InferOutput<TInputSchema>>;
|
|
202
|
+
prompt?: ResolveTextLogicValue<string | undefined, InferOutput<TInputSchema>>;
|
|
203
|
+
messages?: ResolveTextLogicValue<AgentMessage[] | undefined, InferOutput<TInputSchema>>;
|
|
204
|
+
allowedEvents?: AllowedEvents<TEvent, InferOutput<TInputSchema>>;
|
|
205
|
+
maxRetries?: number;
|
|
206
|
+
temperature?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
207
|
+
maxOutputTokens?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
208
|
+
topP?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
209
|
+
topK?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
210
|
+
seed?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
211
|
+
stopSequences?: ResolveTextLogicValue<string[] | undefined, InferOutput<TInputSchema>>;
|
|
212
|
+
metadata?: ResolveTextLogicValue<TMetadata | undefined, InferOutput<TInputSchema>>;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Actor logic for a decision: an async effect that resolves to exactly one
|
|
216
|
+
* currently-legal {@link ChosenEvent} (never a plain value). Under `runAgent`
|
|
217
|
+
* the chosen event is delivered to the invoking actor automatically — the
|
|
218
|
+
* transition it triggers usually exits the invoking state and ends the invoke.
|
|
219
|
+
* Built by {@link createDecisionLogic}. Register it under `actorSources:` to reuse/export/
|
|
220
|
+
* test it standalone; for a state-local, zero-config decision, use the
|
|
221
|
+
* `agent.decide` builtin invoke instead.
|
|
222
|
+
*/
|
|
223
|
+
interface DecisionLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TMetadata extends Record<string, unknown> = Record<string, unknown>> extends AsyncActorLogic<ChosenEvent, InferOutput<TInputSchema>> {
|
|
224
|
+
readonly kind: "statelyai.decisionLogic";
|
|
225
|
+
readonly maxRetries: number;
|
|
226
|
+
request(input: InferOutput<TInputSchema>): AgentDecisionRequest;
|
|
227
|
+
withExecutor(execute: AgentDecisionExecutor): DecisionLogic<TInputSchema, TMetadata>;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* A decision request: resolves to exactly one currently-legal event. See
|
|
231
|
+
* `resolveDecision`.
|
|
232
|
+
*/
|
|
233
|
+
interface AgentDecisionRequest {
|
|
234
|
+
kind: "decision";
|
|
235
|
+
/** Durable invoke id. */
|
|
236
|
+
id: string;
|
|
237
|
+
model: string;
|
|
238
|
+
system?: string;
|
|
239
|
+
prompt?: string;
|
|
240
|
+
messages?: AgentMessage[];
|
|
241
|
+
/** Candidate events: declared `allowedEvents` ∩ snapshot-legal events. */
|
|
242
|
+
events: AgentEventDescriptor[];
|
|
243
|
+
/**
|
|
244
|
+
* Prior failed attempts for THIS decision. Empty on the first attempt.
|
|
245
|
+
* Adapters render these into the provider request so retries converge.
|
|
246
|
+
* Core never rewrites prompts/messages — attempts are data on the request.
|
|
247
|
+
*/
|
|
248
|
+
attempts: DecisionAttempt[];
|
|
249
|
+
temperature?: number;
|
|
250
|
+
maxOutputTokens?: number;
|
|
251
|
+
topP?: number;
|
|
252
|
+
topK?: number;
|
|
253
|
+
seed?: number;
|
|
254
|
+
stopSequences?: string[];
|
|
255
|
+
metadata?: Record<string, unknown>;
|
|
256
|
+
/**
|
|
257
|
+
* Abort signal for the underlying model call, threaded through by
|
|
258
|
+
* {@link resolveDecision} from its `options.signal` so a `decide` executor
|
|
259
|
+
* can cancel the in-flight request (symmetric with the text executors'
|
|
260
|
+
* `info.signal`). Runtime-only — never serialized into a provider request.
|
|
261
|
+
*/
|
|
262
|
+
signal?: AbortSignal;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* A single failed decision attempt, recorded by {@link resolveDecision} and
|
|
266
|
+
* fed back to the executor on the next attempt via
|
|
267
|
+
* `request.attempts`. `failure` names which of the three checks rejected the
|
|
268
|
+
* choice: `'unknown-event'` (not among the candidate `events`),
|
|
269
|
+
* `'invalid-payload'` (failed the event's schema), or `'rejected-by-guard'`
|
|
270
|
+
* (failed the `canTake` check — type/payload were legal, but the machine's
|
|
271
|
+
* guard rejected it at apply time).
|
|
272
|
+
*/
|
|
273
|
+
interface DecisionAttempt {
|
|
274
|
+
event?: ChosenEvent;
|
|
275
|
+
failure: "unknown-event" | "invalid-payload" | "rejected-by-guard";
|
|
276
|
+
reason: string;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Thrown by {@link resolveDecision} when every attempt (up to
|
|
280
|
+
* `maxRetries + 1` of them) fails one of the three checks recorded in
|
|
281
|
+
* {@link DecisionAttempt.failure}. Carries the full `attempts` list for
|
|
282
|
+
* diagnostics; a machine typically routes this via the decision invoke's
|
|
283
|
+
* `onError`.
|
|
284
|
+
*/
|
|
285
|
+
declare class DecisionExhaustedError extends Error {
|
|
286
|
+
attempts: DecisionAttempt[];
|
|
287
|
+
constructor(attempts: DecisionAttempt[]);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Renders a decision request's prior failed `attempts` into feedback messages
|
|
291
|
+
* a host appends to the model call so retries converge — the transport-agnostic
|
|
292
|
+
* "your last choice failed because X, choose again from Y" logic every adapter
|
|
293
|
+
* and raw-SDK host repeats. Returns one `user`-role {@link AgentMessage} per
|
|
294
|
+
* attempt (empty when there are none); adapters map each onto their wire
|
|
295
|
+
* message shape (`attempt.content` is always a string). Core never rewrites the
|
|
296
|
+
* request itself — this only turns the recorded attempts into messages.
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* ```ts
|
|
300
|
+
* const messages = [...baseMessages, ...renderDecisionAttempts(request)];
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
declare function renderDecisionAttempts(request: Pick<AgentDecisionRequest, "events" | "attempts">): AgentMessage[];
|
|
304
|
+
/**
|
|
305
|
+
* Host implementation of "make the model choose one of `request.events`."
|
|
306
|
+
* Third executor slot on {@link AgentRequestExecutors}, symmetric with
|
|
307
|
+
* `generateText`/`streamText` — how the model is coerced into choosing
|
|
308
|
+
* (tool-per-event + forced tool choice, structured output, …) is entirely
|
|
309
|
+
* adapter business; core only validates and retries the returned choice (see
|
|
310
|
+
* {@link resolveDecision}). The optional `reason` is carried through to
|
|
311
|
+
* `onResult`/event-sourcing but never affects validation. Like text
|
|
312
|
+
* executors' `{ output, ...extras }` envelope, any extra keys (usage, finish
|
|
313
|
+
* reason, …) flow untouched to `onResult`'s `raw`.
|
|
314
|
+
*/
|
|
315
|
+
type AgentDecisionExecutor = (request: AgentDecisionRequest) => PromiseLike<{
|
|
316
|
+
event: ChosenEvent;
|
|
317
|
+
reason?: string;
|
|
318
|
+
[key: string]: unknown;
|
|
319
|
+
}>;
|
|
320
|
+
/**
|
|
321
|
+
* Options for {@link resolveDecision}. The `TEvent` parameter (the machine's
|
|
322
|
+
* event union, defaulting to the loose {@link ChosenEvent}) types both
|
|
323
|
+
* `canTake`'s argument and {@link resolveDecision}'s return — pass it (or let
|
|
324
|
+
* it infer from `canTake`) to get a machine-typed chosen event out without a
|
|
325
|
+
* downstream cast.
|
|
326
|
+
*/
|
|
327
|
+
interface ResolveDecisionOptions<TEvent extends ChosenEvent = ChosenEvent> {
|
|
328
|
+
/** Retries after a failed attempt. Default `2`, so up to 3 attempts total. */
|
|
329
|
+
maxRetries?: number;
|
|
330
|
+
/** Checked before each attempt; aborting rejects the pending decision. */
|
|
331
|
+
signal?: AbortSignal;
|
|
332
|
+
/**
|
|
333
|
+
* Guard-legality check (mode 3), typically `(e) => snapshot.can(e)`. A
|
|
334
|
+
* type-and-payload-valid event that this rejects records a
|
|
335
|
+
* `'rejected-by-guard'` attempt and retries. Omit to skip guard checking
|
|
336
|
+
* (type + payload validation only — e.g. under bare `createActor`, where
|
|
337
|
+
* no snapshot is reachable). Typing its argument as the machine's event
|
|
338
|
+
* union (e.g. `(e: GameEvent) => snapshot.can(e)`) makes
|
|
339
|
+
* {@link resolveDecision} return that union.
|
|
340
|
+
*/
|
|
341
|
+
canTake?: (event: TEvent) => boolean;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Validation + retry core for decisions. No provider mechanics — the
|
|
345
|
+
* `executor` is responsible for making the model choose an event; this
|
|
346
|
+
* function only validates the choice and retries on failure, up to
|
|
347
|
+
* `options.maxRetries` (default 2, i.e. up to 3 attempts total).
|
|
348
|
+
*
|
|
349
|
+
* Each attempt is checked in order and can fail one of three ways (recorded
|
|
350
|
+
* as a {@link DecisionAttempt}): `'unknown-event'` (the chosen `type` is not
|
|
351
|
+
* among `request.events`), `'invalid-payload'` (the payload fails that
|
|
352
|
+
* event's schema), or `'rejected-by-guard'` (passes both checks but
|
|
353
|
+
* `options.canTake` returns `false` — a type/payload-legal event the
|
|
354
|
+
* machine's guard rejects right now; omit `canTake` to skip this check).
|
|
355
|
+
* Every prior failed attempt for this call is fed back to the executor on
|
|
356
|
+
* the next attempt via `request.attempts`, so an adapter can render "your
|
|
357
|
+
* last choice failed because X — try again" into the next model call; core
|
|
358
|
+
* never rewrites the request itself. Exhausting all attempts throws
|
|
359
|
+
* {@link DecisionExhaustedError} with the full attempts list.
|
|
360
|
+
*
|
|
361
|
+
* @example
|
|
362
|
+
* ```ts
|
|
363
|
+
* const event = await resolveDecision(request, decide, {
|
|
364
|
+
* canTake: (e) => snapshot.can(e),
|
|
365
|
+
* });
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
declare function resolveDecision<TEvent extends ChosenEvent = ChosenEvent>(request: AgentDecisionRequest, executor: AgentDecisionExecutor, options?: ResolveDecisionOptions<TEvent>): Promise<TEvent>;
|
|
369
|
+
//#endregion
|
|
370
|
+
//#region src/text-logic.d.ts
|
|
371
|
+
declare const USER_INPUT_ACTOR: "agent.userInput";
|
|
372
|
+
declare const GENERATE_TEXT_ACTOR: "agent.generateText";
|
|
373
|
+
declare const STREAM_TEXT_ACTOR: "agent.streamText";
|
|
374
|
+
declare const DECIDE_ACTOR: "agent.decide";
|
|
375
|
+
declare const PLAN_ACTOR: "agent.plan";
|
|
376
|
+
/** Whether a text request should be resolved with `generateText` (one-shot) or `streamText` (chunked, via `onChunk`). */
|
|
377
|
+
type AgentRequestMode = "generate" | "stream";
|
|
378
|
+
/** A `setupAgent({ models })` model registry, mapping short model refs to provider-specific model values. */
|
|
379
|
+
type AgentModelMap = Record<string, unknown>;
|
|
380
|
+
/**
|
|
381
|
+
* A model reference: any string is legal, but a registered `models` map's keys
|
|
382
|
+
* autocomplete. Refs are opaque routing keys — the host/executor (or the AI SDK
|
|
383
|
+
* adapter's models map / `resolveModel`) resolves them to a real model.
|
|
384
|
+
*/
|
|
385
|
+
type AgentModelRef<TModels extends AgentModelMap = {}> = [keyof TModels] extends [never] ? string : (keyof TModels & string) | (string & {});
|
|
386
|
+
/**
|
|
387
|
+
* Portable, provider-agnostic input a text request passes to a host
|
|
388
|
+
* executor (`generateText`/`streamText` on {@link AgentRequestExecutors}).
|
|
389
|
+
* Built by {@link TextLogic.request} / `DecisionLogic.request` from a
|
|
390
|
+
* `TextLogicConfig`/`DecisionLogicConfig`; adapters (e.g.
|
|
391
|
+
* `createAiSdkExecutors`) map this shape onto their provider's call
|
|
392
|
+
* settings.
|
|
393
|
+
*/
|
|
394
|
+
interface AgentTextRequest<TMetadata = Record<string, unknown>> {
|
|
395
|
+
/**
|
|
396
|
+
* The registered name of the request that produced this call — the
|
|
397
|
+
* `setupAgent({ requests })` key (also set by `setupAgent.fromConfig`), or
|
|
398
|
+
* `TextLogicConfig.name` for standalone `createTextLogic` actors. Hosts and
|
|
399
|
+
* test mocks can route on it instead of sniffing `system`/`prompt` text.
|
|
400
|
+
* Absent for ad-hoc `agent.generateText`/`agent.streamText` invokes unless
|
|
401
|
+
* the caller sets it on the inline input.
|
|
402
|
+
*/
|
|
403
|
+
name?: string;
|
|
404
|
+
model: string;
|
|
405
|
+
system?: string;
|
|
406
|
+
prompt?: string;
|
|
407
|
+
messages?: AgentMessage[];
|
|
408
|
+
/** Host/model tools that are always available to this text call. */
|
|
409
|
+
tools?: AgentTools;
|
|
410
|
+
toolChoice?: AgentToolChoice;
|
|
411
|
+
outputSchema?: StandardSchemaV1;
|
|
412
|
+
/**
|
|
413
|
+
* Opt-in reasoning for a structured-output request: when `true`, adapters add
|
|
414
|
+
* an optional string `reasoning` property (listed BEFORE `result`) to the
|
|
415
|
+
* structured-output envelope schema, nudging the model to reason before
|
|
416
|
+
* committing to the result. The reasoning is surfaced on the executor's raw
|
|
417
|
+
* result (never in machine context/output). Ignored for text-mode requests.
|
|
418
|
+
*/
|
|
419
|
+
reasoning?: boolean;
|
|
420
|
+
temperature?: number;
|
|
421
|
+
/**
|
|
422
|
+
* Maximum number of output tokens to generate. Named `maxOutputTokens` (not
|
|
423
|
+
* `maxTokens`) so an `AgentTextRequest` is spread-compatible with the Vercel
|
|
424
|
+
* AI SDK's `generateText`/`streamText` options.
|
|
425
|
+
*/
|
|
426
|
+
maxOutputTokens?: number;
|
|
427
|
+
topP?: number;
|
|
428
|
+
topK?: number;
|
|
429
|
+
seed?: number;
|
|
430
|
+
stopSequences?: string[];
|
|
431
|
+
/**
|
|
432
|
+
* Host-owned per-call options. Use this for provider/runtime details such
|
|
433
|
+
* as Cloudflare bindings, tracing IDs, SDK provider options, or transport
|
|
434
|
+
* hints. The machine carries it; the host decides what it means — e.g.
|
|
435
|
+
* the AI SDK adapter (`createAiSdkExecutors`) reads `metadata.maxSteps` to
|
|
436
|
+
* bound its multi-step tool-call loop for that request.
|
|
437
|
+
*/
|
|
438
|
+
metadata?: TMetadata;
|
|
439
|
+
}
|
|
440
|
+
/** Inline input for the `agent.userInput` builtin actor — a human-input request (CLI prompt, form, chat reply, …). See {@link RunAgentOptions.userInput}. */
|
|
441
|
+
interface AgentUserInput<TMetadata = Record<string, unknown>> {
|
|
442
|
+
prompt?: string;
|
|
443
|
+
schema?: StandardSchemaV1;
|
|
444
|
+
metadata?: TMetadata;
|
|
445
|
+
}
|
|
446
|
+
/** The five `agent.*` builtin actor logics every setupAgent-built machine registers. @internal */
|
|
447
|
+
type BuiltinAgentActors<TEvent extends string = string, TModel extends string = string> = {
|
|
448
|
+
[GENERATE_TEXT_ACTOR]: AsyncActorLogic<unknown, AgentTextRequest>;
|
|
449
|
+
[STREAM_TEXT_ACTOR]: AsyncActorLogic<unknown, AgentTextRequest>;
|
|
450
|
+
[USER_INPUT_ACTOR]: AsyncActorLogic<unknown, AgentUserInput>;
|
|
451
|
+
[DECIDE_ACTOR]: AsyncActorLogic<ChosenEvent, AgentDecisionInput<TEvent, Record<string, unknown>, TModel>>;
|
|
452
|
+
[PLAN_ACTOR]: PlanLogic<StandardSchemaV1<AgentPlanInput<TEvent, Record<string, unknown>, TModel>>>;
|
|
453
|
+
};
|
|
454
|
+
/**
|
|
455
|
+
* Validates a raw model/executor output against `schema`, returning the
|
|
456
|
+
* parsed value. Thin wrapper over {@link validateSchemaSync} for parsing a
|
|
457
|
+
* text request's structured output outside of `TextLogic.execute`/
|
|
458
|
+
* `executeAgentRequest` (e.g. a custom host loop).
|
|
459
|
+
*/
|
|
460
|
+
declare function parseOutput<TSchema extends StandardSchemaV1>(schema: TSchema, output: unknown): InferOutput<TSchema>;
|
|
461
|
+
/** A TextLogicConfig/DecisionLogicConfig field value: either static, or a `({ input }) => value` resolver. @internal */
|
|
462
|
+
type ResolveTextLogicValue<TValue, TInput> = TValue | ((args: {
|
|
463
|
+
input: TInput;
|
|
464
|
+
}) => TValue);
|
|
465
|
+
/**
|
|
466
|
+
* Config for {@link createTextLogic}: how to build an
|
|
467
|
+
* {@link AgentTextRequest} from typed input, plus the input/output schemas
|
|
468
|
+
* that validate it. Each request-shaping field (`model`, `system`, `prompt`,
|
|
469
|
+
* …) is either a static value or a `({ input }) => value` resolver.
|
|
470
|
+
*/
|
|
471
|
+
interface TextLogicConfig<TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetadata = Record<string, unknown>, TModel extends string = string> {
|
|
472
|
+
mode?: AgentRequestMode;
|
|
473
|
+
/** Stamped onto every lowered request as {@link AgentTextRequest.name}. `setupAgent({ requests })` sets this to the request's key. */
|
|
474
|
+
name?: ResolveTextLogicValue<string | undefined, InferOutput<TInputSchema>>;
|
|
475
|
+
schemas: {
|
|
476
|
+
input: TInputSchema;
|
|
477
|
+
output: TOutputSchema;
|
|
478
|
+
};
|
|
479
|
+
model: ResolveTextLogicValue<TModel, InferOutput<TInputSchema>>;
|
|
480
|
+
system?: ResolveTextLogicValue<string | undefined, InferOutput<TInputSchema>>;
|
|
481
|
+
prompt?: ResolveTextLogicValue<string | undefined, InferOutput<TInputSchema>>;
|
|
482
|
+
messages?: ResolveTextLogicValue<AgentMessage[] | undefined, InferOutput<TInputSchema>>;
|
|
483
|
+
tools?: ResolveTextLogicValue<AgentTools | undefined, InferOutput<TInputSchema>>;
|
|
484
|
+
toolChoice?: ResolveTextLogicValue<AgentToolChoice | undefined, InferOutput<TInputSchema>>;
|
|
485
|
+
/** Opt into the structured-output envelope's `reasoning` field (see {@link AgentTextRequest.reasoning}). */
|
|
486
|
+
reasoning?: ResolveTextLogicValue<boolean | undefined, InferOutput<TInputSchema>>;
|
|
487
|
+
temperature?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
488
|
+
maxOutputTokens?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
489
|
+
topP?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
490
|
+
topK?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
491
|
+
seed?: ResolveTextLogicValue<number | undefined, InferOutput<TInputSchema>>;
|
|
492
|
+
stopSequences?: ResolveTextLogicValue<string[] | undefined, InferOutput<TInputSchema>>;
|
|
493
|
+
metadata?: ResolveTextLogicValue<TMetadata | undefined, InferOutput<TInputSchema>>;
|
|
494
|
+
}
|
|
495
|
+
/** Arguments passed to a {@link TextLogicExecutor}: the typed input, the lowered {@link AgentTextRequest}, and the actor's own `signal`/`system`/`self`/`emit`. */
|
|
496
|
+
interface TextLogicExecuteArgs<TInput, TMetadata = Record<string, unknown>> {
|
|
497
|
+
input: TInput;
|
|
498
|
+
request: AgentTextRequest<TMetadata>;
|
|
499
|
+
signal: AbortSignal;
|
|
500
|
+
system: unknown;
|
|
501
|
+
self: unknown;
|
|
502
|
+
emit: (emitted: EventObject) => void;
|
|
503
|
+
}
|
|
504
|
+
/** Host implementation bound to a specific {@link TextLogic} via `withExecutor`/`createTextLogic`'s second argument — resolves one text request to an `{ output }` envelope typed from the logic's output schema (`{ output: T }`). Passthrough fields (usage, raw, …) are allowed alongside `output`. */
|
|
505
|
+
type TextLogicExecutor<TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetadata = unknown> = (args: TextLogicExecuteArgs<InferOutput<TInputSchema>, TMetadata>) => PromiseLike<AgentRequestExecutorResult<InferOutput<TOutputSchema>>> | AgentRequestExecutorResult<InferOutput<TOutputSchema>>;
|
|
506
|
+
/**
|
|
507
|
+
* Actor logic for a text request: an async effect that resolves typed input
|
|
508
|
+
* to typed, schema-validated output via a model call. Built by
|
|
509
|
+
* {@link createTextLogic}; register under `actorSources:` and invoke by name, or
|
|
510
|
+
* bind an executor later with `withExecutor`. The `agent.generateText`/
|
|
511
|
+
* `agent.streamText` builtins and `setupAgent({ requests })` entries are
|
|
512
|
+
* both `TextLogic` under the hood.
|
|
513
|
+
*/
|
|
514
|
+
interface TextLogic<TInputSchema extends StandardSchemaV1 = StandardSchemaV1, TOutputSchema extends StandardSchemaV1 = StandardSchemaV1, TMetadata = Record<string, unknown>> extends AsyncActorLogic<InferOutput<TOutputSchema>, InferOutput<TInputSchema>> {
|
|
515
|
+
readonly kind: "statelyai.textLogic";
|
|
516
|
+
readonly mode: AgentRequestMode;
|
|
517
|
+
readonly schemas: {
|
|
518
|
+
readonly input: TInputSchema;
|
|
519
|
+
readonly output: TOutputSchema;
|
|
520
|
+
};
|
|
521
|
+
request(input: InferOutput<TInputSchema>): AgentTextRequest<TMetadata>;
|
|
522
|
+
execute(input: InferOutput<TInputSchema>, executors: AgentRequestExecutors): Promise<InferOutput<TOutputSchema>>;
|
|
523
|
+
withExecutor(execute: TextLogicExecutor<TInputSchema, TOutputSchema, TMetadata>): TextLogic<TInputSchema, TOutputSchema, TMetadata>;
|
|
524
|
+
}
|
|
525
|
+
/** Extracts a {@link TextLogic}'s validated input type. */
|
|
526
|
+
type TextLogicInput<TLogic extends TextLogic> = TLogic extends TextLogic<infer TInputSchema, StandardSchemaV1, infer _TMetadata> ? InferOutput<TInputSchema> : never;
|
|
527
|
+
/** Extracts a {@link TextLogic}'s validated output type. */
|
|
528
|
+
type TextLogicOutput<TLogic extends TextLogic> = TLogic extends TextLogic<StandardSchemaV1, infer TOutputSchema, infer _TMetadata> ? InferOutput<TOutputSchema> : never;
|
|
529
|
+
/**
|
|
530
|
+
* Creates reusable, standalone {@link TextLogic}: an actor that, when run,
|
|
531
|
+
* resolves typed input to typed output via a model call. Register the
|
|
532
|
+
* result under `actorSources:` and invoke it by name (equivalent to what
|
|
533
|
+
* `setupAgent({ requests })` builds internally for each request entry). Pass
|
|
534
|
+
* `execute` here, or bind it later with `.withExecutor(...)`, a runtime
|
|
535
|
+
* adapter's `machine.provide(...)`, or `runAgent`'s `generateText`/
|
|
536
|
+
* `streamText` options.
|
|
537
|
+
*
|
|
538
|
+
* @example
|
|
539
|
+
* ```ts
|
|
540
|
+
* export const tellJoke = createTextLogic({
|
|
541
|
+
* mode: 'stream',
|
|
542
|
+
* schemas: { input: z.object({ topic: z.string() }), output: z.string() },
|
|
543
|
+
* model: 'openai/gpt-5.4-mini',
|
|
544
|
+
* system: 'You tell short, punchy jokes.',
|
|
545
|
+
* prompt: ({ input }) => `Tell a joke about ${input.topic}.`,
|
|
546
|
+
* });
|
|
547
|
+
* ```
|
|
548
|
+
*/
|
|
549
|
+
declare function createTextLogic<TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetadata = Record<string, unknown>, TModel extends string = string>(config: TextLogicConfig<TInputSchema, TOutputSchema, TMetadata, TModel>, execute?: TextLogicExecutor<TInputSchema, TOutputSchema, TMetadata>): TextLogic<TInputSchema, TOutputSchema, TMetadata>;
|
|
550
|
+
/**
|
|
551
|
+
* Binds a child machine's {@link TextLogic} to a raw
|
|
552
|
+
* {@link AgentRequestExecutor} (the `generateText`/`streamText` shape hosts
|
|
553
|
+
* implement). Encapsulates the `withExecutor` idiom child agents repeat:
|
|
554
|
+
* default the request's `tools` to `{}`, forward the actor `signal`, call the
|
|
555
|
+
* executor, and return its `{ output }` envelope. Use this to share ONE
|
|
556
|
+
* executor across a parent and its nested children.
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```ts
|
|
560
|
+
* childMachine.provide({
|
|
561
|
+
* actorSources: {
|
|
562
|
+
* researchTopic: bindRequestExecutor(setup.requests.researchTopic, generateText),
|
|
563
|
+
* },
|
|
564
|
+
* });
|
|
565
|
+
* ```
|
|
566
|
+
*/
|
|
567
|
+
declare function bindRequestExecutor<TInputSchema extends StandardSchemaV1, TOutputSchema extends StandardSchemaV1, TMetadata>(logic: TextLogic<TInputSchema, TOutputSchema, TMetadata>, executor: AgentRequestExecutor): TextLogic<TInputSchema, TOutputSchema, TMetadata>;
|
|
568
|
+
/**
|
|
569
|
+
* The envelope an {@link AgentRequestExecutor} must return: `{ output }` where
|
|
570
|
+
* `output` is the request's value (a text string or a structured object).
|
|
571
|
+
* Passthrough fields (usage, toolCalls, finishReason, raw, …) are allowed
|
|
572
|
+
* alongside `output` and preserved on the raw result. {@link normalizeGeneratorResult}
|
|
573
|
+
* unwraps `output`; a non-envelope return is a runtime error.
|
|
574
|
+
*/
|
|
575
|
+
type AgentRequestExecutorResult<TOutput = unknown> = {
|
|
576
|
+
output: TOutput;
|
|
577
|
+
[key: string]: unknown;
|
|
578
|
+
};
|
|
579
|
+
/**
|
|
580
|
+
* Optional second argument passed to executors by `runAgent`. The step path
|
|
581
|
+
* (`executeAgentRequest`) never passes this — chunk streaming only exists on
|
|
582
|
+
* the live path, where `onChunk` (§3.1) needs a way to reach the executor.
|
|
583
|
+
*/
|
|
584
|
+
interface AgentRequestExecutorInfo {
|
|
585
|
+
onChunk?: (chunk: string) => void;
|
|
586
|
+
signal?: AbortSignal;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* A raw Vercel AI SDK `generateText` result shape: resolves `{ text }` (a
|
|
590
|
+
* string or a promise of one) instead of the `{ output }`
|
|
591
|
+
* {@link AgentRequestExecutorResult} envelope. Admitted directly as an executor
|
|
592
|
+
* return type so `ai`'s `generateText` passes to `runAgent`/executors without a
|
|
593
|
+
* cast — {@link normalizeGeneratorResult} unwraps `text` at runtime (text-only;
|
|
594
|
+
* structured output is best-effort JSON parsing against the request's
|
|
595
|
+
* `outputSchema`). Extra fields (`content`, `usage`, …) are ignored.
|
|
596
|
+
*/
|
|
597
|
+
type AiSdkShapedTextResult = {
|
|
598
|
+
text: string | PromiseLike<string>;
|
|
599
|
+
[key: string]: unknown;
|
|
600
|
+
};
|
|
601
|
+
/**
|
|
602
|
+
* A raw Vercel AI SDK `streamText` result shape: exposes a `textStream` async
|
|
603
|
+
* iterable of string chunks (and, optionally, a `text` promise for the final
|
|
604
|
+
* text) instead of the `{ output }` {@link AgentRequestExecutorResult} envelope.
|
|
605
|
+
* Admitted directly as an executor return type so `ai`'s `streamText` passes to
|
|
606
|
+
* `runAgent`/executors without a cast — {@link normalizeGeneratorResult}
|
|
607
|
+
* iterates `textStream`, forwarding chunks, then resolves the final text
|
|
608
|
+
* (text-only; structured output is best-effort). Extra fields are ignored.
|
|
609
|
+
*/
|
|
610
|
+
type AiSdkShapedStreamResult = {
|
|
611
|
+
textStream: AsyncIterable<string>;
|
|
612
|
+
text?: PromiseLike<string>;
|
|
613
|
+
[key: string]: unknown;
|
|
614
|
+
};
|
|
615
|
+
/**
|
|
616
|
+
* Host implementation of one text call (`generateText` or `streamText`) —
|
|
617
|
+
* resolves a lowered {@link AgentTextRequest} to an `{ output }` envelope (see
|
|
618
|
+
* {@link AgentRequestExecutorResult}), unwrapped by
|
|
619
|
+
* {@link normalizeGeneratorResult}. The return type is widened to also admit the
|
|
620
|
+
* raw Vercel AI SDK shapes ({@link AiSdkShapedTextResult} /
|
|
621
|
+
* {@link AiSdkShapedStreamResult}) so `ai`'s own `generateText`/`streamText`
|
|
622
|
+
* pass through without a cast; `normalizeGeneratorResult` checks for `{ output }`
|
|
623
|
+
* first, then falls back to those shapes at runtime.
|
|
624
|
+
*/
|
|
625
|
+
type AgentRequestExecutor<TResult extends AgentRequestExecutorResult = AgentRequestExecutorResult> = (request: AgentTextRequest & {
|
|
626
|
+
tools: AgentTools;
|
|
627
|
+
}, info?: AgentRequestExecutorInfo) => PromiseLike<TResult | AiSdkShapedTextResult | AiSdkShapedStreamResult> | TResult | AiSdkShapedTextResult | AiSdkShapedStreamResult;
|
|
628
|
+
/**
|
|
629
|
+
* The full set of host executors a machine's agent actors are resolved
|
|
630
|
+
* with — passed to `runAgent`, `executeAgentRequest`, and
|
|
631
|
+
* `TextLogic.execute`. `generateText` is required; `streamText` is only
|
|
632
|
+
* needed if the machine has a `mode: 'stream'` text request, and `decide`
|
|
633
|
+
* only if it uses a decision — omitting either is a bind-time error when the
|
|
634
|
+
* machine actually needs it (see `runAgent`).
|
|
635
|
+
*/
|
|
636
|
+
interface AgentRequestExecutors<TGenerateResult extends AgentRequestExecutorResult = AgentRequestExecutorResult, TStreamResult extends AgentRequestExecutorResult = AgentRequestExecutorResult> {
|
|
637
|
+
generateText: AgentRequestExecutor<TGenerateResult>;
|
|
638
|
+
streamText?: AgentRequestExecutor<TStreamResult>;
|
|
639
|
+
decide?: AgentDecisionExecutor;
|
|
640
|
+
}
|
|
641
|
+
/** Whether a text request's output is a validated structured object (`'structured'`) or plain text (`'text'`) — derived from the output schema's JSON Schema `type`. */
|
|
642
|
+
type AgentOutputMode = "structured" | "text";
|
|
643
|
+
/**
|
|
644
|
+
* Classifies a text request's output schema as `'structured'` (its JSON
|
|
645
|
+
* Schema is `type: 'object'`, `type: 'array'`, or a top-level union/
|
|
646
|
+
* composition — `anyOf`/`oneOf`/`allOf`, which a bare `z.union`/
|
|
647
|
+
* `z.discriminatedUnion` emits with no top-level `type`) or `'text'`
|
|
648
|
+
* (anything else, including no schema). Reads the schema's
|
|
649
|
+
* `~standard.jsonSchema.input()` extension — schemas without it are treated
|
|
650
|
+
* as `'text'`.
|
|
651
|
+
*/
|
|
652
|
+
declare function getAgentOutputMode(schema?: StandardSchemaV1): AgentOutputMode;
|
|
653
|
+
/** True when {@link getAgentOutputMode} classifies `schema` as `'structured'`. */
|
|
654
|
+
declare function isStructuredOutputSchema(schema?: StandardSchemaV1): boolean;
|
|
655
|
+
/** The unwrapped shape a {@link buildEnvelopeSchema} validate returns: the inner
|
|
656
|
+
* `result` value plus, when opted in and present, the model's `reasoning`. */
|
|
657
|
+
interface StructuredOutputEnvelope {
|
|
658
|
+
result: unknown;
|
|
659
|
+
reasoning?: string;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Builds the uniform structured-output envelope schema every structured request
|
|
663
|
+
* is sent to the provider as: a root object `{ result: <inner> }`, plus — when
|
|
664
|
+
* `options.reasoning` is `true` — an optional string `reasoning` property listed
|
|
665
|
+
* BEFORE `result` (property order nudges the model to reason first). This is THE
|
|
666
|
+
* wire contract for structured output: a root object is universally accepted as
|
|
667
|
+
* a provider response schema, unlike a bare union/array root that many providers
|
|
668
|
+
* reject.
|
|
669
|
+
*
|
|
670
|
+
* The returned {@link StandardSchemaV1} validates the `{ reasoning?, result }`
|
|
671
|
+
* envelope (unwrapping `result` through the original schema, capturing a string
|
|
672
|
+
* `reasoning` when present) and exposes the enveloped JSON Schema. Adapters read
|
|
673
|
+
* `.result` off the provider output before the machine validates it — so this is
|
|
674
|
+
* transparent: user-facing output types stay the declared (un-enveloped) schema,
|
|
675
|
+
* and `reasoning` is surfaced only on the raw executor result, never in machine
|
|
676
|
+
* context/output.
|
|
677
|
+
*/
|
|
678
|
+
declare function buildEnvelopeSchema(inner: StandardSchemaV1, options?: {
|
|
679
|
+
reasoning?: boolean;
|
|
680
|
+
}): StandardSchemaV1<StructuredOutputEnvelope>;
|
|
681
|
+
//#endregion
|
|
682
|
+
export { AgentPlanInput as A, AgentEventDescriptor as B, createTextLogic as C, AgentDecisionExecutor as D, parseOutput as E, DecisionLogicConfig as F, getAcceptedEvents as G, AgentRequestOptions as H, PLAN_DONE_EVENT_TYPE as I, matchesEventPattern as K, ResolveDecisionOptions as L, DecisionAttempt as M, DecisionExhaustedError as N, AgentDecisionInput as O, DecisionLogic as P, renderDecisionAttempts as R, buildEnvelopeSchema as S, isStructuredOutputSchema as T, AgentRequestSource as U, AgentEventToolNameResolver as V, EVENT_TOOL_PREFIX as W, TextLogicExecuteArgs as _, AgentRequestExecutorInfo as a, TextLogicOutput as b, AgentRequestMode as c, AiSdkShapedStreamResult as d, AiSdkShapedTextResult as f, TextLogicConfig as g, TextLogic as h, AgentRequestExecutor as i, AgentPlanOutput as j, AgentDecisionRequest as k, AgentTextRequest as l, StructuredOutputEnvelope as m, AgentModelRef as n, AgentRequestExecutorResult as o, BuiltinAgentActors as p, parseAgentEvent as q, AgentOutputMode as r, AgentRequestExecutors as s, AgentModelMap as t, AgentUserInput as u, TextLogicExecutor as v, getAgentOutputMode as w, bindRequestExecutor as x, TextLogicInput as y, resolveDecision as z };
|