@statelyai/agent 2.0.0-alpha.22 → 2.0.0-alpha.24
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 +53 -25
- package/dist/ai-sdk.d.cts +20 -12
- package/dist/ai-sdk.d.mts +20 -12
- package/dist/ai-sdk.mjs +53 -25
- package/dist/{decision-DxSTqzgZ.mjs → decision-BBZ2jMO1.mjs} +444 -79
- package/dist/{decision-1o45_ZrS.cjs → decision-Cv6SfNWl.cjs} +525 -94
- package/dist/index.cjs +2224 -1032
- package/dist/index.d.cts +413 -275
- package/dist/index.d.mts +413 -275
- package/dist/index.mjs +2163 -983
- package/dist/machines.cjs +30 -2
- package/dist/machines.d.cts +1 -1
- package/dist/machines.d.mts +1 -1
- package/dist/machines.mjs +30 -2
- package/dist/openai.cjs +447 -0
- package/dist/openai.d.cts +177 -0
- package/dist/openai.d.mts +177 -0
- package/dist/openai.mjs +437 -0
- package/dist/otel.cjs +3 -6
- package/dist/otel.d.cts +1 -1
- package/dist/otel.d.mts +1 -1
- package/dist/otel.mjs +3 -6
- package/dist/run-agent-Ck7Sa3Tb.d.mts +968 -0
- package/dist/run-agent-DWqA8KiI.d.cts +968 -0
- package/dist/setup-agent-CeO2fARv.mjs +639 -0
- package/dist/setup-agent-Dl2VELLi.cjs +663 -0
- package/dist/{text-logic-BaxPrcLk.d.cts → text-logic-C7bSnH_B.d.cts} +195 -44
- package/dist/{text-logic-DhfFWzu9.d.mts → text-logic-DJBK3LbG.d.mts} +195 -44
- package/dist/{types-DSdj2tGs.d.cts → types-CjHk5OdH.d.cts} +4 -19
- package/dist/{types-CvWRGFxP.d.mts → types-DWA6X9R-.d.mts} +4 -19
- package/package.json +17 -21
- package/readme.md +32 -17
- package/dist/errors-BQRk9eiZ.d.cts +0 -19
- package/dist/errors-C9rxnWbX.d.mts +0 -19
- package/dist/errors-CeSXQx0v.mjs +0 -23
- package/dist/errors-DUBBzRLP.cjs +0 -28
- package/dist/event-log-store-Bz7HDBkE.d.cts +0 -145
- package/dist/event-log-store-DmIDosD6.mjs +0 -427
- package/dist/event-log-store-a_TKy1gk.cjs +0 -468
- package/dist/event-log-store-hrA1vqtN.d.mts +0 -145
- package/dist/run-agent-0fpEZ1wJ.d.mts +0 -1098
- package/dist/run-agent-Zbkx7XP8.d.cts +0 -1098
- package/dist/setup-agent-DkCTy5Eu.cjs +0 -1707
- package/dist/setup-agent-nSFYrNTP.mjs +0 -1587
- package/dist/sqlite.cjs +0 -129
- package/dist/sqlite.d.cts +0 -57
- package/dist/sqlite.d.mts +0 -57
- package/dist/sqlite.mjs +0 -127
package/readme.md
CHANGED
|
@@ -25,7 +25,19 @@ Stately Agent 2 is in alpha. APIs may change before the stable release.
|
|
|
25
25
|
<!-- install command matching the package prerelease channel and package.json peers -->
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
|
-
pnpm add @statelyai/agent@alpha xstate@alpha zod
|
|
28
|
+
pnpm add @statelyai/agent@alpha xstate@alpha zod
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
For the optional Vercel AI SDK executor:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
pnpm add ai@^7 @ai-sdk/openai@^4
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
For the optional raw OpenAI SDK executor (`@statelyai/agent/openai`):
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
pnpm add openai
|
|
29
41
|
```
|
|
30
42
|
|
|
31
43
|
Requirements:
|
|
@@ -41,17 +53,10 @@ Requirements:
|
|
|
41
53
|
This agent reviews refund requests. The model may propose an automatic refund, but the state machine owns the $100 limit.
|
|
42
54
|
|
|
43
55
|
```ts
|
|
44
|
-
import { openai } from "@ai-sdk/openai";
|
|
45
56
|
import { runAgent, setupAgent } from "@statelyai/agent";
|
|
46
|
-
import { createAiSdkExecutors, defineModels } from "@statelyai/agent/ai-sdk";
|
|
47
57
|
import { z } from "zod";
|
|
48
58
|
|
|
49
|
-
const models = defineModels({
|
|
50
|
-
fast: openai("gpt-5.4-mini"),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
59
|
const agentSetup = setupAgent({
|
|
54
|
-
models,
|
|
55
60
|
context: z.object({
|
|
56
61
|
request: z.string(),
|
|
57
62
|
amount: z.number(),
|
|
@@ -104,7 +109,9 @@ const result = await runAgent(refundMachine, {
|
|
|
104
109
|
request: "I was charged twice for the same order.",
|
|
105
110
|
amount: 75,
|
|
106
111
|
},
|
|
107
|
-
|
|
112
|
+
// An executor is a plain function, so this run needs no API key and no
|
|
113
|
+
// provider package.
|
|
114
|
+
executors: { decide: async () => ({ event: { type: "AUTO_REFUND" } }) },
|
|
108
115
|
});
|
|
109
116
|
|
|
110
117
|
if (result.status === "done") {
|
|
@@ -120,16 +127,21 @@ When the machine reaches `refunded`, the result is:
|
|
|
120
127
|
|
|
121
128
|
The model chooses between the events allowed in `deciding`. The `AUTO_REFUND` transition only works when the amount is at most $100. If the model chooses it for a larger amount, the guard rejects the choice and the decision is tried again.
|
|
122
129
|
|
|
130
|
+
To call a real model, leave the machine unchanged and swap the executors:
|
|
131
|
+
|
|
123
132
|
```ts
|
|
124
|
-
import {
|
|
133
|
+
import { openai } from "@ai-sdk/openai";
|
|
134
|
+
import { createAiSdkExecutors } from "@statelyai/agent/ai-sdk";
|
|
125
135
|
|
|
126
|
-
const
|
|
136
|
+
const liveResult = await runAgent(refundMachine, {
|
|
127
137
|
input: { request: "I was charged twice for the same order.", amount: 75 },
|
|
128
|
-
executors:
|
|
138
|
+
executors: createAiSdkExecutors({ models: { fast: openai("gpt-5.4-mini") } }),
|
|
129
139
|
});
|
|
130
140
|
```
|
|
131
141
|
|
|
132
|
-
|
|
142
|
+
For a machine with several requests, `createScriptedExecutors` holds ordered answers keyed by request name. See [Evals](docs/evals.md#scripted-executors).
|
|
143
|
+
|
|
144
|
+
Passing a `defineModels` registry to `setupAgent({ models })` types the machine's model refs and supplies the AI SDK executor by default; explicit `executors` override it. Core does not import the AI SDK. See [Hosts and executors](docs/hosts.md).
|
|
133
145
|
|
|
134
146
|
## Architecture
|
|
135
147
|
|
|
@@ -147,15 +159,18 @@ The machine never talks to a model directly, so swapping `createAiSdkExecutors`
|
|
|
147
159
|
|
|
148
160
|
The example above has one model decision and two final outcomes. Real machines add approval states, retries, parallel work, child agents, and long-running waits without changing how control flow is represented.
|
|
149
161
|
|
|
150
|
-
The core concepts (machines owning control flow, bounded model decisions, typed requests, host-run executors,
|
|
162
|
+
The core concepts (machines owning control flow, bounded model decisions, typed requests, host-run executors, and native XState snapshots) are in the [documentation overview](docs/index.md).
|
|
151
163
|
|
|
152
164
|
## Examples
|
|
153
165
|
|
|
154
166
|
<!-- starter examples derived from examples/*/metadata.json and examples/index.ts -->
|
|
155
167
|
|
|
156
168
|
- [Twenty Questions](examples/twenty-questions) shows a model choosing legal events in a loop.
|
|
157
|
-
- [
|
|
158
|
-
- [
|
|
169
|
+
- [Chameleon](examples/chameleon) combines hidden information, sequential turns, and a human vote.
|
|
170
|
+
- [Snapshot migration](examples/snapshot-migration) uses XState's native `version` and `migrate` contract.
|
|
171
|
+
- [Portable XState loop](examples/portable-xstate-loop) runs the artifact through native transitions and effects.
|
|
172
|
+
- [Framework-owned storage](examples/file-snapshot-store) persists native XState snapshots in application code.
|
|
173
|
+
- [Tool calling](examples/review-tool-calls) keeps tools and message history in the AI SDK's native format.
|
|
159
174
|
- [Ticket triage](examples/triage) returns structured data from a model request.
|
|
160
175
|
- [JSON agent](examples/json-agent) runs a machine defined as data.
|
|
161
176
|
|
|
@@ -173,7 +188,7 @@ See [all examples](examples/README.md).
|
|
|
173
188
|
- [Hosts and executors](docs/hosts.md)
|
|
174
189
|
- [Models and providers](docs/models-and-providers.md)
|
|
175
190
|
- [Use in any stack](docs/any-stack.md)
|
|
176
|
-
- [
|
|
191
|
+
- [Persistence](docs/persistence.md)
|
|
177
192
|
- [Observability](docs/observability.md)
|
|
178
193
|
- [Usage and budgets](docs/usage-and-budgets.md)
|
|
179
194
|
- [Agent patterns](docs/patterns.md)
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
//#region src/errors.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Base class for every error this package throws. Carries a stable, kebab-case
|
|
4
|
-
* `code` so hosts can branch on the failure without `instanceof` (useful across
|
|
5
|
-
* bundle/realm boundaries and after serialization).
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* catch (error) {
|
|
10
|
-
* if (error instanceof AgentError && error.code === 'agent-idle') { ... }
|
|
11
|
-
* }
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
declare class AgentError extends Error {
|
|
15
|
-
readonly code: string;
|
|
16
|
-
constructor(code: string, message: string, options?: ErrorOptions);
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
19
|
-
export { AgentError as t };
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
//#region src/errors.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Base class for every error this package throws. Carries a stable, kebab-case
|
|
4
|
-
* `code` so hosts can branch on the failure without `instanceof` (useful across
|
|
5
|
-
* bundle/realm boundaries and after serialization).
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* catch (error) {
|
|
10
|
-
* if (error instanceof AgentError && error.code === 'agent-idle') { ... }
|
|
11
|
-
* }
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
declare class AgentError extends Error {
|
|
15
|
-
readonly code: string;
|
|
16
|
-
constructor(code: string, message: string, options?: ErrorOptions);
|
|
17
|
-
}
|
|
18
|
-
//#endregion
|
|
19
|
-
export { AgentError as t };
|
package/dist/errors-CeSXQx0v.mjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
//#region src/errors.ts
|
|
2
|
-
/**
|
|
3
|
-
* Base class for every error this package throws. Carries a stable, kebab-case
|
|
4
|
-
* `code` so hosts can branch on the failure without `instanceof` (useful across
|
|
5
|
-
* bundle/realm boundaries and after serialization).
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* catch (error) {
|
|
10
|
-
* if (error instanceof AgentError && error.code === 'agent-idle') { ... }
|
|
11
|
-
* }
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
var AgentError = class extends Error {
|
|
15
|
-
code;
|
|
16
|
-
constructor(code, message, options) {
|
|
17
|
-
super(message, options);
|
|
18
|
-
this.name = "AgentError";
|
|
19
|
-
this.code = code;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
//#endregion
|
|
23
|
-
export { AgentError as t };
|
package/dist/errors-DUBBzRLP.cjs
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
//#region src/errors.ts
|
|
2
|
-
/**
|
|
3
|
-
* Base class for every error this package throws. Carries a stable, kebab-case
|
|
4
|
-
* `code` so hosts can branch on the failure without `instanceof` (useful across
|
|
5
|
-
* bundle/realm boundaries and after serialization).
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* catch (error) {
|
|
10
|
-
* if (error instanceof AgentError && error.code === 'agent-idle') { ... }
|
|
11
|
-
* }
|
|
12
|
-
* ```
|
|
13
|
-
*/
|
|
14
|
-
var AgentError = class extends Error {
|
|
15
|
-
code;
|
|
16
|
-
constructor(code, message, options) {
|
|
17
|
-
super(message, options);
|
|
18
|
-
this.name = "AgentError";
|
|
19
|
-
this.code = code;
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
//#endregion
|
|
23
|
-
Object.defineProperty(exports, "AgentError", {
|
|
24
|
-
enumerable: true,
|
|
25
|
-
get: function() {
|
|
26
|
-
return AgentError;
|
|
27
|
-
}
|
|
28
|
-
});
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { t as AgentError } from "./errors-BQRk9eiZ.cjs";
|
|
2
|
-
import { EventObject } from "xstate";
|
|
3
|
-
|
|
4
|
-
//#region src/event-log-store-conformance.d.ts
|
|
5
|
-
/** Produces a fresh, empty store for one assertion. */
|
|
6
|
-
type CreateStore = () => Promise<AgentEventLogStore> | AgentEventLogStore;
|
|
7
|
-
/**
|
|
8
|
-
* Validates a store against the reference's semantics: empty read + zero length
|
|
9
|
-
* for unknown threads; single and multi-entry append; contiguity misuse guard;
|
|
10
|
-
* stale-`expectedIndex` conflict with correct fields; an interleaved concurrent
|
|
11
|
-
* append race (exactly one winner); event-id uniqueness; `read({ from })`
|
|
12
|
-
* incremental correctness; thread isolation; metadata round-trip; deep-copy
|
|
13
|
-
* isolation on append and read; and the full fork contract.
|
|
14
|
-
*/
|
|
15
|
-
declare function assertEventLogStoreConformance(create: CreateStore): Promise<void>;
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/event-log-store.d.ts
|
|
18
|
-
/** The durable replay-entry envelope version. */
|
|
19
|
-
declare const AGENT_EVENT_SCHEMA_VERSION: 1;
|
|
20
|
-
/** Values that round-trip through JSON without adapters or silent coercion. */
|
|
21
|
-
type JsonValue = null | boolean | number | string | JsonValue[] | {
|
|
22
|
-
[key: string]: JsonValue;
|
|
23
|
-
};
|
|
24
|
-
interface AgentLogVerification {
|
|
25
|
-
/** Hash of the logical machine projection after this entry is applied. */
|
|
26
|
-
stateHash: string;
|
|
27
|
-
/** Hash of the serializable effects owed at that frontier. */
|
|
28
|
-
effectsHash: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* One journaled entry: an EXTERNAL input to the machine — an effect completion
|
|
32
|
-
* (a `done`/`error` event carrying its output inline), a user-sent event, or a
|
|
33
|
-
* timer firing. Never a raised/internal event: deterministic replay re-derives
|
|
34
|
-
* those from the machine's own logic, so journaling them would double-apply.
|
|
35
|
-
* JSON-safe, stored verbatim.
|
|
36
|
-
*/
|
|
37
|
-
interface AgentLogEntry {
|
|
38
|
-
/** Version of this outer envelope, independent of the machine event type. */
|
|
39
|
-
schemaVersion: typeof AGENT_EVENT_SCHEMA_VERSION;
|
|
40
|
-
/** Stable identity within the thread. Forked prefixes retain their ids. */
|
|
41
|
-
id: string;
|
|
42
|
-
/** 0-based position in the thread's log. */
|
|
43
|
-
index: number;
|
|
44
|
-
/** RFC 3339 wall-clock time when the host accepted the entry. Metadata only. */
|
|
45
|
-
recordedAt: string;
|
|
46
|
-
/** The authored XState machine id. */
|
|
47
|
-
machineId: string;
|
|
48
|
-
/** Explicit version or structural hash of the machine that accepted the event. */
|
|
49
|
-
machineVersion: string;
|
|
50
|
-
event: EventObject;
|
|
51
|
-
/** Optional causal parent entry id, scoped to the same thread. */
|
|
52
|
-
causationId?: string;
|
|
53
|
-
/** Optional host-owned correlation id spanning threads/runs. */
|
|
54
|
-
correlationId?: string;
|
|
55
|
-
/** Recorded projection hashes used by strict replay verification. */
|
|
56
|
-
verification?: AgentLogVerification;
|
|
57
|
-
/** Host-owned, JSON-safe; stored verbatim, never interpreted. */
|
|
58
|
-
metadata?: Record<string, JsonValue>;
|
|
59
|
-
}
|
|
60
|
-
/** A precise failure when an entry would not survive a JSON round-trip. */
|
|
61
|
-
declare class NonSerializableAgentEventError extends AgentError {
|
|
62
|
-
readonly path: string;
|
|
63
|
-
readonly valueType: string;
|
|
64
|
-
constructor(path: string, valueType: string);
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Rejects values JSON would drop or coerce. Unlike `JSON.stringify`, this does
|
|
68
|
-
* not silently erase `undefined`/functions or turn non-finite numbers into
|
|
69
|
-
* `null`; durable entries contain only plain JSON values.
|
|
70
|
-
*/
|
|
71
|
-
declare function assertJsonSerializable(value: unknown, path?: string, ancestors?: WeakSet<object>): asserts value is JsonValue;
|
|
72
|
-
/** Validates the complete durable envelope before append/export/replay. */
|
|
73
|
-
declare function assertAgentLogEntry(entry: unknown): asserts entry is AgentLogEntry;
|
|
74
|
-
/**
|
|
75
|
-
* An append-only event log: the authoritative durability artifact of a thread.
|
|
76
|
-
* The journal of external inputs IS the source of truth — deterministic machine
|
|
77
|
-
* replay derives every snapshot from it, a fork is a copied log prefix, and the
|
|
78
|
-
* type-only {@link AgentSnapshotStore} is a mere idle-point compaction cache
|
|
79
|
-
* over what the log already implies.
|
|
80
|
-
*
|
|
81
|
-
* Userland stores (a Postgres table with a `(thread_id, index)` primary key, an
|
|
82
|
-
* append-only object in blob storage, …) implement this one shape so they
|
|
83
|
-
* interoperate; {@link createInMemoryEventLogStore} is the in-memory reference.
|
|
84
|
-
*/
|
|
85
|
-
interface AgentEventLogStore {
|
|
86
|
-
/**
|
|
87
|
-
* Append `entries` starting at `expectedIndex` (the current length of the
|
|
88
|
-
* thread's log; 0 for a new thread). Atomic — all entries land or none do.
|
|
89
|
-
* Rejects with {@link AgentEventLogConflictError} when the thread's length
|
|
90
|
-
* differs from `expectedIndex`: a concurrent writer appended first. Each
|
|
91
|
-
* entry's `index` must be contiguous from `expectedIndex` (a plain `Error`
|
|
92
|
-
* otherwise: that is caller misuse, not a race).
|
|
93
|
-
*/
|
|
94
|
-
append(input: {
|
|
95
|
-
threadId: string;
|
|
96
|
-
expectedIndex: number;
|
|
97
|
-
entries: AgentLogEntry[];
|
|
98
|
-
}): Promise<void>;
|
|
99
|
-
/**
|
|
100
|
-
* Read a thread's entries in log order. `from` (default 0) skips entries
|
|
101
|
-
* below that index for incremental catch-up. An unknown thread reads as an
|
|
102
|
-
* empty array.
|
|
103
|
-
*/
|
|
104
|
-
read(threadId: string, options?: {
|
|
105
|
-
from?: number;
|
|
106
|
-
}): Promise<AgentLogEntry[]>;
|
|
107
|
-
/** The thread's current log length (0 for an unknown thread) — the next `expectedIndex`. */
|
|
108
|
-
length(threadId: string): Promise<number>;
|
|
109
|
-
/**
|
|
110
|
-
* Copy the prefix `[0, upToIndex)` onto a fresh, empty `newThreadId`.
|
|
111
|
-
* Without `upToIndex` the full source is copied. The fork then appends
|
|
112
|
-
* independently. Rejects (plain `Error`) if `newThreadId` already has
|
|
113
|
-
* entries, the source is unknown, or `upToIndex` is out of range.
|
|
114
|
-
* Implementations may copy-on-write or physically copy; observable behavior
|
|
115
|
-
* must match a full copy.
|
|
116
|
-
*/
|
|
117
|
-
fork(input: {
|
|
118
|
-
threadId: string;
|
|
119
|
-
newThreadId: string; /** Exclusive index cutoff. */
|
|
120
|
-
upToIndex?: number;
|
|
121
|
-
}): Promise<void>;
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Rejection from {@link AgentEventLogStore.append} when the thread's stored
|
|
125
|
-
* length is not the `expectedIndex` the writer held — a concurrent writer
|
|
126
|
-
* appended first. `actualIndex` is the next index the store would accept.
|
|
127
|
-
*/
|
|
128
|
-
declare class AgentEventLogConflictError extends AgentError {
|
|
129
|
-
readonly threadId: string;
|
|
130
|
-
readonly expectedIndex: number;
|
|
131
|
-
readonly actualIndex: number;
|
|
132
|
-
constructor(threadId: string, expectedIndex: number, actualIndex: number);
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* In-memory reference store, and the baseline the conformance suite runs
|
|
136
|
-
* against. Per-thread entries are held in a contiguous, index-ordered list;
|
|
137
|
-
* append's check-and-push runs synchronously (no `await` between reading the
|
|
138
|
-
* length and writing), so two appends racing on the same `expectedIndex`
|
|
139
|
-
* resolve to exactly one winner. Every stored and returned entry is
|
|
140
|
-
* `structuredClone`d, so a caller can neither mutate stored state through a
|
|
141
|
-
* value it appended nor through a value it read.
|
|
142
|
-
*/
|
|
143
|
-
declare function createInMemoryEventLogStore(): AgentEventLogStore;
|
|
144
|
-
//#endregion
|
|
145
|
-
export { AgentLogVerification as a, assertAgentLogEntry as c, assertEventLogStoreConformance as d, AgentLogEntry as i, assertJsonSerializable as l, AgentEventLogConflictError as n, JsonValue as o, AgentEventLogStore as r, NonSerializableAgentEventError as s, AGENT_EVENT_SCHEMA_VERSION as t, createInMemoryEventLogStore as u };
|