@demlik/tea 0.15.0 → 0.16.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.
Files changed (115) hide show
  1. package/README.md +30 -7
  2. package/dist/agent/index.d.ts +49 -37
  3. package/dist/agent/index.js +12 -8
  4. package/dist/chunk-4LPY67E4.js +18 -0
  5. package/dist/chunk-4LPY67E4.js.map +1 -0
  6. package/dist/chunk-5XU6ZJO2.js +533 -0
  7. package/dist/chunk-5XU6ZJO2.js.map +1 -0
  8. package/dist/{chunk-AYS5N6WY.js → chunk-6NG4V5SB.js} +62 -172
  9. package/dist/chunk-6NG4V5SB.js.map +1 -0
  10. package/dist/{chunk-3B5X7SBB.js → chunk-7MGXQZPW.js} +11 -9
  11. package/dist/chunk-7MGXQZPW.js.map +1 -0
  12. package/dist/{chunk-V46HSVCK.js → chunk-BCTEOVOU.js} +3 -3
  13. package/dist/{chunk-V46HSVCK.js.map → chunk-BCTEOVOU.js.map} +1 -1
  14. package/dist/chunk-CH5KTOEZ.js +710 -0
  15. package/dist/chunk-CH5KTOEZ.js.map +1 -0
  16. package/dist/chunk-CIHSHLQX.js +64 -0
  17. package/dist/chunk-CIHSHLQX.js.map +1 -0
  18. package/dist/{chunk-TCLBCERH.js → chunk-EHUDXAKC.js} +238 -212
  19. package/dist/chunk-EHUDXAKC.js.map +1 -0
  20. package/dist/chunk-GOX2CYIM.js +380 -0
  21. package/dist/chunk-GOX2CYIM.js.map +1 -0
  22. package/dist/{chunk-22POWGFA.js → chunk-IVJP3GKJ.js} +46 -20
  23. package/dist/chunk-IVJP3GKJ.js.map +1 -0
  24. package/dist/{chunk-QPEVCJ5Q.js → chunk-MVZS5FDM.js} +13 -6
  25. package/dist/chunk-MVZS5FDM.js.map +1 -0
  26. package/dist/{chunk-VTQI2NHP.js → chunk-MYNLY3HP.js} +9 -8
  27. package/dist/chunk-MYNLY3HP.js.map +1 -0
  28. package/dist/{chunk-Q5CQTBFA.js → chunk-NSIAORRY.js} +20 -30
  29. package/dist/chunk-NSIAORRY.js.map +1 -0
  30. package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
  31. package/dist/chunk-QNGYQMZB.js.map +1 -0
  32. package/dist/chunk-WT5PBPLB.js +98 -0
  33. package/dist/chunk-WT5PBPLB.js.map +1 -0
  34. package/dist/{core-DnzqWy6u.d.ts → core-BbgtiXdg.d.ts} +231 -139
  35. package/dist/do/index.d.ts +37 -33
  36. package/dist/do/index.js +21 -14
  37. package/dist/do/index.js.map +1 -1
  38. package/dist/{durable-effects-CWzA-o2B.d.ts → durable-effects-7MTK_jnj.d.ts} +1 -1
  39. package/dist/effect/index.d.ts +151 -0
  40. package/dist/effect/index.js +98 -0
  41. package/dist/effect/index.js.map +1 -0
  42. package/dist/extension/index.d.ts +6 -7
  43. package/dist/extension/index.js +3 -2
  44. package/dist/extension/index.js.map +1 -1
  45. package/dist/flow/index.d.ts +68 -59
  46. package/dist/flow/index.js +32 -27
  47. package/dist/flow/index.js.map +1 -1
  48. package/dist/idempotency/index.d.ts +6 -7
  49. package/dist/idempotency/index.js +4 -2
  50. package/dist/{index-CSyMYDAB.d.ts → index-7vV8xmsD.d.ts} +1 -1
  51. package/dist/{index-KXqTRJyb.d.ts → index-Bz5Rh9Ga.d.ts} +19 -96
  52. package/dist/index-CjFDUBeq.d.ts +207 -0
  53. package/dist/{index-CuNO9m8i.d.ts → index-CkFYA9Y6.d.ts} +14 -16
  54. package/dist/{index-CA_7I5g9.d.ts → index-Cou86-GX.d.ts} +137 -246
  55. package/dist/{index-DrIRb_Ch.d.ts → index-DU6JpQ8G.d.ts} +1 -1
  56. package/dist/{index-HSYgG2Yt.d.ts → index-Xufl55W8.d.ts} +247 -211
  57. package/dist/{index-C2DwkjlP.d.ts → index-_dOR3xqA.d.ts} +57 -45
  58. package/dist/index.d.ts +121 -385
  59. package/dist/index.js +2 -1
  60. package/dist/jev/index.d.ts +133 -97
  61. package/dist/jev/index.js +205 -161
  62. package/dist/jev/index.js.map +1 -1
  63. package/dist/{machine-DGlPWCWI.d.ts → machine-BQzTV8On.d.ts} +171 -288
  64. package/dist/machine-viz/index.d.ts +5 -5
  65. package/dist/machine-viz/index.js +8 -4
  66. package/dist/machine-viz/index.js.map +1 -1
  67. package/dist/mem/index.d.ts +3 -4
  68. package/dist/mem/index.js +2 -1
  69. package/dist/mem/index.js.map +1 -1
  70. package/dist/node/index.d.ts +119 -78
  71. package/dist/node/index.js +52 -38
  72. package/dist/node/index.js.map +1 -1
  73. package/dist/paginate/index.d.ts +27 -22
  74. package/dist/paginate/index.js +6 -4
  75. package/dist/parity/index.d.ts +4 -5
  76. package/dist/parity/index.js +3 -2
  77. package/dist/parity/index.js.map +1 -1
  78. package/dist/pbt/index.d.ts +2 -2
  79. package/dist/pbt/index.js +2 -1
  80. package/dist/pbt/index.js.map +1 -1
  81. package/dist/persistence/index.d.ts +6 -7
  82. package/dist/persistence/index.js +5 -3
  83. package/dist/promise/index.d.ts +186 -0
  84. package/dist/promise/index.js +5 -0
  85. package/dist/promise/index.js.map +1 -0
  86. package/dist/{protocol-D8VbH-VH.d.ts → protocol-ClRZBhHQ.d.ts} +7 -8
  87. package/dist/react/index.d.ts +36 -17
  88. package/dist/react/index.js +27 -4
  89. package/dist/react/index.js.map +1 -1
  90. package/dist/resilience/index.d.ts +63 -456
  91. package/dist/resilience/index.js +37 -483
  92. package/dist/resilience/index.js.map +1 -1
  93. package/dist/{runtime-types-CMF13BBh.d.ts → runtime-types-CiVpC0HN.d.ts} +131 -388
  94. package/dist/testing/index.d.ts +22 -16
  95. package/dist/testing/index.js +15 -7
  96. package/dist/testing/index.js.map +1 -1
  97. package/dist/timing/index.d.ts +25 -22
  98. package/dist/timing/index.js +4 -3
  99. package/dist/timing/index.js.map +1 -1
  100. package/dist/{types-BseNPIhr.d.ts → types-LxZxGYda.d.ts} +2 -2
  101. package/dist/work-queue/index.d.ts +5 -6
  102. package/package.json +18 -5
  103. package/dist/chunk-22POWGFA.js.map +0 -1
  104. package/dist/chunk-3B5X7SBB.js.map +0 -1
  105. package/dist/chunk-66PY5WYF.js +0 -1816
  106. package/dist/chunk-66PY5WYF.js.map +0 -1
  107. package/dist/chunk-AYS5N6WY.js.map +0 -1
  108. package/dist/chunk-L3TND7LA.js +0 -97
  109. package/dist/chunk-L3TND7LA.js.map +0 -1
  110. package/dist/chunk-MYXFNWAJ.js.map +0 -1
  111. package/dist/chunk-Q5CQTBFA.js.map +0 -1
  112. package/dist/chunk-QPEVCJ5Q.js.map +0 -1
  113. package/dist/chunk-TCLBCERH.js.map +0 -1
  114. package/dist/chunk-VTQI2NHP.js.map +0 -1
  115. package/dist/index-ZCMhnVKN.d.ts +0 -272
