@demlik/tea 0.19.0 → 0.20.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 (116) hide show
  1. package/README.md +25 -18
  2. package/dist/agent/index.d.ts +44 -13
  3. package/dist/agent/index.js +10 -10
  4. package/dist/{chunk-PCJA2HTZ.js → chunk-2774I242.js} +7 -7
  5. package/dist/chunk-2774I242.js.map +1 -0
  6. package/dist/{chunk-YIMOFXST.js → chunk-2R62Q5UK.js} +3 -3
  7. package/dist/chunk-2R62Q5UK.js.map +1 -0
  8. package/dist/{chunk-PQSDUX6B.js → chunk-5HVKDHY6.js} +3 -3
  9. package/dist/{chunk-PQSDUX6B.js.map → chunk-5HVKDHY6.js.map} +1 -1
  10. package/dist/{chunk-WTSOW2MD.js → chunk-72CN3VPY.js} +5 -5
  11. package/dist/{chunk-WTSOW2MD.js.map → chunk-72CN3VPY.js.map} +1 -1
  12. package/dist/{chunk-JVE2LBFJ.js → chunk-A73IJ27X.js} +3 -3
  13. package/dist/{chunk-JVE2LBFJ.js.map → chunk-A73IJ27X.js.map} +1 -1
  14. package/dist/{chunk-I7E7AD2S.js → chunk-AIXC33SE.js} +4 -4
  15. package/dist/chunk-AIXC33SE.js.map +1 -0
  16. package/dist/{chunk-FNGZMVIT.js → chunk-DVNXEB7V.js} +3 -3
  17. package/dist/chunk-DVNXEB7V.js.map +1 -0
  18. package/dist/{chunk-XVIKSRCK.js → chunk-EA47MI5Q.js} +4 -4
  19. package/dist/{chunk-XVIKSRCK.js.map → chunk-EA47MI5Q.js.map} +1 -1
  20. package/dist/{chunk-IHUNKHDX.js → chunk-FTCYY2DO.js} +3 -3
  21. package/dist/{chunk-IHUNKHDX.js.map → chunk-FTCYY2DO.js.map} +1 -1
  22. package/dist/{chunk-JVKU2UQC.js → chunk-HX3C6LDK.js} +3 -3
  23. package/dist/{chunk-JVKU2UQC.js.map → chunk-HX3C6LDK.js.map} +1 -1
  24. package/dist/{chunk-H2ELKHI6.js → chunk-JAKM53JF.js} +4 -4
  25. package/dist/chunk-JAKM53JF.js.map +1 -0
  26. package/dist/{chunk-JYNYG5SF.js → chunk-NGYFBD5G.js} +3 -3
  27. package/dist/chunk-NGYFBD5G.js.map +1 -0
  28. package/dist/{chunk-AIIXV4XB.js → chunk-RKVUVALV.js} +2 -2
  29. package/dist/chunk-RKVUVALV.js.map +1 -0
  30. package/dist/{chunk-C3G2QFEZ.js → chunk-TAKPC6SD.js} +4 -4
  31. package/dist/{chunk-C3G2QFEZ.js.map → chunk-TAKPC6SD.js.map} +1 -1
  32. package/dist/{chunk-BRX3243I.js → chunk-TGJLXZAU.js} +3 -3
  33. package/dist/{chunk-BRX3243I.js.map → chunk-TGJLXZAU.js.map} +1 -1
  34. package/dist/{chunk-AHW2CLPT.js → chunk-UHAQ4PI6.js} +4 -4
  35. package/dist/{chunk-AHW2CLPT.js.map → chunk-UHAQ4PI6.js.map} +1 -1
  36. package/dist/{chunk-H3MWNH7A.js → chunk-XWIE5V7R.js} +4 -4
  37. package/dist/{chunk-H3MWNH7A.js.map → chunk-XWIE5V7R.js.map} +1 -1
  38. package/dist/{core-Ce9ncpuv.d.ts → core-CtvAyPpH.d.ts} +153 -1
  39. package/dist/devtools/index.d.ts +17 -0
  40. package/dist/devtools/index.js.map +1 -1
  41. package/dist/do/index.d.ts +12 -12
  42. package/dist/do/index.js +11 -11
  43. package/dist/{drive-loop-CsUsW3Wo.d.ts → drive-loop-Dw1sGSsW.d.ts} +1 -1
  44. package/dist/{durable-effects-BmUrRA-h.d.ts → durable-effects-Ump5lSdO.d.ts} +1 -1
  45. package/dist/effect/index.d.ts +124 -5
  46. package/dist/effect/index.js +33 -4
  47. package/dist/effect/index.js.map +1 -1
  48. package/dist/extension/index.d.ts +84 -3
  49. package/dist/extension/index.js +2 -2
  50. package/dist/extension/index.js.map +1 -1
  51. package/dist/flow/index.d.ts +29 -13
  52. package/dist/flow/index.js +11 -11
  53. package/dist/flow/index.js.map +1 -1
  54. package/dist/idempotency/index.d.ts +11 -3
  55. package/dist/idempotency/index.js +3 -3
  56. package/dist/{index-D8sYVzCI.d.ts → index-Bk2hBUdK.d.ts} +6 -1
  57. package/dist/{index-2kNxy6az.d.ts → index-CKtEKGyp.d.ts} +15 -3
  58. package/dist/{index-e36uEyl4.d.ts → index-CVU7SK3a.d.ts} +2 -2
  59. package/dist/{index-Dy3379ve.d.ts → index-CZZ3HI-Z.d.ts} +4 -4
  60. package/dist/{index-Ce5GYAuI.d.ts → index-CrcoVfd_.d.ts} +2 -2
  61. package/dist/{index-DWdg7R1l.d.ts → index-D3NY3VCN.d.ts} +5 -1
  62. package/dist/{index-B1Wzarkl.d.ts → index-Dl71V7kt.d.ts} +1 -1
  63. package/dist/{index-Bf9_bNql.d.ts → index-EIgfl83J.d.ts} +2 -2
  64. package/dist/index.d.ts +66 -5
  65. package/dist/index.js +2 -2
  66. package/dist/jev/index.d.ts +39 -27
  67. package/dist/jev/index.js +12 -8
  68. package/dist/jev/index.js.map +1 -1
  69. package/dist/{machine-CuojfZup.d.ts → machine-Dtre2TmN.d.ts} +9 -7
  70. package/dist/machine-viz/index.d.ts +2 -1
  71. package/dist/machine-viz/index.js +2 -2
  72. package/dist/machine-viz/index.js.map +1 -1
  73. package/dist/mem/index.d.ts +2 -2
  74. package/dist/mem/index.js +2 -2
  75. package/dist/node/index.d.ts +11 -2
  76. package/dist/node/index.js +2 -2
  77. package/dist/node/index.js.map +1 -1
  78. package/dist/otel/index.d.ts +10 -10
  79. package/dist/otel/index.js +10 -10
  80. package/dist/paginate/index.d.ts +5 -4
  81. package/dist/paginate/index.js +5 -5
  82. package/dist/parity/index.d.ts +3 -3
  83. package/dist/parity/index.js +3 -3
  84. package/dist/pbt/index.d.ts +1 -1
  85. package/dist/pbt/index.js +2 -2
  86. package/dist/persistence/index.d.ts +5 -5
  87. package/dist/persistence/index.js +4 -4
  88. package/dist/promise/index.d.ts +7 -2
  89. package/dist/promise/index.js +4 -4
  90. package/dist/react/index.d.ts +2 -2
  91. package/dist/resilience/index.d.ts +7 -6
  92. package/dist/resilience/index.js +5 -5
  93. package/dist/resilience/index.js.map +1 -1
  94. package/dist/{index-BnsAqn0-.d.ts → run-fiBe7pOG.d.ts} +8 -5
  95. package/dist/{runtime-types-BKg2CGMx.d.ts → runtime-types-DEluQgGO.d.ts} +74 -2
  96. package/dist/testing/effect/index.d.ts +5 -5
  97. package/dist/testing/effect/index.js +8 -8
  98. package/dist/testing/index.d.ts +2 -2
  99. package/dist/testing/index.js +3 -3
  100. package/dist/testing/promise/index.d.ts +4 -4
  101. package/dist/testing/promise/index.js +5 -5
  102. package/dist/timing/index.d.ts +4 -4
  103. package/dist/timing/index.js +4 -4
  104. package/dist/types-CXNzlbAg.d.ts +9 -0
  105. package/dist/work-queue/index.d.ts +4 -4
  106. package/dist/work-queue/index.js +2 -2
  107. package/dist/work-queue/index.js.map +1 -1
  108. package/package.json +3 -2
  109. package/dist/chunk-AIIXV4XB.js.map +0 -1
  110. package/dist/chunk-FNGZMVIT.js.map +0 -1
  111. package/dist/chunk-H2ELKHI6.js.map +0 -1
  112. package/dist/chunk-I7E7AD2S.js.map +0 -1
  113. package/dist/chunk-JYNYG5SF.js.map +0 -1
  114. package/dist/chunk-PCJA2HTZ.js.map +0 -1
  115. package/dist/chunk-YIMOFXST.js.map +0 -1
  116. package/dist/types-SzNSHKlV.d.ts +0 -5
