@obversa/api 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.
Files changed (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +49 -0
  3. package/dist/accepted-result-support.d.ts +1 -0
  4. package/dist/accepted-result-support.js +5 -0
  5. package/dist/accepted-result-support.js.map +1 -0
  6. package/dist/action-decision.d.ts +15 -0
  7. package/dist/approval-support.d.ts +1 -0
  8. package/dist/approval-support.js +5 -0
  9. package/dist/approval-support.js.map +1 -0
  10. package/dist/artifacts/conformance.d.ts +20 -0
  11. package/dist/artifacts/store.d.ts +30 -0
  12. package/dist/budget.d.ts +36 -0
  13. package/dist/callback/approval.d.ts +80 -0
  14. package/dist/callback/client-contract.d.ts +81 -0
  15. package/dist/callback/gate.d.ts +49 -0
  16. package/dist/callback/stored-client.d.ts +22 -0
  17. package/dist/chunk-6NA4RDQ4.js +81 -0
  18. package/dist/chunk-6NA4RDQ4.js.map +1 -0
  19. package/dist/chunk-6NAMCSPJ.js +331 -0
  20. package/dist/chunk-6NAMCSPJ.js.map +1 -0
  21. package/dist/chunk-6ZP73HZN.js +293 -0
  22. package/dist/chunk-6ZP73HZN.js.map +1 -0
  23. package/dist/chunk-AJ353QD5.js +157 -0
  24. package/dist/chunk-AJ353QD5.js.map +1 -0
  25. package/dist/chunk-VWZKI7AG.js +552 -0
  26. package/dist/chunk-VWZKI7AG.js.map +1 -0
  27. package/dist/chunk-WGLWWKF3.js +135 -0
  28. package/dist/chunk-WGLWWKF3.js.map +1 -0
  29. package/dist/contracts.d.ts +122 -0
  30. package/dist/engine-conformance.d.ts +80 -0
  31. package/dist/environment.d.ts +53 -0
  32. package/dist/error.d.ts +36 -0
  33. package/dist/events/conformance.d.ts +20 -0
  34. package/dist/events/envelope.d.ts +26 -0
  35. package/dist/events/store.d.ts +15 -0
  36. package/dist/graph-commands.d.ts +23 -0
  37. package/dist/graph-contract.d.ts +48 -0
  38. package/dist/graph-executor.d.ts +61 -0
  39. package/dist/graph-kernel.d.ts +2 -0
  40. package/dist/graph-plan.d.ts +140 -0
  41. package/dist/graph-type.d.ts +45 -0
  42. package/dist/index.d.ts +33 -0
  43. package/dist/index.js +806 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/json.d.ts +14 -0
  46. package/dist/memory-conformance.d.ts +17 -0
  47. package/dist/memory-types.d.ts +127 -0
  48. package/dist/model-identity.d.ts +28 -0
  49. package/dist/node-data-context.d.ts +11 -0
  50. package/dist/preflight-result.d.ts +17 -0
  51. package/dist/proof/acceptance.d.ts +60 -0
  52. package/dist/proof/artifact.d.ts +2 -0
  53. package/dist/proof/cache.d.ts +46 -0
  54. package/dist/reasoning-record-contract.d.ts +52 -0
  55. package/dist/result-contract.d.ts +16 -0
  56. package/dist/result.d.ts +30 -0
  57. package/dist/run-definition-support.d.ts +1 -0
  58. package/dist/run-definition-support.js +5 -0
  59. package/dist/run-definition-support.js.map +1 -0
  60. package/dist/run-definition.d.ts +73 -0
  61. package/dist/storage/error.d.ts +7 -0
  62. package/dist/storage/id.d.ts +2 -0
  63. package/dist/testing.d.ts +5 -0
  64. package/dist/testing.js +1745 -0
  65. package/dist/testing.js.map +1 -0
  66. package/dist/workspace/conformance.d.ts +30 -0
  67. package/dist/workspace/policy.d.ts +6 -0
  68. package/dist/workspace/provider.d.ts +132 -0
  69. package/package.json +68 -0
@@ -0,0 +1,293 @@
1
+ import { cloneFrozenJson } from './chunk-AJ353QD5.js';
2
+ import { isAbsolute } from 'path';
3
+
4
+ var ENGINE_FAILURE_KINDS = /* @__PURE__ */ new Set([
5
+ "auth",
6
+ "billing",
7
+ "missing-cli",
8
+ "model-unavailable",
9
+ "invalid-config",
10
+ "rate-limit",
11
+ "quota",
12
+ "transient",
13
+ "timeout",
14
+ "aborted",
15
+ "unknown"
16
+ ]);
17
+ function nonEmptyText(value, field) {
18
+ if (typeof value !== "string" || value.trim().length === 0) {
19
+ throw new TypeError(`${field} must be a non-empty string`);
20
+ }
21
+ cloneFrozenJson(value);
22
+ return value;
23
+ }
24
+ function nullableText(value, field) {
25
+ if (value === null) return null;
26
+ return nonEmptyText(value, field);
27
+ }
28
+ function nullableExecutable(value, field) {
29
+ if (value === null || value === void 0) return null;
30
+ const path = nonEmptyText(value, field);
31
+ if (!isAbsolute(path)) {
32
+ throw new TypeError(`${field} must be an absolute path or null`);
33
+ }
34
+ return path;
35
+ }
36
+ function tokenCount(value, field) {
37
+ if (!Number.isSafeInteger(value) || value < 0) {
38
+ throw new TypeError(`${field} must be a non-negative safe integer`);
39
+ }
40
+ return value;
41
+ }
42
+ function validateUsage(value) {
43
+ if (value.kind === "unknown") return Object.freeze({ kind: "unknown" });
44
+ if (value.kind !== "reported") {
45
+ throw new TypeError("usage.kind must be unknown or reported");
46
+ }
47
+ const receipt = {
48
+ kind: "reported",
49
+ inputTokens: tokenCount(value.inputTokens, "usage.inputTokens"),
50
+ outputTokens: tokenCount(value.outputTokens, "usage.outputTokens"),
51
+ ...value.cacheCreationInputTokens === void 0 ? {} : {
52
+ cacheCreationInputTokens: tokenCount(
53
+ value.cacheCreationInputTokens,
54
+ "usage.cacheCreationInputTokens"
55
+ )
56
+ },
57
+ ...value.cacheReadInputTokens === void 0 ? {} : {
58
+ cacheReadInputTokens: tokenCount(
59
+ value.cacheReadInputTokens,
60
+ "usage.cacheReadInputTokens"
61
+ )
62
+ }
63
+ };
64
+ return Object.freeze(receipt);
65
+ }
66
+ function validateSelection(value, field) {
67
+ const capabilities = value.capabilities.map(
68
+ (capability, index) => nonEmptyText(capability, `${field}.capabilities[${index}]`)
69
+ );
70
+ if (new Set(capabilities).size !== capabilities.length) {
71
+ throw new TypeError(`${field}.capabilities must be unique`);
72
+ }
73
+ return Object.freeze({
74
+ adapter: nonEmptyText(value.adapter, `${field}.adapter`),
75
+ adapterVersion: value.adapterVersion === null ? null : nonEmptyText(value.adapterVersion, `${field}.adapterVersion`),
76
+ provider: nullableText(value.provider, `${field}.provider`),
77
+ modelFamily: nullableText(value.modelFamily, `${field}.modelFamily`),
78
+ model: nullableText(value.model, `${field}.model`),
79
+ executable: nullableExecutable(value.executable, `${field}.executable`),
80
+ capabilities: Object.freeze(capabilities)
81
+ });
82
+ }
83
+ function validatePart(value, index) {
84
+ if (value.kind === "assistant") {
85
+ if (typeof value.final !== "boolean") {
86
+ throw new TypeError(`parts[${index}].final must be a boolean`);
87
+ }
88
+ if (typeof value.text !== "string") {
89
+ throw new TypeError(`parts[${index}].text must be a string`);
90
+ }
91
+ cloneFrozenJson(value.text);
92
+ return Object.freeze({
93
+ kind: "assistant",
94
+ text: value.text,
95
+ final: value.final
96
+ });
97
+ }
98
+ if (value.kind === "structured" && value.final === true) {
99
+ return Object.freeze({
100
+ kind: "structured",
101
+ value: cloneFrozenJson(value.value),
102
+ final: true
103
+ });
104
+ }
105
+ throw new TypeError(`parts[${index}] is not a valid result part`);
106
+ }
107
+ function validateTransportFailure(value) {
108
+ if (value === void 0) return void 0;
109
+ if (value.exitCode !== null && !Number.isSafeInteger(value.exitCode)) {
110
+ throw new TypeError("transportFailure.exitCode must be a safe integer or null");
111
+ }
112
+ if (!ENGINE_FAILURE_KINDS.has(value.kind)) {
113
+ throw new TypeError("transportFailure.kind is invalid");
114
+ }
115
+ return Object.freeze({
116
+ kind: value.kind,
117
+ message: nonEmptyText(value.message, "transportFailure.message"),
118
+ exitCode: value.exitCode
119
+ });
120
+ }
121
+ function validateIncompleteResultEvidence(result) {
122
+ const parts = result.parts.map(validatePart);
123
+ if (parts.filter((part) => part.final).length > 1) {
124
+ throw new TypeError("incomplete engine evidence cannot contain two final parts");
125
+ }
126
+ const transportFailure = validateTransportFailure(result.transportFailure);
127
+ return Object.freeze({
128
+ parts: Object.freeze(parts),
129
+ usage: validateUsage(result.usage),
130
+ requested: validateSelection(result.requested, "requested"),
131
+ effective: validateSelection(result.effective, "effective"),
132
+ ...result.stopReason === void 0 ? {} : { stopReason: nonEmptyText(result.stopReason, "stopReason") },
133
+ ...transportFailure === void 0 ? {} : { transportFailure },
134
+ ...result.raw === void 0 ? {} : { raw: result.raw }
135
+ });
136
+ }
137
+ function validateAgentResult(result) {
138
+ if (result.parts.filter((part) => part.final).length !== 1) {
139
+ throw new TypeError("agent result must contain exactly one final part");
140
+ }
141
+ return validateIncompleteResultEvidence(result);
142
+ }
143
+ function engineSelection(input) {
144
+ return validateSelection({
145
+ adapter: input.adapter,
146
+ adapterVersion: input.adapterVersion ?? null,
147
+ provider: input.provider ?? null,
148
+ modelFamily: input.modelFamily ?? null,
149
+ model: input.model ?? null,
150
+ executable: input.executable ?? null,
151
+ capabilities: input.capabilities ?? []
152
+ }, "selection");
153
+ }
154
+ function reportedUsage(usage) {
155
+ return validateUsage({ kind: "reported", ...usage });
156
+ }
157
+ function assistantResult(input) {
158
+ return validateAgentResult({
159
+ parts: [{ kind: "assistant", text: input.text, final: true }],
160
+ usage: input.usage,
161
+ requested: input.requested,
162
+ effective: input.effective ?? input.requested,
163
+ ...input.stopReason === void 0 ? {} : { stopReason: input.stopReason },
164
+ ...input.transportFailure === void 0 ? {} : { transportFailure: input.transportFailure },
165
+ ...input.raw === void 0 ? {} : { raw: input.raw }
166
+ });
167
+ }
168
+ function finalResultPart(result) {
169
+ const part = result.parts.find((candidate) => candidate.final);
170
+ if (!part) throw new TypeError("agent result must contain exactly one final part");
171
+ return part;
172
+ }
173
+ function finalResultText(result) {
174
+ const part = finalResultPart(result);
175
+ return part.kind === "assistant" ? part.text : void 0;
176
+ }
177
+ function requireFinalResultText(result) {
178
+ const text = finalResultText(result);
179
+ if (text === void 0) {
180
+ throw new TypeError("engine result must end with assistant text");
181
+ }
182
+ return text;
183
+ }
184
+
185
+ // src/error.ts
186
+ var EngineError = class extends Error {
187
+ kind;
188
+ retryAfterMs;
189
+ resetAt;
190
+ effective;
191
+ constructor(init) {
192
+ super(
193
+ init.message,
194
+ init.cause === void 0 ? void 0 : { cause: init.cause }
195
+ );
196
+ this.name = "EngineError";
197
+ this.kind = init.kind;
198
+ this.retryAfterMs = init.retryAfterMs;
199
+ this.resetAt = init.resetAt;
200
+ this.effective = init.effective === void 0 ? void 0 : engineSelection(init.effective);
201
+ }
202
+ };
203
+ var EngineIncompleteResultError = class extends EngineError {
204
+ evidence;
205
+ constructor(message, evidence) {
206
+ super({ kind: "unknown", message });
207
+ this.name = "EngineIncompleteResultError";
208
+ this.evidence = evidence;
209
+ }
210
+ };
211
+ var LANE_DEAD_FAILURES = /* @__PURE__ */ new Set([
212
+ "auth",
213
+ "billing",
214
+ "missing-cli",
215
+ "model-unavailable",
216
+ "invalid-config",
217
+ "quota"
218
+ ]);
219
+ var MESSAGE_RULES = [
220
+ {
221
+ kind: "invalid-config",
222
+ pattern: /invalid value.*supported values|invalid (?:configuration|config)|(?:load|parse).*config(?:uration)?|bad config/
223
+ },
224
+ { kind: "billing", pattern: /credit balance|billing|payment required|purchase more|insufficient funds|402/ },
225
+ { kind: "auth", pattern: /not authenticated|unauthorized|invalid (api |x-)?key|authentication[_ ](error|failed)|expired.*(token|credentials)|login|401/ },
226
+ { kind: "missing-cli", pattern: /enoent|command not found|not recognized as an internal|no such file or directory.*(claude|codex)/ },
227
+ { kind: "model-unavailable", pattern: /model.*(not found|unavailable|does not exist|unknown)|unknown model|no such model|404/ },
228
+ { kind: "quota", pattern: /\bmonthly (?:usage limit|quota|allowance)\b|out of.*credits|\binsufficient credits\b/ },
229
+ { kind: "rate-limit", pattern: /rate.?limit|too many requests|overloaded|429|529|quota|allowance|usage limit|session limit/ },
230
+ { kind: "timeout", pattern: /\btim(ed?)?.?out\b|deadline exceeded/ },
231
+ { kind: "transient", pattern: /internal server error|bad gateway|service unavailable|gateway timeout|\b5\d\d\b/ }
232
+ ];
233
+ function messageOf(error) {
234
+ if (error instanceof Error) {
235
+ const parts = [error.message];
236
+ if (error.cause instanceof Error) parts.push(error.cause.message);
237
+ return parts.join("\n");
238
+ }
239
+ return String(error);
240
+ }
241
+ function classifyEngineFailure(error) {
242
+ if (error instanceof EngineError) return error.kind;
243
+ const code = error?.code;
244
+ if (code === "RATE_LIMIT") return "rate-limit";
245
+ if (code === "QUOTA") return "quota";
246
+ if (code === "TIMEOUT") return "timeout";
247
+ if (code === "ABORTED") return "aborted";
248
+ if (code === "CONFIG") return "invalid-config";
249
+ const err = error;
250
+ if (err && (err.code === "ENOENT" || err.cause?.code === "ENOENT")) {
251
+ return "missing-cli";
252
+ }
253
+ if (err?.name === "AbortError") return "aborted";
254
+ const text = messageOf(error).toLowerCase();
255
+ for (const rule of MESSAGE_RULES) {
256
+ if (rule.pattern.test(text)) return rule.kind;
257
+ }
258
+ return "unknown";
259
+ }
260
+
261
+ // src/model-identity.ts
262
+ function modelIdentity(model) {
263
+ if (typeof model !== "string") {
264
+ throw invalid(`a model must be a string, not ${typeof model}`);
265
+ }
266
+ const trimmed = model.trim();
267
+ const slash = trimmed.indexOf("/");
268
+ const provider = slash === -1 ? void 0 : trimmed.slice(0, slash).trim().toLowerCase();
269
+ const name = slash === -1 ? trimmed : trimmed.slice(slash + 1).trim();
270
+ if (slash !== -1 && (provider === "" || name === "")) {
271
+ throw invalid(`model ${JSON.stringify(model)} must name both a provider and a model`);
272
+ }
273
+ if (name.includes("/")) {
274
+ throw invalid(
275
+ `model ${JSON.stringify(model)} must name one provider and one model, separated once`
276
+ );
277
+ }
278
+ if (/\s/u.test(trimmed)) {
279
+ throw invalid(`model ${JSON.stringify(model)} must not contain whitespace`);
280
+ }
281
+ const family = name.split("-", 1)[0]?.trim().toLowerCase() ?? "";
282
+ if (family === "" || family === "unknown") {
283
+ throw invalid(`model ${JSON.stringify(model)} names no readable model family`);
284
+ }
285
+ return Object.freeze(provider === void 0 ? { modelFamily: family } : { provider, modelFamily: family });
286
+ }
287
+ function invalid(message) {
288
+ return new EngineError({ kind: "invalid-config", message });
289
+ }
290
+
291
+ export { EngineError, EngineIncompleteResultError, LANE_DEAD_FAILURES, assistantResult, classifyEngineFailure, engineSelection, finalResultPart, finalResultText, modelIdentity, reportedUsage, requireFinalResultText, validateAgentResult, validateIncompleteResultEvidence };
292
+ //# sourceMappingURL=chunk-6ZP73HZN.js.map
293
+ //# sourceMappingURL=chunk-6ZP73HZN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/result.ts","../src/error.ts","../src/model-identity.ts"],"names":[],"mappings":"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","file":"chunk-6ZP73HZN.js","sourcesContent":["import { isAbsolute } from 'node:path';\n\nimport type {\n AgentResult,\n AgentResultPart,\n EngineIncompleteResultEvidence,\n EngineSelectionRecord,\n EngineTransportFailure,\n UsageReceipt,\n} from './contracts.js';\nimport { cloneFrozenJson, type JsonValue } from './json.js';\n\nconst ENGINE_FAILURE_KINDS = new Set<EngineTransportFailure['kind']>([\n 'auth',\n 'billing',\n 'missing-cli',\n 'model-unavailable',\n 'invalid-config',\n 'rate-limit',\n 'quota',\n 'transient',\n 'timeout',\n 'aborted',\n 'unknown',\n]);\n\nfunction nonEmptyText(value: unknown, field: string): string {\n if (typeof value !== 'string' || value.trim().length === 0) {\n throw new TypeError(`${field} must be a non-empty string`);\n }\n cloneFrozenJson(value);\n return value;\n}\n\nfunction nullableText(value: unknown, field: string): string | null {\n if (value === null) return null;\n return nonEmptyText(value, field);\n}\n\nfunction nullableExecutable(value: unknown, field: string): string | null {\n if (value === null || value === undefined) return null;\n const path = nonEmptyText(value, field);\n if (!isAbsolute(path)) {\n throw new TypeError(`${field} must be an absolute path or null`);\n }\n return path;\n}\n\nfunction tokenCount(value: unknown, field: string): number {\n if (!Number.isSafeInteger(value) || (value as number) < 0) {\n throw new TypeError(`${field} must be a non-negative safe integer`);\n }\n return value as number;\n}\n\nfunction validateUsage(value: UsageReceipt): UsageReceipt {\n if (value.kind === 'unknown') return Object.freeze({ kind: 'unknown' });\n if (value.kind !== 'reported') {\n throw new TypeError('usage.kind must be unknown or reported');\n }\n const receipt = {\n kind: 'reported' as const,\n inputTokens: tokenCount(value.inputTokens, 'usage.inputTokens'),\n outputTokens: tokenCount(value.outputTokens, 'usage.outputTokens'),\n ...(value.cacheCreationInputTokens === undefined\n ? {}\n : {\n cacheCreationInputTokens: tokenCount(\n value.cacheCreationInputTokens,\n 'usage.cacheCreationInputTokens',\n ),\n }),\n ...(value.cacheReadInputTokens === undefined\n ? {}\n : {\n cacheReadInputTokens: tokenCount(\n value.cacheReadInputTokens,\n 'usage.cacheReadInputTokens',\n ),\n }),\n };\n return Object.freeze(receipt);\n}\n\nfunction validateSelection(\n value: EngineSelectionRecord,\n field: string,\n): EngineSelectionRecord {\n const capabilities = value.capabilities.map((capability, index) =>\n nonEmptyText(capability, `${field}.capabilities[${index}]`),\n );\n if (new Set(capabilities).size !== capabilities.length) {\n throw new TypeError(`${field}.capabilities must be unique`);\n }\n return Object.freeze({\n adapter: nonEmptyText(value.adapter, `${field}.adapter`),\n adapterVersion:\n value.adapterVersion === null\n ? null\n : nonEmptyText(value.adapterVersion, `${field}.adapterVersion`),\n provider: nullableText(value.provider, `${field}.provider`),\n modelFamily: nullableText(value.modelFamily, `${field}.modelFamily`),\n model: nullableText(value.model, `${field}.model`),\n executable: nullableExecutable(value.executable, `${field}.executable`),\n capabilities: Object.freeze(capabilities),\n });\n}\n\nfunction validatePart(value: AgentResultPart, index: number): AgentResultPart {\n if (value.kind === 'assistant') {\n if (typeof value.final !== 'boolean') {\n throw new TypeError(`parts[${index}].final must be a boolean`);\n }\n if (typeof value.text !== 'string') {\n throw new TypeError(`parts[${index}].text must be a string`);\n }\n cloneFrozenJson(value.text);\n return Object.freeze({\n kind: 'assistant',\n text: value.text,\n final: value.final,\n });\n }\n if (value.kind === 'structured' && value.final === true) {\n return Object.freeze({\n kind: 'structured',\n value: cloneFrozenJson(value.value as JsonValue),\n final: true,\n });\n }\n throw new TypeError(`parts[${index}] is not a valid result part`);\n}\n\nfunction validateTransportFailure(\n value: EngineTransportFailure | undefined,\n): EngineTransportFailure | undefined {\n if (value === undefined) return undefined;\n if (value.exitCode !== null && !Number.isSafeInteger(value.exitCode)) {\n throw new TypeError('transportFailure.exitCode must be a safe integer or null');\n }\n if (!ENGINE_FAILURE_KINDS.has(value.kind)) {\n throw new TypeError('transportFailure.kind is invalid');\n }\n return Object.freeze({\n kind: value.kind,\n message: nonEmptyText(value.message, 'transportFailure.message'),\n exitCode: value.exitCode,\n });\n}\n\nexport function validateIncompleteResultEvidence(\n result: EngineIncompleteResultEvidence,\n): EngineIncompleteResultEvidence {\n const parts = result.parts.map(validatePart);\n if (parts.filter((part) => part.final).length > 1) {\n throw new TypeError('incomplete engine evidence cannot contain two final parts');\n }\n const transportFailure = validateTransportFailure(result.transportFailure);\n return Object.freeze({\n parts: Object.freeze(parts),\n usage: validateUsage(result.usage),\n requested: validateSelection(result.requested, 'requested'),\n effective: validateSelection(result.effective, 'effective'),\n ...(result.stopReason === undefined\n ? {}\n : { stopReason: nonEmptyText(result.stopReason, 'stopReason') }),\n ...(transportFailure === undefined ? {} : { transportFailure }),\n ...(result.raw === undefined ? {} : { raw: result.raw }),\n });\n}\n\nexport function validateAgentResult(result: AgentResult): AgentResult {\n if (result.parts.filter((part) => part.final).length !== 1) {\n throw new TypeError('agent result must contain exactly one final part');\n }\n return validateIncompleteResultEvidence(result);\n}\n\nexport function engineSelection(input: {\n adapter: string;\n adapterVersion?: string | null;\n provider?: string | null;\n modelFamily?: string | null;\n model?: string | null;\n executable?: string | null;\n capabilities?: readonly string[];\n}): EngineSelectionRecord {\n return validateSelection({\n adapter: input.adapter,\n adapterVersion: input.adapterVersion ?? null,\n provider: input.provider ?? null,\n modelFamily: input.modelFamily ?? null,\n model: input.model ?? null,\n executable: input.executable ?? null,\n capabilities: input.capabilities ?? [],\n }, 'selection');\n}\n\nexport function reportedUsage(usage: {\n inputTokens: number;\n outputTokens: number;\n cacheCreationInputTokens?: number;\n cacheReadInputTokens?: number;\n}): UsageReceipt {\n return validateUsage({ kind: 'reported', ...usage });\n}\n\nexport function assistantResult(input: {\n text: string;\n usage: UsageReceipt;\n requested: EngineSelectionRecord;\n effective?: EngineSelectionRecord;\n stopReason?: string;\n transportFailure?: EngineTransportFailure;\n raw?: unknown;\n}): AgentResult {\n return validateAgentResult({\n parts: [{ kind: 'assistant', text: input.text, final: true }],\n usage: input.usage,\n requested: input.requested,\n effective: input.effective ?? input.requested,\n ...(input.stopReason === undefined\n ? {}\n : { stopReason: input.stopReason }),\n ...(input.transportFailure === undefined\n ? {}\n : { transportFailure: input.transportFailure }),\n ...(input.raw === undefined ? {} : { raw: input.raw }),\n });\n}\n\nexport function finalResultPart(result: AgentResult): AgentResultPart {\n const part = result.parts.find((candidate) => candidate.final);\n if (!part) throw new TypeError('agent result must contain exactly one final part');\n return part;\n}\n\nexport function finalResultText(result: AgentResult): string | undefined {\n const part = finalResultPart(result);\n return part.kind === 'assistant' ? part.text : undefined;\n}\n\nexport function requireFinalResultText(result: AgentResult): string {\n const text = finalResultText(result);\n if (text === undefined) {\n throw new TypeError('engine result must end with assistant text');\n }\n return text;\n}\n","/**\n * Shared engine failure classification. Typed engine failures and compatible\n * runtime codes take priority over process errors and message text.\n *\n * Default fallback treats auth, billing, missing executables, unavailable\n * models, invalid configuration and exhausted long allowances as lasting for\n * the run. Ambiguous limit wording is rate-limit, not evidence of quota.\n * Rate limits and transient failures remain outside the default lasting set.\n */\n\nimport type {\n EngineFailureKind,\n EngineIncompleteResultEvidence,\n EngineSelectionRecord,\n} from './contracts.js';\nimport { engineSelection } from './result.js';\nexport type { EngineFailureKind } from './contracts.js';\n\nexport interface EngineErrorInit {\n readonly kind: EngineFailureKind;\n readonly message: string;\n readonly cause?: unknown;\n readonly retryAfterMs?: number;\n readonly resetAt?: number;\n readonly effective?: EngineSelectionRecord;\n}\n\n/** A provider or adapter failure with no runtime policy attached. */\nexport class EngineError extends Error {\n readonly kind: EngineFailureKind;\n readonly retryAfterMs?: number;\n readonly resetAt?: number;\n readonly effective?: EngineSelectionRecord;\n\n constructor(init: EngineErrorInit) {\n super(\n init.message,\n init.cause === undefined ? undefined : { cause: init.cause },\n );\n this.name = 'EngineError';\n this.kind = init.kind;\n this.retryAfterMs = init.retryAfterMs;\n this.resetAt = init.resetAt;\n this.effective = init.effective === undefined\n ? undefined\n : engineSelection(init.effective);\n }\n}\n\n/** A failed engine turn that still produced measured, recordable evidence. */\nexport class EngineIncompleteResultError extends EngineError {\n readonly evidence: EngineIncompleteResultEvidence;\n\n constructor(message: string, evidence: EngineIncompleteResultEvidence) {\n super({ kind: 'unknown', message });\n this.name = 'EngineIncompleteResultError';\n this.evidence = evidence;\n }\n}\n\n/** Failures that default fallback treats as lasting for the run. */\nexport const LANE_DEAD_FAILURES: ReadonlySet<EngineFailureKind> = new Set([\n 'auth',\n 'billing',\n 'missing-cli',\n 'model-unavailable',\n 'invalid-config',\n 'quota',\n]);\n\ninterface Rule {\n kind: EngineFailureKind;\n pattern: RegExp;\n}\n\n/** Substring rules over the lowercased message, most specific first. The\n * vocabulary spans the Anthropic API, the claude/codex CLIs, and generic\n * HTTP phrasing, so every engine classifies through one table. */\nconst MESSAGE_RULES: Rule[] = [\n {\n kind: 'invalid-config',\n pattern:\n /invalid value.*supported values|invalid (?:configuration|config)|(?:load|parse).*config(?:uration)?|bad config/,\n },\n { kind: 'billing', pattern: /credit balance|billing|payment required|purchase more|insufficient funds|402/ },\n { kind: 'auth', pattern: /not authenticated|unauthorized|invalid (api |x-)?key|authentication[_ ](error|failed)|expired.*(token|credentials)|login|401/ },\n { kind: 'missing-cli', pattern: /enoent|command not found|not recognized as an internal|no such file or directory.*(claude|codex)/ },\n { kind: 'model-unavailable', pattern: /model.*(not found|unavailable|does not exist|unknown)|unknown model|no such model|404/ },\n { kind: 'quota', pattern: /\\bmonthly (?:usage limit|quota|allowance)\\b|out of.*credits|\\binsufficient credits\\b/ },\n { kind: 'rate-limit', pattern: /rate.?limit|too many requests|overloaded|429|529|quota|allowance|usage limit|session limit/ },\n { kind: 'timeout', pattern: /\\btim(ed?)?.?out\\b|deadline exceeded/ },\n { kind: 'transient', pattern: /internal server error|bad gateway|service unavailable|gateway timeout|\\b5\\d\\d\\b/ },\n];\n\nfunction messageOf(error: unknown): string {\n if (error instanceof Error) {\n const parts = [error.message];\n if (error.cause instanceof Error) parts.push(error.cause.message);\n return parts.join('\\n');\n }\n return String(error);\n}\n\n/** Classify a failed engine turn. Typed signals win over substring rules. */\nexport function classifyEngineFailure(error: unknown): EngineFailureKind {\n if (error instanceof EngineError) return error.kind;\n const code = (error as { readonly code?: unknown } | null)?.code;\n if (code === 'RATE_LIMIT') return 'rate-limit';\n if (code === 'QUOTA') return 'quota';\n if (code === 'TIMEOUT') return 'timeout';\n if (code === 'ABORTED') return 'aborted';\n if (code === 'CONFIG') return 'invalid-config';\n const err = error as NodeJS.ErrnoException | undefined;\n if (err && (err.code === 'ENOENT' || (err.cause as NodeJS.ErrnoException | undefined)?.code === 'ENOENT')) {\n return 'missing-cli';\n }\n if (err?.name === 'AbortError') return 'aborted';\n const text = messageOf(error).toLowerCase();\n for (const rule of MESSAGE_RULES) {\n if (rule.pattern.test(text)) return rule.kind;\n }\n return 'unknown';\n}\n","import { EngineError } from './error.js';\n\n/**\n * The provider and model family a harness reports for the model it was given.\n * `provider` is present only when the string carried one (`provider/model`);\n * a harness that runs one provider's models supplies its own.\n */\nexport interface ModelIdentity {\n readonly provider?: string;\n readonly modelFamily: string;\n}\n\n/**\n * Read the provider and the model family from a model string.\n *\n * A harness that runs other providers' models (OpenCode today, Devin next)\n * must report the identity of the model it was given, never its own name,\n * or two seats on one model wearing different tool names pass the\n * distinct-family check. Every such harness, and the teams gate that reads\n * recorded models back, derives the identity through this one function.\n *\n * `provider/model` yields both parts; a bare `model` yields the family alone.\n * A second separator, or whitespace anywhere inside, is refused rather than\n * read as part of a name.\n * The family is the model name up to its first hyphen, lowercased, so\n * `claude-sonnet-4-5` and `claude-opus-4-1` are one family and `gpt-5.6-luna`\n * another. A string that names no readable family, including the `unknown`\n * placeholder some adapters emit, is refused with an `invalid-config` engine\n * error rather than reported as a family called `unknown`.\n */\nexport function modelIdentity(model: string): ModelIdentity {\n if (typeof model !== 'string') {\n throw invalid(`a model must be a string, not ${typeof model}`);\n }\n const trimmed = model.trim();\n const slash = trimmed.indexOf('/');\n const provider = slash === -1 ? undefined : trimmed.slice(0, slash).trim().toLowerCase();\n const name = slash === -1 ? trimmed : trimmed.slice(slash + 1).trim();\n if (slash !== -1 && (provider === '' || name === '')) {\n throw invalid(`model ${JSON.stringify(model)} must name both a provider and a model`);\n }\n // One provider and one model, with nothing hidden inside either part. A\n // second separator let `anthropic//unknown` read as the family `/unknown`,\n // which walks straight past the refusal the `unknown` placeholder exists to\n // trigger, and `anthropic//` read as the family `/`. Whitespace anywhere\n // inside is the same kind of hiding place, so it is refused across the whole\n // identifier rather than in the model half alone.\n if (name.includes('/')) {\n throw invalid(\n `model ${JSON.stringify(model)} must name one provider and one model, separated once`,\n );\n }\n if (/\\s/u.test(trimmed)) {\n throw invalid(`model ${JSON.stringify(model)} must not contain whitespace`);\n }\n const family = name.split('-', 1)[0]?.trim().toLowerCase() ?? '';\n if (family === '' || family === 'unknown') {\n throw invalid(`model ${JSON.stringify(model)} names no readable model family`);\n }\n return Object.freeze(provider === undefined ? { modelFamily: family } : { provider, modelFamily: family });\n}\n\nfunction invalid(message: string): EngineError {\n return new EngineError({ kind: 'invalid-config', message });\n}\n"]}
@@ -0,0 +1,157 @@
1
+ import { createHash } from 'crypto';
2
+
3
+ // src/json.ts
4
+ var MAX_JSON_DEPTH = 256;
5
+ var JsonValueError = class extends TypeError {
6
+ code = "INVALID_JSON_VALUE";
7
+ path;
8
+ constructor(path, reason) {
9
+ super(`Invalid JSON value at ${path || "<root>"}: ${reason}`);
10
+ this.name = "JsonValueError";
11
+ this.path = path;
12
+ }
13
+ };
14
+ function pointer(path, token) {
15
+ const escaped = String(token).replaceAll("~", "~0").replaceAll("/", "~1");
16
+ return `${path}/${escaped}`;
17
+ }
18
+ function assertUnicode(value, path) {
19
+ for (let index = 0; index < value.length; index += 1) {
20
+ const unit = value.charCodeAt(index);
21
+ if (unit >= 55296 && unit <= 56319) {
22
+ const next = value.charCodeAt(index + 1);
23
+ if (!Number.isInteger(next) || next < 56320 || next > 57343) {
24
+ throw new JsonValueError(path, "strings must contain valid Unicode");
25
+ }
26
+ index += 1;
27
+ continue;
28
+ }
29
+ if (unit >= 56320 && unit <= 57343) {
30
+ throw new JsonValueError(path, "strings must contain valid Unicode");
31
+ }
32
+ }
33
+ }
34
+ function invalidType(value) {
35
+ if (value === void 0) return "undefined is not JSON";
36
+ if (typeof value === "number") return "numbers must be finite";
37
+ if (typeof value !== "object" || value === null) {
38
+ return `${typeof value} is not JSON`;
39
+ }
40
+ const name = value.constructor?.name;
41
+ return `${name ? `${name} instances` : "this object"} are not JSON`;
42
+ }
43
+ function cloneValue(value, path, ancestors, depth) {
44
+ if (depth > MAX_JSON_DEPTH) {
45
+ throw new JsonValueError(
46
+ path,
47
+ `nesting must not exceed ${MAX_JSON_DEPTH} levels`
48
+ );
49
+ }
50
+ if (value === null || typeof value === "boolean") return value;
51
+ if (typeof value === "string") {
52
+ assertUnicode(value, path);
53
+ return value;
54
+ }
55
+ if (typeof value === "number") {
56
+ if (!Number.isFinite(value)) throw new JsonValueError(path, invalidType(value));
57
+ return Object.is(value, -0) ? 0 : value;
58
+ }
59
+ if (typeof value !== "object") {
60
+ throw new JsonValueError(path, invalidType(value));
61
+ }
62
+ if (ancestors.has(value)) {
63
+ throw new JsonValueError(path, "cycles are not JSON");
64
+ }
65
+ ancestors.add(value);
66
+ try {
67
+ if (Array.isArray(value)) {
68
+ if (Object.getOwnPropertySymbols(value).length > 0) {
69
+ throw new JsonValueError(path, "symbol keys are not JSON");
70
+ }
71
+ for (const key of Object.getOwnPropertyNames(value)) {
72
+ if (key === "length") continue;
73
+ const index = Number(key);
74
+ if (!Number.isSafeInteger(index) || index < 0 || String(index) !== key) {
75
+ throw new JsonValueError(pointer(path, key), "array properties must be indexes");
76
+ }
77
+ }
78
+ const result2 = [];
79
+ for (let index = 0; index < value.length; index += 1) {
80
+ const itemPath = pointer(path, index);
81
+ const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
82
+ if (!descriptor) {
83
+ throw new JsonValueError(itemPath, "sparse arrays are not JSON");
84
+ }
85
+ if (!("value" in descriptor) || !descriptor.enumerable) {
86
+ throw new JsonValueError(itemPath, "array items must be enumerable data values");
87
+ }
88
+ result2.push(cloneValue(descriptor.value, itemPath, ancestors, depth + 1));
89
+ }
90
+ return Object.freeze(result2);
91
+ }
92
+ const prototype = Object.getPrototypeOf(value);
93
+ if (prototype !== Object.prototype && prototype !== null) {
94
+ throw new JsonValueError(path, invalidType(value));
95
+ }
96
+ if (Object.getOwnPropertySymbols(value).length > 0) {
97
+ throw new JsonValueError(path, "symbol keys are not JSON");
98
+ }
99
+ const result = {};
100
+ for (const key of Object.getOwnPropertyNames(value)) {
101
+ const keyPath = pointer(path, key);
102
+ assertUnicode(key, keyPath);
103
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
104
+ if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
105
+ throw new JsonValueError(keyPath, "object properties must be enumerable data values");
106
+ }
107
+ Object.defineProperty(result, key, {
108
+ value: cloneValue(descriptor.value, keyPath, ancestors, depth + 1),
109
+ enumerable: true,
110
+ configurable: false,
111
+ writable: false
112
+ });
113
+ }
114
+ return Object.freeze(result);
115
+ } finally {
116
+ ancestors.delete(value);
117
+ }
118
+ }
119
+ function cloneFrozenJson(value) {
120
+ return cloneValue(value, "", /* @__PURE__ */ new WeakSet(), 0);
121
+ }
122
+ function encodeCanonical(value) {
123
+ if (value === null) return "null";
124
+ if (typeof value === "boolean") return value ? "true" : "false";
125
+ if (typeof value === "number") {
126
+ return Object.is(value, -0) ? "0" : JSON.stringify(value);
127
+ }
128
+ if (typeof value === "string") return JSON.stringify(value);
129
+ if (Array.isArray(value)) {
130
+ return `[${value.map(encodeCanonical).join(",")}]`;
131
+ }
132
+ const objectValue = value;
133
+ return `{${Object.keys(objectValue).sort().map((key) => `${JSON.stringify(key)}:${encodeCanonical(objectValue[key])}`).join(",")}}`;
134
+ }
135
+ function canonicalJson(value) {
136
+ return encodeCanonical(cloneFrozenJson(value));
137
+ }
138
+ function digestJson(value) {
139
+ const digest = createHash("sha256").update(canonicalJson(value), "utf8").digest("hex");
140
+ return `sha256:${digest}`;
141
+ }
142
+
143
+ // src/storage/error.ts
144
+ var StorageError = class extends Error {
145
+ code;
146
+ details;
147
+ constructor(code, message, details = {}) {
148
+ super(message);
149
+ this.name = "StorageError";
150
+ this.code = code;
151
+ this.details = cloneFrozenJson(details);
152
+ }
153
+ };
154
+
155
+ export { JsonValueError, StorageError, canonicalJson, cloneFrozenJson, digestJson };
156
+ //# sourceMappingURL=chunk-AJ353QD5.js.map
157
+ //# sourceMappingURL=chunk-AJ353QD5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/json.ts","../src/storage/error.ts"],"names":["result"],"mappings":"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","file":"chunk-AJ353QD5.js","sourcesContent":["import { createHash } from 'node:crypto';\n\nexport type JsonPrimitive = null | boolean | number | string;\n\nexport type JsonObject = { readonly [key: string]: JsonValue };\n\nexport type JsonValue = JsonPrimitive | JsonObject | readonly JsonValue[];\n\nexport type Sha256Digest = `sha256:${string}`;\n\nconst MAX_JSON_DEPTH = 256;\n\nexport class JsonValueError extends TypeError {\n readonly code = 'INVALID_JSON_VALUE' as const;\n readonly path: string;\n\n constructor(path: string, reason: string) {\n super(`Invalid JSON value at ${path || '<root>'}: ${reason}`);\n this.name = 'JsonValueError';\n this.path = path;\n }\n}\n\nfunction pointer(path: string, token: string | number): string {\n const escaped = String(token).replaceAll('~', '~0').replaceAll('/', '~1');\n return `${path}/${escaped}`;\n}\n\nfunction assertUnicode(value: string, path: string): void {\n for (let index = 0; index < value.length; index += 1) {\n const unit = value.charCodeAt(index);\n if (unit >= 0xd800 && unit <= 0xdbff) {\n const next = value.charCodeAt(index + 1);\n if (!Number.isInteger(next) || next < 0xdc00 || next > 0xdfff) {\n throw new JsonValueError(path, 'strings must contain valid Unicode');\n }\n index += 1;\n continue;\n }\n if (unit >= 0xdc00 && unit <= 0xdfff) {\n throw new JsonValueError(path, 'strings must contain valid Unicode');\n }\n }\n}\n\nfunction invalidType(value: unknown): string {\n if (value === undefined) return 'undefined is not JSON';\n if (typeof value === 'number') return 'numbers must be finite';\n if (typeof value !== 'object' || value === null) {\n return `${typeof value} is not JSON`;\n }\n const name = value.constructor?.name;\n return `${name ? `${name} instances` : 'this object'} are not JSON`;\n}\n\nfunction cloneValue(\n value: unknown,\n path: string,\n ancestors: WeakSet<object>,\n depth: number,\n): JsonValue {\n if (depth > MAX_JSON_DEPTH) {\n throw new JsonValueError(\n path,\n `nesting must not exceed ${MAX_JSON_DEPTH} levels`,\n );\n }\n\n if (value === null || typeof value === 'boolean') return value;\n\n if (typeof value === 'string') {\n assertUnicode(value, path);\n return value;\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value)) throw new JsonValueError(path, invalidType(value));\n return Object.is(value, -0) ? 0 : value;\n }\n\n if (typeof value !== 'object') {\n throw new JsonValueError(path, invalidType(value));\n }\n\n if (ancestors.has(value)) {\n throw new JsonValueError(path, 'cycles are not JSON');\n }\n ancestors.add(value);\n\n try {\n if (Array.isArray(value)) {\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw new JsonValueError(path, 'symbol keys are not JSON');\n }\n\n for (const key of Object.getOwnPropertyNames(value)) {\n if (key === 'length') continue;\n const index = Number(key);\n if (!Number.isSafeInteger(index) || index < 0 || String(index) !== key) {\n throw new JsonValueError(pointer(path, key), 'array properties must be indexes');\n }\n }\n\n const result: JsonValue[] = [];\n for (let index = 0; index < value.length; index += 1) {\n const itemPath = pointer(path, index);\n const descriptor = Object.getOwnPropertyDescriptor(value, String(index));\n if (!descriptor) {\n throw new JsonValueError(itemPath, 'sparse arrays are not JSON');\n }\n if (!('value' in descriptor) || !descriptor.enumerable) {\n throw new JsonValueError(itemPath, 'array items must be enumerable data values');\n }\n result.push(cloneValue(descriptor.value, itemPath, ancestors, depth + 1));\n }\n return Object.freeze(result);\n }\n\n const prototype = Object.getPrototypeOf(value);\n if (prototype !== Object.prototype && prototype !== null) {\n throw new JsonValueError(path, invalidType(value));\n }\n if (Object.getOwnPropertySymbols(value).length > 0) {\n throw new JsonValueError(path, 'symbol keys are not JSON');\n }\n\n const result: Record<string, JsonValue> = {};\n for (const key of Object.getOwnPropertyNames(value)) {\n const keyPath = pointer(path, key);\n assertUnicode(key, keyPath);\n const descriptor = Object.getOwnPropertyDescriptor(value, key);\n if (!descriptor || !('value' in descriptor) || !descriptor.enumerable) {\n throw new JsonValueError(keyPath, 'object properties must be enumerable data values');\n }\n Object.defineProperty(result, key, {\n value: cloneValue(descriptor.value, keyPath, ancestors, depth + 1),\n enumerable: true,\n configurable: false,\n writable: false,\n });\n }\n return Object.freeze(result);\n } finally {\n ancestors.delete(value);\n }\n}\n\nexport function cloneFrozenJson<Value extends JsonValue>(value: Value): Value {\n return cloneValue(value, '', new WeakSet<object>(), 0) as Value;\n}\n\nfunction encodeCanonical(value: JsonValue): string {\n if (value === null) return 'null';\n if (typeof value === 'boolean') return value ? 'true' : 'false';\n if (typeof value === 'number') {\n return Object.is(value, -0) ? '0' : JSON.stringify(value);\n }\n if (typeof value === 'string') return JSON.stringify(value);\n if (Array.isArray(value)) {\n return `[${value.map(encodeCanonical).join(',')}]`;\n }\n\n const objectValue = value as JsonObject;\n return `{${Object.keys(objectValue)\n .sort()\n .map((key) => `${JSON.stringify(key)}:${encodeCanonical(objectValue[key]!)}`)\n .join(',')}}`;\n}\n\nexport function canonicalJson(value: JsonValue): string {\n return encodeCanonical(cloneFrozenJson(value));\n}\n\nexport function digestJson(value: JsonValue): Sha256Digest {\n const digest = createHash('sha256').update(canonicalJson(value), 'utf8').digest('hex');\n return `sha256:${digest}`;\n}\n","import {\n cloneFrozenJson,\n type JsonObject,\n} from '../json.js';\n\nexport type StorageErrorCode =\n | 'INVALID_STORED_VALUE'\n | 'UNSUPPORTED_ENVELOPE_VERSION'\n | 'REVISION_CONFLICT'\n | 'DUPLICATE_EVENT_ID'\n | 'CORRUPT_EVENT_STREAM'\n | 'ARTIFACT_NOT_FOUND'\n | 'ARTIFACT_NOT_ADMITTED'\n | 'ARTIFACT_INTEGRITY'\n | 'STORAGE_LIMIT_EXCEEDED'\n | 'SENSITIVE_CONTENT'\n | 'KNOWN_SECRET'\n | 'UNSAFE_STORAGE_PATH';\n\nexport class StorageError extends Error {\n readonly code: StorageErrorCode;\n readonly details: JsonObject;\n\n constructor(\n code: StorageErrorCode,\n message: string,\n details: JsonObject = {},\n ) {\n super(message);\n this.name = 'StorageError';\n this.code = code;\n this.details = cloneFrozenJson(details);\n }\n}\n"]}