@demlik/tea 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +30 -7
  2. package/dist/agent/index.d.ts +49 -37
  3. package/dist/agent/index.js +12 -8
  4. package/dist/chunk-4LPY67E4.js +18 -0
  5. package/dist/chunk-4LPY67E4.js.map +1 -0
  6. package/dist/chunk-4NTCPTNQ.js +64 -0
  7. package/dist/chunk-4NTCPTNQ.js.map +1 -0
  8. package/dist/{chunk-3B5X7SBB.js → chunk-4PXNZ5UY.js} +11 -9
  9. package/dist/chunk-4PXNZ5UY.js.map +1 -0
  10. package/dist/{chunk-AYS5N6WY.js → chunk-6XBEYZME.js} +62 -172
  11. package/dist/chunk-6XBEYZME.js.map +1 -0
  12. package/dist/chunk-C4U5D5HP.js +380 -0
  13. package/dist/chunk-C4U5D5HP.js.map +1 -0
  14. package/dist/{chunk-QPEVCJ5Q.js → chunk-DFUEAA6L.js} +13 -6
  15. package/dist/chunk-DFUEAA6L.js.map +1 -0
  16. package/dist/{chunk-22POWGFA.js → chunk-GWWCCSDH.js} +46 -20
  17. package/dist/chunk-GWWCCSDH.js.map +1 -0
  18. package/dist/chunk-K4ETBNKS.js +733 -0
  19. package/dist/chunk-K4ETBNKS.js.map +1 -0
  20. package/dist/chunk-KWNCM6XM.js +539 -0
  21. package/dist/chunk-KWNCM6XM.js.map +1 -0
  22. package/dist/{chunk-V46HSVCK.js → chunk-LYVOGOBC.js} +3 -3
  23. package/dist/{chunk-V46HSVCK.js.map → chunk-LYVOGOBC.js.map} +1 -1
  24. package/dist/{chunk-VTQI2NHP.js → chunk-OPH6Y4UT.js} +9 -8
  25. package/dist/chunk-OPH6Y4UT.js.map +1 -0
  26. package/dist/{chunk-Q5CQTBFA.js → chunk-OYR7ENKU.js} +20 -30
  27. package/dist/chunk-OYR7ENKU.js.map +1 -0
  28. package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
  29. package/dist/chunk-QNGYQMZB.js.map +1 -0
  30. package/dist/chunk-QWIPH4YH.js +98 -0
  31. package/dist/chunk-QWIPH4YH.js.map +1 -0
  32. package/dist/{chunk-TCLBCERH.js → chunk-XBZQT2TD.js} +238 -212
  33. package/dist/chunk-XBZQT2TD.js.map +1 -0
  34. package/dist/{core-DnzqWy6u.d.ts → core-rDbOaJTN.d.ts} +236 -140
  35. package/dist/do/index.d.ts +37 -33
  36. package/dist/do/index.js +21 -14
  37. package/dist/do/index.js.map +1 -1
  38. package/dist/{durable-effects-CWzA-o2B.d.ts → durable-effects-CNaw97Be.d.ts} +1 -1
  39. package/dist/effect/index.d.ts +151 -0
  40. package/dist/effect/index.js +98 -0
  41. package/dist/effect/index.js.map +1 -0
  42. package/dist/extension/index.d.ts +6 -7
  43. package/dist/extension/index.js +3 -2
  44. package/dist/extension/index.js.map +1 -1
  45. package/dist/flow/index.d.ts +68 -59
  46. package/dist/flow/index.js +32 -27
  47. package/dist/flow/index.js.map +1 -1
  48. package/dist/idempotency/index.d.ts +6 -7
  49. package/dist/idempotency/index.js +4 -2
  50. package/dist/{index-KXqTRJyb.d.ts → index-BOrsbdAf.d.ts} +19 -96
  51. package/dist/{index-DrIRb_Ch.d.ts → index-B_BxplWi.d.ts} +1 -1
  52. package/dist/index-CWmsXNdX.d.ts +207 -0
  53. package/dist/{index-C2DwkjlP.d.ts → index-Cberb5Rr.d.ts} +57 -45
  54. package/dist/{index-CSyMYDAB.d.ts → index-CcrKLtse.d.ts} +1 -1
  55. package/dist/{index-CuNO9m8i.d.ts → index-Cx0F2M34.d.ts} +14 -16
  56. package/dist/{index-HSYgG2Yt.d.ts → index-DaX_P35Q.d.ts} +247 -211
  57. package/dist/{index-CA_7I5g9.d.ts → index-q1PoukOZ.d.ts} +137 -246
  58. package/dist/index.d.ts +121 -385
  59. package/dist/index.js +2 -1
  60. package/dist/jev/index.d.ts +133 -97
  61. package/dist/jev/index.js +205 -161
  62. package/dist/jev/index.js.map +1 -1
  63. package/dist/{machine-DGlPWCWI.d.ts → machine-BcfCFMYF.d.ts} +171 -288
  64. package/dist/machine-viz/index.d.ts +5 -5
  65. package/dist/machine-viz/index.js +8 -4
  66. package/dist/machine-viz/index.js.map +1 -1
  67. package/dist/mem/index.d.ts +3 -4
  68. package/dist/mem/index.js +2 -1
  69. package/dist/mem/index.js.map +1 -1
  70. package/dist/node/index.d.ts +119 -78
  71. package/dist/node/index.js +52 -38
  72. package/dist/node/index.js.map +1 -1
  73. package/dist/paginate/index.d.ts +27 -22
  74. package/dist/paginate/index.js +6 -4
  75. package/dist/parity/index.d.ts +4 -5
  76. package/dist/parity/index.js +3 -2
  77. package/dist/parity/index.js.map +1 -1
  78. package/dist/pbt/index.d.ts +2 -2
  79. package/dist/pbt/index.js +2 -1
  80. package/dist/pbt/index.js.map +1 -1
  81. package/dist/persistence/index.d.ts +10 -12
  82. package/dist/persistence/index.js +5 -3
  83. package/dist/promise/index.d.ts +186 -0
  84. package/dist/promise/index.js +5 -0
  85. package/dist/promise/index.js.map +1 -0
  86. package/dist/{protocol-D8VbH-VH.d.ts → protocol-ClRZBhHQ.d.ts} +7 -8
  87. package/dist/react/index.d.ts +36 -17
  88. package/dist/react/index.js +27 -4
  89. package/dist/react/index.js.map +1 -1
  90. package/dist/resilience/index.d.ts +63 -456
  91. package/dist/resilience/index.js +37 -483
  92. package/dist/resilience/index.js.map +1 -1
  93. package/dist/{runtime-types-CMF13BBh.d.ts → runtime-types-B62Ucnxr.d.ts} +132 -389
  94. package/dist/testing/index.d.ts +33 -113
  95. package/dist/testing/index.js +39 -181
  96. package/dist/testing/index.js.map +1 -1
  97. package/dist/timing/index.d.ts +25 -22
  98. package/dist/timing/index.js +4 -3
  99. package/dist/timing/index.js.map +1 -1
  100. package/dist/{types-BseNPIhr.d.ts → types-DPm5YCDQ.d.ts} +2 -2
  101. package/dist/work-queue/index.d.ts +5 -6
  102. package/package.json +20 -7
  103. package/dist/chunk-22POWGFA.js.map +0 -1
  104. package/dist/chunk-3B5X7SBB.js.map +0 -1
  105. package/dist/chunk-66PY5WYF.js +0 -1816
  106. package/dist/chunk-66PY5WYF.js.map +0 -1
  107. package/dist/chunk-AYS5N6WY.js.map +0 -1
  108. package/dist/chunk-L3TND7LA.js +0 -97
  109. package/dist/chunk-L3TND7LA.js.map +0 -1
  110. package/dist/chunk-MYXFNWAJ.js.map +0 -1
  111. package/dist/chunk-Q5CQTBFA.js.map +0 -1
  112. package/dist/chunk-QPEVCJ5Q.js.map +0 -1
  113. package/dist/chunk-TCLBCERH.js.map +0 -1
  114. package/dist/chunk-VTQI2NHP.js.map +0 -1
  115. package/dist/index-ZCMhnVKN.d.ts +0 -272