@@ -130,6 +130,11 @@ type CmdInput = {
130
130
  } & Record<string, unknown>;
131
131
  /** The value `Cmd.define("fetch", …)` builds: `{ type: "fetch", ...input }`. */
132
132
  type CmdValue<Name extends string, Input extends CmdInput, Ok, E extends Tagged> = Cmd<Name, Ok, E | MalformedResult> & Readonly<Input>;
133
+ /**
134
+ * The Msg the engine mints when a `Cmd.define`d Cmd's handler succeeds:
135
+ * `<name>_ok`, carrying the Cmd and its value. Handle it in `update` to fold
136
+ * the result into state.
137
+ */
133
138
  type SettledOk<Name extends string, C, Ok> = {
134
139
  readonly type: `${Name}_ok`;
135
140
  readonly cmd: C;
@@ -137,6 +142,11 @@ type SettledOk<Name extends string, C, Ok> = {
137
142
  /** Stamped by the runtime at the interpret edge (`run`'s `clock`). */
138
143
  readonly at: number;
139
144
  };
145
+ /**
146
+ * The Msg the engine mints when a `Cmd.define`d Cmd's handler fails:
147
+ * `<name>_err`, carrying the Cmd and the tagged error. Handle it in `update` to
148
+ * decide what a failure means.
149
+ */
140
150
  type SettledErr<Name extends string, C, E extends Tagged> = {
141
151
  readonly type: `${Name}_err`;
142
152
  readonly cmd: C;
@@ -200,15 +210,41 @@ declare function defineCmd<const Name extends string, Input extends CmdInput, Ok
200
210
  readonly ok: StandardSchemaV1<unknown, Ok>;
201
211
  readonly err: Tags;
202
212
  }): CmdDef<Name, Input, Ok, TaggedError<Tags[number]>>;
213
+ /**
214
+ * What an update cell returns: the `[nextState, cmds]` tuple, typed so that a
215
+ * Promise cannot stand in for it. An `async` cell fails to compile against it.
216
+ */
203
217
  type SyncReturn<S, C extends Cmd> = readonly [S, readonly C[]] & {
204
218
  readonly then?: never;
205
219
  };
220
+ /**
221
+ * Which of the two shapes a machine's `update` takes: a flat `reducer` keyed by
222
+ * Msg type, or a `transitions` table keyed by state type and then Msg type.
223
+ */
206
224
  type UpdateForm = "reducer" | "transitions";
225
+ /**
226
+ * Work out an `update` record's `UpdateForm` from its shape. For a machine, use
227
+ * `formOf`, which prefers the form `defineMachine` already recorded.
228
+ *
229
+ * A reducer's first own value is a function; a transitions table's is a record
230
+ * of functions. An empty record can never dispatch a Msg, so it reads as
231
+ * `reducer`.
232
+ */
207
233
  declare function detectUpdateForm(update: object): UpdateForm;
234
+ /**
235
+ * Read a machine's `UpdateForm`. Reach for it when code has to treat reducer
236
+ * and transitions machines differently. It prefers the form `defineMachine`
237
+ * recorded, and works the form out from the shape only for a machine that
238
+ * never went through `defineMachine`.
239
+ */
208
240
  declare function formOf(machine: {
209
241
  update: object;
210
242
  __form?: UpdateForm;
211
243
  }): UpdateForm;
