@full-self-browsing/lattice 1.4.0 → 1.5.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 (108) hide show
  1. package/dist/agent-run-C6miAzwI.d.ts +45 -0
  2. package/dist/agent-run-C6miAzwI.d.ts.map +1 -0
  3. package/dist/agent-run-CgPVFl0Z.js +47 -0
  4. package/dist/agent-run-CgPVFl0Z.js.map +1 -0
  5. package/dist/agents.d.ts +5 -0
  6. package/dist/agents.js +6 -0
  7. package/dist/artifact-Bg6mJGnm.d.ts +125 -0
  8. package/dist/artifact-Bg6mJGnm.d.ts.map +1 -0
  9. package/dist/artifact-DOfpeXLb.js +140 -0
  10. package/dist/artifact-DOfpeXLb.js.map +1 -0
  11. package/dist/artifacts.d.ts +2 -0
  12. package/dist/artifacts.js +2 -0
  13. package/dist/audit.d.ts +3 -0
  14. package/dist/audit.js +4 -0
  15. package/dist/catalog-CAfYwB_-.js +91 -0
  16. package/dist/catalog-CAfYwB_-.js.map +1 -0
  17. package/dist/context-pack-Bz3GXmjv.js +99 -0
  18. package/dist/context-pack-Bz3GXmjv.js.map +1 -0
  19. package/dist/context.d.ts +2 -0
  20. package/dist/context.js +2 -0
  21. package/dist/contract-S3oJGlc9.d.ts +74 -0
  22. package/dist/contract-S3oJGlc9.d.ts.map +1 -0
  23. package/dist/core.d.ts +48 -0
  24. package/dist/core.d.ts.map +1 -0
  25. package/dist/core.js +95 -0
  26. package/dist/core.js.map +1 -0
  27. package/dist/errors-eEuEIx6X.js +407 -0
  28. package/dist/errors-eEuEIx6X.js.map +1 -0
  29. package/dist/eval.d.ts +2 -0
  30. package/dist/eval.js +2 -0
  31. package/dist/fingerprint-DodDbQKN.js +34 -0
  32. package/dist/fingerprint-DodDbQKN.js.map +1 -0
  33. package/dist/index-DpnHGHVL.d.ts +53 -0
  34. package/dist/index-DpnHGHVL.d.ts.map +1 -0
  35. package/dist/index.d.ts +90 -3533
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +26 -15968
  38. package/dist/index.js.map +1 -1
  39. package/dist/infer-DLqp5QIM.d.ts +96 -0
  40. package/dist/infer-DLqp5QIM.d.ts.map +1 -0
  41. package/dist/lineage-DBgoPWAZ.js +137 -0
  42. package/dist/lineage-DBgoPWAZ.js.map +1 -0
  43. package/dist/local-CXOGPJ1f.js +139 -0
  44. package/dist/local-CXOGPJ1f.js.map +1 -0
  45. package/dist/local-Dy--7peL.d.ts +10 -0
  46. package/dist/local-Dy--7peL.d.ts.map +1 -0
  47. package/dist/memory-CkQEW6m5.js +62 -0
  48. package/dist/memory-CkQEW6m5.js.map +1 -0
  49. package/dist/memory-DRig5EHV.d.ts +10 -0
  50. package/dist/memory-DRig5EHV.d.ts.map +1 -0
  51. package/dist/negotiate-ClD88hkc.js +10967 -0
  52. package/dist/negotiate-ClD88hkc.js.map +1 -0
  53. package/dist/otel-BgM4e55_.d.ts +421 -0
  54. package/dist/otel-BgM4e55_.d.ts.map +1 -0
  55. package/dist/permission-context-CUKMo79F.js +134 -0
  56. package/dist/permission-context-CUKMo79F.js.map +1 -0
  57. package/dist/plan-DFm8Llep.js +125 -0
  58. package/dist/plan-DFm8Llep.js.map +1 -0
  59. package/dist/preflight-DNHWuJ46.d.ts +64 -0
  60. package/dist/preflight-DNHWuJ46.d.ts.map +1 -0
  61. package/dist/provider-C2IfKsvz.d.ts +1178 -0
  62. package/dist/provider-C2IfKsvz.d.ts.map +1 -0
  63. package/dist/providers.d.ts +4 -0
  64. package/dist/providers.js +4 -0
  65. package/dist/rate-limit-group-nDsBJqSu.d.ts +235 -0
  66. package/dist/rate-limit-group-nDsBJqSu.d.ts.map +1 -0
  67. package/dist/receipt-FYouoPHv.js +205 -0
  68. package/dist/receipt-FYouoPHv.js.map +1 -0
  69. package/dist/replay-CtIhpLek.js +964 -0
  70. package/dist/replay-CtIhpLek.js.map +1 -0
  71. package/dist/result-DLEx2WvU.d.ts +38 -0
  72. package/dist/result-DLEx2WvU.d.ts.map +1 -0
  73. package/dist/router-DU4Z3pTd.js +314 -0
  74. package/dist/router-DU4Z3pTd.js.map +1 -0
  75. package/dist/router-Yo1-aDOv.d.ts +42 -0
  76. package/dist/router-Yo1-aDOv.d.ts.map +1 -0
  77. package/dist/routing.d.ts +6 -0
  78. package/dist/routing.js +4 -0
  79. package/dist/{run-crew-CKdBjh5P.js → run-crew-B2fQLmgB.js} +7 -136
  80. package/dist/run-crew-B2fQLmgB.js.map +1 -0
  81. package/dist/run-crew-Bnve5dyI.d.ts +721 -0
  82. package/dist/run-crew-Bnve5dyI.d.ts.map +1 -0
  83. package/dist/{runtime-D25ehzCj.js → runtime-Dxiet5YS.js} +98 -641
  84. package/dist/runtime-Dxiet5YS.js.map +1 -0
  85. package/dist/scaffolds-DKQrCRqh.d.ts +535 -0
  86. package/dist/scaffolds-DKQrCRqh.d.ts.map +1 -0
  87. package/dist/scaffolds-ekPIlBeU.js +3139 -0
  88. package/dist/scaffolds-ekPIlBeU.js.map +1 -0
  89. package/dist/schema-CNfa_VEy.d.ts +15 -0
  90. package/dist/schema-CNfa_VEy.d.ts.map +1 -0
  91. package/dist/storage-DJKmsaEI.d.ts +26 -0
  92. package/dist/storage-DJKmsaEI.d.ts.map +1 -0
  93. package/dist/storage.d.ts +10 -0
  94. package/dist/storage.d.ts.map +1 -0
  95. package/dist/storage.js +4 -0
  96. package/dist/tool-call-validation-BFoXkwbf.js +107 -0
  97. package/dist/tool-call-validation-BFoXkwbf.js.map +1 -0
  98. package/dist/tools-C4wHgGKQ.js +49 -0
  99. package/dist/tools-C4wHgGKQ.js.map +1 -0
  100. package/dist/tools.d.ts +46 -0
  101. package/dist/tools.d.ts.map +1 -0
  102. package/dist/tools.js +106 -0
  103. package/dist/tools.js.map +1 -0
  104. package/dist/validate-c7EL5uuH.js +224 -0
  105. package/dist/validate-c7EL5uuH.js.map +1 -0
  106. package/package.json +99 -2
  107. package/dist/run-crew-CKdBjh5P.js.map +0 -1
  108. package/dist/runtime-D25ehzCj.js.map +0 -1
