@statelyai/agent 2.0.0-alpha.15 → 2.0.0-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/ai-sdk.cjs +1 -1
  2. package/dist/ai-sdk.d.cts +2 -2
  3. package/dist/ai-sdk.d.mts +2 -2
  4. package/dist/ai-sdk.mjs +1 -1
  5. package/dist/{decision-D9Zi7Xi5.mjs → decision-C11xuud2.mjs} +35 -26
  6. package/dist/{decision-C0cUKvNt.cjs → decision-DnQCQPew.cjs} +46 -31
  7. package/dist/{event-log-store-D7pWtIhb.mjs → event-log-store-B-1fcfkT.mjs} +149 -141
  8. package/dist/{event-log-store-BkUNtyOF.d.mts → event-log-store-BrC9Q1xW.d.mts} +14 -12
  9. package/dist/{event-log-store-CVd2eyRy.d.cts → event-log-store-CQJq8_v4.d.cts} +14 -12
  10. package/dist/{event-log-store-CNT_7F0V.cjs → event-log-store-yquOV1TX.cjs} +148 -140
  11. package/dist/index.cjs +498 -520
  12. package/dist/index.d.cts +130 -104
  13. package/dist/index.d.mts +130 -104
  14. package/dist/index.mjs +497 -519
  15. package/dist/machines.cjs +1 -1
  16. package/dist/machines.d.cts +1 -1
  17. package/dist/machines.d.mts +1 -1
  18. package/dist/machines.mjs +1 -1
  19. package/dist/otel.d.cts +1 -1
  20. package/dist/otel.d.mts +1 -1
  21. package/dist/{run-agent-B_n4Qxye.d.cts → run-agent-BxjGaVpL.d.cts} +49 -109
  22. package/dist/{run-agent-BWzo4FLv.d.mts → run-agent-COHoCgQd.d.mts} +49 -109
  23. package/dist/{setup-agent-DeHRW-qX.mjs → setup-agent-CTg57Pa4.mjs} +154 -167
  24. package/dist/{setup-agent-CpK0ZRWV.cjs → setup-agent-D_EyJ0Ik.cjs} +159 -172
  25. package/dist/sqlite.cjs +1 -1
  26. package/dist/sqlite.d.cts +2 -2
  27. package/dist/sqlite.d.mts +2 -2
  28. package/dist/sqlite.mjs +1 -1
  29. package/dist/{text-logic-DZW7XWy9.d.cts → text-logic-BFX5q7fM.d.cts} +23 -2
  30. package/dist/{text-logic-C7anC7qX.d.mts → text-logic-DQW8_DWW.d.mts} +23 -2
  31. package/dist/{types-DFD28AWe.d.cts → types-DYpK3QF4.d.mts} +7 -6
  32. package/dist/{types-CTBhMnFu.d.mts → types-pJ5Hn8fv.d.cts} +7 -6
  33. package/package.json +28 -28
  34. package/readme.md +6 -19
  35. package/schemas/agent-workflow.json +9 -4
@@ -1,4 +1,4 @@
1
- import { a as AgentToolChoice, c as AgentTools, d as ChosenEvent, g as InferOutput, l as AllowedEvents, n as AgentMessage, v as StandardSchemaV1 } from "./types-CTBhMnFu.mjs";
1
+ import { a as AgentToolChoice, c as AgentTools, d as ChosenEvent, g as InferOutput, l as AllowedEvents, n as AgentMessage, v as StandardSchemaV1 } from "./types-DYpK3QF4.mjs";
2
2
  import { t as AgentError } from "./errors-C9rxnWbX.mjs";
3
3
  import { AnyMachineSnapshot, AsyncActorLogic, EventObject, MachineSnapshot } from "xstate";
4
4
 
@@ -389,6 +389,27 @@ interface AgentUsage {
389
389
  }
390
390
  /** One model call's reported usage — {@link AgentUsage} without the run-level `modelCalls` count. What an executor puts on its result's `usage` field. */
391
391
  type AgentCallUsage = Omit<AgentUsage, "modelCalls">;