package/dist/jev/index.js CHANGED
@@ -1,16 +1,16 @@
1
- import { createBatchWindow, subscribeBatchWindow } from '../chunk-QPEVCJ5Q.js';
1
+ import { createBatchWindow } from '../chunk-DFUEAA6L.js';
2
2
  import '../chunk-LFZUK6J2.js';
3
- import { createFanOut } from '../chunk-MYXFNWAJ.js';
3
+ import { describeError } from '../chunk-G5E74IJB.js';
4
+ import { createFanOut } from '../chunk-QNGYQMZB.js';
4
5
  import '../chunk-TXN2KFHF.js';
5
- import { runCmdDef, createResilientCall, MsgType } from '../chunk-AYS5N6WY.js';
6
- export { mountResilientCall } from '../chunk-AYS5N6WY.js';
6
+ import { runCmdDef, createResilientCall } from '../chunk-6XBEYZME.js';
7
7
  import '../chunk-VBDU4JL6.js';
8
- import { initCache, has, set, evictExpired, cacheEvictionSub, cacheEvictionSubscribe, get } from '../chunk-22POWGFA.js';
9
- export { deadlineSub, subscribeDeadline } from '../chunk-22POWGFA.js';
10
- import { describeError } from '../chunk-G5E74IJB.js';
11
- import { liftSlice, readInOrder } from '../chunk-66PY5WYF.js';
12
- import { z } from 'zod';
8
+ import '../chunk-4LPY67E4.js';
9
+ import { initCache, has, set, evictExpired, cacheEvictionSub, cacheEvictionSubscribe, get } from '../chunk-GWWCCSDH.js';
10
+ import { liftSlice, readInOrder } from '../chunk-C4U5D5HP.js';
11
+ import { Outcome } from '../chunk-K4ETBNKS.js';
13
12
 