@@ -0,0 +1,964 @@
1
+ import { r as toArtifactRef } from "./artifact-DOfpeXLb.js";
2
+ import { a as decodeEnvelope, i as buildPae, n as PAYLOAD_TYPE, o as canonicalizeReceiptBody, r as base64Encode, t as createReceipt } from "./receipt-FYouoPHv.js";
3
+ import { n as receiptCid, t as computeArtifactLineageMerkleRoot } from "./lineage-DBgoPWAZ.js";
4
+ import { r as withPlanStatus, t as createExecutionPlan } from "./plan-DFm8Llep.js";
5
+ import { t as fingerprintArtifactValue } from "./fingerprint-DodDbQKN.js";
6
+ import canonicalize from "canonicalize";
7
+ //#region src/observability/otel.ts
8
+ const DEFAULT_SPAN_NAME = "lattice.run";
9
+ const DEFAULT_LANGFUSE_BASE_URL = "https://cloud.langfuse.com";
10
+ const DEFAULT_PHOENIX_BASE_URL = "http://localhost:6006";
11
+ const OTEL_STATUS_OK = 1;
12
+ const OTEL_STATUS_ERROR = 2;
13
+ const SECRET_KEY_RE = /api[-_]?key|authorization|credentials?|headers?|password|secret|token/iu;
14
+ const CONTENT_KEY_RE = /artifact|body|content|input|inputs|message|messages|output|outputs|payload|prompt|rawOutputs|task|value/iu;
15
+ function createOtelRunEventSink(options) {
16
+ const spans = /* @__PURE__ */ new Map();
17
+ return async (event) => {
18
+ const span = getOrCreateRunSpan(event, options, spans);
19
+ const attributes = await createRunEventAttributes(event, options);
20
+ setSpanAttributes(span, attributes);
21
+ span.addEvent?.(`lattice.${event.kind}`, attributes);
22
+ if (event.kind === "capabilities.negotiation.fallback") {
23
+ span.setStatus?.({ code: OTEL_STATUS_OK });
24
+ span.end?.(eventTime(event));
25
+ spans.delete(event.runId);
26
+ return;
27
+ }
28
+ if (event.kind === "run.complete") {
29
+ span.setStatus?.({ code: OTEL_STATUS_OK });
30
+ span.end?.(eventTime(event));
31
+ spans.delete(event.runId);
32
+ return;
33
+ }
34
+ if (event.kind === "run.failed") {
35
+ const message = metadataString(event, "reason");
36
+ span.setStatus?.({
37
+ code: OTEL_STATUS_ERROR,
38
+ ...message !== void 0 ? { message } : {}
39
+ });
40
+ if (message !== void 0) span.recordException?.(message);
41
+ span.end?.(eventTime(event));
42
+ spans.delete(event.runId);
43
+ }
44
+ };
45
+ }
46
+ function sanitizeRunEventAttributes(event, options = {}) {
47
+ const attributes = {
48
+ "lattice.event.kind": event.kind,
49
+ "lattice.run.id": event.runId
50
+ };
51
+ assignString(attributes, "lattice.plan.id", event.planId);
52
+ assignString(attributes, "lattice.stage.id", event.stageId);
53
+ assignString(attributes, "lattice.provider.id", event.providerId);
54
+ assignString(attributes, "lattice.model.id", event.modelId);
55
+ assignString(attributes, "lattice.artifact.id", event.artifactId);
56
+ assignString(attributes, "gen_ai.provider.name", event.providerId);
57
+ assignString(attributes, "gen_ai.request.model", event.modelId);
58
+ if (event.kind === "stream.start" || event.kind === "stream.complete" || event.kind === "stream.failed") attributes["gen_ai.request.stream"] = true;
59
+ const metadata = event.metadata ?? {};
60
+ assignString(attributes, "lattice.event.status", metadataString(event, "status"));
61
+ assignBoolean(attributes, "lattice.error.present", metadataString(event, "error") !== void 0 ? true : void 0);
62
+ assignString(attributes, "lattice.failure.reason", metadataString(event, "reason"));
63
+ assignString(attributes, "lattice.tripwire.invariant_id", asString(metadata.invariantId));
64
+ assignString(attributes, "lattice.artifact.source", asString(metadata.source));
65
+ assignString(attributes, "lattice.receipt.id", asString(metadata.receiptId));
66
+ assignBoolean(attributes, "lattice.receipt.mint_error.present", asString(metadata.mintError) !== void 0 ? true : void 0);
67
+ assignString(attributes, "lattice.route.selected_model", asString(metadata.selected));
68
+ assignNumber(attributes, "lattice.route.rejected.count", asNumber(metadata.rejected));
69
+ assignNumber(attributes, "lattice.route.fallback.count", asNumber(metadata.fallbacks));
70
+ assignBoolean(attributes, "lattice.provider.attempt.fallback", asBoolean(metadata.fallback));
71
+ assignNumber(attributes, "lattice.context.estimated_tokens", asNumber(metadata.estimatedTokens));
72
+ assignNumber(attributes, "lattice.context.included.count", asNumber(metadata.included));
73
+ assignNumber(attributes, "lattice.context.summarized.count", asNumber(metadata.summarized));
74
+ assignNumber(attributes, "lattice.context.omitted.count", asNumber(metadata.omitted));
75
+ assignString(attributes, "lattice.tool.name", asString(metadata.toolName));
76
+ assignString(attributes, "lattice.tool.call.id", asString(metadata.callId));
77
+ assignStringArray(attributes, "lattice.output.names", asStringArray(metadata.outputNames));
78
+ assignUsage(attributes, metadata);
79
+ assignGateway(attributes, metadata.gateway);
80
+ captureSafeMetadata(attributes, metadata, options);
81
+ return attributes;
82
+ }
83
+ async function createOtelReceiptAttributes(envelope) {
84
+ const attributes = {
85
+ "lattice.receipt.cid": await receiptCid(envelope),
86
+ "lattice.receipt.signature.count": envelope.signatures.length
87
+ };
88
+ assignString(attributes, "lattice.receipt.signature.keyid", envelope.signatures[0]?.keyid);
89
+ return attributes;
90
+ }
91
+ function createLangfuseOtlpConfig(options = {}) {
92
+ const authString = langfuseAuthString(options);
93
+ return {
94
+ endpoint: langfuseTraceEndpoint(options.baseUrl ?? DEFAULT_LANGFUSE_BASE_URL),
95
+ headers: {
96
+ ...authString !== void 0 ? { Authorization: `Basic ${authString}` } : {},
97
+ "x-langfuse-ingestion-version": options.ingestionVersion ?? "4",
98
+ ...options.headers ?? {}
99
+ }
100
+ };
101
+ }
102
+ function createPhoenixOtlpConfig(options = {}) {
103
+ return {
104
+ endpoint: options.endpoint ?? phoenixTraceEndpoint(options.baseUrl ?? DEFAULT_PHOENIX_BASE_URL),
105
+ headers: {
106
+ ...options.apiKey !== void 0 ? { Authorization: `Bearer ${options.apiKey}` } : {},
107
+ ...options.projectName !== void 0 ? { "x-project-name": options.projectName } : {},
108
+ ...options.headers ?? {}
109
+ }
110
+ };
111
+ }
112
+ function getOrCreateRunSpan(event, options, spans) {
113
+ const existing = spans.get(event.runId);
114
+ if (existing !== void 0) return existing;
115
+ const span = options.tracer.startSpan(options.spanName ?? DEFAULT_SPAN_NAME, {
116
+ attributes: sanitizeRunEventAttributes(event, options),
117
+ startTime: eventTime(event)
118
+ });
119
+ spans.set(event.runId, span);
120
+ return span;
121
+ }
122
+ function setSpanAttributes(span, attributes) {
123
+ if (span.setAttributes !== void 0) {
124
+ span.setAttributes(attributes);
125
+ return;
126
+ }
127
+ for (const [key, value] of Object.entries(attributes)) span.setAttribute?.(key, value);
128
+ }
129
+ async function createRunEventAttributes(event, options) {
130
+ const attributes = sanitizeRunEventAttributes(event, options);
131
+ const envelope = findReceiptEnvelope(event.metadata);
132
+ if (envelope === void 0) return attributes;
133
+ try {
134
+ return {
135
+ ...attributes,
136
+ ...await createOtelReceiptAttributes(envelope)
137
+ };
138
+ } catch {
139
+ return attributes;
140
+ }
141
+ }
142
+ function eventTime(event) {
143
+ return new Date(event.timestamp);
144
+ }
145
+ function metadataString(event, key) {
146
+ return asString(event.metadata?.[key]);
147
+ }
148
+ function assignString(attributes, key, value) {
149
+ if (value !== void 0) attributes[key] = value;
150
+ }
151
+ function assignNumber(attributes, key, value) {
152
+ if (value !== void 0) attributes[key] = value;
153
+ }
154
+ function assignBoolean(attributes, key, value) {
155
+ if (value !== void 0) attributes[key] = value;
156
+ }
157
+ function assignStringArray(attributes, key, value) {
158
+ if (value !== void 0 && value.length > 0) attributes[key] = value;
159
+ }
160
+ function assignNumberArray(attributes, key, value) {
161
+ if (value !== void 0 && value.length > 0) attributes[key] = value;
162
+ }
163
+ function assignBooleanArray(attributes, key, value) {
164
+ if (value !== void 0 && value.length > 0) attributes[key] = value;
165
+ }
166
+ function asString(value) {
167
+ return typeof value === "string" && value.length > 0 ? value : void 0;
168
+ }
169
+ function asNumber(value) {
170
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
171
+ }
172
+ function asBoolean(value) {
173
+ return typeof value === "boolean" ? value : void 0;
174
+ }
175
+ function asStringArray(value) {
176
+ return Array.isArray(value) && value.every((item) => typeof item === "string") ? value : void 0;
177
+ }
178
+ function asNumberArray(value) {
179
+ return Array.isArray(value) && value.every((item) => typeof item === "number" && Number.isFinite(item)) ? value : void 0;
180
+ }
181
+ function asBooleanArray(value) {
182
+ return Array.isArray(value) && value.every((item) => typeof item === "boolean") ? value : void 0;
183
+ }
184
+ function assignUsage(attributes, metadata) {
185
+ const usage = usageFrom(metadata.normalizedUsage) ?? usageFrom(metadata.usage) ?? usageFrom(metadata);
186
+ if (usage === void 0) return;
187
+ assignNumber(attributes, "gen_ai.usage.input_tokens", usage.inputTokens);
188
+ assignNumber(attributes, "gen_ai.usage.output_tokens", usage.outputTokens);
189
+ assignNumber(attributes, "llm.token_count.prompt", usage.inputTokens);
190
+ assignNumber(attributes, "llm.token_count.completion", usage.outputTokens);
191
+ assignNumber(attributes, "lattice.usage.cost_usd", usage.costUsd);
192
+ }
193
+ function usageFrom(value) {
194
+ if (!isRecord(value)) return;
195
+ const inputTokens = asNumber(value.promptTokens) ?? asNumber(value.inputTokens);
196
+ const outputTokens = asNumber(value.completionTokens) ?? asNumber(value.outputTokens);
197
+ const costUsd = asNumber(value.costUsd);
198
+ if (inputTokens === void 0 && outputTokens === void 0 && costUsd === void 0) return;
199
+ return {
200
+ ...inputTokens !== void 0 ? { inputTokens } : {},
201
+ ...outputTokens !== void 0 ? { outputTokens } : {},
202
+ ...costUsd !== void 0 ? { costUsd } : {}
203
+ };
204
+ }
205
+ function assignGateway(attributes, value) {
206
+ if (!isRecord(value)) return;
207
+ assignBoolean(attributes, "lattice.gateway.used", asBoolean(value.used));
208
+ assignString(attributes, "lattice.gateway.provider.id", asString(value.providerId));
209
+ assignString(attributes, "lattice.gateway.selected_provider.id", asString(value.selectedProviderId));
210
+ assignString(attributes, "lattice.gateway.requested_model", asString(value.requestedModel));
211
+ assignString(attributes, "lattice.gateway.observed_model", asString(value.observedModel));
212
+ assignStringArray(attributes, "lattice.gateway.fallback_models", asStringArray(value.fallbackModels));
213
+ const requestedModel = asString(value.requestedModel);
214
+ const observedModel = asString(value.observedModel);
215
+ if (requestedModel !== void 0 && attributes["gen_ai.request.model"] === void 0) attributes["gen_ai.request.model"] = requestedModel;
216
+ assignString(attributes, "gen_ai.response.model", observedModel);
217
+ }
218
+ function captureSafeMetadata(attributes, metadata, options) {
219
+ if (options.contentCapture !== "metadata") return;
220
+ const knownKeys = new Set([
221
+ "callId",
222
+ "estimatedTokens",
223
+ "error",
224
+ "fallback",
225
+ "fallbacks",
226
+ "gateway",
227
+ "included",
228
+ "invariantId",
229
+ "mintError",
230
+ "normalizedUsage",
231
+ "omitted",
232
+ "outputNames",
233
+ "reason",
234
+ "receiptId",
235
+ "rejected",
236
+ "selected",
237
+ "source",
238
+ "status",
239
+ "summarized",
240
+ "toolName",
241
+ "usage"
242
+ ]);
243
+ for (const [key, value] of Object.entries(metadata)) {
244
+ if (knownKeys.has(key) || isUnsafeMetadataKey(key)) continue;
245
+ const attrKey = `lattice.metadata.${safeAttributeKey(key)}`;
246
+ assignString(attributes, attrKey, asString(value));
247
+ assignNumber(attributes, attrKey, asNumber(value));
248
+ assignBoolean(attributes, attrKey, asBoolean(value));
249
+ assignStringArray(attributes, attrKey, asStringArray(value));
250
+ assignNumberArray(attributes, attrKey, asNumberArray(value));
251
+ assignBooleanArray(attributes, attrKey, asBooleanArray(value));
252
+ }
253
+ }
254
+ function isUnsafeMetadataKey(key) {
255
+ return SECRET_KEY_RE.test(key) || CONTENT_KEY_RE.test(key);
256
+ }
257
+ function safeAttributeKey(key) {
258
+ return key.replace(/[^a-zA-Z0-9_.-]+/gu, "_");
259
+ }
260
+ function findReceiptEnvelope(metadata) {
261
+ if (metadata === void 0) return;
262
+ return [
263
+ metadata.envelope,
264
+ metadata.receiptEnvelope,
265
+ metadata.receipt
266
+ ].find(isReceiptEnvelope);
267
+ }
268
+ function isReceiptEnvelope(value) {
269
+ return isRecord(value) && value.payloadType === "application/vnd.lattice.receipt+json" && typeof value.payload === "string" && Array.isArray(value.signatures) && value.signatures.every((signature) => isRecord(signature) && typeof signature.keyid === "string" && typeof signature.sig === "string");
270
+ }
271
+ function isRecord(value) {
272
+ return typeof value === "object" && value !== null && !Array.isArray(value);
273
+ }
274
+ function langfuseAuthString(options) {
275
+ if (options.authString !== void 0) return options.authString;
276
+ if (options.publicKey === void 0 && options.secretKey === void 0) return;
277
+ if (options.publicKey === void 0 || options.secretKey === void 0) throw new Error("Langfuse OTLP auth requires both publicKey and secretKey.");
278
+ return base64Utf8(`${options.publicKey}:${options.secretKey}`);
279
+ }
280
+ function langfuseTraceEndpoint(baseUrl) {
281
+ const base = trimTrailingSlashes(baseUrl);
282
+ if (base.endsWith("/api/public/otel/v1/traces")) return base;
283
+ if (base.endsWith("/api/public/otel")) return `${base}/v1/traces`;
284
+ return `${base}/api/public/otel/v1/traces`;
285
+ }
286
+ function phoenixTraceEndpoint(baseUrl) {
287
+ const base = trimTrailingSlashes(baseUrl);
288
+ if (base.endsWith("/v1/traces")) return base;
289
+ return `${base}/v1/traces`;
290
+ }
291
+ function trimTrailingSlashes(value) {
292
+ return value.replace(/\/+$/u, "");
293
+ }
294
+ function base64Utf8(value) {
295
+ const bytes = new TextEncoder().encode(value);
296
+ let binary = "";
297
+ for (const byte of bytes) binary += String.fromCharCode(byte);
298
+ return btoa(binary);
299
+ }
300
+ //#endregion
301
+ //#region src/receipts/keyset.ts
302
+ /**
303
+ * In-memory KeySet factory.
304
+ *
305
+ * Verification flow (plan 09-03):
306
+ * - keySet.lookup(kid) returns undefined → VerifyError {kind: "key-not-found"}
307
+ * - entry.state === "revoked" → VerifyError {kind: "key-revoked"}
308
+ * - entry.state === "retired" → VerifyOk + keyState: "retired" (caller may warn)
309
+ * - entry.state === "active" → VerifyOk + keyState: "active"
310
+ *
311
+ * Duplicate kids: last write wins (deterministic — callers control entry order).
312
+ * Empty entries array is legal — every lookup returns undefined.
313
+ * Returned KeySet exposes only `lookup` — no enumeration.
314
+ *
315
+ * See 09-CONTEXT.md "Key Management (UNRETROFITTABLE)".
316
+ */
317
+ function createMemoryKeySet(entries) {
318
+ const byKid = /* @__PURE__ */ new Map();
319
+ for (const entry of entries) byKid.set(entry.kid, entry);
320
+ return { lookup(kid) {
321
+ return byKid.get(kid);
322
+ } };
323
+ }
324
+ //#endregion
325
+ //#region src/receipts/remote-signer.ts
326
+ /**
327
+ * Adapt a remote signing service to Lattice's existing ReceiptSigner contract.
328
+ *
329
+ * The callback receives the exact DSSE PAE bytes that createReceipt signs.
330
+ * Cloud-specific request construction, hashing choices, credentials, retries,
331
+ * and audit logging stay outside core.
332
+ */
333
+ function createRemoteReceiptSigner(options) {
334
+ return {
335
+ kid: options.kid,
336
+ publicKeyJwk: options.publicKeyJwk,
337
+ async sign(bytes) {
338
+ const result = await options.sign({
339
+ kid: options.kid,
340
+ publicKeyJwk: options.publicKeyJwk,
341
+ bytes: copyBytes(bytes),
342
+ payloadFormat: "dsse-pae",
343
+ algorithm: "Ed25519",
344
+ ...options.provider !== void 0 ? { provider: options.provider } : {},
345
+ ...options.keyRef !== void 0 ? { keyRef: options.keyRef } : {},
346
+ ...options.metadata !== void 0 ? { metadata: options.metadata } : {}
347
+ });
348
+ return copyBytes(result instanceof Uint8Array ? result : result.signature);
349
+ }
350
+ };
351
+ }
352
+ function copyBytes(bytes) {
353
+ const copy = new Uint8Array(bytes.byteLength);
354
+ copy.set(bytes);
355
+ return copy;
356
+ }
357
+ //#endregion
358
+ //#region src/receipts/sign.ts
359
+ const ALG = "Ed25519";
360
+ /**
361
+ * Copy a Uint8Array into a fresh ArrayBuffer. WebCrypto's BufferSource type
362
+ * (under exactOptionalPropertyTypes + strict TS) rejects `Uint8Array<ArrayBufferLike>`
363
+ * because the underlying buffer could be a SharedArrayBuffer. Matches the
364
+ * pattern used in storage/fingerprint.ts.
365
+ */
366
+ function toArrayBuffer(bytes) {
367
+ const copy = new Uint8Array(bytes.byteLength);
368
+ copy.set(bytes);
369
+ return copy.buffer;
370
+ }
371
+ async function importEd25519PrivateKey(jwk) {
372
+ return crypto.subtle.importKey("jwk", jwk, ALG, true, ["sign"]);
373
+ }
374
+ async function importEd25519PublicKey(jwk) {
375
+ return crypto.subtle.importKey("jwk", jwk, ALG, true, ["verify"]);
376
+ }
377
+ async function generateEd25519KeyPairJwk() {
378
+ const pair = await crypto.subtle.generateKey(ALG, true, ["sign", "verify"]);
379
+ const [privateKeyJwk, publicKeyJwk] = await Promise.all([crypto.subtle.exportKey("jwk", pair.privateKey), crypto.subtle.exportKey("jwk", pair.publicKey)]);
380
+ return {
381
+ privateKeyJwk,
382
+ publicKeyJwk
383
+ };
384
+ }
385
+ async function verifyEd25519Signature(publicKeyJwk, message, signature) {
386
+ let key;
387
+ try {
388
+ key = await importEd25519PublicKey(publicKeyJwk);
389
+ } catch {
390
+ return false;
391
+ }
392
+ try {
393
+ return await crypto.subtle.verify(ALG, key, toArrayBuffer(signature), toArrayBuffer(message));
394
+ } catch {
395
+ return false;
396
+ }
397
+ }
398
+ function createInMemorySigner(privateKeyJwk, options) {
399
+ let cachedKey;
400
+ const ensureKey = async () => {
401
+ if (cachedKey === void 0) cachedKey = await importEd25519PrivateKey(privateKeyJwk);
402
+ return cachedKey;
403
+ };
404
+ return {
405
+ kid: options.kid,
406
+ publicKeyJwk: options.publicKeyJwk,
407
+ async sign(bytes) {
408
+ const key = await ensureKey();
409
+ const sig = await crypto.subtle.sign(ALG, key, toArrayBuffer(bytes));
410
+ return new Uint8Array(sig);
411
+ }
412
+ };
413
+ }
414
+ //#endregion
415
+ //#region src/receipts/verify.ts
416
+ function fail$1(kind, message) {
417
+ return {
418
+ ok: false,
419
+ error: {
420
+ kind,
421
+ message
422
+ }
423
+ };
424
+ }
425
+ function bytesEqual(a, b) {
426
+ if (a.byteLength !== b.byteLength) return false;
427
+ for (let i = 0; i < a.byteLength; i += 1) if (a[i] !== b[i]) return false;
428
+ return true;
429
+ }
430
+ /**
431
+ * Receipt body shape check. We trust the JSON parse — but we re-validate
432
+ * that the required fields exist with the right primitive types before
433
+ * canonicalizing again. Anything off -> version-mismatch (the body is
434
+ * structurally NOT a v1 receipt, even if it parses as JSON).
435
+ */
436
+ function asReceiptBody(value) {
437
+ if (typeof value !== "object" || value === null) return void 0;
438
+ const v = value;
439
+ if (v.version !== void 0 && v.version !== "lattice-receipt/v1" && v.version !== "lattice-receipt/v1.1" && v.version !== "lattice-receipt/v1.2" && v.version !== "lattice-receipt/v1.3") return;
440
+ if (typeof v.receiptId !== "string") return void 0;
441
+ if (typeof v.runId !== "string") return void 0;
442
+ if (typeof v.issuedAt !== "string") return void 0;
443
+ if (typeof v.kid !== "string") return void 0;
444
+ if (typeof v.model !== "object" || v.model === null) return void 0;
445
+ if (typeof v.route !== "object" || v.route === null) return void 0;
446
+ if (typeof v.usage !== "object" || v.usage === null) return void 0;
447
+ if (typeof v.contractVerdict !== "string") return void 0;
448
+ if (!Array.isArray(v.inputHashes)) return void 0;
449
+ if (typeof v.redactionPolicyId !== "string") return void 0;
450
+ if (!Array.isArray(v.redactions)) return void 0;
451
+ return v;
452
+ }
453
+ /**
454
+ * Pure receipt verifier.
455
+ *
456
+ * Returns a typed VerifyResult — never throws across the verification
457
+ * boundary (PITFALLS.md security: "Verifier panics on malformed receipts
458
+ * -> DoS via crafted input"). All parsing failures become typed errors.
459
+ *
460
+ * Decision tree (first match wins):
461
+ * 1. decodeEnvelope throws OR signatures[] empty -> envelope-malformed
462
+ * 2. payload bytes are not valid JSON -> envelope-malformed
463
+ * 3. body shape check fails OR version unknown literal -> version-mismatch
464
+ * 4. body.version === undefined OR "lattice-receipt/v1"-> schema-version-too-low (CRYPTO-01)
465
+ * 5. keySet.lookup(keyid) === undefined -> key-not-found
466
+ * 6. entry.state === "revoked" -> key-revoked
467
+ * 7. re-canonicalized body != signed payloadBytes -> canonicalization-mismatch
468
+ * 8. Ed25519 verification of PAE fails -> signature-invalid
469
+ * 9. body.kid !== entry.kid (defense in depth) -> signature-invalid
470
+ * 10. otherwise -> ok + keyState
471
+ */
472
+ async function verifyReceipt(envelope, keySet) {
473
+ let decoded;
474
+ try {
475
+ decoded = decodeEnvelope(envelope);
476
+ } catch (error) {
477
+ return fail$1("envelope-malformed", error instanceof Error ? error.message : String(error));
478
+ }
479
+ if (decoded.signatures.length === 0) return fail$1("envelope-malformed", "envelope has no signatures");
480
+ let parsed;
481
+ try {
482
+ parsed = JSON.parse(new TextDecoder().decode(decoded.payloadBytes));
483
+ } catch (error) {
484
+ return fail$1("envelope-malformed", `payload is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
485
+ }
486
+ const body = asReceiptBody(parsed);
487
+ if (body === void 0) return fail$1("version-mismatch", "receipt body is not a lattice-receipt/v1.1, lattice-receipt/v1.2, or lattice-receipt/v1.3 shape");
488
+ if (body.version === void 0 || body.version === "lattice-receipt/v1") return fail$1("schema-version-too-low", "Receipt body.version must be 'lattice-receipt/v1.1', 'lattice-receipt/v1.2', or 'lattice-receipt/v1.3' — v1 receipts are not accepted (CRYPTO-01).");
489
+ const firstSig = decoded.signatures[0];
490
+ const entry = keySet.lookup(firstSig.keyid);
491
+ if (entry === void 0) return fail$1("key-not-found", `keySet has no entry for kid "${firstSig.keyid}"`);
492
+ if (entry.state === "revoked") return fail$1("key-revoked", `key "${entry.kid}" is revoked`);
493
+ if (!bytesEqual(canonicalizeReceiptBody(body), decoded.payloadBytes)) return fail$1("canonicalization-mismatch", "re-canonicalized body does not match signed payload bytes");
494
+ const pae = buildPae(PAYLOAD_TYPE, base64Encode(decoded.payloadBytes));
495
+ if (!await verifyEd25519Signature(entry.publicKeyJwk, pae, firstSig.sig)) return fail$1("signature-invalid", "Ed25519 signature does not verify");
496
+ if (body.kid !== entry.kid) return fail$1("signature-invalid", `body.kid "${body.kid}" does not match envelope keyid "${entry.kid}"`);
497
+ return {
498
+ ok: true,
499
+ body,
500
+ keyState: entry.state
501
+ };
502
+ }
503
+ //#endregion
504
+ //#region src/version.ts
505
+ const latticeVersion = "1.5.0";
506
+ //#endregion
507
+ //#region src/audit/external-execution.ts
508
+ async function createExternalExecutionAudit(input, signer) {
509
+ const runId = input.runId ?? createId("external-run");
510
+ const receiptId = input.receiptId ?? createId("external-receipt");
511
+ const issuedAt = input.issuedAt ?? (/* @__PURE__ */ new Date()).toISOString();
512
+ const artifacts = input.artifacts ?? [];
513
+ const artifactRefs = artifacts.map(toArtifactRef);
514
+ const outputSpecs = input.outputSpecs ?? inferOutputSpecs(input.outputs);
515
+ const inputHashes = await hashInputArtifacts(artifacts);
516
+ const outputHash = input.outputs === void 0 ? null : await hashUnknown(input.outputs);
517
+ const contractHash = await hashCanonical(input.contract);
518
+ const lineageMerkleRoot = await computeArtifactLineageMerkleRoot(artifacts);
519
+ const rawRequestHash = input.rawRequest === void 0 ? void 0 : await hashUnknown(input.rawRequest) ?? void 0;
520
+ const rawResponseHash = input.rawResponse === void 0 ? void 0 : await hashUnknown(input.rawResponse) ?? void 0;
521
+ const contractVerdict = input.contractVerdict ?? "success";
522
+ const receipt = await createReceipt({
523
+ runId,
524
+ receiptId,
525
+ issuedAt,
526
+ model: input.model,
527
+ route: input.route,
528
+ ...lineageMerkleRoot !== void 0 ? { lineageMerkleRoot } : {},
529
+ usage: input.usage,
530
+ contractVerdict,
531
+ contractHash,
532
+ inputHashes,
533
+ outputHash
534
+ }, signer);
535
+ return {
536
+ receipt,
537
+ sidecar: {
538
+ version: "lattice-sidecar/v1",
539
+ task: input.task,
540
+ outputs: outputSpecs,
541
+ policy: input.policy,
542
+ contract: input.contract,
543
+ ...input.outputs !== void 0 ? { rawOutputs: input.outputs } : {},
544
+ externalExecution: {
545
+ kind: "external-execution",
546
+ model: input.model,
547
+ route: input.route,
548
+ usage: input.usage,
549
+ ...input.rawRequest !== void 0 ? { rawRequest: input.rawRequest } : {},
550
+ ...input.rawResponse !== void 0 ? { rawResponse: input.rawResponse } : {},
551
+ ...rawRequestHash !== void 0 ? { rawRequestHash } : {},
552
+ ...rawResponseHash !== void 0 ? { rawResponseHash } : {},
553
+ inputHashes,
554
+ outputHash,
555
+ ...input.metadata !== void 0 ? { metadata: input.metadata } : {}
556
+ }
557
+ },
558
+ replayEnvelope: createExternalReplayEnvelope({
559
+ runId,
560
+ task: input.task,
561
+ artifacts: artifactRefs,
562
+ outputSpecs,
563
+ outputs: input.outputs,
564
+ catalogVersion: input.catalogVersion ?? "external",
565
+ route: input.route,
566
+ usage: input.usage,
567
+ receipt,
568
+ contract: input.contract,
569
+ contractVerdict,
570
+ metadata: input.metadata
571
+ }),
572
+ inputHashes,
573
+ outputHash
574
+ };
575
+ }
576
+ function createExternalReplayEnvelope(input) {
577
+ const isSuccess = input.contractVerdict === "success";
578
+ const attempt = {
579
+ providerId: input.route.providerId,
580
+ modelId: input.route.capabilityId,
581
+ status: isSuccess ? "succeeded" : "failed",
582
+ usage: usageRecord(input.usage),
583
+ metadata: { externalExecution: true },
584
+ ...!isSuccess ? { error: input.contractVerdict } : {}
585
+ };
586
+ const plan = withPlanStatus(createExecutionPlan({
587
+ task: input.task,
588
+ artifacts: input.artifacts,
589
+ outputs: input.outputSpecs,
590
+ route: {
591
+ catalogVersion: input.catalogVersion,
592
+ selected: {
593
+ providerId: input.route.providerId,
594
+ modelId: input.route.capabilityId,
595
+ score: 0,
596
+ estimates: {
597
+ inputTokens: input.usage.promptTokens,
598
+ outputTokens: input.usage.completionTokens,
599
+ ...input.usage.costUsd !== null ? { costUsd: input.usage.costUsd } : {}
600
+ },
601
+ inputModalities: [],
602
+ outputModalities: [],
603
+ fileTransport: []
604
+ },
605
+ candidates: [],
606
+ rejected: [],
607
+ fallbackChain: [],
608
+ noRouteReasons: []
609
+ },
610
+ metadata: {
611
+ externalExecution: true,
612
+ runId: input.runId,
613
+ contractVerdict: input.contractVerdict,
614
+ ...input.metadata !== void 0 ? { external: input.metadata } : {}
615
+ }
616
+ }), isSuccess ? "completed" : "failed", {
617
+ stages: isSuccess ? markAllStagesCompleted : markExternalStagesFailed(input.contractVerdict),
618
+ attempts: [attempt]
619
+ });
620
+ return {
621
+ kind: "replay-envelope",
622
+ version: 1,
623
+ runtimeVersion: latticeVersion,
624
+ catalogVersion: input.catalogVersion,
625
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
626
+ plan,
627
+ artifacts: input.artifacts,
628
+ ...isSuccess && input.outputs !== void 0 ? { outputs: input.outputs } : {},
629
+ warnings: [],
630
+ errors: isSuccess ? [] : [input.contractVerdict],
631
+ usage: usageRecord(input.usage),
632
+ events: [],
633
+ receipt: input.receipt,
634
+ contract: input.contract
635
+ };
636
+ }
637
+ function markExternalStagesFailed(verdict) {
638
+ const failedStage = failedStageForVerdict(verdict);
639
+ let hasFailed = false;
640
+ return markAllStagesCompleted.map((stage) => {
641
+ if (stage.kind === failedStage) {
642
+ hasFailed = true;
643
+ return {
644
+ ...stage,
645
+ status: "failed",
646
+ warnings: [...stage.warnings, verdict]
647
+ };
648
+ }
649
+ if (hasFailed) return {
650
+ ...stage,
651
+ status: "skipped"
652
+ };
653
+ return stage;
654
+ });
655
+ }
656
+ function failedStageForVerdict(verdict) {
657
+ switch (verdict) {
658
+ case "validation-failed": return "validation";
659
+ case "tripwire-violated": return "tripwire";
660
+ case "no-contract-match": return "analysis";
661
+ case "execution-failed":
662
+ case "success": return "execution";
663
+ }
664
+ }
665
+ function usageRecord(usage) {
666
+ return {
667
+ inputTokens: usage.promptTokens,
668
+ outputTokens: usage.completionTokens,
669
+ totalTokens: usage.promptTokens + usage.completionTokens,
670
+ ...usage.costUsd !== null ? { costUsd: usage.costUsd } : {}
671
+ };
672
+ }
673
+ function inferOutputSpecs(outputs) {
674
+ if (outputs === void 0) return {};
675
+ return Object.fromEntries(Object.keys(outputs).map((name) => [name, "text"]));
676
+ }
677
+ async function hashInputArtifacts(artifacts) {
678
+ const hashes = [];
679
+ for (const artifact of artifacts) hashes.push(artifact.fingerprint?.value ?? await hashUnknown(artifact.value) ?? "");
680
+ return hashes;
681
+ }
682
+ async function hashUnknown(value) {
683
+ return (await fingerprintArtifactValue(value))?.value ?? null;
684
+ }
685
+ async function hashCanonical(value) {
686
+ const canonical = canonicalize(value);
687
+ if (canonical === void 0) return null;
688
+ return hashUnknown(canonical);
689
+ }
690
+ function createId(prefix) {
691
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") return `${prefix}:${crypto.randomUUID()}`;
692
+ return `${prefix}:${Date.now()}:${Math.random().toString(16).slice(2)}`;
693
+ }
694
+ const markAllStagesCompleted = [
695
+ {
696
+ id: "stage:analysis",
697
+ kind: "analysis",
698
+ status: "completed",
699
+ warnings: []
700
+ },
701
+ {
702
+ id: "stage:transforms",
703
+ kind: "transforms",
704
+ status: "completed",
705
+ warnings: []
706
+ },
707
+ {
708
+ id: "stage:context-packing",
709
+ kind: "context-packing",
710
+ status: "completed",
711
+ warnings: []
712
+ },
713
+ {
714
+ id: "stage:provider-packaging",
715
+ kind: "provider-packaging",
716
+ status: "completed",
717
+ warnings: []
718
+ },
719
+ {
720
+ id: "stage:tool-execution",
721
+ kind: "tool-execution",
722
+ status: "completed",
723
+ warnings: []
724
+ },
725
+ {
726
+ id: "stage:execution",
727
+ kind: "execution",
728
+ status: "completed",
729
+ warnings: []
730
+ },
731
+ {
732
+ id: "stage:validation",
733
+ kind: "validation",
734
+ status: "completed",
735
+ warnings: []
736
+ },
737
+ {
738
+ id: "stage:tripwire",
739
+ kind: "tripwire",
740
+ status: "completed",
741
+ warnings: []
742
+ },
743
+ {
744
+ id: "stage:persistence",
745
+ kind: "persistence",
746
+ status: "completed",
747
+ warnings: []
748
+ }
749
+ ];
750
+ //#endregion
751
+ //#region src/replay/materialize.ts
752
+ function asMaterializationError(value) {
753
+ return typeof value === "object" && value !== null && typeof value.kind === "string" && typeof value.message === "string";
754
+ }
755
+ /** Throwable shape — `instanceof Error` is not required for typed unions, so
756
+ * the function just throws a plain object literal that matches the
757
+ * `MaterializationError` shape. Callers pattern-match on `err.kind`. */
758
+ function fail(kind, message) {
759
+ return {
760
+ kind,
761
+ message
762
+ };
763
+ }
764
+ /**
765
+ * Pure async function that reconstructs a `ReplayEnvelope` from a receipt.
766
+ *
767
+ * Verify-FIRST ordering: `verifyReceipt` runs before `artifactLoader` is
768
+ * touched. Tampered receipts MUST NOT cause loader side effects.
769
+ */
770
+ async function materializeReplayEnvelope(receipt, options) {
771
+ const verifyResult = await verifyReceipt(receipt, options.keySet);
772
+ if (!verifyResult.ok) throw fail(verifyResult.error.kind === "envelope-malformed" ? "envelope-malformed" : "verify-failed", verifyResult.error.message);
773
+ const body = verifyResult.body;
774
+ const loadedInputs = [];
775
+ for (const hash of body.inputHashes) {
776
+ if (hash === "") continue;
777
+ try {
778
+ const input = await options.artifactLoader(hash);
779
+ loadedInputs.push(input);
780
+ } catch (error) {
781
+ throw fail("artifact-load-failed", error instanceof Error ? error.message : asMaterializationError(error) ? error.message : String(error));
782
+ }
783
+ }
784
+ const artifactRefs = loadedInputs.map(toArtifactRef);
785
+ const outputsMap = options.outputs !== void 0 ? Object.fromEntries(Object.keys(options.outputs).map((k) => [k, "text"])) : {};
786
+ const plan = createExecutionPlan({
787
+ task: options.task ?? "",
788
+ artifacts: artifactRefs,
789
+ outputs: outputsMap,
790
+ route: {
791
+ catalogVersion: "materialized",
792
+ selected: {
793
+ providerId: body.route.providerId,
794
+ modelId: body.route.capabilityId,
795
+ score: 0,
796
+ estimates: {
797
+ inputTokens: 0,
798
+ outputTokens: 0
799
+ },
800
+ inputModalities: [],
801
+ outputModalities: [],
802
+ fileTransport: []
803
+ },
804
+ candidates: [],
805
+ rejected: [],
806
+ fallbackChain: [],
807
+ noRouteReasons: []
808
+ },
809
+ warnings: [],
810
+ metadata: {
811
+ materialized: true,
812
+ receiptId: body.receiptId,
813
+ runId: body.runId,
814
+ contractVerdict: body.contractVerdict,
815
+ ...options.policy !== void 0 ? { policy: { ...options.policy } } : {}
816
+ }
817
+ });
818
+ const usage = {
819
+ inputTokens: body.usage.promptTokens,
820
+ outputTokens: body.usage.completionTokens,
821
+ ...body.usage.costUsd !== null ? { costUsd: Number(body.usage.costUsd) } : {}
822
+ };
823
+ return {
824
+ kind: "replay-envelope",
825
+ version: 1,
826
+ runtimeVersion: latticeVersion,
827
+ catalogVersion: "materialized",
828
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
829
+ plan,
830
+ artifacts: artifactRefs,
831
+ ...options.outputs !== void 0 ? { outputs: options.outputs } : {},
832
+ warnings: [],
833
+ errors: [],
834
+ usage,
835
+ events: [],
836
+ receipt,
837
+ ...options.contract !== void 0 ? { contract: options.contract } : {}
838
+ };
839
+ }
840
+ //#endregion
841
+ //#region src/replay/replay.ts
842
+ function createReplayEnvelope(result) {
843
+ if (result.plan.kind !== "execution-plan") throw new Error("Replay envelopes require an execution plan.");
844
+ const usage = result.plan.attempts.at(-1)?.usage;
845
+ return {
846
+ kind: "replay-envelope",
847
+ version: 1,
848
+ runtimeVersion: latticeVersion,
849
+ catalogVersion: result.plan.route.catalogVersion,
850
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
851
+ plan: redactPlan(result.plan),
852
+ artifacts: result.ok ? result.artifacts : result.plan.artifactRefs,
853
+ ...result.ok ? { outputs: result.outputs } : {},
854
+ warnings: result.plan.warnings,
855
+ errors: result.ok ? [] : [result.error.message],
856
+ ...usage !== void 0 ? { usage } : {},
857
+ events: result.events ?? []
858
+ };
859
+ }
860
+ async function replayOffline(envelope) {
861
+ const replayedUsage = envelopeUsage(envelope);
862
+ if (envelope.outputs === void 0) return {
863
+ ok: false,
864
+ error: {
865
+ kind: "execution_unavailable",
866
+ message: "Replay envelope does not contain successful outputs."
867
+ },
868
+ usage: replayedUsage,
869
+ plan: envelope.plan,
870
+ events: envelope.events
871
+ };
872
+ return {
873
+ ok: true,
874
+ outputs: envelope.outputs,
875
+ artifacts: envelope.artifacts,
876
+ usage: replayedUsage,
877
+ plan: envelope.plan,
878
+ events: envelope.events
879
+ };
880
+ }
881
+ function envelopeUsage(envelope) {
882
+ if (envelope.usage === void 0) return {
883
+ promptTokens: 0,
884
+ completionTokens: 0,
885
+ costUsd: null
886
+ };
887
+ return {
888
+ promptTokens: envelope.usage.inputTokens ?? 0,
889
+ completionTokens: envelope.usage.outputTokens ?? 0,
890
+ costUsd: envelope.usage.costUsd ?? null
891
+ };
892
+ }
893
+ async function rerunLive(ai, envelope, intent) {
894
+ const result = await ai.run(intent);
895
+ if (result.plan.kind === "execution-plan") return {
896
+ ...result,
897
+ plan: {
898
+ ...result.plan,
899
+ warnings: [...result.plan.warnings, `Live rerun of ${envelope.plan.id}: provider behavior, model versions, cost, and latency may differ.`]
900
+ }
901
+ };
902
+ return result;
903
+ }
904
+ function redactReplayEnvelope(envelope) {
905
+ return {
906
+ ...envelope,
907
+ plan: redactPlan(envelope.plan),
908
+ artifacts: envelope.artifacts.map(redactArtifactRef),
909
+ events: envelope.events.map((event) => {
910
+ const metadata = redactRecord(event.metadata);
911
+ return {
912
+ ...event,
913
+ ...metadata !== void 0 ? { metadata } : {}
914
+ };
915
+ })
916
+ };
917
+ }
918
+ function redactPlan(plan) {
919
+ return {
920
+ ...plan,
921
+ task: redactText(plan.task),
922
+ artifactRefs: plan.artifactRefs.map(redactArtifactRef),
923
+ ...plan.providerPackaging !== void 0 ? { providerPackaging: {
924
+ ...plan.providerPackaging,
925
+ artifacts: plan.providerPackaging.artifacts.map((item) => ({
926
+ ...item,
927
+ warnings: item.warnings.map(redactText)
928
+ })),
929
+ warnings: plan.providerPackaging.warnings.map(redactText)
930
+ } } : {},
931
+ warnings: plan.warnings.map(redactText)
932
+ };
933
+ }
934
+ function redactArtifactRef(ref) {
935
+ const redactedMetadata = redactRecord(ref.metadata);
936
+ return {
937
+ ...ref,
938
+ ...redactedMetadata !== void 0 ? { metadata: redactedMetadata } : {},
939
+ ...ref.source === "url" ? { metadata: {
940
+ ...redactedMetadata,
941
+ redactedSource: "url"
942
+ } } : {}
943
+ };
944
+ }
945
+ function redactRecord(record) {
946
+ if (record === void 0) return;
947
+ return Object.fromEntries(Object.entries(record).map(([key, value]) => [key, shouldRedactKey(key) ? "[redacted]" : redactValue(value)]));
948
+ }
949
+ function redactValue(value) {
950
+ if (typeof value === "string") return redactText(value);
951
+ if (Array.isArray(value)) return value.map(redactValue);
952
+ if (typeof value === "object" && value !== null) return redactRecord(value);
953
+ return value;
954
+ }
955
+ function redactText(value) {
956
+ return value.replace(/Bearer\s+[A-Za-z0-9._-]+/gu, "Bearer [redacted]").replace(/https?:\/\/[^\s)]+/gu, "[redacted-url]").replace(/[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/gu, "[redacted-email]");
957
+ }
958
+ function shouldRedactKey(key) {
959
+ return /api.?key|authorization|token|secret|password|credential|signed.?url|raw|body|transcript/iu.test(key);
960
+ }
961
+ //#endregion
962
+ export { createOtelRunEventSink as _, replayOffline as a, createExternalExecutionAudit as c, createInMemorySigner as d, generateEd25519KeyPairJwk as f, createOtelReceiptAttributes as g, createLangfuseOtlpConfig as h, redactReplayEnvelope as i, latticeVersion as l, createMemoryKeySet as m, redactArtifactRef as n, rerunLive as o, createRemoteReceiptSigner as p, redactPlan as r, materializeReplayEnvelope as s, createReplayEnvelope as t, verifyReceipt as u, createPhoenixOtlpConfig as v, sanitizeRunEventAttributes as y };
963
+
964
+ //# sourceMappingURL=replay-CtIhpLek.js.map