@demlik/tea 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/agent/index.d.ts +907 -0
- package/dist/agent/index.js +20 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/authed-call/index.d.ts +119 -0
- package/dist/authed-call/index.js +148 -0
- package/dist/authed-call/index.js.map +1 -0
- package/dist/await-terminal/index.d.ts +99 -0
- package/dist/await-terminal/index.js +75 -0
- package/dist/await-terminal/index.js.map +1 -0
- package/dist/batch-window/index.d.ts +259 -0
- package/dist/batch-window/index.js +43 -0
- package/dist/batch-window/index.js.map +1 -0
- package/dist/cache/index.d.ts +2 -2
- package/dist/cache/index.js +2 -50
- package/dist/cache/index.js.map +1 -1
- package/dist/chunk-27N2SPTN.js +222 -0
- package/dist/chunk-27N2SPTN.js.map +1 -0
- package/dist/chunk-2YOE5PIS.js +45 -0
- package/dist/chunk-2YOE5PIS.js.map +1 -0
- package/dist/chunk-3545BOYL.js +65 -0
- package/dist/chunk-3545BOYL.js.map +1 -0
- package/dist/chunk-3XJWC7VW.js +61 -0
- package/dist/chunk-3XJWC7VW.js.map +1 -0
- package/dist/chunk-5DEQ5I3U.js +132 -0
- package/dist/chunk-5DEQ5I3U.js.map +1 -0
- package/dist/chunk-5VNWZADP.js +49 -0
- package/dist/chunk-5VNWZADP.js.map +1 -0
- package/dist/chunk-6RGBKODV.js +268 -0
- package/dist/chunk-6RGBKODV.js.map +1 -0
- package/dist/{chunk-ZRUST6BK.js → chunk-7FYQGDMF.js} +2 -2
- package/dist/chunk-7FYQGDMF.js.map +1 -0
- package/dist/chunk-7W4LMPUW.js +186 -0
- package/dist/chunk-7W4LMPUW.js.map +1 -0
- package/dist/chunk-BYQUGDD3.js +16 -0
- package/dist/chunk-BYQUGDD3.js.map +1 -0
- package/dist/{chunk-PYBQREFU.js → chunk-DILMKOZ7.js} +22 -26
- package/dist/chunk-DILMKOZ7.js.map +1 -0
- package/dist/chunk-EHIX7NYZ.js +93 -0
- package/dist/chunk-EHIX7NYZ.js.map +1 -0
- package/dist/chunk-HCEVHFJ7.js +54 -0
- package/dist/chunk-HCEVHFJ7.js.map +1 -0
- package/dist/chunk-HJO6VNQI.js +15 -0
- package/dist/chunk-HJO6VNQI.js.map +1 -0
- package/dist/chunk-IN33Q4VJ.js +52 -0
- package/dist/chunk-IN33Q4VJ.js.map +1 -0
- package/dist/chunk-J6527VRQ.js +56 -0
- package/dist/chunk-J6527VRQ.js.map +1 -0
- package/dist/chunk-JELSZN25.js +47 -0
- package/dist/chunk-JELSZN25.js.map +1 -0
- package/dist/chunk-K575PT4S.js +58 -0
- package/dist/chunk-K575PT4S.js.map +1 -0
- package/dist/chunk-K7Q23EQ4.js +20 -0
- package/dist/chunk-K7Q23EQ4.js.map +1 -0
- package/dist/chunk-LEC4U6CX.js +91 -0
- package/dist/chunk-LEC4U6CX.js.map +1 -0
- package/dist/{chunk-PYOCUBQJ.js → chunk-LP7VQBRG.js} +22 -15
- package/dist/chunk-LP7VQBRG.js.map +1 -0
- package/dist/{chunk-CMG2KMWX.js → chunk-MMH7CW5K.js} +220 -189
- package/dist/chunk-MMH7CW5K.js.map +1 -0
- package/dist/{chunk-Y5JM3UUH.js → chunk-NSDFA6M6.js} +75 -3
- package/dist/chunk-NSDFA6M6.js.map +1 -0
- package/dist/chunk-ON24RKSE.js +60 -0
- package/dist/chunk-ON24RKSE.js.map +1 -0
- package/dist/chunk-PS23H6KQ.js +87 -0
- package/dist/chunk-PS23H6KQ.js.map +1 -0
- package/dist/chunk-QLA76GIT.js +162 -0
- package/dist/chunk-QLA76GIT.js.map +1 -0
- package/dist/chunk-S3FQN4SL.js +506 -0
- package/dist/chunk-S3FQN4SL.js.map +1 -0
- package/dist/chunk-SC3FAFZN.js +53 -0
- package/dist/chunk-SC3FAFZN.js.map +1 -0
- package/dist/chunk-SINXE47Y.js +55 -0
- package/dist/chunk-SINXE47Y.js.map +1 -0
- package/dist/chunk-SQTCS44W.js +33 -0
- package/dist/chunk-SQTCS44W.js.map +1 -0
- package/dist/chunk-TGG26XMK.js +52 -0
- package/dist/chunk-TGG26XMK.js.map +1 -0
- package/dist/chunk-UV6UWGEO.js +147 -0
- package/dist/chunk-UV6UWGEO.js.map +1 -0
- package/dist/chunk-UYWUVEP6.js +158 -0
- package/dist/chunk-UYWUVEP6.js.map +1 -0
- package/dist/chunk-VLGARN6H.js +202 -0
- package/dist/chunk-VLGARN6H.js.map +1 -0
- package/dist/circuit-breaker/index.js +1 -51
- package/dist/circuit-breaker/index.js.map +1 -1
- package/dist/core-BoB6t7dB.d.ts +188 -0
- package/dist/deadline/index.d.ts +24 -5
- package/dist/deadline/index.js +4 -18
- package/dist/deadline/index.js.map +1 -1
- package/dist/debounce/index.d.ts +6 -0
- package/dist/debounce/index.js +1 -54
- package/dist/debounce/index.js.map +1 -1
- package/dist/devtools/index.d.ts +1 -1
- package/dist/devtools/index.js +18 -6
- package/dist/devtools/index.js.map +1 -1
- package/dist/do/index.d.ts +1723 -92
- package/dist/do/index.js +673 -31
- package/dist/do/index.js.map +1 -1
- package/dist/durable-effects-CO9Uh971.d.ts +180 -0
- package/dist/extension/index.d.ts +31 -13
- package/dist/extension/index.js +5 -3
- package/dist/extension/index.js.map +1 -1
- package/dist/extension/react.js +8 -3
- package/dist/extension/react.js.map +1 -1
- package/dist/extension/subs/index.d.ts +2 -2
- package/dist/extension/subs/index.js.map +1 -1
- package/dist/extension/test-utils.js +11 -3
- package/dist/extension/test-utils.js.map +1 -1
- package/dist/fan-out/index.d.ts +239 -0
- package/dist/fan-out/index.js +5 -0
- package/dist/fan-out/index.js.map +1 -0
- package/dist/idempotency/adapter.d.ts +62 -0
- package/dist/idempotency/adapter.js +4 -0
- package/dist/idempotency/adapter.js.map +1 -0
- package/dist/idempotency/index.js +1 -56
- package/dist/idempotency/index.js.map +1 -1
- package/dist/idempotent-intake/index.d.ts +186 -0
- package/dist/idempotent-intake/index.js +7 -0
- package/dist/idempotent-intake/index.js.map +1 -0
- package/dist/index.d.ts +341 -191
- package/dist/index.js +2 -1
- package/dist/llm-call/index.d.ts +309 -0
- package/dist/llm-call/index.js +14 -0
- package/dist/llm-call/index.js.map +1 -0
- package/dist/machine-viz/index.d.ts +4 -4
- package/dist/machine-viz/index.js +5 -9
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +1 -0
- package/dist/monitored-run/index.d.ts +253 -0
- package/dist/monitored-run/index.js +10 -0
- package/dist/monitored-run/index.js.map +1 -0
- package/dist/node/index.d.ts +5 -5
- package/dist/node/index.js.map +1 -1
- package/dist/paginated-walk/index.d.ts +234 -0
- package/dist/paginated-walk/index.js +15 -0
- package/dist/paginated-walk/index.js.map +1 -0
- package/dist/paginator/index.d.ts +271 -0
- package/dist/paginator/index.js +3 -0
- package/dist/paginator/index.js.map +1 -0
- package/dist/parity/index.d.ts +92 -0
- package/dist/parity/index.js +78 -0
- package/dist/parity/index.js.map +1 -0
- package/dist/pbt/arbitraries/index.d.ts +1 -1
- package/dist/pbt/arbitraries/index.js +1 -1
- package/dist/pbt/index.d.ts +15 -8
- package/dist/pbt/index.js +6 -11
- package/dist/pbt/index.js.map +1 -1
- package/dist/pbt/runners/index.d.ts +1 -1
- package/dist/pbt/runners/index.js +3 -2
- package/dist/poller/index.d.ts +288 -0
- package/dist/poller/index.js +79 -0
- package/dist/poller/index.js.map +1 -0
- package/dist/prediction/index.d.ts +130 -0
- package/dist/prediction/index.js +4 -0
- package/dist/prediction/index.js.map +1 -0
- package/dist/protocol-B5YmJr0d.d.ts +45 -0
- package/dist/pure/index.d.ts +2 -0
- package/dist/pure/index.js +4 -0
- package/dist/pure/index.js.map +1 -0
- package/dist/raft/demo.d.ts +105 -0
- package/dist/raft/demo.js +172 -0
- package/dist/raft/demo.js.map +1 -0
- package/dist/raft/index.d.ts +548 -0
- package/dist/raft/index.js +7 -0
- package/dist/raft/index.js.map +1 -0
- package/dist/raft/sim.d.ts +222 -0
- package/dist/raft/sim.js +8 -0
- package/dist/raft/sim.js.map +1 -0
- package/dist/raft/timeline.d.ts +46 -0
- package/dist/raft/timeline.js +62 -0
- package/dist/raft/timeline.js.map +1 -0
- package/dist/rate-limit/index.js +1 -43
- package/dist/rate-limit/index.js.map +1 -1
- package/dist/react/index.d.ts +2 -1
- package/dist/react/index.js +43 -20
- package/dist/react/index.js.map +1 -1
- package/dist/reconciler/index.d.ts +192 -0
- package/dist/reconciler/index.js +166 -0
- package/dist/reconciler/index.js.map +1 -0
- package/dist/recorder/index.d.ts +7 -3
- package/dist/recorder/index.js +1 -155
- package/dist/recorder/index.js.map +1 -1
- package/dist/resilient-call/index.d.ts +294 -0
- package/dist/resilient-call/index.js +13 -0
- package/dist/resilient-call/index.js.map +1 -0
- package/dist/retry-backoff/index.d.ts +42 -5
- package/dist/retry-backoff/index.js +1 -35
- package/dist/retry-backoff/index.js.map +1 -1
- package/dist/retry-to-success/index.d.ts +109 -0
- package/dist/retry-to-success/index.js +35 -0
- package/dist/retry-to-success/index.js.map +1 -0
- package/dist/saga/index.d.ts +238 -0
- package/dist/saga/index.js +150 -0
- package/dist/saga/index.js.map +1 -0
- package/dist/snapshot/index.d.ts +334 -0
- package/dist/snapshot/index.js +5 -0
- package/dist/snapshot/index.js.map +1 -0
- package/dist/subs/index.d.ts +48 -10
- package/dist/subs/index.js +1 -1
- package/dist/testing/index.d.ts +107 -2
- package/dist/testing/index.js +204 -6
- package/dist/testing/index.js.map +1 -1
- package/dist/throttle/index.d.ts +9 -0
- package/dist/throttle/index.js +1 -52
- package/dist/throttle/index.js.map +1 -1
- package/dist/throttled-input/index.d.ts +380 -0
- package/dist/throttled-input/index.js +88 -0
- package/dist/throttled-input/index.js.map +1 -0
- package/dist/token-refresh/index.d.ts +215 -0
- package/dist/token-refresh/index.js +6 -0
- package/dist/token-refresh/index.js.map +1 -0
- package/dist/trace-replay/index.d.ts +11 -2
- package/dist/trace-replay/index.js +3 -55
- package/dist/trace-replay/index.js.map +1 -1
- package/dist/{types-CwBC5wMn.d.ts → types-B-8bcAp8.d.ts} +1 -1
- package/dist/with-deadline/index.d.ts +196 -0
- package/dist/with-deadline/index.js +111 -0
- package/dist/with-deadline/index.js.map +1 -0
- package/dist/with-resilience/index.d.ts +205 -0
- package/dist/with-resilience/index.js +251 -0
- package/dist/with-resilience/index.js.map +1 -0
- package/dist/with-telemetry/index.d.ts +149 -0
- package/dist/with-telemetry/index.js +70 -0
- package/dist/with-telemetry/index.js.map +1 -0
- package/dist/work-queue/adapter.d.ts +82 -0
- package/dist/work-queue/adapter.js +4 -0
- package/dist/work-queue/adapter.js.map +1 -0
- package/dist/work-queue/index.d.ts +25 -11
- package/dist/work-queue/index.js +1 -46
- package/dist/work-queue/index.js.map +1 -1
- package/dist/work-queue/ops.d.ts +69 -0
- package/dist/work-queue/ops.js +3 -0
- package/dist/work-queue/ops.js.map +1 -0
- package/dist/workflow/index.d.ts +450 -0
- package/dist/workflow/index.js +225 -0
- package/dist/workflow/index.js.map +1 -0
- package/package.json +168 -25
- package/dist/chunk-CMG2KMWX.js.map +0 -1
- package/dist/chunk-PYBQREFU.js.map +0 -1
- package/dist/chunk-PYOCUBQJ.js.map +0 -1
- package/dist/chunk-Y5JM3UUH.js.map +0 -1
- package/dist/chunk-ZRUST6BK.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,38 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
[K in M["type"]]: (state: S, msg: Extract<M, {
|
|
5
|
-
type: K;
|
|
6
|
-
}>) => readonly [S, readonly C[]];
|
|
7
|
-
};
|
|
8
|
-
type Transitions<S extends {
|
|
9
|
-
type: string;
|
|
10
|
-
}, M extends {
|
|
11
|
-
type: string;
|
|
12
|
-
}, C extends Cmd> = {
|
|
13
|
-
[P in S["type"]]: {
|
|
14
|
-
[K in M["type"]]: (state: Extract<S, {
|
|
15
|
-
type: P;
|
|
16
|
-
}>, msg: Extract<M, {
|
|
17
|
-
type: K;
|
|
18
|
-
}>) => readonly [S, readonly C[]];
|
|
19
|
-
};
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Compile-time exhaustiveness assertion. Use in default branches of
|
|
23
|
-
* switches over discriminated unions where every case should be handled
|
|
24
|
-
* explicitly — TS narrows the type to `never` only if every variant has
|
|
25
|
-
* been covered. Strengthens invariant 7 (identity is explicit).
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* switch (msg.type) {
|
|
29
|
-
* case "a": return ...;
|
|
30
|
-
* case "b": return ...;
|
|
31
|
-
* default: return absurd(msg); // compile error if a "c" is added
|
|
32
|
-
* }
|
|
33
|
-
*/
|
|
34
|
-
declare function absurd(x: never): never;
|
|
35
|
-
declare const noop: <S, M, C extends Cmd>(state: S, _msg: M) => readonly [S, readonly C[]];
|
|
1
|
+
import { C as Cmd, P as Port, S as Sub, M as Machine, T as Transitions, R as Reducer } from './core-BoB6t7dB.js';
|
|
2
|
+
export { b as ContextFree, I as Interpret, N as NoCtx, c as PortEmitter, a as SubId, d as Subscribe, e as SyncReturn, U as UpdateForm, f as applyCell, g as detectUpdateForm, h as foldMsgs, i as formOf, m as msgKeysOf, s as subId } from './core-BoB6t7dB.js';
|
|
3
|
+
|
|
36
4
|
/**
|
|
37
5
|
* @demlik/tea — TEA-faithful state machine substrate.
|
|
38
6
|
*
|
|
@@ -46,84 +14,26 @@ declare const noop: <S, M, C extends Cmd>(state: S, _msg: M) => readonly [S, rea
|
|
|
46
14
|
* `tryInterpret` is Railway sugar — wraps a fallible async function and routes
|
|
47
15
|
* Ok/Err to two Msg constructors via better-result.
|
|
48
16
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* The empty Cmd array. Typed `readonly never[]` so it's assignable to any
|
|
55
|
-
* `readonly C[]` for any `C extends Cmd`. Use in `init` returns and
|
|
56
|
-
* Transitions cells that emit zero effects:
|
|
57
|
-
*
|
|
58
|
-
* init: (loaded) => [loaded ?? initial, Cmd.none],
|
|
59
|
-
* tick: (state) => [state, Cmd.none],
|
|
60
|
-
*
|
|
61
|
-
* Elm's `Cmd.none` analogue. Cultural signal alongside the runtime help:
|
|
62
|
-
* `[state, Cmd.none]` reads as intent ("this transition emits nothing"),
|
|
63
|
-
* `[state, []]` reads as "empty array of what".
|
|
64
|
-
*
|
|
65
|
-
* Frozen at runtime so a downstream consumer can't `.push()` into the
|
|
66
|
-
* shared reference.
|
|
67
|
-
*/
|
|
68
|
-
readonly none: readonly never[];
|
|
69
|
-
/**
|
|
70
|
-
* Flat concat of cmd arrays. Use when a cell composes effects from
|
|
71
|
-
* multiple conditional sources:
|
|
72
|
-
*
|
|
73
|
-
* return [next, Cmd.batch(
|
|
74
|
-
* Cmd.whenDefined(state.queueItemId, (id) => ({ type: "complete", id })),
|
|
75
|
-
* Cmd.when(state.windowId !== undefined, { type: "close_window", windowId }),
|
|
76
|
-
* [{ type: "detach_debugger", tabId: state.tabId }],
|
|
77
|
-
* )];
|
|
78
|
-
*
|
|
79
|
-
* `<const C>` keeps inline cmd literals' discriminants narrow (same
|
|
80
|
-
* rationale as `when` / `whenDefined` above).
|
|
81
|
-
*/
|
|
82
|
-
readonly batch: <const C extends Cmd>(...arrs: readonly (readonly C[])[]) => readonly C[];
|
|
83
|
-
/**
|
|
84
|
-
* Emit `cmd` wrapped in a single-element array iff `cond` is true.
|
|
85
|
-
* Otherwise return the empty array. Spreads cleanly into the cmds array
|
|
86
|
-
* returned by a Transitions cell.
|
|
87
|
-
*
|
|
88
|
-
* `const C` (TypeScript 5.0+) keeps the inferred `type:` discriminator
|
|
89
|
-
* literal narrow when called with an object literal — so `Cmd.when(b,
|
|
90
|
-
* { type: "x", ... })` infers as `{ type: "x", ... }`, not `{ type:
|
|
91
|
-
* string, ... }`, and stays assignable to a discriminated-union arm
|
|
92
|
-
* without `as const` at the call site.
|
|
93
|
-
*/
|
|
94
|
-
readonly when: <const C extends Cmd>(cond: boolean, cmd: C) => readonly C[];
|
|
95
|
-
/**
|
|
96
|
-
* If `value` is defined, call `build(value)` and emit the resulting cmd
|
|
97
|
-
* wrapped in a single-element array. If `value` is `undefined`, return
|
|
98
|
-
* the empty array. `value` is narrowed to `T` inside `build`.
|
|
99
|
-
*
|
|
100
|
-
* `const C` on the return type keeps the callback's object-literal
|
|
101
|
-
* `type:` field narrow (see `when` above for the full rationale).
|
|
102
|
-
*/
|
|
103
|
-
readonly whenDefined: <T, const C extends Cmd>(value: T | undefined, build: (value: T) => C) => readonly C[];
|
|
104
|
-
};
|
|
105
|
-
type SubId = string & {
|
|
106
|
-
readonly __brand: "SubId";
|
|
17
|
+
|
|
18
|
+
declare const ReducerBrand: unique symbol;
|
|
19
|
+
type Branded<T> = T & {
|
|
20
|
+
readonly [ReducerBrand]: true;
|
|
107
21
|
};
|
|
108
22
|
/**
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* site so the type system can catch accidental raw-string drift.
|
|
23
|
+
* Compile-time exhaustiveness assertion. Use in default branches of
|
|
24
|
+
* switches over discriminated unions where every case should be handled
|
|
25
|
+
* explicitly — TS narrows the type to `never` only if every variant has
|
|
26
|
+
* been covered. Strengthens invariant 7 (identity is explicit).
|
|
114
27
|
*
|
|
115
|
-
*
|
|
28
|
+
* @example
|
|
29
|
+
* switch (msg.type) {
|
|
30
|
+
* case "a": return ...;
|
|
31
|
+
* case "b": return ...;
|
|
32
|
+
* default: return absurd(msg); // compile error if a "c" is added
|
|
33
|
+
* }
|
|
116
34
|
*/
|
|
117
|
-
declare function
|
|
118
|
-
|
|
119
|
-
id: SubId;
|
|
120
|
-
type: T;
|
|
121
|
-
};
|
|
122
|
-
interface Port<T> {
|
|
123
|
-
readonly __brand: "port";
|
|
124
|
-
readonly name: string;
|
|
125
|
-
readonly __t?: T;
|
|
126
|
-
}
|
|
35
|
+
declare function absurd(x: never): never;
|
|
36
|
+
declare const noop: <S, M, C extends Cmd>(state: S, _msg: M) => readonly [S, readonly C[]];
|
|
127
37
|
/**
|
|
128
38
|
* Thrown by `definePort` when a name has already been registered in the
|
|
129
39
|
* current process. Symmetric with the `Sub.id` collision assert in
|
|
@@ -144,6 +54,85 @@ declare class PortNameCollisionError extends Error {
|
|
|
144
54
|
* @internal test-only
|
|
145
55
|
*/
|
|
146
56
|
declare function __resetPortRegistry(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Which otherwise-unattributable runtime path produced an error.
|
|
59
|
+
*
|
|
60
|
+
* - `"follow-up"` — a follow-up Msg an interpret handler returned rejected
|
|
61
|
+
* when re-dispatched. The original dispatcher already resolved, so this
|
|
62
|
+
* rejection has no caller; without the sink it was swallowed.
|
|
63
|
+
* - `"stop-save"` — the final `store.save(state)` inside `stop()` threw.
|
|
64
|
+
* `stop()` resolves regardless (its contract), so without the sink this was
|
|
65
|
+
* silent loss of the last write.
|
|
66
|
+
* - `"reduce"` — the pure `update` (reducer) threw synchronously while folding
|
|
67
|
+
* a Msg. #71's reentrancy brand makes a reducer provably synchronous, so this
|
|
68
|
+
* throw is catchable in the dispatch loop; the configured `Supervision`
|
|
69
|
+
* strategy decides what the runtime does next (`stop` / `escalate` /
|
|
70
|
+
* `restart`), but the failure is ALWAYS surfaced here as data first.
|
|
71
|
+
*/
|
|
72
|
+
type RuntimeErrorPhase = "follow-up" | "stop-save" | "reduce";
|
|
73
|
+
/** Context handed to an `OnError` sink alongside the error itself. */
|
|
74
|
+
interface RuntimeErrorContext {
|
|
75
|
+
readonly phase: RuntimeErrorPhase;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Sink for runtime failures that have no caller to reject at. Configured via
|
|
79
|
+
* `run(machine, { onError })`. Should be total — a throw inside the sink is
|
|
80
|
+
* itself surfaced via `defaultOnError`, so the sink can never re-introduce a
|
|
81
|
+
* silent failure.
|
|
82
|
+
*/
|
|
83
|
+
type OnError = (error: unknown, context: RuntimeErrorContext) => void;
|
|
84
|
+
/** The three declared reducer-throw supervision strategies. */
|
|
85
|
+
type SupervisionStrategy = "stop" | "escalate" | "restart";
|
|
86
|
+
/**
|
|
87
|
+
* Declared supervision policy for a reducer (`update`) throw, configured at
|
|
88
|
+
* `run(machine, { supervision })`.
|
|
89
|
+
*
|
|
90
|
+
* - `{ strategy: "stop" }` — halt + surface (the safe default; also the bare
|
|
91
|
+
* shorthand `"stop"`).
|
|
92
|
+
* - `{ strategy: "escalate" }` — surface + propagate, runtime stays live (also
|
|
93
|
+
* the bare shorthand `"escalate"`).
|
|
94
|
+
* - `{ strategy: "restart", rehydrate }` — surface, then re-init from the
|
|
95
|
+
* host-supplied last-known-good `S` and keep folding. `rehydrate` receives
|
|
96
|
+
* the failing `(state, msg, error)` so the host can log / pick a snapshot;
|
|
97
|
+
* it MUST return a valid `S` synchronously (the reducer is synchronous, so
|
|
98
|
+
* recovery is too — no suspension across the single-writer slot).
|
|
99
|
+
*
|
|
100
|
+
* The bare-string shorthands (`"stop"` / `"escalate"`) are accepted for the two
|
|
101
|
+
* strategies that need no host data; `restart` MUST be the object form because
|
|
102
|
+
* it carries the `rehydrate` callback.
|
|
103
|
+
*/
|
|
104
|
+
type Supervision<S, M extends {
|
|
105
|
+
type: string;
|
|
106
|
+
}> = "stop" | "escalate" | {
|
|
107
|
+
readonly strategy: "stop";
|
|
108
|
+
} | {
|
|
109
|
+
readonly strategy: "escalate";
|
|
110
|
+
} | {
|
|
111
|
+
readonly strategy: "restart";
|
|
112
|
+
/**
|
|
113
|
+
* Host-provided rehydration to last-known-good state. Invoked by the core
|
|
114
|
+
* when the reducer throws; its return value becomes the new state and the
|
|
115
|
+
* transition continues from there. Receives the pre-throw `state`, the
|
|
116
|
+
* `msg` that triggered the throw, and the thrown `error` so the host can
|
|
117
|
+
* route by cause.
|
|
118
|
+
*/
|
|
119
|
+
readonly rehydrate: (state: S, msg: M, error: unknown) => S;
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Raised by `idle()` when the quiescence wait hits its iteration cap without
|
|
123
|
+
* the dispatch tail stabilizing. Replaces the old silent fall-through-resolve
|
|
124
|
+
* (which made "the loop quiesced" indistinguishable from "we gave up"):
|
|
125
|
+
* `idle()` now REJECTS with this so a livelocking machine surfaces instead of
|
|
126
|
+
* masquerading as quiescent.
|
|
127
|
+
*
|
|
128
|
+
* Mechanizes invariant 6 (no silent failures) at the runtime layer — the same
|
|
129
|
+
* role `PortNameCollisionError` plays for invariant 7.
|
|
130
|
+
*/
|
|
131
|
+
declare class QuiescenceTimeoutError extends Error {
|
|
132
|
+
readonly iterations: number;
|
|
133
|
+
readonly name = "QuiescenceTimeoutError";
|
|
134
|
+
constructor(iterations: number);
|
|
135
|
+
}
|
|
147
136
|
/**
|
|
148
137
|
* Define a typed port. `name` is metadata (shown in devtools / debug logs);
|
|
149
138
|
* port identity is by reference. Each definePort call must use a unique
|
|
@@ -159,78 +148,88 @@ declare function __resetPortRegistry(): void;
|
|
|
159
148
|
* Port-side counterpart of `SubId`'s id collision check in `reconcileSubs`.
|
|
160
149
|
*/
|
|
161
150
|
declare function definePort<T>(name: string): Port<T>;
|
|
162
|
-
/**
|
|
163
|
-
* Augmentation injected onto `ctx` inside Cmd handlers. Handlers receive
|
|
164
|
-
* `ctx & PortEmitter` so they can call `ctx.emit(port, value)` synchronously.
|
|
165
|
-
* Subscribers registered via `runtime.subscribePort(port, listener)` receive
|
|
166
|
-
* the value immediately.
|
|
167
|
-
*
|
|
168
|
-
* Emitting to a port with no subscribers is a no-op (does not throw).
|
|
169
|
-
*/
|
|
170
|
-
interface PortEmitter {
|
|
171
|
-
emit<T>(port: Port<T>, value: T): void;
|
|
172
|
-
}
|
|
173
|
-
type Interpret<M extends {
|
|
174
|
-
type: string;
|
|
175
|
-
}, C extends Cmd, Ctx> = {
|
|
176
|
-
[K in C["type"]]: (cmd: Extract<C, {
|
|
177
|
-
type: K;
|
|
178
|
-
}>, ctx: Ctx & PortEmitter) => Promise<M | void>;
|
|
179
|
-
};
|
|
180
|
-
type Subscribe<M extends {
|
|
181
|
-
type: string;
|
|
182
|
-
}, U extends Sub, Ctx> = {
|
|
183
|
-
[K in U["type"]]: (sub: Extract<U, {
|
|
184
|
-
type: K;
|
|
185
|
-
}>, ctx: Ctx, dispatch: (msg: M) => void) => () => void;
|
|
186
|
-
};
|
|
187
|
-
type Machine<S, M extends {
|
|
188
|
-
type: string;
|
|
189
|
-
}, C extends Cmd, U extends Sub, Ctx> = {
|
|
190
|
-
/**
|
|
191
|
-
* Boot the runtime. Called once by `run(...)` with whatever `Store.load()`
|
|
192
|
-
* returned: `null` on fresh boot, the persisted state on rehydrate.
|
|
193
|
-
*
|
|
194
|
-
* **Contract:** when `loaded !== null`, init MUST return `[loaded, []]` —
|
|
195
|
-
* no Cmds. Init's rehydrate branch is the migration / parse boundary, not
|
|
196
|
-
* the boot-effect hook. See Invariant 2 in `.patterns/tea/tea-invariants.md`.
|
|
197
|
-
*
|
|
198
|
-
* Boot effects routes:
|
|
199
|
-
* - Stateless infrastructure → host module top, outside TEA.
|
|
200
|
-
* - State-conditional resume → a `boot` Msg the host dispatches once
|
|
201
|
-
* after `run(...)` returns.
|
|
202
|
-
*
|
|
203
|
-
* Violations are caught at runtime by `replay` (which throws with a
|
|
204
|
-
* pointer to the alternatives).
|
|
205
|
-
*/
|
|
206
|
-
init: (loaded: S | null, ctx: Ctx) => readonly [S, readonly C[]];
|
|
207
|
-
update: Reducer<S, M, C> | ([S] extends [{
|
|
208
|
-
type: string;
|
|
209
|
-
}] ? Transitions<S, M, C> : never);
|
|
210
|
-
subscriptions?: (state: S) => readonly U[];
|
|
211
|
-
subscribe?: Subscribe<M, U, Ctx>;
|
|
212
|
-
} & ([C] extends [Cmd<never>] ? {
|
|
213
|
-
interpret?: Interpret<M, C, Ctx>;
|
|
214
|
-
} : {
|
|
215
|
-
interpret: Interpret<M, C, Ctx>;
|
|
216
|
-
});
|
|
217
151
|
interface Store<S> {
|
|
218
152
|
load(): Promise<unknown>;
|
|
219
153
|
save(state: S): Promise<void>;
|
|
220
154
|
migrate(raw: unknown): S | null;
|
|
221
155
|
}
|
|
156
|
+
type DispatchSettle = "quiescent" | "once";
|
|
222
157
|
interface RuntimeRef<M extends {
|
|
223
158
|
type: string;
|
|
224
159
|
}> {
|
|
225
|
-
|
|
160
|
+
/**
|
|
161
|
+
* Put a Msg in the runtime's inbox and resolve once it has been processed.
|
|
162
|
+
*
|
|
163
|
+
* Runs to QUIESCENCE by default (issue #50): the returned promise settles
|
|
164
|
+
* only after the dispatched Msg AND every follow-up Msg its `interpret`
|
|
165
|
+
* handlers (transitively) returned have drained off the serial tail. This is
|
|
166
|
+
* the safe default — `await dispatch(msg)` means "the consequences have run",
|
|
167
|
+
* not "one transition fired and the rest are racing". Pass
|
|
168
|
+
* `{ settle: "once" }` (or call `dispatchOnce`) for the rare single-step
|
|
169
|
+
* case where the caller will await the tail itself.
|
|
170
|
+
*
|
|
171
|
+
* Rejection ordering: the ONE dispatched transition's own failure (a reducer
|
|
172
|
+
* / save / sub-start / interpret throw) surfaces first, on this promise. If
|
|
173
|
+
* that transition succeeds but the follow-up chain never stabilizes, the
|
|
174
|
+
* quiescent drain rejects with `QuiescenceTimeoutError` (same cap and same
|
|
175
|
+
* no-silent-give-up contract as `idle()` — issue #51). Follow-up Msg
|
|
176
|
+
* rejections themselves route to the `onError` sink, never here.
|
|
177
|
+
*/
|
|
178
|
+
dispatch(msg: M, opts?: {
|
|
179
|
+
readonly settle?: DispatchSettle;
|
|
180
|
+
}): Promise<void>;
|
|
181
|
+
/**
|
|
182
|
+
* Dispatch `msg` and resolve after exactly ONE transition's effects settle,
|
|
183
|
+
* WITHOUT draining the follow-up chain. Equivalent to
|
|
184
|
+
* `dispatch(msg, { settle: "once" })`.
|
|
185
|
+
*
|
|
186
|
+
* This is the old (pre-#50) `dispatch` behavior, kept as an explicit escape
|
|
187
|
+
* hatch: a caller that wants to interleave its own work between the first
|
|
188
|
+
* transition and its follow-ups, then `await runtime.idle()` itself. Prefer
|
|
189
|
+
* plain `dispatch` (run-to-quiescence) unless you specifically need the
|
|
190
|
+
* single step — the un-awaited follow-up chain is exactly the footgun #50
|
|
191
|
+
* removed from the default.
|
|
192
|
+
*/
|
|
193
|
+
dispatchOnce(msg: M): Promise<void>;
|
|
226
194
|
}
|
|
227
|
-
interface
|
|
195
|
+
interface BootingRuntime<S, M extends {
|
|
228
196
|
type: string;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
|
|
197
|
+
}, E extends {
|
|
198
|
+
type: string;
|
|
199
|
+
} = never> extends RuntimeRef<M> {
|
|
200
|
+
dispatch(msg: M, opts?: {
|
|
201
|
+
readonly settle?: DispatchSettle;
|
|
202
|
+
}): Promise<void>;
|
|
203
|
+
dispatchOnce(msg: M): Promise<void>;
|
|
232
204
|
subscribe(listener: () => void): () => void;
|
|
233
|
-
observe(observer: (msg: M
|
|
205
|
+
observe(observer: (msg: M, state: S) => void): () => void;
|
|
206
|
+
/**
|
|
207
|
+
* Subscribe to the INITIAL State — the boot transition the old `observe`
|
|
208
|
+
* `msg === null` arm carried (#47). Fires exactly once: immediately if boot
|
|
209
|
+
* has already completed when `onBoot` is called (so a late subscriber never
|
|
210
|
+
* misses it), otherwise on the boot fanout. Returns a cleanup that detaches
|
|
211
|
+
* the handler (a no-op once it has fired).
|
|
212
|
+
*
|
|
213
|
+
* This is where the boot case the `observe` firehose used to fold in went
|
|
214
|
+
* once `observe`'s `msg` became total: a consumer that needs to seed a view
|
|
215
|
+
* from the initial State wires `onBoot`; a consumer that only folds events
|
|
216
|
+
* (the common case) wires `observe` (or `on`) and is no longer handed a boot
|
|
217
|
+
* arm to skip.
|
|
218
|
+
*/
|
|
219
|
+
onBoot(handler: (state: S) => void): () => void;
|
|
220
|
+
/**
|
|
221
|
+
* Subscribe to a SEMANTIC event of `type` (#47). Typed narrowing: the handler
|
|
222
|
+
* receives exactly the `E` member whose `type` matches `K`, so a consumer
|
|
223
|
+
* built on `on("TurnSettled", …)` never touches another event's shape and —
|
|
224
|
+
* critically — never references the machine's PRIVATE Msg names. Returns a
|
|
225
|
+
* cleanup that detaches the handler. Multiple handlers per type are
|
|
226
|
+
* supported; fanout is synchronous and throw-isolated (same discipline as
|
|
227
|
+
* `observe`). Fires only when the machine's `events` projector (wired on
|
|
228
|
+
* `run`) emits an event of that type for a transition.
|
|
229
|
+
*/
|
|
230
|
+
on<K extends E["type"]>(type: K, handler: (event: Extract<E, {
|
|
231
|
+
type: K;
|
|
232
|
+
}>) => void): () => void;
|
|
234
233
|
/**
|
|
235
234
|
* Subscribe to a typed Port. Returns a cleanup function that removes the
|
|
236
235
|
* listener. Multiple listeners per port are supported; fanout is synchronous
|
|
@@ -263,26 +262,119 @@ interface Runtime<S, M extends {
|
|
|
263
262
|
*/
|
|
264
263
|
emitPort<T>(port: Port<T>, value: T): void;
|
|
265
264
|
/**
|
|
266
|
-
* Resolves after boot completes — i.e. after
|
|
267
|
-
* `store.
|
|
268
|
-
* init-emitted cmds, and the initial
|
|
269
|
-
* the boot error if boot fails (the
|
|
270
|
-
* call rejects with).
|
|
265
|
+
* Resolves to the booted `Runtime<S, M>` after boot completes — i.e. after
|
|
266
|
+
* `store.load()` (if any), `init`, `store.save()` of the initial state,
|
|
267
|
+
* `reconcileSubs`, `interpret` of any init-emitted cmds, and the initial
|
|
268
|
+
* listener / observer fanout. Rejects with the boot error if boot fails (the
|
|
269
|
+
* same error every subsequent `dispatch` call rejects with).
|
|
270
|
+
*
|
|
271
|
+
* This is the ONLY way to obtain a `Runtime<S, M>` — and a `Runtime` is the
|
|
272
|
+
* only handle whose `getState()` is total. Awaiting `ready` is therefore the
|
|
273
|
+
* single gate between "boot in flight" and "State exists":
|
|
274
|
+
*
|
|
275
|
+
* ```ts
|
|
276
|
+
* const runtime = await run(machine, opts).ready;
|
|
277
|
+
* runtime.getState(); // total — never throws-before-boot
|
|
278
|
+
* ```
|
|
271
279
|
*
|
|
272
280
|
* Idempotent — subsequent reads return the same settled promise. The runtime
|
|
273
|
-
* holds exactly one `ready` promise per `run()` call
|
|
281
|
+
* holds exactly one `ready` promise per `run()` call; it resolves to the same
|
|
282
|
+
* `Runtime` object every time.
|
|
274
283
|
*
|
|
275
|
-
* Closes the v1 boot-await gap
|
|
276
|
-
* components that need synchronous initial
|
|
277
|
-
* `useSyncExternalStore` consumers)
|
|
278
|
-
*
|
|
284
|
+
* Closes issue #45 (the `getState()` lie) and the v1 boot-await gap once
|
|
285
|
+
* documented in `stepBootEffects`: components that need synchronous initial
|
|
286
|
+
* state under a store (e.g. `useSyncExternalStore` consumers) await `ready`
|
|
287
|
+
* for the booted runtime instead of dispatching a no-op Msg.
|
|
279
288
|
*
|
|
280
289
|
* Expresses canon §2.3 (the `init` contract — boot is a named, awaitable
|
|
281
290
|
* moment). Strengthens invariant 6 (runtime is small and inspectable).
|
|
282
291
|
*/
|
|
283
|
-
ready: Promise<
|
|
292
|
+
ready: Promise<Runtime<S, M, E>>;
|
|
284
293
|
stop(): Promise<void>;
|
|
285
294
|
}
|
|
295
|
+
interface Runtime<S, M extends {
|
|
296
|
+
type: string;
|
|
297
|
+
}, E extends {
|
|
298
|
+
type: string;
|
|
299
|
+
} = never> extends BootingRuntime<S, M, E> {
|
|
300
|
+
/**
|
|
301
|
+
* The current State. TOTAL — never throws. Obtaining a `Runtime` requires
|
|
302
|
+
* awaiting `ready`, which only resolves AFTER boot has run `init` and set the
|
|
303
|
+
* initial State; a `Runtime` therefore always has a State to return. (Before
|
|
304
|
+
* #45 this was declared on the synchronously-returned handle and threw under
|
|
305
|
+
* a store until boot finished — the type lied. It no longer does.)
|
|
306
|
+
*/
|
|
307
|
+
getState(): S;
|
|
308
|
+
/**
|
|
309
|
+
* Resolves to this same `Runtime` once boot completes. Idempotent.
|
|
310
|
+
*/
|
|
311
|
+
ready: Promise<Runtime<S, M, E>>;
|
|
312
|
+
/**
|
|
313
|
+
* Resolves once the runtime has reached QUIESCENCE — every dispatched Msg AND
|
|
314
|
+
* every follow-up Msg an interpret handler returned has been processed, with
|
|
315
|
+
* no further step pending on the serial tail.
|
|
316
|
+
*
|
|
317
|
+
* Since #50, plain `dispatch(msg)` already runs to quiescence (it awaits this
|
|
318
|
+
* same drain after its own transition), so a caller rarely needs `idle()`
|
|
319
|
+
* directly. `idle()` is still the right tool to (a) settle follow-ups left in
|
|
320
|
+
* flight by a `dispatchOnce` / `dispatch(msg, { settle: "once" })` single
|
|
321
|
+
* step, or (b) wait out a follow-up chain kicked off by a Sub or by boot
|
|
322
|
+
* `init` cmds where there was no `dispatch` call to await. It chains onto the
|
|
323
|
+
* current tail and re-checks until the tail stops advancing, draining the
|
|
324
|
+
* entire transitive follow-up chain.
|
|
325
|
+
*
|
|
326
|
+
* Idempotent and re-entrant-safe: each call reads the live tail; a tail that
|
|
327
|
+
* advanced during the await (a follow-up landed) is awaited again until
|
|
328
|
+
* stable. Tail rejections are NOT surfaced here — a failing dispatch
|
|
329
|
+
* surfaces on its OWN returned promise (and follow-up rejections route to
|
|
330
|
+
* the `onError` sink). The ONE rejection `idle()` itself produces is a
|
|
331
|
+
* `QuiescenceTimeoutError` when the wait hits its iteration cap without the
|
|
332
|
+
* tail stabilizing: that replaces the old silent fall-through-resolve so a
|
|
333
|
+
* livelocking machine is distinguishable from a genuinely quiesced one
|
|
334
|
+
* (invariant 6 — no silent failures).
|
|
335
|
+
*
|
|
336
|
+
* Use `idle()` for runtime-internal follow-ups; a poll is still correct when
|
|
337
|
+
* waiting on an EXTERNAL event (a WS reply) the runtime cannot enqueue itself.
|
|
338
|
+
*
|
|
339
|
+
* Strengthens invariant 6 (runtime is small and inspectable — quiescence is a
|
|
340
|
+
* first-class awaitable moment, not a poll the consumer re-derives).
|
|
341
|
+
*/
|
|
342
|
+
idle(): Promise<void>;
|
|
343
|
+
/**
|
|
344
|
+
* The terminal State of the run, or `undefined` while it is still in flight.
|
|
345
|
+
* A run is "terminal" exactly when the `terminal` predicate passed to `run()`
|
|
346
|
+
* returns `true` for the current State; with no predicate supplied a run is
|
|
347
|
+
* never terminal and this always returns `undefined`.
|
|
348
|
+
*
|
|
349
|
+
* This is the FIRST-CLASS result read (issue #46): the outcome of running the
|
|
350
|
+
* thing, off the State the machine already owns — NOT scraped off the
|
|
351
|
+
* `observe` firehose by matching an internal Msg name (`resilient_ok`) and
|
|
352
|
+
* racing a state-clear. The consumer reads the run's product (e.g. an agent's
|
|
353
|
+
* `state.output`) off the returned `S`, with no coupling to the machine's
|
|
354
|
+
* private retry / loop vocabulary.
|
|
355
|
+
*
|
|
356
|
+
* Total — never throws (a `Runtime` always has a State; see `getState`).
|
|
357
|
+
*/
|
|
358
|
+
result(): S | undefined;
|
|
359
|
+
/**
|
|
360
|
+
* Resolves with the terminal State the first time the run reaches a terminal
|
|
361
|
+
* State (per the `terminal` predicate passed to `run()`). If the run is
|
|
362
|
+
* ALREADY terminal when `done()` is called, resolves immediately with the
|
|
363
|
+
* current State; otherwise resolves on the transition that first makes
|
|
364
|
+
* `terminal` hold.
|
|
365
|
+
*
|
|
366
|
+
* The awaitable companion to `result()` — "wait for the run to finish, then
|
|
367
|
+
* hand me what it produced" in one call, instead of polling `result()` or
|
|
368
|
+
* hand-rolling an `observe` loop that watches for a private terminal Msg.
|
|
369
|
+
* With no `terminal` predicate supplied the run is never terminal, so this
|
|
370
|
+
* promise never resolves (a non-terminating machine has no result to await).
|
|
371
|
+
*
|
|
372
|
+
* Idempotent and multi-caller safe: every call observes the live State, so a
|
|
373
|
+
* call made after the run already terminated resolves at once, and concurrent
|
|
374
|
+
* callers all settle on the same terminal transition.
|
|
375
|
+
*/
|
|
376
|
+
done(): Promise<S>;
|
|
377
|
+
}
|
|
286
378
|
declare function defineMachine<S, M extends {
|
|
287
379
|
type: string;
|
|
288
380
|
}, C extends Cmd, U extends Sub, Ctx>(m: Omit<Machine<S, M, C, U, Ctx>, "update"> & {
|
|
@@ -295,12 +387,66 @@ declare function defineMachine<S, M extends {
|
|
|
295
387
|
}, C extends Cmd, U extends Sub, Ctx>(m: Omit<Machine<S, M, C, U, Ctx>, "update"> & {
|
|
296
388
|
update: Reducer<S, M, C>;
|
|
297
389
|
}): Machine<S, M, C, U, Ctx>;
|
|
298
|
-
declare function
|
|
390
|
+
declare function asReducer<S, M extends {
|
|
299
391
|
type: string;
|
|
300
|
-
}, C extends Cmd
|
|
392
|
+
}, C extends Cmd>(reducer: Reducer<S, M, C>): Branded<Reducer<S, M, C>>;
|
|
393
|
+
type CtxArg<Ctx> = [Record<never, never>] extends [Ctx] ? {
|
|
394
|
+
ctx?: Ctx;
|
|
395
|
+
} : {
|
|
301
396
|
ctx: Ctx;
|
|
397
|
+
};
|
|
398
|
+
declare function run<S, M extends {
|
|
399
|
+
type: string;
|
|
400
|
+
}, C extends Cmd, U extends Sub, Ctx, E extends {
|
|
401
|
+
type: string;
|
|
402
|
+
} = never>(machine: Machine<S, M, C, U, Ctx>, opts: CtxArg<Ctx> & {
|
|
302
403
|
store?: Store<S>;
|
|
303
|
-
|
|
404
|
+
onError?: OnError;
|
|
405
|
+
/**
|
|
406
|
+
* The SEMANTIC event projector (#47). Maps one APPLIED transition `(msg,
|
|
407
|
+
* state)` to zero-or-more public events of the machine-level union `E`.
|
|
408
|
+
* Returning `[]` skips the transition (it produced no event the consumer's
|
|
409
|
+
* `on(type, …)` cares about). This is where a machine maps its PRIVATE Msg
|
|
410
|
+
* vocabulary (a retry plumbing's `resilient_ok`, a tool loop's
|
|
411
|
+
* `agent_tool_ok`) to NAMED events — the private names live only inside this
|
|
412
|
+
* closure and never reach `on`'s `E` surface. Omit → the run has no event
|
|
413
|
+
* surface (`E = never`) and `on` is uncallable.
|
|
414
|
+
*
|
|
415
|
+
* PURE — called inside the dispatch loop on the freshly-folded `(msg,
|
|
416
|
+
* state)`; it must not read the clock, mutate, or throw (a throw is
|
|
417
|
+
* isolated like an observer throw, never stranding the transition).
|
|
418
|
+
*/
|
|
419
|
+
events?: (msg: M, state: S) => readonly E[];
|
|
420
|
+
/**
|
|
421
|
+
* Declared policy for when the pure `update` (reducer) throws. The reducer
|
|
422
|
+
* throw is always surfaced via `onError` (`phase: "reduce"`); the strategy
|
|
423
|
+
* decides what the runtime does next. Defaults to `"stop"` — the explicit,
|
|
424
|
+
* safe choice (surface + halt, never a silent resume). See `Supervision`.
|
|
425
|
+
*/
|
|
426
|
+
supervision?: Supervision<S, M>;
|
|
427
|
+
/**
|
|
428
|
+
* The run-terminality predicate — what makes the run's outcome first-class
|
|
429
|
+
* (issue #46). Returns `true` for a State the run has finished in (e.g. an
|
|
430
|
+
* agent's `state.run.phase === "done"`). The runtime feeds it to
|
|
431
|
+
* `Runtime.result()` (the terminal State, or `undefined` in flight) and
|
|
432
|
+
* `Runtime.done()` (resolves with the terminal State when it first holds).
|
|
433
|
+
*
|
|
434
|
+
* PURE — the runtime calls it inside the dispatch loop on the freshly-folded
|
|
435
|
+
* State; it must not read the clock, mutate, or throw. Omit → the run is
|
|
436
|
+
* never terminal: `result()` always returns `undefined` and `done()` never
|
|
437
|
+
* resolves (the right behavior for a machine with no natural completion).
|
|
438
|
+
*/
|
|
439
|
+
terminal?: (state: S) => boolean;
|
|
440
|
+
/**
|
|
441
|
+
* Iteration cap for `idle()`'s quiescence wait. Defaults to 100_000. Test
|
|
442
|
+
* seam only — lets a livelock test trip the `QuiescenceTimeoutError` reject
|
|
443
|
+
* path in a handful of iterations instead of 100k. Production code must not
|
|
444
|
+
* set it.
|
|
445
|
+
*
|
|
446
|
+
* @internal test-only
|
|
447
|
+
*/
|
|
448
|
+
__idleCap?: number;
|
|
449
|
+
}): BootingRuntime<S, M, E>;
|
|
304
450
|
interface HistoryTracker<S, M extends {
|
|
305
451
|
type: string;
|
|
306
452
|
}> {
|
|
@@ -335,11 +481,15 @@ interface HistoryTracker<S, M extends {
|
|
|
335
481
|
* to the runtime via `observe(...)` and retains the last `size` `(msg,
|
|
336
482
|
* state)` transitions in a FIFO ring buffer.
|
|
337
483
|
*
|
|
338
|
-
* @param runtime Any `
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
484
|
+
* @param runtime Any `BootingRuntime<S, M>` (a full `Runtime` satisfies it).
|
|
485
|
+
* The tracker uses only `observe`, which is total before boot —
|
|
486
|
+
* attach it to the synchronous `run()` handle to record the
|
|
487
|
+
* boot transition.
|
|
488
|
+
* @param size Buffer cap. `size <= 0` produces an inert no-op tracker:
|
|
489
|
+
* no observer is attached to the runtime, `snapshot()` is
|
|
490
|
+
* always `[]`, and `stop()` is a no-op. (Prefer skipping the
|
|
491
|
+
* tracker entirely in that case — this arm just makes a
|
|
492
|
+
* non-positive `size` harmless rather than an error.)
|
|
343
493
|
*
|
|
344
494
|
* Memory cost: O(size × avg(msg + state size)). For audit-extension's
|
|
345
495
|
* inspector use case (size 100, audit state ~5KB), ~500KB max — held
|
|
@@ -347,7 +497,7 @@ interface HistoryTracker<S, M extends {
|
|
|
347
497
|
*/
|
|
348
498
|
declare function historyTracker<S, M extends {
|
|
349
499
|
type: string;
|
|
350
|
-
}>(runtime:
|
|
500
|
+
}>(runtime: BootingRuntime<S, M>, size: number): HistoryTracker<S, M>;
|
|
351
501
|
declare function replay<S, M extends {
|
|
352
502
|
type: string;
|
|
353
503
|
}, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, opts: {
|
|
@@ -361,4 +511,4 @@ declare function replay<S, M extends {
|
|
|
361
511
|
};
|
|
362
512
|
declare function tryInterpret<C extends Cmd, Ok, M, Ctx>(work: (cmd: C, ctx: Ctx) => Promise<Ok>, onOk: (value: Ok, cmd: C) => M, onErr: (error: unknown, cmd: C) => M): (cmd: C, ctx: Ctx) => Promise<M>;
|
|
363
513
|
|
|
364
|
-
export {
|
|
514
|
+
export { type BootingRuntime, type Branded, Cmd, type CtxArg, type DispatchSettle, type HistoryTracker, Machine, type OnError, Port, PortNameCollisionError, QuiescenceTimeoutError, Reducer, type Runtime, type RuntimeErrorContext, type RuntimeErrorPhase, type RuntimeRef, type Store, Sub, type Supervision, type SupervisionStrategy, Transitions, __resetPortRegistry, absurd, asReducer, defineMachine, definePort, historyTracker, noop, replay, run, tryInterpret };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { PortNameCollisionError, QuiescenceTimeoutError, __resetPortRegistry, absurd, asReducer, defineMachine, definePort, historyTracker, noop, replay, run, tryInterpret } from './chunk-MMH7CW5K.js';
|
|
2
|
+
export { Cmd, applyCell, detectUpdateForm, foldMsgs, formOf, msgKeysOf, subId } from './chunk-QLA76GIT.js';
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
|
3
4
|
//# sourceMappingURL=index.js.map
|