13
+ // src/internal/jev/protocol/index.ts
14
14
  var jevQuestions = (questions) => questions;
15
15
  var JEV_ENDPOINT = "https://api.typesafe.ai/v1/systemone";
16
16
  var JEV_ERR_TAG_WITNESS = {
@@ -36,48 +36,99 @@ var err = (error) => ({
36
36
  ok: false,
37
37
  error
38
38
  });
39
- var finite = z.number().finite();
40
- var answerSchema = (question) => {
39
+ var pass = (value) => ({ ok: true, value });
40
+ var fail = (path) => ({
41
+ ok: false,
42
+ issue: { path }
43
+ });
44
+ var isFiniteNumber = (v) => typeof v === "number" && Number.isFinite(v);
45
+ var object = (value, path, fields) => {
46
+ if (!isObj(value)) return fail(path);
47
+ const out = {};
48
+ for (const [key, check] of fields) {
49
+ const step = check(value[key], [...path, key]);
50
+ if (!step.ok) return step;
51
+ out[key] = step.value;
52
+ }
53
+ return pass(out);
54
+ };
55
+ var record = (isValue) => (value, path) => {
56
+ if (!isObj(value)) return fail(path);
57
+ for (const [key, v] of Object.entries(value)) {
58
+ if (!isValue(v)) return fail([...path, key]);
59
+ }
60
+ return pass({ ...value });
61
+ };
62
+ var literal = (expected) => (value, path) => value === expected ? pass(expected) : fail(path);
63
+ var finite = (value, path) => isFiniteNumber(value) ? pass(value) : fail(path);
64
+ var string = (value, path) => typeof value === "string" ? pass(value) : fail(path);
65
+ var exactProbabilities = (options) => (value, path) => {
66
+ const named = object(
67
+ value,
68
+ path,
69
+ options.map((k) => [k, finite])
70
+ );
71
+ if (!named.ok || !isObj(value)) return named;
72
+ return Object.keys(value).every((k) => options.includes(k)) ? named : fail(path);
73
+ };
74
+ var checkAnswer = (question, value, path) => {
41
75
  switch (question.type) {
42
76
  case "noul":
43
- return z.object({ type: z.literal("noul"), noul: finite });
77
+ return object(value, path, [
78
+ ["type", literal("noul")],
79
+ ["noul", finite]
80
+ ]);
44
81
  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
- });
82
+ return object(value, path, [
83
+ ["type", literal("score")],
84
+ ["confidence", finite],
85
+ ["score", finite],
86
+ ["legend", record((v) => typeof v === "string")],
87
+ ["probabilities", record(isFiniteNumber)]
88
+ ]);
52
89
  case "choice": {
53
90
  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
- });
91
+ return object(value, path, [
92
+ ["type", literal("choice")],
93
+ [
94
+ "choice",
95
+ (v, p) => typeof v === "string" && options.includes(v) ? pass(v) : fail(p)
96
+ ],
97
+ ["confidence", finite],
98
+ ["probabilities", exactProbabilities(options)]
99
+ ]);
65
100
  }
