@demlik/tea 0.14.0 → 0.15.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 (77) hide show
  1. package/dist/agent/index.d.ts +14 -13
  2. package/dist/agent/index.js +6 -6
  3. package/dist/{chunk-F2US5BW6.js → chunk-22POWGFA.js} +17 -11
  4. package/dist/chunk-22POWGFA.js.map +1 -0
  5. package/dist/{chunk-HYDWG35Q.js → chunk-3B5X7SBB.js} +4 -4
  6. package/dist/{chunk-HYDWG35Q.js.map → chunk-3B5X7SBB.js.map} +1 -1
  7. package/dist/{chunk-RQULHGYH.js → chunk-66PY5WYF.js} +15 -3
  8. package/dist/{chunk-RQULHGYH.js.map → chunk-66PY5WYF.js.map} +1 -1
  9. package/dist/{chunk-AQ6ZIMEA.js → chunk-AYS5N6WY.js} +121 -37
  10. package/dist/chunk-AYS5N6WY.js.map +1 -0
  11. package/dist/{chunk-HUKZQX6U.js → chunk-L3TND7LA.js} +3 -3
  12. package/dist/{chunk-HUKZQX6U.js.map → chunk-L3TND7LA.js.map} +1 -1
  13. package/dist/{chunk-I5MQMJDW.js → chunk-Q5CQTBFA.js} +3 -3
  14. package/dist/{chunk-I5MQMJDW.js.map → chunk-Q5CQTBFA.js.map} +1 -1
  15. package/dist/{chunk-F7FMAWLA.js → chunk-QPEVCJ5Q.js} +3 -3
  16. package/dist/{chunk-F7FMAWLA.js.map → chunk-QPEVCJ5Q.js.map} +1 -1
  17. package/dist/{chunk-Z2L3LSNV.js → chunk-TCLBCERH.js} +17 -7
  18. package/dist/chunk-TCLBCERH.js.map +1 -0
  19. package/dist/{chunk-BLJ2JQSH.js → chunk-V46HSVCK.js} +3 -3
  20. package/dist/{chunk-BLJ2JQSH.js.map → chunk-V46HSVCK.js.map} +1 -1
  21. package/dist/{chunk-LYLTKJWM.js → chunk-VTQI2NHP.js} +3 -3
  22. package/dist/{chunk-LYLTKJWM.js.map → chunk-VTQI2NHP.js.map} +1 -1
  23. package/dist/{core-CTzMJ82M.d.ts → core-DnzqWy6u.d.ts} +1 -1
  24. package/dist/do/index.d.ts +13 -12
  25. package/dist/do/index.js +7 -7
  26. package/dist/{durable-effects-B0-qGQDy.d.ts → durable-effects-CWzA-o2B.d.ts} +1 -1
  27. package/dist/extension/index.d.ts +3 -3
  28. package/dist/extension/index.js +1 -1
  29. package/dist/flow/index.d.ts +15 -26
  30. package/dist/flow/index.js +8 -8
  31. package/dist/idempotency/index.d.ts +3 -3
  32. package/dist/idempotency/index.js +2 -2
  33. package/dist/{index-4vZzljCD.d.ts → index-C2DwkjlP.d.ts} +4 -4
  34. package/dist/{index-B5BZ-_cT.d.ts → index-CA_7I5g9.d.ts} +277 -87
  35. package/dist/{index-DJWIER_3.d.ts → index-CSyMYDAB.d.ts} +1 -1
  36. package/dist/{index-6A7dB8f6.d.ts → index-CuNO9m8i.d.ts} +2 -2
  37. package/dist/{index-TvRb1KVf.d.ts → index-DrIRb_Ch.d.ts} +1 -1
  38. package/dist/{index-q0hXFeZ0.d.ts → index-HSYgG2Yt.d.ts} +50 -15
  39. package/dist/{index-NjrT3fL2.d.ts → index-KXqTRJyb.d.ts} +4 -4
  40. package/dist/{index-DMCeMPMJ.d.ts → index-ZCMhnVKN.d.ts} +1 -1
  41. package/dist/index.d.ts +66 -6
  42. package/dist/index.js +1 -1
  43. package/dist/jev/index.d.ts +34 -22
  44. package/dist/jev/index.js +178 -126
  45. package/dist/jev/index.js.map +1 -1
  46. package/dist/{machine-CdIcN2Xm.d.ts → machine-DGlPWCWI.d.ts} +34 -26
  47. package/dist/machine-viz/index.d.ts +1 -1
  48. package/dist/machine-viz/index.js +1 -1
  49. package/dist/mem/index.d.ts +2 -2
  50. package/dist/mem/index.js +1 -1
  51. package/dist/node/index.d.ts +2 -2
  52. package/dist/node/index.js +1 -1
  53. package/dist/paginate/index.d.ts +6 -17
  54. package/dist/paginate/index.js +4 -4
  55. package/dist/parity/index.d.ts +3 -3
  56. package/dist/parity/index.js +2 -2
  57. package/dist/pbt/index.d.ts +1 -1
  58. package/dist/pbt/index.js +1 -1
  59. package/dist/persistence/index.d.ts +5 -5
  60. package/dist/persistence/index.js +3 -3
  61. package/dist/protocol-D8VbH-VH.d.ts +54 -0
  62. package/dist/react/index.d.ts +2 -2
  63. package/dist/react/index.js +1 -1
  64. package/dist/resilience/index.d.ts +8 -7
  65. package/dist/resilience/index.js +5 -5
  66. package/dist/{runtime-types-LWDoi943.d.ts → runtime-types-CMF13BBh.d.ts} +1 -1
  67. package/dist/testing/index.d.ts +147 -3
  68. package/dist/testing/index.js +95 -2
  69. package/dist/testing/index.js.map +1 -1
  70. package/dist/timing/index.d.ts +4 -4
  71. package/dist/timing/index.js +3 -3
  72. package/dist/{types-DP3f5NIl.d.ts → types-BseNPIhr.d.ts} +1 -1
  73. package/dist/work-queue/index.d.ts +4 -4
  74. package/package.json +1 -1
  75. package/dist/chunk-AQ6ZIMEA.js.map +0 -1
  76. package/dist/chunk-F2US5BW6.js.map +0 -1
  77. package/dist/chunk-Z2L3LSNV.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,11 +1,71 @@