@@ -1,6 +1,6 @@
1
- import { a as CmdOf, b as CmdDef, i as NoCtx, C as Cmd } from './core-DnzqWy6u.js';
1
+ import { c as CmdOf, b as CmdDef, g as TaggedError, r as MalformedResult, T as TimerDeps, C as Cmd } from './core-BbgtiXdg.js';
2
2
  import { RetryState, AnyRetryPolicy } from './retry-backoff/index.js';
3
- import { T as TtlCache, D as DeadlineExceeded, a as DeadlineSub, s as subscribeDeadline } from './index-HSYgG2Yt.js';
3
+ import { T as TtlCache, D as DeadlineExceeded, a as DeadlineSub } from './index-Xufl55W8.js';
4
4
 
5
5
  /**
6
6
  * @packageDocumentation
@@ -352,18 +352,18 @@ interface DeadlineConfig {
352
352
  readonly ms: number;
353
353
  }
354
354
  /**
355
- * The family every unnamed knob speaks: `resilient_run` / `resilient_ok` /
356
- * `resilient_err`. Identical to the `MsgType.Resilient*` literals, which stay
357
- * the vocabulary of every knob that passes no name.
355
+ * The family every unnamed knob speaks: `resilient_run` / `resilient_run_ok` /
356
+ * `resilient_run_err`. Identical to the `MsgType.Resilient*` literals, which
357
+ * stay the vocabulary of every knob that passes no name.
358
358
  */
359
359
  declare const DEFAULT_RESILIENT_NAME = "resilient";
360
360
  type DefaultResilientName = typeof DEFAULT_RESILIENT_NAME;
361
361
  /** The run Cmd's `type` for the `N` family. */
362
362
  type ResilientRunType<N extends string> = `${N}_run`;
