system-one 0.1.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.
@@ -0,0 +1,259 @@
1
+ //#region src/errors.ts
2
+ /** Messages and details must never contain credentials or request/response bodies. */
3
+ var System1Error = class extends Error {
4
+ _tag;
5
+ details;
6
+ name = "System1Error";
7
+ constructor(_tag, message, details = {}) {
8
+ super(message);
9
+ this._tag = _tag;
10
+ this.details = details;
11
+ }
12
+ };
13
+ function isSystem1Error(value) {
14
+ return value instanceof System1Error;
15
+ }
16
+ function fail(tag, message) {
17
+ throw new System1Error(tag, message);
18
+ }
19
+ //#endregion
20
+ //#region src/core.ts
21
+ /** Copy plain JSON without invoking getters or toJSON; reject lossy serialization. */
22
+ function snapshot(value, tag = "InvalidRequest") {
23
+ const active = /* @__PURE__ */ new Set();
24
+ function visit(input, depth) {
25
+ if (depth > 100) return fail(tag, "JSON nesting exceeds 100 levels");
26
+ if (input === null || typeof input === "string" || typeof input === "boolean") return input;
27
+ if (typeof input === "number" && Number.isFinite(input)) return input;
28
+ if (typeof input !== "object" || input === null) return fail(tag, "Expected a finite, plain JSON value");
29
+ if (active.has(input)) return fail(tag, "Cyclic JSON is not supported");
30
+ if (!Array.isArray(input) && Object.getPrototypeOf(input) !== Object.prototype && Object.getPrototypeOf(input) !== null) return fail(tag, "Only plain objects and arrays are supported");
31
+ active.add(input);
32
+ const descriptors = Object.getOwnPropertyDescriptors(input);
33
+ if (Object.getOwnPropertySymbols(input).length) return fail(tag, "Symbol keys are not JSON");
34
+ const entries = [];
35
+ for (const [key, descriptor] of Object.entries(descriptors)) {
36
+ if (Array.isArray(input) && key === "length") continue;
37
+ if (!descriptor.enumerable || !("value" in descriptor)) return fail(tag, "JSON properties must be enumerable data properties");
38
+ entries.push([key, visit(descriptor.value, depth + 1)]);
39
+ }
40
+ let output;
41
+ if (Array.isArray(input)) {
42
+ if (entries.length !== input.length || entries.some(([key], i) => key !== String(i))) return fail(tag, "Sparse or augmented arrays are not JSON");
43
+ output = entries.map(([, item]) => item);
44
+ } else output = Object.fromEntries(entries);
45
+ active.delete(input);
46
+ return Object.freeze(output);
47
+ }
48
+ return visit(value, 0);
49
+ }
50
+ function record(value, tag = "InvalidResponse") {
51
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return fail(tag, "Expected an object");
52
+ return value;
53
+ }
54
+ function exactKeys(value, allowed, tag) {
55
+ if (Object.keys(value).some((key) => !allowed.includes(key))) fail(tag, "Unexpected fields");
56
+ }
57
+ function own(value, key) {
58
+ return Object.hasOwn(value, key);
59
+ }
60
+ function validateQuestion(value) {
61
+ const q = record(value, "InvalidRequest");
62
+ if (!own(q, "instructions")) fail("InvalidRequest", "Question instructions are required");
63
+ switch (q.kind) {
64
+ case "boolean":
65
+ exactKeys(q, [
66
+ "kind",
67
+ "instructions",
68
+ "criteria"
69
+ ], "InvalidRequest");
70
+ if (q.criteria !== void 0) {
71
+ const criteria = record(q.criteria, "InvalidRequest");
72
+ exactKeys(criteria, ["true", "false"], "InvalidRequest");
73
+ if (!own(criteria, "true") || !own(criteria, "false")) fail("InvalidRequest", "Boolean criteria need true and false descriptions");
74
+ }
75
+ break;
76
+ case "choice": {
77
+ exactKeys(q, [
78
+ "kind",
79
+ "instructions",
80
+ "options"
81
+ ], "InvalidRequest");
82
+ const keys = Object.keys(record(q.options, "InvalidRequest"));
83
+ if (keys.length < 2 || keys.some((key) => !key.trim())) fail("InvalidRequest", "Choice questions need at least two nonempty keys");
84
+ break;
85
+ }
86
+ case "ordinal":
87
+ exactKeys(q, [
88
+ "kind",
89
+ "instructions",
90
+ "levels"
91
+ ], "InvalidRequest");
92
+ if (!Array.isArray(q.levels) || q.levels.length < 2) fail("InvalidRequest", "Ordinal questions need at least two levels");
93
+ break;
94
+ default: fail("InvalidRequest", "Unknown question kind");
95
+ }
96
+ }
97
+ function question(input) {
98
+ const copy = snapshot(input);
99
+ validateQuestion(copy);
100
+ return copy;
101
+ }
102
+ const Question = {
103
+ boolean: (input) => question({
104
+ ...input,
105
+ kind: "boolean"
106
+ }),
107
+ choice: (input) => question({
108
+ ...input,
109
+ kind: "choice"
110
+ }),
111
+ ordinal: (input) => question({
112
+ ...input,
113
+ kind: "ordinal"
114
+ })
115
+ };
116
+ function defineQuestions(input) {
117
+ const copy = record(snapshot(input), "InvalidRequest");
118
+ const keys = Object.keys(copy);
119
+ if (!keys.length || keys.some((key) => !key.trim())) fail("InvalidRequest", "At least one nonempty question name is required");
120
+ for (const item of Object.values(copy)) validateQuestion(item);
121
+ return copy;
122
+ }
123
+ function prepare(request, capabilities) {
124
+ const copy = record(snapshot(request), "InvalidRequest");
125
+ exactKeys(copy, [
126
+ "state",
127
+ "questions",
128
+ "requirements"
129
+ ], "InvalidRequest");
130
+ if (!own(copy, "state")) fail("InvalidRequest", "State is required");
131
+ const questions = defineQuestions(copy.questions);
132
+ if (copy.requirements !== void 0) {
133
+ const req = record(copy.requirements, "InvalidRequest");
134
+ exactKeys(req, ["probabilities"], "InvalidRequest");
135
+ if (req.probabilities !== void 0 && req.probabilities !== "required") fail("InvalidRequest", "Unknown probability requirement");
136
+ }
137
+ if (capabilities.state === "text" && typeof copy.state !== "string") fail("UnsupportedCapability", "Model requires text state");
138
+ if (capabilities.state === "text-or-structured" && (copy.state === null || typeof copy.state === "number" || typeof copy.state === "boolean")) fail("UnsupportedCapability", "Model requires text, object, or array state");
139
+ if (capabilities.maxQuestions !== void 0 && Object.keys(questions).length > capabilities.maxQuestions) fail("UnsupportedCapability", "Too many questions for model");
140
+ for (const q of Object.values(questions)) {
141
+ const capability = capabilities.kinds[q.kind];
142
+ if (!capability) fail("UnsupportedCapability", "Unsupported question kind");
143
+ if (copy.requirements?.probabilities === "required" && !capability.probabilities) fail("UnsupportedCapability", "Model does not provide required probabilities");
144
+ if (capabilities.descriptions === "text") {
145
+ if ([q.instructions, ...q.kind === "choice" ? Object.values(q.options) : q.kind === "ordinal" ? q.levels : Object.values(q.criteria ?? {})].some((x) => typeof x !== "string")) fail("UnsupportedCapability", "Model requires text descriptions");
146
+ }
147
+ }
148
+ return Object.freeze({
149
+ ...copy,
150
+ questions
151
+ });
152
+ }
153
+ function probability(value) {
154
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) fail("InvalidResponse", "Invalid probability");
155
+ }
156
+ /** Absolute sum tolerance; never renormalizes a distribution. */
157
+ const DISTRIBUTION_TOLERANCE = .001;
158
+ function distribution(values) {
159
+ values.forEach(probability);
160
+ if (Math.abs(values.reduce((a, b) => a + b, 0) - 1) > .001) fail("InvalidResponse", "Probabilities do not sum to one");
161
+ }
162
+ function matchingKeys(value, keys) {
163
+ if (Object.keys(value).length !== keys.length || keys.some((key) => !own(value, key))) fail("InvalidResponse", "Answer keys do not match the request");
164
+ }
165
+ /** Validates untrusted normalized output before recovering question-specific types. */
166
+ function validateResult(request, decoded, identity, capabilities) {
167
+ const safe = record(snapshot(decoded, "InvalidResponse"));
168
+ exactKeys(safe, [
169
+ "answers",
170
+ "resolvedModel",
171
+ "requestId",
172
+ "usage"
173
+ ], "InvalidResponse");
174
+ const answers = record(safe.answers);
175
+ matchingKeys(answers, Object.keys(request.questions));
176
+ for (const [key, q] of Object.entries(request.questions)) {
177
+ const a = record(answers[key]);
178
+ if (a.kind !== q.kind) fail("InvalidResponse", "Answer kind does not match question");
179
+ if (a.confidence !== void 0) {
180
+ const c = record(a.confidence);
181
+ exactKeys(c, ["value", "definition"], "InvalidResponse");
182
+ probability(c.value);
183
+ if (typeof c.definition !== "string" || !c.definition.trim()) fail("InvalidResponse", "Confidence needs a definition");
184
+ } else if (capabilities.kinds[q.kind]?.confidence) fail("InvalidResponse", "Missing advertised confidence");
185
+ const required = request.requirements?.probabilities === "required" || capabilities.kinds[q.kind]?.probabilities;
186
+ if (q.kind === "boolean") {
187
+ exactKeys(a, [
188
+ "kind",
189
+ "probabilityTrue",
190
+ "predictedValue",
191
+ "confidence"
192
+ ], "InvalidResponse");
193
+ if (a.probabilityTrue !== void 0) probability(a.probabilityTrue);
194
+ else if (required) fail("InvalidResponse", "Missing probability of true");
195
+ if (a.predictedValue !== void 0 && typeof a.predictedValue !== "boolean") fail("InvalidResponse", "Invalid boolean prediction");
196
+ if (a.probabilityTrue === void 0 && a.predictedValue === void 0) fail("InvalidResponse", "Empty boolean answer");
197
+ } else if (q.kind === "choice") {
198
+ exactKeys(a, [
199
+ "kind",
200
+ "value",
201
+ "probabilities",
202
+ "confidence"
203
+ ], "InvalidResponse");
204
+ if (typeof a.value !== "string" || !own(q.options, a.value)) fail("InvalidResponse", "Unknown choice value");
205
+ if (a.probabilities !== void 0) {
206
+ const probabilities = record(a.probabilities);
207
+ matchingKeys(probabilities, Object.keys(q.options));
208
+ distribution(Object.values(probabilities));
209
+ } else if (required) fail("InvalidResponse", "Missing choice probabilities");
210
+ } else {
211
+ exactKeys(a, [
212
+ "kind",
213
+ "selectedIndex",
214
+ "expectedIndex",
215
+ "probabilities",
216
+ "confidence"
217
+ ], "InvalidResponse");
218
+ for (const field of ["selectedIndex", "expectedIndex"]) {
219
+ const n = a[field];
220
+ if (n !== void 0 && (typeof n !== "number" || !Number.isFinite(n) || n < 0 || n > q.levels.length - 1 || field === "selectedIndex" && !Number.isInteger(n))) fail("InvalidResponse", "Invalid ordinal index");
221
+ }
222
+ if (a.probabilities !== void 0) {
223
+ if (!Array.isArray(a.probabilities) || a.probabilities.length !== q.levels.length) fail("InvalidResponse", "Ordinal distribution has wrong length");
224
+ distribution(a.probabilities);
225
+ } else if (required) fail("InvalidResponse", "Missing ordinal probabilities");
226
+ if (a.selectedIndex === void 0 && a.expectedIndex === void 0 && a.probabilities === void 0) fail("InvalidResponse", "Empty ordinal answer");
227
+ }
228
+ }
229
+ for (const key of ["resolvedModel", "requestId"]) if (safe[key] !== void 0 && (typeof safe[key] !== "string" || !safe[key].trim())) fail("InvalidResponse", "Invalid response metadata");
230
+ if (safe.usage !== void 0) {
231
+ const usage = record(safe.usage);
232
+ exactKeys(usage, [
233
+ "inputTokens",
234
+ "outputTokens",
235
+ "totalTokens"
236
+ ], "InvalidResponse");
237
+ for (const n of Object.values(usage)) if (typeof n !== "number" || !Number.isSafeInteger(n) || n < 0) fail("InvalidResponse", "Invalid token usage");
238
+ }
239
+ return Object.freeze({
240
+ answers,
241
+ model: Object.freeze({
242
+ adapter: identity.adapter,
243
+ requestedModel: identity.model,
244
+ ...safe.resolvedModel === void 0 ? {} : { resolvedModel: safe.resolvedModel }
245
+ }),
246
+ ...safe.requestId === void 0 ? {} : { requestId: safe.requestId },
247
+ ...safe.usage === void 0 ? {} : { usage: safe.usage }
248
+ });
249
+ }
250
+ /** Explicit derived statistic, not a provider-reported prediction. */
251
+ function expectedIndex(probabilities) {
252
+ if (probabilities.length < 2) fail("InvalidRequest", "At least two levels are required");
253
+ distribution([...probabilities]);
254
+ return probabilities.reduce((sum, p, i) => sum + p * i, 0);
255
+ }
256
+ //#endregion
257
+ export { prepare as a, validateResult as c, expectedIndex as i, System1Error as l, Question as n, record as o, defineQuestions as r, snapshot as s, DISTRIBUTION_TOLERANCE as t, isSystem1Error as u };
258
+
259
+ //# sourceMappingURL=core-D7i-WVU7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-D7i-WVU7.mjs","names":[],"sources":["../src/errors.ts","../src/core.ts"],"sourcesContent":["export type ErrorTag =\n | \"InvalidRequest\"\n | \"UnsupportedCapability\"\n | \"AuthenticationError\"\n | \"QuotaExceeded\"\n | \"RateLimited\"\n | \"ContextLimitExceeded\"\n | \"TransportError\"\n | \"InvalidResponse\"\n | \"ProviderError\";\n\nexport interface ErrorDetails {\n readonly status?: number;\n readonly providerCode?: string;\n readonly requestId?: string;\n readonly retryAfterMs?: number;\n}\n\n/** Messages and details must never contain credentials or request/response bodies. */\nexport class System1Error extends Error {\n readonly name = \"System1Error\";\n constructor(\n readonly _tag: ErrorTag,\n message: string,\n readonly details: ErrorDetails = {},\n ) {\n super(message);\n }\n}\n\nexport function isSystem1Error(value: unknown): value is System1Error {\n return value instanceof System1Error;\n}\n\nexport function fail(tag: ErrorTag, message: string): never {\n throw new System1Error(tag, message);\n}\n","import { fail } from \"./errors.js\";\nexport { System1Error, isSystem1Error } from \"./errors.js\";\nexport type { ErrorTag, ErrorDetails } from \"./errors.js\";\n\nexport type JsonValue =\n | null\n | boolean\n | number\n | string\n | readonly JsonValue[]\n | { readonly [key: string]: JsonValue };\nexport type Description = JsonValue;\nexport type Kind = \"boolean\" | \"choice\" | \"ordinal\";\nexport interface BooleanQuestion {\n readonly kind: \"boolean\";\n readonly instructions: Description;\n readonly criteria?: { readonly true: Description; readonly false: Description };\n}\nexport interface ChoiceQuestion<K extends string = string> {\n readonly kind: \"choice\";\n readonly instructions: Description;\n readonly options: Readonly<Record<K, Description>>;\n}\nexport interface OrdinalQuestion {\n readonly kind: \"ordinal\";\n readonly instructions: Description;\n readonly levels: readonly Description[];\n}\nexport type QuestionDefinition = BooleanQuestion | ChoiceQuestion | OrdinalQuestion;\nexport type Questions = Readonly<Record<string, QuestionDefinition>>;\n\n/** Copy plain JSON without invoking getters or toJSON; reject lossy serialization. */\nexport function snapshot(\n value: unknown,\n tag: \"InvalidRequest\" | \"InvalidResponse\" = \"InvalidRequest\",\n): JsonValue {\n const active = new Set<object>();\n function visit(input: unknown, depth: number): JsonValue {\n if (depth > 100) return fail(tag, \"JSON nesting exceeds 100 levels\");\n if (input === null || typeof input === \"string\" || typeof input === \"boolean\") return input;\n if (typeof input === \"number\" && Number.isFinite(input)) return input;\n if (typeof input !== \"object\" || input === null)\n return fail(tag, \"Expected a finite, plain JSON value\");\n if (active.has(input)) return fail(tag, \"Cyclic JSON is not supported\");\n if (\n !Array.isArray(input) &&\n Object.getPrototypeOf(input) !== Object.prototype &&\n Object.getPrototypeOf(input) !== null\n ) {\n return fail(tag, \"Only plain objects and arrays are supported\");\n }\n active.add(input);\n const descriptors = Object.getOwnPropertyDescriptors(input);\n if (Object.getOwnPropertySymbols(input).length) return fail(tag, \"Symbol keys are not JSON\");\n const entries: [string, JsonValue][] = [];\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (Array.isArray(input) && key === \"length\") continue;\n if (!descriptor.enumerable || !(\"value\" in descriptor))\n return fail(tag, \"JSON properties must be enumerable data properties\");\n entries.push([key, visit(descriptor.value, depth + 1)]);\n }\n let output: JsonValue;\n if (Array.isArray(input)) {\n if (entries.length !== input.length || entries.some(([key], i) => key !== String(i)))\n return fail(tag, \"Sparse or augmented arrays are not JSON\");\n output = entries.map(([, item]) => item);\n } else output = Object.fromEntries(entries);\n active.delete(input);\n return Object.freeze(output);\n }\n return visit(value, 0);\n}\n\nexport function record(\n value: unknown,\n tag: \"InvalidRequest\" | \"InvalidResponse\" = \"InvalidResponse\",\n): Record<string, unknown> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value))\n return fail(tag, \"Expected an object\");\n return value as Record<string, unknown>;\n}\n\nfunction exactKeys(\n value: Record<string, unknown>,\n allowed: readonly string[],\n tag: \"InvalidRequest\" | \"InvalidResponse\",\n): void {\n if (Object.keys(value).some((key) => !allowed.includes(key))) fail(tag, \"Unexpected fields\");\n}\nfunction own(value: object, key: PropertyKey): boolean {\n return Object.hasOwn(value, key);\n}\nfunction validateQuestion(value: unknown): void {\n const q = record(value, \"InvalidRequest\");\n if (!own(q, \"instructions\")) fail(\"InvalidRequest\", \"Question instructions are required\");\n switch (q.kind) {\n case \"boolean\": {\n exactKeys(q, [\"kind\", \"instructions\", \"criteria\"], \"InvalidRequest\");\n if (q.criteria !== undefined) {\n const criteria = record(q.criteria, \"InvalidRequest\");\n exactKeys(criteria, [\"true\", \"false\"], \"InvalidRequest\");\n if (!own(criteria, \"true\") || !own(criteria, \"false\"))\n fail(\"InvalidRequest\", \"Boolean criteria need true and false descriptions\");\n }\n break;\n }\n case \"choice\": {\n exactKeys(q, [\"kind\", \"instructions\", \"options\"], \"InvalidRequest\");\n const keys = Object.keys(record(q.options, \"InvalidRequest\"));\n if (keys.length < 2 || keys.some((key) => !key.trim()))\n fail(\"InvalidRequest\", \"Choice questions need at least two nonempty keys\");\n break;\n }\n case \"ordinal\":\n exactKeys(q, [\"kind\", \"instructions\", \"levels\"], \"InvalidRequest\");\n if (!Array.isArray(q.levels) || q.levels.length < 2)\n fail(\"InvalidRequest\", \"Ordinal questions need at least two levels\");\n break;\n default:\n fail(\"InvalidRequest\", \"Unknown question kind\");\n }\n}\nfunction question<T extends QuestionDefinition>(input: T): T {\n const copy = snapshot(input);\n validateQuestion(copy);\n return copy as unknown as T;\n}\nexport const Question = {\n boolean: (input: Omit<BooleanQuestion, \"kind\">): BooleanQuestion =>\n question({ ...input, kind: \"boolean\" }),\n choice: <const O extends Readonly<Record<string, Description>>>(input: {\n readonly instructions: Description;\n readonly options: O;\n }): ChoiceQuestion<Extract<keyof O, string>> => question({ ...input, kind: \"choice\" }),\n ordinal: (input: Omit<OrdinalQuestion, \"kind\">): OrdinalQuestion =>\n question({ ...input, kind: \"ordinal\" }),\n} as const;\n\nexport function defineQuestions<const Q extends Questions>(input: Q): Q {\n const copy = record(snapshot(input), \"InvalidRequest\");\n const keys = Object.keys(copy);\n if (!keys.length || keys.some((key) => !key.trim()))\n fail(\"InvalidRequest\", \"At least one nonempty question name is required\");\n for (const item of Object.values(copy)) validateQuestion(item);\n return copy as Q;\n}\n\nexport interface ReportedConfidence {\n readonly value: number;\n readonly definition: string;\n}\ntype Confidence = { readonly confidence?: ReportedConfidence };\nexport type BooleanAnswer = Confidence & { readonly kind: \"boolean\" } & (\n | { readonly probabilityTrue: number; readonly predictedValue?: boolean }\n | { readonly probabilityTrue?: number; readonly predictedValue: boolean }\n );\nexport interface ChoiceAnswer<K extends string = string> extends Confidence {\n readonly kind: \"choice\";\n readonly value: K;\n readonly probabilities?: Readonly<Record<K, number>>;\n}\nexport type OrdinalAnswer = Confidence & { readonly kind: \"ordinal\" } & (\n | {\n readonly selectedIndex: number;\n readonly expectedIndex?: number;\n readonly probabilities?: readonly number[];\n }\n | {\n readonly selectedIndex?: number;\n readonly expectedIndex: number;\n readonly probabilities?: readonly number[];\n }\n | {\n readonly selectedIndex?: number;\n readonly expectedIndex?: number;\n readonly probabilities: readonly number[];\n }\n );\nexport interface Requirements {\n readonly probabilities?: \"required\";\n}\nexport type AnswerFor<\n Q extends QuestionDefinition,\n R extends Requirements = {},\n> = Q extends BooleanQuestion\n ? BooleanAnswer &\n (R extends { probabilities: \"required\" } ? { readonly probabilityTrue: number } : {})\n : Q extends ChoiceQuestion<infer K>\n ? ChoiceAnswer<K> &\n (R extends { probabilities: \"required\" }\n ? { readonly probabilities: Readonly<Record<K, number>> }\n : {})\n : OrdinalAnswer &\n (R extends { probabilities: \"required\" }\n ? { readonly probabilities: readonly number[] }\n : {});\nexport type Answers<Q extends Questions, R extends Requirements = {}> = {\n readonly [K in keyof Q]: AnswerFor<Q[K], R>;\n};\nexport interface EvaluationRequest<\n Q extends Questions = Questions,\n R extends Requirements = Requirements,\n> {\n readonly state: JsonValue;\n readonly questions: Q;\n readonly requirements?: R;\n}\nexport interface EvaluationResult<Q extends Questions, R extends Requirements = {}> {\n readonly answers: Answers<Q, R>;\n readonly model: {\n readonly adapter: string;\n readonly requestedModel: string;\n readonly resolvedModel?: string;\n };\n readonly requestId?: string;\n readonly usage?: {\n readonly inputTokens?: number;\n readonly outputTokens?: number;\n readonly totalTokens?: number;\n };\n}\nexport interface KindCapability {\n readonly probabilities: boolean;\n readonly confidence: boolean;\n}\nexport interface Capabilities {\n readonly kinds: Readonly<Partial<Record<Kind, KindCapability>>>;\n readonly state: \"json\" | \"text-or-structured\" | \"text\";\n readonly descriptions: \"json\" | \"text\";\n readonly maxQuestions?: number;\n /** Informational only. No tokenizer is assumed; providers enforce token limits. */\n readonly context?: readonly { readonly scope: string; readonly tokens: number }[];\n}\n\nexport function prepare<Q extends Questions, R extends Requirements>(\n request: EvaluationRequest<Q, R>,\n capabilities: Capabilities,\n): EvaluationRequest<Q, R> {\n const copy = record(snapshot(request), \"InvalidRequest\");\n exactKeys(copy, [\"state\", \"questions\", \"requirements\"], \"InvalidRequest\");\n if (!own(copy, \"state\")) fail(\"InvalidRequest\", \"State is required\");\n const questions = defineQuestions(copy.questions as Q);\n if (copy.requirements !== undefined) {\n const req = record(copy.requirements, \"InvalidRequest\");\n exactKeys(req, [\"probabilities\"], \"InvalidRequest\");\n if (req.probabilities !== undefined && req.probabilities !== \"required\")\n fail(\"InvalidRequest\", \"Unknown probability requirement\");\n }\n if (capabilities.state === \"text\" && typeof copy.state !== \"string\")\n fail(\"UnsupportedCapability\", \"Model requires text state\");\n if (\n capabilities.state === \"text-or-structured\" &&\n (copy.state === null || typeof copy.state === \"number\" || typeof copy.state === \"boolean\")\n )\n fail(\"UnsupportedCapability\", \"Model requires text, object, or array state\");\n if (\n capabilities.maxQuestions !== undefined &&\n Object.keys(questions).length > capabilities.maxQuestions\n )\n fail(\"UnsupportedCapability\", \"Too many questions for model\");\n for (const q of Object.values(questions)) {\n const capability = capabilities.kinds[q.kind];\n if (!capability) fail(\"UnsupportedCapability\", \"Unsupported question kind\");\n if (\n (copy.requirements as Requirements | undefined)?.probabilities === \"required\" &&\n !capability.probabilities\n )\n fail(\"UnsupportedCapability\", \"Model does not provide required probabilities\");\n if (capabilities.descriptions === \"text\") {\n const descriptions = [\n q.instructions,\n ...(q.kind === \"choice\"\n ? Object.values(q.options)\n : q.kind === \"ordinal\"\n ? q.levels\n : Object.values(q.criteria ?? {})),\n ];\n if (descriptions.some((x) => typeof x !== \"string\"))\n fail(\"UnsupportedCapability\", \"Model requires text descriptions\");\n }\n }\n return Object.freeze({ ...copy, questions }) as unknown as EvaluationRequest<Q, R>;\n}\n\nfunction probability(value: unknown): asserts value is number {\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0 || value > 1)\n fail(\"InvalidResponse\", \"Invalid probability\");\n}\n/** Absolute sum tolerance; never renormalizes a distribution. */\nexport const DISTRIBUTION_TOLERANCE = 0.001;\nfunction distribution(values: unknown[]): void {\n values.forEach(probability);\n if (Math.abs((values as number[]).reduce((a, b) => a + b, 0) - 1) > DISTRIBUTION_TOLERANCE)\n fail(\"InvalidResponse\", \"Probabilities do not sum to one\");\n}\nfunction matchingKeys(value: Record<string, unknown>, keys: readonly string[]): void {\n if (Object.keys(value).length !== keys.length || keys.some((key) => !own(value, key)))\n fail(\"InvalidResponse\", \"Answer keys do not match the request\");\n}\nexport interface DecodedEvaluation {\n readonly answers: unknown;\n readonly resolvedModel?: string;\n readonly requestId?: string;\n readonly usage?: EvaluationResult<Questions>[\"usage\"];\n}\n\n/** Validates untrusted normalized output before recovering question-specific types. */\nexport function validateResult<const Q extends Questions, const R extends Requirements>(\n request: EvaluationRequest<Q, R>,\n decoded: DecodedEvaluation,\n identity: { readonly adapter: string; readonly model: string },\n capabilities: Capabilities,\n): EvaluationResult<Q, R> {\n const safe = record(snapshot(decoded, \"InvalidResponse\"));\n exactKeys(safe, [\"answers\", \"resolvedModel\", \"requestId\", \"usage\"], \"InvalidResponse\");\n const answers = record(safe.answers);\n matchingKeys(answers, Object.keys(request.questions));\n for (const [key, q] of Object.entries(request.questions)) {\n const a = record(answers[key]);\n if (a.kind !== q.kind) fail(\"InvalidResponse\", \"Answer kind does not match question\");\n if (a.confidence !== undefined) {\n const c = record(a.confidence);\n exactKeys(c, [\"value\", \"definition\"], \"InvalidResponse\");\n probability(c.value);\n if (typeof c.definition !== \"string\" || !c.definition.trim())\n fail(\"InvalidResponse\", \"Confidence needs a definition\");\n } else if (capabilities.kinds[q.kind]?.confidence)\n fail(\"InvalidResponse\", \"Missing advertised confidence\");\n const required =\n request.requirements?.probabilities === \"required\" ||\n capabilities.kinds[q.kind]?.probabilities;\n if (q.kind === \"boolean\") {\n exactKeys(a, [\"kind\", \"probabilityTrue\", \"predictedValue\", \"confidence\"], \"InvalidResponse\");\n if (a.probabilityTrue !== undefined) probability(a.probabilityTrue);\n else if (required) fail(\"InvalidResponse\", \"Missing probability of true\");\n if (a.predictedValue !== undefined && typeof a.predictedValue !== \"boolean\")\n fail(\"InvalidResponse\", \"Invalid boolean prediction\");\n if (a.probabilityTrue === undefined && a.predictedValue === undefined)\n fail(\"InvalidResponse\", \"Empty boolean answer\");\n } else if (q.kind === \"choice\") {\n exactKeys(a, [\"kind\", \"value\", \"probabilities\", \"confidence\"], \"InvalidResponse\");\n if (typeof a.value !== \"string\" || !own(q.options, a.value))\n fail(\"InvalidResponse\", \"Unknown choice value\");\n if (a.probabilities !== undefined) {\n const probabilities = record(a.probabilities);\n matchingKeys(probabilities, Object.keys(q.options));\n distribution(Object.values(probabilities));\n } else if (required) fail(\"InvalidResponse\", \"Missing choice probabilities\");\n } else {\n exactKeys(\n a,\n [\"kind\", \"selectedIndex\", \"expectedIndex\", \"probabilities\", \"confidence\"],\n \"InvalidResponse\",\n );\n for (const field of [\"selectedIndex\", \"expectedIndex\"]) {\n const n = a[field];\n if (\n n !== undefined &&\n (typeof n !== \"number\" ||\n !Number.isFinite(n) ||\n n < 0 ||\n n > q.levels.length - 1 ||\n (field === \"selectedIndex\" && !Number.isInteger(n)))\n )\n fail(\"InvalidResponse\", \"Invalid ordinal index\");\n }\n if (a.probabilities !== undefined) {\n if (!Array.isArray(a.probabilities) || a.probabilities.length !== q.levels.length)\n fail(\"InvalidResponse\", \"Ordinal distribution has wrong length\");\n distribution(a.probabilities);\n } else if (required) fail(\"InvalidResponse\", \"Missing ordinal probabilities\");\n if (\n a.selectedIndex === undefined &&\n a.expectedIndex === undefined &&\n a.probabilities === undefined\n )\n fail(\"InvalidResponse\", \"Empty ordinal answer\");\n }\n }\n for (const key of [\"resolvedModel\", \"requestId\"]) {\n if (safe[key] !== undefined && (typeof safe[key] !== \"string\" || !safe[key].trim()))\n fail(\"InvalidResponse\", \"Invalid response metadata\");\n }\n if (safe.usage !== undefined) {\n const usage = record(safe.usage);\n exactKeys(usage, [\"inputTokens\", \"outputTokens\", \"totalTokens\"], \"InvalidResponse\");\n for (const n of Object.values(usage))\n if (typeof n !== \"number\" || !Number.isSafeInteger(n) || n < 0)\n fail(\"InvalidResponse\", \"Invalid token usage\");\n }\n return Object.freeze({\n answers,\n model: Object.freeze({\n adapter: identity.adapter,\n requestedModel: identity.model,\n ...(safe.resolvedModel === undefined ? {} : { resolvedModel: safe.resolvedModel }),\n }),\n ...(safe.requestId === undefined ? {} : { requestId: safe.requestId }),\n ...(safe.usage === undefined ? {} : { usage: safe.usage }),\n }) as unknown as EvaluationResult<Q, R>;\n}\n\n/** Explicit derived statistic, not a provider-reported prediction. */\nexport function expectedIndex(probabilities: readonly number[]): number {\n if (probabilities.length < 2) fail(\"InvalidRequest\", \"At least two levels are required\");\n distribution([...probabilities]);\n return probabilities.reduce((sum, p, i) => sum + p * i, 0);\n}\n"],"mappings":";;AAmBA,IAAa,eAAb,cAAkC,MAAM;CAG3B;CAEA;CAJX,OAAgB;CAChB,YACE,MACA,SACA,UAAiC,CAAC,GAClC;EACA,MAAM,OAAO;EAJJ,KAAA,OAAA;EAEA,KAAA,UAAA;CAGX;AACF;AAEA,SAAgB,eAAe,OAAuC;CACpE,OAAO,iBAAiB;AAC1B;AAEA,SAAgB,KAAK,KAAe,SAAwB;CAC1D,MAAM,IAAI,aAAa,KAAK,OAAO;AACrC;;;;ACJA,SAAgB,SACd,OACA,MAA4C,kBACjC;CACX,MAAM,yBAAS,IAAI,IAAY;CAC/B,SAAS,MAAM,OAAgB,OAA0B;EACvD,IAAI,QAAQ,KAAK,OAAO,KAAK,KAAK,iCAAiC;EACnE,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,OAAO,UAAU,WAAW,OAAO;EACtF,IAAI,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,GAAG,OAAO;EAChE,IAAI,OAAO,UAAU,YAAY,UAAU,MACzC,OAAO,KAAK,KAAK,qCAAqC;EACxD,IAAI,OAAO,IAAI,KAAK,GAAG,OAAO,KAAK,KAAK,8BAA8B;EACtE,IACE,CAAC,MAAM,QAAQ,KAAK,KACpB,OAAO,eAAe,KAAK,MAAM,OAAO,aACxC,OAAO,eAAe,KAAK,MAAM,MAEjC,OAAO,KAAK,KAAK,6CAA6C;EAEhE,OAAO,IAAI,KAAK;EAChB,MAAM,cAAc,OAAO,0BAA0B,KAAK;EAC1D,IAAI,OAAO,sBAAsB,KAAK,CAAC,CAAC,QAAQ,OAAO,KAAK,KAAK,0BAA0B;EAC3F,MAAM,UAAiC,CAAC;EACxC,KAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,WAAW,GAAG;GAC3D,IAAI,MAAM,QAAQ,KAAK,KAAK,QAAQ,UAAU;GAC9C,IAAI,CAAC,WAAW,cAAc,EAAE,WAAW,aACzC,OAAO,KAAK,KAAK,oDAAoD;GACvE,QAAQ,KAAK,CAAC,KAAK,MAAM,WAAW,OAAO,QAAQ,CAAC,CAAC,CAAC;EACxD;EACA,IAAI;EACJ,IAAI,MAAM,QAAQ,KAAK,GAAG;GACxB,IAAI,QAAQ,WAAW,MAAM,UAAU,QAAQ,MAAM,CAAC,MAAM,MAAM,QAAQ,OAAO,CAAC,CAAC,GACjF,OAAO,KAAK,KAAK,yCAAyC;GAC5D,SAAS,QAAQ,KAAK,GAAG,UAAU,IAAI;EACzC,OAAO,SAAS,OAAO,YAAY,OAAO;EAC1C,OAAO,OAAO,KAAK;EACnB,OAAO,OAAO,OAAO,MAAM;CAC7B;CACA,OAAO,MAAM,OAAO,CAAC;AACvB;AAEA,SAAgB,OACd,OACA,MAA4C,mBACnB;CACzB,IAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GACpE,OAAO,KAAK,KAAK,oBAAoB;CACvC,OAAO;AACT;AAEA,SAAS,UACP,OACA,SACA,KACM;CACN,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,MAAM,QAAQ,CAAC,QAAQ,SAAS,GAAG,CAAC,GAAG,KAAK,KAAK,mBAAmB;AAC7F;AACA,SAAS,IAAI,OAAe,KAA2B;CACrD,OAAO,OAAO,OAAO,OAAO,GAAG;AACjC;AACA,SAAS,iBAAiB,OAAsB;CAC9C,MAAM,IAAI,OAAO,OAAO,gBAAgB;CACxC,IAAI,CAAC,IAAI,GAAG,cAAc,GAAG,KAAK,kBAAkB,oCAAoC;CACxF,QAAQ,EAAE,MAAV;EACE,KAAK;GACH,UAAU,GAAG;IAAC;IAAQ;IAAgB;GAAU,GAAG,gBAAgB;GACnE,IAAI,EAAE,aAAa,KAAA,GAAW;IAC5B,MAAM,WAAW,OAAO,EAAE,UAAU,gBAAgB;IACpD,UAAU,UAAU,CAAC,QAAQ,OAAO,GAAG,gBAAgB;IACvD,IAAI,CAAC,IAAI,UAAU,MAAM,KAAK,CAAC,IAAI,UAAU,OAAO,GAClD,KAAK,kBAAkB,mDAAmD;GAC9E;GACA;EAEF,KAAK,UAAU;GACb,UAAU,GAAG;IAAC;IAAQ;IAAgB;GAAS,GAAG,gBAAgB;GAClE,MAAM,OAAO,OAAO,KAAK,OAAO,EAAE,SAAS,gBAAgB,CAAC;GAC5D,IAAI,KAAK,SAAS,KAAK,KAAK,MAAM,QAAQ,CAAC,IAAI,KAAK,CAAC,GACnD,KAAK,kBAAkB,kDAAkD;GAC3E;EACF;EACA,KAAK;GACH,UAAU,GAAG;IAAC;IAAQ;IAAgB;GAAQ,GAAG,gBAAgB;GACjE,IAAI,CAAC,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,SAAS,GAChD,KAAK,kBAAkB,4CAA4C;GACrE;EACF,SACE,KAAK,kBAAkB,uBAAuB;CAClD;AACF;AACA,SAAS,SAAuC,OAAa;CAC3D,MAAM,OAAO,SAAS,KAAK;CAC3B,iBAAiB,IAAI;CACrB,OAAO;AACT;AACA,MAAa,WAAW;CACtB,UAAU,UACR,SAAS;EAAE,GAAG;EAAO,MAAM;CAAU,CAAC;CACxC,SAAgE,UAGhB,SAAS;EAAE,GAAG;EAAO,MAAM;CAAS,CAAC;CACrF,UAAU,UACR,SAAS;EAAE,GAAG;EAAO,MAAM;CAAU,CAAC;AAC1C;AAEA,SAAgB,gBAA2C,OAAa;CACtE,MAAM,OAAO,OAAO,SAAS,KAAK,GAAG,gBAAgB;CACrD,MAAM,OAAO,OAAO,KAAK,IAAI;CAC7B,IAAI,CAAC,KAAK,UAAU,KAAK,MAAM,QAAQ,CAAC,IAAI,KAAK,CAAC,GAChD,KAAK,kBAAkB,iDAAiD;CAC1E,KAAK,MAAM,QAAQ,OAAO,OAAO,IAAI,GAAG,iBAAiB,IAAI;CAC7D,OAAO;AACT;AAyFA,SAAgB,QACd,SACA,cACyB;CACzB,MAAM,OAAO,OAAO,SAAS,OAAO,GAAG,gBAAgB;CACvD,UAAU,MAAM;EAAC;EAAS;EAAa;CAAc,GAAG,gBAAgB;CACxE,IAAI,CAAC,IAAI,MAAM,OAAO,GAAG,KAAK,kBAAkB,mBAAmB;CACnE,MAAM,YAAY,gBAAgB,KAAK,SAAc;CACrD,IAAI,KAAK,iBAAiB,KAAA,GAAW;EACnC,MAAM,MAAM,OAAO,KAAK,cAAc,gBAAgB;EACtD,UAAU,KAAK,CAAC,eAAe,GAAG,gBAAgB;EAClD,IAAI,IAAI,kBAAkB,KAAA,KAAa,IAAI,kBAAkB,YAC3D,KAAK,kBAAkB,iCAAiC;CAC5D;CACA,IAAI,aAAa,UAAU,UAAU,OAAO,KAAK,UAAU,UACzD,KAAK,yBAAyB,2BAA2B;CAC3D,IACE,aAAa,UAAU,yBACtB,KAAK,UAAU,QAAQ,OAAO,KAAK,UAAU,YAAY,OAAO,KAAK,UAAU,YAEhF,KAAK,yBAAyB,6CAA6C;CAC7E,IACE,aAAa,iBAAiB,KAAA,KAC9B,OAAO,KAAK,SAAS,CAAC,CAAC,SAAS,aAAa,cAE7C,KAAK,yBAAyB,8BAA8B;CAC9D,KAAK,MAAM,KAAK,OAAO,OAAO,SAAS,GAAG;EACxC,MAAM,aAAa,aAAa,MAAM,EAAE;EACxC,IAAI,CAAC,YAAY,KAAK,yBAAyB,2BAA2B;EAC1E,IACG,KAAK,cAA2C,kBAAkB,cACnE,CAAC,WAAW,eAEZ,KAAK,yBAAyB,+CAA+C;EAC/E,IAAI,aAAa,iBAAiB,QAS5B;OAAA,CAPF,EAAE,cACF,GAAI,EAAE,SAAS,WACX,OAAO,OAAO,EAAE,OAAO,IACvB,EAAE,SAAS,YACT,EAAE,SACF,OAAO,OAAO,EAAE,YAAY,CAAC,CAAC,CAEvB,CAAC,CAAC,MAAM,MAAM,OAAO,MAAM,QAAQ,GAChD,KAAK,yBAAyB,kCAAkC;EAAA;CAEtE;CACA,OAAO,OAAO,OAAO;EAAE,GAAG;EAAM;CAAU,CAAC;AAC7C;AAEA,SAAS,YAAY,OAAyC;CAC5D,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,KAAK,QAAQ,GAC/E,KAAK,mBAAmB,qBAAqB;AACjD;;AAEA,MAAa,yBAAyB;AACtC,SAAS,aAAa,QAAyB;CAC7C,OAAO,QAAQ,WAAW;CAC1B,IAAI,KAAK,IAAK,OAAoB,QAAQ,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,IAAA,MAC9D,KAAK,mBAAmB,iCAAiC;AAC7D;AACA,SAAS,aAAa,OAAgC,MAA+B;CACnF,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,WAAW,KAAK,UAAU,KAAK,MAAM,QAAQ,CAAC,IAAI,OAAO,GAAG,CAAC,GAClF,KAAK,mBAAmB,sCAAsC;AAClE;;AASA,SAAgB,eACd,SACA,SACA,UACA,cACwB;CACxB,MAAM,OAAO,OAAO,SAAS,SAAS,iBAAiB,CAAC;CACxD,UAAU,MAAM;EAAC;EAAW;EAAiB;EAAa;CAAO,GAAG,iBAAiB;CACrF,MAAM,UAAU,OAAO,KAAK,OAAO;CACnC,aAAa,SAAS,OAAO,KAAK,QAAQ,SAAS,CAAC;CACpD,KAAK,MAAM,CAAC,KAAK,MAAM,OAAO,QAAQ,QAAQ,SAAS,GAAG;EACxD,MAAM,IAAI,OAAO,QAAQ,IAAI;EAC7B,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,mBAAmB,qCAAqC;EACpF,IAAI,EAAE,eAAe,KAAA,GAAW;GAC9B,MAAM,IAAI,OAAO,EAAE,UAAU;GAC7B,UAAU,GAAG,CAAC,SAAS,YAAY,GAAG,iBAAiB;GACvD,YAAY,EAAE,KAAK;GACnB,IAAI,OAAO,EAAE,eAAe,YAAY,CAAC,EAAE,WAAW,KAAK,GACzD,KAAK,mBAAmB,+BAA+B;EAC3D,OAAO,IAAI,aAAa,MAAM,EAAE,KAAK,EAAE,YACrC,KAAK,mBAAmB,+BAA+B;EACzD,MAAM,WACJ,QAAQ,cAAc,kBAAkB,cACxC,aAAa,MAAM,EAAE,KAAK,EAAE;EAC9B,IAAI,EAAE,SAAS,WAAW;GACxB,UAAU,GAAG;IAAC;IAAQ;IAAmB;IAAkB;GAAY,GAAG,iBAAiB;GAC3F,IAAI,EAAE,oBAAoB,KAAA,GAAW,YAAY,EAAE,eAAe;QAC7D,IAAI,UAAU,KAAK,mBAAmB,6BAA6B;GACxE,IAAI,EAAE,mBAAmB,KAAA,KAAa,OAAO,EAAE,mBAAmB,WAChE,KAAK,mBAAmB,4BAA4B;GACtD,IAAI,EAAE,oBAAoB,KAAA,KAAa,EAAE,mBAAmB,KAAA,GAC1D,KAAK,mBAAmB,sBAAsB;EAClD,OAAO,IAAI,EAAE,SAAS,UAAU;GAC9B,UAAU,GAAG;IAAC;IAAQ;IAAS;IAAiB;GAAY,GAAG,iBAAiB;GAChF,IAAI,OAAO,EAAE,UAAU,YAAY,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,GACxD,KAAK,mBAAmB,sBAAsB;GAChD,IAAI,EAAE,kBAAkB,KAAA,GAAW;IACjC,MAAM,gBAAgB,OAAO,EAAE,aAAa;IAC5C,aAAa,eAAe,OAAO,KAAK,EAAE,OAAO,CAAC;IAClD,aAAa,OAAO,OAAO,aAAa,CAAC;GAC3C,OAAO,IAAI,UAAU,KAAK,mBAAmB,8BAA8B;EAC7E,OAAO;GACL,UACE,GACA;IAAC;IAAQ;IAAiB;IAAiB;IAAiB;GAAY,GACxE,iBACF;GACA,KAAK,MAAM,SAAS,CAAC,iBAAiB,eAAe,GAAG;IACtD,MAAM,IAAI,EAAE;IACZ,IACE,MAAM,KAAA,MACL,OAAO,MAAM,YACZ,CAAC,OAAO,SAAS,CAAC,KAClB,IAAI,KACJ,IAAI,EAAE,OAAO,SAAS,KACrB,UAAU,mBAAmB,CAAC,OAAO,UAAU,CAAC,IAEnD,KAAK,mBAAmB,uBAAuB;GACnD;GACA,IAAI,EAAE,kBAAkB,KAAA,GAAW;IACjC,IAAI,CAAC,MAAM,QAAQ,EAAE,aAAa,KAAK,EAAE,cAAc,WAAW,EAAE,OAAO,QACzE,KAAK,mBAAmB,uCAAuC;IACjE,aAAa,EAAE,aAAa;GAC9B,OAAO,IAAI,UAAU,KAAK,mBAAmB,+BAA+B;GAC5E,IACE,EAAE,kBAAkB,KAAA,KACpB,EAAE,kBAAkB,KAAA,KACpB,EAAE,kBAAkB,KAAA,GAEpB,KAAK,mBAAmB,sBAAsB;EAClD;CACF;CACA,KAAK,MAAM,OAAO,CAAC,iBAAiB,WAAW,GAC7C,IAAI,KAAK,SAAS,KAAA,MAAc,OAAO,KAAK,SAAS,YAAY,CAAC,KAAK,IAAI,CAAC,KAAK,IAC/E,KAAK,mBAAmB,2BAA2B;CAEvD,IAAI,KAAK,UAAU,KAAA,GAAW;EAC5B,MAAM,QAAQ,OAAO,KAAK,KAAK;EAC/B,UAAU,OAAO;GAAC;GAAe;GAAgB;EAAa,GAAG,iBAAiB;EAClF,KAAK,MAAM,KAAK,OAAO,OAAO,KAAK,GACjC,IAAI,OAAO,MAAM,YAAY,CAAC,OAAO,cAAc,CAAC,KAAK,IAAI,GAC3D,KAAK,mBAAmB,qBAAqB;CACnD;CACA,OAAO,OAAO,OAAO;EACnB;EACA,OAAO,OAAO,OAAO;GACnB,SAAS,SAAS;GAClB,gBAAgB,SAAS;GACzB,GAAI,KAAK,kBAAkB,KAAA,IAAY,CAAC,IAAI,EAAE,eAAe,KAAK,cAAc;EAClF,CAAC;EACD,GAAI,KAAK,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,KAAK,UAAU;EACpE,GAAI,KAAK,UAAU,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO,KAAK,MAAM;CAC1D,CAAC;AACH;;AAGA,SAAgB,cAAc,eAA0C;CACtE,IAAI,cAAc,SAAS,GAAG,KAAK,kBAAkB,kCAAkC;CACvF,aAAa,CAAC,GAAG,aAAa,CAAC;CAC/B,OAAO,cAAc,QAAQ,KAAK,GAAG,MAAM,MAAM,IAAI,GAAG,CAAC;AAC3D"}
@@ -0,0 +1,161 @@
1
+ //#region src/errors.d.ts
2
+ type ErrorTag = "InvalidRequest" | "UnsupportedCapability" | "AuthenticationError" | "QuotaExceeded" | "RateLimited" | "ContextLimitExceeded" | "TransportError" | "InvalidResponse" | "ProviderError";
3
+ interface ErrorDetails {
4
+ readonly status?: number;
5
+ readonly providerCode?: string;
6
+ readonly requestId?: string;
7
+ readonly retryAfterMs?: number;
8
+ }
9
+ /** Messages and details must never contain credentials or request/response bodies. */
10
+ declare class System1Error extends Error {
11
+ readonly _tag: ErrorTag;
12
+ readonly details: ErrorDetails;
13
+ readonly name = "System1Error";
14
+ constructor(_tag: ErrorTag, message: string, details?: ErrorDetails);
15
+ }
16
+ declare function isSystem1Error(value: unknown): value is System1Error;
17
+ //#endregion
18
+ //#region src/core.d.ts
19
+ type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
20
+ readonly [key: string]: JsonValue;
21
+ };
22
+ type Description = JsonValue;
23
+ type Kind = "boolean" | "choice" | "ordinal";
24
+ interface BooleanQuestion {
25
+ readonly kind: "boolean";
26
+ readonly instructions: Description;
27
+ readonly criteria?: {
28
+ readonly true: Description;
29
+ readonly false: Description;
30
+ };
31
+ }
32
+ interface ChoiceQuestion<K extends string = string> {
33
+ readonly kind: "choice";
34
+ readonly instructions: Description;
35
+ readonly options: Readonly<Record<K, Description>>;
36
+ }
37
+ interface OrdinalQuestion {
38
+ readonly kind: "ordinal";
39
+ readonly instructions: Description;
40
+ readonly levels: readonly Description[];
41
+ }
42
+ type QuestionDefinition = BooleanQuestion | ChoiceQuestion | OrdinalQuestion;
43
+ type Questions = Readonly<Record<string, QuestionDefinition>>;
44
+ /** Copy plain JSON without invoking getters or toJSON; reject lossy serialization. */
45
+ declare function snapshot(value: unknown, tag?: "InvalidRequest" | "InvalidResponse"): JsonValue;
46
+ declare function record(value: unknown, tag?: "InvalidRequest" | "InvalidResponse"): Record<string, unknown>;
47
+ declare const Question: {
48
+ readonly boolean: (input: Omit<BooleanQuestion, "kind">) => BooleanQuestion;
49
+ readonly choice: <const O extends Readonly<Record<string, Description>>>(input: {
50
+ readonly instructions: Description;
51
+ readonly options: O;
52
+ }) => ChoiceQuestion<Extract<keyof O, string>>;
53
+ readonly ordinal: (input: Omit<OrdinalQuestion, "kind">) => OrdinalQuestion;
54
+ };
55
+ declare function defineQuestions<const Q extends Questions>(input: Q): Q;
56
+ interface ReportedConfidence {
57
+ readonly value: number;
58
+ readonly definition: string;
59
+ }
60
+ type Confidence = {
61
+ readonly confidence?: ReportedConfidence;
62
+ };
63
+ type BooleanAnswer = Confidence & {
64
+ readonly kind: "boolean";
65
+ } & ({
66
+ readonly probabilityTrue: number;
67
+ readonly predictedValue?: boolean;
68
+ } | {
69
+ readonly probabilityTrue?: number;
70
+ readonly predictedValue: boolean;
71
+ });
72
+ interface ChoiceAnswer<K extends string = string> extends Confidence {
73
+ readonly kind: "choice";
74
+ readonly value: K;
75
+ readonly probabilities?: Readonly<Record<K, number>>;
76
+ }
77
+ type OrdinalAnswer = Confidence & {
78
+ readonly kind: "ordinal";
79
+ } & ({
80
+ readonly selectedIndex: number;
81
+ readonly expectedIndex?: number;
82
+ readonly probabilities?: readonly number[];
83
+ } | {
84
+ readonly selectedIndex?: number;
85
+ readonly expectedIndex: number;
86
+ readonly probabilities?: readonly number[];
87
+ } | {
88
+ readonly selectedIndex?: number;
89
+ readonly expectedIndex?: number;
90
+ readonly probabilities: readonly number[];
91
+ });
92
+ interface Requirements {
93
+ readonly probabilities?: "required";
94
+ }
95
+ type AnswerFor<Q extends QuestionDefinition, R extends Requirements = {}> = Q extends BooleanQuestion ? BooleanAnswer & (R extends {
96
+ probabilities: "required";
97
+ } ? {
98
+ readonly probabilityTrue: number;
99
+ } : {}) : Q extends ChoiceQuestion<infer K> ? ChoiceAnswer<K> & (R extends {
100
+ probabilities: "required";
101
+ } ? {
102
+ readonly probabilities: Readonly<Record<K, number>>;
103
+ } : {}) : OrdinalAnswer & (R extends {
104
+ probabilities: "required";
105
+ } ? {
106
+ readonly probabilities: readonly number[];
107
+ } : {});
108
+ type Answers<Q extends Questions, R extends Requirements = {}> = { readonly [K in keyof Q]: AnswerFor<Q[K], R>; };
109
+ interface EvaluationRequest<Q extends Questions = Questions, R extends Requirements = Requirements> {
110
+ readonly state: JsonValue;
111
+ readonly questions: Q;
112
+ readonly requirements?: R;
113
+ }
114
+ interface EvaluationResult<Q extends Questions, R extends Requirements = {}> {
115
+ readonly answers: Answers<Q, R>;
116
+ readonly model: {
117
+ readonly adapter: string;
118
+ readonly requestedModel: string;
119
+ readonly resolvedModel?: string;
120
+ };
121
+ readonly requestId?: string;
122
+ readonly usage?: {
123
+ readonly inputTokens?: number;
124
+ readonly outputTokens?: number;
125
+ readonly totalTokens?: number;
126
+ };
127
+ }
128
+ interface KindCapability {
129
+ readonly probabilities: boolean;
130
+ readonly confidence: boolean;
131
+ }
132
+ interface Capabilities {
133
+ readonly kinds: Readonly<Partial<Record<Kind, KindCapability>>>;
134
+ readonly state: "json" | "text-or-structured" | "text";
135
+ readonly descriptions: "json" | "text";
136
+ readonly maxQuestions?: number;
137
+ /** Informational only. No tokenizer is assumed; providers enforce token limits. */
138
+ readonly context?: readonly {
139
+ readonly scope: string;
140
+ readonly tokens: number;
141
+ }[];
142
+ }
143
+ declare function prepare<Q extends Questions, R extends Requirements>(request: EvaluationRequest<Q, R>, capabilities: Capabilities): EvaluationRequest<Q, R>;
144
+ /** Absolute sum tolerance; never renormalizes a distribution. */
145
+ declare const DISTRIBUTION_TOLERANCE = 0.001;
146
+ interface DecodedEvaluation {
147
+ readonly answers: unknown;
148
+ readonly resolvedModel?: string;
149
+ readonly requestId?: string;
150
+ readonly usage?: EvaluationResult<Questions>["usage"];
151
+ }
152
+ /** Validates untrusted normalized output before recovering question-specific types. */
153
+ declare function validateResult<const Q extends Questions, const R extends Requirements>(request: EvaluationRequest<Q, R>, decoded: DecodedEvaluation, identity: {
154
+ readonly adapter: string;
155
+ readonly model: string;
156
+ }, capabilities: Capabilities): EvaluationResult<Q, R>;
157
+ /** Explicit derived statistic, not a provider-reported prediction. */
158
+ declare function expectedIndex(probabilities: readonly number[]): number;
159
+ //#endregion
160
+ export { ErrorTag as A, defineQuestions as C, snapshot as D, record as E, isSystem1Error as M, validateResult as O, Requirements as S, prepare as T, OrdinalQuestion as _, Capabilities as a, Questions as b, DISTRIBUTION_TOLERANCE as c, EvaluationRequest as d, EvaluationResult as f, OrdinalAnswer as g, KindCapability as h, BooleanQuestion as i, System1Error as j, ErrorDetails as k, DecodedEvaluation as l, Kind as m, Answers as n, ChoiceAnswer as o, JsonValue as p, BooleanAnswer as r, ChoiceQuestion as s, AnswerFor as t, Description as u, Question as v, expectedIndex as w, ReportedConfidence as x, QuestionDefinition as y };
161
+ //# sourceMappingURL=core-DwacbzM7.d.mts.map
@@ -0,0 +1,2 @@
1
+ import { A as ErrorTag, C as defineQuestions, D as snapshot, E as record, M as isSystem1Error, O as validateResult, S as Requirements, T as prepare, _ as OrdinalQuestion, a as Capabilities, b as Questions, c as DISTRIBUTION_TOLERANCE, d as EvaluationRequest, f as EvaluationResult, g as OrdinalAnswer, h as KindCapability, i as BooleanQuestion, j as System1Error, k as ErrorDetails, l as DecodedEvaluation, m as Kind, n as Answers, o as ChoiceAnswer, p as JsonValue, r as BooleanAnswer, s as ChoiceQuestion, t as AnswerFor, u as Description, v as Question, w as expectedIndex, x as ReportedConfidence, y as QuestionDefinition } from "./core-DwacbzM7.mjs";
2
+ export { AnswerFor, Answers, BooleanAnswer, BooleanQuestion, Capabilities, ChoiceAnswer, ChoiceQuestion, DISTRIBUTION_TOLERANCE, DecodedEvaluation, Description, type ErrorDetails, type ErrorTag, EvaluationRequest, EvaluationResult, JsonValue, Kind, KindCapability, OrdinalAnswer, OrdinalQuestion, Question, QuestionDefinition, Questions, ReportedConfidence, Requirements, System1Error, defineQuestions, expectedIndex, isSystem1Error, prepare, record, snapshot, validateResult };
package/dist/core.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import { a as prepare, c as validateResult, i as expectedIndex, l as System1Error, n as Question, o as record, r as defineQuestions, s as snapshot, t as DISTRIBUTION_TOLERANCE, u as isSystem1Error } from "./core-D7i-WVU7.mjs";
2
+ export { DISTRIBUTION_TOLERANCE, Question, System1Error, defineQuestions, expectedIndex, isSystem1Error, prepare, record, snapshot, validateResult };
@@ -0,0 +1,19 @@
1
+ import { S as Requirements, a as Capabilities, b as Questions, d as EvaluationRequest, f as EvaluationResult, j as System1Error, l as DecodedEvaluation } from "./core-DwacbzM7.mjs";
2
+ import { t as ModelProtocol } from "./adapter-DndZN8Se.mjs";
3
+ import { Context, Effect, Layer } from "effect";
4
+ import { HttpClient } from "@effect/platform";
5
+ //#region src/effect.d.ts
6
+ export interface System1Service {
7
+ readonly evaluate: <const Q extends Questions, const R extends Requirements = {}>(request: EvaluationRequest<Q, R>) => Effect.Effect<EvaluationResult<Q, R>, System1Error>;
8
+ }
9
+ declare const System1_base: Context.TagClass<System1, "system-one/System1", System1Service>;
10
+ export declare class System1 extends System1_base {}
11
+ /** Supply any protocol with an injectable Effect HttpClient. No nested runtime or Promise wrapper. */
12
+ export declare function layer(model: ModelProtocol): Layer.Layer<System1, never, HttpClient.HttpClient>;
13
+ /** Fixture callbacks return untrusted normalized data; validation remains active. */
14
+ export declare function testLayer(options: {
15
+ readonly capabilities: Capabilities;
16
+ readonly evaluate: (request: EvaluationRequest) => DecodedEvaluation;
17
+ }): Layer.Layer<System1>;
18
+ //#endregion
19
+ //# sourceMappingURL=effect.d.mts.map
@@ -0,0 +1,60 @@
1
+ import { a as prepare, c as validateResult, l as System1Error, u as isSystem1Error } from "./core-D7i-WVU7.mjs";
2
+ import { Context, Effect, Layer } from "effect";
3
+ import { HttpClient, HttpClientRequest } from "@effect/platform";
4
+ //#region src/effect.ts
5
+ var System1 = class extends Context.Tag("system-one/System1")() {};
6
+ /** Only documented operational failures enter the error channel. Bugs remain defects. */
7
+ function attempt(thunk) {
8
+ return Effect.suspend(() => {
9
+ try {
10
+ return Effect.succeed(thunk());
11
+ } catch (error) {
12
+ return isSystem1Error(error) ? Effect.fail(error) : Effect.die(error);
13
+ }
14
+ });
15
+ }
16
+ /** Supply any protocol with an injectable Effect HttpClient. No nested runtime or Promise wrapper. */
17
+ function layer(model) {
18
+ return Layer.effect(System1, Effect.gen(function* () {
19
+ const http = yield* HttpClient.HttpClient;
20
+ return System1.of({ evaluate: (request) => Effect.gen(function* () {
21
+ const prepared = yield* attempt(() => prepare(request, model.capabilities));
22
+ const encoded = yield* attempt(() => model.encode(prepared));
23
+ const outgoing = HttpClientRequest.post(encoded.url, { headers: encoded.headers }).pipe(HttpClientRequest.bodyText(encoded.body, "application/json"));
24
+ const response = yield* http.execute(outgoing).pipe(Effect.mapError(() => new System1Error("TransportError", "HTTP transport failed")));
25
+ const text = yield* response.text.pipe(Effect.mapError(() => new System1Error("TransportError", "Response transport failed")));
26
+ let body;
27
+ try {
28
+ body = JSON.parse(text);
29
+ } catch {
30
+ body = null;
31
+ }
32
+ const decoded = yield* attempt(() => model.decode({
33
+ status: response.status,
34
+ headers: response.headers,
35
+ body
36
+ }, prepared));
37
+ return yield* attempt(() => validateResult(prepared, decoded, {
38
+ adapter: model.id,
39
+ model: model.model
40
+ }, model.capabilities));
41
+ }).pipe(Effect.withSpan("system1.evaluate", { attributes: {
42
+ "system1.adapter": model.id,
43
+ "system1.model": model.model
44
+ } })) });
45
+ }));
46
+ }
47
+ /** Fixture callbacks return untrusted normalized data; validation remains active. */
48
+ function testLayer(options) {
49
+ return Layer.succeed(System1, System1.of({ evaluate: (request) => attempt(() => {
50
+ const prepared = prepare(request, options.capabilities);
51
+ return validateResult(prepared, options.evaluate(prepared), {
52
+ adapter: "test",
53
+ model: "fixture"
54
+ }, options.capabilities);
55
+ }) }));
56
+ }
57
+ //#endregion
58
+ export { System1, layer, testLayer };
59
+
60
+ //# sourceMappingURL=effect.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effect.mjs","names":[],"sources":["../src/effect.ts"],"sourcesContent":["import { Context, Effect, Layer } from \"effect\";\nimport { HttpClient, HttpClientRequest } from \"@effect/platform\";\nimport { prepare, validateResult } from \"./core.js\";\nimport type {\n EvaluationRequest,\n EvaluationResult,\n Questions,\n Requirements,\n DecodedEvaluation,\n Capabilities,\n} from \"./core.js\";\nimport type { ModelProtocol } from \"./adapter.js\";\nimport { isSystem1Error, System1Error } from \"./errors.js\";\n\nexport interface System1Service {\n readonly evaluate: <const Q extends Questions, const R extends Requirements = {}>(\n request: EvaluationRequest<Q, R>,\n ) => Effect.Effect<EvaluationResult<Q, R>, System1Error>;\n}\nexport class System1 extends Context.Tag(\"system-one/System1\")<System1, System1Service>() {}\n\n/** Only documented operational failures enter the error channel. Bugs remain defects. */\nfunction attempt<A>(thunk: () => A): Effect.Effect<A, System1Error> {\n return Effect.suspend(() => {\n try {\n return Effect.succeed(thunk());\n } catch (error) {\n return isSystem1Error(error) ? Effect.fail(error) : Effect.die(error);\n }\n });\n}\n\n/** Supply any protocol with an injectable Effect HttpClient. No nested runtime or Promise wrapper. */\nexport function layer(model: ModelProtocol): Layer.Layer<System1, never, HttpClient.HttpClient> {\n return Layer.effect(\n System1,\n Effect.gen(function* () {\n const http = yield* HttpClient.HttpClient;\n return System1.of({\n evaluate: (request) =>\n Effect.gen(function* () {\n const prepared = yield* attempt(() => prepare(request, model.capabilities));\n const encoded = yield* attempt(() => model.encode(prepared));\n const outgoing = HttpClientRequest.post(encoded.url, { headers: encoded.headers }).pipe(\n HttpClientRequest.bodyText(encoded.body, \"application/json\"),\n );\n const response = yield* http\n .execute(outgoing)\n .pipe(\n Effect.mapError(() => new System1Error(\"TransportError\", \"HTTP transport failed\")),\n );\n const text = yield* response.text.pipe(\n Effect.mapError(\n () => new System1Error(\"TransportError\", \"Response transport failed\"),\n ),\n );\n let body: unknown;\n try {\n body = JSON.parse(text);\n } catch {\n body = null;\n }\n const decoded = yield* attempt(() =>\n model.decode({ status: response.status, headers: response.headers, body }, prepared),\n );\n return yield* attempt(() =>\n validateResult(\n prepared,\n decoded,\n { adapter: model.id, model: model.model },\n model.capabilities,\n ),\n );\n }).pipe(\n Effect.withSpan(\"system1.evaluate\", {\n attributes: { \"system1.adapter\": model.id, \"system1.model\": model.model },\n }),\n ),\n });\n }),\n );\n}\n\n/** Fixture callbacks return untrusted normalized data; validation remains active. */\nexport function testLayer(options: {\n readonly capabilities: Capabilities;\n readonly evaluate: (request: EvaluationRequest) => DecodedEvaluation;\n}): Layer.Layer<System1> {\n return Layer.succeed(\n System1,\n System1.of({\n evaluate: (request) =>\n attempt(() => {\n const prepared = prepare(request, options.capabilities);\n return validateResult(\n prepared,\n options.evaluate(prepared),\n { adapter: \"test\", model: \"fixture\" },\n options.capabilities,\n );\n }),\n }),\n );\n}\n"],"mappings":";;;;AAmBA,IAAa,UAAb,cAA6B,QAAQ,IAAI,oBAAoB,CAAC,CAA0B,CAAC,CAAC,CAAC;;AAG3F,SAAS,QAAW,OAAgD;CAClE,OAAO,OAAO,cAAc;EAC1B,IAAI;GACF,OAAO,OAAO,QAAQ,MAAM,CAAC;EAC/B,SAAS,OAAO;GACd,OAAO,eAAe,KAAK,IAAI,OAAO,KAAK,KAAK,IAAI,OAAO,IAAI,KAAK;EACtE;CACF,CAAC;AACH;;AAGA,SAAgB,MAAM,OAA0E;CAC9F,OAAO,MAAM,OACX,SACA,OAAO,IAAI,aAAa;EACtB,MAAM,OAAO,OAAO,WAAW;EAC/B,OAAO,QAAQ,GAAG,EAChB,WAAW,YACT,OAAO,IAAI,aAAa;GACtB,MAAM,WAAW,OAAO,cAAc,QAAQ,SAAS,MAAM,YAAY,CAAC;GAC1E,MAAM,UAAU,OAAO,cAAc,MAAM,OAAO,QAAQ,CAAC;GAC3D,MAAM,WAAW,kBAAkB,KAAK,QAAQ,KAAK,EAAE,SAAS,QAAQ,QAAQ,CAAC,CAAC,CAAC,KACjF,kBAAkB,SAAS,QAAQ,MAAM,kBAAkB,CAC7D;GACA,MAAM,WAAW,OAAO,KACrB,QAAQ,QAAQ,CAAC,CACjB,KACC,OAAO,eAAe,IAAI,aAAa,kBAAkB,uBAAuB,CAAC,CACnF;GACF,MAAM,OAAO,OAAO,SAAS,KAAK,KAChC,OAAO,eACC,IAAI,aAAa,kBAAkB,2BAA2B,CACtE,CACF;GACA,IAAI;GACJ,IAAI;IACF,OAAO,KAAK,MAAM,IAAI;GACxB,QAAQ;IACN,OAAO;GACT;GACA,MAAM,UAAU,OAAO,cACrB,MAAM,OAAO;IAAE,QAAQ,SAAS;IAAQ,SAAS,SAAS;IAAS;GAAK,GAAG,QAAQ,CACrF;GACA,OAAO,OAAO,cACZ,eACE,UACA,SACA;IAAE,SAAS,MAAM;IAAI,OAAO,MAAM;GAAM,GACxC,MAAM,YACR,CACF;EACF,CAAC,CAAC,CAAC,KACD,OAAO,SAAS,oBAAoB,EAClC,YAAY;GAAE,mBAAmB,MAAM;GAAI,iBAAiB,MAAM;EAAM,EAC1E,CAAC,CACH,EACJ,CAAC;CACH,CAAC,CACH;AACF;;AAGA,SAAgB,UAAU,SAGD;CACvB,OAAO,MAAM,QACX,SACA,QAAQ,GAAG,EACT,WAAW,YACT,cAAc;EACZ,MAAM,WAAW,QAAQ,SAAS,QAAQ,YAAY;EACtD,OAAO,eACL,UACA,QAAQ,SAAS,QAAQ,GACzB;GAAE,SAAS;GAAQ,OAAO;EAAU,GACpC,QAAQ,YACV;CACF,CAAC,EACL,CAAC,CACH;AACF"}
@@ -0,0 +1,18 @@
1
+ import { A as ErrorTag, C as defineQuestions, D as snapshot, E as record, M as isSystem1Error, O as validateResult, S as Requirements, T as prepare, _ as OrdinalQuestion, a as Capabilities, b as Questions, c as DISTRIBUTION_TOLERANCE, d as EvaluationRequest, f as EvaluationResult, g as OrdinalAnswer, h as KindCapability, i as BooleanQuestion, j as System1Error, k as ErrorDetails, l as DecodedEvaluation, m as Kind, n as Answers, o as ChoiceAnswer, p as JsonValue, r as BooleanAnswer, s as ChoiceQuestion, t as AnswerFor, u as Description, v as Question, w as expectedIndex, x as ReportedConfidence, y as QuestionDefinition } from "./core-DwacbzM7.mjs";
2
+ import { t as ModelProtocol } from "./adapter-DndZN8Se.mjs";
3
+ //#region src/client.d.ts
4
+ interface ExecutionOptions {
5
+ readonly signal?: AbortSignal;
6
+ readonly timeoutMs?: number;
7
+ }
8
+ interface Client {
9
+ evaluate<const Q extends Questions, const R extends Requirements = {}>(request: EvaluationRequest<Q, R>, options?: ExecutionOptions): Promise<EvaluationResult<Q, R>>;
10
+ }
11
+ /** One attempt per evaluation. No hidden retries, redirects, or model fallback. */
12
+ export declare function createClient(config: {
13
+ readonly model: ModelProtocol;
14
+ readonly fetch?: typeof globalThis.fetch;
15
+ }): Client;
16
+ //#endregion
17
+ export { AnswerFor, Answers, BooleanAnswer, BooleanQuestion, Capabilities, ChoiceAnswer, ChoiceQuestion, type Client, DISTRIBUTION_TOLERANCE, DecodedEvaluation, Description, type ErrorDetails, type ErrorTag, EvaluationRequest, EvaluationResult, type ExecutionOptions, JsonValue, Kind, KindCapability, OrdinalAnswer, OrdinalQuestion, Question, QuestionDefinition, Questions, ReportedConfidence, Requirements, System1Error, defineQuestions, expectedIndex, isSystem1Error, prepare, record, snapshot, validateResult };
18
+ //# sourceMappingURL=index.d.mts.map