66
101
  }
67
102
  };
68
- var jevAnswersSchema = (questions) => z.object(
69
- Object.fromEntries(
70
- Object.entries(questions).map(([id, question]) => [
71
- id,
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
- });
103
+ var checkResponse = (questions, body) => {
104
+ const envelope = object(
105
+ body,
106
+ [],
107
+ [
108
+ ["model", string],
109
+ [
110
+ "usage",
111
+ (v, p) => object(v, p, [
112
+ ["input_tokens", finite],
113
+ ["output_tokens", finite]
114
+ ])
115
+ ],
116
+ [
117
+ "answers",
118
+ (v, p) => object(
119
+ v,
120
+ p,
121
+ Object.entries(questions).map(
122
+ ([id, question]) => [id, (a, ap) => checkAnswer(question, a, ap)]
123
+ )
124
+ )
125
+ ]
126
+ ]
127
+ );
128
+ if (!envelope.ok) return envelope;
129
+ const { model, usage, answers } = envelope.value;
130
+ return pass({ model, usage, answers });
131
+ };
81
132
  var ANSWER_FIELD_REASON = {
82
133
  confidence: "`confidence` is not a number",
83
134
  score: "`score` is not a number",
@@ -87,7 +138,7 @@ var ANSWER_FIELD_REASON = {
87
138
  noul: "`noul` is not a number"
88
139
  };
89
140
  var toJevErr = (questions, body, issue) => {
90
- const [head, id, field] = issue?.path ?? [];
141
+ const [head, id, field] = issue.path;
91
142
  if (head === "model") {
92
143
  return { _tag: "malformed_body", reason: "`model` is not a string" };
93
144
  }
@@ -124,7 +175,7 @@ var toJevErr = (questions, body, issue) => {
124
175
  }
125
176
  if (field === "probabilities") {
126
177
  const probabilities = at(answer, "probabilities");
127
- const key = issue?.path[3];
178
+ const key = issue.path[3];
128
179
  const badValue = isObj(probabilities) && typeof key === "string" && Object.hasOwn(probabilities, key);
129
180
  if (isObj(probabilities) && !badValue) {
130
181
  return {
@@ -141,15 +192,13 @@ var toJevErr = (questions, body, issue) => {
141
192
  return {
142
193
  _tag: "malformed_answer",
143
194
  id,
144
- reason: named ?? issue?.message ?? "answer is malformed"
195
+ reason: named ?? "answer is malformed"
145
196
  };
146
197
  };
147
198
  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;
199
+ const parsed = checkResponse(questions, body);
200
+ if (!parsed.ok) return err(toJevErr(questions, body, parsed.issue));
201
+ const { answers, model, usage } = parsed.value;
153
202
  return { ok: true, answers, model, usage };
154
203
  };
155
204
  var classifyStatus = (status) => {
@@ -162,20 +211,53 @@ var classifyStatus = (status) => {
162
211
  function isTransientJevAskErr(error) {
163
212
  return error._tag === "http_retry" || error._tag === "port_threw";
164
213
  }
165
- var JevAskFailure = class extends Error {
166
- constructor(jev) {
167
- super(`jev ask: ${jev._tag}`);
168
- this.jev = jev;
169
- this.name = "JevAskFailure";
214
+ function reject(jev) {
215
+ return Outcome.err({ _tag: "port_rejected", jev });
216
+ }
217
+ function jevAskErrOf(error) {
218
+ if (typeof error === "object" && error !== null) {
219
+ const jev = error.jev;
220
+ if (typeof jev === "object" && jev !== null && typeof jev._tag === "string") {
221
+ return jev;
222
+ }
170
223
  }
171
- jev;
172
- };
173
- function toAskErr(error) {
174
- if (error instanceof JevAskFailure) return error.jev;
175
224
  return { _tag: "port_threw", reason: describeError(error) };
176
225
  }
177
226
  var DEFAULT_JEV_MODEL = "jev-latest";
178
227
  var NO_USAGE = { input_tokens: 0, output_tokens: 0 };
228
+ function isErrDecision(decided) {
229
+ return isJevErr(decided);
230
+ }
231
+ function decodeJevReply(request, reply) {
232
+ const kind = classifyStatus(reply.status);
233
+ if (kind === "retry")
234
+ return reject({ _tag: "http_retry", status: reply.status });
235
+ if (kind === "terminal") {
236
+ return reject({ _tag: "http_terminal", status: reply.status });
237
+ }
238
+ const parsed = parseAnswers(request.questions, reply.body);
239
+ if (!parsed.ok) return reject(parsed.error);
240
+ return Outcome.ok({
241
+ answers: parsed.answers,
242
+ model: parsed.model,
243
+ usage: parsed.usage,
244
+ source: "port"
245
+ });
246
+ }
247
+ function jevCallThrew(cause) {
248
+ return reject({ _tag: "port_threw", reason: describeError(cause) });
249
+ }
250
+ function offlineJevAnswer(request, fallback) {
251
+ if (fallback === void 0) return reject({ _tag: "no_answer_path" });
252
+ const decided = fallback(request);
253
+ if (isErrDecision(decided)) return reject(decided);
254
+ return Outcome.ok({
255
+ answers: decided,
256
+ model: request.model,
257
+ usage: NO_USAGE,
258
+ source: "fallback"
259
+ });
260
+ }
179
261
  function jevAskCmdDef() {
180
262
  return runCmdDef();
181
263
  }
@@ -185,9 +267,6 @@ function createJevAsk(config, rng = Math.random) {
185
267
  };
186
268
  const rc = createResilientCall(resilientConfig, rng);
187
269
  const model = config.model ?? DEFAULT_JEV_MODEL;
188
- function isErrDecision(decided) {
189
- return isJevErr(decided);
190
- }
191
270
  function liveRequest(s, key) {
192
271
  const call = s.calls[key];
193
272
  if (call?.phase === "running" || call?.phase === "waiting_retry") {
@@ -206,98 +285,59 @@ function createJevAsk(config, rng = Math.random) {
206
285
  };
207
286
  return rc.attempt(s, key, request, at2);
208
287
  }
209
- function succeed(s, key, msg) {
210
- return rc.succeed(s, key, msg);
288
+ function succeed(s, msg) {
289
+ const { call, cmds } = rc.settle(s, msg);
290
+ return [call, cmds];
211
291
  }
212
292
  function settleFromFallback(s, key, request, fallback, at2) {
213
- const decided = fallback(request);
214
- if (isErrDecision(decided)) return rc.settleFailed(s, key, decided);
215
- return rc.succeed(s, key, {
216
- type: MsgType.ResilientOk,
217
- key,
218
- result: {
219
- answers: decided,
220
- model: request.model,
221
- usage: NO_USAGE,
222
- source: "fallback"
223
- },
293
+ const decided = offlineJevAnswer(request, fallback);
294
+ if (decided._tag === "Err") {
295
+ return rc.settleFailed(s, key, decided.error.jev, at2);
296
+ }
297
+ const { call, cmds } = rc.settle(s, {
298
+ cmd: { key },
299
+ value: decided.value,
224
300
  at: at2
225
301
  });
302
+ return [call, cmds];
226
303
  }
227
- function fail(s, key, msg) {
228
- if (!isTransientJevAskErr(msg.error)) {
229
- return rc.settleFailed(s, key, msg.error);
304
+ function fail2(s, msg) {
305
+ const { key } = msg.cmd;
306
+ const error = jevAskErrOf(msg.error);
307
+ if (!isTransientJevAskErr(error)) {
308
+ return rc.settleFailed(s, key, error, msg.at);
230
309
  }
231
310
  const request = liveRequest(s, key);
232
- const settled = rc.fail(s, key, msg);
233
- const backedOff = settled[0].calls[key]?.phase !== "failed";
234
- if (backedOff || config.fallback === void 0 || request === void 0) {
235
- return settled;
311
+ const { call, cmds, outcome } = rc.settle(s, { ...msg, error });
312
+ if (outcome.kind !== "failed" || config.fallback === void 0 || request === void 0) {
313
+ return [call, cmds];
236
314
  }
237
315
  return settleFromFallback(s, key, request, config.fallback, msg.at);
238
316
  }
239
317
  function onTimer(s, msg) {
240
318
  return rc.onTimer(s, msg);
241
319
  }
242
- function subs(s) {
243
- return rc.subs(s);
244
- }
245
- async function ask(request, signal) {
246
- if (config.port === void 0) {
247
- if (config.fallback === void 0) {
248
- throw new JevAskFailure({ _tag: "no_answer_path" });
249
- }
250
- const decided = config.fallback(request);
251
- if (isErrDecision(decided)) throw new JevAskFailure(decided);
252
- return {
253
- answers: decided,
254
- model: request.model,
255
- usage: NO_USAGE,
256
- source: "fallback"
257
- };
258
- }
259
- const { status, body } = await config.port(request, signal);
260
- const kind = classifyStatus(status);
261
- if (kind === "retry")
262
- throw new JevAskFailure({ _tag: "http_retry", status });
263
- if (kind === "terminal") {
264
- throw new JevAskFailure({ _tag: "http_terminal", status });
265
- }
266
- const parsed = parseAnswers(config.questions, body);
267
- if (!parsed.ok) throw new JevAskFailure(parsed.error);
268
- return {
269
- answers: parsed.answers,
270
- model: parsed.model,
271
- usage: parsed.usage,
272
- source: "port"
273
- };
274
- }
275
- const resilientRunHandler = rc.handlers({
276
- run: (request) => ask(request)
277
- }).resilient_run;
278
- async function settleOf(cmd) {
279
- const settle = await resilientRunHandler(cmd, {});
280
- if (settle.type === MsgType.ResilientOk) return settle;
281
- return {
282
- type: MsgType.ResilientErr,
283
- key: settle.key,
284
- error: toAskErr(settle.error),
285
- at: settle.at
286
- };
287
- }
288
- function handlers() {
289
- return { resilient_run: (cmd) => settleOf(cmd) };
320
+ function deadlines(s) {
321
+ return rc.deadlines(s);
290
322
  }
291
323
  return {
292
324
  name: rc.name,
325
+ /** The `Cmd.define`d run Cmd — list it in the machine's `cmds`. */
326
+ run: rc.run,
293
327
  init,
294
328
  attempt,
295
329
  succeed,
296
- fail,
330
+ fail: fail2,
297
331
  onTimer,
298
- subs,
299
- handlers,
300
- ask
332
+ deadlines,
333
+ /** The built-in `timer` Sub's deps — resilient-call's `timer`. */
334
+ timer: rc.timer,
335
+ /** Your handler's outcome for an HTTP reply — {@link decodeJevReply}. */
336
+ decode: (request, reply) => decodeJevReply(request, reply),
337
+ /** Your handler's outcome when the call threw — {@link jevCallThrew}. */
338
+ rejected: jevCallThrew,
339
+ /** Your handler's outcome with no network — {@link offlineJevAnswer}. */
340
+ offline: (request) => offlineJevAnswer(request, config.fallback)
301
341
  };
302
342
  }
303
343
  function liftJevAsk(state, result) {
@@ -395,27 +435,28 @@ function createClassifyBatch(config) {
395
435
  }
396
436
  function onBatchOk(state, msg) {
397
437
  let cache = state.cache;
398
- for (const [key, answer] of Object.entries(msg.result.answers)) {
438
+ for (const [key, answer] of Object.entries(msg.value.answers)) {
399
439
  cache = set(cache, key, answer, msg.at, config.ttlMs);
400
440
  }
401
441
  const failed = { ...state.failed };
402
- for (const key of Object.keys(msg.result.answers)) delete failed[key];
442
+ for (const key of Object.keys(msg.value.answers)) delete failed[key];
403
443
  return liftSlice(
404
444
  "fanOut",
405
445
  { ...state, cache, failed },
406
- fanOut.itemOk(state.fanOut, msg.key, msg.result)
446
+ fanOut.itemOk(state.fanOut, msg.cmd.key, msg.value)
407
447
  );
408
448
  }
409
449
  function onBatchErr(state, msg) {
410
- const batch = runningBatch(state, msg.key);
450
+ const batch = runningBatch(state, msg.cmd.key);
451
+ const error = jevAskErrOf(msg.error);
411
452
  const failed = { ...state.failed };
412
453
  if (batch !== void 0) {
413
- for (const item of batch.items) failed[config.keyOf(item)] = msg.error;
454
+ for (const item of batch.items) failed[config.keyOf(item)] = error;
414
455
  }
415
456
  return liftSlice(
416
457
  "fanOut",
417
458
  { ...state, failed },
418
- fanOut.itemErr(state.fanOut, msg.key, msg.error)
459
+ fanOut.itemErr(state.fanOut, msg.cmd.key, error)
419
460
  );
420
461
  }
421
462
  function onEvict(state, at2) {
@@ -445,28 +486,22 @@ function createClassifyBatch(config) {
445
486
  return readInOrder({ state, key, at: at2 }, ANSWER_ORDER, { status: "absent" });
446
487
  }
447
488
  function subs(state, id = "jev-classify-batch") {
448
- const windowSubs = window.subs(state.window, id);
449
- if (config.evictEveryMs === void 0) return windowSubs;
450
- return [...windowSubs, cacheEvictionSub(id, config.evictEveryMs)];
451
- }
452
- function subscribers() {
453
- return { deadline: subscribeBatchWindow, cache: cacheEvictionSubscribe };
489
+ return window.subs(state.window, id);
454
490
  }
455
- function handlers() {
456
- return {
457
- resilient_run: (cmd) => {
458
- const request = cmd.input;
459
- const ask = createJevAsk({
460
- questions: request.questions,
461
- ...config.port === void 0 ? {} : { port: config.port },
462
- ...config.fallback === void 0 ? {} : { fallback: config.fallback },
463
- ...config.model === void 0 ? {} : { model: config.model }
464
- });
465
- return ask.handlers().resilient_run(cmd);
466
- }
491
+ function subEntries(select, id = "jev-classify-batch") {
492
+ const flush = {
493
+ type: "timer",
494
+ deps: (model) => window.timer(select(model).window, id)
467
495
  };
496
+ if (config.evictEveryMs === void 0) return [flush];
497
+ return [flush, cacheEvictionSub(id, config.evictEveryMs)];
498
+ }
499
+ function subscribers() {
500
+ return { cache: cacheEvictionSubscribe };
468
501
  }
469
502
  return {
503
+ /** The ask Cmd def — list it in the machine's `cmds`. */
504
+ ask: askCmd,
470
505
  init,
471
506
  add,
472
507
  onWindow,
@@ -475,11 +510,20 @@ function createClassifyBatch(config) {
475
510
  onEvict,
476
511
  answerFor,
477
512
  subs,
513
+ subEntries,
478
514
  subscribers,
479
- handlers
515
+ /**
516
+ * Your handler's outcome for Jev's reply to one batch — `../ask`'s
517
+ * `decodeJevReply`, parsing against the questions the batch carried.
518
+ */
519
+ decode: (request, reply) => decodeJevReply(request, reply),
520
+ /** Your handler's outcome when the call threw — `../ask`'s `jevCallThrew`. */
521
+ rejected: jevCallThrew,
522
+ /** Your handler's outcome with no network — the configured `fallback`. */
523
+ offline: (request) => offlineJevAnswer(request, config.fallback)
480
524
  };
481
525
  }
482
526
 
483
- export { DEFAULT_CLASSIFY_MAX_ITEMS, DEFAULT_JEV_MODEL, JEV_ENDPOINT, JevAskFailure, classifyStatus, createClassifyBatch, createJevAsk, isJevErr, isTransientJevAskErr, jevAskCmdDef, jevQuestions, liftJevAsk, parseAnswers };
527
+ export { DEFAULT_CLASSIFY_MAX_ITEMS, DEFAULT_JEV_MODEL, JEV_ENDPOINT, classifyStatus, createClassifyBatch, createJevAsk, decodeJevReply, isJevErr, isTransientJevAskErr, jevAskCmdDef, jevAskErrOf, jevCallThrew, jevQuestions, liftJevAsk, offlineJevAnswer, parseAnswers };
484
528
  //# sourceMappingURL=index.js.map
485
529
  //# sourceMappingURL=index.js.map