363
- /** The success settle Msg's `type` for the `N` family. */
364
- type ResilientOkType<N extends string> = `${N}_ok`;
365
- /** The failure settle Msg's `type` for the `N` family. */
366
- type ResilientErrType<N extends string> = `${N}_err`;
363
+ /** The success settle Msg's `type` for the `N` family — minted by the engine. */
364
+ type ResilientOkType<N extends string> = `${N}_run_ok`;
365
+ /** The failure settle Msg's `type` for the `N` family — minted by the engine. */
366
+ type ResilientErrType<N extends string> = `${N}_run_err`;
367
367
  /**
368
368
  * The resilience knob. EVERY field is optional: omit a brick and its gate is
369
369
  * skipped entirely (the slice still carries a default brick state so the shape
@@ -375,12 +375,13 @@ type ResilientErrType<N extends string> = `${N}_err`;
375
375
  */
376
376
  interface ResilientConfig<N extends string = DefaultResilientName> {
377
377
  /**
378
- * What this knob's Cmd and settle Msgs are called: `<name>_run`, `<name>_ok`,
379
- * `<name>_err`. Omit it and the family is `resilient` — `resilient_run` /
380
- * `resilient_ok` / `resilient_err`, exactly as before this parameter existed.
378
+ * What this knob's Cmd and settle Msgs are called: `<name>_run`, and the
379
+ * `<name>_run_ok` / `<name>_run_err` the engine mints from the run handler's
380
+ * outcome. Omit it and the family is `resilient` — `resilient_run` /
381
+ * `resilient_run_ok` / `resilient_run_err`.
381
382
  *
382
- * Name a knob when a machine mounts more than one of the resilient family.
383
- * Two unnamed knobs meet in ONE `resilient_ok` cell whose payload is the union
383
+ * Name a knob when a machine holds more than one of the resilient family.
384
+ * Two unnamed knobs meet in ONE `resilient_run_ok` cell whose payload is the union
384
385
  * of both results, and the consumer discriminates by hand on `key` — which the
385
386
  * type checker cannot see. Under distinct names each knob settles into its own
386
387
  * cell, already narrowed to its own payload.
@@ -398,7 +399,7 @@ interface ResilientConfig<N extends string = DefaultResilientName> {
398
399
  * wall-clock outage budget (`DurationRetryPolicy`), or explicit
399
400
  * `unbounded: true`. A duration bound needs no extra wiring: every path that
400
401
  * records a failure already holds the instant it was observed as DATA —
401
- * `fail`'s `msg.at` (stamped at the interpret boundary) and `gate`'s `at`
402
+ * `settle`'s `msg.at` (stamped at the interpret boundary) and `gate`'s `at`
402
403
  * (the caller's `attempt` / the retry timer's `atMs`) — so the streak clock
403
404
  * is fed from a Msg, never from a `Date.now()` inside a verb (invariant 2).
404
405
  */
@@ -441,7 +442,7 @@ interface CallBudget {
441
442
  * `phase` so each phase carries only its own data (pattern 11):
442
443
  *
443
444
  * - `idle` — never attempted, or fully settled and forgotten.
444
- * - `running` — the effect Cmd is out; awaiting `succeed` / `fail`.
445
+ * - `running` — the effect Cmd is out; awaiting `settle`.
445
446
  * Carries the deadline budget ({@link CallBudget}) and the
446
447
  * last `input` so a retry can re-issue it.
447
448
  * - `waiting_retry` — a transient failure backed off; the retry timer is armed
@@ -497,11 +498,28 @@ interface ResilientState<I, R> {
497
498
  readonly retry: Readonly<Record<string, RetryState>>;
498
499
  readonly cache: TtlCache<R>;
499
500
  readonly calls: Readonly<Record<string, CallPhase<I, R>>>;
501
+ /**
502
+ * The instant of the latest clocked transition this slice saw — the `at` of
503
+ * the last `attempt` / `resume` / `settleFailed`, settled Msg or timer fire.
504
+ * `timer` counts the soonest deadline down from it, so the built-in `timer`
505
+ * Sub gets a relative `ms` without anything reading a clock. `0` until the
506
+ * first clocked transition.
507
+ */
508
+ readonly clockMs: number;
500
509
  }
501
510
  /**
502
- * The one effect this knob emits: "run the port for `key` with `input`". The
503
- * consumer's `handlers(ports)` interprets it; it carries no closure — `input`
504
- * is plain data (invariant 3).
511
+ * The failures a run handler may return (ADR 0021). `port_rejected` is the
512
+ * work failing — carry the cause beside the tag (`err({ _tag: "port_rejected",
513
+ * cause })`); `deadline_exceeded` is a handler that timed the work out itself.
514
+ * Either one settles as `<name>_run_err` and feeds the retry / breaker. Any
515
+ * other failure is a contract breach and goes to the error sink.
516
+ */
517
+ type RunErr = TaggedError<"port_rejected" | "deadline_exceeded">;
518
+ /**
519
+ * The one effect this knob emits: "run the work for `key` with `input`". It is
520
+ * `Cmd.define`d, so the handler you write for it returns an outcome and the
521
+ * engine mints `<name>_run_ok` / `<name>_run_err` (ADR 0021). It carries no
522
+ * closure — `input` is plain data (invariant 3).
505
523
  */
506
524
  declare function runCmdDef<I, R, N extends string = DefaultResilientName>(name?: N): CmdDef<`${N}_run`, {
507
525
  readonly key: string;
@@ -512,37 +530,97 @@ declare function runCmdDef<I, R, N extends string = DefaultResilientName>(name?:
512
530
  } | {
513
531
  readonly [detail: string]: unknown;
514
532
  readonly _tag: "port_rejected";
515
- }, unknown>;
533
+ }>;
516
534
  type RunCmdDef<I, R, N extends string = DefaultResilientName> = ReturnType<typeof runCmdDef<I, R, N>>;
517
- type RunCmd<I, N extends string = DefaultResilientName> = CmdOf<RunCmdDef<I, unknown, N>>;
518
535
  /**
519
- * Settle Msgs the `handlers` port dispatches back. `at` is stamped at the
520
- * boundary. Both are generic in the knob's name family `N`, so two knobs named
521
- * apart land in two `update` cells whose payloads are already narrowed — the
522
- * `key` switch a single shared cell forces is gone.
536
+ * The run Cmd value. `R` is its settle value — `unknown` reads any knob's run
537
+ * Cmd; the knob's own verbs emit it at their `R`, which is what lets a machine
538
+ * list `cmds: [rc.run]` and take the verbs' Cmds as its own.
523
539
  */
524
- type SucceedMsg<R, N extends string = DefaultResilientName> = {
540
+ type RunCmd<I, N extends string = DefaultResilientName, R = unknown> = CmdOf<RunCmdDef<I, R, N>>;
541
+ /**
542
+ * The settle Msgs the engine mints from a run handler's outcome:
543
+ * `<name>_run_ok` carrying the handler's `value`, `<name>_run_err` carrying its
544
+ * declared `error`. Each carries the run Cmd it settles (`cmd.key` names the
545
+ * call) and the `at` the engine stamped. Both are generic in the knob's name
546
+ * family `N`, so two knobs named apart land in two `update` cells whose
547
+ * payloads are already narrowed.
548
+ *
549
+ * They are the `SettledOk` / `SettledErr` pair `Cmd.define` mints, spelled out
550
+ * so a helper that folds the error into a richer type of its own (llm-call's
551
+ * `LlmErr`, jev-ask's `JevAskErr`) can hand `settle` its Msg with `E` widened.
552
+ */
553
+ type SucceedMsg<R, N extends string = DefaultResilientName, I = unknown> = {
525
554
  readonly type: ResilientOkType<N>;
526
- readonly key: string;
527
- readonly result: R;
555
+ readonly cmd: RunCmd<I, N>;
556
+ readonly value: R;
528
557
  readonly at: number;
529
558
  };
530
- type FailMsg<N extends string = DefaultResilientName> = {
559
+ type FailMsg<N extends string = DefaultResilientName, I = unknown, E = RunErr | MalformedResult> = {
531
560
  readonly type: ResilientErrType<N>;
532
- readonly key: string;
561
+ readonly cmd: RunCmd<I, N>;
562
+ readonly error: E;
563
+ readonly at: number;
564
+ };
565
+ /**
566
+ * What `settle` reads off a settled Msg: the call's `key` (on `cmd`), the
567
+ * engine's `at`, and the handler's `value` or `error`. {@link SucceedMsg} and
568
+ * {@link FailMsg} are both one of these, so an engine-minted Msg passes
569
+ * straight in; a helper that settles from its own data (a fallback answer, a
570
+ * compaction summary) builds the record without inventing a whole run Cmd.
571
+ */
572
+ type SettleMsg<R, N extends string = DefaultResilientName> = {
573
+ readonly type?: ResilientOkType<N>;
574
+ readonly cmd: {
575
+ readonly key: string;
576
+ };
577
+ readonly value: R;
578
+ readonly at: number;
579
+ } | {
580
+ readonly type?: ResilientErrType<N>;
581
+ readonly cmd: {
582
+ readonly key: string;
583
+ };
533
584
  readonly error: unknown;
534
585
  readonly at: number;
535
586
  };
587
+ /**
588
+ * How a settled call ended — the third thing `settle` hands back, and the only
589
+ * place the port's value can be read from.
590
+ *
591
+ * - `done` — the port answered; `value` is its result.
592
+ * - `failed` — no retry is left (or no retry brick); `error` is the last
593
+ * failure.
594
+ * - `retrying` — backed off; the retry timer is armed and the call is still
595
+ * live.
596
+ */
597
+ type SettleOutcome<R> = {
598
+ readonly kind: "done";
599
+ readonly value: R;
600
+ } | {
601
+ readonly kind: "failed";
602
+ readonly error: unknown;
603
+ } | {
604
+ readonly kind: "retrying";
605
+ };
606
+ /**
607
+ * What `settle` returns: the settled slice, the Cmds it emitted, and the
608
+ * {@link SettleOutcome}. One record, so the slice update and the result read
609
+ * cannot be split apart in a hand-wired `update` cell.
610
+ */
611
+ interface SettleResult<I, R, N extends string = DefaultResilientName> {
612
+ readonly call: ResilientState<I, R>;
613
+ readonly cmds: readonly RunCmd<I, N, R>[];
614
+ readonly outcome: SettleOutcome<R>;
615
+ }
536
616
  /**
537
617
  * The deadline Msg tag this knob's timers dispatch, derived from its name the
538
- * same way `<name>_ok` / `<name>_err` are. The DEFAULT family keeps the bare
539
- * `"deadline_exceeded"` literal — that is the tag every machine wired before
540
- * the name existed already handles, and `mountResilientCall` still returns a
541
- * `deadline_exceeded` cell for an unnamed knob.
618
+ * same way the settle Msgs are. The DEFAULT family keeps the bare
619
+ * `"deadline_exceeded"` literal.
542
620
  */
543
621
  type ResilientDeadlineType<N extends string = DefaultResilientName> = N extends DefaultResilientName ? "deadline_exceeded" : `${N}_deadline`;
544
622
  /**
545
- * The name the deadline Sub carries for the `N` family — `undefined` for the
623
+ * The name a deadline carries for the `N` family — `undefined` for the
546
624
  * default family (no name at all, so the bare literal is dispatched), the name
547
625
  * itself otherwise. One conditional, so the value and {@link
548
626
  * ResilientDeadlineType} can never disagree about which family is unnamed.
@@ -567,20 +645,6 @@ type DeadlineExceededError = {
567
645
  readonly id: string;
568
646
  readonly atMs: number;
569
647
  };
570
- /**
571
- * What `handlers(ports)` returns: the interpret cell for this knob's run Cmd,
572
- * under that Cmd's own name. A named knob contributes `<name>_run`, so two
573
- * knobs' handler records merge into one `interpret` without either shadowing
574
- * the other.
575
- */
576
- type ResilientHandlers<I, R, N extends string = DefaultResilientName> = {
577
- readonly [K in ResilientRunType<N>]: (cmd: RunCmd<I, N>, ctx: NoCtx) => Promise<SucceedMsg<R, N> | FailMsg<N>>;
578
- };
579
- /** Ports the consumer supplies to `handlers`. */
580
- interface ResilientPorts<I, R> {
581
- /** The fallible work this knob wraps. Throws on failure → routed to `fail`. */
582
- readonly run: (input: I, key: string) => Promise<R>;
583
- }
584
648
  /**
585
649
  * Build a resilient-call knob from `config`. `rng` is injected for retry
586
650
  * jitter — pass a fixed `() => 0.5` in tests to pin backoff; defaults to
@@ -588,30 +652,39 @@ interface ResilientPorts<I, R> {
588
652
  * curried onto the factory rather than threaded through every verb so callers
589
653
  * spell the determinism choice once.
590
654
  *
591
- * Returns the uniform L2 knob contract. `I` is the port input type, `R` the
592
- * port result type. Consumers outside the package reach this through
593
- * `withResilience` (`../with-resilience`) — see the migration map at the top
594
- * of this module.
655
+ * Returns plain functions and the run Cmd def (ADR 0022) — see the module doc
656
+ * for the wiring. `I` is the work's input type, `R` its result type.
595
657
  */
596
658
  declare function createResilientCall<I, R, N extends string = DefaultResilientName>(config: ResilientConfig<N>, rng?: () => number): {
597
659
  name: N;
660
+ /** The `Cmd.define`d run Cmd; list it in the machine's `cmds`. */
661
+ run: CmdDef<`${N}_run`, {
662
+ readonly key: string;
663
+ readonly input: I;
664
+ }, R, {
665
+ readonly [detail: string]: unknown;
666
+ readonly _tag: "deadline_exceeded";
667
+ } | {
668
+ readonly [detail: string]: unknown;
669
+ readonly _tag: "port_rejected";
670
+ }>;
598
671
  init: () => ResilientState<I, R>;
599
- attempt: (s: ResilientState<I, R>, key: string, input: I, at: number) => readonly [ResilientState<I, R>, readonly RunCmd<I, N>[]];
672
+ attempt: (s: ResilientState<I, R>, key: string, input: I, at: number) => readonly [ResilientState<I, R>, readonly RunCmd<I, N, R>[]];
600
673
  resume: (s: ResilientState<I, R>, at: number) => ResilientState<I, R>;
601
- succeed: (s: ResilientState<I, R>, key: string, msg: SucceedMsg<R, N>) => readonly [ResilientState<I, R>, readonly RunCmd<I, N>[]];
602
- fail: (s: ResilientState<I, R>, key: string, msg: FailMsg<N>) => readonly [ResilientState<I, R>, readonly RunCmd<I, N>[]];
603
- settleFailed: (s: ResilientState<I, R>, key: string, error: unknown) => readonly [ResilientState<I, R>, readonly RunCmd<I, N>[]];
604
- onTimer: (s: ResilientState<I, R>, msg: ResilientTimerMsg) => readonly [ResilientState<I, R>, readonly RunCmd<I, N>[]];
605
- subs: (s: ResilientState<I, R>) => readonly DeadlineSub<DeadlineNameOf<N>>[];
606
- handlers: (ports: ResilientPorts<I, R>) => ResilientHandlers<I, R, N>;
674
+ settle: (s: ResilientState<I, R>, msg: SettleMsg<R, N>) => SettleResult<I, R, N>;
675
+ settleFailed: (s: ResilientState<I, R>, key: string, error: unknown, at: number) => readonly [ResilientState<I, R>, readonly RunCmd<I, N, R>[]];
676
+ onTimer: (slice: ResilientState<I, R>, msg: {
677
+ readonly id: string;
678
+ readonly atMs: number;
679
+ }) => readonly [ResilientState<I, R>, readonly RunCmd<I, N, R>[]];
680
+ deadlines: (s: ResilientState<I, R>) => readonly DeadlineSub<DeadlineNameOf<N>>[];
681
+ timer: (s: ResilientState<I, R>) => TimerDeps<ResilientTimerMsg<N>> | null;
607
682
  };
608
683
  /**
609
684
  * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the
610
685
  * slice lives at `state.resilience`. A convenience for the common single-slice
611
686
  * host; consumers with a differently-named field spread by hand. Pure — a thin
612
- * record rebuild, no clock / RNG. Under `withResilience` the wrapper owns
613
- * `model.$resilience`, so there is nothing to lift; this is for the embedded
614
- * slice consumers only.
687
+ * record rebuild, no clock / RNG.
615
688
  *
616
689
  * The record rebuild itself is `liftSlice` from the root door (#231) — this
617
690
  * stays as the named, pre-keyed convenience for the `state.resilience` field,
@@ -620,187 +693,5 @@ declare function createResilientCall<I, R, N extends string = DefaultResilientNa
620
693
  declare function liftResilience<S extends {
621
694
  resilience: ResilientState<I, R>;
622
695
  }, I, R, C extends Cmd>(state: S, result: readonly [ResilientState<I, R>, readonly C[]]): readonly [S, readonly C[]];
623
- /** What every verb of a knob in this family hands back. */
624
- type Settle<I, R> = readonly [
625
- ResilientState<I, R>,
626
- readonly RunCmd<I>[]
627
- ];
628
- /**
629
- * The part of a resilient-call knob {@link mountResilientCall} needs. This knob
630
- * satisfies it, and so does every knob that delegates these verbs to it —
631
- * `internal/jev/ask` and `internal/llm-call` both do, which is why the mount is
632
- * written against the shape rather than against either door.
633
- *
634
- * `OkMsg` / `ErrMsg` are parameters rather than {@link SucceedMsg} /
635
- * {@link FailMsg} because an inheriting knob narrows them: jev-ask's `fail`
636
- * takes a `JevFailMsg` whose `error` is a typed `JevAskErr`, and a mount that
637
- * fixed the supertype would hand that verb a widened Msg.
638
- */
639
- interface MountableKnob<I, R, OkMsg, ErrMsg, Handlers, N extends string = DefaultResilientName> {
640
- /**
641
- * The Msg-name family this knob settles into — `<name>_ok` / `<name>_err`
642
- * (#229). The mount reads it rather than assuming `resilient_*`, so a named
643
- * knob mounts into the cells it actually emits; an unnamed one is
644
- * `resilient`, so nothing a machine already spread changes.
645
- */
646
- readonly name: N;
647
- init(): ResilientState<I, R>;
648
- succeed(s: ResilientState<I, R>, key: string, msg: OkMsg): Settle<I, R>;
649
- fail(s: ResilientState<I, R>, key: string, msg: ErrMsg): Settle<I, R>;
650
- onTimer(s: ResilientState<I, R>, msg: ResilientTimerMsg<N>): Settle<I, R>;
651
- subs(s: ResilientState<I, R>): readonly DeadlineSub<DeadlineNameOf<N>>[];
652
- handlers(): Handlers;
653
- }
654
- /**
655
- * The consumer's half of a settle cell: fold the settled answer into the
656
- * machine's own Model.
657
- *
658
- * It is handed the Model the inherited verb ALREADY settled — the slice at
659
- * `slice` is the post-`succeed` / post-`fail` one — so the ordering that wedges
660
- * a call at `running` is not something this callback can express. It returns
661
- * the repo's universal cell shape so a fold that needs to chain an effect
662
- * (book the answer, then write it somewhere) returns that Cmd like any other
663
- * reducer cell would.
664
- */
665
- type SettleFold<Model, M, C extends Cmd> = (model: Model, msg: M) => readonly [Model, readonly C[]];
666
- /** One cell of the update fragment {@link mountResilientCall} returns. */
667
- type MountedCell<Model, M, I, C extends Cmd> = (model: Model, msg: M) => readonly [Model, readonly (RunCmd<I> | C)[]];
668
- /**
669
- * What to mount, and where. `slice` names the Model field the knob's state
670
- * lives on — a plain, readable field, per
671
- * [ADR 0015](../../../../.decisions/0015-hide-the-wiring-never-the-state.md):
672
- * the mount absorbs the assembly and hides none of the durable state.
673
- */
674
- interface MountConfig<Model, Slice extends string, I, R, AttemptType extends string, AttemptMsg, OkMsg, ErrMsg, C extends Cmd, N extends string = DefaultResilientName> {
675
- /** The Model field carrying the knob's slice. */
676
- readonly slice: Slice;
677
- /**
678
- * The cell that starts a call. Its shape is the one wiring point the mount
679
- * cannot supply: each door's `attempt` takes its own arguments (jev-ask reads
680
- * a key, a state and an instant; llm-call reads a request), and only the
681
- * consumer knows which Msg field carries each. `run` is that one line.
682
- */
683
- readonly attempt: {
684
- /** The Msg type that starts a call — the key the cell lands on. */
685
- readonly on: AttemptType;
686
- readonly run: (slice: ResilientState<I, R>, msg: AttemptMsg) => Settle<I, R>;
687
- };
688
- /** Fold a settled success into the Model. Omit and only the slice advances. */
689
- readonly onOk?: SettleFold<Model, OkMsg, C>;
690
- /** Fold a settled failure into the Model. Omit and only the slice advances. */
691
- readonly onErr?: SettleFold<Model, ErrMsg, C>;
692
- /**
693
- * Fold a call the TIMER settled into the Model. This is the third failure
694
- * class, and it never reaches {@link MountConfig.onErr}: a deadline fire
695
- * settles `failed` inside the slice and emits no settle Msg, so without this
696
- * callback a call that dies on its budget advances the slice and folds
697
- * nothing — the shape that used to be a documented caveat.
698
- *
699
- * It runs once per call the knob's deadline cell moved INTO `failed`:
700
- * the deadline fire itself, and the resumed retry whose gate found the
701
- * budget spent. A plain backoff tick, a stale fire and an already-`failed`
702
- * call fold nothing. `error` is the slice's own settled error — a
703
- * {@link DeadlineExceededError} on the deadline path.
704
- *
705
- * Omit and only the slice advances, exactly as the other two do.
706
- */
707
- readonly onDeadline?: SettleFold<Model, DeadlineSettled<N>, C>;
708
- }
709
- /**
710
- * What {@link MountConfig.onDeadline} is handed: the one call the timer cell
711
- * just settled `failed`, named by its `key`, carrying the error the slice
712
- * settled with and the timer Msg that produced it. It is not a Msg the reducer
713
- * ever sees — no settle Msg exists for this failure class, which is the whole
714
- * reason the callback is here.
715
- */
716
- interface DeadlineSettled<N extends string = DefaultResilientName> {
717
- /** The call key that settled. */
718
- readonly key: string;
719
- /** The error now on the slice — a {@link DeadlineExceededError} on the deadline path. */
720
- readonly error: unknown;
721
- /**
722
- * The timer Msg whose fire settled it — this knob's own tag, so a fold on a
723
- * knob named `jev` is handed a `jev_deadline` and one on an unnamed knob a
724
- * `deadline_exceeded`.
725
- */
726
- readonly msg: ResilientTimerMsg<N>;
727
- }
728
- /**
729
- * The four fragments a consumer spreads into `defineMachine`. Together with
730
- * `init` they are the eight wiring points; none of them is optional at the type
731
- * level, so a consumer that mounts cannot omit `subscribe` (a backed-off retry
732
- * that never fires) or re-implement `interpret` as a dispatching handler.
733
- */
734
- interface MountedResilientCall<Model, Slice extends string, I, R, AttemptType extends string, AttemptMsg, OkMsg, ErrMsg, C extends Cmd, Handlers, N extends string = DefaultResilientName> {
735
- /** The starting slice under its field name — spread into the machine's `init`. */
736
- init(): {
737
- readonly [K in Slice]: ResilientState<I, R>;
738
- };
739
- /**
740
- * The three settle cells plus the attempt cell, to spread into `update`.
741
- *
742
- * The two settle keys are the knob's OWN Msg names (#229), so a knob built as
743
- * `name: "jev"` mounts into `jev_ok` / `jev_err` and two named knobs in one
744
- * machine spread into four distinct cells instead of colliding on one. An
745
- * unnamed knob is `resilient`, so the keys read `resilient_ok` /
746
- * `resilient_err` exactly as they always have.
747
- *
748
- * The deadline cell is keyed the same way (#238). A knob's deadline Sub
749
- * carries its name, so a knob built as `name: "jev"` dispatches
750
- * `jev_deadline` and mounts into a `jev_deadline` cell; an unnamed knob still
751
- * dispatches and mounts `deadline_exceeded`. Before that, both mounts wrote
752
- * the one unqualified `deadline_exceeded` key and the last spread silently
753
- * dropped the other knob's deadline fold. The cell folds through
754
- * {@link MountConfig.onDeadline}, since a call the timer settles emits no
755
- * settle Msg and so reaches no `onErr`.
756
- */
757
- readonly update: Readonly<Record<AttemptType, MountedCell<Model, AttemptMsg, I, C>>> & {
758
- readonly [K in ResilientOkType<N>]: MountedCell<Model, OkMsg, I, C>;
759
- } & {
760
- readonly [K in ResilientErrType<N>]: MountedCell<Model, ErrMsg, I, C>;
761
- } & {
762
- readonly [K in ResilientDeadlineType<N>]: MountedCell<Model, ResilientTimerMsg<N>, I, C>;
763
- };
764
- subscriptions(model: Model): readonly DeadlineSub<DeadlineNameOf<N>>[];
765
- readonly subscribe: {
766
- readonly deadline: typeof subscribeDeadline;
767
- };
768
- readonly interpret: Handlers;
769
- }
770
- /**
771
- * Pre-assemble a resilient-call knob into the fragments a machine definition
772
- * spreads, so mounting one is a spread instead of eight hand-spliced points.
773
- *
774
- * The three points that used to fail only at runtime are gone at the type
775
- * level rather than documented:
776
- *
777
- * - The settle cells run the inherited `succeed` / `fail` verb and hand the
778
- * already-settled Model to {@link SettleFold}. There is no cell for a
779
- * consumer to write in the wrong order.
780
- * - `interpret` is `knob.handlers()` — the form that RETURNS the settle Msg
781
- * so it re-enters the reducer. A consumer that spreads the fragment cannot
782
- * substitute a dispatching handler for it.
783
- * - `subscribe` carries `subscribeDeadline`, so the retry timer is armed by
784
- * construction rather than by remembering.
785
- *
786
- * A deadline-exceeded call settles inside the slice and emits no settle Msg, so
787
- * it reaches no `onErr`. {@link MountConfig.onDeadline} is that failure class's
788
- * fold — omit it and the slice still advances, exactly as omitting `onErr`
789
- * does.
790
- *
791
- * Nothing is taken away. The slice stays a plain field at `slice` that the
792
- * consumer reads, `replay` sees and the journal prints, and every verb the
793
- * fragments call is still exported and callable by hand — a consumer that
794
- * wants a settle cell this shape cannot express writes that one cell itself and
795
- * spreads the rest. PURE: a record of closures over `knob` and `config`, no
796
- * clock and no RNG.
797
- */
798
- declare function mountResilientCall<Slice extends string, I, R, Model extends {
799
- readonly [K in Slice]: ResilientState<I, R>;
800
- }, AttemptType extends string, AttemptMsg, OkMsg extends {
801
- readonly key: string;
802
- }, ErrMsg extends {
803
- readonly key: string;
804
- }, Handlers, C extends Cmd = never, N extends string = DefaultResilientName>(knob: MountableKnob<I, R, OkMsg, ErrMsg, Handlers, N>, config: MountConfig<Model, Slice, I, R, AttemptType, AttemptMsg, OkMsg, ErrMsg, C, N>): MountedResilientCall<Model, Slice, I, R, AttemptType, AttemptMsg, OkMsg, ErrMsg, C, Handlers, N>;
805
696
 
806
- export { type SettleFold as A, type SlidingWindow as B, type CircuitConfig as C, type DeadlineConfig as D, canPass as E, type FailMsg as F, createResilientCall as G, defaultCircuitPolicy as H, initBucket as I, initCircuit as J, initWindow as K, liftResilience as L, type MountConfig as M, onFailure as N, onSuccess as O, record as P, refill as Q, type RunCmd as R, type SucceedMsg as S, type TokenBucket as T, remaining as U, runCmdDef as V, tryConsume as W, type ResilientState as a, type RateLimitConfig as b, type ResilientPorts as c, type ResilientHandlers as d, type ResilientConfig as e, type ResilientTimerMsg as f, type CacheConfig as g, type CallBudget as h, type CallPhase as i, type CircuitPolicy as j, type CircuitState as k, DEFAULT_RESILIENT_NAME as l, mountResilientCall as m, type DeadlineExceededError as n, type DeadlineNameOf as o, type DeadlineSettled as p, type DefaultResilientName as q, type MountableKnob as r, type MountedCell as s, type MountedResilientCall as t, type ResilientDeadlineType as u, type ResilientErrType as v, type ResilientOkType as w, type ResilientRunType as x, type RunCmdDef as y, type Settle as z };
697
+ export { initBucket as A, initCircuit as B, type CacheConfig as C, DEFAULT_RESILIENT_NAME as D, initWindow as E, type FailMsg as F, liftResilience as G, onFailure as H, onSuccess as I, record as J, refill as K, remaining as L, runCmdDef as M, tryConsume as N, type RunCmd as R, type SucceedMsg as S, type TokenBucket as T, type ResilientState as a, type ResilientTimerMsg as b, type ResilientConfig as c, type CallBudget as d, type CallPhase as e, type CircuitConfig as f, type CircuitPolicy as g, type CircuitState as h, type DeadlineExceededError as i, type DeadlineNameOf as j, type DefaultResilientName as k, type RateLimitConfig as l, type DeadlineConfig as m, type ResilientDeadlineType as n, type ResilientErrType as o, type ResilientOkType as p, type ResilientRunType as q, type RunCmdDef as r, type RunErr as s, type SettleMsg as t, type SettleOutcome as u, type SettleResult as v, type SlidingWindow as w, canPass as x, createResilientCall as y, defaultCircuitPolicy as z };
@@ -1,4 +1,4 @@
1
- import { B as BootingRuntime } from './runtime-types-CMF13BBh.js';
1
+ import { B as BootingRuntime } from './runtime-types-CiVpC0HN.js';
2
2
 
3
3
  /**
4
4
  * A recorded run, sufficient to reproduce it via `../trace-replay`.