@eduardorenani/atlasjs 0.1.0-alpha.0
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 +201 -0
- package/README.md +113 -0
- package/dist/actorName.d.ts +2 -0
- package/dist/actorName.d.ts.map +1 -0
- package/dist/actorName.js +24 -0
- package/dist/actorName.js.map +1 -0
- package/dist/buildActions.d.ts +11 -0
- package/dist/buildActions.d.ts.map +1 -0
- package/dist/buildActions.js +23 -0
- package/dist/buildActions.js.map +1 -0
- package/dist/buildActiveState.d.ts +43 -0
- package/dist/buildActiveState.d.ts.map +1 -0
- package/dist/buildActiveState.js +194 -0
- package/dist/buildActiveState.js.map +1 -0
- package/dist/buildActors.d.ts +4 -0
- package/dist/buildActors.d.ts.map +1 -0
- package/dist/buildActors.js +40 -0
- package/dist/buildActors.js.map +1 -0
- package/dist/buildPassiveState.d.ts +19 -0
- package/dist/buildPassiveState.d.ts.map +1 -0
- package/dist/buildPassiveState.js +59 -0
- package/dist/buildPassiveState.js.map +1 -0
- package/dist/compile.d.ts +6 -0
- package/dist/compile.d.ts.map +1 -0
- package/dist/compile.js +164 -0
- package/dist/compile.js.map +1 -0
- package/dist/contextLift.d.ts +35 -0
- package/dist/contextLift.d.ts.map +1 -0
- package/dist/contextLift.js +172 -0
- package/dist/contextLift.js.map +1 -0
- package/dist/defineAgent.d.ts +60 -0
- package/dist/defineAgent.d.ts.map +1 -0
- package/dist/defineAgent.js +79 -0
- package/dist/defineAgent.js.map +1 -0
- package/dist/defineCompoundMode.d.ts +77 -0
- package/dist/defineCompoundMode.d.ts.map +1 -0
- package/dist/defineCompoundMode.js +79 -0
- package/dist/defineCompoundMode.js.map +1 -0
- package/dist/defineMode.d.ts +89 -0
- package/dist/defineMode.d.ts.map +1 -0
- package/dist/defineMode.js +95 -0
- package/dist/defineMode.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/injectEnd.d.ts +10 -0
- package/dist/injectEnd.d.ts.map +1 -0
- package/dist/injectEnd.js +106 -0
- package/dist/injectEnd.js.map +1 -0
- package/dist/types.d.ts +539 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +51 -0
- package/dist/types.js.map +1 -0
- package/dist/validateRoutes.d.ts +2 -0
- package/dist/validateRoutes.d.ts.map +1 -0
- package/dist/validateRoutes.js +107 -0
- package/dist/validateRoutes.js.map +1 -0
- package/dist/validateTargets.d.ts +2 -0
- package/dist/validateTargets.d.ts.map +1 -0
- package/dist/validateTargets.js +132 -0
- package/dist/validateTargets.js.map +1 -0
- package/dist/walk.d.ts +20 -0
- package/dist/walk.d.ts.map +1 -0
- package/dist/walk.js +35 -0
- package/dist/walk.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildActors.d.ts","sourceRoot":"","sources":["../src/buildActors.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AAG5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,wBAAgB,WAAW,CACvB,KAAK,EAAE,SAAS,IAAI,EAAE,EACtB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CA6B/B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// Build the `actors` map for XState's `setup({ actors })`. Spec:
|
|
2
|
+
// docs/specs/004-tasks.md Phase 5.3 + docs/specs/004-xstate-agent-wrapper.md
|
|
3
|
+
// §Mapping. Spec 005: the wrapper closes over the agent's frozen `deps`
|
|
4
|
+
// reference and threads it into every active leaf's `behavior` callback.
|
|
5
|
+
//
|
|
6
|
+
// One entry per active `Mode` (leaf) slot, keyed by `actorName(path)`. Each
|
|
7
|
+
// entry wraps the user's `behavior` in
|
|
8
|
+
// `fromPromise(async ({ input }) => behavior({ input, deps }))` — the only
|
|
9
|
+
// place the wrapper bridges user code to XState's actor runtime.
|
|
10
|
+
// Passive leaves do not produce an actor; they are atomic states with `on`
|
|
11
|
+
// handlers (handled in slice 5.4).
|
|
12
|
+
import { fromPromise } from "xstate";
|
|
13
|
+
import { actorName } from "./actorName.js";
|
|
14
|
+
export function buildActors(slots, deps) {
|
|
15
|
+
const actors = {};
|
|
16
|
+
for (const slot of slots) {
|
|
17
|
+
if (slot.kind !== "leaf")
|
|
18
|
+
continue;
|
|
19
|
+
const config = slot.config;
|
|
20
|
+
if (!("behavior" in config))
|
|
21
|
+
continue; // passive leaf — no actor
|
|
22
|
+
const name = actorName(slot.path);
|
|
23
|
+
if (name in actors) {
|
|
24
|
+
// Two leaves sharing an actor name would silently overwrite. Per
|
|
25
|
+
// DD-008 the name is derived from path, so a collision here means
|
|
26
|
+
// two slots share a path — which `walk()` already prevents — or
|
|
27
|
+
// future renames broke the invariant. Fail loudly.
|
|
28
|
+
throw new Error(`atlas/buildActors: duplicate actor name "${name}" at path "${slot.path}"`);
|
|
29
|
+
}
|
|
30
|
+
// The user's `behavior` was typed against its own `TDeps` at the
|
|
31
|
+
// `defineMode` call site; the internal carrier here erases that
|
|
32
|
+
// generic to the default `Record<string, never>`. Cast through the
|
|
33
|
+
// user-facing envelope shape — by-identity threading is the same
|
|
34
|
+
// frozen reference all callbacks receive.
|
|
35
|
+
const userBehavior = config.behavior;
|
|
36
|
+
actors[name] = fromPromise(async ({ input }) => userBehavior({ input, deps }));
|
|
37
|
+
}
|
|
38
|
+
return actors;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=buildActors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildActors.js","sourceRoot":"","sources":["../src/buildActors.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,6EAA6E;AAC7E,wEAAwE;AACxE,yEAAyE;AACzE,EAAE;AACF,4EAA4E;AAC5E,uCAAuC;AACvC,2EAA2E;AAC3E,iEAAiE;AACjE,2EAA2E;AAC3E,mCAAmC;AAEnC,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGrC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,MAAM,UAAU,WAAW,CACvB,KAAsB,EACtB,IAAuC;IAEvC,MAAM,MAAM,GAAkC,EAAE,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,CAAC,UAAU,IAAI,MAAM,CAAC;YAAE,SAAS,CAAC,0BAA0B;QAEjE,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;YACjB,iEAAiE;YACjE,kEAAkE;YAClE,gEAAgE;YAChE,mDAAmD;YACnD,MAAM,IAAI,KAAK,CACX,4CAA4C,IAAI,cAAc,IAAI,CAAC,IAAI,GAAG,CAC7E,CAAC;QACN,CAAC;QACD,iEAAiE;QACjE,gEAAgE;QAChE,mEAAmE;QACnE,iEAAiE;QACjE,0CAA0C;QAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,QAGN,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type LiftContext } from "./contextLift.js";
|
|
2
|
+
import type { JsonObject, PassiveModeConfig, RouteTarget } from "./types.js";
|
|
3
|
+
type InternalCtx = JsonObject;
|
|
4
|
+
export type LoweredTransition = {
|
|
5
|
+
target?: RouteTarget;
|
|
6
|
+
actions?: string | readonly string[];
|
|
7
|
+
guard?: (args: {
|
|
8
|
+
context: unknown;
|
|
9
|
+
event: unknown;
|
|
10
|
+
}) => boolean;
|
|
11
|
+
};
|
|
12
|
+
export type LoweredAtomicState = {
|
|
13
|
+
on: Record<string, LoweredTransition | readonly LoweredTransition[]>;
|
|
14
|
+
};
|
|
15
|
+
export declare function buildPassiveState(config: PassiveModeConfig<InternalCtx, {
|
|
16
|
+
type: string;
|
|
17
|
+
}>, lift: LiftContext | undefined, deps: Readonly<Record<string, unknown>>): LoweredAtomicState;
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=buildPassiveState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildPassiveState.d.ts","sourceRoot":"","sources":["../src/buildPassiveState.ts"],"names":[],"mappings":"AAeA,OAAO,EAAa,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,KAAK,EAER,UAAU,EACV,iBAAiB,EACjB,WAAW,EACd,MAAM,YAAY,CAAC;AAIpB,KAAK,WAAW,GAAG,UAAU,CAAC;AAK9B,MAAM,MAAM,iBAAiB,GAAG;IAC5B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC7B,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,GAAG,SAAS,iBAAiB,EAAE,CAAC,CAAC;CACxE,CAAC;AAyCF,wBAAgB,iBAAiB,CAC7B,MAAM,EAAE,iBAAiB,CAAC,WAAW,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EACxD,IAAI,EAAE,WAAW,GAAG,SAAS,EAC7B,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,kBAAkB,CASpB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Lower a passive `ModeConfig` to an XState atomic-state config.
|
|
2
|
+
// Spec: docs/specs/004-tasks.md Phase 5.4 + docs/specs/004-xstate-agent-wrapper.md §Mapping.
|
|
3
|
+
// Spec 005: `on[*].guard` gains a `deps` parameter; the wrapper captures the
|
|
4
|
+
// agent's frozen `deps` reference in the generated guard's closure.
|
|
5
|
+
//
|
|
6
|
+
// Passive leaves carry only `on` handlers (no `behavior`, no actor). The
|
|
7
|
+
// mapping is structurally identity for `target` / `actions`:
|
|
8
|
+
// { on: { EVENT: { target, actions, guard } } } → same shape on XState.
|
|
9
|
+
// `actions` strings reference entries in `defineAgent.actions` (registered
|
|
10
|
+
// in `setup({ actions })` — those already close over `deps`).
|
|
11
|
+
//
|
|
12
|
+
// `END` targets stay as the `END` symbol in the output; the compound-level
|
|
13
|
+
// `$end` substate injection + END→`$end` rewrite happens in slice 5.11
|
|
14
|
+
// before the final XState `createMachine` call.
|
|
15
|
+
import { liftGuard } from "./contextLift.js";
|
|
16
|
+
// `Array.isArray` narrows to `any[]`, which fails to subtract
|
|
17
|
+
// `readonly T[]` from a union like `T | readonly T[]`. This typed predicate
|
|
18
|
+
// gives TypeScript the narrowing it needs without leaking `any`.
|
|
19
|
+
function isReadonlyArray(value) {
|
|
20
|
+
return Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
function mapTransition(t, lift, deps) {
|
|
23
|
+
const out = {};
|
|
24
|
+
if (t.target !== undefined)
|
|
25
|
+
out.target = t.target;
|
|
26
|
+
if (t.actions !== undefined)
|
|
27
|
+
out.actions = t.actions;
|
|
28
|
+
if (t.guard !== undefined) {
|
|
29
|
+
// The user typed `guard` as `({ context, event, deps }) => boolean`
|
|
30
|
+
// with concrete C/E types. Widening to `unknown` is safe — XState
|
|
31
|
+
// calls the function with the matching shape at runtime, and the
|
|
32
|
+
// user code's narrowing is preserved as it was written.
|
|
33
|
+
//
|
|
34
|
+
// Under a compound-local context lift, route the call through
|
|
35
|
+
// `liftGuard` so the user sees the virtual merged view (inherited
|
|
36
|
+
// + local) — same view the type system promised. `deps` is
|
|
37
|
+
// forwarded verbatim regardless of lift.
|
|
38
|
+
const userGuard = t.guard;
|
|
39
|
+
if (lift !== undefined) {
|
|
40
|
+
out.guard = liftGuard(userGuard, lift, deps);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
out.guard = ({ context, event }) => userGuard({ context, event, deps });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
export function buildPassiveState(config, lift, deps) {
|
|
49
|
+
const on = {};
|
|
50
|
+
for (const [eventType, transitions] of Object.entries(config.on)) {
|
|
51
|
+
if (transitions === undefined)
|
|
52
|
+
continue;
|
|
53
|
+
on[eventType] = isReadonlyArray(transitions)
|
|
54
|
+
? transitions.map((t) => mapTransition(t, lift, deps))
|
|
55
|
+
: mapTransition(transitions, lift, deps);
|
|
56
|
+
}
|
|
57
|
+
return { on };
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=buildPassiveState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buildPassiveState.js","sourceRoot":"","sources":["../src/buildPassiveState.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,6FAA6F;AAC7F,6EAA6E;AAC7E,oEAAoE;AACpE,EAAE;AACF,yEAAyE;AACzE,6DAA6D;AAC7D,0EAA0E;AAC1E,2EAA2E;AAC3E,8DAA8D;AAC9D,EAAE;AACF,2EAA2E;AAC3E,uEAAuE;AACvE,gDAAgD;AAEhD,OAAO,EAAE,SAAS,EAAoB,MAAM,kBAAkB,CAAC;AAyB/D,8DAA8D;AAC9D,4EAA4E;AAC5E,iEAAiE;AACjE,SAAS,eAAe,CAAI,KAAuB;IAC/C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,aAAa,CAClB,CAAiD,EACjD,IAA6B,EAC7B,IAAuC;IAEvC,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;IAClD,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS;QAAE,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;IACrD,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,oEAAoE;QACpE,kEAAkE;QAClE,iEAAiE;QACjE,wDAAwD;QACxD,EAAE;QACF,8DAA8D;QAC9D,kEAAkE;QAClE,2DAA2D;QAC3D,yCAAyC;QACzC,MAAM,SAAS,GAAG,CAAC,CAAC,KAIP,CAAC;QACd,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACrB,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACjD,CAAC;aAAM,CAAC;YACJ,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5E,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC7B,MAAwD,EACxD,IAA6B,EAC7B,IAAuC;IAEvC,MAAM,EAAE,GAA6B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QAC/D,IAAI,WAAW,KAAK,SAAS;YAAE,SAAS;QACxC,EAAE,CAAC,SAAS,CAAC,GAAG,eAAe,CAAC,WAAW,CAAC;YACxC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YACtD,CAAC,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type AnyStateMachine } from "xstate";
|
|
2
|
+
import type { AgentConfig, ModesMap } from "./types.js";
|
|
3
|
+
export declare function compile<TContext, TEvents extends {
|
|
4
|
+
type: string;
|
|
5
|
+
}, TModes extends ModesMap<TContext, TEvents, TDeps>, TDeps extends Record<string, unknown> = Record<string, never>>(config: AgentConfig<TContext, TEvents, TModes, TDeps>, frozenDeps: Readonly<TDeps>): AnyStateMachine;
|
|
6
|
+
//# sourceMappingURL=compile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.d.ts","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"AAoBA,OAAO,EAA6B,KAAK,eAAe,EAA0B,MAAM,QAAQ,CAAC;AAmBjG,OAAO,KAAK,EACR,WAAW,EAGX,QAAQ,EAGX,MAAM,YAAY,CAAC;AAkLpB,wBAAgB,OAAO,CACnB,QAAQ,EACR,OAAO,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAChC,MAAM,SAAS,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,EACjD,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAE7D,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EACrD,UAAU,EAAE,QAAQ,CAAC,KAAK,CAAC,GAC5B,eAAe,CA6CjB"}
|
package/dist/compile.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
// `compile` — lowers an `AgentConfig` tree into an XState machine.
|
|
2
|
+
//
|
|
3
|
+
// Spec: docs/specs/004-xstate-agent-wrapper.md §"Wrapper internals (compile.ts)"
|
|
4
|
+
// + §Mapping. Tasks: docs/specs/004-tasks.md Phase 5.16 (final emit).
|
|
5
|
+
// Spec 005: closes over a frozen `deps` reference and threads it to every
|
|
6
|
+
// build* helper. `deps` is NOT placed in XState context — it lives
|
|
7
|
+
// in callback closures, so `JSON.stringify(actor.getSnapshot().context)`
|
|
8
|
+
// returns only TContext (+ synthetic compound-local slots).
|
|
9
|
+
//
|
|
10
|
+
// This is the only file in `atlas` that calls `setup().createMachine`. It
|
|
11
|
+
// composes the toolkit slices built in 5.1–5.15:
|
|
12
|
+
// - validateTargets, validateRoutes (fail-fast at machine creation)
|
|
13
|
+
// - walk + actorName + buildActors (active-leaf actor map)
|
|
14
|
+
// - buildActions (named-actions map)
|
|
15
|
+
// - buildActiveState / buildPassiveState (per-leaf lowering, lift-aware)
|
|
16
|
+
// - contextLift (LiftContext + entry/exit on compounds that declare context)
|
|
17
|
+
// - injectEnd (per-level `$end` substate + END → name rewrite)
|
|
18
|
+
//
|
|
19
|
+
// `defineAgent` returns this value verbatim.
|
|
20
|
+
import { setup } from "xstate";
|
|
21
|
+
import { buildActions } from "./buildActions.js";
|
|
22
|
+
import { buildActiveState } from "./buildActiveState.js";
|
|
23
|
+
import { buildActors } from "./buildActors.js";
|
|
24
|
+
import { buildPassiveState } from "./buildPassiveState.js";
|
|
25
|
+
import { compoundLocalKey, makeCompoundEntry, makeCompoundExit, } from "./contextLift.js";
|
|
26
|
+
import { END_SUBSTATE, hasEndReference, pickEndName, rewriteEndTargets, } from "./injectEnd.js";
|
|
27
|
+
import { END } from "./types.js";
|
|
28
|
+
import { validateRoutes } from "./validateRoutes.js";
|
|
29
|
+
import { validateTargets } from "./validateTargets.js";
|
|
30
|
+
import { walk } from "./walk.js";
|
|
31
|
+
function asCarrier(value) {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
// ── END detection / rewriting at a level ─────────────────────────────
|
|
35
|
+
function isCompound(node) {
|
|
36
|
+
return "initial" in node && "states" in node;
|
|
37
|
+
}
|
|
38
|
+
function isFinal(node) {
|
|
39
|
+
return "type" in node && node.type === "final";
|
|
40
|
+
}
|
|
41
|
+
function nodeExitsViaEnd(node) {
|
|
42
|
+
if (isFinal(node))
|
|
43
|
+
return false;
|
|
44
|
+
if (isCompound(node)) {
|
|
45
|
+
return node.onDone !== undefined && node.onDone.target === END;
|
|
46
|
+
}
|
|
47
|
+
return hasEndReference(node);
|
|
48
|
+
}
|
|
49
|
+
function rewriteNodeEnd(node, endName) {
|
|
50
|
+
if (isFinal(node))
|
|
51
|
+
return node;
|
|
52
|
+
if (isCompound(node)) {
|
|
53
|
+
if (node.onDone !== undefined && node.onDone.target === END) {
|
|
54
|
+
return { ...node, onDone: { target: endName } };
|
|
55
|
+
}
|
|
56
|
+
return node;
|
|
57
|
+
}
|
|
58
|
+
return rewriteEndTargets(node, endName);
|
|
59
|
+
}
|
|
60
|
+
function injectEndAtLevel(states) {
|
|
61
|
+
let anyEnd = false;
|
|
62
|
+
for (const node of Object.values(states)) {
|
|
63
|
+
if (nodeExitsViaEnd(node)) {
|
|
64
|
+
anyEnd = true;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (!anyEnd)
|
|
69
|
+
return states;
|
|
70
|
+
const endName = pickEndName(Object.keys(states));
|
|
71
|
+
const rewritten = {};
|
|
72
|
+
for (const [name, node] of Object.entries(states)) {
|
|
73
|
+
rewritten[name] = rewriteNodeEnd(node, endName);
|
|
74
|
+
}
|
|
75
|
+
rewritten[endName] = END_SUBSTATE;
|
|
76
|
+
return rewritten;
|
|
77
|
+
}
|
|
78
|
+
// ── Recursive mode-map lowering ──────────────────────────────────────
|
|
79
|
+
function joinPath(parent, name) {
|
|
80
|
+
return parent === "" ? name : `${parent}.${name}`;
|
|
81
|
+
}
|
|
82
|
+
function buildStatesMap(modes, parentLift, parentPath, deps) {
|
|
83
|
+
const out = {};
|
|
84
|
+
for (const [name, value] of Object.entries(modes)) {
|
|
85
|
+
const path = joinPath(parentPath, name);
|
|
86
|
+
const carrier = asCarrier(value);
|
|
87
|
+
if (carrier.__kind === "leaf") {
|
|
88
|
+
const config = carrier.config;
|
|
89
|
+
if ("behavior" in config && config.behavior !== undefined) {
|
|
90
|
+
const slot = { kind: "leaf", path, config };
|
|
91
|
+
out[name] = buildActiveState(slot, parentLift, deps);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
out[name] = buildPassiveState(config, parentLift, deps);
|
|
95
|
+
}
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// Compound.
|
|
99
|
+
const cfg = carrier.config;
|
|
100
|
+
let childLift = parentLift;
|
|
101
|
+
let ownEntry;
|
|
102
|
+
let ownExit;
|
|
103
|
+
if (cfg.context !== undefined) {
|
|
104
|
+
const ctx = cfg.context;
|
|
105
|
+
const newLift = {
|
|
106
|
+
key: compoundLocalKey(path),
|
|
107
|
+
inherit: ctx.inherit,
|
|
108
|
+
initialLocal: ctx.local,
|
|
109
|
+
parent: parentLift,
|
|
110
|
+
};
|
|
111
|
+
childLift = newLift;
|
|
112
|
+
ownEntry = makeCompoundEntry(newLift);
|
|
113
|
+
ownExit = makeCompoundExit(newLift);
|
|
114
|
+
}
|
|
115
|
+
const childStatesRaw = buildStatesMap(cfg.modes, childLift, path, deps);
|
|
116
|
+
const childStates = injectEndAtLevel(childStatesRaw);
|
|
117
|
+
const compound = {
|
|
118
|
+
initial: cfg.initial,
|
|
119
|
+
states: childStates,
|
|
120
|
+
onDone: { target: cfg.onDone },
|
|
121
|
+
};
|
|
122
|
+
if (ownEntry !== undefined)
|
|
123
|
+
compound.entry = ownEntry;
|
|
124
|
+
if (ownExit !== undefined)
|
|
125
|
+
compound.exit = ownExit;
|
|
126
|
+
out[name] = compound;
|
|
127
|
+
}
|
|
128
|
+
return out;
|
|
129
|
+
}
|
|
130
|
+
// ── Public entry ─────────────────────────────────────────────────────
|
|
131
|
+
export function compile(config, frozenDeps) {
|
|
132
|
+
const rawModes = config.modes;
|
|
133
|
+
// Erase TDeps for the loose internal contract — every build* helper takes
|
|
134
|
+
// `Readonly<Record<string, unknown>>` and the user's concrete type has
|
|
135
|
+
// already been enforced at the call site.
|
|
136
|
+
const deps = frozenDeps;
|
|
137
|
+
// Fail-fast at machine creation — spec verification lines 821 + 824.
|
|
138
|
+
validateTargets(rawModes);
|
|
139
|
+
validateRoutes(rawModes);
|
|
140
|
+
const slots = walk(rawModes);
|
|
141
|
+
const actors = buildActors(slots, deps);
|
|
142
|
+
const actions = buildActions(config.actions, deps);
|
|
143
|
+
const lowered = buildStatesMap(rawModes, undefined, "", deps);
|
|
144
|
+
const finalStates = injectEndAtLevel(lowered);
|
|
145
|
+
// The wrapper's type contract was discharged at the user's call site
|
|
146
|
+
// (defineMode / defineCompoundMode / defineAgent). At this internal layer
|
|
147
|
+
// every shape is `unknown`-typed by construction. XState's `setup` types
|
|
148
|
+
// are too strict to satisfy generically — its `MachineContext` constraint
|
|
149
|
+
// collides with `TContext` being arbitrary — so we hand it the already-
|
|
150
|
+
// shaped values through `unknown`. The output is `AnyStateMachine`, which
|
|
151
|
+
// is what `defineAgent` returns.
|
|
152
|
+
const looseSetup = setup;
|
|
153
|
+
const machine = looseSetup({
|
|
154
|
+
actors,
|
|
155
|
+
actions,
|
|
156
|
+
}).createMachine({
|
|
157
|
+
id: config.id,
|
|
158
|
+
initial: config.initial,
|
|
159
|
+
context: config.context,
|
|
160
|
+
states: finalStates,
|
|
161
|
+
});
|
|
162
|
+
return machine;
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=compile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile.js","sourceRoot":"","sources":["../src/compile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { assign } from "xstate";
|
|
2
|
+
export type LiftContext = {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly inherit: readonly string[];
|
|
5
|
+
readonly initialLocal: Readonly<Record<string, unknown>>;
|
|
6
|
+
readonly parent?: LiftContext;
|
|
7
|
+
};
|
|
8
|
+
export declare function compoundLocalKey(path: string): string;
|
|
9
|
+
export declare function liftInput(userInput: (args: {
|
|
10
|
+
context: unknown;
|
|
11
|
+
deps: Readonly<Record<string, unknown>>;
|
|
12
|
+
}) => unknown, lift: LiftContext, deps: Readonly<Record<string, unknown>>): (args: {
|
|
13
|
+
context: unknown;
|
|
14
|
+
}) => unknown;
|
|
15
|
+
export declare function liftExitAssign(userAssign: (args: {
|
|
16
|
+
context: unknown;
|
|
17
|
+
payload: unknown;
|
|
18
|
+
deps: Readonly<Record<string, unknown>>;
|
|
19
|
+
}) => object, lift: LiftContext, deps: Readonly<Record<string, unknown>>): ReturnType<typeof assign>;
|
|
20
|
+
export declare function liftErrorAssign(userAssign: (args: {
|
|
21
|
+
context: unknown;
|
|
22
|
+
error: unknown;
|
|
23
|
+
deps: Readonly<Record<string, unknown>>;
|
|
24
|
+
}) => object, lift: LiftContext, deps: Readonly<Record<string, unknown>>): ReturnType<typeof assign>;
|
|
25
|
+
export declare function liftGuard(userGuard: (args: {
|
|
26
|
+
context: unknown;
|
|
27
|
+
event: unknown;
|
|
28
|
+
deps: Readonly<Record<string, unknown>>;
|
|
29
|
+
}) => boolean, lift: LiftContext, deps: Readonly<Record<string, unknown>>): (args: {
|
|
30
|
+
context: unknown;
|
|
31
|
+
event: unknown;
|
|
32
|
+
}) => boolean;
|
|
33
|
+
export declare function makeCompoundEntry(lift: LiftContext): ReturnType<typeof assign>;
|
|
34
|
+
export declare function makeCompoundExit(lift: LiftContext): ReturnType<typeof assign>;
|
|
35
|
+
//# sourceMappingURL=contextLift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextLift.d.ts","sourceRoot":"","sources":["../src/contextLift.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,MAAM,MAAM,WAAW,GAAG;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CACjC,CAAC;AAOF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrD;AAmGD,wBAAgB,SAAS,CACrB,SAAS,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAAK,OAAO,EAC3F,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAKzC;AAKD,wBAAgB,cAAc,CAC1B,UAAU,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAAK,MAAM,EAC7G,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,UAAU,CAAC,OAAO,MAAM,CAAC,CAQ3B;AAGD,wBAAgB,eAAe,CAC3B,UAAU,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAAK,MAAM,EAC3G,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,UAAU,CAAC,OAAO,MAAM,CAAC,CAQ3B;AAGD,wBAAgB,SAAS,CACrB,SAAS,EAAE,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAAE,KAAK,OAAO,EAC3G,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,KAAK,OAAO,CAKzD;AAOD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAI9E;AAKD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAI7E"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
// Phase 5.13 helpers: compound-local context lift.
|
|
2
|
+
//
|
|
3
|
+
// Spec: docs/specs/004-tasks.md Phase 5.13,
|
|
4
|
+
// docs/specs/004-xstate-agent-wrapper.md §"Lexical scoping of context"
|
|
5
|
+
// (lines 104-111) and §Mapping line 626.
|
|
6
|
+
//
|
|
7
|
+
// A `CompoundMode` with `context: { inherit, local }` exposes a narrowed view
|
|
8
|
+
// to its children: `Pick<TParent, inherit[number]> & typeof local`. At runtime the
|
|
9
|
+
// wrapper materializes this view by:
|
|
10
|
+
// - allocating a slot under a generated root-context key (`__<path>_local`)
|
|
11
|
+
// initialized to `local` on every entry, cleared on every exit
|
|
12
|
+
// - wrapping each child callback (`input`, `assign`, passive `guard`) so
|
|
13
|
+
// the `context` they see is the virtual merged view, and any `Partial`
|
|
14
|
+
// they return is split back to the correct destination
|
|
15
|
+
//
|
|
16
|
+
// Inherit keys are read live from the parent (no copy on entry, no
|
|
17
|
+
// project-back on exit) — writes propagate through to the owning slot in
|
|
18
|
+
// the same step. Local keys live in this compound's own slot and reset
|
|
19
|
+
// automatically on re-entry. Nested compounds chain: a nested `LiftContext`
|
|
20
|
+
// carries a `parent` reference that the helpers walk to resolve inherit
|
|
21
|
+
// reads/writes.
|
|
22
|
+
//
|
|
23
|
+
// The actual emission of `entry`/`exit` actions onto a lowered compound
|
|
24
|
+
// shape, plus the threading of `LiftContext` through the walk, lands in
|
|
25
|
+
// slice 5.16; 5.13 ships the toolkit and integrates it with
|
|
26
|
+
// `buildActiveState` / `buildPassiveState` via an optional `lift` argument.
|
|
27
|
+
import { assign } from "xstate";
|
|
28
|
+
// Slot-name generator. Path is the compound's dotted slot
|
|
29
|
+
// (e.g. `socratic.evaluating` → `__socratic_evaluating_local`). The `__`
|
|
30
|
+
// prefix + `_local` suffix make collisions with user-declared agent-context
|
|
31
|
+
// keys vanishingly rare; dots are replaced with `_` so the key is a valid
|
|
32
|
+
// JS identifier.
|
|
33
|
+
export function compoundLocalKey(path) {
|
|
34
|
+
if (path === "") {
|
|
35
|
+
throw new Error("atlas/contextLift: compoundLocalKey called with empty path");
|
|
36
|
+
}
|
|
37
|
+
const safe = path.replace(/\./g, "_");
|
|
38
|
+
return `__${safe}_local`;
|
|
39
|
+
}
|
|
40
|
+
function localKeys(lift) {
|
|
41
|
+
return Object.keys(lift.initialLocal);
|
|
42
|
+
}
|
|
43
|
+
// Build the parent's effective view from the root context. For a top-level
|
|
44
|
+
// compound (no parent), the parent view IS the root context. For a nested
|
|
45
|
+
// compound, recurse into the enclosing lift to materialize ITS subContext.
|
|
46
|
+
function buildParentView(rootContext, parent) {
|
|
47
|
+
if (parent === undefined)
|
|
48
|
+
return rootContext;
|
|
49
|
+
return buildSubContext(rootContext, parent);
|
|
50
|
+
}
|
|
51
|
+
// Build the virtual subContext a child callback sees: inherit keys read
|
|
52
|
+
// from the parent view (live), local keys read from this compound's slot.
|
|
53
|
+
function buildSubContext(rootContext, lift) {
|
|
54
|
+
const parentView = buildParentView(rootContext, lift.parent);
|
|
55
|
+
const sub = {};
|
|
56
|
+
for (const k of lift.inherit) {
|
|
57
|
+
sub[k] = parentView[k];
|
|
58
|
+
}
|
|
59
|
+
const slot = rootContext[lift.key];
|
|
60
|
+
if (slot !== undefined && typeof slot === "object" && slot !== null) {
|
|
61
|
+
const slotRec = slot;
|
|
62
|
+
for (const k of localKeys(lift)) {
|
|
63
|
+
sub[k] = slotRec[k];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return sub;
|
|
67
|
+
}
|
|
68
|
+
// Walk up the parent chain to find which ancestor declared `key` as a
|
|
69
|
+
// local. If no ancestor owns it, the key lives in the agent's root context.
|
|
70
|
+
function findInheritOwner(key, parent) {
|
|
71
|
+
if (parent === undefined)
|
|
72
|
+
return { kind: "root" };
|
|
73
|
+
if (localKeys(parent).includes(key))
|
|
74
|
+
return { kind: "slot", slotKey: parent.key };
|
|
75
|
+
return findInheritOwner(key, parent.parent);
|
|
76
|
+
}
|
|
77
|
+
// Split the user's `Partial<combined>` return into a root-context patch
|
|
78
|
+
// XState's `assign` can apply. Local writes update this compound's slot;
|
|
79
|
+
// inherit writes update either the agent root or an ancestor's slot,
|
|
80
|
+
// depending on where the key was declared as local.
|
|
81
|
+
function splitUserUpdate(update, rootContext, lift) {
|
|
82
|
+
const ownLocals = localKeys(lift);
|
|
83
|
+
const rootPatch = {};
|
|
84
|
+
const slotPatches = {};
|
|
85
|
+
function touchSlot(slotKey, k, v) {
|
|
86
|
+
const existing = slotPatches[slotKey] ?? {};
|
|
87
|
+
existing[k] = v;
|
|
88
|
+
slotPatches[slotKey] = existing;
|
|
89
|
+
}
|
|
90
|
+
for (const [k, v] of Object.entries(update)) {
|
|
91
|
+
if (ownLocals.includes(k)) {
|
|
92
|
+
touchSlot(lift.key, k, v);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
if (lift.inherit.includes(k)) {
|
|
96
|
+
const owner = findInheritOwner(k, lift.parent);
|
|
97
|
+
if (owner.kind === "root") {
|
|
98
|
+
rootPatch[k] = v;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
touchSlot(owner.slotKey, k, v);
|
|
102
|
+
}
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
// Out-of-scope key: the type system already rejected it. A bypass
|
|
106
|
+
// via `as` reaches here — drop silently rather than leak into root.
|
|
107
|
+
}
|
|
108
|
+
// XState `assign` is shallow at the root level — we must hand it the
|
|
109
|
+
// full new slot object, not a delta.
|
|
110
|
+
for (const [slotKey, patch] of Object.entries(slotPatches)) {
|
|
111
|
+
const current = (rootContext[slotKey] ?? {});
|
|
112
|
+
rootPatch[slotKey] = { ...current, ...patch };
|
|
113
|
+
}
|
|
114
|
+
return rootPatch;
|
|
115
|
+
}
|
|
116
|
+
// Wrap a user `input({ context, deps })` callback so it sees the virtual
|
|
117
|
+
// view. `deps` is captured verbatim from the closure that `compile.ts`
|
|
118
|
+
// threaded down — the lift only transforms `context`.
|
|
119
|
+
export function liftInput(userInput, lift, deps) {
|
|
120
|
+
return ({ context }) => {
|
|
121
|
+
const sub = buildSubContext(context, lift);
|
|
122
|
+
return userInput({ context: sub, deps });
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Wrap a user `assign({ context, payload, deps }) => Partial<combined>`
|
|
126
|
+
// callback, returning an XState `assign(...)` action that applies the split
|
|
127
|
+
// update. `deps` is forwarded by identity from the wrapper's closure.
|
|
128
|
+
export function liftExitAssign(userAssign, lift, deps) {
|
|
129
|
+
return assign(({ context, event }) => {
|
|
130
|
+
const root = context;
|
|
131
|
+
const sub = buildSubContext(root, lift);
|
|
132
|
+
const payload = event.output.payload;
|
|
133
|
+
const update = userAssign({ context: sub, payload, deps });
|
|
134
|
+
return splitUserUpdate(update, root, lift);
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// Wrap a user `assign({ context, error, deps })` callback (error routes).
|
|
138
|
+
export function liftErrorAssign(userAssign, lift, deps) {
|
|
139
|
+
return assign(({ context, event }) => {
|
|
140
|
+
const root = context;
|
|
141
|
+
const sub = buildSubContext(root, lift);
|
|
142
|
+
const error = event.error;
|
|
143
|
+
const update = userAssign({ context: sub, error, deps });
|
|
144
|
+
return splitUserUpdate(update, root, lift);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
// Wrap a user `guard({ context, event, deps })` (passive `on` transitions).
|
|
148
|
+
export function liftGuard(userGuard, lift, deps) {
|
|
149
|
+
return ({ context, event }) => {
|
|
150
|
+
const sub = buildSubContext(context, lift);
|
|
151
|
+
return userGuard({ context: sub, event, deps });
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
// XState `entry` action: initialize this compound's local slot. A fresh
|
|
155
|
+
// shallow copy of `initialLocal` per entry so subsequent mutations stay
|
|
156
|
+
// scoped to this activation. Deep cloning is not promised — the spec's
|
|
157
|
+
// canonical local is primitive-valued (`{ attempts: 0 }`); nested object
|
|
158
|
+
// values are shared by reference.
|
|
159
|
+
export function makeCompoundEntry(lift) {
|
|
160
|
+
return assign({
|
|
161
|
+
[lift.key]: () => ({ ...lift.initialLocal }),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
// XState `exit` action: clear this compound's local slot. The next entry
|
|
165
|
+
// (if any) re-initializes via `makeCompoundEntry`, satisfying the
|
|
166
|
+
// reset-on-re-entry invariant from spec line 109.
|
|
167
|
+
export function makeCompoundExit(lift) {
|
|
168
|
+
return assign({
|
|
169
|
+
[lift.key]: () => undefined,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=contextLift.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contextLift.js","sourceRoot":"","sources":["../src/contextLift.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,4CAA4C;AAC5C,uEAAuE;AACvE,yCAAyC;AACzC,EAAE;AACF,8EAA8E;AAC9E,mFAAmF;AACnF,qCAAqC;AACrC,8EAA8E;AAC9E,mEAAmE;AACnE,2EAA2E;AAC3E,2EAA2E;AAC3E,2DAA2D;AAC3D,EAAE;AACF,mEAAmE;AACnE,yEAAyE;AACzE,uEAAuE;AACvE,4EAA4E;AAC5E,wEAAwE;AACxE,gBAAgB;AAChB,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,4DAA4D;AAC5D,4EAA4E;AAE5E,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAShC,0DAA0D;AAC1D,yEAAyE;AACzE,4EAA4E;AAC5E,0EAA0E;AAC1E,iBAAiB;AACjB,MAAM,UAAU,gBAAgB,CAAC,IAAY;IACzC,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;IAClF,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACtC,OAAO,KAAK,IAAI,QAAQ,CAAC;AAC7B,CAAC;AAED,SAAS,SAAS,CAAC,IAAiB;IAChC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;AAC1C,CAAC;AAED,2EAA2E;AAC3E,0EAA0E;AAC1E,2EAA2E;AAC3E,SAAS,eAAe,CACpB,WAAoC,EACpC,MAA+B;IAE/B,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,WAAW,CAAC;IAC7C,OAAO,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,wEAAwE;AACxE,0EAA0E;AAC1E,SAAS,eAAe,CACpB,WAAoC,EACpC,IAAiB;IAEjB,MAAM,UAAU,GAAG,eAAe,CAAC,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC7D,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClE,MAAM,OAAO,GAAG,IAA+B,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC9B,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACf,CAAC;AAED,sEAAsE;AACtE,4EAA4E;AAC5E,SAAS,gBAAgB,CACrB,GAAW,EACX,MAA+B;IAE/B,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAClD,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,GAAG,EAAE,CAAC;IAClF,OAAO,gBAAgB,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AAChD,CAAC;AAED,wEAAwE;AACxE,yEAAyE;AACzE,qEAAqE;AACrE,oDAAoD;AACpD,SAAS,eAAe,CACpB,MAA+B,EAC/B,WAAoC,EACpC,IAAiB;IAEjB,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,SAAS,GAA4B,EAAE,CAAC;IAC9C,MAAM,WAAW,GAA4C,EAAE,CAAC;IAEhE,SAAS,SAAS,CAAC,OAAe,EAAE,CAAS,EAAE,CAAU;QACrD,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5C,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAChB,WAAW,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC;IACpC,CAAC;IAED,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1C,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YACxB,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1B,SAAS;QACb,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBACxB,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACJ,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACnC,CAAC;YACD,SAAS;QACb,CAAC;QACD,kEAAkE;QAClE,oEAAoE;IACxE,CAAC;IAED,qEAAqE;IACrE,qCAAqC;IACrC,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACzD,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,CAA4B,CAAC;QACxE,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;IAClD,CAAC;IAED,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,yEAAyE;AACzE,uEAAuE;AACvE,sDAAsD;AACtD,MAAM,UAAU,SAAS,CACrB,SAA2F,EAC3F,IAAiB,EACjB,IAAuC;IAEvC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;QACnB,MAAM,GAAG,GAAG,eAAe,CAAC,OAAkC,EAAE,IAAI,CAAC,CAAC;QACtE,OAAO,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC,CAAC;AACN,CAAC;AAED,wEAAwE;AACxE,4EAA4E;AAC5E,sEAAsE;AACtE,MAAM,UAAU,cAAc,CAC1B,UAA6G,EAC7G,IAAiB,EACjB,IAAuC;IAEvC,OAAO,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,OAAkC,CAAC;QAChD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACxC,MAAM,OAAO,GAAI,KAAqD,CAAC,MAAM,CAAC,OAAO,CAAC;QACtF,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAA4B,CAAC;QACtF,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACP,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,eAAe,CAC3B,UAA2G,EAC3G,IAAiB,EACjB,IAAuC;IAEvC,OAAO,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QACjC,MAAM,IAAI,GAAG,OAAkC,CAAC;QAChD,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACxC,MAAM,KAAK,GAAI,KAAuC,CAAC,KAAK,CAAC;QAC7D,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAA4B,CAAC;QACpF,OAAO,eAAe,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;AACP,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CACrB,SAA2G,EAC3G,IAAiB,EACjB,IAAuC;IAEvC,OAAO,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE;QAC1B,MAAM,GAAG,GAAG,eAAe,CAAC,OAAkC,EAAE,IAAI,CAAC,CAAC;QACtE,OAAO,SAAS,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC;AACN,CAAC;AAED,wEAAwE;AACxE,wEAAwE;AACxE,uEAAuE;AACvE,yEAAyE;AACzE,kCAAkC;AAClC,MAAM,UAAU,iBAAiB,CAAC,IAAiB;IAC/C,OAAO,MAAM,CAAC;QACV,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;KAC/C,CAAC,CAAC;AACP,CAAC;AAED,yEAAyE;AACzE,kEAAkE;AAClE,kDAAkD;AAClD,MAAM,UAAU,gBAAgB,CAAC,IAAiB;IAC9C,OAAO,MAAM,CAAC;QACV,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,SAAS;KAC9B,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { AnyStateMachine } from "xstate";
|
|
2
|
+
import type { AgentConfig, ModesMap } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Construct the **root agent** — compiles the declarative `AgentConfig` into
|
|
5
|
+
* a runnable XState machine. This is the single boundary where the wrapper
|
|
6
|
+
* touches `xstate`: the return type is `AnyStateMachine`, so callers feed it
|
|
7
|
+
* straight into `createActor`, the inspector, and existing tests.
|
|
8
|
+
*
|
|
9
|
+
* The agent's `modes` map can mix `Mode`s (leaves) and nested `CompoundMode`s
|
|
10
|
+
* freely. The compile step lowers them, validates sibling-target references,
|
|
11
|
+
* injects the `END` synthetic state per-compound when referenced, and wires
|
|
12
|
+
* the payload-driven `routes` into XState transitions.
|
|
13
|
+
*
|
|
14
|
+
* @template TContext The agent's root context shape. Constrained to
|
|
15
|
+
* `JsonCompatible<TContext>` so the snapshot round-trips
|
|
16
|
+
* through arbitrary storage without custom encoding.
|
|
17
|
+
* @template TEvents The agent's full event union. Each variant must have a
|
|
18
|
+
* `type: string` discriminant. Pass `{} as Ev` to the
|
|
19
|
+
* `events` field — only its type matters; it's a phantom.
|
|
20
|
+
* @template TModes The root `modes` map. `initial` is keyed against this
|
|
21
|
+
* type so a typo is a compile error.
|
|
22
|
+
* @template TDeps Frozen container of external resources. Defaults to
|
|
23
|
+
* `Record<string, never>` when `deps` is omitted —
|
|
24
|
+
* callbacks still receive `deps`, typed as the empty
|
|
25
|
+
* object, so the envelope shape stays uniform.
|
|
26
|
+
*
|
|
27
|
+
* @param config `{ id, initial, context, events, deps?, actions?, modes }`.
|
|
28
|
+
* `actions` registers reusable, deps-aware callbacks (each
|
|
29
|
+
* returning `Partial<TContext>`) referenced by name from
|
|
30
|
+
* passive `on[event].actions`. The wrapper wraps them in
|
|
31
|
+
* `assign(...)` at compile time, so user code never imports
|
|
32
|
+
* from `xstate`.
|
|
33
|
+
*
|
|
34
|
+
* @returns An `AnyStateMachine` ready to pass to `createActor`.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const agent = defineAgent<Ctx, Ev, Modes, { db: Driver; logger: Logger }>({
|
|
39
|
+
* id: "zoe",
|
|
40
|
+
* initial: "listening",
|
|
41
|
+
* context: { messages: [], attempts: 0 },
|
|
42
|
+
* events: {} as Ev,
|
|
43
|
+
* deps: { db: realDb, logger: pino() },
|
|
44
|
+
* actions: {
|
|
45
|
+
* appendUserMsg: ({ context, event, deps }) =>
|
|
46
|
+
* event.type === "USER_MSG"
|
|
47
|
+
* ? { messages: [...context.messages, { role: "user", content: event.text }] }
|
|
48
|
+
* : {},
|
|
49
|
+
* },
|
|
50
|
+
* modes: { listening, classifying, greetings, socratic },
|
|
51
|
+
* });
|
|
52
|
+
*
|
|
53
|
+
* const actor = createActor(agent).start();
|
|
54
|
+
* actor.send({ type: "USER_MSG", text: "hi" });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function defineAgent<TContext, TEvents extends {
|
|
58
|
+
type: string;
|
|
59
|
+
}, TModes extends ModesMap<TContext, TEvents, TDeps>, TDeps extends Record<string, unknown> = Record<string, never>>(config: AgentConfig<TContext, TEvents, TModes, TDeps>): AnyStateMachine;
|
|
60
|
+
//# sourceMappingURL=defineAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineAgent.d.ts","sourceRoot":"","sources":["../src/defineAgent.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAC;AAG9C,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,wBAAgB,WAAW,CACvB,QAAQ,EACR,OAAO,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAChC,MAAM,SAAS,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,EACjD,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,EAC/D,MAAM,EAAE,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG,eAAe,CAOxE"}
|