@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.
- package/dist/agent-run-C6miAzwI.d.ts +45 -0
- package/dist/agent-run-C6miAzwI.d.ts.map +1 -0
- package/dist/agent-run-CgPVFl0Z.js +47 -0
- package/dist/agent-run-CgPVFl0Z.js.map +1 -0
- package/dist/agents.d.ts +5 -0
- package/dist/agents.js +6 -0
- package/dist/artifact-Bg6mJGnm.d.ts +125 -0
- package/dist/artifact-Bg6mJGnm.d.ts.map +1 -0
- package/dist/artifact-DOfpeXLb.js +140 -0
- package/dist/artifact-DOfpeXLb.js.map +1 -0
- package/dist/artifacts.d.ts +2 -0
- package/dist/artifacts.js +2 -0
- package/dist/audit.d.ts +3 -0
- package/dist/audit.js +4 -0
- package/dist/catalog-CAfYwB_-.js +91 -0
- package/dist/catalog-CAfYwB_-.js.map +1 -0
- package/dist/context-pack-Bz3GXmjv.js +99 -0
- package/dist/context-pack-Bz3GXmjv.js.map +1 -0
- package/dist/context.d.ts +2 -0
- package/dist/context.js +2 -0
- package/dist/contract-S3oJGlc9.d.ts +74 -0
- package/dist/contract-S3oJGlc9.d.ts.map +1 -0
- package/dist/core.d.ts +48 -0
- package/dist/core.d.ts.map +1 -0
- package/dist/core.js +95 -0
- package/dist/core.js.map +1 -0
- package/dist/errors-eEuEIx6X.js +407 -0
- package/dist/errors-eEuEIx6X.js.map +1 -0
- package/dist/eval.d.ts +2 -0
- package/dist/eval.js +2 -0
- package/dist/fingerprint-DodDbQKN.js +34 -0
- package/dist/fingerprint-DodDbQKN.js.map +1 -0
- package/dist/index-DpnHGHVL.d.ts +53 -0
- package/dist/index-DpnHGHVL.d.ts.map +1 -0
- package/dist/index.d.ts +90 -3533
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -15968
- package/dist/index.js.map +1 -1
- package/dist/infer-DLqp5QIM.d.ts +96 -0
- package/dist/infer-DLqp5QIM.d.ts.map +1 -0
- package/dist/lineage-DBgoPWAZ.js +137 -0
- package/dist/lineage-DBgoPWAZ.js.map +1 -0
- package/dist/local-CXOGPJ1f.js +139 -0
- package/dist/local-CXOGPJ1f.js.map +1 -0
- package/dist/local-Dy--7peL.d.ts +10 -0
- package/dist/local-Dy--7peL.d.ts.map +1 -0
- package/dist/memory-CkQEW6m5.js +62 -0
- package/dist/memory-CkQEW6m5.js.map +1 -0
- package/dist/memory-DRig5EHV.d.ts +10 -0
- package/dist/memory-DRig5EHV.d.ts.map +1 -0
- package/dist/negotiate-ClD88hkc.js +10967 -0
- package/dist/negotiate-ClD88hkc.js.map +1 -0
- package/dist/otel-BgM4e55_.d.ts +421 -0
- package/dist/otel-BgM4e55_.d.ts.map +1 -0
- package/dist/permission-context-CUKMo79F.js +134 -0
- package/dist/permission-context-CUKMo79F.js.map +1 -0
- package/dist/plan-DFm8Llep.js +125 -0
- package/dist/plan-DFm8Llep.js.map +1 -0
- package/dist/preflight-DNHWuJ46.d.ts +64 -0
- package/dist/preflight-DNHWuJ46.d.ts.map +1 -0
- package/dist/provider-C2IfKsvz.d.ts +1178 -0
- package/dist/provider-C2IfKsvz.d.ts.map +1 -0
- package/dist/providers.d.ts +4 -0
- package/dist/providers.js +4 -0
- package/dist/rate-limit-group-nDsBJqSu.d.ts +235 -0
- package/dist/rate-limit-group-nDsBJqSu.d.ts.map +1 -0
- package/dist/receipt-FYouoPHv.js +205 -0
- package/dist/receipt-FYouoPHv.js.map +1 -0
- package/dist/replay-CtIhpLek.js +964 -0
- package/dist/replay-CtIhpLek.js.map +1 -0
- package/dist/result-DLEx2WvU.d.ts +38 -0
- package/dist/result-DLEx2WvU.d.ts.map +1 -0
- package/dist/router-DU4Z3pTd.js +314 -0
- package/dist/router-DU4Z3pTd.js.map +1 -0
- package/dist/router-Yo1-aDOv.d.ts +42 -0
- package/dist/router-Yo1-aDOv.d.ts.map +1 -0
- package/dist/routing.d.ts +6 -0
- package/dist/routing.js +4 -0
- package/dist/{run-crew-CKdBjh5P.js → run-crew-B2fQLmgB.js} +7 -136
- package/dist/run-crew-B2fQLmgB.js.map +1 -0
- package/dist/run-crew-Bnve5dyI.d.ts +721 -0
- package/dist/run-crew-Bnve5dyI.d.ts.map +1 -0
- package/dist/{runtime-D25ehzCj.js → runtime-Dxiet5YS.js} +98 -641
- package/dist/runtime-Dxiet5YS.js.map +1 -0
- package/dist/scaffolds-DKQrCRqh.d.ts +535 -0
- package/dist/scaffolds-DKQrCRqh.d.ts.map +1 -0
- package/dist/scaffolds-ekPIlBeU.js +3139 -0
- package/dist/scaffolds-ekPIlBeU.js.map +1 -0
- package/dist/schema-CNfa_VEy.d.ts +15 -0
- package/dist/schema-CNfa_VEy.d.ts.map +1 -0
- package/dist/storage-DJKmsaEI.d.ts +26 -0
- package/dist/storage-DJKmsaEI.d.ts.map +1 -0
- package/dist/storage.d.ts +10 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +4 -0
- package/dist/tool-call-validation-BFoXkwbf.js +107 -0
- package/dist/tool-call-validation-BFoXkwbf.js.map +1 -0
- package/dist/tools-C4wHgGKQ.js +49 -0
- package/dist/tools-C4wHgGKQ.js.map +1 -0
- package/dist/tools.d.ts +46 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +106 -0
- package/dist/tools.js.map +1 -0
- package/dist/validate-c7EL5uuH.js +224 -0
- package/dist/validate-c7EL5uuH.js.map +1 -0
- package/package.json +99 -2
- package/dist/run-crew-CKdBjh5P.js.map +0 -1
- package/dist/runtime-D25ehzCj.js.map +0 -1
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Tt as TripwireEvidence, W as TrainingClass, dn as CitationRef, fn as CitationsOutputContract, mn as OutputContractMap, sn as RouteRejectReason, un as ArtifactRefsOutputContract } from "./provider-C2IfKsvz.js";
|
|
2
|
+
import { s as ArtifactRef } from "./artifact-Bg6mJGnm.js";
|
|
3
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
4
|
+
|
|
5
|
+
//#region src/receipts/types.d.ts
|
|
6
|
+
type ContractVerdict = "success" | "tripwire-violated" | "no-contract-match" | "execution-failed" | "validation-failed";
|
|
7
|
+
interface ReceiptUsageCanonical {
|
|
8
|
+
readonly promptTokens: number;
|
|
9
|
+
readonly completionTokens: number;
|
|
10
|
+
readonly costUsd: string | null;
|
|
11
|
+
}
|
|
12
|
+
interface ReceiptModel {
|
|
13
|
+
readonly requested: string;
|
|
14
|
+
readonly observed: string | null;
|
|
15
|
+
}
|
|
16
|
+
interface ReceiptRoute {
|
|
17
|
+
readonly providerId: string;
|
|
18
|
+
readonly capabilityId: string;
|
|
19
|
+
readonly attemptNumber: number;
|
|
20
|
+
}
|
|
21
|
+
interface ReceiptRedaction {
|
|
22
|
+
readonly path: string;
|
|
23
|
+
readonly reason: string;
|
|
24
|
+
}
|
|
25
|
+
interface CapabilityReceiptBody {
|
|
26
|
+
readonly version: "lattice-receipt/v1" | "lattice-receipt/v1.1" | "lattice-receipt/v1.2" | "lattice-receipt/v1.3";
|
|
27
|
+
readonly receiptId: string;
|
|
28
|
+
readonly runId: string;
|
|
29
|
+
readonly issuedAt: string;
|
|
30
|
+
readonly kid: string;
|
|
31
|
+
readonly model: ReceiptModel;
|
|
32
|
+
readonly route: ReceiptRoute;
|
|
33
|
+
readonly modelClass?: TrainingClass;
|
|
34
|
+
readonly parentReceiptCid?: string;
|
|
35
|
+
readonly lineageMerkleRoot?: string;
|
|
36
|
+
readonly usage: ReceiptUsageCanonical;
|
|
37
|
+
readonly contractVerdict: ContractVerdict;
|
|
38
|
+
readonly contractHash: string | null;
|
|
39
|
+
readonly inputHashes: readonly string[];
|
|
40
|
+
readonly outputHash: string | null;
|
|
41
|
+
readonly redactionPolicyId: string;
|
|
42
|
+
readonly redactions: readonly ReceiptRedaction[];
|
|
43
|
+
readonly noRouteReasons?: readonly RouteRejectReason[];
|
|
44
|
+
readonly tripwireEvidence?: TripwireEvidence;
|
|
45
|
+
readonly stepName?: string;
|
|
46
|
+
readonly stepIndex?: number;
|
|
47
|
+
readonly parentStepName?: string;
|
|
48
|
+
readonly previousStepName?: string;
|
|
49
|
+
readonly sessionId?: string;
|
|
50
|
+
readonly timestamp?: string;
|
|
51
|
+
}
|
|
52
|
+
interface ReceiptSignature {
|
|
53
|
+
readonly keyid: string;
|
|
54
|
+
readonly sig: string;
|
|
55
|
+
}
|
|
56
|
+
interface ReceiptEnvelope {
|
|
57
|
+
readonly payloadType: "application/vnd.lattice.receipt+json";
|
|
58
|
+
readonly payload: string;
|
|
59
|
+
readonly signatures: readonly ReceiptSignature[];
|
|
60
|
+
}
|
|
61
|
+
interface ReceiptSigner {
|
|
62
|
+
readonly kid: string;
|
|
63
|
+
sign(bytes: Uint8Array): Promise<Uint8Array>;
|
|
64
|
+
readonly publicKeyJwk: JsonWebKey;
|
|
65
|
+
}
|
|
66
|
+
type KeyState = "active" | "retired" | "revoked";
|
|
67
|
+
interface KeyEntry {
|
|
68
|
+
readonly kid: string;
|
|
69
|
+
readonly publicKeyJwk: JsonWebKey;
|
|
70
|
+
readonly state: KeyState;
|
|
71
|
+
}
|
|
72
|
+
interface KeySet {
|
|
73
|
+
lookup(kid: string): KeyEntry | undefined;
|
|
74
|
+
}
|
|
75
|
+
type VerifyErrorKind = "key-not-found" | "key-revoked" | "canonicalization-mismatch" | "signature-invalid" | "envelope-malformed" | "version-mismatch" | "schema-version-too-low";
|
|
76
|
+
interface VerifyError {
|
|
77
|
+
readonly kind: VerifyErrorKind;
|
|
78
|
+
readonly message: string;
|
|
79
|
+
}
|
|
80
|
+
interface VerifyOk {
|
|
81
|
+
readonly ok: true;
|
|
82
|
+
readonly body: CapabilityReceiptBody;
|
|
83
|
+
readonly keyState: KeyState;
|
|
84
|
+
}
|
|
85
|
+
interface VerifyFail {
|
|
86
|
+
readonly ok: false;
|
|
87
|
+
readonly error: VerifyError;
|
|
88
|
+
}
|
|
89
|
+
type VerifyResult = VerifyOk | VerifyFail;
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/outputs/infer.d.ts
|
|
92
|
+
type InferOutput<C> = C extends "text" ? string : C extends StandardSchemaV1 ? StandardSchemaV1.InferOutput<C> : C extends CitationsOutputContract ? readonly CitationRef[] : C extends ArtifactRefsOutputContract ? readonly ArtifactRef[] : never;
|
|
93
|
+
type InferOutputMap<T extends OutputContractMap> = { readonly [K in keyof T]: InferOutput<T[K]> };
|
|
94
|
+
//#endregion
|
|
95
|
+
export { VerifyFail as _, KeyEntry as a, ReceiptEnvelope as c, ReceiptRoute as d, ReceiptSignature as f, VerifyErrorKind as g, VerifyError as h, ContractVerdict as i, ReceiptModel as l, ReceiptUsageCanonical as m, InferOutputMap as n, KeySet as o, ReceiptSigner as p, CapabilityReceiptBody as r, KeyState as s, InferOutput as t, ReceiptRedaction as u, VerifyOk as v, VerifyResult as y };
|
|
96
|
+
//# sourceMappingURL=infer-DLqp5QIM.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"infer-DLqp5QIM.d.ts","names":[],"sources":["../src/receipts/types.ts","../src/outputs/infer.ts"],"mappings":";;;;;KAaY,eAAA;AAAA,UAOK,qBAAA;EAAA,SACN,YAAA;EAAA,SACA,gBAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGM,YAAA;EAAA,SACN,SAAA;EAAA,SACA,QAAA;AAAA;AAAA,UAGM,YAAA;EAAA,SACN,UAAA;EAAA,SACA,YAAA;EAAA,SACA,aAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,IAAA;EAAA,SACA,MAAA;AAAA;AAAA,UAGM,qBAAA;EAAA,SACN,OAAA;EAAA,SAKA,SAAA;EAAA,SACA,KAAA;EAAA,SACA,QAAA;EAAA,SACA,GAAA;EAAA,SACA,KAAA,EAAO,YAAA;EAAA,SACP,KAAA,EAAO,YAAA;EAAA,SAIP,UAAA,GAAa,aAAA;EAAA,SAOb,gBAAA;EAAA,SAGA,iBAAA;EAAA,SACA,KAAA,EAAO,qBAAA;EAAA,SACP,eAAA,EAAiB,eAAA;EAAA,SACjB,YAAA;EAAA,SACA,WAAA;EAAA,SACA,UAAA;EAAA,SACA,iBAAA;EAAA,SACA,UAAA,WAAqB,gBAAA;EAAA,SACrB,cAAA,YAA0B,iBAAA;EAAA,SAC1B,gBAAA,GAAmB,gBAAA;EAAA,SAKnB,QAAA;EAAA,SACA,SAAA;EAAA,SACA,cAAA;EAAA,SACA,gBAAA;EAAA,SACA,SAAA;EAAA,SACA,SAAA;AAAA;AAAA,UAGM,gBAAA;EAAA,SACN,KAAA;EAAA,SACA,GAAA;AAAA;AAAA,UAGM,eAAA;EAAA,SACN,WAAA;EAAA,SACA,OAAA;EAAA,SACA,UAAA,WAAqB,gBAAA;AAAA;AAAA,UAGf,aAAA;EAAA,SACN,GAAA;EACT,IAAA,CAAK,KAAA,EAAO,UAAA,GAAa,OAAA,CAAQ,UAAA;EAAA,SACxB,YAAA,EAAc,UAAA;AAAA;AAAA,KAGb,QAAA;AAAA,UAEK,QAAA;EAAA,SACN,GAAA;EAAA,SACA,YAAA,EAAc,UAAA;EAAA,SACd,KAAA,EAAO,QAAA;AAAA;AAAA,UAGD,MAAA;EACf,MAAA,CAAO,GAAA,WAAc,QAAA;AAAA;AAAA,KAGX,eAAA;AAAA,UASK,WAAA;EAAA,SACN,IAAA,EAAM,eAAA;EAAA,SACN,OAAA;AAAA;AAAA,UAGM,QAAA;EAAA,SACN,EAAA;EAAA,SACA,IAAA,EAAM,qBAAA;EAAA,SACN,QAAA,EAAU,QAAA;AAAA;AAAA,UAGJ,UAAA;EAAA,SACN,EAAA;EAAA,SACA,KAAA,EAAO,WAAA;AAAA;AAAA,KAGN,YAAA,GAAe,QAAA,GAAW,UAAA;;;KCrI1B,WAAA,MAAiB,CAAA,2BAEzB,CAAA,SAAU,gBAAA,GACR,gBAAA,CAAiB,WAAA,CAAY,CAAA,IAC7B,CAAA,SAAU,uBAAA,YACC,WAAA,KACT,CAAA,SAAU,0BAAA,YACC,WAAA;AAAA,KAGP,cAAA,WAAyB,iBAAA,2BACd,CAAA,GAAI,WAAA,CAAY,CAAA,CAAE,CAAA"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { r as toArtifactRef } from "./artifact-DOfpeXLb.js";
|
|
2
|
+
import canonicalize from "canonicalize";
|
|
3
|
+
//#region src/receipts/cid.ts
|
|
4
|
+
/**
|
|
5
|
+
* Derive the content-addressed CID of a receipt envelope.
|
|
6
|
+
*
|
|
7
|
+
* Returns `sha256:<hex>` where `<hex>` is the 64-char lowercase SHA-256
|
|
8
|
+
* digest of the decoded DSSE payload bytes. No KeySet, signer, or other
|
|
9
|
+
* key material is required — callers chaining receipts (parentReceiptCid)
|
|
10
|
+
* compute this from the parent envelope alone.
|
|
11
|
+
*/
|
|
12
|
+
async function receiptCid(envelope) {
|
|
13
|
+
const bytes = Uint8Array.from(atob(envelope.payload), (c) => c.charCodeAt(0));
|
|
14
|
+
const copy = new Uint8Array(bytes.byteLength);
|
|
15
|
+
copy.set(bytes);
|
|
16
|
+
const digest = await crypto.subtle.digest("SHA-256", copy.buffer);
|
|
17
|
+
return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/receipts/lineage.ts
|
|
21
|
+
const encoder = new TextEncoder();
|
|
22
|
+
const LEAF_DOMAIN = encoder.encode("lattice-lineage-leaf-v1:");
|
|
23
|
+
const NODE_DOMAIN = encoder.encode("lattice-lineage-node-v1:");
|
|
24
|
+
/**
|
|
25
|
+
* Compute a deterministic descriptor-only merkle root for artifact lineage.
|
|
26
|
+
*
|
|
27
|
+
* The root commits to `ArtifactRef` descriptors and nested lineage graphs, not
|
|
28
|
+
* raw artifact values. Returns undefined when no lineage metadata exists.
|
|
29
|
+
*/
|
|
30
|
+
async function computeArtifactLineageMerkleRoot(artifacts) {
|
|
31
|
+
const leaves = artifacts.filter((artifact) => artifact.lineage !== void 0).map((artifact) => canonicalLineageLeaf(artifact));
|
|
32
|
+
if (leaves.length === 0) return void 0;
|
|
33
|
+
let level = (await Promise.all(leaves.map((leaf) => sha256(concatBytes(LEAF_DOMAIN, leaf))))).sort(compareBytes);
|
|
34
|
+
while (level.length > 1) {
|
|
35
|
+
const next = [];
|
|
36
|
+
for (let i = 0; i < level.length; i += 2) {
|
|
37
|
+
const left = level[i];
|
|
38
|
+
const right = level[i + 1] ?? left;
|
|
39
|
+
next.push(await sha256(concatBytes(NODE_DOMAIN, left, right)));
|
|
40
|
+
}
|
|
41
|
+
level = next.sort(compareBytes);
|
|
42
|
+
}
|
|
43
|
+
return `sha256:${bytesToHex(level[0])}`;
|
|
44
|
+
}
|
|
45
|
+
function canonicalLineageLeaf(artifact) {
|
|
46
|
+
const json = canonicalize(sanitizeArtifactRef(artifact));
|
|
47
|
+
if (json === void 0) throw new Error("computeArtifactLineageMerkleRoot: lineage descriptor is not canonicalizable.");
|
|
48
|
+
return encoder.encode(json);
|
|
49
|
+
}
|
|
50
|
+
function sanitizeArtifactRef(input) {
|
|
51
|
+
const ref = toArtifactRef(input);
|
|
52
|
+
return compactObject({
|
|
53
|
+
id: ref.id,
|
|
54
|
+
kind: ref.kind,
|
|
55
|
+
source: ref.source,
|
|
56
|
+
privacy: ref.privacy,
|
|
57
|
+
mediaType: ref.mediaType,
|
|
58
|
+
label: ref.label,
|
|
59
|
+
metadata: sanitizeUnknown(ref.metadata),
|
|
60
|
+
size: sanitizeUnknown(ref.size),
|
|
61
|
+
fingerprint: sanitizeUnknown(ref.fingerprint),
|
|
62
|
+
storage: sanitizeUnknown(ref.storage),
|
|
63
|
+
lineage: ref.lineage !== void 0 ? sanitizeLineage(ref.lineage) : void 0
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function sanitizeLineage(lineage) {
|
|
67
|
+
return compactObject({
|
|
68
|
+
parents: lineage.parents.map((parent) => sanitizeArtifactRef(parent)).sort(compareCanonicalJson),
|
|
69
|
+
transform: compactObject({
|
|
70
|
+
kind: lineage.transform.kind,
|
|
71
|
+
name: lineage.transform.name,
|
|
72
|
+
metadata: sanitizeUnknown(lineage.transform.metadata)
|
|
73
|
+
})
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
function sanitizeUnknown(value) {
|
|
77
|
+
if (value === void 0) return void 0;
|
|
78
|
+
if (value === null) return null;
|
|
79
|
+
switch (typeof value) {
|
|
80
|
+
case "string":
|
|
81
|
+
case "boolean": return value;
|
|
82
|
+
case "number": return Number.isFinite(value) ? value : void 0;
|
|
83
|
+
case "bigint": return value.toString();
|
|
84
|
+
case "object": {
|
|
85
|
+
if (Array.isArray(value)) return value.map((item) => sanitizeUnknown(item)).filter((item) => item !== void 0);
|
|
86
|
+
const out = {};
|
|
87
|
+
for (const key of Object.keys(value).sort()) {
|
|
88
|
+
const child = sanitizeUnknown(value[key]);
|
|
89
|
+
if (child !== void 0) out[key] = child;
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
}
|
|
93
|
+
default: return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
function compactObject(input) {
|
|
97
|
+
const out = {};
|
|
98
|
+
for (const key of Object.keys(input).sort()) {
|
|
99
|
+
const value = input[key];
|
|
100
|
+
if (value !== void 0) out[key] = value;
|
|
101
|
+
}
|
|
102
|
+
return out;
|
|
103
|
+
}
|
|
104
|
+
function compareCanonicalJson(a, b) {
|
|
105
|
+
const aJson = canonicalize(a) ?? "";
|
|
106
|
+
const bJson = canonicalize(b) ?? "";
|
|
107
|
+
return aJson.localeCompare(bJson);
|
|
108
|
+
}
|
|
109
|
+
async function sha256(bytes) {
|
|
110
|
+
const digest = await crypto.subtle.digest("SHA-256", toArrayBuffer(bytes));
|
|
111
|
+
return new Uint8Array(digest);
|
|
112
|
+
}
|
|
113
|
+
function concatBytes(...chunks) {
|
|
114
|
+
const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
|
|
115
|
+
const out = new Uint8Array(total);
|
|
116
|
+
let offset = 0;
|
|
117
|
+
for (const chunk of chunks) {
|
|
118
|
+
out.set(chunk, offset);
|
|
119
|
+
offset += chunk.byteLength;
|
|
120
|
+
}
|
|
121
|
+
return out;
|
|
122
|
+
}
|
|
123
|
+
function compareBytes(a, b) {
|
|
124
|
+
return bytesToHex(a).localeCompare(bytesToHex(b));
|
|
125
|
+
}
|
|
126
|
+
function bytesToHex(bytes) {
|
|
127
|
+
return Array.from(bytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
128
|
+
}
|
|
129
|
+
function toArrayBuffer(bytes) {
|
|
130
|
+
const copy = new Uint8Array(bytes.byteLength);
|
|
131
|
+
copy.set(bytes);
|
|
132
|
+
return copy.buffer;
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { receiptCid as n, computeArtifactLineageMerkleRoot as t };
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=lineage-DBgoPWAZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lineage-DBgoPWAZ.js","names":[],"sources":["../src/receipts/cid.ts","../src/receipts/lineage.ts"],"sourcesContent":["/**\n * Receipt CID — Phase 39 (v1.3). Content address = sha256 of the DSSE\n * canonical payload bytes (the exact bytes that were signed).\n *\n * The CID is derivable from any envelope WITHOUT key material: it digests\n * `envelope.payload` (the base64-encoded RFC 8785 JCS canonical body) after\n * decoding. verifyReceipt proves payload byte-equality on every accepted\n * envelope (verify.ts re-canonicalization step), so two envelopes with the\n * same signed body always share a CID and any body tamper changes it.\n *\n * Web-standard APIs only (atob + crypto.subtle) — no Node-specific byte\n * types, matching the checkpoint.ts / fingerprint.ts precedents.\n */\n\nimport type { ReceiptEnvelope } from \"./types.js\";\n\n/**\n * Derive the content-addressed CID of a receipt envelope.\n *\n * Returns `sha256:<hex>` where `<hex>` is the 64-char lowercase SHA-256\n * digest of the decoded DSSE payload bytes. No KeySet, signer, or other\n * key material is required — callers chaining receipts (parentReceiptCid)\n * compute this from the parent envelope alone.\n */\nexport async function receiptCid(envelope: ReceiptEnvelope): Promise<string> {\n // Decode base64 via atob — web-standard, runtime-agnostic (checkpoint.ts:255).\n const bytes = Uint8Array.from(atob(envelope.payload), (c) => c.charCodeAt(0));\n\n // Copy into a freshly-allocated backing store so crypto.subtle.digest\n // never sees a view over a larger shared allocation (fingerprint.ts idiom).\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n\n const digest = await crypto.subtle.digest(\"SHA-256\", copy.buffer);\n\n const hex = Array.from(new Uint8Array(digest), (byte) =>\n byte.toString(16).padStart(2, \"0\"),\n ).join(\"\");\n\n return `sha256:${hex}`;\n}\n","import canonicalize from \"canonicalize\";\n\nimport type { ArtifactInput, ArtifactRef } from \"../artifacts/artifact.js\";\nimport { toArtifactRef } from \"../artifacts/artifact.js\";\nimport type { ArtifactLineage, ArtifactParentRef } from \"../artifacts/lineage.js\";\n\ntype LineageArtifact = ArtifactInput | ArtifactRef | ArtifactParentRef;\ntype JsonValue =\n | null\n | string\n | number\n | boolean\n | readonly JsonValue[]\n | { readonly [key: string]: JsonValue };\n\nconst encoder = new TextEncoder();\nconst LEAF_DOMAIN = encoder.encode(\"lattice-lineage-leaf-v1:\");\nconst NODE_DOMAIN = encoder.encode(\"lattice-lineage-node-v1:\");\n\n/**\n * Compute a deterministic descriptor-only merkle root for artifact lineage.\n *\n * The root commits to `ArtifactRef` descriptors and nested lineage graphs, not\n * raw artifact values. Returns undefined when no lineage metadata exists.\n */\nexport async function computeArtifactLineageMerkleRoot(\n artifacts: readonly LineageArtifact[],\n): Promise<string | undefined> {\n const leaves = artifacts\n .filter((artifact) => artifact.lineage !== undefined)\n .map((artifact) => canonicalLineageLeaf(artifact));\n\n if (leaves.length === 0) return undefined;\n\n let level = (await Promise.all(\n leaves.map((leaf) => sha256(concatBytes(LEAF_DOMAIN, leaf))),\n )).sort(compareBytes);\n\n while (level.length > 1) {\n const next: Uint8Array[] = [];\n for (let i = 0; i < level.length; i += 2) {\n const left = level[i]!;\n const right = level[i + 1] ?? left;\n next.push(await sha256(concatBytes(NODE_DOMAIN, left, right)));\n }\n level = next.sort(compareBytes);\n }\n\n return `sha256:${bytesToHex(level[0]!)}`;\n}\n\nfunction canonicalLineageLeaf(artifact: LineageArtifact): Uint8Array {\n const sanitized = sanitizeArtifactRef(artifact);\n const json = canonicalize(sanitized);\n if (json === undefined) {\n throw new Error(\n \"computeArtifactLineageMerkleRoot: lineage descriptor is not canonicalizable.\",\n );\n }\n return encoder.encode(json);\n}\n\nfunction sanitizeArtifactRef(input: LineageArtifact): JsonValue {\n const ref = toArtifactRef(input as ArtifactInput | ArtifactRef);\n return compactObject({\n id: ref.id,\n kind: ref.kind,\n source: ref.source,\n privacy: ref.privacy,\n mediaType: ref.mediaType,\n label: ref.label,\n metadata: sanitizeUnknown(ref.metadata),\n size: sanitizeUnknown(ref.size),\n fingerprint: sanitizeUnknown(ref.fingerprint),\n storage: sanitizeUnknown(ref.storage),\n lineage:\n ref.lineage !== undefined ? sanitizeLineage(ref.lineage) : undefined,\n });\n}\n\nfunction sanitizeLineage(lineage: ArtifactLineage): JsonValue {\n const parents = lineage.parents\n .map((parent) => sanitizeArtifactRef(parent))\n .sort(compareCanonicalJson);\n\n return compactObject({\n parents,\n transform: compactObject({\n kind: lineage.transform.kind,\n name: lineage.transform.name,\n metadata: sanitizeUnknown(lineage.transform.metadata),\n }),\n });\n}\n\nfunction sanitizeUnknown(value: unknown): JsonValue | undefined {\n if (value === undefined) return undefined;\n if (value === null) return null;\n switch (typeof value) {\n case \"string\":\n case \"boolean\":\n return value;\n case \"number\":\n return Number.isFinite(value) ? value : undefined;\n case \"bigint\":\n return value.toString();\n case \"object\": {\n if (Array.isArray(value)) {\n return value\n .map((item) => sanitizeUnknown(item))\n .filter((item): item is JsonValue => item !== undefined);\n }\n const out: Record<string, JsonValue> = {};\n for (const key of Object.keys(value as Record<string, unknown>).sort()) {\n const child = sanitizeUnknown((value as Record<string, unknown>)[key]);\n if (child !== undefined) out[key] = child;\n }\n return out;\n }\n default:\n return undefined;\n }\n}\n\nfunction compactObject(\n input: Record<string, JsonValue | undefined>,\n): { readonly [key: string]: JsonValue } {\n const out: Record<string, JsonValue> = {};\n for (const key of Object.keys(input).sort()) {\n const value = input[key];\n if (value !== undefined) out[key] = value;\n }\n return out;\n}\n\nfunction compareCanonicalJson(a: JsonValue, b: JsonValue): number {\n const aJson = canonicalize(a) ?? \"\";\n const bJson = canonicalize(b) ?? \"\";\n return aJson.localeCompare(bJson);\n}\n\nasync function sha256(bytes: Uint8Array): Promise<Uint8Array> {\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n toArrayBuffer(bytes),\n );\n return new Uint8Array(digest);\n}\n\nfunction concatBytes(...chunks: readonly Uint8Array[]): Uint8Array {\n const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);\n const out = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n out.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return out;\n}\n\nfunction compareBytes(a: Uint8Array, b: Uint8Array): number {\n return bytesToHex(a).localeCompare(bytesToHex(b));\n}\n\nfunction bytesToHex(bytes: Uint8Array): string {\n return Array.from(bytes)\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\n .join(\"\");\n}\n\nfunction toArrayBuffer(bytes: Uint8Array): ArrayBuffer {\n const copy = new Uint8Array(bytes.byteLength);\n copy.set(bytes);\n return copy.buffer as ArrayBuffer;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { r as toArtifactRef } from "./artifact-DOfpeXLb.js";
|
|
2
|
+
import { t as fingerprintArtifactValue } from "./fingerprint-DodDbQKN.js";
|
|
3
|
+
import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
//#region src/storage/local.ts
|
|
7
|
+
function createLocalArtifactStore(rootDir, options = {}) {
|
|
8
|
+
const rootPath = rootDir instanceof URL ? fileURLToPath(rootDir) : rootDir;
|
|
9
|
+
const storeId = options.id ?? "local";
|
|
10
|
+
return {
|
|
11
|
+
kind: "artifact-store",
|
|
12
|
+
id: storeId,
|
|
13
|
+
async put(artifact) {
|
|
14
|
+
const artifactDir = artifactDirectory(rootPath, artifact.id);
|
|
15
|
+
const fingerprint = artifact.fingerprint ?? await fingerprintArtifactValue(artifact.value);
|
|
16
|
+
const ref = toArtifactRef({
|
|
17
|
+
...artifact,
|
|
18
|
+
storage: {
|
|
19
|
+
storeId,
|
|
20
|
+
key: artifact.id
|
|
21
|
+
},
|
|
22
|
+
...fingerprint !== void 0 ? { fingerprint } : {}
|
|
23
|
+
});
|
|
24
|
+
await rm(artifactDir, {
|
|
25
|
+
recursive: true,
|
|
26
|
+
force: true
|
|
27
|
+
});
|
|
28
|
+
await mkdir(artifactDir, { recursive: true });
|
|
29
|
+
const payload = await writePayload(artifactDir, artifact.value);
|
|
30
|
+
const envelope = {
|
|
31
|
+
version: 1,
|
|
32
|
+
ref,
|
|
33
|
+
...payload !== void 0 ? { payload } : {}
|
|
34
|
+
};
|
|
35
|
+
await writeFile(metadataPath(rootPath, artifact.id), `${JSON.stringify(envelope, null, 2)}\n`, "utf8");
|
|
36
|
+
return ref;
|
|
37
|
+
},
|
|
38
|
+
async get(id) {
|
|
39
|
+
return (await readEnvelope(rootPath, id))?.ref;
|
|
40
|
+
},
|
|
41
|
+
async load(id) {
|
|
42
|
+
const envelope = await readEnvelope(rootPath, id);
|
|
43
|
+
if (envelope === void 0) return;
|
|
44
|
+
if (envelope.payload === void 0) return envelope.ref;
|
|
45
|
+
const value = await readPayload(artifactDirectory(rootPath, id), envelope.payload);
|
|
46
|
+
return {
|
|
47
|
+
...envelope.ref,
|
|
48
|
+
value
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
async has(id) {
|
|
52
|
+
try {
|
|
53
|
+
await stat(metadataPath(rootPath, id));
|
|
54
|
+
return true;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (isNotFoundError(error)) return false;
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async delete(id) {
|
|
61
|
+
if (!await this.has(id)) return false;
|
|
62
|
+
await rm(artifactDirectory(rootPath, id), {
|
|
63
|
+
recursive: true,
|
|
64
|
+
force: true
|
|
65
|
+
});
|
|
66
|
+
return true;
|
|
67
|
+
},
|
|
68
|
+
async list() {
|
|
69
|
+
const artifactsPath = join(rootPath, "artifacts");
|
|
70
|
+
let entries;
|
|
71
|
+
try {
|
|
72
|
+
entries = await readdir(artifactsPath, { withFileTypes: true });
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (isNotFoundError(error)) return [];
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
return (await Promise.all(entries.filter((entry) => entry.isDirectory()).map(async (entry) => {
|
|
78
|
+
return (await readEnvelopeByDirectory(join(artifactsPath, entry.name))).ref;
|
|
79
|
+
}))).sort((left, right) => left.id.localeCompare(right.id));
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
async function writePayload(artifactDir, value) {
|
|
84
|
+
if (value === void 0) return;
|
|
85
|
+
if (value instanceof Uint8Array || value instanceof ArrayBuffer || isBlobLike(value)) {
|
|
86
|
+
await writeFile(join(artifactDir, "payload.bin"), await toBinaryPayload(value));
|
|
87
|
+
return {
|
|
88
|
+
kind: "binary",
|
|
89
|
+
path: "payload.bin"
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const serialized = JSON.stringify(value, null, 2);
|
|
93
|
+
if (serialized === void 0) return;
|
|
94
|
+
await writeFile(join(artifactDir, "payload.json"), `${serialized}\n`, "utf8");
|
|
95
|
+
return {
|
|
96
|
+
kind: "json",
|
|
97
|
+
path: "payload.json"
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async function readPayload(artifactDir, payload) {
|
|
101
|
+
const payloadPath = join(artifactDir, payload.path);
|
|
102
|
+
if (payload.kind === "binary") {
|
|
103
|
+
const bytes = await readFile(payloadPath);
|
|
104
|
+
return new Uint8Array(bytes);
|
|
105
|
+
}
|
|
106
|
+
return JSON.parse(await readFile(payloadPath, "utf8"));
|
|
107
|
+
}
|
|
108
|
+
async function readEnvelope(rootPath, id) {
|
|
109
|
+
try {
|
|
110
|
+
return JSON.parse(await readFile(metadataPath(rootPath, id), "utf8"));
|
|
111
|
+
} catch (error) {
|
|
112
|
+
if (isNotFoundError(error)) return;
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async function readEnvelopeByDirectory(artifactDir) {
|
|
117
|
+
return JSON.parse(await readFile(join(artifactDir, "metadata.json"), "utf8"));
|
|
118
|
+
}
|
|
119
|
+
async function toBinaryPayload(value) {
|
|
120
|
+
if (value instanceof Uint8Array) return value;
|
|
121
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
122
|
+
return new Uint8Array(await value.arrayBuffer());
|
|
123
|
+
}
|
|
124
|
+
function artifactDirectory(rootPath, id) {
|
|
125
|
+
return join(rootPath, "artifacts", encodeURIComponent(id));
|
|
126
|
+
}
|
|
127
|
+
function metadataPath(rootPath, id) {
|
|
128
|
+
return join(artifactDirectory(rootPath, id), "metadata.json");
|
|
129
|
+
}
|
|
130
|
+
function isBlobLike(value) {
|
|
131
|
+
return typeof Blob !== "undefined" && value instanceof Blob;
|
|
132
|
+
}
|
|
133
|
+
function isNotFoundError(error) {
|
|
134
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
export { createLocalArtifactStore as t };
|
|
138
|
+
|
|
139
|
+
//# sourceMappingURL=local-CXOGPJ1f.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-CXOGPJ1f.js","names":[],"sources":["../src/storage/local.ts"],"sourcesContent":["import { mkdir, readFile, readdir, rm, stat, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { ArtifactInput, ArtifactRef } from \"../artifacts/artifact.js\";\nimport { toArtifactRef } from \"../artifacts/artifact.js\";\nimport { fingerprintArtifactValue } from \"./fingerprint.js\";\nimport type {\n ArtifactStore,\n StoredArtifactEnvelope,\n StoredArtifactPayloadDescriptor,\n} from \"./storage.js\";\n\nexport interface LocalArtifactStoreOptions {\n readonly id?: string;\n}\n\nexport function createLocalArtifactStore(\n rootDir: string | URL,\n options: LocalArtifactStoreOptions = {},\n): ArtifactStore {\n const rootPath = rootDir instanceof URL ? fileURLToPath(rootDir) : rootDir;\n const storeId = options.id ?? \"local\";\n\n return {\n kind: \"artifact-store\",\n id: storeId,\n\n async put(artifact: ArtifactInput): Promise<ArtifactRef> {\n const artifactDir = artifactDirectory(rootPath, artifact.id);\n const fingerprint =\n artifact.fingerprint ?? await fingerprintArtifactValue(artifact.value);\n const storedArtifact: ArtifactInput = {\n ...artifact,\n storage: {\n storeId,\n key: artifact.id,\n },\n ...(fingerprint !== undefined ? { fingerprint } : {}),\n };\n const ref = toArtifactRef(storedArtifact);\n\n await rm(artifactDir, { recursive: true, force: true });\n await mkdir(artifactDir, { recursive: true });\n\n const payload = await writePayload(artifactDir, artifact.value);\n const envelope: StoredArtifactEnvelope = {\n version: 1,\n ref,\n ...(payload !== undefined ? { payload } : {}),\n };\n\n await writeFile(\n metadataPath(rootPath, artifact.id),\n `${JSON.stringify(envelope, null, 2)}\\n`,\n \"utf8\",\n );\n\n return ref;\n },\n\n async get(id: string): Promise<ArtifactRef | undefined> {\n const envelope = await readEnvelope(rootPath, id);\n\n return envelope?.ref;\n },\n\n async load(id: string): Promise<ArtifactInput | undefined> {\n const envelope = await readEnvelope(rootPath, id);\n\n if (envelope === undefined) {\n return undefined;\n }\n\n if (envelope.payload === undefined) {\n return envelope.ref;\n }\n\n const value = await readPayload(artifactDirectory(rootPath, id), envelope.payload);\n\n return {\n ...envelope.ref,\n value,\n };\n },\n\n async has(id: string): Promise<boolean> {\n try {\n await stat(metadataPath(rootPath, id));\n\n return true;\n } catch (error) {\n if (isNotFoundError(error)) {\n return false;\n }\n\n throw error;\n }\n },\n\n async delete(id: string): Promise<boolean> {\n const exists = await this.has(id);\n\n if (!exists) {\n return false;\n }\n\n await rm(artifactDirectory(rootPath, id), { recursive: true, force: true });\n\n return true;\n },\n\n async list(): Promise<readonly ArtifactRef[]> {\n const artifactsPath = join(rootPath, \"artifacts\");\n let entries: readonly { isDirectory(): boolean; name: string }[];\n\n try {\n entries = await readdir(artifactsPath, { withFileTypes: true });\n } catch (error) {\n if (isNotFoundError(error)) {\n return [];\n }\n\n throw error;\n }\n\n const refs = await Promise.all(\n entries\n .filter((entry) => entry.isDirectory())\n .map(async (entry) => {\n const envelope = await readEnvelopeByDirectory(\n join(artifactsPath, entry.name),\n );\n\n return envelope.ref;\n }),\n );\n\n return refs.sort((left, right) => left.id.localeCompare(right.id));\n },\n };\n}\n\nasync function writePayload(\n artifactDir: string,\n value: unknown,\n): Promise<StoredArtifactPayloadDescriptor | undefined> {\n if (value === undefined) {\n return undefined;\n }\n\n if (value instanceof Uint8Array || value instanceof ArrayBuffer || isBlobLike(value)) {\n await writeFile(join(artifactDir, \"payload.bin\"), await toBinaryPayload(value));\n\n return {\n kind: \"binary\",\n path: \"payload.bin\",\n };\n }\n\n const serialized = JSON.stringify(value, null, 2);\n\n if (serialized === undefined) {\n return undefined;\n }\n\n await writeFile(join(artifactDir, \"payload.json\"), `${serialized}\\n`, \"utf8\");\n\n return {\n kind: \"json\",\n path: \"payload.json\",\n };\n}\n\nasync function readPayload(\n artifactDir: string,\n payload: StoredArtifactPayloadDescriptor,\n): Promise<unknown> {\n const payloadPath = join(artifactDir, payload.path);\n\n if (payload.kind === \"binary\") {\n const bytes = await readFile(payloadPath);\n\n return new Uint8Array(bytes);\n }\n\n return JSON.parse(await readFile(payloadPath, \"utf8\"));\n}\n\nasync function readEnvelope(\n rootPath: string,\n id: string,\n): Promise<StoredArtifactEnvelope | undefined> {\n try {\n return JSON.parse(await readFile(metadataPath(rootPath, id), \"utf8\"));\n } catch (error) {\n if (isNotFoundError(error)) {\n return undefined;\n }\n\n throw error;\n }\n}\n\nasync function readEnvelopeByDirectory(\n artifactDir: string,\n): Promise<StoredArtifactEnvelope> {\n return JSON.parse(await readFile(join(artifactDir, \"metadata.json\"), \"utf8\"));\n}\n\nasync function toBinaryPayload(\n value: Blob | ArrayBuffer | Uint8Array,\n): Promise<Uint8Array> {\n if (value instanceof Uint8Array) {\n return value;\n }\n\n if (value instanceof ArrayBuffer) {\n return new Uint8Array(value);\n }\n\n return new Uint8Array(await value.arrayBuffer());\n}\n\nfunction artifactDirectory(rootPath: string, id: string): string {\n return join(rootPath, \"artifacts\", encodeURIComponent(id));\n}\n\nfunction metadataPath(rootPath: string, id: string): string {\n return join(artifactDirectory(rootPath, id), \"metadata.json\");\n}\n\nfunction isBlobLike(value: unknown): value is Blob {\n return typeof Blob !== \"undefined\" && value instanceof Blob;\n}\n\nfunction isNotFoundError(error: unknown): boolean {\n return (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n error.code === \"ENOENT\"\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { t as ArtifactStore } from "./storage-DJKmsaEI.js";
|
|
2
|
+
|
|
3
|
+
//#region src/storage/local.d.ts
|
|
4
|
+
interface LocalArtifactStoreOptions {
|
|
5
|
+
readonly id?: string;
|
|
6
|
+
}
|
|
7
|
+
declare function createLocalArtifactStore(rootDir: string | URL, options?: LocalArtifactStoreOptions): ArtifactStore;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { createLocalArtifactStore as n, LocalArtifactStoreOptions as t };
|
|
10
|
+
//# sourceMappingURL=local-Dy--7peL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-Dy--7peL.d.ts","names":[],"sources":["../src/storage/local.ts"],"mappings":";;;UAaiB,yBAAA;EAAA,SACN,EAAA;AAAA;AAAA,iBAGK,wBAAA,CACd,OAAA,WAAkB,GAAA,EAClB,OAAA,GAAS,yBAAA,GACR,aAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { r as toArtifactRef } from "./artifact-DOfpeXLb.js";
|
|
2
|
+
import { t as fingerprintArtifactValue } from "./fingerprint-DodDbQKN.js";
|
|
3
|
+
//#region src/storage/memory.ts
|
|
4
|
+
function createMemoryArtifactStore(options = {}) {
|
|
5
|
+
const storeId = options.id ?? "memory";
|
|
6
|
+
const artifacts = /* @__PURE__ */ new Map();
|
|
7
|
+
return {
|
|
8
|
+
kind: "artifact-store",
|
|
9
|
+
id: storeId,
|
|
10
|
+
async put(artifact) {
|
|
11
|
+
const fingerprint = artifact.fingerprint ?? await fingerprintArtifactValue(artifact.value);
|
|
12
|
+
const storedArtifact = {
|
|
13
|
+
...cloneArtifactInput(artifact),
|
|
14
|
+
storage: {
|
|
15
|
+
storeId,
|
|
16
|
+
key: artifact.id
|
|
17
|
+
},
|
|
18
|
+
...fingerprint !== void 0 ? { fingerprint } : {}
|
|
19
|
+
};
|
|
20
|
+
const ref = toArtifactRef(storedArtifact);
|
|
21
|
+
artifacts.set(artifact.id, {
|
|
22
|
+
ref: cloneArtifactRef(ref),
|
|
23
|
+
artifact: cloneArtifactInput(storedArtifact)
|
|
24
|
+
});
|
|
25
|
+
return cloneArtifactRef(ref);
|
|
26
|
+
},
|
|
27
|
+
async get(id) {
|
|
28
|
+
const record = artifacts.get(id);
|
|
29
|
+
return record === void 0 ? void 0 : cloneArtifactRef(record.ref);
|
|
30
|
+
},
|
|
31
|
+
async load(id) {
|
|
32
|
+
const record = artifacts.get(id);
|
|
33
|
+
return record === void 0 ? void 0 : cloneArtifactInput(record.artifact);
|
|
34
|
+
},
|
|
35
|
+
async has(id) {
|
|
36
|
+
return artifacts.has(id);
|
|
37
|
+
},
|
|
38
|
+
async delete(id) {
|
|
39
|
+
return artifacts.delete(id);
|
|
40
|
+
},
|
|
41
|
+
async list() {
|
|
42
|
+
return Array.from(artifacts.values(), (record) => cloneArtifactRef(record.ref));
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function cloneArtifactInput(artifact) {
|
|
47
|
+
return cloneValue(artifact);
|
|
48
|
+
}
|
|
49
|
+
function cloneArtifactRef(ref) {
|
|
50
|
+
return cloneValue(ref);
|
|
51
|
+
}
|
|
52
|
+
function cloneValue(value) {
|
|
53
|
+
try {
|
|
54
|
+
return structuredClone(value);
|
|
55
|
+
} catch {
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { createMemoryArtifactStore as t };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=memory-CkQEW6m5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-CkQEW6m5.js","names":[],"sources":["../src/storage/memory.ts"],"sourcesContent":["import type { ArtifactInput, ArtifactRef } from \"../artifacts/artifact.js\";\nimport { toArtifactRef } from \"../artifacts/artifact.js\";\nimport { fingerprintArtifactValue } from \"./fingerprint.js\";\nimport type { ArtifactStore } from \"./storage.js\";\n\nexport interface MemoryArtifactStoreOptions {\n readonly id?: string;\n}\n\ninterface MemoryArtifactRecord {\n readonly ref: ArtifactRef;\n readonly artifact: ArtifactInput;\n}\n\nexport function createMemoryArtifactStore(\n options: MemoryArtifactStoreOptions = {},\n): ArtifactStore {\n const storeId = options.id ?? \"memory\";\n const artifacts = new Map<string, MemoryArtifactRecord>();\n\n return {\n kind: \"artifact-store\",\n id: storeId,\n\n async put(artifact) {\n const fingerprint =\n artifact.fingerprint ?? await fingerprintArtifactValue(artifact.value);\n const storedArtifact: ArtifactInput = {\n ...cloneArtifactInput(artifact),\n storage: {\n storeId,\n key: artifact.id,\n },\n ...(fingerprint !== undefined ? { fingerprint } : {}),\n };\n const ref = toArtifactRef(storedArtifact);\n\n artifacts.set(artifact.id, {\n ref: cloneArtifactRef(ref),\n artifact: cloneArtifactInput(storedArtifact),\n });\n\n return cloneArtifactRef(ref);\n },\n\n async get(id) {\n const record = artifacts.get(id);\n\n return record === undefined ? undefined : cloneArtifactRef(record.ref);\n },\n\n async load(id) {\n const record = artifacts.get(id);\n\n return record === undefined ? undefined : cloneArtifactInput(record.artifact);\n },\n\n async has(id) {\n return artifacts.has(id);\n },\n\n async delete(id) {\n return artifacts.delete(id);\n },\n\n async list() {\n return Array.from(artifacts.values(), (record) =>\n cloneArtifactRef(record.ref),\n );\n },\n };\n}\n\nfunction cloneArtifactInput(artifact: ArtifactInput): ArtifactInput {\n return cloneValue(artifact);\n}\n\nfunction cloneArtifactRef(ref: ArtifactRef): ArtifactRef {\n return cloneValue(ref);\n}\n\nfunction cloneValue<T>(value: T): T {\n try {\n return structuredClone(value);\n } catch {\n return value;\n }\n}\n"],"mappings":";;;AAcA,SAAgB,0BACd,UAAsC,EAAE,EACzB;CACf,MAAM,UAAU,QAAQ,MAAM;CAC9B,MAAM,4BAAY,IAAI,KAAmC;AAEzD,QAAO;EACL,MAAM;EACN,IAAI;EAEJ,MAAM,IAAI,UAAU;GAClB,MAAM,cACJ,SAAS,eAAe,MAAM,yBAAyB,SAAS,MAAM;GACxE,MAAM,iBAAgC;IACpC,GAAG,mBAAmB,SAAS;IAC/B,SAAS;KACP;KACA,KAAK,SAAS;KACf;IACD,GAAI,gBAAgB,KAAA,IAAY,EAAE,aAAa,GAAG,EAAE;IACrD;GACD,MAAM,MAAM,cAAc,eAAe;AAEzC,aAAU,IAAI,SAAS,IAAI;IACzB,KAAK,iBAAiB,IAAI;IAC1B,UAAU,mBAAmB,eAAe;IAC7C,CAAC;AAEF,UAAO,iBAAiB,IAAI;;EAG9B,MAAM,IAAI,IAAI;GACZ,MAAM,SAAS,UAAU,IAAI,GAAG;AAEhC,UAAO,WAAW,KAAA,IAAY,KAAA,IAAY,iBAAiB,OAAO,IAAI;;EAGxE,MAAM,KAAK,IAAI;GACb,MAAM,SAAS,UAAU,IAAI,GAAG;AAEhC,UAAO,WAAW,KAAA,IAAY,KAAA,IAAY,mBAAmB,OAAO,SAAS;;EAG/E,MAAM,IAAI,IAAI;AACZ,UAAO,UAAU,IAAI,GAAG;;EAG1B,MAAM,OAAO,IAAI;AACf,UAAO,UAAU,OAAO,GAAG;;EAG7B,MAAM,OAAO;AACX,UAAO,MAAM,KAAK,UAAU,QAAQ,GAAG,WACrC,iBAAiB,OAAO,IAAI,CAC7B;;EAEJ;;AAGH,SAAS,mBAAmB,UAAwC;AAClE,QAAO,WAAW,SAAS;;AAG7B,SAAS,iBAAiB,KAA+B;AACvD,QAAO,WAAW,IAAI;;AAGxB,SAAS,WAAc,OAAa;AAClC,KAAI;AACF,SAAO,gBAAgB,MAAM;SACvB;AACN,SAAO"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { t as ArtifactStore } from "./storage-DJKmsaEI.js";
|
|
2
|
+
|
|
3
|
+
//#region src/storage/memory.d.ts
|
|
4
|
+
interface MemoryArtifactStoreOptions {
|
|
5
|
+
readonly id?: string;
|
|
6
|
+
}
|
|
7
|
+
declare function createMemoryArtifactStore(options?: MemoryArtifactStoreOptions): ArtifactStore;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { createMemoryArtifactStore as n, MemoryArtifactStoreOptions as t };
|
|
10
|
+
//# sourceMappingURL=memory-DRig5EHV.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-DRig5EHV.d.ts","names":[],"sources":["../src/storage/memory.ts"],"mappings":";;;UAKiB,0BAAA;EAAA,SACN,EAAA;AAAA;AAAA,iBAQK,yBAAA,CACd,OAAA,GAAS,0BAAA,GACR,aAAA"}
|