1
- import { B as BootingRuntime, a as ScopedCtxArg, S as Store, O as OnError, b as Supervision, R as Runtime } from './runtime-types-LWDoi943.js';
2
- export { c as Branded, C as CtxArg, D as DepToken, d as DepsOf, e as DispatchDiscardedError, f as DispatchSettle, g as DisposeTimeoutNotice, h as DriveFailedError, i as DriveStalledError, j as FencedRead, F as FencedStore, k as FoldRefusal, I as IdentityDropNotice, M as MachineTypes, l as OnReleaseError, P as PortNameCollisionError, m as ProvideFailedError, n as Provided, o as ProvidedCtx, p as Provider, q as ProviderCycleError, Q as QuiescenceTimeoutError, r as RuntimeDiscardNotice, s as RuntimeDiscardedError, t as RuntimeErrorContext, u as RuntimeErrorPhase, v as RuntimeRef, w as Schema, x as Scope, y as StoreConflictError, z as SubIdCollisionError, A as SupervisionStrategy, U as UnknownProviderError, _ as __resetPortRegistry, E as absurd, G as asReducer, H as defineMachine, J as definePort, K as dep, L as isFencedStore, N as isProvided, T as layer, V as noop, W as provide, X as replay, Y as schemaMigrate, Z as settle, $ as tryApplyCell, a0 as tryFoldMsgs, a1 as tryInterpret, a2 as value, a3 as wrapDetached } from './runtime-types-LWDoi943.js';
3
- import { C as Cmd, S as Sub, M as Machine, R as RequiredCtx, P as Port, D as Dispose, o as DepKeyedSub, c as SubId } from './core-CTzMJ82M.js';
4
- export { A as AnyCmdDef, b as CmdDef, p as CmdInput, a as CmdOf, i as CmdValue, E as ErrOf, q as ErrorsOf, r as ExhaustiveTransitions, s as Identity, I as Interpret, h as InterpretDetached, t as MachineShape, l as MalformedResult, N as NoCellError, k as NoCtx, O as OkOf, g as PortEmitter, d as Reducer, m as Requirements, f as RequirementsOf, e as Settled, u as SettledErr, v as SettledOk, w as Subscribe, x as SyncReturn, j as Tagged, n as TaggedError, T as Transitions, U as UpdateForm, y as acceptedTypes, z as acceptsOf, B as applyCell, F as applyCellChecked, G as describeMachine, H as detectUpdateForm, J as foldMsgs, K as foldUpdates, L as formOf, Q as msgKeysOf, V as structuralHash, W as subId } from './core-CTzMJ82M.js';
5
- import { S as SubscribeHandler } from './types-DP3f5NIl.js';
1
+ import { B as BootingRuntime, a as ScopedCtxArg, S as Store, O as OnError, b as Supervision, R as Runtime } from './runtime-types-CMF13BBh.js';
2
+ export { c as Branded, C as CtxArg, D as DepToken, d as DepsOf, e as DispatchDiscardedError, f as DispatchSettle, g as DisposeTimeoutNotice, h as DriveFailedError, i as DriveStalledError, j as FencedRead, F as FencedStore, k as FoldRefusal, I as IdentityDropNotice, M as MachineTypes, l as OnReleaseError, P as PortNameCollisionError, m as ProvideFailedError, n as Provided, o as ProvidedCtx, p as Provider, q as ProviderCycleError, Q as QuiescenceTimeoutError, r as RuntimeDiscardNotice, s as RuntimeDiscardedError, t as RuntimeErrorContext, u as RuntimeErrorPhase, v as RuntimeRef, w as Schema, x as Scope, y as StoreConflictError, z as SubIdCollisionError, A as SupervisionStrategy, U as UnknownProviderError, _ as __resetPortRegistry, E as absurd, G as asReducer, H as defineMachine, J as definePort, K as dep, L as isFencedStore, N as isProvided, T as layer, V as noop, W as provide, X as replay, Y as schemaMigrate, Z as settle, $ as tryApplyCell, a0 as tryFoldMsgs, a1 as tryInterpret, a2 as value, a3 as wrapDetached } from './runtime-types-CMF13BBh.js';
3
+ import { C as Cmd, S as Sub, M as Machine, R as RequiredCtx, P as Port, D as Dispose, o as DepKeyedSub, c as SubId } from './core-DnzqWy6u.js';
4
+ export { A as AnyCmdDef, b as CmdDef, p as CmdInput, a as CmdOf, l as CmdValue, E as ErrOf, q as ErrorsOf, r as ExhaustiveTransitions, s as Identity, I as Interpret, h as InterpretDetached, t as MachineShape, k as MalformedResult, N as NoCellError, i as NoCtx, O as OkOf, g as PortEmitter, d as Reducer, m as Requirements, f as RequirementsOf, e as Settled, u as SettledErr, v as SettledOk, w as Subscribe, x as SyncReturn, j as Tagged, n as TaggedError, T as Transitions, U as UpdateForm, y as acceptedTypes, z as acceptsOf, B as applyCell, F as applyCellChecked, G as describeMachine, H as detectUpdateForm, J as foldMsgs, K as foldUpdates, L as formOf, Q as msgKeysOf, V as structuralHash, W as subId } from './core-DnzqWy6u.js';
5
+ import { S as SubscribeHandler } from './types-BseNPIhr.js';
6
6
  import 'better-result';
