agentfootprint 9.24.0 → 9.26.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/AGENTS.md +1 -1
- package/CLAUDE.md +7 -1
- package/README.md +3 -1
- package/ai-instructions/claude-code/SKILL.md +1 -1
- package/dist/adapters/code/local.js +102 -2
- package/dist/adapters/code/local.js.map +1 -1
- package/dist/adapters/hosting/agentcore.js +11 -0
- package/dist/adapters/hosting/agentcore.js.map +1 -1
- package/dist/adapters/identity/jwks.js +277 -0
- package/dist/adapters/identity/jwks.js.map +1 -0
- package/dist/adapters/types.js +18 -1
- package/dist/adapters/types.js.map +1 -1
- package/dist/artifacts/fileArtifacts.js +144 -17
- package/dist/artifacts/fileArtifacts.js.map +1 -1
- package/dist/artifacts/gcsArtifacts.js +398 -0
- package/dist/artifacts/gcsArtifacts.js.map +1 -0
- package/dist/artifacts/index.js +17 -1
- package/dist/artifacts/index.js.map +1 -1
- package/dist/artifacts/objectStore.js +264 -0
- package/dist/artifacts/objectStore.js.map +1 -0
- package/dist/artifacts/payload.js +41 -2
- package/dist/artifacts/payload.js.map +1 -1
- package/dist/artifacts/recordingArtifact.js +88 -0
- package/dist/artifacts/recordingArtifact.js.map +1 -0
- package/dist/artifacts/s3Artifacts.js +542 -0
- package/dist/artifacts/s3Artifacts.js.map +1 -0
- package/dist/artifacts/scopePath.js +87 -0
- package/dist/artifacts/scopePath.js.map +1 -0
- package/dist/artifacts/streaming.js +132 -0
- package/dist/artifacts/streaming.js.map +1 -0
- package/dist/artifacts/types.js +10 -2
- package/dist/artifacts/types.js.map +1 -1
- package/dist/core/Agent.js +176 -0
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/agent/AgentBuilder.js +20 -0
- package/dist/core/agent/AgentBuilder.js.map +1 -1
- package/dist/core/agent/repeatedCall.js +190 -0
- package/dist/core/agent/repeatedCall.js.map +1 -0
- package/dist/core/agent/stages/toolCalls.js +50 -0
- package/dist/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/core/codeRunnerTool.js +149 -12
- package/dist/core/codeRunnerTool.js.map +1 -1
- package/dist/esm/adapters/code/local.d.ts +16 -0
- package/dist/esm/adapters/code/local.js +102 -2
- package/dist/esm/adapters/code/local.js.map +1 -1
- package/dist/esm/adapters/hosting/agentcore.js +11 -0
- package/dist/esm/adapters/hosting/agentcore.js.map +1 -1
- package/dist/esm/adapters/identity/jwks.d.ts +124 -0
- package/dist/esm/adapters/identity/jwks.js +249 -0
- package/dist/esm/adapters/identity/jwks.js.map +1 -0
- package/dist/esm/adapters/types.d.ts +86 -0
- package/dist/esm/adapters/types.js +16 -0
- package/dist/esm/adapters/types.js.map +1 -1
- package/dist/esm/artifacts/fileArtifacts.d.ts +13 -1
- package/dist/esm/artifacts/fileArtifacts.js +145 -18
- package/dist/esm/artifacts/fileArtifacts.js.map +1 -1
- package/dist/esm/artifacts/gcsArtifacts.d.ts +142 -0
- package/dist/esm/artifacts/gcsArtifacts.js +394 -0
- package/dist/esm/artifacts/gcsArtifacts.js.map +1 -0
- package/dist/esm/artifacts/index.d.ts +5 -1
- package/dist/esm/artifacts/index.js +4 -0
- package/dist/esm/artifacts/index.js.map +1 -1
- package/dist/esm/artifacts/objectStore.d.ts +166 -0
- package/dist/esm/artifacts/objectStore.js +252 -0
- package/dist/esm/artifacts/objectStore.js.map +1 -0
- package/dist/esm/artifacts/payload.d.ts +36 -4
- package/dist/esm/artifacts/payload.js +38 -1
- package/dist/esm/artifacts/payload.js.map +1 -1
- package/dist/esm/artifacts/recordingArtifact.d.ts +76 -0
- package/dist/esm/artifacts/recordingArtifact.js +83 -0
- package/dist/esm/artifacts/recordingArtifact.js.map +1 -0
- package/dist/esm/artifacts/s3Artifacts.d.ts +149 -0
- package/dist/esm/artifacts/s3Artifacts.js +538 -0
- package/dist/esm/artifacts/s3Artifacts.js.map +1 -0
- package/dist/esm/artifacts/scopePath.d.ts +50 -0
- package/dist/esm/artifacts/scopePath.js +80 -0
- package/dist/esm/artifacts/scopePath.js.map +1 -0
- package/dist/esm/artifacts/streaming.d.ts +82 -0
- package/dist/esm/artifacts/streaming.js +123 -0
- package/dist/esm/artifacts/streaming.js.map +1 -0
- package/dist/esm/artifacts/types.d.ts +71 -5
- package/dist/esm/artifacts/types.js +10 -2
- package/dist/esm/artifacts/types.js.map +1 -1
- package/dist/esm/core/Agent.d.ts +66 -2
- package/dist/esm/core/Agent.js +176 -0
- package/dist/esm/core/Agent.js.map +1 -1
- package/dist/esm/core/agent/AgentBuilder.js +20 -0
- package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
- package/dist/esm/core/agent/repeatedCall.d.ts +150 -0
- package/dist/esm/core/agent/repeatedCall.js +184 -0
- package/dist/esm/core/agent/repeatedCall.js.map +1 -0
- package/dist/esm/core/agent/stages/toolCalls.d.ts +12 -0
- package/dist/esm/core/agent/stages/toolCalls.js +50 -0
- package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
- package/dist/esm/core/agent/types.d.ts +82 -0
- package/dist/esm/core/codeRunnerTool.d.ts +31 -0
- package/dist/esm/core/codeRunnerTool.js +149 -12
- package/dist/esm/core/codeRunnerTool.js.map +1 -1
- package/dist/esm/events/payloads.d.ts +22 -0
- package/dist/esm/events/registry.d.ts +3 -1
- package/dist/esm/events/registry.js +2 -0
- package/dist/esm/events/registry.js.map +1 -1
- package/dist/esm/hosting/admission.d.ts +180 -0
- package/dist/esm/hosting/admission.js +188 -0
- package/dist/esm/hosting/admission.js.map +1 -0
- package/dist/esm/hosting/artifactWire.d.ts +8 -5
- package/dist/esm/hosting/artifactWire.js +14 -9
- package/dist/esm/hosting/artifactWire.js.map +1 -1
- package/dist/esm/hosting/envelope.d.ts +34 -0
- package/dist/esm/hosting/envelope.js +81 -0
- package/dist/esm/hosting/envelope.js.map +1 -1
- package/dist/esm/hosting/errors.d.ts +131 -0
- package/dist/esm/hosting/errors.js +195 -0
- package/dist/esm/hosting/errors.js.map +1 -1
- package/dist/esm/hosting/httpHost.d.ts +21 -0
- package/dist/esm/hosting/httpHost.js +44 -2
- package/dist/esm/hosting/httpHost.js.map +1 -1
- package/dist/esm/hosting/identityVerification.d.ts +154 -0
- package/dist/esm/hosting/identityVerification.js +135 -0
- package/dist/esm/hosting/identityVerification.js.map +1 -0
- package/dist/esm/hosting/index.d.ts +12 -3
- package/dist/esm/hosting/index.js +16 -2
- package/dist/esm/hosting/index.js.map +1 -1
- package/dist/esm/hosting/memorySessions.d.ts +9 -0
- package/dist/esm/hosting/memorySessions.js +86 -0
- package/dist/esm/hosting/memorySessions.js.map +1 -1
- package/dist/esm/hosting/nodeHost.js +8 -0
- package/dist/esm/hosting/nodeHost.js.map +1 -1
- package/dist/esm/hosting/sessionWire.d.ts +126 -0
- package/dist/esm/hosting/sessionWire.js +95 -0
- package/dist/esm/hosting/sessionWire.js.map +1 -0
- package/dist/esm/hosting/sqliteSessions.js +122 -5
- package/dist/esm/hosting/sqliteSessions.js.map +1 -1
- package/dist/esm/hosting/standingAgent.js +299 -8
- package/dist/esm/hosting/standingAgent.js.map +1 -1
- package/dist/esm/hosting/types.d.ts +166 -6
- package/dist/esm/hosting/types.js.map +1 -1
- package/dist/esm/hosting/wireOps.d.ts +52 -0
- package/dist/esm/hosting/wireOps.js +60 -0
- package/dist/esm/hosting/wireOps.js.map +1 -0
- package/dist/esm/identity.d.ts +1 -0
- package/dist/esm/identity.js +6 -0
- package/dist/esm/identity.js.map +1 -1
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +10 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/injection-engine/factories/defineSkill.d.ts +27 -0
- package/dist/esm/lib/injection-engine/factories/defineSkill.js +13 -0
- package/dist/esm/lib/injection-engine/factories/defineSkill.js.map +1 -1
- package/dist/esm/lib/injection-engine/index.d.ts +1 -0
- package/dist/esm/lib/injection-engine/index.js +7 -0
- package/dist/esm/lib/injection-engine/index.js.map +1 -1
- package/dist/esm/lib/injection-engine/skillGraph.js +9 -1
- package/dist/esm/lib/injection-engine/skillGraph.js.map +1 -1
- package/dist/esm/lib/injection-engine/skillGraphCheckup.d.ts +1 -1
- package/dist/esm/lib/injection-engine/skillGraphCheckup.js.map +1 -1
- package/dist/esm/lib/injection-engine/skillSteps.d.ts +16 -0
- package/dist/esm/lib/injection-engine/skillSteps.js +5 -0
- package/dist/esm/lib/injection-engine/skillSteps.js.map +1 -1
- package/dist/esm/lib/injection-engine/skillVocabulary.d.ts +83 -0
- package/dist/esm/lib/injection-engine/skillVocabulary.js +218 -0
- package/dist/esm/lib/injection-engine/skillVocabulary.js.map +1 -0
- package/dist/events/registry.js +2 -0
- package/dist/events/registry.js.map +1 -1
- package/dist/hosting/admission.js +194 -0
- package/dist/hosting/admission.js.map +1 -0
- package/dist/hosting/artifactWire.js +14 -9
- package/dist/hosting/artifactWire.js.map +1 -1
- package/dist/hosting/envelope.js +84 -1
- package/dist/hosting/envelope.js.map +1 -1
- package/dist/hosting/errors.js +203 -1
- package/dist/hosting/errors.js.map +1 -1
- package/dist/hosting/httpHost.js +43 -1
- package/dist/hosting/httpHost.js.map +1 -1
- package/dist/hosting/identityVerification.js +140 -0
- package/dist/hosting/identityVerification.js.map +1 -0
- package/dist/hosting/index.js +38 -1
- package/dist/hosting/index.js.map +1 -1
- package/dist/hosting/memorySessions.js +86 -0
- package/dist/hosting/memorySessions.js.map +1 -1
- package/dist/hosting/nodeHost.js +8 -0
- package/dist/hosting/nodeHost.js.map +1 -1
- package/dist/hosting/sessionWire.js +100 -0
- package/dist/hosting/sessionWire.js.map +1 -0
- package/dist/hosting/sqliteSessions.js +121 -4
- package/dist/hosting/sqliteSessions.js.map +1 -1
- package/dist/hosting/standingAgent.js +297 -6
- package/dist/hosting/standingAgent.js.map +1 -1
- package/dist/hosting/types.js.map +1 -1
- package/dist/hosting/wireOps.js +65 -0
- package/dist/hosting/wireOps.js.map +1 -0
- package/dist/identity.js +9 -1
- package/dist/identity.js.map +1 -1
- package/dist/index.js +30 -13
- package/dist/index.js.map +1 -1
- package/dist/lib/injection-engine/factories/defineSkill.js +13 -0
- package/dist/lib/injection-engine/factories/defineSkill.js.map +1 -1
- package/dist/lib/injection-engine/index.js +10 -1
- package/dist/lib/injection-engine/index.js.map +1 -1
- package/dist/lib/injection-engine/skillGraph.js +9 -1
- package/dist/lib/injection-engine/skillGraph.js.map +1 -1
- package/dist/lib/injection-engine/skillGraphCheckup.js.map +1 -1
- package/dist/lib/injection-engine/skillSteps.js +5 -0
- package/dist/lib/injection-engine/skillSteps.js.map +1 -1
- package/dist/lib/injection-engine/skillVocabulary.js +224 -0
- package/dist/lib/injection-engine/skillVocabulary.js.map +1 -0
- package/dist/types/adapters/code/local.d.ts +16 -0
- package/dist/types/adapters/code/local.d.ts.map +1 -1
- package/dist/types/adapters/hosting/agentcore.d.ts.map +1 -1
- package/dist/types/adapters/identity/jwks.d.ts +125 -0
- package/dist/types/adapters/identity/jwks.d.ts.map +1 -0
- package/dist/types/adapters/types.d.ts +86 -0
- package/dist/types/adapters/types.d.ts.map +1 -1
- package/dist/types/artifacts/fileArtifacts.d.ts +13 -1
- package/dist/types/artifacts/fileArtifacts.d.ts.map +1 -1
- package/dist/types/artifacts/gcsArtifacts.d.ts +143 -0
- package/dist/types/artifacts/gcsArtifacts.d.ts.map +1 -0
- package/dist/types/artifacts/index.d.ts +5 -1
- package/dist/types/artifacts/index.d.ts.map +1 -1
- package/dist/types/artifacts/objectStore.d.ts +167 -0
- package/dist/types/artifacts/objectStore.d.ts.map +1 -0
- package/dist/types/artifacts/payload.d.ts +36 -4
- package/dist/types/artifacts/payload.d.ts.map +1 -1
- package/dist/types/artifacts/recordingArtifact.d.ts +77 -0
- package/dist/types/artifacts/recordingArtifact.d.ts.map +1 -0
- package/dist/types/artifacts/s3Artifacts.d.ts +150 -0
- package/dist/types/artifacts/s3Artifacts.d.ts.map +1 -0
- package/dist/types/artifacts/scopePath.d.ts +51 -0
- package/dist/types/artifacts/scopePath.d.ts.map +1 -0
- package/dist/types/artifacts/streaming.d.ts +83 -0
- package/dist/types/artifacts/streaming.d.ts.map +1 -0
- package/dist/types/artifacts/types.d.ts +71 -5
- package/dist/types/artifacts/types.d.ts.map +1 -1
- package/dist/types/core/Agent.d.ts +66 -2
- package/dist/types/core/Agent.d.ts.map +1 -1
- package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
- package/dist/types/core/agent/repeatedCall.d.ts +151 -0
- package/dist/types/core/agent/repeatedCall.d.ts.map +1 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts +12 -0
- package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
- package/dist/types/core/agent/types.d.ts +82 -0
- package/dist/types/core/agent/types.d.ts.map +1 -1
- package/dist/types/core/codeRunnerTool.d.ts +31 -0
- package/dist/types/core/codeRunnerTool.d.ts.map +1 -1
- package/dist/types/events/payloads.d.ts +22 -0
- package/dist/types/events/payloads.d.ts.map +1 -1
- package/dist/types/events/registry.d.ts +3 -1
- package/dist/types/events/registry.d.ts.map +1 -1
- package/dist/types/hosting/admission.d.ts +181 -0
- package/dist/types/hosting/admission.d.ts.map +1 -0
- package/dist/types/hosting/artifactWire.d.ts +8 -5
- package/dist/types/hosting/artifactWire.d.ts.map +1 -1
- package/dist/types/hosting/envelope.d.ts +34 -0
- package/dist/types/hosting/envelope.d.ts.map +1 -1
- package/dist/types/hosting/errors.d.ts +131 -0
- package/dist/types/hosting/errors.d.ts.map +1 -1
- package/dist/types/hosting/httpHost.d.ts +21 -0
- package/dist/types/hosting/httpHost.d.ts.map +1 -1
- package/dist/types/hosting/identityVerification.d.ts +155 -0
- package/dist/types/hosting/identityVerification.d.ts.map +1 -0
- package/dist/types/hosting/index.d.ts +12 -3
- package/dist/types/hosting/index.d.ts.map +1 -1
- package/dist/types/hosting/memorySessions.d.ts +9 -0
- package/dist/types/hosting/memorySessions.d.ts.map +1 -1
- package/dist/types/hosting/nodeHost.d.ts.map +1 -1
- package/dist/types/hosting/sessionWire.d.ts +127 -0
- package/dist/types/hosting/sessionWire.d.ts.map +1 -0
- package/dist/types/hosting/sqliteSessions.d.ts.map +1 -1
- package/dist/types/hosting/standingAgent.d.ts.map +1 -1
- package/dist/types/hosting/types.d.ts +166 -6
- package/dist/types/hosting/types.d.ts.map +1 -1
- package/dist/types/hosting/wireOps.d.ts +53 -0
- package/dist/types/hosting/wireOps.d.ts.map +1 -0
- package/dist/types/identity.d.ts +1 -0
- package/dist/types/identity.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/factories/defineSkill.d.ts +27 -0
- package/dist/types/lib/injection-engine/factories/defineSkill.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/index.d.ts +1 -0
- package/dist/types/lib/injection-engine/index.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/skillGraph.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/skillGraphCheckup.d.ts +1 -1
- package/dist/types/lib/injection-engine/skillGraphCheckup.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/skillSteps.d.ts +16 -0
- package/dist/types/lib/injection-engine/skillSteps.d.ts.map +1 -1
- package/dist/types/lib/injection-engine/skillVocabulary.d.ts +84 -0
- package/dist/types/lib/injection-engine/skillVocabulary.d.ts.map +1 -0
- package/package.json +15 -1
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* artifacts/s3Artifacts — the claim-check store in an S3 bucket.
|
|
4
|
+
*
|
|
5
|
+
* The third rung of the same ladder: `inMemoryArtifacts` for a test,
|
|
6
|
+
* `fileArtifacts`/`sqliteArtifacts` for one machine, this for a fleet. Nothing
|
|
7
|
+
* about the five verbs changes — a tool that stored a dataset against the
|
|
8
|
+
* in-memory store stores it here by swapping one constructor, because the port
|
|
9
|
+
* is the contract and this file is only a translation of it.
|
|
10
|
+
*
|
|
11
|
+
* Read `objectStore.ts` first: it holds the five laws both object adapters
|
|
12
|
+
* obey (payload as canonical bytes in the body, ONE metadata entry carrying
|
|
13
|
+
* the ticket, a checked metadata budget, 404-means-null-everything-else-means-
|
|
14
|
+
* error, service-time ordering). What is genuinely S3's, and therefore lives
|
|
15
|
+
* here:
|
|
16
|
+
*
|
|
17
|
+
* ── The object key ──────────────────────────────────────────────────────────
|
|
18
|
+
* `[<prefix>/]<tenant>/<principal>/<conversation>/<ref>` — the scope
|
|
19
|
+
* partitioned into key segments by `scopePath.ts`, the same percent-encoding
|
|
20
|
+
* law the directory adapter uses, so a tenant of literally `'..'` is a NAME in
|
|
21
|
+
* both. A ref alone opens nothing: a wrong scope computes a different key,
|
|
22
|
+
* S3 answers 404, and the caller reads `null` — one indistinguishable miss,
|
|
23
|
+
* never a cross-tenant read.
|
|
24
|
+
*
|
|
25
|
+
* ── The ticket rides as object metadata, not a sidecar ──────────────────────
|
|
26
|
+
* `x-amz-meta-af-artifact`, one entry, ASCII JSON. Two reasons this beats a
|
|
27
|
+
* second `<ref>.meta.json` object: `head()` becomes ONE HeadObject (the port
|
|
28
|
+
* promises the render-by-ref decision without paying for the payload, and a
|
|
29
|
+
* sidecar would make it a second GET), and `get()` returns the ticket AND the
|
|
30
|
+
* bytes in a single GetObject — a sidecar would make every read two round
|
|
31
|
+
* trips and open a window where one exists and the other does not.
|
|
32
|
+
*
|
|
33
|
+
* The cost is S3's cap: **2 KB of user metadata per object**, checked at put
|
|
34
|
+
* and refused by name. A ticket is small (a ref, a kind, a media type, sizes,
|
|
35
|
+
* a label); it only reaches 2 KB if the label is prose or `parentRefs` is a
|
|
36
|
+
* bibliography, and the refusal says which.
|
|
37
|
+
*
|
|
38
|
+
* ── What a 404 is allowed to mean here ──────────────────────────────────────
|
|
39
|
+
* S3 answers 404 for two different sentences: "no such key" and "no such
|
|
40
|
+
* bucket". Only the first is the port's "no data", so this adapter reads the
|
|
41
|
+
* CODE and not the status, and only the calls that named one object —
|
|
42
|
+
* Head/Get/Delete — may read a 404 as `null` at all. A 404 from PutObject or
|
|
43
|
+
* ListObjectsV2 means the bucket is not there; it goes through the sanitizer
|
|
44
|
+
* like every other failure, because nothing downstream is waiting to turn it
|
|
45
|
+
* into `null` and the SDK's text for it contains the object key.
|
|
46
|
+
*
|
|
47
|
+
* ── What a listing costs, said plainly ──────────────────────────────────────
|
|
48
|
+
* `ListObjectsV2` returns keys, sizes and `LastModified` — never user
|
|
49
|
+
* metadata. So `list()` pages the keys (cheap, 1000 per call), sorts by
|
|
50
|
+
* `LastModified` (newest first, as the port promises), and issues one
|
|
51
|
+
* `HeadObject` for each row IT RETURNS — not for the whole scope. An expired
|
|
52
|
+
* object inside a page is dropped from that page rather than backfilled, so a
|
|
53
|
+
* page can come back short while more pages remain. That is the honest trade;
|
|
54
|
+
* an "index object" listing every ticket in a scope would be cheaper and
|
|
55
|
+
* would be a lost-update race between two writers, which is worse than a
|
|
56
|
+
* round trip.
|
|
57
|
+
*
|
|
58
|
+
* ── Retention, and the operator's bulk tool ─────────────────────────────────
|
|
59
|
+
* The dials work exactly as everywhere else: `ttlMs` stamps `expiresAt` AT
|
|
60
|
+
* MINT (stated, never sprung), and budgets evict oldest-first (S3 has no cheap
|
|
61
|
+
* read-recency, the same statement `fileArtifacts` makes). Two S3-specific
|
|
62
|
+
* facts:
|
|
63
|
+
*
|
|
64
|
+
* • **Expiry is enforced on READ.** An expired object answers `null` from
|
|
65
|
+
* `head`/`get` and is deleted on the way past (a sweep on access), so an
|
|
66
|
+
* expired ticket can never be redeemed even if the object is still there.
|
|
67
|
+
* • **A put only SCANS the scope when a budget is configured.** With no
|
|
68
|
+
* `maxBytesPerScope`/`maxCountPerScope` there is nothing to plan, so a put
|
|
69
|
+
* is exactly one `PutObject` — and paying for a full scope listing on
|
|
70
|
+
* every write would be a real bill for no answer.
|
|
71
|
+
*
|
|
72
|
+
* Which leaves reclamation of storage for artifacts nobody reads again — and
|
|
73
|
+
* that is what **S3 Lifecycle rules** are for. They are the operator's bulk
|
|
74
|
+
* tool and this adapter does not create them (a lifecycle rule is a cost and
|
|
75
|
+
* compliance decision that belongs to your infrastructure). Align them like
|
|
76
|
+
* this:
|
|
77
|
+
*
|
|
78
|
+
* ```jsonc
|
|
79
|
+
* // Expire objects 7 days after creation, under the store's prefix.
|
|
80
|
+
* // Keep the rule LONGER than the store's ttlMs, never shorter:
|
|
81
|
+
* // the store's expiresAt is the promise consumers read on the ticket, and a
|
|
82
|
+
* // lifecycle rule that deletes first makes a live ticket resolve to null
|
|
83
|
+
* // BEFORE the time it printed. Longer, and lifecycle is what it should be:
|
|
84
|
+
* // the backstop that reclaims what the store's own sweep never revisited.
|
|
85
|
+
* { "Rules": [{ "ID": "agentfootprint-artifacts", "Status": "Enabled",
|
|
86
|
+
* "Filter": { "Prefix": "artifacts/" },
|
|
87
|
+
* "Expiration": { "Days": 7 } }] }
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* ── Lazy peer dependency ────────────────────────────────────────────────────
|
|
91
|
+
* `@aws-sdk/client-s3` is an OPTIONAL peer dependency, required at
|
|
92
|
+
* CONSTRUCTION (the sqliteSessions law): importing the barrel costs a browser
|
|
93
|
+
* bundle nothing, and a missing install refuses where the config was written
|
|
94
|
+
* rather than at the first put of the first run. Pass `client` to share the
|
|
95
|
+
* SDK configuration your app already has.
|
|
96
|
+
*
|
|
97
|
+
* ── Status ──────────────────────────────────────────────────────────────────
|
|
98
|
+
* Contract-shaped and tested; awaiting field use. The five commands it
|
|
99
|
+
* dispatches are pinned by `test/adapters/aws/aws-command-pin.test.ts`; the
|
|
100
|
+
* behavior is proved against an emulation double that speaks the same five.
|
|
101
|
+
* No live call has been made from this repository.
|
|
102
|
+
*/
|
|
103
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
104
|
+
exports.s3Artifacts = void 0;
|
|
105
|
+
const lazyRequire_js_1 = require("../lib/lazyRequire.js");
|
|
106
|
+
const minting_js_1 = require("./minting.js");
|
|
107
|
+
const naming_js_1 = require("./naming.js");
|
|
108
|
+
const objectStore_js_1 = require("./objectStore.js");
|
|
109
|
+
const payload_js_1 = require("./payload.js");
|
|
110
|
+
const retention_js_1 = require("./retention.js");
|
|
111
|
+
const scopePath_js_1 = require("./scopePath.js");
|
|
112
|
+
const streaming_js_1 = require("./streaming.js");
|
|
113
|
+
const types_js_1 = require("./types.js");
|
|
114
|
+
/** S3's user-metadata cap: 2 KB per object, keys and values together. */
|
|
115
|
+
const S3_METADATA_BUDGET = 2 * 1024;
|
|
116
|
+
/** Keys per ListObjectsV2 call. S3's own maximum. */
|
|
117
|
+
const LIST_PAGE_SIZE = 1000;
|
|
118
|
+
/** How many ListObjectsV2 calls one `list()`/sweep may make before it stops
|
|
119
|
+
* walking. A scope with a million objects is a retention bug, and spending
|
|
120
|
+
* the caller's afternoon proving it is not the answer. */
|
|
121
|
+
const MAX_LIST_CALLS = 20;
|
|
122
|
+
/** Load the peer dep, or refuse by name with the install line. */
|
|
123
|
+
function loadS3Sdk() {
|
|
124
|
+
try {
|
|
125
|
+
return (0, lazyRequire_js_1.lazyRequire)('@aws-sdk/client-s3');
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
throw new Error(`[artifacts] s3Artifacts requires the \`@aws-sdk/client-s3\` package.\n` +
|
|
129
|
+
` Install: npm install @aws-sdk/client-s3\n` +
|
|
130
|
+
` It is an OPTIONAL peer dependency, loaded only when you construct this store — ` +
|
|
131
|
+
`every other artifact adapter (inMemoryArtifacts, fileArtifacts, sqliteArtifacts) needs ` +
|
|
132
|
+
`nothing installed.`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* S3 error codes that are 404 and are NOT about the object: the BUCKET is not
|
|
137
|
+
* there.
|
|
138
|
+
*
|
|
139
|
+
* The status alone cannot carry this. `NoSuchBucket` is a modelled S3
|
|
140
|
+
* exception with `$metadata.httpStatusCode: 404`, exactly like `NoSuchKey`, so
|
|
141
|
+
* a check that reads only the status answers "that artifact is missing" for a
|
|
142
|
+
* store pointed at a bucket that does not exist — an empty scope reported over
|
|
143
|
+
* a configuration mistake, which is the failure law 4 forbids. Named codes,
|
|
144
|
+
* not the status, are what separate the two.
|
|
145
|
+
*/
|
|
146
|
+
const NOT_ABOUT_THE_OBJECT = new Set(['NoSuchBucket']);
|
|
147
|
+
/** Is this the SDK's "no such OBJECT"? 404 in any of the spellings S3 uses,
|
|
148
|
+
* minus the 404s that are about something else — see law 4 in
|
|
149
|
+
* `objectStore.ts`. Everything this rejects is NOT "no data". */
|
|
150
|
+
function isMissingObject(err) {
|
|
151
|
+
const e = err;
|
|
152
|
+
if (e === null || typeof e !== 'object')
|
|
153
|
+
return false;
|
|
154
|
+
const name = typeof e.name === 'string' ? e.name : '';
|
|
155
|
+
const code = typeof e.Code === 'string' ? e.Code : '';
|
|
156
|
+
if (NOT_ABOUT_THE_OBJECT.has(name) || NOT_ABOUT_THE_OBJECT.has(code))
|
|
157
|
+
return false;
|
|
158
|
+
if (e.$metadata?.httpStatusCode === 404)
|
|
159
|
+
return true;
|
|
160
|
+
return name === 'NotFound' || name === 'NoSuchKey' || code === 'NotFound' || code === 'NoSuchKey';
|
|
161
|
+
}
|
|
162
|
+
/** The bytes of a GetObject body, whichever shape the SDK handed back. */
|
|
163
|
+
async function readBodyBytes(body) {
|
|
164
|
+
if (body instanceof Uint8Array)
|
|
165
|
+
return body;
|
|
166
|
+
const stream = body;
|
|
167
|
+
if (stream !== null && typeof stream?.transformToByteArray === 'function') {
|
|
168
|
+
return await stream.transformToByteArray();
|
|
169
|
+
}
|
|
170
|
+
throw new Error(`[artifacts] s3Artifacts: GetObject answered with a body this adapter cannot read ` +
|
|
171
|
+
`(no transformToByteArray). The SDK's response stream mixin is missing — check the ` +
|
|
172
|
+
`@aws-sdk/client-s3 version.`);
|
|
173
|
+
}
|
|
174
|
+
/** The web stream of a GetObject body, or the bytes wrapped as one. */
|
|
175
|
+
async function readBodyStream(body) {
|
|
176
|
+
const stream = body;
|
|
177
|
+
if (stream !== null && typeof stream?.transformToWebStream === 'function') {
|
|
178
|
+
return stream.transformToWebStream();
|
|
179
|
+
}
|
|
180
|
+
return (0, streaming_js_1.bytesAsStream)(await readBodyBytes(body));
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Yield a web stream's chunks while COUNTING them against the declared
|
|
184
|
+
* length, so a producer that lied about its own payload fails with this
|
|
185
|
+
* library's sentence rather than as a malformed HTTP request.
|
|
186
|
+
*/
|
|
187
|
+
async function* countedChunks(body, declared) {
|
|
188
|
+
const reader = body.getReader();
|
|
189
|
+
let total = 0;
|
|
190
|
+
try {
|
|
191
|
+
for (;;) {
|
|
192
|
+
const { done, value } = await reader.read();
|
|
193
|
+
if (done)
|
|
194
|
+
break;
|
|
195
|
+
if (value === undefined)
|
|
196
|
+
continue;
|
|
197
|
+
total += value.byteLength;
|
|
198
|
+
if (total > declared) {
|
|
199
|
+
await reader.cancel();
|
|
200
|
+
throw new types_js_1.InvalidArtifactError(`s3Artifacts: the streamed payload is longer than the ${declared} bytes it declared. ` +
|
|
201
|
+
`The upload was cut off rather than completed under a meta that describes a ` +
|
|
202
|
+
`different payload. State the exact byte length.`);
|
|
203
|
+
}
|
|
204
|
+
yield value;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
finally {
|
|
208
|
+
reader.releaseLock();
|
|
209
|
+
}
|
|
210
|
+
if (total !== declared) {
|
|
211
|
+
throw new types_js_1.InvalidArtifactError(`s3Artifacts: the streamed payload ended after ${total} bytes but declared ${declared}. ` +
|
|
212
|
+
`The upload fails rather than storing a ticket that misdescribes its own payload.`);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* An artifact store in an S3 bucket.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* const store = s3Artifacts({ bucket: 'my-agent-artifacts', prefix: 'artifacts' });
|
|
220
|
+
* const agent = Agent.create({ provider, artifacts: store });
|
|
221
|
+
*/
|
|
222
|
+
function s3Artifacts(options) {
|
|
223
|
+
const bucket = (0, objectStore_js_1.assertBucketOption)('s3Artifacts', 'bucket', options.bucket);
|
|
224
|
+
const root = (0, scopePath_js_1.normalizeKeyRoot)('s3Artifacts', options.prefix);
|
|
225
|
+
const { retention } = options;
|
|
226
|
+
(0, retention_js_1.assertRetention)('s3Artifacts', retention);
|
|
227
|
+
const now = options._now ?? Date.now;
|
|
228
|
+
// Resolved at CONSTRUCTION: a missing peer dep refuses where the config was
|
|
229
|
+
// written, not at the first put of the first run.
|
|
230
|
+
const sdk = options._sdk ?? (options._client ? {} : loadS3Sdk());
|
|
231
|
+
const client = options._client ?? options.client ?? buildClient(sdk, options.region);
|
|
232
|
+
const commands = resolveCommands(sdk, options._client !== undefined || options.client !== undefined);
|
|
233
|
+
const keyFor = (scope, ref) => `${(0, scopePath_js_1.scopeKeyPrefix)(scope, root)}${ref}`;
|
|
234
|
+
const failure = (0, objectStore_js_1.objectFailurePolicy)('s3Artifacts', isMissingObject);
|
|
235
|
+
/**
|
|
236
|
+
* One command, dispatched.
|
|
237
|
+
*
|
|
238
|
+
* `meaning` says whether THIS call asked about one object, and so whether a
|
|
239
|
+
* 404 may travel back raw for the call site to read as `null`. It defaults
|
|
240
|
+
* to `'not-an-answer'`: a new call site that forgets it gets the sanitizer,
|
|
241
|
+
* never the leak. Only pass `'missing-object'` where the `catch` that
|
|
242
|
+
* converts it is a line away.
|
|
243
|
+
*/
|
|
244
|
+
const send = async (operation, command, meaning = 'not-an-answer') => {
|
|
245
|
+
try {
|
|
246
|
+
return await client.send(command);
|
|
247
|
+
}
|
|
248
|
+
catch (err) {
|
|
249
|
+
throw failure(operation, err, meaning);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
/** HeadObject → the ticket, or undefined for missing/foreign/expired.
|
|
253
|
+
* Expired objects are swept on the way past. */
|
|
254
|
+
const liveHead = async (scope, ref) => {
|
|
255
|
+
if (!(0, naming_js_1.isArtifactRef)(ref))
|
|
256
|
+
return undefined;
|
|
257
|
+
const key = keyFor(scope, ref);
|
|
258
|
+
let output;
|
|
259
|
+
try {
|
|
260
|
+
output = (await send('HeadObject', new commands.Head({ Bucket: bucket, Key: key }), 'missing-object'));
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
if (isMissingObject(err))
|
|
264
|
+
return undefined;
|
|
265
|
+
throw err;
|
|
266
|
+
}
|
|
267
|
+
const ticket = (0, objectStore_js_1.decodeArtifactMetaValue)((0, objectStore_js_1.readMetadataEntry)(output?.Metadata, objectStore_js_1.ARTIFACT_META_KEY));
|
|
268
|
+
if (ticket === undefined)
|
|
269
|
+
return undefined; // not one of ours
|
|
270
|
+
if ((0, objectStore_js_1.isExpiredMeta)(ticket.meta, now())) {
|
|
271
|
+
await removeKey(key);
|
|
272
|
+
return undefined;
|
|
273
|
+
}
|
|
274
|
+
return ticket;
|
|
275
|
+
};
|
|
276
|
+
const removeKey = async (key) => {
|
|
277
|
+
try {
|
|
278
|
+
await send('DeleteObject', new commands.Delete({ Bucket: bucket, Key: key }), 'missing-object');
|
|
279
|
+
}
|
|
280
|
+
catch (err) {
|
|
281
|
+
if (!isMissingObject(err))
|
|
282
|
+
throw err; // deleting an absence is agreement
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
/** Every key in a scope, with the size and creation time S3 reports for
|
|
286
|
+
* free on a listing. */
|
|
287
|
+
const listKeys = async (scope) => {
|
|
288
|
+
const prefix = (0, scopePath_js_1.scopeKeyPrefix)(scope, root);
|
|
289
|
+
const rows = [];
|
|
290
|
+
let token;
|
|
291
|
+
for (let call = 0; call < MAX_LIST_CALLS; call++) {
|
|
292
|
+
const output = (await send('ListObjectsV2', new commands.List({
|
|
293
|
+
Bucket: bucket,
|
|
294
|
+
Prefix: prefix,
|
|
295
|
+
MaxKeys: LIST_PAGE_SIZE,
|
|
296
|
+
...(token !== undefined && { ContinuationToken: token }),
|
|
297
|
+
})));
|
|
298
|
+
for (const object of output?.Contents ?? []) {
|
|
299
|
+
const key = object.Key;
|
|
300
|
+
if (typeof key !== 'string')
|
|
301
|
+
continue;
|
|
302
|
+
const ref = key.slice(prefix.length);
|
|
303
|
+
if (!(0, naming_js_1.isArtifactRef)(ref))
|
|
304
|
+
continue; // foreign object in a shared bucket
|
|
305
|
+
rows.push({
|
|
306
|
+
key,
|
|
307
|
+
ref,
|
|
308
|
+
serviceCreatedAt: toMillis(object.LastModified),
|
|
309
|
+
bytes: typeof object.Size === 'number' ? object.Size : 0,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
token = output?.IsTruncated === true ? output.NextContinuationToken : undefined;
|
|
313
|
+
if (token === undefined)
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
return rows;
|
|
317
|
+
};
|
|
318
|
+
return {
|
|
319
|
+
async put(scope, input) {
|
|
320
|
+
const at = now();
|
|
321
|
+
const { meta } = await (0, minting_js_1.prepareArtifact)(input, async (parent) => (await liveHead(scope, parent)) !== undefined, retention, at);
|
|
322
|
+
const bytes = (0, payload_js_1.canonicalPayloadBytes)(input.data);
|
|
323
|
+
const shape = (0, payload_js_1.payloadShapeOf)(input.data);
|
|
324
|
+
const metaValue = (0, objectStore_js_1.encodeArtifactMetaValue)(meta, shape, S3_METADATA_BUDGET, 's3Artifacts');
|
|
325
|
+
const swept = await applyRetention(scope, meta.bytes, at);
|
|
326
|
+
await send('PutObject', new commands.Put({
|
|
327
|
+
Bucket: bucket,
|
|
328
|
+
Key: keyFor(scope, meta.ref),
|
|
329
|
+
Body: bytes,
|
|
330
|
+
ContentType: meta.mediaType,
|
|
331
|
+
Metadata: { [objectStore_js_1.ARTIFACT_META_KEY]: metaValue },
|
|
332
|
+
}));
|
|
333
|
+
return { meta, swept };
|
|
334
|
+
},
|
|
335
|
+
async head(scope, ref) {
|
|
336
|
+
return (await liveHead(scope, ref))?.meta ?? null;
|
|
337
|
+
},
|
|
338
|
+
async get(scope, ref) {
|
|
339
|
+
if (!(0, naming_js_1.isArtifactRef)(ref))
|
|
340
|
+
return null;
|
|
341
|
+
const key = keyFor(scope, ref);
|
|
342
|
+
let output;
|
|
343
|
+
try {
|
|
344
|
+
output = (await send('GetObject', new commands.Get({ Bucket: bucket, Key: key }), 'missing-object'));
|
|
345
|
+
}
|
|
346
|
+
catch (err) {
|
|
347
|
+
if (isMissingObject(err))
|
|
348
|
+
return null;
|
|
349
|
+
throw err;
|
|
350
|
+
}
|
|
351
|
+
const ticket = (0, objectStore_js_1.decodeArtifactMetaValue)((0, objectStore_js_1.readMetadataEntry)(output?.Metadata, objectStore_js_1.ARTIFACT_META_KEY));
|
|
352
|
+
if (ticket === undefined)
|
|
353
|
+
return null;
|
|
354
|
+
if ((0, objectStore_js_1.isExpiredMeta)(ticket.meta, now())) {
|
|
355
|
+
await removeKey(key);
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
const bytes = await readBodyBytes(output.Body);
|
|
359
|
+
const data = (0, payload_js_1.decodeCanonicalPayload)(ticket.shape, bytes);
|
|
360
|
+
if (ticket.meta.digest !== undefined) {
|
|
361
|
+
const actual = await (0, payload_js_1.computeArtifactDigest)(data);
|
|
362
|
+
if (actual !== ticket.meta.digest) {
|
|
363
|
+
throw new types_js_1.ArtifactIntegrityError(ticket.meta.ref, ticket.meta.digest, actual);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return { meta: ticket.meta, data };
|
|
367
|
+
},
|
|
368
|
+
async delete(scope, ref) {
|
|
369
|
+
if (!(0, naming_js_1.isArtifactRef)(ref))
|
|
370
|
+
return;
|
|
371
|
+
await removeKey(keyFor(scope, ref));
|
|
372
|
+
},
|
|
373
|
+
async list(scope, listOptions) {
|
|
374
|
+
const keys = await listKeys(scope);
|
|
375
|
+
// Order and page over the KEY rows (LastModified is free on a listing);
|
|
376
|
+
// only the rows this page returns are HEADed for their tickets.
|
|
377
|
+
const window = (0, objectStore_js_1.pageObjectListing)(keys.map((row) => ({
|
|
378
|
+
meta: { ref: row.ref },
|
|
379
|
+
serviceCreatedAt: row.serviceCreatedAt,
|
|
380
|
+
})), listOptions);
|
|
381
|
+
const rows = [];
|
|
382
|
+
for (const stub of window.artifacts) {
|
|
383
|
+
const ticket = await liveHead(scope, stub.ref);
|
|
384
|
+
if (ticket !== undefined)
|
|
385
|
+
rows.push(ticket.meta);
|
|
386
|
+
}
|
|
387
|
+
return { artifacts: rows, ...(window.cursor !== undefined && { cursor: window.cursor }) };
|
|
388
|
+
},
|
|
389
|
+
async putStream(scope, input, body) {
|
|
390
|
+
const at = now();
|
|
391
|
+
const declared = (0, streaming_js_1.assertStreamBytes)('s3Artifacts', input.bytes);
|
|
392
|
+
// The streamed payload is bytes by definition: nothing here parses it,
|
|
393
|
+
// so it reads back as a Uint8Array through get() and as the same bytes
|
|
394
|
+
// through getStream().
|
|
395
|
+
const { meta } = await (0, minting_js_1.prepareArtifact)({ ...input, data: new Uint8Array(0) }, async (parent) => (await liveHead(scope, parent)) !== undefined, retention, at);
|
|
396
|
+
const stated = { ...meta, bytes: declared };
|
|
397
|
+
const metaValue = (0, objectStore_js_1.encodeArtifactMetaValue)(stated, 'binary', S3_METADATA_BUDGET, 's3Artifacts');
|
|
398
|
+
const swept = await applyRetention(scope, declared, at);
|
|
399
|
+
const stream = (0, lazyRequire_js_1.lazyRequire)('node:stream');
|
|
400
|
+
await send('PutObject', new commands.Put({
|
|
401
|
+
Bucket: bucket,
|
|
402
|
+
Key: keyFor(scope, stated.ref),
|
|
403
|
+
Body: stream.Readable.from(countedChunks(body, declared)),
|
|
404
|
+
ContentLength: declared,
|
|
405
|
+
ContentType: stated.mediaType,
|
|
406
|
+
Metadata: { [objectStore_js_1.ARTIFACT_META_KEY]: metaValue },
|
|
407
|
+
}));
|
|
408
|
+
return { meta: stated, swept };
|
|
409
|
+
},
|
|
410
|
+
async getStream(scope, ref) {
|
|
411
|
+
if (!(0, naming_js_1.isArtifactRef)(ref))
|
|
412
|
+
return null;
|
|
413
|
+
const key = keyFor(scope, ref);
|
|
414
|
+
let output;
|
|
415
|
+
try {
|
|
416
|
+
output = (await send('GetObject', new commands.Get({ Bucket: bucket, Key: key }), 'missing-object'));
|
|
417
|
+
}
|
|
418
|
+
catch (err) {
|
|
419
|
+
if (isMissingObject(err))
|
|
420
|
+
return null;
|
|
421
|
+
throw err;
|
|
422
|
+
}
|
|
423
|
+
const ticket = (0, objectStore_js_1.decodeArtifactMetaValue)((0, objectStore_js_1.readMetadataEntry)(output?.Metadata, objectStore_js_1.ARTIFACT_META_KEY));
|
|
424
|
+
if (ticket === undefined)
|
|
425
|
+
return null;
|
|
426
|
+
if ((0, objectStore_js_1.isExpiredMeta)(ticket.meta, now())) {
|
|
427
|
+
await removeKey(key);
|
|
428
|
+
return null;
|
|
429
|
+
}
|
|
430
|
+
return { meta: ticket.meta, body: await readBodyStream(output.Body) };
|
|
431
|
+
},
|
|
432
|
+
};
|
|
433
|
+
/**
|
|
434
|
+
* The retention pass, run at put. Returns what it swept.
|
|
435
|
+
*
|
|
436
|
+
* With no budget dials there is nothing to plan, so nothing is listed: a
|
|
437
|
+
* put stays exactly one PutObject. Expiry still binds — it is enforced at
|
|
438
|
+
* read, where it cannot be missed, and reclaimed in bulk by the lifecycle
|
|
439
|
+
* rule in this file's header.
|
|
440
|
+
*/
|
|
441
|
+
async function applyRetention(scope, incomingBytes, at) {
|
|
442
|
+
if (retention === undefined ||
|
|
443
|
+
(retention.maxBytesPerScope === undefined && retention.maxCountPerScope === undefined)) {
|
|
444
|
+
return [];
|
|
445
|
+
}
|
|
446
|
+
const keys = await listKeys(scope);
|
|
447
|
+
const held = [];
|
|
448
|
+
for (const row of keys) {
|
|
449
|
+
const ticket = await liveHead(scope, row.ref);
|
|
450
|
+
if (ticket === undefined)
|
|
451
|
+
continue; // missing, foreign, or just swept
|
|
452
|
+
held.push({
|
|
453
|
+
ref: ticket.meta.ref,
|
|
454
|
+
kind: ticket.meta.kind,
|
|
455
|
+
bytes: ticket.meta.bytes,
|
|
456
|
+
...(ticket.meta.expiresAt !== undefined && { expiresAt: ticket.meta.expiresAt }),
|
|
457
|
+
// No cheap read-recency in an object store: oldest-first is the
|
|
458
|
+
// stated law, exactly as it is for a directory.
|
|
459
|
+
lastAccessedAt: ticket.meta.createdAt,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
const plan = (0, retention_js_1.planRetention)(held, incomingBytes, retention, at);
|
|
463
|
+
if (plan.refusal !== undefined)
|
|
464
|
+
throw new types_js_1.InvalidArtifactError(plan.refusal);
|
|
465
|
+
for (const gone of plan.swept)
|
|
466
|
+
await removeKey(keyFor(scope, gone.ref));
|
|
467
|
+
return plan.swept;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
exports.s3Artifacts = s3Artifacts;
|
|
471
|
+
/** `LastModified` as milliseconds, whatever shape it arrived in. */
|
|
472
|
+
function toMillis(value) {
|
|
473
|
+
if (value instanceof Date)
|
|
474
|
+
return value.getTime();
|
|
475
|
+
if (typeof value === 'string') {
|
|
476
|
+
const parsed = Date.parse(value);
|
|
477
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
478
|
+
}
|
|
479
|
+
return 0;
|
|
480
|
+
}
|
|
481
|
+
function buildClient(sdk, region) {
|
|
482
|
+
if (typeof sdk.S3Client !== 'function') {
|
|
483
|
+
throw new Error(`[artifacts] s3Artifacts: \`@aws-sdk/client-s3\` is installed but exports no S3Client. ` +
|
|
484
|
+
`Update the SDK, or pass \`client\` with a pre-built one.`);
|
|
485
|
+
}
|
|
486
|
+
return new sdk.S3Client({ ...(region !== undefined && { region }) });
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* The five command constructors, resolved once.
|
|
490
|
+
*
|
|
491
|
+
* A name this adapter reaches for and the SDK does not export is a REFUSAL,
|
|
492
|
+
* never a silent `undefined` that fails as "x is not a constructor" three
|
|
493
|
+
* frames away — the command-name pin exists because this package shipped that
|
|
494
|
+
* bug three times.
|
|
495
|
+
*/
|
|
496
|
+
function resolveCommands(sdk, injected) {
|
|
497
|
+
const wanted = [
|
|
498
|
+
'PutObjectCommand',
|
|
499
|
+
'GetObjectCommand',
|
|
500
|
+
'HeadObjectCommand',
|
|
501
|
+
'DeleteObjectCommand',
|
|
502
|
+
'ListObjectsV2Command',
|
|
503
|
+
];
|
|
504
|
+
const missing = wanted.filter((name) => typeof sdk[name] !== 'function');
|
|
505
|
+
if (missing.length > 0) {
|
|
506
|
+
if (injected && missing.length === wanted.length) {
|
|
507
|
+
// An injected client with no SDK module: the double owns the wire, and
|
|
508
|
+
// each command is a plain object stamped with its own operation name.
|
|
509
|
+
return {
|
|
510
|
+
Put: shimCommand('PutObject'),
|
|
511
|
+
Get: shimCommand('GetObject'),
|
|
512
|
+
Head: shimCommand('HeadObject'),
|
|
513
|
+
Delete: shimCommand('DeleteObject'),
|
|
514
|
+
List: shimCommand('ListObjectsV2'),
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
throw new Error(`[artifacts] s3Artifacts: \`@aws-sdk/client-s3\` is installed but ${missing.join(', ')} ` +
|
|
518
|
+
`${missing.length === 1 ? 'was' : 'were'} not found. Update the SDK.`);
|
|
519
|
+
}
|
|
520
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
521
|
+
return {
|
|
522
|
+
Put: sdk.PutObjectCommand,
|
|
523
|
+
Get: sdk.GetObjectCommand,
|
|
524
|
+
Head: sdk.HeadObjectCommand,
|
|
525
|
+
Delete: sdk.DeleteObjectCommand,
|
|
526
|
+
List: sdk.ListObjectsV2Command,
|
|
527
|
+
};
|
|
528
|
+
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
|
529
|
+
}
|
|
530
|
+
/** A stand-in command for an injected client: it carries the operation name
|
|
531
|
+
* and the input, so a double sees exactly which call was made. */
|
|
532
|
+
function shimCommand(operation) {
|
|
533
|
+
return class {
|
|
534
|
+
static __command = operation;
|
|
535
|
+
__command = operation;
|
|
536
|
+
__input;
|
|
537
|
+
constructor(input) {
|
|
538
|
+
this.__input = input;
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
//# sourceMappingURL=s3Artifacts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"s3Artifacts.js","sourceRoot":"","sources":["../../src/artifacts/s3Artifacts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* artifacts/scopePath — the ONE owner of "a scope becomes path segments".
|
|
4
|
+
*
|
|
5
|
+
* Every durable adapter partitions its storage by the scope tuple, and every
|
|
6
|
+
* one of them takes CALLER STRINGS (`tenant`, `principal`, `conversationId`)
|
|
7
|
+
* and turns them into names inside a hierarchy: directories on a filesystem,
|
|
8
|
+
* key prefixes in an object store. That is a traversal surface, and it must
|
|
9
|
+
* be closed the same way in all of them — one encoding, one place, so a
|
|
10
|
+
* hostile tenant cannot be inert on disk and a navigation hop in a bucket.
|
|
11
|
+
*
|
|
12
|
+
* The law, unchanged from the directory adapter that first stated it
|
|
13
|
+
* (9.21.0), now shared rather than copied:
|
|
14
|
+
*
|
|
15
|
+
* • encode from the FIELD, never from a joined namespace — a tenant
|
|
16
|
+
* containing `/` must not become two segments;
|
|
17
|
+
* • `encodeURIComponent` leaves `.` alone, so dots are encoded too:
|
|
18
|
+
* a tenant of literally `'..'` would otherwise survive as a real
|
|
19
|
+
* parent-directory hop (`%2E%2E` is a NAME);
|
|
20
|
+
* • an empty or absent field collapses to `_`, mirroring
|
|
21
|
+
* `identityNamespace`'s stable layout, so "no tenant" is one shape and
|
|
22
|
+
* not two.
|
|
23
|
+
*
|
|
24
|
+
* After this, `..`, `/` and `\` arrive as data and land as literals. The
|
|
25
|
+
* adapters assert `isArtifactRef` on the last segment anyway, because
|
|
26
|
+
* "cannot happen" is a claim, not a defence.
|
|
27
|
+
*/
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.normalizeKeyRoot = exports.scopeKeyPrefix = exports.scopeSegments = exports.scopeSegment = void 0;
|
|
30
|
+
/** One RAW tuple field → one inert path/key segment. */
|
|
31
|
+
function scopeSegment(raw) {
|
|
32
|
+
return encodeURIComponent(raw === undefined || raw === '' ? '_' : raw).replace(/\./g, '%2E');
|
|
33
|
+
}
|
|
34
|
+
exports.scopeSegment = scopeSegment;
|
|
35
|
+
/** The three encoded segments of a scope, in the fixed tenant/principal/
|
|
36
|
+
* conversation order every adapter lays out. */
|
|
37
|
+
function scopeSegments(scope) {
|
|
38
|
+
return [
|
|
39
|
+
scopeSegment(scope.tenant),
|
|
40
|
+
scopeSegment(scope.principal),
|
|
41
|
+
scopeSegment(scope.conversationId),
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
exports.scopeSegments = scopeSegments;
|
|
45
|
+
/**
|
|
46
|
+
* The object-key prefix for one scope: `[<root>/]<tenant>/<principal>/<conversation>/`.
|
|
47
|
+
*
|
|
48
|
+
* Trailing slash included on purpose — it is what makes a prefix listing
|
|
49
|
+
* exact. Without it, scope `c` would also list scope `c2`'s keys, which is
|
|
50
|
+
* the isolation bug this whole module exists to prevent.
|
|
51
|
+
*/
|
|
52
|
+
function scopeKeyPrefix(scope, root) {
|
|
53
|
+
const head = root === undefined || root === '' ? '' : `${root}/`;
|
|
54
|
+
return `${head}${scopeSegments(scope).join('/')}/`;
|
|
55
|
+
}
|
|
56
|
+
exports.scopeKeyPrefix = scopeKeyPrefix;
|
|
57
|
+
/**
|
|
58
|
+
* Validate an operator-supplied key ROOT at construction (the prefix a bucket
|
|
59
|
+
* is shared under). It is not caller data — an operator writes it — so it is
|
|
60
|
+
* not encoded; it is CHECKED, and refused where it would be ambiguous.
|
|
61
|
+
*
|
|
62
|
+
* @param adapter the factory name, for the refusal's first word.
|
|
63
|
+
* @param root the raw option, or undefined.
|
|
64
|
+
* @returns the normalized root (no leading/trailing `/`), or undefined.
|
|
65
|
+
*/
|
|
66
|
+
function normalizeKeyRoot(adapter, root) {
|
|
67
|
+
if (root === undefined)
|
|
68
|
+
return undefined;
|
|
69
|
+
if (typeof root !== 'string' || root.trim() === '') {
|
|
70
|
+
throw new TypeError(`[artifacts] ${adapter}({ prefix: ${JSON.stringify(root)} }) is not a key prefix. ` +
|
|
71
|
+
`Give it a path segment (e.g. 'artifacts'), or omit the option — absent means the ` +
|
|
72
|
+
`scope layout starts at the root of the bucket.`);
|
|
73
|
+
}
|
|
74
|
+
if (root.includes('..')) {
|
|
75
|
+
throw new TypeError(`[artifacts] ${adapter}({ prefix: ${JSON.stringify(root)} }) contains '..'. Object keys ` +
|
|
76
|
+
`are flat strings and '..' is not a hop here, but a prefix that reads like one is a ` +
|
|
77
|
+
`misunderstanding waiting to be acted on. Name the prefix literally.`);
|
|
78
|
+
}
|
|
79
|
+
const trimmed = root.replace(/^\/+/, '').replace(/\/+$/, '');
|
|
80
|
+
if (trimmed === '') {
|
|
81
|
+
throw new TypeError(`[artifacts] ${adapter}({ prefix: ${JSON.stringify(root)} }) is only slashes. Name a ` +
|
|
82
|
+
`prefix, or omit the option.`);
|
|
83
|
+
}
|
|
84
|
+
return trimmed;
|
|
85
|
+
}
|
|
86
|
+
exports.normalizeKeyRoot = normalizeKeyRoot;
|
|
87
|
+
//# sourceMappingURL=scopePath.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopePath.js","sourceRoot":"","sources":["../../src/artifacts/scopePath.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;;AAIH,wDAAwD;AACxD,SAAgB,YAAY,CAAC,GAAuB;IAClD,OAAO,kBAAkB,CAAC,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC/F,CAAC;AAFD,oCAEC;AAED;iDACiD;AACjD,SAAgB,aAAa,CAAC,KAAoB;IAChD,OAAO;QACL,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC;QAC1B,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC;QAC7B,YAAY,CAAC,KAAK,CAAC,cAAc,CAAC;KACnC,CAAC;AACJ,CAAC;AAND,sCAMC;AAED;;;;;;GAMG;AACH,SAAgB,cAAc,CAAC,KAAoB,EAAE,IAAa;IAChE,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;IACjE,OAAO,GAAG,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;AACrD,CAAC;AAHD,wCAGC;AAED;;;;;;;;GAQG;AACH,SAAgB,gBAAgB,CAAC,OAAe,EAAE,IAAwB;IACxE,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACzC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QACnD,MAAM,IAAI,SAAS,CACjB,eAAe,OAAO,cAAc,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,2BAA2B;YACjF,mFAAmF;YACnF,gDAAgD,CACnD,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,SAAS,CACjB,eAAe,OAAO,cAAc,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iCAAiC;YACvF,qFAAqF;YACrF,qEAAqE,CACxE,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7D,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,SAAS,CACjB,eAAe,OAAO,cAAc,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,8BAA8B;YACpF,6BAA6B,CAChC,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAxBD,4CAwBC"}
|