392
+ /**
393
+ * Reads a settled call's per-call {@link AgentCallUsage} off a RAW executor
394
+ * result's `usage` field, keeping only finite numbers — the same normalization
395
+ * `runAgent` applies before it delivers `'@agent.usage'`. Returns `undefined`
396
+ * when the result reports no usage at all. Works for our `{ output, usage }`
397
+ * envelope, for a raw Vercel AI SDK result (its `LanguageModelUsage` carries
398
+ * the same flat field names), and for any custom executor that follows the
399
+ * shape.
400
+ *
401
+ * The seam for the step-loop path, where the host holds the raw result itself:
402
+ *
403
+ * ```ts
404
+ * const { output, raw } = await executeAgentRequest(effect, executors);
405
+ * const usage = getCallUsage(raw);
406
+ * if (usage) append({ type: AGENT_USAGE_EVENT_TYPE, usage }); // journal + transition, like any event
407
+ * append(effect.toDoneEvent(output));
408
+ * ```
409
+ *
410
+ * See "Token usage on this path" in docs/steps.md for the full loop.
411
+ */
412
+ declare function getCallUsage(raw: unknown): AgentCallUsage | undefined;
392
413
  /**
393
414
  * Inline input for the `agent.userInput` builtin actor — a human-input request
394
415
  * (CLI prompt, chat reply, …) that resolves to the `string` the human typed.
@@ -704,4 +725,4 @@ declare function buildEnvelopeSchema(inner: StandardSchemaV1, options?: {
704
725
  */
705
726
  declare function parseStructuredEnvelope(request: Pick<AgentTextRequest, "outputSchema" | "reasoning">, value: unknown): StructuredOutputEnvelope;
706
727
  //#endregion