7
7
  import 'zod';
8
8
 
9
+ /**
10
+ * @packageDocumentation
11
+ * The composition seam — the layer between a battery and a door.
12
+ *
13
+ * A battery is pure state plus verbs over that state. A door holds several
14
+ * batteries side by side in one Model. Everything between those two facts was,
15
+ * until now, hand-written at every consumer: the one-key record rebuild that
16
+ * threads a verb's `[slice, cmds]` result back into the host state, and the
17
+ * statement order that decides which slice wins a derived read.
18
+ *
19
+ * Two helpers cover it, and neither is an optics kit. {@link liftSlice} is the
20
+ * record rebuild with the key checked by the type system; {@link readInOrder}
21
+ * turns a read's precedence from statement order into a value you can name,
22
+ * export and assert on. ADR 0001 (no off-the-shelf resilience) and ADR 0014
23
+ * (Effect's types, never its runtime values) between them settle why this is
24
+ * forty lines here rather than a dependency.
25
+ *
26
+ * Both are pure: no clock, no RNG, no storage, nothing captured. A `liftSlice`
27
+ * result is a fresh record and a Cmd array, so ADR 0014's journal/hash promise
28
+ * over a reducer's return value is untouched.
29
+ */
30
+ /**
31
+ * Lift a battery verb's result into the host state that carries its slice.
32
+ *
33
+ * `liftSlice("resilience", state, knob.attempt(state.resilience, …))` is the
34
+ * `{ ...state, resilience: slice }` every consumer writes by hand, with the key
35
+ * checked: `key` must be a key of `S`, and the slice the verb returned must be
36
+ * assignable to the type that key carries — so naming the wrong field, or
37
+ * threading one battery's slice into another's key, is a compile error rather
38
+ * than a state shape nothing reads correctly.
39
+ *
40
+ * PURE — a fresh record and the verb's own Cmds, unchanged.
41
+ */
42
+ declare function liftSlice<S, K extends keyof S, C>(key: K, state: S, [slice, cmds]: readonly [S[K], readonly C[]]): readonly [S, readonly C[]];
43
+ /**
44
+ * One step of a composed read: the slice it consults, under the name that slice
45
+ * goes by. `read` returns `undefined` for "this slice has nothing to say",
46
+ * which is what hands the read on to the next step.
47
+ */
48
+ interface ReadStep<In, Out> {
49
+ /** The slice this step consults — `"cache"`, `"failed"`, `"inFlight"`. */
50
+ readonly name: string;
51
+ /** What this slice says about `input`, or `undefined` to defer. */
52
+ readonly read: (input: In) => Out | undefined;
53
+ }
54
+ /**
55
+ * Run a composed read through `order` and return the first answer any step
56
+ * gives, or `absent` when every one defers.
57
+ *
58
+ * The point is that `order` is a VALUE. A derived read over three battery
59
+ * slices otherwise states its precedence as the order of three `if` statements,
60
+ * where it is invisible to the type system, unnameable in a test and one
61
+ * innocent-looking reshuffle away from being wrong — which is exactly the
62
+ * defect that escaped `classify-batch`'s per-battery test suites. Written as
63
+ * data, the precedence can be exported, printed and asserted on directly.
64
+ *
65
+ * PURE — it evaluates `read` in order and stores nothing.
66
+ */
67
+ declare function readInOrder<In, Out>(input: In, order: readonly ReadStep<In, Out>[], absent: Out): Out;
68
+
9
69
  interface HistoryTracker<S, M extends {
10
70
  type: string;
11
71
  }> {
@@ -817,4 +877,4 @@ interface TransportBattery<TKey, Outbound, M, Ctx> {
817
877
  */
818
878
  declare function fromTransport<TKey, Inbound, Outbound, M, Ctx>(opts: FromTransportOpts<TKey, Inbound, Outbound, M, Ctx>): TransportBattery<TKey, Outbound, M, Ctx>;
819
879
 
820
- export { type Ack, type AckPartition, BootingRuntime, type CancelTimer, Cmd, type CombinedManagedResources, type DefineManagedResourceOpts, DepKeyedSub, Dispose, type DriveToDoneOptions, type EventSourceFactoryOpts, type FromTransportOpts, type GatedManagedResource, type HistoryTracker, type ListenerTarget, Machine, type ManagedResourceBattery, type ManagedResourceSub, NO_ACK, OnError, Port, type ReconnectingWebSocketFactoryOpts, RequiredCtx, Runtime, ScopedCtxArg, type Seq, type SeqTagged, Store, Sub, SubId, SubscribeHandler, Supervision, type Transport, type TransportBattery, type TransportFactory, type TransportSub, type WebSocketFactoryOpts, type WebSocketSubData, ack, combineManagedResources, defineListener, defineManagedResource, driveToDone, fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromReconnectingWebSocket, fromTimeout, fromTransport, fromWebSocket, historyTracker, initAck, nextSeq, partitionByAck, reconcile, run, tagSeq };
880
+ export { type Ack, type AckPartition, BootingRuntime, type CancelTimer, Cmd, type CombinedManagedResources, type DefineManagedResourceOpts, DepKeyedSub, Dispose, type DriveToDoneOptions, type EventSourceFactoryOpts, type FromTransportOpts, type GatedManagedResource, type HistoryTracker, type ListenerTarget, Machine, type ManagedResourceBattery, type ManagedResourceSub, NO_ACK, OnError, Port, type ReadStep, type ReconnectingWebSocketFactoryOpts, RequiredCtx, Runtime, ScopedCtxArg, type Seq, type SeqTagged, Store, Sub, SubId, SubscribeHandler, Supervision, type Transport, type TransportBattery, type TransportFactory, type TransportSub, type WebSocketFactoryOpts, type WebSocketSubData, ack, combineManagedResources, defineListener, defineManagedResource, driveToDone, fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromReconnectingWebSocket, fromTimeout, fromTransport, fromWebSocket, historyTracker, initAck, liftSlice, nextSeq, partitionByAck, readInOrder, reconcile, run, tagSeq };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { Cmd, DispatchDiscardedError, DisposeTimeoutNotice, DriveFailedError, DriveStalledError, IdentityDropNotice, NO_ACK, NoCellError, PortNameCollisionError, ProvideFailedError, ProviderCycleError, QuiescenceTimeoutError, RuntimeDiscardNotice, RuntimeDiscardedError, StoreConflictError, SubIdCollisionError, UnknownProviderError, __resetPortRegistry, absurd, acceptedTypes, acceptsOf, ack, applyCell, applyCellChecked, asReducer, combineManagedResources, defineListener, defineMachine, defineManagedResource, definePort, dep, describeMachine, detectUpdateForm, driveToDone, foldMsgs, foldUpdates, formOf, fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromReconnectingWebSocket, fromTimeout, fromTransport, fromWebSocket, historyTracker, initAck, isFencedStore, isProvided, layer, msgKeysOf, nextSeq, noop, partitionByAck, provide, reconcile, replay, run, schemaMigrate, settle, structuralHash, subId, tagSeq, tryApplyCell, tryFoldMsgs, tryInterpret, value, wrapDetached } from './chunk-RQULHGYH.js';
1
+ export { Cmd, DispatchDiscardedError, DisposeTimeoutNotice, DriveFailedError, DriveStalledError, IdentityDropNotice, NO_ACK, NoCellError, PortNameCollisionError, ProvideFailedError, ProviderCycleError, QuiescenceTimeoutError, RuntimeDiscardNotice, RuntimeDiscardedError, StoreConflictError, SubIdCollisionError, UnknownProviderError, __resetPortRegistry, absurd, acceptedTypes, acceptsOf, ack, applyCell, applyCellChecked, asReducer, combineManagedResources, defineListener, defineMachine, defineManagedResource, definePort, dep, describeMachine, detectUpdateForm, driveToDone, foldMsgs, foldUpdates, formOf, fromBroadcastChannel, fromEventSource, fromEventTarget, fromInterval, fromPort, fromReconnectingWebSocket, fromTimeout, fromTransport, fromWebSocket, historyTracker, initAck, isFencedStore, isProvided, layer, liftSlice, msgKeysOf, nextSeq, noop, partitionByAck, provide, readInOrder, reconcile, replay, run, schemaMigrate, settle, structuralHash, subId, tagSeq, tryApplyCell, tryFoldMsgs, tryInterpret, value, wrapDetached } from './chunk-66PY5WYF.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1,14 +1,15 @@
1
- import { b as CmdDef, C as Cmd } from '../core-CTzMJ82M.js';
1
+ import { b as CmdDef, C as Cmd } from '../core-DnzqWy6u.js';
2
2
  import { RetryPolicy } from '../retry-backoff/index.js';
3
- import { R as RunCmd, F as FailMsg, S as SucceedMsg, a as ResilientState } from '../index-B5BZ-_cT.js';
4
- import { a as DeadlineSub, D as DeadlineExceeded, T as TtlCache, C as CacheEvictionSub, c as CacheEvictMsg } from '../index-q0hXFeZ0.js';
5
- export { b as deadlineSub, s as subscribeDeadline } from '../index-q0hXFeZ0.js';
6
- import { S as SubscribeHandler } from '../types-DP3f5NIl.js';
7
- import { B as BatchWindow, a as BatchWindowSub } from '../index-4vZzljCD.js';
8
- import { F as FanOutState } from '../index-6A7dB8f6.js';
3
+ import { R as RunCmd, F as FailMsg, S as SucceedMsg, a as ResilientState } from '../index-CA_7I5g9.js';
4
+ export { m as mountResilientCall } from '../index-CA_7I5g9.js';
5
+ import { a as DeadlineSub, D as DeadlineExceeded, T as TtlCache, C as CacheEvictionSub, c as CacheEvictMsg } from '../index-HSYgG2Yt.js';
6
+ export { b as deadlineSub, s as subscribeDeadline } from '../index-HSYgG2Yt.js';
7
+ import { S as SubscribeHandler } from '../types-BseNPIhr.js';
8
+ import { B as BatchWindow, a as BatchWindowSub, b as BatchWindowExpired } from '../index-C2DwkjlP.js';
9
+ import { F as FanOutState } from '../index-CuNO9m8i.js';
9
10
  import 'zod';
10
- import '../index-DJWIER_3.js';
11
- import '../runtime-types-LWDoi943.js';
11
+ import '../index-CSyMYDAB.js';
12
+ import '../runtime-types-CMF13BBh.js';
12
13
  import 'better-result';
13
14
 
14
15
  /**
@@ -59,12 +60,19 @@ import 'better-result';
59
60
  * network actually produced. Every `unknown` reaches a `JevErr`; nothing
60
61
  * reaches a `throw`.
61
62
  *
62
- * Both halves of a choice question's claim are checked, because both are cast
63
- * away at the tail of `parseAnswers`: `choice` must be one of the criteria
64
- * keys, and `probabilities` must be keyed by EXACTLY those keys — none
65
- * missing, none extra. A partial distribution typed `Record<K, number>` is the
66
- * representable-invalid state this module exists to refuse, and it arrives
67
- * through this gate or not at all.
63
+ * The check itself is a `zod` schema DERIVED from the questions map, so the
64
+ * typed value is what `safeParse` returns rather than something asserted after
65
+ * a hand-walk. Both halves of a choice question's claim are structural in that
66
+ * schema: `choice` is a `z.enum` over the criteria keys, and `probabilities`
67
+ * is a strict `z.object` whose shape IS those keys — so a distribution missing
68
+ * one or carrying an extra fails the schema rather than a separate arm a later
69
+ * reader has to remember. A partial distribution typed `Record<K, number>` is
70
+ * the representable-invalid state this module exists to refuse, and it arrives
71
+ * through this gate or not at all. The envelope is checked by the same schema:
72
+ * `model` is a string and `usage` carries two finite numbers.
73
+ *
74
+ * `safeParse`, never `parse`: a zod failure is turned into a `JevErr` value by
75
+ * mapping its first issue's path onto the arm that names it.
68
76
  *
69
77
  * ## Why status classification lives here and not in `ask`
70
78
  *
@@ -280,12 +288,11 @@ type JevParse<Q extends JevQuestionMap> = {
280
288
  * Turn an `unknown` response body into the typed answers for `questions`, or
281
289
  * into one `JevErr`. Pure, total, and never throwing on any input.
282
290
  *
283
- * The walk is question-driven, not body-driven: every id the request asked
284
- * about must be answered, and each answer is checked against ITS question's
285
- * type and — for a choice — against that question's own criteria keys, both as
286
- * the `choice` picked and as the exact key set of `probabilities`. An
287
- * answer under an id nobody asked about is ignored rather than refused; the
288
- * questions are the contract, and a wider response still satisfies it.
291
+ * The schema is question-driven: every id the request asked about must be
292
+ * answered, each answer is checked against ITS question's type and — for a
293
+ * choice — against that question's own criteria keys, both as the `choice`
294
+ * picked and as the exact key set of `probabilities`. An answer under an id
295
+ * nobody asked about is dropped rather than refused.
289
296
  */
290
297
  declare const parseAnswers: <Q extends JevQuestionMap>(questions: Q, body: unknown) => JevParse<Q>;
291
298
  /**
@@ -468,6 +475,7 @@ type JevTimerMsg = DeadlineExceeded;
468
475
  * enriched settle Msg.
469
476
  */
470
477
  declare function createJevAsk<Q extends JevQuestionMap>(config: JevAskConfig<Q>, rng?: () => number): {
478
+ name: "resilient";
471
479
  init: () => ResilientState<JevRequest<Q>, JevOk<Q>>;
472
480
  attempt: (s: ResilientState<JevRequest<Q>, JevOk<Q>>, key: string, content: JevState, at: number) => readonly [ResilientState<JevRequest<Q>, JevOk<Q>>, readonly JevAskCmd<Q>[]];
473
481
  succeed: (s: ResilientState<JevRequest<Q>, JevOk<Q>>, key: string, msg: JevSucceedMsg<Q>) => readonly [ResilientState<JevRequest<Q>, JevOk<Q>>, readonly JevAskCmd<Q>[]];
@@ -499,6 +507,10 @@ type JevSub = DeadlineSub;
499
507
  * Lift a knob result `[slice, cmds]` into a host `[State, cmds]` where the slice
500
508
  * lives at `state.resilience` — resilient-call's convenience, re-typed for this
501
509
  * door's slice so a consumer wires one import. Pure.
510
+ *
511
+ * The record rebuild is `liftSlice` from the root door (#231), the same helper
512
+ * `liftResilience` is expressed over — this stays as the named, pre-keyed
513
+ * convenience for this door, unchanged in name, signature and subpath.
502
514
  */
503
515
  declare function liftJevAsk<S extends {
504
516
  resilience: ResilientState<JevRequest<Q>, JevOk<Q>>;
@@ -621,7 +633,7 @@ declare function createClassifyBatch<I, C extends string>(config: ClassifyBatchC
621
633
  answerFor: (state: ClassifyBatchState<I, C>, key: string, at: number) => KeyAnswer<C>;
622
634
  subs: (state: ClassifyBatchState<I, C>, id?: string) => readonly (BatchWindowSub | CacheEvictionSub)[];
623
635
  subscribers: () => {
624
- deadline: SubscribeHandler<DeadlineSub, DeadlineExceeded, unknown>;
636
+ deadline: SubscribeHandler<BatchWindowSub, BatchWindowExpired, unknown>;
625
637
  cache: SubscribeHandler<CacheEvictionSub, CacheEvictMsg, unknown>;
626
638
  };
627
639
  handlers: () => {
package/dist/jev/index.js CHANGED
@@ -1,15 +1,16 @@
1
- import { createBatchWindow, subscribeBatchWindow } from '../chunk-F7FMAWLA.js';
1
+ import { createBatchWindow, subscribeBatchWindow } from '../chunk-QPEVCJ5Q.js';
2
2
  import '../chunk-LFZUK6J2.js';
3
3
  import { createFanOut } from '../chunk-MYXFNWAJ.js';
4
4
  import '../chunk-TXN2KFHF.js';
5
- import { runCmdDef, createResilientCall, liftResilience, MsgType } from '../chunk-AQ6ZIMEA.js';
5
+ import { runCmdDef, createResilientCall, MsgType } from '../chunk-AYS5N6WY.js';
6
+ export { mountResilientCall } from '../chunk-AYS5N6WY.js';
6
7
  import '../chunk-VBDU4JL6.js';
7
- import { initCache, has, set, evictExpired, get, cacheEvictionSub, cacheEvictionSubscribe } from '../chunk-F2US5BW6.js';
8
- export { deadlineSub, subscribeDeadline } from '../chunk-F2US5BW6.js';
8
+ import { initCache, has, set, evictExpired, cacheEvictionSub, cacheEvictionSubscribe, get } from '../chunk-22POWGFA.js';
9
+ export { deadlineSub, subscribeDeadline } from '../chunk-22POWGFA.js';
9
10
  import { describeError } from '../chunk-G5E74IJB.js';
10
- import '../chunk-RQULHGYH.js';
11
+ import { liftSlice, readInOrder } from '../chunk-66PY5WYF.js';
12
+ import { z } from 'zod';
11
13
 
12
- // src/internal/jev/protocol/index.ts
13
14
  var jevQuestions = (questions) => questions;
14
15
  var JEV_ENDPOINT = "https://api.typesafe.ai/v1/systemone";
15
16
  var JEV_ERR_TAG_WITNESS = {
@@ -30,114 +31,127 @@ function isJevErr(value) {
30
31
  return typeof tag === "string" && tags.has(tag);
31
32
  }
32
33
  var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
33
- var isNum = (v) => typeof v === "number" && Number.isFinite(v);
34
- var isNumMap = (v) => isObj(v) && Object.values(v).every(isNum);
35
- var isStrMap = (v) => isObj(v) && Object.values(v).every((x) => typeof x === "string");
34
+ var at = (value, key) => isObj(value) ? value[key] : void 0;
36
35
  var err = (error) => ({
37
36
  ok: false,
38
37
  error
39
38
  });
40
- var checkAnswer = (id, question, answer) => {
41
- if (!isObj(answer)) {
42
- return { _tag: "malformed_answer", id, reason: "answer is not an object" };
43
- }
44
- const received = answer["type"];
45
- if (typeof received !== "string") {
46
- return { _tag: "malformed_answer", id, reason: "answer has no `type`" };
47
- }
48
- if (received !== question.type) {
49
- return {
50
- _tag: "answer_type_mismatch",
51
- id,
52
- expected: question.type,
53
- received
54
- };
55
- }
56
- if (question.type === "noul") {
57
- return isNum(answer["noul"]) ? void 0 : { _tag: "malformed_answer", id, reason: "`noul` is not a number" };
39
+ var finite = z.number().finite();
40
+ var answerSchema = (question) => {
41
+ switch (question.type) {
42
+ case "noul":
43
+ return z.object({ type: z.literal("noul"), noul: finite });
44
+ case "score":
45
+ return z.object({
46
+ type: z.literal("score"),
47
+ confidence: finite,
48
+ score: finite,
49
+ legend: z.record(z.string(), z.string()),
50
+ probabilities: z.record(z.string(), finite)
51
+ });
52
+ case "choice": {
53
+ const options = Object.keys(question.criteria);
54
+ return z.object({
55
+ type: z.literal("choice"),
56
+ choice: z.enum(options),
57
+ confidence: finite,
58
+ // `JevChoiceAnswer<K>` types `probabilities` as TOTAL over the criteria
59
+ // keys. A strict object whose shape is those keys IS that claim: a
60
+ // missing key fails the shape, an extra one is unrecognized.
61
+ probabilities: z.strictObject(
62
+ Object.fromEntries(options.map((k) => [k, finite]))
63
+ )
64
+ });
65
+ }
58
66
  }
59
- if (!isNum(answer["confidence"])) {
60
- return {
61
- _tag: "malformed_answer",
67
+ };
68
+ var jevAnswersSchema = (questions) => z.object(
69
+ Object.fromEntries(
70
+ Object.entries(questions).map(([id, question]) => [
62
71
  id,
63
- reason: "`confidence` is not a number"
64
- };
72
+ answerSchema(question)
73
+ ])
74
+ )
75
+ );
76
+ var responseSchema = (questions) => z.object({
77
+ model: z.string(),
78
+ usage: z.object({ input_tokens: finite, output_tokens: finite }),
79
+ answers: jevAnswersSchema(questions)
80
+ });
81
+ var ANSWER_FIELD_REASON = {
82
+ confidence: "`confidence` is not a number",
83
+ score: "`score` is not a number",
84
+ legend: "`legend` is not a map of strings",
85
+ probabilities: "`probabilities` is not a map of numbers",
86
+ choice: "`choice` is not a string",
87
+ noul: "`noul` is not a number"
88
+ };
89
+ var toJevErr = (questions, body, issue) => {
90
+ const [head, id, field] = issue?.path ?? [];
91
+ if (head === "model") {
92
+ return { _tag: "malformed_body", reason: "`model` is not a string" };
65
93
  }
66
- const probabilities = answer["probabilities"];
67
- if (!isNumMap(probabilities)) {
94
+ if (head === "usage") {
68
95
  return {
69
- _tag: "malformed_answer",
70
- id,
71
- reason: "`probabilities` is not a map of numbers"
72
- };
73
- }
74
- if (question.type === "score") {
75
- if (!isNum(answer["score"])) {
76
- return {
77
- _tag: "malformed_answer",
78
- id,
79
- reason: "`score` is not a number"
80
- };
81
- }
82
- return isStrMap(answer["legend"]) ? void 0 : {
83
- _tag: "malformed_answer",
84
- id,
85
- reason: "`legend` is not a map of strings"
96
+ _tag: "malformed_body",
97
+ reason: "`usage` is not `{ input_tokens, output_tokens }`"
86
98
  };
87
99
  }
88
- const choice = answer["choice"];
89
- if (typeof choice !== "string") {
90
- return { _tag: "malformed_answer", id, reason: "`choice` is not a string" };
100
+ if (head !== "answers") {
101
+ return { _tag: "malformed_body", reason: "body is not an object" };
91
102
  }
92
- const options = Object.keys(question.criteria);
93
- if (!options.includes(choice)) {
94
- return { _tag: "off_criteria_choice", id, choice, options };
103
+ const answers = at(body, "answers");
104
+ if (!isObj(answers) || typeof id !== "string") {
105
+ return { _tag: "malformed_body", reason: "`answers` is not an object" };
95
106
  }
96
- const missing = options.filter((k) => !Object.hasOwn(probabilities, k));
97
- const extra = Object.keys(probabilities).filter((k) => !options.includes(k));
98
- return missing.length === 0 && extra.length === 0 ? void 0 : { _tag: "off_criteria_probabilities", id, missing, extra, options };
99
- };
100
- var parseAnswers = (questions, body) => {
101
- if (!isObj(body))
102
- return err({ _tag: "malformed_body", reason: "body is not an object" });
103
- const model = body["model"];
104
- if (typeof model !== "string") {
105
- return err({ _tag: "malformed_body", reason: "`model` is not a string" });
106
- }
107
- const usage = body["usage"];
108
- if (!isObj(usage) || !isNum(usage["input_tokens"]) || !isNum(usage["output_tokens"])) {
109
- return err({
110
- _tag: "malformed_body",
111
- reason: "`usage` is not `{ input_tokens, output_tokens }`"
112
- });
107
+ if (!Object.hasOwn(answers, id)) return { _tag: "missing_answer", id };
108
+ const answer = answers[id];
109
+ const question = questions[id];
110
+ if (question === void 0 || field === void 0) {
111
+ return { _tag: "malformed_answer", id, reason: "answer is not an object" };
113
112
  }
114
- const answers = body["answers"];
115
- if (!isObj(answers)) {
116
- return err({
117
- _tag: "malformed_body",
118
- reason: "`answers` is not an object"
119
- });
113
+ if (field === "type") {
114
+ const received = at(answer, "type");
115
+ return typeof received === "string" ? { _tag: "answer_type_mismatch", id, expected: question.type, received } : { _tag: "malformed_answer", id, reason: "answer has no `type`" };
120
116
  }
121
- for (const [id, question] of Object.entries(questions)) {
122
- if (!Object.hasOwn(answers, id)) {
123
- return err({ _tag: "missing_answer", id });
117
+ if (question.type === "choice") {
118
+ const options = Object.keys(question.criteria);
119
+ if (field === "choice") {
120
+ const choice = at(answer, "choice");
121
+ if (typeof choice === "string") {
122
+ return { _tag: "off_criteria_choice", id, choice, options };
123
+ }
124
+ }
125
+ if (field === "probabilities") {
126
+ const probabilities = at(answer, "probabilities");
127
+ const key = issue?.path[3];
128
+ const badValue = isObj(probabilities) && typeof key === "string" && Object.hasOwn(probabilities, key);
129
+ if (isObj(probabilities) && !badValue) {
130
+ return {
131
+ _tag: "off_criteria_probabilities",
132
+ id,
133
+ missing: options.filter((k) => !Object.hasOwn(probabilities, k)),
134
+ extra: Object.keys(probabilities).filter((k) => !options.includes(k)),
135
+ options
136
+ };
137
+ }
124
138
  }
125
- const bad = checkAnswer(id, question, answers[id]);
126
- if (bad !== void 0) return err(bad);
127
139
  }
140
+ const named = typeof field === "string" ? ANSWER_FIELD_REASON[field] : void 0;
128
141
  return {
129
- ok: true,
130
- // Every id of `questions` passed `checkAnswer`, which is exactly the set of
131
- // obligations `JevAnswers<Q>` states. `unknown` is the bridge because the
132
- // per-id narrowing happened in a loop, where the compiler cannot carry it.
133
- answers,
134
- model,
135
- usage: {
136
- input_tokens: usage["input_tokens"],
137
- output_tokens: usage["output_tokens"]
138
- }
142
+ _tag: "malformed_answer",
143
+ id,
144
+ reason: named ?? issue?.message ?? "answer is malformed"
139
145
  };
140
146
  };
147
+ var parseAnswers = (questions, body) => {
148
+ const parsed = responseSchema(questions).safeParse(body);
149
+ if (!parsed.success) {
150
+ return err(toJevErr(questions, body, parsed.error.issues[0]));
151
+ }
152
+ const { answers, model, usage } = parsed.data;
153
+ return { ok: true, answers, model, usage };
154
+ };
141
155
  var classifyStatus = (status) => {
142
156
  if (status >= 200 && status < 300) return "ok";
143
157
  if (status === 429 || status === 529) return "retry";
@@ -184,18 +198,18 @@ function createJevAsk(config, rng = Math.random) {
184
198
  function init() {
185
199
  return rc.init();
186
200
  }
187
- function attempt(s, key, content, at) {
201
+ function attempt(s, key, content, at2) {
188
202
  const request = {
189
203
  state: content,
190
204
  model,
191
205
  questions: config.questions
192
206
  };
193
- return rc.attempt(s, key, request, at);
207
+ return rc.attempt(s, key, request, at2);
194
208
  }
195
209
  function succeed(s, key, msg) {
196
210
  return rc.succeed(s, key, msg);
197
211
  }
198
- function settleFromFallback(s, key, request, fallback, at) {
212
+ function settleFromFallback(s, key, request, fallback, at2) {
199
213
  const decided = fallback(request);
200
214
  if (isErrDecision(decided)) return rc.settleFailed(s, key, decided);
201
215
  return rc.succeed(s, key, {
@@ -207,7 +221,7 @@ function createJevAsk(config, rng = Math.random) {
207
221
  usage: NO_USAGE,
208
222
  source: "fallback"
209
223
  },
210
- at
224
+ at: at2
211
225
  });
212
226
  }
213
227
  function fail(s, key, msg) {
@@ -274,10 +288,20 @@ function createJevAsk(config, rng = Math.random) {
274
288
  function handlers() {
275
289
  return { resilient_run: (cmd) => settleOf(cmd) };
276
290
  }
277
- return { init, attempt, succeed, fail, onTimer, subs, handlers, ask };
291
+ return {
292
+ name: rc.name,
293
+ init,
294
+ attempt,
295
+ succeed,
296
+ fail,
297
+ onTimer,
298
+ subs,
299
+ handlers,
300
+ ask
301
+ };
278
302
  }
279
303
  function liftJevAsk(state, result) {
280
- return liftResilience(state, result);
304
+ return liftSlice("resilience", state, result);
281
305
  }
282
306
 
283
307
  // src/internal/jev/classify-batch/index.ts
@@ -346,21 +370,28 @@ function createClassifyBatch(config) {
346
370
  id: cmd.items.map(config.keyOf).join("\0"),
347
371
  items: cmd.items
348
372
  }));
349
- const [next, cmds] = fanOut.scatter(state.fanOut, batches);
350
- return [{ ...state, fanOut: next }, cmds];
373
+ return liftSlice("fanOut", state, fanOut.scatter(state.fanOut, batches));
351
374
  }
352
- function add(state, item, at) {
375
+ function add(state, item, at2) {
353
376
  const key = config.keyOf(item);
354
- if (has(state.cache, key, at)) return [state, []];
377
+ if (has(state.cache, key, at2)) return [state, []];
355
378
  if (keysInFlight(state).has(key)) return [state, []];
356
379
  const failed = { ...state.failed };
357
380
  delete failed[key];
358
- const [nextWindow, flushed] = window.add(state.window, item, at);
359
- return scatter({ ...state, failed, window: nextWindow }, flushed);
360
- }
361
- function onWindow(state, at) {
362
- const [nextWindow, flushed] = window.onWindow(state.window, at);
363
- return scatter({ ...state, window: nextWindow }, flushed);
381
+ const [buffered, flushed] = liftSlice(
382
+ "window",
383
+ { ...state, failed },
384
+ window.add(state.window, item, at2)
385
+ );
386
+ return scatter(buffered, flushed);
387
+ }
388
+ function onWindow(state, at2) {
389
+ const [closed, flushed] = liftSlice(
390
+ "window",
391
+ state,
392
+ window.onWindow(state.window, at2)
393
+ );
394
+ return scatter(closed, flushed);
364
395
  }
365
396
  function onBatchOk(state, msg) {
366
397
  let cache = state.cache;
@@ -369,8 +400,11 @@ function createClassifyBatch(config) {
369
400
  }
370
401
  const failed = { ...state.failed };
371
402
  for (const key of Object.keys(msg.result.answers)) delete failed[key];
372
- const [nextFanOut, cmds] = fanOut.itemOk(state.fanOut, msg.key, msg.result);
373
- return [{ ...state, cache, failed, fanOut: nextFanOut }, cmds];
403
+ return liftSlice(
404
+ "fanOut",
405
+ { ...state, cache, failed },
406
+ fanOut.itemOk(state.fanOut, msg.key, msg.result)
407
+ );
374
408
  }
375
409
  function onBatchErr(state, msg) {
376
410
  const batch = runningBatch(state, msg.key);
@@ -378,19 +412,37 @@ function createClassifyBatch(config) {
378
412
  if (batch !== void 0) {
379
413
  for (const item of batch.items) failed[config.keyOf(item)] = msg.error;
380
414
  }
381
- const [nextFanOut, cmds] = fanOut.itemErr(state.fanOut, msg.key, msg.error);
382
- return [{ ...state, failed, fanOut: nextFanOut }, cmds];
383
- }
384
- function onEvict(state, at) {
385
- return [{ ...state, cache: evictExpired(state.cache, at) }, []];
386
- }
387
- function answerFor(state, key, at) {
388
- const answer = get(state.cache, key, at);
389
- if (answer !== void 0) return { status: "answered", answer };
390
- const error = state.failed[key];
391
- if (error !== void 0) return { status: "failed", error };
392
- if (keysInFlight(state).has(key)) return { status: "pending" };
393
- return { status: "absent" };
415
+ return liftSlice(
416
+ "fanOut",
417
+ { ...state, failed },
418
+ fanOut.itemErr(state.fanOut, msg.key, msg.error)
419
+ );
420
+ }
421
+ function onEvict(state, at2) {
422
+ return liftSlice("cache", state, [evictExpired(state.cache, at2), []]);
423
+ }
424
+ const ANSWER_ORDER = [
425
+ {
426
+ name: "cache",
427
+ read: ({ state, key, at: at2 }) => {
428
+ const answer = get(state.cache, key, at2);
429
+ return answer === void 0 ? void 0 : { status: "answered", answer };
430
+ }
431
+ },
432
+ {
433
+ name: "failed",
434
+ read: ({ state, key }) => {
435
+ const error = state.failed[key];
436
+ return error === void 0 ? void 0 : { status: "failed", error };
437
+ }
438
+ },
439
+ {
440
+ name: "inFlight",
441
+ read: ({ state, key }) => keysInFlight(state).has(key) ? { status: "pending" } : void 0
442
+ }
443
+ ];
444
+ function answerFor(state, key, at2) {
445
+ return readInOrder({ state, key, at: at2 }, ANSWER_ORDER, { status: "absent" });
394
446
  }
395
447
  function subs(state, id = "jev-classify-batch") {
396
448
  const windowSubs = window.subs(state.window, id);