244
+ /**
245
+ * Thrown when a Msg is dispatched to a state that has no update cell for it. It
246
+ * names the Msg type, the state, and the Msg types that state does accept.
247
+ */
212
248
  declare class NoCellError extends Error {
213
249
  readonly msgType: string;
214
250
  readonly stateName: string;
@@ -232,22 +268,39 @@ declare function acceptedTypes<S>(machine: {
232
268
  update: object;
233
269
  __form?: UpdateForm;
234
270
  }, state: S): readonly string[];
271
+ /**
272
+ * Run the one update cell that matches `state` and `msg` and return its
273
+ * `[nextState, cmds]`. Use it to step a machine by hand; it throws
274
+ * `NoCellError` when no cell matches.
275
+ */
235
276
  declare function applyCell<S, M extends {
236
277
  type: string;
237
278
  }, C extends Cmd>(machine: {
238
279
  update: object;
239
280
  __form?: UpdateForm;
240
281
  }, state: S, msg: M): readonly [S, readonly C[]];
282
+ /**
283
+ * `applyCell` with the development-mode checks that catch an impure cell: the
284
+ * input state is frozen and the result is asserted to be plain data.
285
+ */
241
286
  declare function applyCellChecked<S, M extends {
242
287
  type: string;
243
288
  }, C extends Cmd>(machine: {
244
289
  update: object;
245
290
  __form?: UpdateForm;
246
291
  }, state: S, msg: M): readonly [S, readonly C[]];
292
+ /**
293
+ * List every Msg type a machine has an update cell for, across all of its
294
+ * states.
295
+ */
247
296
  declare function msgKeysOf(machine: {
248
297
  update: object;
249
298
  __form?: UpdateForm;
250
299
  }): readonly string[];
300
+ /**
301
+ * What `describeMachine` returns: the Msg types a machine handles and, for a
302
+ * transitions machine, its states and the Msg types each one accepts.
303
+ */
251
304
  type MachineShape = {
252
305
  readonly form: "reducer";
253
306
  /** Every `Msg.type` the flat reducer has a cell for. */
@@ -261,14 +314,28 @@ type MachineShape = {
261
314
  /** `state.type` → the `Msg.type`s that state has a cell for. */
262
315
  readonly accepts: Readonly<Record<string, readonly string[]>>;
263
316
  };
317
+ /**
318
+ * Describe a machine's update table as data: its form, its Msg types, and the
319
+ * per-state accept sets of a transitions machine. Use it to build tooling, or
320
+ * to ask what a machine handles without dispatching to it.
321
+ */
264
322
  declare function describeMachine(machine: {
265
323
  update: object;
266
324
  __form?: UpdateForm;
267
325
  }): MachineShape;
326
+ /**
327
+ * List the Msg types a machine accepts in the state named `stateType`. A
328
+ * reducer machine accepts every one of its Msg types in every state, and a
329
+ * `stateType` with no row in a transitions table accepts none.
330
+ */
268
331
  declare function acceptsOf(machine: {
269
332
  update: object;
270
333
  __form?: UpdateForm;
271
334
  }, stateType: string): readonly string[];
335
+ /**
336
+ * The flat form of `update`: a record with one handler per Msg type, each
337
+ * returning `[nextState, cmds]`. Leaving a Msg type out is a compile error.
338
+ */
272
339
  type Reducer<S, M extends {
273
340
  type: string;
274
341
  }, C extends Cmd> = {
@@ -323,6 +390,11 @@ type Cmd<T extends string = string, Ok = unknown, E = unknown> = {
323
390
  /** Phantom — the `_tag` union this Cmd can settle with. Never assigned. */
324
391
  readonly __e?: E;
325
392
  };
393
+ /**
394
+ * The helpers for building Cmds: `Cmd.define` declares a typed Cmd constructor,
395
+ * and `Cmd.none`, `Cmd.batch`, `Cmd.when` and `Cmd.whenDefined` build the Cmd
396
+ * list an update cell returns.
397
+ */
326
398
  declare const Cmd: {
327
399
  /**
328
400
  * Declare a typed Cmd constructor (ADR 0014, 0021). Returns the builder —
@@ -407,6 +479,7 @@ declare const Cmd: {
407
479
  */
408
480
  readonly whenDefined: <T, const C extends Cmd>(value: T | undefined, build: (value: T) => C) => readonly C[];
409
481
  };
482
+ /** The branded string that identifies a running Sub. Build one with `subId`. */
410
483
  type SubId = string & {
411
484
  readonly __brand: "SubId";
412
485
  };
@@ -420,11 +493,29 @@ type SubId = string & {
420
493
  * Strengthens invariant 7 (identity is explicit).
421
494
  */
422
495
  declare function subId(s: string): SubId;
496
+ /**
497
+ * A running subscription as its runner sees it: its `type`, the `deps` value
498
+ * the machine's `subs` entry returned, and an `id` derived from both. Use it to
499
+ * declare a machine's Sub union and to type the `sub` argument of a runner.
500
+ *
501
+ * A machine never builds one. It declares `{ type, deps(state) }` in `subs`
502
+ * (see `DepKeyedSub`) and the engine derives the rest. A runner reads its data
503
+ * off `sub.deps`. `id` is `structuralHash({ type, deps })`, so it changes
504
+ * exactly when the type or the deps value does, which is when the engine
505
+ * restarts the runner.
506
+ */
423
507
  type Sub<T extends string = string, D = unknown> = {
424
508
  readonly id: SubId;
425
509
  readonly type: T;
426
510
  readonly deps: D;
427
511
  };
512
+ /**
513
+ * The cleanup function a Sub runner returns. The runner opens a resource and
514
+ * returns the function that closes it. The engine calls it when the Sub's
515
+ * `deps` go null (turned off), when they change (restarted: the old `Dispose`,
516
+ * then a fresh runner), and when the runtime stops. A returned Promise is
517
+ * awaited by `stop()`, with a bound.
518
+ */
428
519
  type Dispose = () => void | Promise<void>;
429
520
  /** The `deps` a `timer` Sub declares: fire `msg` once, `ms` after it starts. */
430
521
  type TimerDeps<M> = {
@@ -442,7 +533,16 @@ type BuiltinSub<M> = TimerSub<M>;
442
533
  * value. Same type and same deps → same id → the running Sub is left alone.
443
534
  */
444
535
  declare function subIdOf(type: string, deps: unknown): SubId;
536
+ /**
537
+ * Turn a plain-data value into a stable string that does not depend on object
538
+ * key order. Use it wherever two values must compare equal by content, as the
539
+ * engine does for Sub ids.
540
+ */
445
541
  declare function structuralHash(deps: unknown): string;
542
+ /**
543
+ * One entry of a machine's `subs`: a Sub `type` plus `deps(state)`, which
544
+ * returns the data the runner needs, or `null` to keep the Sub off.
545
+ */
446
546
  type DepKeyedSub<S, U extends Sub = Sub> = U extends Sub<infer T, infer D> ? {
447
547
  readonly type: T;
448
548
  /**
@@ -454,6 +554,11 @@ type DepKeyedSub<S, U extends Sub = Sub> = U extends Sub<infer T, infer D> ? {
454
554
  */
455
555
  readonly deps: (state: S) => D | null | undefined;
456
556
  } : never;
557
+ /**
558
+ * A machine's optional message filter: `ofState` names the identity this
559
+ * instance owns, and `ofMsg` the identity a Msg is addressed to. The engine
560
+ * drops a Msg addressed to a different identity before `update` runs.
561
+ */
457
562
  interface Identity<S, M> {
458
563
  /** The identity THIS instance owns. Pure (invariant 2); plain value. */
459
564
  readonly ofState: (state: S) => unknown;
@@ -464,6 +569,11 @@ interface Identity<S, M> {
464
569
  */
465
570
  readonly ofMsg: (msg: M) => unknown;
466
571
  }
572
+ /**
573
+ * A named, typed channel for values leaving the runtime. A Cmd handler sends on
574
+ * it with `ctx.emit(port, value)` and a host listens with
575
+ * `runtime.subscribePort`; create one with `definePort`.
576
+ */
467
577
  interface Port<T> {
468
578
  readonly __brand: "port";
469
579
  readonly name: string;
@@ -480,10 +590,18 @@ interface Port<T> {
480
590
  interface PortEmitter {
481
591
  emit<T>(port: Port<T>, value: T): void;
482
592
  }
593
+ /**
594
+ * The `Ctx` of a machine whose handlers read nothing from context. Use it in
595
+ * place of `unknown` to say so on purpose.
596
+ */
483
597
  type NoCtx = Readonly<Record<never, never>>;
484
598
  type HandlerCtx<Ctx> = (0 extends 1 & Ctx ? Ctx : [
485
599
  Ctx
486
600
  ] extends [void] ? unknown : Ctx) & PortEmitter;
601
+ /**
602
+ * The Cmd handler table an engine is handed: one async handler per Cmd type.
603
+ * Leaving a Cmd type out is a compile error.
604
+ */
487
605
  type Interpret<M extends {
488
606
  type: string;
489
607
  }, C extends Cmd, Ctx> = {
@@ -506,9 +624,28 @@ type OkOfCmd<C> = C extends {
506
624
  } ? Ok : unknown;
507
625
  /** The failures a `Cmd.define`d Cmd's handler may return: its declared tags. */
508
626
  type DeclaredErrorsOf<C> = Exclude<ErrorsOf<C>, MalformedResult>;
627
+ /**
628
+ * A Cmd handler that reports back through a `dispatch` limited to the Msgs it
629
+ * is allowed to send. Use it for work that outlives the handler call, and adapt
630
+ * it into an `Interpret` cell with `wrapDetached`.
631
+ *
632
+ * Such a handler hands its long-running work to `ctx.waitUntil(...)` and cannot
633
+ * return its terminal Msg inline, because awaiting it would deadlock the serial
634
+ * dispatch tail. So it returns `Promise<void>` and dispatches instead.
635
+ * `Allowed` is the Cmd's declared result-Msg set (e.g.
636
+ * `GraphFinished | GraphFailed`), and `dispatch` takes only those, so a wrong
637
+ * or mistyped terminal Msg fails to compile.
638
+ */
509
639
  type InterpretDetached<C extends Cmd, Allowed extends {
510
640
  type: string;
511
641
  }, Ctx> = (cmd: C, ctx: HandlerCtx<Ctx>, dispatch: (msg: Allowed) => void) => Promise<void>;
642
+ /**
643
+ * The Sub runner table an engine is handed: one runner per Sub type. Leaving a
644
+ * Sub type out is a compile error. Each runner receives the running Sub
645
+ * (`{ id, type, deps }`), the Ctx and a `dispatch`. It opens its resource,
646
+ * dispatches Msgs from it, and returns the `Dispose` the engine calls when the
647
+ * Sub stops.
648
+ */
512
649
  type Subscribe<M extends {
513
650
  type: string;
514
651
  }, U extends Sub, Ctx> = {
@@ -564,6 +701,10 @@ type Wired<S, M extends {
564
701
  }, C extends Cmd, U extends Sub, Ctx> = {
565
702
  readonly machine: Machine<S, M, C, U, Ctx>;
566
703
  } & RunHandlers<M, C, U, Ctx>;
704
+ /**
705
+ * A machine as plain data: `init`, `update`, and optionally `subs`, `cmds` and
706
+ * `identity`. Build one with `defineMachine` and hand it to an engine's `run`.
707
+ */
567
708
  type Machine<S, M extends {
568
709
  type: string;
569
710
  }, C extends Cmd, U extends Sub, Ctx> = {
@@ -643,6 +784,12 @@ type Machine<S, M extends {
643
784
  */
644
785
  readonly __form?: UpdateForm;
645
786
  };
787
+ /**
788
+ * Fold a machine's `update` over a list of Msgs from a starting state, and
789
+ * return the final state with every Cmd the cells emitted. `replay` and
790
+ * `foldMsgs` cover the common cases; use this when you need both the state and
791
+ * the Cmds from a state of your choosing.
792
+ */
646
793
  declare function foldUpdates<S, M extends {
647
794
  type: string;
648
795
  }, C extends Cmd>(machine: {
@@ -652,8 +799,13 @@ declare function foldUpdates<S, M extends {
652
799
  state: S;
653
800
  cmds: C[];
654
801
  };
802
+ /**
803
+ * Fold a machine's `update` over a list of Msgs from a base state and return
804
+ * only the final state. Use it for client-side prediction: re-apply
805
+ * unacknowledged inputs on top of a server snapshot without running any effect.
806
+ */
655
807
  declare function foldMsgs<S, M extends {
656
808
  type: string;
657
809
  }, C extends Cmd, U extends Sub, Ctx>(machine: Machine<S, M, C, U, Ctx>, base: S, msgs: readonly M[]): S;
658
810
 
659
- export { applyCell as $, type AnyCmdDef as A, type BuiltinSub as B, Cmd as C, type Dispose as D, type ErrOf as E, type MachineShape as F, type NoCtx as G, type HandlerCtx as H, type Interpret as I, type OkOfCmd as J, OutcomeContractError as K, type OutcomeHelpers as L, type Machine as M, NoCellError as N, Outcome as O, type Port as P, type PortEmitter as Q, type RunHandlers as R, type Subscribe as S, type TimerDeps as T, type UpdateForm as U, type SubscribeArg as V, type Wired as W, type SyncReturn as X, UndeclaredFailureError as Y, acceptedTypes as Z, acceptsOf as _, type CmdOf as a, applyCellChecked as a0, describeMachine as a1, detectUpdateForm as a2, foldMsgs as a3, foldUpdates as a4, formOf as a5, msgKeysOf as a6, structuralHash as a7, subId as a8, subIdOf as a9, type CmdDef as b, type Sub as c, type SettledOk as d, type SettledErr as e, type TaggedError as f, type Reducer as g, type Settled as h, type Transitions as i, type InterpretDetached as j, type SubId as k, type DepKeyedSub as l, type TimerSub as m, type MalformedResult as n, type Tagged as o, type OkOf as p, type CmdValue as q, AsyncSchemaError as r, type BuiltinSubType as s, type CmdInput as t, type DeclaredErrorsOf as u, type ErrorsOf as v, type ExhaustiveTransitions as w, type Identity as x, type InterpretArg as y, type InterpretCell as z };
811
+ export { applyCell as $, type AnyCmdDef as A, type BuiltinSub as B, Cmd as C, type Dispose as D, type ErrorsOf as E, type InterpretCell as F, type MachineShape as G, type HandlerCtx as H, type Interpret as I, type NoCtx as J, OutcomeContractError as K, type OutcomeHelpers as L, type Machine as M, NoCellError as N, Outcome as O, type Port as P, type PortEmitter as Q, type RunHandlers as R, type Sub as S, type TimerDeps as T, type UpdateForm as U, type SubscribeArg as V, type Wired as W, type SyncReturn as X, UndeclaredFailureError as Y, acceptedTypes as Z, acceptsOf as _, type CmdOf as a, applyCellChecked as a0, describeMachine as a1, detectUpdateForm as a2, foldMsgs as a3, foldUpdates as a4, formOf as a5, msgKeysOf as a6, structuralHash as a7, subId as a8, subIdOf as a9, type CmdDef as b, type Subscribe as c, type SettledOk as d, type SettledErr as e, type TaggedError as f, type Reducer as g, type Settled as h, type Transitions as i, type InterpretDetached as j, type SubId as k, type DepKeyedSub as l, type TimerSub as m, type MalformedResult as n, type OkOfCmd as o, type DeclaredErrorsOf as p, type BuiltinSubType as q, type Tagged as r, type OkOf as s, type ErrOf as t, type CmdValue as u, AsyncSchemaError as v, type CmdInput as w, type ExhaustiveTransitions as x, type Identity as y, type InterpretArg as z };
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ /** One row of the `MsgLog`: a timestamp, a category and the text to show. */
3
4
  type MsgLogEntry = {
4
5
  /** Display timestamp (whatever format you produced). */
5
6
  ts: string;
@@ -8,10 +9,14 @@ type MsgLogEntry = {
8
9
  /** Row text — usually the Msg tag plus a short detail. */
9
10
  text: string;
10
11
  };
12
+ /** Props for `MsgLog`: the rows to render and an optional `className`. */
11
13
  interface MsgLogProps {
12
14
  history: readonly MsgLogEntry[];
13
15
  className?: string;
14
16
  }
17
+ /**
18
+ * React component that renders a list of `MsgLogEntry` rows as a message log.
19
+ */
15
20
  declare function MsgLog({ history, className }: MsgLogProps): react_jsx_runtime.JSX.Element;
16
21
 
17
22
  /**
@@ -68,6 +73,10 @@ declare function diffState(expected: unknown, actual: unknown): StateChange[];
68
73
  */
69
74
  declare function formatDiff(changes: StateChange[]): string;
70
75
 
76
+ /**
77
+ * Props for `StateDiff`: the `expected` and `actual` states to compare, and an
78
+ * optional `className`.
79
+ */
71
80
  interface StateDiffProps {
72
81
  /**
73
82
  * The baseline / "before" state — what you expected. In a regression view
@@ -95,6 +104,10 @@ interface StateDiffProps {
95
104
  */
96
105
  declare function StateDiff({ expected, actual, className }: StateDiffProps): react_jsx_runtime.JSX.Element;
97
106
 
107
+ /**
108
+ * Props for `StateInspector`: the `state` to show, an optional `flashKey`, and
109
+ * an optional `className`.
110
+ */
98
111
  interface StateInspectorProps {
99
112
  /**
100
113
  * The machine state to display. Render-derived shape — pass whatever you
@@ -111,6 +124,10 @@ interface StateInspectorProps {
111
124
  */
112
125
  className?: string;
113
126
  }
127
+ /**
128
+ * React component that renders a state value as formatted JSON, and flashes
129
+ * when `flashKey` changes.
130
+ */
114
131
  declare function StateInspector({ state, flashKey, className, }: StateInspectorProps): react_jsx_runtime.JSX.Element;
115
132
 
116
133
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/devtools/msg-log.tsx","../../src/devtools/state-diff.ts","../../src/devtools/state-diff-view.tsx","../../src/devtools/state-inspector.tsx","../../src/devtools/use-msg-history.ts"],"names":["jsxs","jsx","useRef"],"mappings":"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","file":"index.js","sourcesContent":["export type MsgLogEntry = {\n /** Display timestamp (whatever format you produced). */\n ts: string;\n /** Visual category — drives the row icon. Defaults to \"msg\" via CSS. */\n kind?: \"msg\" | \"sub\" | \"cmd\" | \"ok\" | \"fail\";\n /** Row text — usually the Msg tag plus a short detail. */\n text: string;\n};\n\nexport interface MsgLogProps {\n history: readonly MsgLogEntry[];\n className?: string;\n}\n\nexport function MsgLog({ history, className }: MsgLogProps) {\n return (\n <div className={`tea-dt-log${className ? ` ${className}` : \"\"}`}>\n {history.map((r, i) => (\n <div\n key={`${r.ts}-${i}`}\n className={`tea-dt-row tea-dt-${r.kind ?? \"msg\"}`}\n >\n <span className=\"tea-dt-t\">{r.ts}</span>\n <span className=\"tea-dt-m\">{r.text}</span>\n </div>\n ))}\n </div>\n );\n}\n","// ---------------------------------------------------------------------------\n// state-diff — the RICHER cousin of trace-replay's first-divergence walk.\n//\n// `../trace-replay` answers \"did the state drift, and where FIRST?\" — it stops\n// at the first differing cell because a regression check only needs to point at\n// one. This module answers the fuller devtools question: \"show me EVERY cell\n// that differs,\" classified as added / removed / changed, ready to render.\n//\n// Same substrate, same path grammar (root `state`, `foo[2]` for arrays,\n// `foo.bar` for objects, sorted-union key order, `Object.is` leaf equality) so\n// a path printed here is the SAME string trace-replay would print for that\n// cell. The two tools are deliberately consistent: a `divergence.path` from a\n// replay result indexes straight into this module's `StateChange[]`.\n//\n// Pure + zero-dep on purpose — runs in Node, in tests, in a Worker. The React\n// view (`./state-diff.tsx`) is the only React-touching layer.\n// ---------------------------------------------------------------------------\n\nimport {\n indexPath,\n keyPath,\n typeOf,\n unionKeys,\n} from \"../internal/persistence/trace-replay/state-walk\";\n\n/**\n * A single differing leaf value between two states.\n *\n * - `kind: \"added\"` — the path exists in `actual` but not `expected`\n * (`expected` is `undefined`).\n * - `kind: \"removed\"` — the path exists in `expected` but not `actual`\n * (`actual` is `undefined`).\n * - `kind: \"changed\"` — the path exists on both sides with differing leaf\n * values (or differing kinds, e.g. object vs array).\n */\nexport interface StateChange {\n /** Access path from the state root, e.g. `state.items[1].status`. */\n path: string;\n /** How the cell differs between the two states. */\n kind: \"added\" | \"removed\" | \"changed\";\n /** The value on the `expected` side (`undefined` when `added`). */\n expected: unknown;\n /** The value on the `actual` side (`undefined` when `removed`). */\n actual: unknown;\n}\n\n/**\n * Deep-walk two states and return EVERY differing leaf value, in deterministic\n * pre-order (the node before its children; children in array-index order, then\n * sorted-union key order for objects). The empty array means the two states are\n * deeply equal.\n *\n * Equality + path grammar match `../trace-replay`'s `firstDivergence` exactly:\n * - `Object.is` leaf equality, so `NaN` equals `NaN` and `+0` ≠ `-0`.\n * - arrays index by `[i]`; a length mismatch is NOT reported at the array\n * node — instead each surplus/missing element surfaces as its own\n * added/removed child, which is what a devtools list wants to show.\n * - objects walk the sorted union of both sides' keys; a key on only one\n * side becomes an `added`/`removed` child.\n * - the root path is `\"state\"`.\n *\n * Scope is JSON-shaped state (the same substrate trace-replay targets):\n * primitives, null/undefined, arrays, plain objects. A differing kind at a node\n * (object vs array, number vs string) is reported as a single `changed` at that\n * node — the walk does not descend into mismatched kinds.\n */\nexport function diffState(expected: unknown, actual: unknown): StateChange[] {\n const out: StateChange[] = [];\n walk(expected, actual, \"state\", out);\n return out;\n}\n\nfunction walk(\n expected: unknown,\n actual: unknown,\n path: string,\n out: StateChange[],\n): void {\n // Identity / primitive fast path. Equal cells contribute nothing. `Object.is`\n // so NaN equals NaN and +0 ≠ -0 — same intent as trace-replay's leaf check.\n if (Object.is(expected, actual)) return;\n\n const te = typeOf(expected);\n const ta = typeOf(actual);\n\n // A present/absent pair at this node is an add or a remove — the structural\n // signal a viewer color-codes differently from a value change.\n if (te === \"undefined\") {\n out.push({ path, kind: \"added\", expected, actual });\n return;\n }\n if (ta === \"undefined\") {\n out.push({ path, kind: \"removed\", expected, actual });\n return;\n }\n\n // Different kinds at a present node (object vs array, number vs string,\n // value vs null) — one `changed` at the node; do not descend into mismatched\n // shapes, mirroring trace-replay's \"this node IS the divergence\".\n if (te !== ta) {\n out.push({ path, kind: \"changed\", expected, actual });\n return;\n }\n\n if (te === \"array\") {\n const ae = expected as unknown[];\n const aa = actual as unknown[];\n // Walk the union of indices so surplus elements on EITHER side surface as\n // their own added/removed children (vs trace-replay, which reports a length\n // mismatch at the array node and stops). A viewer wants the per-element\n // detail.\n const len = Math.max(ae.length, aa.length);\n for (let i = 0; i < len; i++) {\n walk(ae[i], aa[i], indexPath(path, i), out);\n }\n return;\n }\n\n if (te === \"object\") {\n const oe = expected as Record<string, unknown>;\n const oa = actual as Record<string, unknown>;\n // Sorted union of keys — deterministic regardless of insertion order, so\n // two states with the same data in different key order produce no changes,\n // and the reported order is reproducible run-to-run.\n for (const key of unionKeys(oe, oa)) {\n walk(oe[key], oa[key], keyPath(path, key), out);\n }\n return;\n }\n\n // Two present primitives (string/number/boolean/bigint/symbol) or two\n // differing nulls that failed the Object.is fast path — a leaf change.\n out.push({ path, kind: \"changed\", expected, actual });\n}\n\n/** Render a single value compactly for a diff cell. Strings get quotes so\n * `\"3\"` is visibly distinct from `3`; everything else is JSON-ish, with the\n * `undefined`/`NaN`/`BigInt` cases JSON.stringify mishandles spelled out.\n * Exported (though not re-exported from `./index`) so the React `<StateDiff>`\n * view renders each cell with this exact formatter rather than a copy. */\nexport function fmtValue(v: unknown): string {\n if (v === undefined) return \"undefined\";\n if (typeof v === \"number\" && Number.isNaN(v)) return \"NaN\";\n if (typeof v === \"bigint\") return `${v}n`;\n if (typeof v === \"string\") return JSON.stringify(v);\n if (typeof v === \"function\" || typeof v === \"symbol\") return String(v);\n try {\n return JSON.stringify(v) ?? String(v);\n } catch {\n // Circular / non-serializable — fall back to a coarse tag.\n return String(v);\n }\n}\n\n/**\n * Pretty multi-line text for a {@link diffState} result. One `±`-prefixed line\n * per change, in the array's (pre-order, deterministic) order:\n *\n * - `~ state.total: 121.5 → 135` (changed: old → new)\n * - `- state.coupon: \"X\"` (removed: only the old value)\n * - `+ state.tax: 8` (added: only the new value)\n *\n * Deterministic given a deterministic `changes` array. An empty array yields\n * the empty string.\n */\nexport function formatDiff(changes: StateChange[]): string {\n return changes.map(formatChange).join(\"\\n\");\n}\n\n/** One `±`-prefixed line for a single change. Split out so the `map` callback\n * is total (Biome's useIterableCallbackReturn) without a dead default branch. */\nfunction formatChange(c: StateChange): string {\n switch (c.kind) {\n case \"changed\":\n return `~ ${c.path}: ${fmtValue(c.expected)} → ${fmtValue(c.actual)}`;\n case \"removed\":\n return `- ${c.path}: ${fmtValue(c.expected)}`;\n case \"added\":\n return `+ ${c.path}: ${fmtValue(c.actual)}`;\n }\n}\n","import {\n diffState,\n fmtValue,\n formatDiff,\n type StateChange,\n} from \"./state-diff\";\n\nexport interface StateDiffProps {\n /**\n * The baseline / \"before\" state — what you expected. In a regression view\n * this is a trace's recorded `finalState`; in a time-travel view it's the\n * previous model.\n */\n expected: unknown;\n /**\n * The \"after\" state to compare against `expected` — the recomputed or\n * current model.\n */\n actual: unknown;\n /** Optional className appended to the container. Use to override layout. */\n className?: string;\n}\n\n/** Per-kind row glyph + value rendering. Lives here (not CSS ::before like the\n * MsgLog rows) because the diff prints the path AND the value(s), so the glyph\n * is part of structured content the screen reader should read in order. */\nfunction changeRow(c: StateChange) {\n // `path` is unique within one diff (each cell appears at most once), so it is\n // a stable React key without needing the array index.\n switch (c.kind) {\n case \"changed\":\n return (\n <div key={c.path} className=\"tea-dt-diff-row tea-dt-diff-changed\">\n <span className=\"tea-dt-diff-mark\">~</span>\n <span className=\"tea-dt-diff-path\">{c.path}</span>\n <span className=\"tea-dt-diff-old\">{fmtValue(c.expected)}</span>\n <span className=\"tea-dt-diff-arrow\">→</span>\n <span className=\"tea-dt-diff-new\">{fmtValue(c.actual)}</span>\n </div>\n );\n case \"removed\":\n return (\n <div key={c.path} className=\"tea-dt-diff-row tea-dt-diff-removed\">\n <span className=\"tea-dt-diff-mark\">-</span>\n <span className=\"tea-dt-diff-path\">{c.path}</span>\n <span className=\"tea-dt-diff-old\">{fmtValue(c.expected)}</span>\n </div>\n );\n case \"added\":\n return (\n <div key={c.path} className=\"tea-dt-diff-row tea-dt-diff-added\">\n <span className=\"tea-dt-diff-mark\">+</span>\n <span className=\"tea-dt-diff-path\">{c.path}</span>\n <span className=\"tea-dt-diff-new\">{fmtValue(c.actual)}</span>\n </div>\n );\n }\n}\n\n/**\n * Presentational diff of two states. Renders {@link diffState}'s output as a\n * color-coded list (added / removed / changed), reusing the devtools `tea-dt-*`\n * class convention so it inherits the same design tokens as `<StateInspector>`\n * and `<MsgLog>` (see ./styles.css). No state, no subscription — pass the two\n * states as props, exactly like the rest of /devtools.\n *\n * When the states are deeply equal the list is empty; a tiny \"no changes\" hint\n * renders so an operator can tell \"equal\" from \"not yet computed\".\n */\nexport function StateDiff({ expected, actual, className }: StateDiffProps) {\n const changes = diffState(expected, actual);\n return (\n <div\n className={`tea-dt-diff${className ? ` ${className}` : \"\"}`}\n // The plain-text diff is the accessible/copyable fallback for the\n // color-coded rows — same content `formatDiff` produces in Node/tests.\n title={changes.length === 0 ? \"no changes\" : formatDiff(changes)}\n >\n {changes.length === 0 ? (\n <div className=\"tea-dt-diff-empty\">no changes</div>\n ) : (\n changes.map(changeRow)\n )}\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\n\nfunction escapeHtml(s: string): string {\n return s.replace(\n /[&<>\"]/g,\n (c) =>\n ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\" })[c] as string,\n );\n}\n\nfunction fmtJson(obj: unknown, indent = 0): string {\n if (obj === null) return '<span class=\"tea-dt-b\">null</span>';\n if (typeof obj === \"number\") return `<span class=\"tea-dt-n\">${obj}</span>`;\n if (typeof obj === \"boolean\") return `<span class=\"tea-dt-b\">${obj}</span>`;\n if (typeof obj === \"string\")\n return `<span class=\"tea-dt-s\">\"${escapeHtml(obj)}\"</span>`;\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '<span class=\"tea-dt-br\">[]</span>';\n return (\n '<span class=\"tea-dt-br\">[</span>' +\n obj\n .map((v) => fmtJson(v, indent + 1))\n .join('<span class=\"tea-dt-br\">, </span>') +\n '<span class=\"tea-dt-br\">]</span>'\n );\n }\n if (typeof obj === \"object\") {\n const keys = Object.keys(obj as object);\n if (keys.length === 0) return '<span class=\"tea-dt-br\">{}</span>';\n const pad = \"&nbsp;&nbsp;\".repeat(indent + 1);\n const lines = keys.map((k, i) => {\n const v = (obj as Record<string, unknown>)[k];\n const comma =\n i < keys.length - 1 ? '<span class=\"tea-dt-br\">,</span>' : \"\";\n return `${pad}<span class=\"tea-dt-k\">${escapeHtml(k)}</span><span class=\"tea-dt-br\">:</span> ${fmtJson(v, indent + 1)}${comma}`;\n });\n return [\n '<span class=\"tea-dt-br\">{</span>',\n ...lines,\n `${\"&nbsp;&nbsp;\".repeat(indent)}<span class=\"tea-dt-br\">}</span>`,\n ].join(\"<br/>\");\n }\n return escapeHtml(String(obj));\n}\n\nexport interface StateInspectorProps {\n /**\n * The machine state to display. Render-derived shape — pass whatever you\n * want surfaced to the inspector (often a hand-picked subset of the model).\n */\n state: unknown;\n /**\n * When this number changes, the inspector flashes. Pass `model.msgCount` or\n * any other monotonic counter you already have. Omit to disable flashing.\n */\n flashKey?: number;\n /**\n * Optional className appended to the container. Use to override layout.\n */\n className?: string;\n}\n\nexport function StateInspector({\n state,\n flashKey,\n className,\n}: StateInspectorProps) {\n const boxRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (flashKey === undefined || !boxRef.current) return;\n boxRef.current.classList.remove(\"tea-dt-flash\");\n void boxRef.current.offsetWidth;\n boxRef.current.classList.add(\"tea-dt-flash\");\n }, [flashKey]);\n\n return (\n <div\n ref={boxRef}\n className={`tea-dt-state${className ? ` ${className}` : \"\"}`}\n >\n <div\n className=\"tea-dt-json\"\n // biome-ignore lint/security/noDangerouslySetInnerHtml: formatter output\n dangerouslySetInnerHTML={{ __html: fmtJson(state) }}\n />\n </div>\n );\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport type { MsgLogEntry } from \"./msg-log\";\n\nfunction nowTs(): string {\n return new Date().toLocaleTimeString(\"en-GB\", { hour12: false }).slice(3);\n}\n\n/**\n * Wrap a `dispatch` so every Msg it sees lands in a bounded history buffer.\n *\n * `derive` lets you map a Msg to a richer entry (e.g. assign `kind: \"sub\"` to\n * subscription-triggered messages). Default: every msg becomes a `\"msg\"` row\n * tagged with `msg.type` (or `String(msg)` if it has no `type`). The substrate\n * uses `type` as the Msg discriminant — using `_tag` here would render every\n * Msg as `[object Object]` in the inspector.\n *\n * `max` caps the buffer — oldest entries fall off (LIFO, newest first).\n *\n * `now` is the timestamp source for the default `derive`. Defaults to\n * `nowTs` (real wall-clock). Tests inject a deterministic shim so\n * snapshots don't drift; production code never sets it.\n */\nexport function useMsgHistory<M>(\n dispatch: (msg: M) => void | Promise<void>,\n opts: {\n max?: number;\n derive?: (msg: M) => MsgLogEntry;\n now?: () => string;\n } = {},\n): readonly [readonly MsgLogEntry[], (msg: M) => void, () => void] {\n const max = opts.max ?? 60;\n const now = opts.now ?? nowTs;\n const derive =\n opts.derive ??\n ((msg: M): MsgLogEntry => {\n const tag =\n msg && typeof msg === \"object\" && \"type\" in msg\n ? String((msg as { type: unknown }).type)\n : String(msg);\n return { ts: now(), kind: \"msg\", text: tag };\n });\n\n const [history, setHistory] = useState<readonly MsgLogEntry[]>([]);\n // Stable ref to `dispatch` so the wrapper identity stays stable across\n // renders — important when this is passed to keyboard handlers and the like.\n const dispatchRef = useRef(dispatch);\n dispatchRef.current = dispatch;\n const deriveRef = useRef(derive);\n deriveRef.current = derive;\n\n const wrapped = useCallback(\n (msg: M) => {\n const entry = deriveRef.current(msg);\n setHistory((prev) => [entry, ...prev].slice(0, max));\n // Fire-and-forget — `dispatch` may return a Promise; we don't await it\n // here because callers historically treat dispatch as void.\n void dispatchRef.current(msg);\n },\n [max],\n );\n\n const clear = useCallback(() => setHistory([]), []);\n\n return [history, wrapped, clear] as const;\n}\n"]}
1
+ {"version":3,"sources":["../../src/devtools/msg-log.tsx","../../src/devtools/state-diff.ts","../../src/devtools/state-diff-view.tsx","../../src/devtools/state-inspector.tsx","../../src/devtools/use-msg-history.ts"],"names":["jsxs","jsx","useRef"],"mappings":"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","file":"index.js","sourcesContent":["/** One row of the `MsgLog`: a timestamp, a category and the text to show. */\nexport type MsgLogEntry = {\n /** Display timestamp (whatever format you produced). */\n ts: string;\n /** Visual category — drives the row icon. Defaults to \"msg\" via CSS. */\n kind?: \"msg\" | \"sub\" | \"cmd\" | \"ok\" | \"fail\";\n /** Row text — usually the Msg tag plus a short detail. */\n text: string;\n};\n\n/** Props for `MsgLog`: the rows to render and an optional `className`. */\nexport interface MsgLogProps {\n history: readonly MsgLogEntry[];\n className?: string;\n}\n\n/**\n * React component that renders a list of `MsgLogEntry` rows as a message log.\n */\nexport function MsgLog({ history, className }: MsgLogProps) {\n return (\n <div className={`tea-dt-log${className ? ` ${className}` : \"\"}`}>\n {history.map((r, i) => (\n <div\n key={`${r.ts}-${i}`}\n className={`tea-dt-row tea-dt-${r.kind ?? \"msg\"}`}\n >\n <span className=\"tea-dt-t\">{r.ts}</span>\n <span className=\"tea-dt-m\">{r.text}</span>\n </div>\n ))}\n </div>\n );\n}\n","// ---------------------------------------------------------------------------\n// state-diff — the RICHER cousin of trace-replay's first-divergence walk.\n//\n// `../trace-replay` answers \"did the state drift, and where FIRST?\" — it stops\n// at the first differing cell because a regression check only needs to point at\n// one. This module answers the fuller devtools question: \"show me EVERY cell\n// that differs,\" classified as added / removed / changed, ready to render.\n//\n// Same substrate, same path grammar (root `state`, `foo[2]` for arrays,\n// `foo.bar` for objects, sorted-union key order, `Object.is` leaf equality) so\n// a path printed here is the SAME string trace-replay would print for that\n// cell. The two tools are deliberately consistent: a `divergence.path` from a\n// replay result indexes straight into this module's `StateChange[]`.\n//\n// Pure + zero-dep on purpose — runs in Node, in tests, in a Worker. The React\n// view (`./state-diff.tsx`) is the only React-touching layer.\n// ---------------------------------------------------------------------------\n\nimport {\n indexPath,\n keyPath,\n typeOf,\n unionKeys,\n} from \"../internal/persistence/trace-replay/state-walk\";\n\n/**\n * A single differing leaf value between two states.\n *\n * - `kind: \"added\"` — the path exists in `actual` but not `expected`\n * (`expected` is `undefined`).\n * - `kind: \"removed\"` — the path exists in `expected` but not `actual`\n * (`actual` is `undefined`).\n * - `kind: \"changed\"` — the path exists on both sides with differing leaf\n * values (or differing kinds, e.g. object vs array).\n */\nexport interface StateChange {\n /** Access path from the state root, e.g. `state.items[1].status`. */\n path: string;\n /** How the cell differs between the two states. */\n kind: \"added\" | \"removed\" | \"changed\";\n /** The value on the `expected` side (`undefined` when `added`). */\n expected: unknown;\n /** The value on the `actual` side (`undefined` when `removed`). */\n actual: unknown;\n}\n\n/**\n * Deep-walk two states and return EVERY differing leaf value, in deterministic\n * pre-order (the node before its children; children in array-index order, then\n * sorted-union key order for objects). The empty array means the two states are\n * deeply equal.\n *\n * Equality + path grammar match `../trace-replay`'s `firstDivergence` exactly:\n * - `Object.is` leaf equality, so `NaN` equals `NaN` and `+0` ≠ `-0`.\n * - arrays index by `[i]`; a length mismatch is NOT reported at the array\n * node — instead each surplus/missing element surfaces as its own\n * added/removed child, which is what a devtools list wants to show.\n * - objects walk the sorted union of both sides' keys; a key on only one\n * side becomes an `added`/`removed` child.\n * - the root path is `\"state\"`.\n *\n * Scope is JSON-shaped state (the same substrate trace-replay targets):\n * primitives, null/undefined, arrays, plain objects. A differing kind at a node\n * (object vs array, number vs string) is reported as a single `changed` at that\n * node — the walk does not descend into mismatched kinds.\n */\nexport function diffState(expected: unknown, actual: unknown): StateChange[] {\n const out: StateChange[] = [];\n walk(expected, actual, \"state\", out);\n return out;\n}\n\nfunction walk(\n expected: unknown,\n actual: unknown,\n path: string,\n out: StateChange[],\n): void {\n // Identity / primitive fast path. Equal cells contribute nothing. `Object.is`\n // so NaN equals NaN and +0 ≠ -0 — same intent as trace-replay's leaf check.\n if (Object.is(expected, actual)) return;\n\n const te = typeOf(expected);\n const ta = typeOf(actual);\n\n // A present/absent pair at this node is an add or a remove — the structural\n // signal a viewer color-codes differently from a value change.\n if (te === \"undefined\") {\n out.push({ path, kind: \"added\", expected, actual });\n return;\n }\n if (ta === \"undefined\") {\n out.push({ path, kind: \"removed\", expected, actual });\n return;\n }\n\n // Different kinds at a present node (object vs array, number vs string,\n // value vs null) — one `changed` at the node; do not descend into mismatched\n // shapes, mirroring trace-replay's \"this node IS the divergence\".\n if (te !== ta) {\n out.push({ path, kind: \"changed\", expected, actual });\n return;\n }\n\n if (te === \"array\") {\n const ae = expected as unknown[];\n const aa = actual as unknown[];\n // Walk the union of indices so surplus elements on EITHER side surface as\n // their own added/removed children (vs trace-replay, which reports a length\n // mismatch at the array node and stops). A viewer wants the per-element\n // detail.\n const len = Math.max(ae.length, aa.length);\n for (let i = 0; i < len; i++) {\n walk(ae[i], aa[i], indexPath(path, i), out);\n }\n return;\n }\n\n if (te === \"object\") {\n const oe = expected as Record<string, unknown>;\n const oa = actual as Record<string, unknown>;\n // Sorted union of keys — deterministic regardless of insertion order, so\n // two states with the same data in different key order produce no changes,\n // and the reported order is reproducible run-to-run.\n for (const key of unionKeys(oe, oa)) {\n walk(oe[key], oa[key], keyPath(path, key), out);\n }\n return;\n }\n\n // Two present primitives (string/number/boolean/bigint/symbol) or two\n // differing nulls that failed the Object.is fast path — a leaf change.\n out.push({ path, kind: \"changed\", expected, actual });\n}\n\n/** Render a single value compactly for a diff cell. Strings get quotes so\n * `\"3\"` is visibly distinct from `3`; everything else is JSON-ish, with the\n * `undefined`/`NaN`/`BigInt` cases JSON.stringify mishandles spelled out.\n * Exported (though not re-exported from `./index`) so the React `<StateDiff>`\n * view renders each cell with this exact formatter rather than a copy. */\nexport function fmtValue(v: unknown): string {\n if (v === undefined) return \"undefined\";\n if (typeof v === \"number\" && Number.isNaN(v)) return \"NaN\";\n if (typeof v === \"bigint\") return `${v}n`;\n if (typeof v === \"string\") return JSON.stringify(v);\n if (typeof v === \"function\" || typeof v === \"symbol\") return String(v);\n try {\n return JSON.stringify(v) ?? String(v);\n } catch {\n // Circular / non-serializable — fall back to a coarse tag.\n return String(v);\n }\n}\n\n/**\n * Pretty multi-line text for a {@link diffState} result. One `±`-prefixed line\n * per change, in the array's (pre-order, deterministic) order:\n *\n * - `~ state.total: 121.5 → 135` (changed: old → new)\n * - `- state.coupon: \"X\"` (removed: only the old value)\n * - `+ state.tax: 8` (added: only the new value)\n *\n * Deterministic given a deterministic `changes` array. An empty array yields\n * the empty string.\n */\nexport function formatDiff(changes: StateChange[]): string {\n return changes.map(formatChange).join(\"\\n\");\n}\n\n/** One `±`-prefixed line for a single change. Split out so the `map` callback\n * is total (Biome's useIterableCallbackReturn) without a dead default branch. */\nfunction formatChange(c: StateChange): string {\n switch (c.kind) {\n case \"changed\":\n return `~ ${c.path}: ${fmtValue(c.expected)} → ${fmtValue(c.actual)}`;\n case \"removed\":\n return `- ${c.path}: ${fmtValue(c.expected)}`;\n case \"added\":\n return `+ ${c.path}: ${fmtValue(c.actual)}`;\n }\n}\n","import {\n diffState,\n fmtValue,\n formatDiff,\n type StateChange,\n} from \"./state-diff\";\n\n/**\n * Props for `StateDiff`: the `expected` and `actual` states to compare, and an\n * optional `className`.\n */\nexport interface StateDiffProps {\n /**\n * The baseline / \"before\" state — what you expected. In a regression view\n * this is a trace's recorded `finalState`; in a time-travel view it's the\n * previous model.\n */\n expected: unknown;\n /**\n * The \"after\" state to compare against `expected` — the recomputed or\n * current model.\n */\n actual: unknown;\n /** Optional className appended to the container. Use to override layout. */\n className?: string;\n}\n\n/** Per-kind row glyph + value rendering. Lives here (not CSS ::before like the\n * MsgLog rows) because the diff prints the path AND the value(s), so the glyph\n * is part of structured content the screen reader should read in order. */\nfunction changeRow(c: StateChange) {\n // `path` is unique within one diff (each cell appears at most once), so it is\n // a stable React key without needing the array index.\n switch (c.kind) {\n case \"changed\":\n return (\n <div key={c.path} className=\"tea-dt-diff-row tea-dt-diff-changed\">\n <span className=\"tea-dt-diff-mark\">~</span>\n <span className=\"tea-dt-diff-path\">{c.path}</span>\n <span className=\"tea-dt-diff-old\">{fmtValue(c.expected)}</span>\n <span className=\"tea-dt-diff-arrow\">→</span>\n <span className=\"tea-dt-diff-new\">{fmtValue(c.actual)}</span>\n </div>\n );\n case \"removed\":\n return (\n <div key={c.path} className=\"tea-dt-diff-row tea-dt-diff-removed\">\n <span className=\"tea-dt-diff-mark\">-</span>\n <span className=\"tea-dt-diff-path\">{c.path}</span>\n <span className=\"tea-dt-diff-old\">{fmtValue(c.expected)}</span>\n </div>\n );\n case \"added\":\n return (\n <div key={c.path} className=\"tea-dt-diff-row tea-dt-diff-added\">\n <span className=\"tea-dt-diff-mark\">+</span>\n <span className=\"tea-dt-diff-path\">{c.path}</span>\n <span className=\"tea-dt-diff-new\">{fmtValue(c.actual)}</span>\n </div>\n );\n }\n}\n\n/**\n * Presentational diff of two states. Renders {@link diffState}'s output as a\n * color-coded list (added / removed / changed), reusing the devtools `tea-dt-*`\n * class convention so it inherits the same design tokens as `<StateInspector>`\n * and `<MsgLog>` (see ./styles.css). No state, no subscription — pass the two\n * states as props, exactly like the rest of /devtools.\n *\n * When the states are deeply equal the list is empty; a tiny \"no changes\" hint\n * renders so an operator can tell \"equal\" from \"not yet computed\".\n */\nexport function StateDiff({ expected, actual, className }: StateDiffProps) {\n const changes = diffState(expected, actual);\n return (\n <div\n className={`tea-dt-diff${className ? ` ${className}` : \"\"}`}\n // The plain-text diff is the accessible/copyable fallback for the\n // color-coded rows — same content `formatDiff` produces in Node/tests.\n title={changes.length === 0 ? \"no changes\" : formatDiff(changes)}\n >\n {changes.length === 0 ? (\n <div className=\"tea-dt-diff-empty\">no changes</div>\n ) : (\n changes.map(changeRow)\n )}\n </div>\n );\n}\n","import { useEffect, useRef } from \"react\";\n\nfunction escapeHtml(s: string): string {\n return s.replace(\n /[&<>\"]/g,\n (c) =>\n ({ \"&\": \"&amp;\", \"<\": \"&lt;\", \">\": \"&gt;\", '\"': \"&quot;\" })[c] as string,\n );\n}\n\nfunction fmtJson(obj: unknown, indent = 0): string {\n if (obj === null) return '<span class=\"tea-dt-b\">null</span>';\n if (typeof obj === \"number\") return `<span class=\"tea-dt-n\">${obj}</span>`;\n if (typeof obj === \"boolean\") return `<span class=\"tea-dt-b\">${obj}</span>`;\n if (typeof obj === \"string\")\n return `<span class=\"tea-dt-s\">\"${escapeHtml(obj)}\"</span>`;\n if (Array.isArray(obj)) {\n if (obj.length === 0) return '<span class=\"tea-dt-br\">[]</span>';\n return (\n '<span class=\"tea-dt-br\">[</span>' +\n obj\n .map((v) => fmtJson(v, indent + 1))\n .join('<span class=\"tea-dt-br\">, </span>') +\n '<span class=\"tea-dt-br\">]</span>'\n );\n }\n if (typeof obj === \"object\") {\n const keys = Object.keys(obj as object);\n if (keys.length === 0) return '<span class=\"tea-dt-br\">{}</span>';\n const pad = \"&nbsp;&nbsp;\".repeat(indent + 1);\n const lines = keys.map((k, i) => {\n const v = (obj as Record<string, unknown>)[k];\n const comma =\n i < keys.length - 1 ? '<span class=\"tea-dt-br\">,</span>' : \"\";\n return `${pad}<span class=\"tea-dt-k\">${escapeHtml(k)}</span><span class=\"tea-dt-br\">:</span> ${fmtJson(v, indent + 1)}${comma}`;\n });\n return [\n '<span class=\"tea-dt-br\">{</span>',\n ...lines,\n `${\"&nbsp;&nbsp;\".repeat(indent)}<span class=\"tea-dt-br\">}</span>`,\n ].join(\"<br/>\");\n }\n return escapeHtml(String(obj));\n}\n\n/**\n * Props for `StateInspector`: the `state` to show, an optional `flashKey`, and\n * an optional `className`.\n */\nexport interface StateInspectorProps {\n /**\n * The machine state to display. Render-derived shape — pass whatever you\n * want surfaced to the inspector (often a hand-picked subset of the model).\n */\n state: unknown;\n /**\n * When this number changes, the inspector flashes. Pass `model.msgCount` or\n * any other monotonic counter you already have. Omit to disable flashing.\n */\n flashKey?: number;\n /**\n * Optional className appended to the container. Use to override layout.\n */\n className?: string;\n}\n\n/**\n * React component that renders a state value as formatted JSON, and flashes\n * when `flashKey` changes.\n */\nexport function StateInspector({\n state,\n flashKey,\n className,\n}: StateInspectorProps) {\n const boxRef = useRef<HTMLDivElement>(null);\n useEffect(() => {\n if (flashKey === undefined || !boxRef.current) return;\n boxRef.current.classList.remove(\"tea-dt-flash\");\n void boxRef.current.offsetWidth;\n boxRef.current.classList.add(\"tea-dt-flash\");\n }, [flashKey]);\n\n return (\n <div\n ref={boxRef}\n className={`tea-dt-state${className ? ` ${className}` : \"\"}`}\n >\n <div\n className=\"tea-dt-json\"\n // biome-ignore lint/security/noDangerouslySetInnerHtml: formatter output\n dangerouslySetInnerHTML={{ __html: fmtJson(state) }}\n />\n </div>\n );\n}\n","import { useCallback, useRef, useState } from \"react\";\nimport type { MsgLogEntry } from \"./msg-log\";\n\nfunction nowTs(): string {\n return new Date().toLocaleTimeString(\"en-GB\", { hour12: false }).slice(3);\n}\n\n/**\n * Wrap a `dispatch` so every Msg it sees lands in a bounded history buffer.\n *\n * `derive` lets you map a Msg to a richer entry (e.g. assign `kind: \"sub\"` to\n * subscription-triggered messages). Default: every msg becomes a `\"msg\"` row\n * tagged with `msg.type` (or `String(msg)` if it has no `type`). The substrate\n * uses `type` as the Msg discriminant — using `_tag` here would render every\n * Msg as `[object Object]` in the inspector.\n *\n * `max` caps the buffer — oldest entries fall off (LIFO, newest first).\n *\n * `now` is the timestamp source for the default `derive`. Defaults to\n * `nowTs` (real wall-clock). Tests inject a deterministic shim so\n * snapshots don't drift; production code never sets it.\n */\nexport function useMsgHistory<M>(\n dispatch: (msg: M) => void | Promise<void>,\n opts: {\n max?: number;\n derive?: (msg: M) => MsgLogEntry;\n now?: () => string;\n } = {},\n): readonly [readonly MsgLogEntry[], (msg: M) => void, () => void] {\n const max = opts.max ?? 60;\n const now = opts.now ?? nowTs;\n const derive =\n opts.derive ??\n ((msg: M): MsgLogEntry => {\n const tag =\n msg && typeof msg === \"object\" && \"type\" in msg\n ? String((msg as { type: unknown }).type)\n : String(msg);\n return { ts: now(), kind: \"msg\", text: tag };\n });\n\n const [history, setHistory] = useState<readonly MsgLogEntry[]>([]);\n // Stable ref to `dispatch` so the wrapper identity stays stable across\n // renders — important when this is passed to keyboard handlers and the like.\n const dispatchRef = useRef(dispatch);\n dispatchRef.current = dispatch;\n const deriveRef = useRef(derive);\n deriveRef.current = derive;\n\n const wrapped = useCallback(\n (msg: M) => {\n const entry = deriveRef.current(msg);\n setHistory((prev) => [entry, ...prev].slice(0, max));\n // Fire-and-forget — `dispatch` may return a Promise; we don't await it\n // here because callers historically treat dispatch as void.\n void dispatchRef.current(msg);\n },\n [max],\n );\n\n const clear = useCallback(() => setHistory([]), []);\n\n return [history, wrapped, clear] as const;\n}\n"]}
@@ -1,18 +1,18 @@
1
- import { S as Store, b as BootedRunHandle, E as EngineRun, c as RunHandle, M as Migrated, F as FencedStore, D as DeletableStore } from '../runtime-types-BKg2CGMx.js';
2
- import { P as PendingEffectsRecorder, b as EffectOwed, a as EffectConfirmed } from '../durable-effects-BmUrRA-h.js';
3
- export { D as DeliveryId, E as EffectLedgerEvent, O as OwedEffect, c as PendingEffectsLedger, d as applyEffectEvent, e as emptyLedger, f as foldLedger, i as isOwed, p as pendingEffectsLedger, s as survivingEffects } from '../durable-effects-BmUrRA-h.js';
1
+ import { S as Store, b as BootedRunHandle, E as EngineRun, d as RunHandle, M as Migrated, F as FencedStore, D as DeletableStore } from '../runtime-types-DEluQgGO.js';
2
+ import { P as PendingEffectsRecorder, b as EffectOwed, a as EffectConfirmed } from '../durable-effects-Ump5lSdO.js';
3
+ export { D as DeliveryId, E as EffectLedgerEvent, O as OwedEffect, c as PendingEffectsLedger, d as applyEffectEvent, e as emptyLedger, f as foldLedger, i as isOwed, p as pendingEffectsLedger, s as survivingEffects } from '../durable-effects-Ump5lSdO.js';
4
4
  import { RetryPolicy, Rng } from '../retry-backoff/index.js';
5
- import { C as Cmd, c as Sub, M as Machine, W as Wired } from '../core-Ce9ncpuv.js';
6
- import { A as AgentEvent, f as AgentTurn, e as AgentState, i as AgentMachineMsg, K as AgentStatus } from '../machine-CuojfZup.js';
5
+ import { C as Cmd, S as Sub, M as Machine, W as Wired } from '../core-CtvAyPpH.js';
6
+ import { A as AgentEvent, f as AgentTurn, e as AgentState, i as AgentMachineMsg, K as AgentStatus } from '../machine-Dtre2TmN.js';
7
7
  import '@standard-schema/spec';
8
- import '../index-Dy3379ve.js';
9
- import '../index-D8sYVzCI.js';
10
- import '../index-e36uEyl4.js';
11
- import '../types-SzNSHKlV.js';
12
- import '../index-DWdg7R1l.js';
13
- import '../index-2kNxy6az.js';
8
+ import '../index-CZZ3HI-Z.js';
9
+ import '../index-Bk2hBUdK.js';
10
+ import '../index-CVU7SK3a.js';
11
+ import '../types-CXNzlbAg.js';
12
+ import '../index-D3NY3VCN.js';
13
+ import '../index-CKtEKGyp.js';
14
14
  import '../protocol-ClRZBhHQ.js';
15
- import '../index-Ce5GYAuI.js';
15
+ import '../index-CrcoVfd_.js';
16
16
 
17
17
  /**
18
18
  * @demlik/tea/do — `stepHost`, the HTTP-PULL control carrier (#92).
package/dist/do/index.js CHANGED
@@ -1,20 +1,20 @@
1
- import { status, agentBootMsg, AGENT_EVENT_TYPES, agentEvents } from '../chunk-PCJA2HTZ.js';
2
- import { createIntake } from '../chunk-JYNYG5SF.js';
1
+ import { status, agentBootMsg, AGENT_EVENT_TYPES, agentEvents } from '../chunk-2774I242.js';
2
+ import { createIntake } from '../chunk-NGYFBD5G.js';
3
3
  export { applyEffectEvent, emptyLedger, foldLedger, isOwed, pendingEffectsLedger, survivingEffects } from '../chunk-6IQPODUF.js';
4
- import '../chunk-XVIKSRCK.js';
5
- import '../chunk-YIMOFXST.js';
4
+ import '../chunk-EA47MI5Q.js';
5
+ import '../chunk-2R62Q5UK.js';
6
6
  import '../chunk-QNGYQMZB.js';
7
- import '../chunk-WTSOW2MD.js';
8
- import '../chunk-C3G2QFEZ.js';
7
+ import '../chunk-72CN3VPY.js';
8
+ import '../chunk-TAKPC6SD.js';
9
9
  import { defaultRetryPolicy, initRetry, recordFailure, shouldRetry, nextDelayMs } from '../chunk-VBDU4JL6.js';
10
10
  import '../chunk-PR6TB3BL.js';
11
11
  import '../chunk-4LPY67E4.js';
12
12
  import '../chunk-TXN2KFHF.js';
13
- import '../chunk-H2ELKHI6.js';
14
- import '../chunk-AHW2CLPT.js';
15
- import '../chunk-JVE2LBFJ.js';
16
- import '../chunk-FNGZMVIT.js';
17
- import { StoreConflictError, replay } from '../chunk-AIIXV4XB.js';
13
+ import '../chunk-JAKM53JF.js';
14
+ import '../chunk-UHAQ4PI6.js';
15
+ import '../chunk-A73IJ27X.js';
16
+ import '../chunk-DVNXEB7V.js';
17
+ import { StoreConflictError, replay } from '../chunk-RKVUVALV.js';
18
18
 
19
19
  // src/do/durable-timer.ts
20
20
  function durableTimer(config) {
@@ -1,4 +1,4 @@
1
- import { C as CtxArg } from './runtime-types-BKg2CGMx.js';
1
+ import { C as CtxArg } from './runtime-types-DEluQgGO.js';
2
2
 
3
3
  /**
4
4
  * The default round bound when `opts.maxRounds` is omitted: **100**.
@@ -1,4 +1,4 @@
1
- import { C as Cmd } from './core-Ce9ncpuv.js';
1
+ import { C as Cmd } from './core-CtvAyPpH.js';
2
2
 
3
3
  /**
4
4
  * @demlik/tea/do — the durable pending-effects ledger (substrate primitive #1).