@statelyai/agent 2.0.0-alpha.28 → 2.0.0-alpha.30
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 +150 -27
- package/dist/ai-sdk.d.cts +59 -36
- package/dist/ai-sdk.d.mts +59 -36
- package/dist/ai-sdk.mjs +148 -24
- package/dist/{decision-RQ0iv0oZ.mjs → decision-BHkvuImD.mjs} +74 -8
- package/dist/{decision-CmM8-HHz.cjs → decision-CIb7ddIv.cjs} +113 -30
- package/dist/{text-logic-f5F5sCdc.cjs → event-log-BZRfBRd7.cjs} +814 -7
- package/dist/{text-logic-CIqHAmBi.mjs → event-log-DJCMHek_.mjs} +680 -4
- package/dist/{event-log-store-BIPOz-di.d.mts → event-log-store-CIIJohjj.d.mts} +90 -5
- package/dist/{event-log-store-2xzFmgr2.d.cts → event-log-store-CLAC9q2Y.d.cts} +90 -5
- package/dist/event-log-store-DZR4IIWe.cjs +95 -0
- package/dist/event-log-store-DsP6GCRh.mjs +84 -0
- package/dist/index.cjs +576 -58
- package/dist/index.d.cts +104 -510
- package/dist/index.d.mts +104 -510
- package/dist/index.mjs +547 -32
- package/dist/log.cjs +77 -20
- package/dist/log.d.cts +5 -5
- package/dist/log.d.mts +5 -5
- package/dist/log.mjs +58 -3
- package/dist/machines.cjs +1 -1
- package/dist/machines.d.cts +15 -15
- package/dist/machines.d.mts +15 -15
- package/dist/machines.mjs +1 -1
- package/dist/model-source-BCKg4qJ1.cjs +44 -0
- package/dist/model-source-BaHwJ1wK.mjs +39 -0
- package/dist/openai.cjs +11 -11
- package/dist/openai.d.cts +28 -26
- package/dist/openai.d.mts +28 -26
- package/dist/openai.mjs +3 -3
- package/dist/otel.cjs +5 -4
- package/dist/otel.d.cts +5 -7
- package/dist/otel.d.mts +5 -7
- package/dist/otel.mjs +5 -3
- package/dist/{run-agent-xNTxpt82.mjs → run-agent-BpHqkaZw.mjs} +181 -44
- package/dist/{run-agent-COXXc0RW.d.mts → run-agent-CAVt5R-r.d.mts} +95 -30
- package/dist/{run-agent-ByO-Bxyd.d.cts → run-agent-CTlMc3Jb.d.cts} +95 -30
- package/dist/{run-agent-Dmf8GV2d.cjs → run-agent-ctLCvNgL.cjs} +230 -88
- package/dist/{setup-agent-BuanDXeh.mjs → setup-agent-7rV_cujV.mjs} +15 -9
- package/dist/setup-agent-CGELn1qZ.d.mts +577 -0
- package/dist/setup-agent-CLPCkXsu.d.cts +577 -0
- package/dist/{setup-agent-DV4cTou-.cjs → setup-agent-DoUk7EdC.cjs} +31 -20
- package/dist/tanstack-ai.cjs +627 -0
- package/dist/tanstack-ai.d.cts +204 -0
- package/dist/tanstack-ai.d.mts +204 -0
- package/dist/tanstack-ai.mjs +618 -0
- package/dist/testing.cjs +204 -985
- package/dist/testing.d.cts +132 -347
- package/dist/testing.d.mts +132 -347
- package/dist/testing.mjs +191 -973
- package/dist/{text-logic-IjfYy9DP.d.cts → text-logic-BRYOPWvY.d.mts} +52 -12
- package/dist/{text-logic-D-czVPYp.d.mts → text-logic-DmciuVUQ.d.cts} +52 -12
- package/dist/{types-BgNbNKnJ.d.mts → types-Dp5_Ru4R.d.cts} +2 -2
- package/dist/{types-hR5f5YXa.d.cts → types-Dp5_Ru4R.d.mts} +2 -2
- package/dist/usage-BkM3z02Y.d.mts +17 -0
- package/dist/usage-Cm_ovz9V.d.cts +17 -0
- package/dist/{utils-_q7F-AZu.d.mts → utils-BnXdWih3.d.mts} +1 -2
- package/dist/{utils-o4YRdHJX.d.cts → utils-ebVpCYoF.d.cts} +1 -2
- package/dist/validate.cjs +239 -8
- package/dist/validate.d.cts +110 -3
- package/dist/validate.d.mts +110 -3
- package/dist/validate.mjs +238 -7
- package/dist/verify-COFWyprJ.mjs +1181 -0
- package/dist/verify-CVlsTZ-V.cjs +1222 -0
- package/dist/verify-Cn86rT8l.d.mts +414 -0
- package/dist/verify-Dzwd4Mvk.d.cts +414 -0
- package/package.json +44 -31
- package/readme.md +40 -28
- package/skills/add-evals/SKILL.md +129 -0
- package/skills/add-traces/SKILL.md +135 -0
- package/skills/generate-machine/SKILL.md +143 -69
- package/skills/graph-engineering/SKILL.md +33 -0
- package/skills/improve-machine/SKILL.md +241 -0
- package/skills/improve-machine/reference.md +101 -0
- package/skills/loop-to-machine/SKILL.md +183 -0
- package/skills/loop-to-machine/policy.md +158 -0
- package/dist/event-log-store-2pAFiWuc.mjs +0 -576
- package/dist/event-log-store-C-COhIXP.cjs +0 -702
- package/dist/usage-BdEjFuIi.mjs +0 -5
- package/dist/usage-efOQPdf_.cjs +0 -10
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# A policy machine
|
|
2
|
+
|
|
3
|
+
A policy answers one decision of the environment. It is a `setupAgent` machine, so `describeMachine`, traces, and evals work on it, and `improve-machine` can change it one diff at a time.
|
|
4
|
+
|
|
5
|
+
- **Input:** the facts it reads, the options the environment offered, and the environment's prompt. **Output:** one event, from a final state.
|
|
6
|
+
- **It proposes; the environment disposes.** The environment's guards still judge whatever the policy returns, so the policy needs no copy of the rules to be safe. It may import the environment's schemas, types, constants, and exported guard functions to decide well, and nothing else from it.
|
|
7
|
+
- **Its first version reproduces the current behavior.** When it still asks the model, it passes the environment's `system`, `prompt`, and `metadata.facts` through unchanged, so the model sees what it saw before.
|
|
8
|
+
- **Declare `version`** and bump it on every change. Its `description` is the environment's goal with measurable success criteria; ask the user to confirm it.
|
|
9
|
+
- **Where it lives:** one file next to the environment (`policy.ts`, or `policy/` with its `CHANGELOG.md`), holding the machine, `policyDecider`, and `withPolicy`.
|
|
10
|
+
|
|
11
|
+
## What the environment exports
|
|
12
|
+
|
|
13
|
+
The event schemas and the facts schema, so the policy reuses them instead of redeclaring them. The `agent.decide` input passes the facts as `metadata: { facts }`.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// In the environment file (exported there):
|
|
17
|
+
export const factsSchema = z.object({
|
|
18
|
+
order: z.object({ orderId: z.string(), amount: z.number(), refunded: z.boolean() }).nullable(),
|
|
19
|
+
requestedAmount: z.number().nullable(),
|
|
20
|
+
});
|
|
21
|
+
export const deskEvents = {
|
|
22
|
+
REFUND: z.object({ amount: z.number() }),
|
|
23
|
+
ESCALATE: z.object({}),
|
|
24
|
+
CLOSE: z.object({}),
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## The policy
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { z } from "zod";
|
|
32
|
+
import { runAgent, setupAgent, type AgentDecisionExecutor, type AgentRequestExecutors } from "@statelyai/agent";
|
|
33
|
+
import { deskEvents, factsSchema } from "./desk.js";
|
|
34
|
+
|
|
35
|
+
/** One proposal: an environment event with its `type`. */
|
|
36
|
+
const proposalSchema = z.discriminatedUnion("type", [
|
|
37
|
+
deskEvents.REFUND.extend({ type: z.literal("REFUND") }),
|
|
38
|
+
deskEvents.ESCALATE.extend({ type: z.literal("ESCALATE") }),
|
|
39
|
+
deskEvents.CLOSE.extend({ type: z.literal("CLOSE") }),
|
|
40
|
+
]);
|
|
41
|
+
type Proposal = z.infer<typeof proposalSchema>;
|
|
42
|
+
|
|
43
|
+
const policySetup = setupAgent({
|
|
44
|
+
input: z.object({
|
|
45
|
+
facts: factsSchema,
|
|
46
|
+
options: z.array(proposalSchema),
|
|
47
|
+
// The environment's own prompt, passed through so the model sees what it saw before.
|
|
48
|
+
system: z.string().optional(),
|
|
49
|
+
prompt: z.string().optional(),
|
|
50
|
+
}),
|
|
51
|
+
context: z.object({
|
|
52
|
+
facts: factsSchema,
|
|
53
|
+
options: z.array(proposalSchema),
|
|
54
|
+
system: z.string().optional(),
|
|
55
|
+
prompt: z.string().optional(),
|
|
56
|
+
chosen: proposalSchema.nullable(),
|
|
57
|
+
}),
|
|
58
|
+
output: proposalSchema,
|
|
59
|
+
// Only the events the policy can propose, not every environment event.
|
|
60
|
+
events: { REFUND: deskEvents.REFUND, ESCALATE: deskEvents.ESCALATE, CLOSE: deskEvents.CLOSE },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/** The offered options of one type, as `payloads` entries (`type` removed). */
|
|
64
|
+
const payloadsOf = (options: readonly Proposal[], type: Proposal["type"]) =>
|
|
65
|
+
options.filter((option) => option.type === type).map(({ type: _type, ...payload }) => payload);
|
|
66
|
+
|
|
67
|
+
const offers = (options: readonly Proposal[], type: Proposal["type"]) =>
|
|
68
|
+
options.some((option) => option.type === type);
|
|
69
|
+
|
|
70
|
+
export const policyMachine = policySetup.createMachine({
|
|
71
|
+
id: "resolution-policy",
|
|
72
|
+
version: "1",
|
|
73
|
+
description: "Pick one offered resolution per ticket. Success: the desk's outcome matches the expected outcome.",
|
|
74
|
+
context: ({ input }) => ({ ...input, chosen: null }),
|
|
75
|
+
initial: "checking",
|
|
76
|
+
states: {
|
|
77
|
+
// A rule ported from the old code: an already-refunded order closes, no model call.
|
|
78
|
+
checking: {
|
|
79
|
+
type: "choice",
|
|
80
|
+
choice: ({ context }) =>
|
|
81
|
+
context.facts.order?.refunded && offers(context.options, "CLOSE")
|
|
82
|
+
? { target: "chosen", context: { chosen: { type: "CLOSE" as const } } }
|
|
83
|
+
: { target: "asking" },
|
|
84
|
+
},
|
|
85
|
+
asking: {
|
|
86
|
+
invoke: {
|
|
87
|
+
src: "agent.decide",
|
|
88
|
+
input: ({ context }) => ({
|
|
89
|
+
model: "decider",
|
|
90
|
+
name: "pickResolution",
|
|
91
|
+
system: context.system,
|
|
92
|
+
prompt: context.prompt ?? `Facts: ${JSON.stringify(context.facts)}`,
|
|
93
|
+
allowedEvents: ["REFUND", "ESCALATE", "CLOSE"],
|
|
94
|
+
// Only what the environment offered; `[]` withholds a type.
|
|
95
|
+
payloads: {
|
|
96
|
+
REFUND: payloadsOf(context.options, "REFUND"),
|
|
97
|
+
ESCALATE: payloadsOf(context.options, "ESCALATE"),
|
|
98
|
+
CLOSE: payloadsOf(context.options, "CLOSE"),
|
|
99
|
+
},
|
|
100
|
+
// Same shape as the environment's request, so the model adapter reads the facts unchanged.
|
|
101
|
+
metadata: { facts: context.facts },
|
|
102
|
+
}),
|
|
103
|
+
onError: { target: "gaveUp" },
|
|
104
|
+
},
|
|
105
|
+
on: {
|
|
106
|
+
REFUND: ({ event }) => ({
|
|
107
|
+
target: "chosen",
|
|
108
|
+
context: { chosen: { type: "REFUND" as const, amount: event.amount } },
|
|
109
|
+
}),
|
|
110
|
+
ESCALATE: { target: "chosen", context: { chosen: { type: "ESCALATE" as const } } },
|
|
111
|
+
CLOSE: { target: "chosen", context: { chosen: { type: "CLOSE" as const } } },
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
chosen: { type: "final", output: ({ context }) => context.chosen! },
|
|
115
|
+
gaveUp: { type: "final", output: { type: "ESCALATE" as const } },
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
/** Runs the policy as the environment's decider. */
|
|
120
|
+
export function policyDecider(executors: AgentRequestExecutors): AgentDecisionExecutor {
|
|
121
|
+
return async (request, info) => {
|
|
122
|
+
const result = await runAgent(policyMachine, {
|
|
123
|
+
input: {
|
|
124
|
+
facts: factsSchema.parse(request.metadata?.facts),
|
|
125
|
+
options: (request.options ?? []).map((option) => proposalSchema.parse(option.event)),
|
|
126
|
+
system: request.system,
|
|
127
|
+
prompt: request.prompt,
|
|
128
|
+
},
|
|
129
|
+
executors,
|
|
130
|
+
signal: info?.signal,
|
|
131
|
+
});
|
|
132
|
+
if (result.status !== "done") throw new Error(`policy settled '${result.status}'`);
|
|
133
|
+
return { event: result.output };
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- Every state that invokes `agent.decide` needs an `onError`, or `lintAgentMachine` warns. A policy that cannot choose falls back to the safest event the environment always accepts (here `ESCALATE`).
|
|
139
|
+
- A rule the policy applies without a model is a `choice` state over the facts, checked against what was offered (`offers`), since the environment may have withheld it.
|
|
140
|
+
|
|
141
|
+
## Running it as the environment's decider
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
/** The model's executors, with the policy answering the environment's `chooseResolution`. */
|
|
145
|
+
export function withPolicy(modelExecutors: AgentRequestExecutors): AgentRequestExecutors {
|
|
146
|
+
const decideWithPolicy = policyDecider(modelExecutors);
|
|
147
|
+
return {
|
|
148
|
+
...modelExecutors,
|
|
149
|
+
decide: (request, info) => {
|
|
150
|
+
if (request.name === "chooseResolution") return decideWithPolicy(request, info);
|
|
151
|
+
if (!modelExecutors.decide) throw new Error("no decide executor");
|
|
152
|
+
return modelExecutors.decide(request, info);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Pass `withPolicy(modelExecutors)` as the environment's `executors` in the runner. That one line is the only runner change a policy needs. Decisions with any other name still reach the model.
|