@demlik/tea 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -7
- package/dist/agent/index.d.ts +49 -36
- package/dist/agent/index.js +12 -8
- package/dist/chunk-4LPY67E4.js +18 -0
- package/dist/chunk-4LPY67E4.js.map +1 -0
- package/dist/chunk-5XU6ZJO2.js +533 -0
- package/dist/chunk-5XU6ZJO2.js.map +1 -0
- package/dist/{chunk-AQ6ZIMEA.js → chunk-6NG4V5SB.js} +89 -115
- package/dist/chunk-6NG4V5SB.js.map +1 -0
- package/dist/{chunk-HYDWG35Q.js → chunk-7MGXQZPW.js} +11 -9
- package/dist/chunk-7MGXQZPW.js.map +1 -0
- package/dist/{chunk-BLJ2JQSH.js → chunk-BCTEOVOU.js} +3 -3
- package/dist/{chunk-BLJ2JQSH.js.map → chunk-BCTEOVOU.js.map} +1 -1
- package/dist/chunk-CH5KTOEZ.js +710 -0
- package/dist/chunk-CH5KTOEZ.js.map +1 -0
- package/dist/chunk-CIHSHLQX.js +64 -0
- package/dist/chunk-CIHSHLQX.js.map +1 -0
- package/dist/{chunk-Z2L3LSNV.js → chunk-EHUDXAKC.js} +246 -210
- package/dist/chunk-EHUDXAKC.js.map +1 -0
- package/dist/chunk-GOX2CYIM.js +380 -0
- package/dist/chunk-GOX2CYIM.js.map +1 -0
- package/dist/chunk-IVJP3GKJ.js +104 -0
- package/dist/chunk-IVJP3GKJ.js.map +1 -0
- package/dist/{chunk-F7FMAWLA.js → chunk-MVZS5FDM.js} +13 -6
- package/dist/chunk-MVZS5FDM.js.map +1 -0
- package/dist/{chunk-LYLTKJWM.js → chunk-MYNLY3HP.js} +9 -8
- package/dist/chunk-MYNLY3HP.js.map +1 -0
- package/dist/{chunk-I5MQMJDW.js → chunk-NSIAORRY.js} +20 -30
- package/dist/chunk-NSIAORRY.js.map +1 -0
- package/dist/{chunk-MYXFNWAJ.js → chunk-QNGYQMZB.js} +4 -4
- package/dist/chunk-QNGYQMZB.js.map +1 -0
- package/dist/chunk-WT5PBPLB.js +98 -0
- package/dist/chunk-WT5PBPLB.js.map +1 -0
- package/dist/{core-CTzMJ82M.d.ts → core-BbgtiXdg.d.ts} +231 -139
- package/dist/do/index.d.ts +37 -32
- package/dist/do/index.js +21 -14
- package/dist/do/index.js.map +1 -1
- package/dist/{durable-effects-B0-qGQDy.d.ts → durable-effects-7MTK_jnj.d.ts} +1 -1
- package/dist/effect/index.d.ts +151 -0
- package/dist/effect/index.js +98 -0
- package/dist/effect/index.js.map +1 -0
- package/dist/extension/index.d.ts +6 -7
- package/dist/extension/index.js +3 -2
- package/dist/extension/index.js.map +1 -1
- package/dist/flow/index.d.ts +68 -70
- package/dist/flow/index.js +32 -27
- package/dist/flow/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +6 -7
- package/dist/idempotency/index.js +4 -2
- package/dist/{index-DJWIER_3.d.ts → index-7vV8xmsD.d.ts} +1 -1
- package/dist/{index-NjrT3fL2.d.ts → index-Bz5Rh9Ga.d.ts} +19 -96
- package/dist/index-CjFDUBeq.d.ts +207 -0
- package/dist/{index-6A7dB8f6.d.ts → index-CkFYA9Y6.d.ts} +14 -16
- package/dist/{index-B5BZ-_cT.d.ts → index-Cou86-GX.d.ts} +189 -108
- package/dist/{index-TvRb1KVf.d.ts → index-DU6JpQ8G.d.ts} +1 -1
- package/dist/{index-q0hXFeZ0.d.ts → index-Xufl55W8.d.ts} +286 -215
- package/dist/{index-4vZzljCD.d.ts → index-_dOR3xqA.d.ts} +57 -45
- package/dist/index.d.ts +181 -385
- package/dist/index.js +2 -1
- package/dist/jev/index.d.ts +147 -99
- package/dist/jev/index.js +329 -233
- package/dist/jev/index.js.map +1 -1
- package/dist/{machine-CdIcN2Xm.d.ts → machine-BQzTV8On.d.ts} +171 -280
- package/dist/machine-viz/index.d.ts +5 -5
- package/dist/machine-viz/index.js +8 -4
- package/dist/machine-viz/index.js.map +1 -1
- package/dist/mem/index.d.ts +3 -4
- package/dist/mem/index.js +2 -1
- package/dist/mem/index.js.map +1 -1
- package/dist/node/index.d.ts +119 -78
- package/dist/node/index.js +52 -38
- package/dist/node/index.js.map +1 -1
- package/dist/paginate/index.d.ts +27 -33
- package/dist/paginate/index.js +6 -4
- package/dist/parity/index.d.ts +4 -5
- package/dist/parity/index.js +3 -2
- package/dist/parity/index.js.map +1 -1
- package/dist/pbt/index.d.ts +2 -2
- package/dist/pbt/index.js +2 -1
- package/dist/pbt/index.js.map +1 -1
- package/dist/persistence/index.d.ts +6 -7
- package/dist/persistence/index.js +5 -3
- package/dist/promise/index.d.ts +186 -0
- package/dist/promise/index.js +5 -0
- package/dist/promise/index.js.map +1 -0
- package/dist/protocol-ClRZBhHQ.d.ts +53 -0
- package/dist/react/index.d.ts +36 -17
- package/dist/react/index.js +27 -4
- package/dist/react/index.js.map +1 -1
- package/dist/resilience/index.d.ts +63 -455
- package/dist/resilience/index.js +37 -483
- package/dist/resilience/index.js.map +1 -1
- package/dist/{runtime-types-LWDoi943.d.ts → runtime-types-CiVpC0HN.d.ts} +131 -388
- package/dist/testing/index.d.ts +165 -15
- package/dist/testing/index.js +104 -3
- package/dist/testing/index.js.map +1 -1
- package/dist/timing/index.d.ts +25 -22
- package/dist/timing/index.js +4 -3
- package/dist/timing/index.js.map +1 -1
- package/dist/{types-DP3f5NIl.d.ts → types-LxZxGYda.d.ts} +2 -2
- package/dist/work-queue/index.d.ts +5 -6
- package/package.json +18 -5
- package/dist/chunk-AQ6ZIMEA.js.map +0 -1
- package/dist/chunk-F2US5BW6.js +0 -72
- package/dist/chunk-F2US5BW6.js.map +0 -1
- package/dist/chunk-F7FMAWLA.js.map +0 -1
- package/dist/chunk-HUKZQX6U.js +0 -97
- package/dist/chunk-HUKZQX6U.js.map +0 -1
- package/dist/chunk-HYDWG35Q.js.map +0 -1
- package/dist/chunk-I5MQMJDW.js.map +0 -1
- package/dist/chunk-LYLTKJWM.js.map +0 -1
- package/dist/chunk-MYXFNWAJ.js.map +0 -1
- package/dist/chunk-RQULHGYH.js +0 -1804
- package/dist/chunk-RQULHGYH.js.map +0 -1
- package/dist/chunk-Z2L3LSNV.js.map +0 -1
- package/dist/index-DMCeMPMJ.d.ts +0 -272
package/dist/jev/index.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { createBatchWindow
|
|
1
|
+
import { createBatchWindow } from '../chunk-MVZS5FDM.js';
|
|
2
2
|
import '../chunk-LFZUK6J2.js';
|
|
3
|
-
import {
|
|
3
|
+
import { describeError } from '../chunk-G5E74IJB.js';
|
|
4
|
+
import { createFanOut } from '../chunk-QNGYQMZB.js';
|
|
4
5
|
import '../chunk-TXN2KFHF.js';
|
|
5
|
-
import { runCmdDef, createResilientCall
|
|
6
|
+
import { runCmdDef, createResilientCall } from '../chunk-6NG4V5SB.js';
|
|
6
7
|
import '../chunk-VBDU4JL6.js';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import '../chunk-
|
|
8
|
+
import '../chunk-4LPY67E4.js';
|
|
9
|
+
import { initCache, has, set, evictExpired, cacheEvictionSub, cacheEvictionSubscribe, get } from '../chunk-IVJP3GKJ.js';
|
|
10
|
+
import { liftSlice, readInOrder } from '../chunk-GOX2CYIM.js';
|
|
11
|
+
import { Outcome } from '../chunk-CH5KTOEZ.js';
|
|
11
12
|
|
|
12
13
|
// src/internal/jev/protocol/index.ts
|
|
13
14
|
var jevQuestions = (questions) => questions;
|
|
@@ -30,114 +31,176 @@ 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
|
|
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
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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]);
|
|
55
59
|
}
|
|
56
|
-
|
|
57
|
-
|
|
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) => {
|
|
75
|
+
switch (question.type) {
|
|
76
|
+
case "noul":
|
|
77
|
+
return object(value, path, [
|
|
78
|
+
["type", literal("noul")],
|
|
79
|
+
["noul", finite]
|
|
80
|
+
]);
|
|
81
|
+
case "score":
|
|
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
|
+
]);
|
|
89
|
+
case "choice": {
|
|
90
|
+
const options = Object.keys(question.criteria);
|
|
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
|
+
]);
|
|
100
|
+
}
|
|
58
101
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
};
|
|
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
|
+
};
|
|
132
|
+
var ANSWER_FIELD_REASON = {
|
|
133
|
+
confidence: "`confidence` is not a number",
|
|
134
|
+
score: "`score` is not a number",
|
|
135
|
+
legend: "`legend` is not a map of strings",
|
|
136
|
+
probabilities: "`probabilities` is not a map of numbers",
|
|
137
|
+
choice: "`choice` is not a string",
|
|
138
|
+
noul: "`noul` is not a number"
|
|
139
|
+
};
|
|
140
|
+
var toJevErr = (questions, body, issue) => {
|
|
141
|
+
const [head, id, field] = issue.path;
|
|
142
|
+
if (head === "model") {
|
|
143
|
+
return { _tag: "malformed_body", reason: "`model` is not a string" };
|
|
65
144
|
}
|
|
66
|
-
|
|
67
|
-
if (!isNumMap(probabilities)) {
|
|
145
|
+
if (head === "usage") {
|
|
68
146
|
return {
|
|
69
|
-
_tag: "
|
|
70
|
-
|
|
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"
|
|
147
|
+
_tag: "malformed_body",
|
|
148
|
+
reason: "`usage` is not `{ input_tokens, output_tokens }`"
|
|
86
149
|
};
|
|
87
150
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return { _tag: "malformed_answer", id, reason: "`choice` is not a string" };
|
|
151
|
+
if (head !== "answers") {
|
|
152
|
+
return { _tag: "malformed_body", reason: "body is not an object" };
|
|
91
153
|
}
|
|
92
|
-
const
|
|
93
|
-
if (!
|
|
94
|
-
return { _tag: "
|
|
154
|
+
const answers = at(body, "answers");
|
|
155
|
+
if (!isObj(answers) || typeof id !== "string") {
|
|
156
|
+
return { _tag: "malformed_body", reason: "`answers` is not an object" };
|
|
95
157
|
}
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
-
});
|
|
158
|
+
if (!Object.hasOwn(answers, id)) return { _tag: "missing_answer", id };
|
|
159
|
+
const answer = answers[id];
|
|
160
|
+
const question = questions[id];
|
|
161
|
+
if (question === void 0 || field === void 0) {
|
|
162
|
+
return { _tag: "malformed_answer", id, reason: "answer is not an object" };
|
|
113
163
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return
|
|
117
|
-
_tag: "malformed_body",
|
|
118
|
-
reason: "`answers` is not an object"
|
|
119
|
-
});
|
|
164
|
+
if (field === "type") {
|
|
165
|
+
const received = at(answer, "type");
|
|
166
|
+
return typeof received === "string" ? { _tag: "answer_type_mismatch", id, expected: question.type, received } : { _tag: "malformed_answer", id, reason: "answer has no `type`" };
|
|
120
167
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
168
|
+
if (question.type === "choice") {
|
|
169
|
+
const options = Object.keys(question.criteria);
|
|
170
|
+
if (field === "choice") {
|
|
171
|
+
const choice = at(answer, "choice");
|
|
172
|
+
if (typeof choice === "string") {
|
|
173
|
+
return { _tag: "off_criteria_choice", id, choice, options };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (field === "probabilities") {
|
|
177
|
+
const probabilities = at(answer, "probabilities");
|
|
178
|
+
const key = issue.path[3];
|
|
179
|
+
const badValue = isObj(probabilities) && typeof key === "string" && Object.hasOwn(probabilities, key);
|
|
180
|
+
if (isObj(probabilities) && !badValue) {
|
|
181
|
+
return {
|
|
182
|
+
_tag: "off_criteria_probabilities",
|
|
183
|
+
id,
|
|
184
|
+
missing: options.filter((k) => !Object.hasOwn(probabilities, k)),
|
|
185
|
+
extra: Object.keys(probabilities).filter((k) => !options.includes(k)),
|
|
186
|
+
options
|
|
187
|
+
};
|
|
188
|
+
}
|
|
124
189
|
}
|
|
125
|
-
const bad = checkAnswer(id, question, answers[id]);
|
|
126
|
-
if (bad !== void 0) return err(bad);
|
|
127
190
|
}
|
|
191
|
+
const named = typeof field === "string" ? ANSWER_FIELD_REASON[field] : void 0;
|
|
128
192
|
return {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
}
|
|
193
|
+
_tag: "malformed_answer",
|
|
194
|
+
id,
|
|
195
|
+
reason: named ?? "answer is malformed"
|
|
139
196
|
};
|
|
140
197
|
};
|
|
198
|
+
var parseAnswers = (questions, body) => {
|
|
199
|
+
const parsed = checkResponse(questions, body);
|
|
200
|
+
if (!parsed.ok) return err(toJevErr(questions, body, parsed.issue));
|
|
201
|
+
const { answers, model, usage } = parsed.value;
|
|
202
|
+
return { ok: true, answers, model, usage };
|
|
203
|
+
};
|
|
141
204
|
var classifyStatus = (status) => {
|
|
142
205
|
if (status >= 200 && status < 300) return "ok";
|
|
143
206
|
if (status === 429 || status === 529) return "retry";
|
|
@@ -148,20 +211,53 @@ var classifyStatus = (status) => {
|
|
|
148
211
|
function isTransientJevAskErr(error) {
|
|
149
212
|
return error._tag === "http_retry" || error._tag === "port_threw";
|
|
150
213
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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
|
+
}
|
|
156
223
|
}
|
|
157
|
-
jev;
|
|
158
|
-
};
|
|
159
|
-
function toAskErr(error) {
|
|
160
|
-
if (error instanceof JevAskFailure) return error.jev;
|
|
161
224
|
return { _tag: "port_threw", reason: describeError(error) };
|
|
162
225
|
}
|
|
163
226
|
var DEFAULT_JEV_MODEL = "jev-latest";
|
|
164
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
|
+
}
|
|
165
261
|
function jevAskCmdDef() {
|
|
166
262
|
return runCmdDef();
|
|
167
263
|
}
|
|
@@ -171,9 +267,6 @@ function createJevAsk(config, rng = Math.random) {
|
|
|
171
267
|
};
|
|
172
268
|
const rc = createResilientCall(resilientConfig, rng);
|
|
173
269
|
const model = config.model ?? DEFAULT_JEV_MODEL;
|
|
174
|
-
function isErrDecision(decided) {
|
|
175
|
-
return isJevErr(decided);
|
|
176
|
-
}
|
|
177
270
|
function liveRequest(s, key) {
|
|
178
271
|
const call = s.calls[key];
|
|
179
272
|
if (call?.phase === "running" || call?.phase === "waiting_retry") {
|
|
@@ -184,100 +277,71 @@ function createJevAsk(config, rng = Math.random) {
|
|
|
184
277
|
function init() {
|
|
185
278
|
return rc.init();
|
|
186
279
|
}
|
|
187
|
-
function attempt(s, key, content,
|
|
280
|
+
function attempt(s, key, content, at2) {
|
|
188
281
|
const request = {
|
|
189
282
|
state: content,
|
|
190
283
|
model,
|
|
191
284
|
questions: config.questions
|
|
192
285
|
};
|
|
193
|
-
return rc.attempt(s, key, request,
|
|
194
|
-
}
|
|
195
|
-
function succeed(s,
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
source: "fallback"
|
|
209
|
-
},
|
|
210
|
-
at
|
|
286
|
+
return rc.attempt(s, key, request, at2);
|
|
287
|
+
}
|
|
288
|
+
function succeed(s, msg) {
|
|
289
|
+
const { call, cmds } = rc.settle(s, msg);
|
|
290
|
+
return [call, cmds];
|
|
291
|
+
}
|
|
292
|
+
function settleFromFallback(s, key, request, fallback, at2) {
|
|
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,
|
|
300
|
+
at: at2
|
|
211
301
|
});
|
|
302
|
+
return [call, cmds];
|
|
212
303
|
}
|
|
213
|
-
function
|
|
214
|
-
|
|
215
|
-
|
|
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);
|
|
216
309
|
}
|
|
217
310
|
const request = liveRequest(s, key);
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
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];
|
|
222
314
|
}
|
|
223
315
|
return settleFromFallback(s, key, request, config.fallback, msg.at);
|
|
224
316
|
}
|
|
225
317
|
function onTimer(s, msg) {
|
|
226
318
|
return rc.onTimer(s, msg);
|
|
227
319
|
}
|
|
228
|
-
function
|
|
229
|
-
return rc.
|
|
230
|
-
}
|
|
231
|
-
async function ask(request, signal) {
|
|
232
|
-
if (config.port === void 0) {
|
|
233
|
-
if (config.fallback === void 0) {
|
|
234
|
-
throw new JevAskFailure({ _tag: "no_answer_path" });
|
|
235
|
-
}
|
|
236
|
-
const decided = config.fallback(request);
|
|
237
|
-
if (isErrDecision(decided)) throw new JevAskFailure(decided);
|
|
238
|
-
return {
|
|
239
|
-
answers: decided,
|
|
240
|
-
model: request.model,
|
|
241
|
-
usage: NO_USAGE,
|
|
242
|
-
source: "fallback"
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
const { status, body } = await config.port(request, signal);
|
|
246
|
-
const kind = classifyStatus(status);
|
|
247
|
-
if (kind === "retry")
|
|
248
|
-
throw new JevAskFailure({ _tag: "http_retry", status });
|
|
249
|
-
if (kind === "terminal") {
|
|
250
|
-
throw new JevAskFailure({ _tag: "http_terminal", status });
|
|
251
|
-
}
|
|
252
|
-
const parsed = parseAnswers(config.questions, body);
|
|
253
|
-
if (!parsed.ok) throw new JevAskFailure(parsed.error);
|
|
254
|
-
return {
|
|
255
|
-
answers: parsed.answers,
|
|
256
|
-
model: parsed.model,
|
|
257
|
-
usage: parsed.usage,
|
|
258
|
-
source: "port"
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
const resilientRunHandler = rc.handlers({
|
|
262
|
-
run: (request) => ask(request)
|
|
263
|
-
}).resilient_run;
|
|
264
|
-
async function settleOf(cmd) {
|
|
265
|
-
const settle = await resilientRunHandler(cmd, {});
|
|
266
|
-
if (settle.type === MsgType.ResilientOk) return settle;
|
|
267
|
-
return {
|
|
268
|
-
type: MsgType.ResilientErr,
|
|
269
|
-
key: settle.key,
|
|
270
|
-
error: toAskErr(settle.error),
|
|
271
|
-
at: settle.at
|
|
272
|
-
};
|
|
320
|
+
function deadlines(s) {
|
|
321
|
+
return rc.deadlines(s);
|
|
273
322
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
323
|
+
return {
|
|
324
|
+
name: rc.name,
|
|
325
|
+
/** The `Cmd.define`d run Cmd — list it in the machine's `cmds`. */
|
|
326
|
+
run: rc.run,
|
|
327
|
+
init,
|
|
328
|
+
attempt,
|
|
329
|
+
succeed,
|
|
330
|
+
fail: fail2,
|
|
331
|
+
onTimer,
|
|
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)
|
|
341
|
+
};
|
|
278
342
|
}
|
|
279
343
|
function liftJevAsk(state, result) {
|
|
280
|
-
return
|
|
344
|
+
return liftSlice("resilience", state, result);
|
|
281
345
|
}
|
|
282
346
|
|
|
283
347
|
// src/internal/jev/classify-batch/index.ts
|
|
@@ -346,75 +410,98 @@ function createClassifyBatch(config) {
|
|
|
346
410
|
id: cmd.items.map(config.keyOf).join("\0"),
|
|
347
411
|
items: cmd.items
|
|
348
412
|
}));
|
|
349
|
-
|
|
350
|
-
return [{ ...state, fanOut: next }, cmds];
|
|
413
|
+
return liftSlice("fanOut", state, fanOut.scatter(state.fanOut, batches));
|
|
351
414
|
}
|
|
352
|
-
function add(state, item,
|
|
415
|
+
function add(state, item, at2) {
|
|
353
416
|
const key = config.keyOf(item);
|
|
354
|
-
if (has(state.cache, key,
|
|
417
|
+
if (has(state.cache, key, at2)) return [state, []];
|
|
355
418
|
if (keysInFlight(state).has(key)) return [state, []];
|
|
356
419
|
const failed = { ...state.failed };
|
|
357
420
|
delete failed[key];
|
|
358
|
-
const [
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return scatter(
|
|
421
|
+
const [buffered, flushed] = liftSlice(
|
|
422
|
+
"window",
|
|
423
|
+
{ ...state, failed },
|
|
424
|
+
window.add(state.window, item, at2)
|
|
425
|
+
);
|
|
426
|
+
return scatter(buffered, flushed);
|
|
427
|
+
}
|
|
428
|
+
function onWindow(state, at2) {
|
|
429
|
+
const [closed, flushed] = liftSlice(
|
|
430
|
+
"window",
|
|
431
|
+
state,
|
|
432
|
+
window.onWindow(state.window, at2)
|
|
433
|
+
);
|
|
434
|
+
return scatter(closed, flushed);
|
|
364
435
|
}
|
|
365
436
|
function onBatchOk(state, msg) {
|
|
366
437
|
let cache = state.cache;
|
|
367
|
-
for (const [key, answer] of Object.entries(msg.
|
|
438
|
+
for (const [key, answer] of Object.entries(msg.value.answers)) {
|
|
368
439
|
cache = set(cache, key, answer, msg.at, config.ttlMs);
|
|
369
440
|
}
|
|
370
441
|
const failed = { ...state.failed };
|
|
371
|
-
for (const key of Object.keys(msg.
|
|
372
|
-
|
|
373
|
-
|
|
442
|
+
for (const key of Object.keys(msg.value.answers)) delete failed[key];
|
|
443
|
+
return liftSlice(
|
|
444
|
+
"fanOut",
|
|
445
|
+
{ ...state, cache, failed },
|
|
446
|
+
fanOut.itemOk(state.fanOut, msg.cmd.key, msg.value)
|
|
447
|
+
);
|
|
374
448
|
}
|
|
375
449
|
function onBatchErr(state, msg) {
|
|
376
|
-
const batch = runningBatch(state, msg.key);
|
|
450
|
+
const batch = runningBatch(state, msg.cmd.key);
|
|
451
|
+
const error = jevAskErrOf(msg.error);
|
|
377
452
|
const failed = { ...state.failed };
|
|
378
453
|
if (batch !== void 0) {
|
|
379
|
-
for (const item of batch.items) failed[config.keyOf(item)] =
|
|
454
|
+
for (const item of batch.items) failed[config.keyOf(item)] = error;
|
|
380
455
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
function
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
456
|
+
return liftSlice(
|
|
457
|
+
"fanOut",
|
|
458
|
+
{ ...state, failed },
|
|
459
|
+
fanOut.itemErr(state.fanOut, msg.cmd.key, error)
|
|
460
|
+
);
|
|
461
|
+
}
|
|
462
|
+
function onEvict(state, at2) {
|
|
463
|
+
return liftSlice("cache", state, [evictExpired(state.cache, at2), []]);
|
|
464
|
+
}
|
|
465
|
+
const ANSWER_ORDER = [
|
|
466
|
+
{
|
|
467
|
+
name: "cache",
|
|
468
|
+
read: ({ state, key, at: at2 }) => {
|
|
469
|
+
const answer = get(state.cache, key, at2);
|
|
470
|
+
return answer === void 0 ? void 0 : { status: "answered", answer };
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
{
|
|
474
|
+
name: "failed",
|
|
475
|
+
read: ({ state, key }) => {
|
|
476
|
+
const error = state.failed[key];
|
|
477
|
+
return error === void 0 ? void 0 : { status: "failed", error };
|
|
478
|
+
}
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
name: "inFlight",
|
|
482
|
+
read: ({ state, key }) => keysInFlight(state).has(key) ? { status: "pending" } : void 0
|
|
483
|
+
}
|
|
484
|
+
];
|
|
485
|
+
function answerFor(state, key, at2) {
|
|
486
|
+
return readInOrder({ state, key, at: at2 }, ANSWER_ORDER, { status: "absent" });
|
|
394
487
|
}
|
|
395
488
|
function subs(state, id = "jev-classify-batch") {
|
|
396
|
-
|
|
397
|
-
if (config.evictEveryMs === void 0) return windowSubs;
|
|
398
|
-
return [...windowSubs, cacheEvictionSub(id, config.evictEveryMs)];
|
|
399
|
-
}
|
|
400
|
-
function subscribers() {
|
|
401
|
-
return { deadline: subscribeBatchWindow, cache: cacheEvictionSubscribe };
|
|
489
|
+
return window.subs(state.window, id);
|
|
402
490
|
}
|
|
403
|
-
function
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
const ask = createJevAsk({
|
|
408
|
-
questions: request.questions,
|
|
409
|
-
...config.port === void 0 ? {} : { port: config.port },
|
|
410
|
-
...config.fallback === void 0 ? {} : { fallback: config.fallback },
|
|
411
|
-
...config.model === void 0 ? {} : { model: config.model }
|
|
412
|
-
});
|
|
413
|
-
return ask.handlers().resilient_run(cmd);
|
|
414
|
-
}
|
|
491
|
+
function subEntries(select, id = "jev-classify-batch") {
|
|
492
|
+
const flush = {
|
|
493
|
+
type: "timer",
|
|
494
|
+
deps: (model) => window.timer(select(model).window, id)
|
|
415
495
|
};
|
|
496
|
+
if (config.evictEveryMs === void 0) return [flush];
|
|
497
|
+
return [flush, cacheEvictionSub(id, config.evictEveryMs)];
|
|
498
|
+
}
|
|
499
|
+
function subscribers() {
|
|
500
|
+
return { cache: cacheEvictionSubscribe };
|
|
416
501
|
}
|
|
417
502
|
return {
|
|
503
|
+
/** The ask Cmd def — list it in the machine's `cmds`. */
|
|
504
|
+
ask: askCmd,
|
|
418
505
|
init,
|
|
419
506
|
add,
|
|
420
507
|
onWindow,
|
|
@@ -423,11 +510,20 @@ function createClassifyBatch(config) {
|
|
|
423
510
|
onEvict,
|
|
424
511
|
answerFor,
|
|
425
512
|
subs,
|
|
513
|
+
subEntries,
|
|
426
514
|
subscribers,
|
|
427
|
-
|
|
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)
|
|
428
524
|
};
|
|
429
525
|
}
|
|
430
526
|
|
|
431
|
-
export { DEFAULT_CLASSIFY_MAX_ITEMS, DEFAULT_JEV_MODEL, JEV_ENDPOINT,
|
|
527
|
+
export { DEFAULT_CLASSIFY_MAX_ITEMS, DEFAULT_JEV_MODEL, JEV_ENDPOINT, classifyStatus, createClassifyBatch, createJevAsk, decodeJevReply, isJevErr, isTransientJevAskErr, jevAskCmdDef, jevAskErrOf, jevCallThrew, jevQuestions, liftJevAsk, offlineJevAnswer, parseAnswers };
|
|
432
528
|
//# sourceMappingURL=index.js.map
|
|
433
529
|
//# sourceMappingURL=index.js.map
|