707
- export { AgentDecisionExhaustedError as A, AgentRequestOptions as B, buildEnvelopeSchema as C, parseOutput as D, parseModelRef as E, ResolveDecisionOptions as F, getAcceptedEvents as H, renderDecisionAttempts as I, resolveDecision as L, AgentDecisionRequest as M, DecisionAttempt as N, parseStructuredEnvelope as O, DecisionLogicConfig as P, AgentEventDescriptor as R, bindRequestExecutor as S, getAgentOutputMode as T, parseAgentEvent as U, AgentRequestSource as V, StructuredOutputEnvelope as _, AgentOutputMode as a, TextLogicExecuteArgs as b, AgentRequestExecutorResult as c, AgentTextRequest as d, AgentUsage as f, BuiltinAgentActors as g, AiSdkShapedTextResult as h, AgentModelRef as i, AgentDecisionInput as j, AgentDecisionExecutor as k, AgentRequestExecutors as l, AiSdkShapedStreamResult as m, AgentExecutorTextRequest as n, AgentRequestExecutor as o, AgentUserInput as p, AgentModelMap as r, AgentRequestExecutorInfo as s, AgentCallUsage as t, AgentRequestMode as u, TextLogic as v, createTextLogic as w, TextLogicExecutor as x, TextLogicConfig as y, AgentEventToolNameResolver as z };
728
+ export { AgentDecisionExecutor as A, AgentEventToolNameResolver as B, buildEnvelopeSchema as C, parseModelRef as D, getCallUsage as E, DecisionLogicConfig as F, AgentRequestSource as H, ResolveDecisionOptions as I, renderDecisionAttempts as L, AgentDecisionInput as M, AgentDecisionRequest as N, parseOutput as O, DecisionAttempt as P, resolveDecision as R, bindRequestExecutor as S, getAgentOutputMode as T, getAcceptedEvents as U, AgentRequestOptions as V, parseAgentEvent as W, StructuredOutputEnvelope as _, AgentOutputMode as a, TextLogicExecuteArgs as b, AgentRequestExecutorResult as c, AgentTextRequest as d, AgentUsage as f, BuiltinAgentActors as g, AiSdkShapedTextResult as h, AgentModelRef as i, AgentDecisionExhaustedError as j, parseStructuredEnvelope as k, AgentRequestExecutors as l, AiSdkShapedStreamResult as m, AgentExecutorTextRequest as n, AgentRequestExecutor as o, AgentUserInput as p, AgentModelMap as r, AgentRequestExecutorInfo as s, AgentCallUsage as t, AgentRequestMode as u, TextLogic as v, createTextLogic as w, TextLogicExecutor as x, TextLogicConfig as y, AgentEventDescriptor as z };
@@ -184,13 +184,14 @@ type ToolMessage = {
184
184
  */
185
185
  type AgentMessage = SystemMessage | UserMessage | AssistantMessage | ToolMessage;
186
186
  /**
187
- * A schema value on an {@link AgentToolDescriptor}. Core reads it as a
188
- * {@link StandardSchemaV1} (via `getJsonSchema`/`isStandardSchema`) when it can,
189
- * but the type is deliberately widened with `object` so an SDK-native tool —
190
- * whose `inputSchema` is the SDK's own union type (a Zod schema, the SDK's
191
- * `Schema`, a lazy thunk, …) assigns structurally with no cast.
187
+ * A schema value on an {@link AgentToolDescriptor}: deliberately just `object`,
188
+ * because an SDK-native tool's `inputSchema` is the SDK's own union type (a Zod
189
+ * schema, the SDK's `Schema`, a lazy thunk, ...) and must assign structurally
190
+ * with no cast. The contract is runtime, not static: core narrows with
191
+ * `isStandardSchema` and reads {@link StandardSchemaV1} schemas via
192
+ * `getJsonSchema`; anything else passes through to the executor untouched.
192
193
  */
193
- type AgentToolSchema = StandardSchemaV1 | object;
194
+ type AgentToolSchema = object;
194
195
  /**
195
196
  * A tool exposed to a text request, described for both the model and
196
197
  * (optionally) host execution. This is a **minimal structural contract**: any
@@ -184,13 +184,14 @@ type ToolMessage = {
184
184
  */
185
185
  type AgentMessage = SystemMessage | UserMessage | AssistantMessage | ToolMessage;
186
186
  /**
187
- * A schema value on an {@link AgentToolDescriptor}. Core reads it as a
188
- * {@link StandardSchemaV1} (via `getJsonSchema`/`isStandardSchema`) when it can,
189
- * but the type is deliberately widened with `object` so an SDK-native tool —
190
- * whose `inputSchema` is the SDK's own union type (a Zod schema, the SDK's
191
- * `Schema`, a lazy thunk, …) assigns structurally with no cast.
187
+ * A schema value on an {@link AgentToolDescriptor}: deliberately just `object`,
188
+ * because an SDK-native tool's `inputSchema` is the SDK's own union type (a Zod
189
+ * schema, the SDK's `Schema`, a lazy thunk, ...) and must assign structurally
190
+ * with no cast. The contract is runtime, not static: core narrows with
191
+ * `isStandardSchema` and reads {@link StandardSchemaV1} schemas via
192
+ * `getJsonSchema`; anything else passes through to the executor untouched.
192
193
  */
193
- type AgentToolSchema = StandardSchemaV1 | object;
194
+ type AgentToolSchema = object;
194
195
  /**
195
196
  * A tool exposed to a text request, described for both the model and
196
197
  * (optionally) host execution. This is a **minimal structural contract**: any
package/package.json CHANGED
@@ -1,7 +1,28 @@
1
1
  {
2
2
  "name": "@statelyai/agent",
3
- "version": "2.0.0-alpha.15",
3
+ "version": "2.0.0-alpha.17",
4
4
  "description": "Make invalid agent actions impossible. Agent logic as state machines: deterministic, inspectable, resumable, runs anywhere.",
5
+ "keywords": [
6
+ "agent",
7
+ "ai",
8
+ "state machine",
9
+ "statechart"
10
+ ],
11
+ "homepage": "https://github.com/statelyai/agent#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/statelyai/agent/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": "David Khourshid <david@stately.ai>",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/statelyai/agent.git"
20
+ },
21
+ "files": [
22
+ "dist",
23
+ "schemas",
24
+ "skills"
25
+ ],
5
26
  "type": "module",
6
27
  "main": "dist/index.cjs",
7
28
  "module": "dist/index.mjs",
@@ -59,29 +80,8 @@
59
80
  },
60
81
  "./agent-workflow.json": "./schemas/agent-workflow.json"
61
82
  },
62
- "files": [
63
- "dist",
64
- "schemas",
65
- "skills"
66
- ],
67
- "keywords": [
68
- "ai",
69
- "state machine",
70
- "agent",
71
- "statechart"
72
- ],
73
- "author": "David Khourshid <david@stately.ai>",
74
- "license": "MIT",
75
- "repository": {
76
- "type": "git",
77
- "url": "git+https://github.com/statelyai/agent.git"
78
- },
79
- "homepage": "https://github.com/statelyai/agent#readme",
80
- "bugs": {
81
- "url": "https://github.com/statelyai/agent/issues"
82
- },
83
- "engines": {
84
- "node": ">=22.18.0"
83
+ "publishConfig": {
84
+ "access": "public"
85
85
  },
86
86
  "devDependencies": {
87
87
  "@ai-sdk/openai": "^3.0.25",
@@ -124,9 +124,6 @@
124
124
  "xstate": "6.0.0-alpha.25",
125
125
  "zod": "^4.3.6"
126
126
  },
127
- "publishConfig": {
128
- "access": "public"
129
- },
130
127
  "peerDependencies": {
131
128
  "@opentelemetry/api": "^1",
132
129
  "ai": "^6.0.67",
@@ -140,6 +137,9 @@
140
137
  "optional": true
141
138
  }
142
139
  },
140
+ "engines": {
141
+ "node": ">=22.18.0"
142
+ },
143
143
  "scripts": {
144
144
  "build": "tsdown",
145
145
  "demo": "pnpm --filter @statelyai/agent-demo dev",
@@ -148,7 +148,7 @@
148
148
  "typecheck": "pnpm run typecheck:src && pnpm run typecheck:examples && pnpm run typecheck:example-packages",
149
149
  "typecheck:src": "tsc --noEmit",
150
150
  "typecheck:examples": "tsc -p examples/tsconfig.json --noEmit",
151
- "typecheck:example-packages": "tsc -p examples/next-host --noEmit && tsc -p examples/tanstack-start-host --noEmit && tsc -p examples/tanstack-ai-stream --noEmit && tsc -p examples/cloudflare-agent-host --noEmit && tsc -p examples/cloudflare-workers-ai-host --noEmit",
151
+ "typecheck:example-packages": "pnpm run build && tsc -p examples/next-host --noEmit && tsc -p examples/tanstack-start-host --noEmit && tsc -p examples/tanstack-ai-stream --noEmit && tsc -p examples/cloudflare-agent-host --noEmit && tsc -p examples/cloudflare-workers-ai-host --noEmit",
152
152
  "test:cloudflare": "pnpm --filter @statelyai/example-cloudflare-agent-host test && pnpm --filter @statelyai/example-cloudflare-workers-ai-host test",
153
153
  "lint": "oxlint",
154
154
  "format": "oxfmt src examples",
package/readme.md CHANGED
@@ -17,7 +17,7 @@ Stately Agent 2 is in alpha. APIs may change before the stable release.
17
17
  ## Three starting points
18
18
 
19
19
  - **Author a new agent.** Build a machine from states, decisions, and typed requests; run it locally with `runAgent`, test it with no API key, then use it in any framework or runtime with zero machine changes. See the [Quickstart](docs/quickstart.md) and [Use in any stack](docs/any-stack.md).
20
- - **Retrofit an existing agent.** Turn a `while` loop into a machine: your SDK calls, tools, and retry code become the executors; the machine replaces only the control flow. See [Migrating from a loop](docs/from-a-loop.md).
20
+ - **Retrofit an existing agent.** Turn a `while` loop into a machine: your SDK calls, tools, and retry code become the executors; the machine replaces only the control flow. See [Migrating from a hand-rolled loop](docs/from-a-loop.md).
21
21
  - **Copy a known pattern.** ReAct, reflection, plan-and-execute, RAG, supervisor, and more, each a single runnable file you lift in 60 seconds. See [Agent patterns](docs/patterns.md).
22
22
 
23
23
  ## Install
@@ -120,8 +120,6 @@ When the machine reaches `refunded`, the result is:
120
120
 
121
121
  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
122
 
123
- `createScriptedExecutors` plays back canned answers through the same executor contract, so the machine above runs end to end before a model is involved. **No API key needed:**
124
-
125
123
  ```ts
126
124
  import { createScriptedExecutors } from "@statelyai/agent";
127
125
 
@@ -131,7 +129,7 @@ const result = await runAgent(refundMachine, {
131
129
  });
132
130
  ```
133
131
 
134
- Swap in `createAiSdkExecutors({ models })` when you want a real model. The scripted set is what your tests keep using.
132
+ Scripted executors run the machine above end to end with no API key; swap in `createAiSdkExecutors({ models })` for a real model. See [Hosts and executors](docs/hosts.md).
135
133
 
136
134
  ## Architecture
137
135
 
@@ -149,18 +147,7 @@ The machine never talks to a model directly, so swapping `createAiSdkExecutors`
149
147
 
150
148
  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.
151
149
 
152
- ## Core concepts
153
-
154
- <!-- core concepts derived from setupAgent, built-in agent actors, runAgent, and XState snapshots -->
155
-
156
- - **Machines own control flow.** States, events, transitions, and guards define what can happen.
157
- - **Models make bounded decisions.** `agent.decide` asks a model to choose one of the events accepted by the current state.
158
- - **Requests are typed.** Inputs, outputs, context, and events use Standard Schema. Zod works out of the box.
159
- - **Your code runs the model.** `runAgent` accepts executor functions. The example uses the Vercel AI SDK adapter, but the machine does not depend on a provider.
160
- - **Snapshots can be stored.** An agent can stop for human input, save its XState snapshot, and resume later in another process.
161
- - **Runs export verified replay entries.** Every `runAgent` result carries a JSON-safe `AgentLogEntry[]` with event identity, timestamp, machine version, and state/effect hashes; pass it to `replay` or `verifyReplay` without repeating model or tool calls.
162
- - **Machines can be checked without model calls.** Lint their structure, simulate scripted decisions, and explore paths without an API key.
163
- - **Agents are XState machines.** Guards, actors, parallel states, inspection, testing, and visualization work as usual.
150
+ The core concepts (machines owning control flow, bounded model decisions, typed requests, host-run executors, storable snapshots, verified replay entries) are in the [documentation overview](docs/index.md).
164
151
 
165
152
  ## Examples
166
153
 
@@ -174,7 +161,7 @@ The example above has one model decision and two final outcomes. Real machines a
174
161
 
175
162
  See [all examples](examples/README.md).
176
163
 
177
- ## Learn more
164
+ ## Related
178
165
 
179
166
  - [Machines](docs/machines.md)
180
167
  - [Text requests](docs/text-requests.md)
@@ -190,5 +177,5 @@ See [all examples](examples/README.md).
190
177
  - [Observability](docs/observability.md)
191
178
  - [Usage and budgets](docs/usage-and-budgets.md)
192
179
  - [Agent patterns](docs/patterns.md)
193
- - [Migrating from a loop](docs/from-a-loop.md)
194
- - [LangGraph vs agent machines](docs/langgraph-comparison.md)
180
+ - [Migrating from a hand-rolled loop](docs/from-a-loop.md)
181
+ - [Coming from LangGraph](docs/langgraph-comparison.md)
@@ -71,6 +71,14 @@
71
71
  "$ref": "#/$defs/State"
72
72
  }
73
73
  },
74
+ "suspendedTags": {
75
+ "description": "State tags that mark an intentional wait for an external event (a human approval, an inbound webhook, ...). Lowered by setupAgent.fromConfig(...) into a snapshot.hasTag(...) suspension predicate so runAgent settles those states idle deterministically. Every listed tag must appear in some state's 'tags'.",
76
+ "type": "array",
77
+ "items": {
78
+ "type": "string",
79
+ "minLength": 1
80
+ }
81
+ },
74
82
  "meta": {
75
83
  "$ref": "#/$defs/JsonObject"
76
84
  }
@@ -483,10 +491,7 @@
483
491
  },
484
492
  "guard": {
485
493
  "description": "Either a whole-string {{ }} expression evaluated as truthy/falsy, or a named guard reference resolved against the `guards` passed to setupAgent.fromConfig(config, { guards }). Object guards ({ type, params }) are rejected by the lowering.",
486
- "anyOf": [
487
- { "$ref": "#/$defs/ExpressionString" },
488
- { "$ref": "#/$defs/Identifier" }
489
- ]
494
+ "anyOf": [{ "$ref": "#/$defs/ExpressionString" }, { "$ref": "#/$defs/Identifier" }]
490
495
  },
491
496
  "assign": {
492
497
  "description": "Context assignments applied when this transition is taken.",