agentfootprint 9.20.0 → 9.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +1 -0
  4. package/ai-instructions/claude-code/SKILL.md +1 -1
  5. package/dist/artifacts/capability.js +131 -0
  6. package/dist/artifacts/capability.js.map +1 -0
  7. package/dist/artifacts/fileArtifacts.js +230 -0
  8. package/dist/artifacts/fileArtifacts.js.map +1 -0
  9. package/dist/artifacts/inMemoryArtifacts.js +165 -0
  10. package/dist/artifacts/inMemoryArtifacts.js.map +1 -0
  11. package/dist/artifacts/index.js +47 -0
  12. package/dist/artifacts/index.js.map +1 -0
  13. package/dist/artifacts/minting.js +79 -0
  14. package/dist/artifacts/minting.js.map +1 -0
  15. package/dist/artifacts/naming.js +64 -0
  16. package/dist/artifacts/naming.js.map +1 -0
  17. package/dist/artifacts/payload.js +113 -0
  18. package/dist/artifacts/payload.js.map +1 -0
  19. package/dist/artifacts/placement.js +86 -0
  20. package/dist/artifacts/placement.js.map +1 -0
  21. package/dist/artifacts/present.js +98 -0
  22. package/dist/artifacts/present.js.map +1 -0
  23. package/dist/artifacts/retention.js +121 -0
  24. package/dist/artifacts/retention.js.map +1 -0
  25. package/dist/artifacts/sqliteArtifacts.js +338 -0
  26. package/dist/artifacts/sqliteArtifacts.js.map +1 -0
  27. package/dist/artifacts/types.js +96 -0
  28. package/dist/artifacts/types.js.map +1 -0
  29. package/dist/artifacts/wants.js +240 -0
  30. package/dist/artifacts/wants.js.map +1 -0
  31. package/dist/core/Agent.js +73 -2
  32. package/dist/core/Agent.js.map +1 -1
  33. package/dist/core/agent/buildToolRegistry.js +30 -1
  34. package/dist/core/agent/buildToolRegistry.js.map +1 -1
  35. package/dist/core/agent/presentTool.js +59 -0
  36. package/dist/core/agent/presentTool.js.map +1 -0
  37. package/dist/core/agent/stages/toolCalls.js +347 -8
  38. package/dist/core/agent/stages/toolCalls.js.map +1 -1
  39. package/dist/core/codeRunnerTool.js +89 -3
  40. package/dist/core/codeRunnerTool.js.map +1 -1
  41. package/dist/core/tools.js +7 -0
  42. package/dist/core/tools.js.map +1 -1
  43. package/dist/esm/adapters/types.d.ts +17 -1
  44. package/dist/esm/artifacts/capability.d.ts +93 -0
  45. package/dist/esm/artifacts/capability.js +126 -0
  46. package/dist/esm/artifacts/capability.js.map +1 -0
  47. package/dist/esm/artifacts/fileArtifacts.d.ts +58 -0
  48. package/dist/esm/artifacts/fileArtifacts.js +225 -0
  49. package/dist/esm/artifacts/fileArtifacts.js.map +1 -0
  50. package/dist/esm/artifacts/inMemoryArtifacts.d.ts +54 -0
  51. package/dist/esm/artifacts/inMemoryArtifacts.js +161 -0
  52. package/dist/esm/artifacts/inMemoryArtifacts.js.map +1 -0
  53. package/dist/esm/artifacts/index.d.ts +21 -0
  54. package/dist/esm/artifacts/index.js +21 -0
  55. package/dist/esm/artifacts/index.js.map +1 -0
  56. package/dist/esm/artifacts/minting.d.ts +29 -0
  57. package/dist/esm/artifacts/minting.js +75 -0
  58. package/dist/esm/artifacts/minting.js.map +1 -0
  59. package/dist/esm/artifacts/naming.d.ts +36 -0
  60. package/dist/esm/artifacts/naming.js +59 -0
  61. package/dist/esm/artifacts/naming.js.map +1 -0
  62. package/dist/esm/artifacts/payload.d.ts +43 -0
  63. package/dist/esm/artifacts/payload.js +105 -0
  64. package/dist/esm/artifacts/payload.js.map +1 -0
  65. package/dist/esm/artifacts/placement.d.ts +74 -0
  66. package/dist/esm/artifacts/placement.js +79 -0
  67. package/dist/esm/artifacts/placement.js.map +1 -0
  68. package/dist/esm/artifacts/present.d.ts +77 -0
  69. package/dist/esm/artifacts/present.js +94 -0
  70. package/dist/esm/artifacts/present.js.map +1 -0
  71. package/dist/esm/artifacts/retention.d.ts +72 -0
  72. package/dist/esm/artifacts/retention.js +115 -0
  73. package/dist/esm/artifacts/retention.js.map +1 -0
  74. package/dist/esm/artifacts/sqliteArtifacts.d.ts +90 -0
  75. package/dist/esm/artifacts/sqliteArtifacts.js +333 -0
  76. package/dist/esm/artifacts/sqliteArtifacts.js.map +1 -0
  77. package/dist/esm/artifacts/types.d.ts +220 -0
  78. package/dist/esm/artifacts/types.js +90 -0
  79. package/dist/esm/artifacts/types.js.map +1 -0
  80. package/dist/esm/artifacts/wants.d.ts +104 -0
  81. package/dist/esm/artifacts/wants.js +234 -0
  82. package/dist/esm/artifacts/wants.js.map +1 -0
  83. package/dist/esm/core/Agent.d.ts +8 -2
  84. package/dist/esm/core/Agent.js +73 -2
  85. package/dist/esm/core/Agent.js.map +1 -1
  86. package/dist/esm/core/agent/buildToolRegistry.d.ts +11 -1
  87. package/dist/esm/core/agent/buildToolRegistry.js +30 -1
  88. package/dist/esm/core/agent/buildToolRegistry.js.map +1 -1
  89. package/dist/esm/core/agent/presentTool.d.ts +22 -0
  90. package/dist/esm/core/agent/presentTool.js +55 -0
  91. package/dist/esm/core/agent/presentTool.js.map +1 -0
  92. package/dist/esm/core/agent/stages/toolCalls.d.ts +22 -0
  93. package/dist/esm/core/agent/stages/toolCalls.js +347 -8
  94. package/dist/esm/core/agent/stages/toolCalls.js.map +1 -1
  95. package/dist/esm/core/agent/types.d.ts +46 -0
  96. package/dist/esm/core/codeRunnerTool.js +89 -3
  97. package/dist/esm/core/codeRunnerTool.js.map +1 -1
  98. package/dist/esm/core/tools.d.ts +49 -0
  99. package/dist/esm/core/tools.js +7 -0
  100. package/dist/esm/core/tools.js.map +1 -1
  101. package/dist/esm/events/dispatcher.d.ts +1 -1
  102. package/dist/esm/events/dispatcher.js.map +1 -1
  103. package/dist/esm/events/payloads.d.ts +83 -0
  104. package/dist/esm/events/registry.d.ts +13 -1
  105. package/dist/esm/events/registry.js +12 -0
  106. package/dist/esm/events/registry.js.map +1 -1
  107. package/dist/esm/index.d.ts +3 -1
  108. package/dist/esm/index.js +17 -0
  109. package/dist/esm/index.js.map +1 -1
  110. package/dist/esm/lib/mcp/mcpServe.js +16 -0
  111. package/dist/esm/lib/mcp/mcpServe.js.map +1 -1
  112. package/dist/esm/lib/trace-toolpack/traceToolpack.js +4 -0
  113. package/dist/esm/lib/trace-toolpack/traceToolpack.js.map +1 -1
  114. package/dist/esm/recorders/core/ArtifactsRecorder.d.ts +22 -0
  115. package/dist/esm/recorders/core/ArtifactsRecorder.js +27 -0
  116. package/dist/esm/recorders/core/ArtifactsRecorder.js.map +1 -0
  117. package/dist/events/dispatcher.js.map +1 -1
  118. package/dist/events/registry.js +12 -0
  119. package/dist/events/registry.js.map +1 -1
  120. package/dist/index.js +43 -8
  121. package/dist/index.js.map +1 -1
  122. package/dist/lib/mcp/mcpServe.js +16 -0
  123. package/dist/lib/mcp/mcpServe.js.map +1 -1
  124. package/dist/lib/trace-toolpack/traceToolpack.js +4 -0
  125. package/dist/lib/trace-toolpack/traceToolpack.js.map +1 -1
  126. package/dist/recorders/core/ArtifactsRecorder.js +31 -0
  127. package/dist/recorders/core/ArtifactsRecorder.js.map +1 -0
  128. package/dist/types/adapters/types.d.ts +17 -1
  129. package/dist/types/adapters/types.d.ts.map +1 -1
  130. package/dist/types/artifacts/capability.d.ts +94 -0
  131. package/dist/types/artifacts/capability.d.ts.map +1 -0
  132. package/dist/types/artifacts/fileArtifacts.d.ts +59 -0
  133. package/dist/types/artifacts/fileArtifacts.d.ts.map +1 -0
  134. package/dist/types/artifacts/inMemoryArtifacts.d.ts +55 -0
  135. package/dist/types/artifacts/inMemoryArtifacts.d.ts.map +1 -0
  136. package/dist/types/artifacts/index.d.ts +22 -0
  137. package/dist/types/artifacts/index.d.ts.map +1 -0
  138. package/dist/types/artifacts/minting.d.ts +30 -0
  139. package/dist/types/artifacts/minting.d.ts.map +1 -0
  140. package/dist/types/artifacts/naming.d.ts +37 -0
  141. package/dist/types/artifacts/naming.d.ts.map +1 -0
  142. package/dist/types/artifacts/payload.d.ts +44 -0
  143. package/dist/types/artifacts/payload.d.ts.map +1 -0
  144. package/dist/types/artifacts/placement.d.ts +75 -0
  145. package/dist/types/artifacts/placement.d.ts.map +1 -0
  146. package/dist/types/artifacts/present.d.ts +78 -0
  147. package/dist/types/artifacts/present.d.ts.map +1 -0
  148. package/dist/types/artifacts/retention.d.ts +73 -0
  149. package/dist/types/artifacts/retention.d.ts.map +1 -0
  150. package/dist/types/artifacts/sqliteArtifacts.d.ts +91 -0
  151. package/dist/types/artifacts/sqliteArtifacts.d.ts.map +1 -0
  152. package/dist/types/artifacts/types.d.ts +221 -0
  153. package/dist/types/artifacts/types.d.ts.map +1 -0
  154. package/dist/types/artifacts/wants.d.ts +105 -0
  155. package/dist/types/artifacts/wants.d.ts.map +1 -0
  156. package/dist/types/core/Agent.d.ts +8 -2
  157. package/dist/types/core/Agent.d.ts.map +1 -1
  158. package/dist/types/core/agent/buildToolRegistry.d.ts +11 -1
  159. package/dist/types/core/agent/buildToolRegistry.d.ts.map +1 -1
  160. package/dist/types/core/agent/presentTool.d.ts +23 -0
  161. package/dist/types/core/agent/presentTool.d.ts.map +1 -0
  162. package/dist/types/core/agent/stages/toolCalls.d.ts +22 -0
  163. package/dist/types/core/agent/stages/toolCalls.d.ts.map +1 -1
  164. package/dist/types/core/agent/types.d.ts +46 -0
  165. package/dist/types/core/agent/types.d.ts.map +1 -1
  166. package/dist/types/core/codeRunnerTool.d.ts.map +1 -1
  167. package/dist/types/core/tools.d.ts +49 -0
  168. package/dist/types/core/tools.d.ts.map +1 -1
  169. package/dist/types/events/dispatcher.d.ts +1 -1
  170. package/dist/types/events/dispatcher.d.ts.map +1 -1
  171. package/dist/types/events/payloads.d.ts +83 -0
  172. package/dist/types/events/payloads.d.ts.map +1 -1
  173. package/dist/types/events/registry.d.ts +13 -1
  174. package/dist/types/events/registry.d.ts.map +1 -1
  175. package/dist/types/index.d.ts +3 -1
  176. package/dist/types/index.d.ts.map +1 -1
  177. package/dist/types/lib/mcp/mcpServe.d.ts.map +1 -1
  178. package/dist/types/lib/trace-toolpack/traceToolpack.d.ts.map +1 -1
  179. package/dist/types/recorders/core/ArtifactsRecorder.d.ts +23 -0
  180. package/dist/types/recorders/core/ArtifactsRecorder.d.ts.map +1 -0
  181. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ /**
2
+ * artifacts/capability — `ctx.artifacts`, the scope-bound door a tool gets.
3
+ *
4
+ * Shaped exactly like `ctx.credentials`:
5
+ * • ALWAYS present — with no store attached every method is a teaching
6
+ * refusal naming how to attach one, so a tool can never silently
7
+ * optional-chain past a store that is not there;
8
+ * • fail-closed — the refusal throws; `ctx.hasArtifacts` is the fact to
9
+ * branch on for an intentional degraded mode;
10
+ * • scope composed by the FRAMEWORK from the run's identity/session — the
11
+ * capability closes over it, so a tool cannot name, widen or replace the
12
+ * scope it resolves under. The five verbs here take no scope argument on
13
+ * purpose: that argument was already answered by whoever built the
14
+ * context.
15
+ *
16
+ * Every hop lands on the record AS IT HAPPENS: this module reports facts to a
17
+ * neutral sink (a plain callback), and the tool-dispatch layer adapts that
18
+ * sink onto the typed event channel. Neutral so this folder never imports the
19
+ * event system or the agent — core wires artifacts, never the reverse.
20
+ */
21
+ import { type ArtifactListOptions, type ArtifactListResult, type ArtifactMeta, type ArtifactOrigin, type ArtifactRecord, type ArtifactRef, type ArtifactScope, type ArtifactStore, type PutArtifactInput, type SweptArtifact } from './types.js';
22
+ /** A tool's `put` — everything the caller owns EXCEPT `origin`, which the
23
+ * framework stamps from the run's own facts (never invented, never spoofed). */
24
+ export type ToolArtifactPutInput = Omit<PutArtifactInput, 'origin'>;
25
+ /**
26
+ * The capability on `ctx.artifacts` — the store's five verbs with the scope
27
+ * already answered.
28
+ */
29
+ export interface ToolArtifacts {
30
+ /** Store a payload under this run's scope; returns the claim ticket. */
31
+ put(input: ToolArtifactPutInput): Promise<ArtifactMeta>;
32
+ /** The ticket without the payload. `null` for missing-or-expired. */
33
+ head(ref: ArtifactRef): Promise<ArtifactMeta | null>;
34
+ /** Ticket + payload. `null` for missing-or-expired; a digest mismatch throws. */
35
+ get(ref: ArtifactRef): Promise<ArtifactRecord | null>;
36
+ /** Remove one artifact this scope holds. */
37
+ delete(ref: ArtifactRef): Promise<void>;
38
+ /** Page through this scope's tickets, newest first. */
39
+ list(options?: ArtifactListOptions): Promise<ArtifactListResult>;
40
+ }
41
+ /** Which door a refusal happened at — the five verbs, plus `'dispatch'`:
42
+ * the framework's own resolution of a tool's declared `wants` (and the
43
+ * `present` tool's argument checks) BEFORE execute. Not a sixth store verb
44
+ * — a dispatch refusal is the tool-calls stage declining to run a tool
45
+ * whose declared data could not be delivered. */
46
+ export type ArtifactOp = 'put' | 'head' | 'get' | 'delete' | 'list' | 'dispatch';
47
+ /** Why a verb refused (or answered "no data" on the record). */
48
+ export type ArtifactRefusalReason = 'no-store' | 'missing-or-expired' | 'unknown-parent' | 'digest-mismatch' | 'invalid-input'
49
+ /** A `wants` ref resolved, but to the wrong kind — the wrong parcel for
50
+ * this ticket window (dispatch resolution only). */
51
+ | 'kind-mismatch';
52
+ /** One thing that happened at this door — meta only, never payloads. */
53
+ export type ArtifactEventFact = {
54
+ readonly type: 'minted';
55
+ readonly meta: ArtifactMeta;
56
+ } | {
57
+ readonly type: 'resolved';
58
+ readonly ref: ArtifactRef;
59
+ readonly via: 'head' | 'get';
60
+ readonly kind: string;
61
+ readonly bytes: number;
62
+ } | {
63
+ readonly type: 'expired';
64
+ readonly swept: SweptArtifact;
65
+ } | {
66
+ readonly type: 'refused';
67
+ readonly op: ArtifactOp;
68
+ readonly reason: ArtifactRefusalReason;
69
+ readonly ref?: ArtifactRef;
70
+ readonly detail?: string;
71
+ };
72
+ /** Where facts go. The dispatch layer adapts this onto the typed events. */
73
+ export type ArtifactEventSink = (fact: ArtifactEventFact) => void;
74
+ /** What `bindArtifacts` needs beyond the store and the scope. */
75
+ export interface BindArtifactsOptions {
76
+ /** Stamped onto every mint — the run's own facts, absent when unknown. */
77
+ readonly origin?: ArtifactOrigin;
78
+ /** Fact sink. Absent = silent binding (raw store semantics, no record). */
79
+ readonly onEvent?: ArtifactEventSink;
80
+ }
81
+ /**
82
+ * Bind a store to one run's scope — the framework's move, made where the
83
+ * scope is known and a tool cannot reach.
84
+ */
85
+ export declare function bindArtifacts(store: ArtifactStore, scope: ArtifactScope, options?: BindArtifactsOptions): ToolArtifacts;
86
+ /**
87
+ * The fail-closed capability used when NO store is attached. Every verb
88
+ * throws the same teaching refusal — loud, named, and on the record — so
89
+ * `ctx.artifacts` is never `undefined` and a missing store can never read as
90
+ * an empty one. Branch on `ctx.hasArtifacts` for an intentional no-store
91
+ * mode. (The `unconfiguredCredentialProvider` law, verb for verb.)
92
+ */
93
+ export declare function unconfiguredArtifacts(onEvent?: ArtifactEventSink): ToolArtifacts;
@@ -0,0 +1,126 @@
1
+ /**
2
+ * artifacts/capability — `ctx.artifacts`, the scope-bound door a tool gets.
3
+ *
4
+ * Shaped exactly like `ctx.credentials`:
5
+ * • ALWAYS present — with no store attached every method is a teaching
6
+ * refusal naming how to attach one, so a tool can never silently
7
+ * optional-chain past a store that is not there;
8
+ * • fail-closed — the refusal throws; `ctx.hasArtifacts` is the fact to
9
+ * branch on for an intentional degraded mode;
10
+ * • scope composed by the FRAMEWORK from the run's identity/session — the
11
+ * capability closes over it, so a tool cannot name, widen or replace the
12
+ * scope it resolves under. The five verbs here take no scope argument on
13
+ * purpose: that argument was already answered by whoever built the
14
+ * context.
15
+ *
16
+ * Every hop lands on the record AS IT HAPPENS: this module reports facts to a
17
+ * neutral sink (a plain callback), and the tool-dispatch layer adapts that
18
+ * sink onto the typed event channel. Neutral so this folder never imports the
19
+ * event system or the agent — core wires artifacts, never the reverse.
20
+ */
21
+ import { ArtifactIntegrityError, InvalidArtifactError, UnknownParentRefError, } from './types.js';
22
+ /**
23
+ * Bind a store to one run's scope — the framework's move, made where the
24
+ * scope is known and a tool cannot reach.
25
+ */
26
+ export function bindArtifacts(store, scope, options = {}) {
27
+ const { origin, onEvent } = options;
28
+ const report = (fact) => {
29
+ onEvent?.(fact);
30
+ };
31
+ return {
32
+ async put(input) {
33
+ try {
34
+ // `origin` is the framework's field: whatever a caller managed to put
35
+ // there is discarded in favor of the run's own facts.
36
+ const result = await store.put(scope, {
37
+ ...input,
38
+ ...(origin !== undefined ? { origin } : {}),
39
+ });
40
+ for (const swept of result.swept)
41
+ report({ type: 'expired', swept });
42
+ report({ type: 'minted', meta: result.meta });
43
+ return result.meta;
44
+ }
45
+ catch (err) {
46
+ if (err instanceof UnknownParentRefError) {
47
+ report({ type: 'refused', op: 'put', reason: 'unknown-parent', detail: err.message });
48
+ }
49
+ else if (err instanceof InvalidArtifactError) {
50
+ report({ type: 'refused', op: 'put', reason: 'invalid-input', detail: err.message });
51
+ }
52
+ throw err;
53
+ }
54
+ },
55
+ async head(ref) {
56
+ const meta = await store.head(scope, ref);
57
+ if (meta === null) {
58
+ report({ type: 'refused', op: 'head', reason: 'missing-or-expired', ref });
59
+ return null;
60
+ }
61
+ report({ type: 'resolved', ref: meta.ref, via: 'head', kind: meta.kind, bytes: meta.bytes });
62
+ return meta;
63
+ },
64
+ async get(ref) {
65
+ let record;
66
+ try {
67
+ record = await store.get(scope, ref);
68
+ }
69
+ catch (err) {
70
+ if (err instanceof ArtifactIntegrityError) {
71
+ report({
72
+ type: 'refused',
73
+ op: 'get',
74
+ reason: 'digest-mismatch',
75
+ ref,
76
+ detail: err.message,
77
+ });
78
+ }
79
+ throw err;
80
+ }
81
+ if (record === null) {
82
+ report({ type: 'refused', op: 'get', reason: 'missing-or-expired', ref });
83
+ return null;
84
+ }
85
+ report({
86
+ type: 'resolved',
87
+ ref: record.meta.ref,
88
+ via: 'get',
89
+ kind: record.meta.kind,
90
+ bytes: record.meta.bytes,
91
+ });
92
+ return record;
93
+ },
94
+ delete(ref) {
95
+ return store.delete(scope, ref);
96
+ },
97
+ list(options) {
98
+ return store.list(scope, options);
99
+ },
100
+ };
101
+ }
102
+ /**
103
+ * The fail-closed capability used when NO store is attached. Every verb
104
+ * throws the same teaching refusal — loud, named, and on the record — so
105
+ * `ctx.artifacts` is never `undefined` and a missing store can never read as
106
+ * an empty one. Branch on `ctx.hasArtifacts` for an intentional no-store
107
+ * mode. (The `unconfiguredCredentialProvider` law, verb for verb.)
108
+ */
109
+ export function unconfiguredArtifacts(onEvent) {
110
+ const refuse = (op, ref) => {
111
+ onEvent?.({ type: 'refused', op, reason: 'no-store', ...(ref !== undefined && { ref }) });
112
+ return Promise.reject(new Error(`No artifact store is attached, but this tool called ctx.artifacts.${op}(...). ` +
113
+ `Pass \`artifacts\` to Agent.create({ ..., artifacts }) — inMemoryArtifacts() for ` +
114
+ `an in-process store, fileArtifacts({ directory }) or sqliteArtifacts({ file }) for ` +
115
+ `one that survives a restart. A tool that intentionally supports running without a ` +
116
+ `store should branch on \`ctx.hasArtifacts\` instead of catching this.`));
117
+ };
118
+ return {
119
+ put: () => refuse('put'),
120
+ head: (ref) => refuse('head', ref),
121
+ get: (ref) => refuse('get', ref),
122
+ delete: (ref) => refuse('delete', ref),
123
+ list: () => refuse('list'),
124
+ };
125
+ }
126
+ //# sourceMappingURL=capability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capability.js","sourceRoot":"","sources":["../../../src/artifacts/capability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * artifacts/fileArtifacts — the claim-check store in a directory.
3
+ *
4
+ * One machine, one directory, nothing to install: each artifact is one JSON
5
+ * envelope at `<dir>/<tenant>/<principal>/<conversation>/<ref>.json`, so an
6
+ * incident can be inspected with `ls` and `cat` — a store you cannot read
7
+ * with the tools already on the box is a store you debug by guessing.
8
+ *
9
+ * ── Scope-partitioned paths, structurally traversal-proof ──────────────────
10
+ * The path is built from two kinds of segment and both are closed:
11
+ * • the ref — MINTED (`art_` + base62), and `isArtifactRef` is asserted
12
+ * before any ref touches a path anyway, because "cannot happen" is a
13
+ * claim, not a defence;
14
+ * • the scope tuple — caller strings, so each segment is percent-encoded
15
+ * before it becomes a directory name: `..`, `/` and `\` arrive as data
16
+ * and land as literals, never as navigation.
17
+ *
18
+ * ── What this adapter does NOT know ────────────────────────────────────────
19
+ * A directory cannot cheaply know which artifact was READ last, so budget
20
+ * evictions here are oldest-first (by mint time) rather than the in-memory
21
+ * adapter's least-recently-used — stated here so nobody discovers it as a
22
+ * surprise under pressure. TTL expiry behaves identically everywhere.
23
+ *
24
+ * Node-only (`node:fs` via lazy require, the sqliteSessions law) — importing
25
+ * the barrel costs a browser bundle nothing; constructing one where there is
26
+ * no filesystem refuses by name.
27
+ */
28
+ import { type ArtifactRetention } from './retention.js';
29
+ import { type ArtifactStore } from './types.js';
30
+ /** Options for {@link fileArtifacts}. */
31
+ export interface FileArtifactsOptions {
32
+ /** The root directory. Created if missing, parents included. */
33
+ readonly directory: string;
34
+ /** Retention dials — all optional here: disk is a budget the operator
35
+ * already owns. TTL is stamped at mint; budgets sweep oldest-first. */
36
+ readonly retention?: ArtifactRetention;
37
+ /** @internal Test seam — the clock. Defaults to `Date.now`. */
38
+ readonly _now?: () => number;
39
+ }
40
+ /**
41
+ * Raised when an artifact file EXISTS but this runtime cannot read it — a
42
+ * different fact from "no artifact", and only one of them is safe to answer
43
+ * with `null`. (The sqliteSessions law, per file.)
44
+ */
45
+ export declare class UnreadableArtifactFileError extends Error {
46
+ readonly code: "ERR_UNREADABLE_ARTIFACT_FILE";
47
+ readonly file: string;
48
+ constructor(file: string, detail: string);
49
+ }
50
+ /**
51
+ * A directory-backed artifact store — durable across restarts, legible to a
52
+ * human, one file per artifact.
53
+ *
54
+ * @example
55
+ * const store = fileArtifacts({ directory: './artifacts' });
56
+ * const agent = Agent.create({ provider, artifacts: store });
57
+ */
58
+ export declare function fileArtifacts(options: FileArtifactsOptions): ArtifactStore;
@@ -0,0 +1,225 @@
1
+ /**
2
+ * artifacts/fileArtifacts — the claim-check store in a directory.
3
+ *
4
+ * One machine, one directory, nothing to install: each artifact is one JSON
5
+ * envelope at `<dir>/<tenant>/<principal>/<conversation>/<ref>.json`, so an
6
+ * incident can be inspected with `ls` and `cat` — a store you cannot read
7
+ * with the tools already on the box is a store you debug by guessing.
8
+ *
9
+ * ── Scope-partitioned paths, structurally traversal-proof ──────────────────
10
+ * The path is built from two kinds of segment and both are closed:
11
+ * • the ref — MINTED (`art_` + base62), and `isArtifactRef` is asserted
12
+ * before any ref touches a path anyway, because "cannot happen" is a
13
+ * claim, not a defence;
14
+ * • the scope tuple — caller strings, so each segment is percent-encoded
15
+ * before it becomes a directory name: `..`, `/` and `\` arrive as data
16
+ * and land as literals, never as navigation.
17
+ *
18
+ * ── What this adapter does NOT know ────────────────────────────────────────
19
+ * A directory cannot cheaply know which artifact was READ last, so budget
20
+ * evictions here are oldest-first (by mint time) rather than the in-memory
21
+ * adapter's least-recently-used — stated here so nobody discovers it as a
22
+ * surprise under pressure. TTL expiry behaves identically everywhere.
23
+ *
24
+ * Node-only (`node:fs` via lazy require, the sqliteSessions law) — importing
25
+ * the barrel costs a browser bundle nothing; constructing one where there is
26
+ * no filesystem refuses by name.
27
+ */
28
+ import { lazyRequire } from '../lib/lazyRequire.js';
29
+ import { prepareArtifact } from './minting.js';
30
+ import { isArtifactRef } from './naming.js';
31
+ import { computeArtifactDigest, decodeArtifactData, encodeArtifactData, } from './payload.js';
32
+ import { assertRetention, planRetention, } from './retention.js';
33
+ import { ArtifactIntegrityError, InvalidArtifactError, } from './types.js';
34
+ /** What one artifact file holds. `format` is bumped only for a change an
35
+ * older reader could not survive; a newer number is refused, never half-read. */
36
+ const FILE_FORMAT = 1;
37
+ /**
38
+ * Raised when an artifact file EXISTS but this runtime cannot read it — a
39
+ * different fact from "no artifact", and only one of them is safe to answer
40
+ * with `null`. (The sqliteSessions law, per file.)
41
+ */
42
+ export class UnreadableArtifactFileError extends Error {
43
+ code = 'ERR_UNREADABLE_ARTIFACT_FILE';
44
+ file;
45
+ constructor(file, detail) {
46
+ super(`[artifacts] the artifact file at '${file}' cannot be read: ${detail} ` +
47
+ `An unreadable artifact and a missing one are different facts — this refuses rather ` +
48
+ `than reporting "no data" over bytes that exist. Move the file aside to release the ref.`);
49
+ this.name = 'UnreadableArtifactFileError';
50
+ this.file = file;
51
+ }
52
+ }
53
+ /**
54
+ * A directory-backed artifact store — durable across restarts, legible to a
55
+ * human, one file per artifact.
56
+ *
57
+ * @example
58
+ * const store = fileArtifacts({ directory: './artifacts' });
59
+ * const agent = Agent.create({ provider, artifacts: store });
60
+ */
61
+ export function fileArtifacts(options) {
62
+ const { directory, retention } = options;
63
+ if (typeof directory !== 'string' || directory.trim() === '') {
64
+ throw new TypeError(`[artifacts] fileArtifacts({ directory: ${JSON.stringify(directory)} }) names no ` +
65
+ `directory. Give it a path — it will be created if it does not exist.`);
66
+ }
67
+ assertRetention('fileArtifacts', retention);
68
+ const now = options._now ?? Date.now;
69
+ const fs = lazyRequire('node:fs');
70
+ const path = lazyRequire('node:path');
71
+ fs.mkdirSync(directory, { recursive: true });
72
+ /**
73
+ * One RAW tuple field → one directory name. Encoded from the FIELD, never
74
+ * from the joined namespace (a tenant containing '/' must not become two
75
+ * path segments), and with dots encoded too — `encodeURIComponent` leaves
76
+ * `.` alone, so a tenant of literally `'..'` would otherwise survive as a
77
+ * real parent-directory hop. After this, `..`, `/` and `\` are inert
78
+ * directory NAMES (`%2E%2E`, `%2F`, `%5C`). Empty fields collapse to `_`,
79
+ * mirroring `identityNamespace`'s stable layout.
80
+ */
81
+ const segment = (raw) => encodeURIComponent(raw === undefined || raw === '' ? '_' : raw).replace(/\./g, '%2E');
82
+ const scopeDir = (scope) => path.join(directory, segment(scope.tenant), segment(scope.principal), segment(scope.conversationId));
83
+ const fileFor = (scope, ref) => path.join(scopeDir(scope), `${ref}.json`);
84
+ const readEnvelope = (file) => {
85
+ let raw;
86
+ try {
87
+ raw = fs.readFileSync(file, 'utf8');
88
+ }
89
+ catch {
90
+ return undefined; // never written (or already swept) — the null case.
91
+ }
92
+ let parsed;
93
+ try {
94
+ parsed = JSON.parse(raw);
95
+ }
96
+ catch {
97
+ throw new UnreadableArtifactFileError(file, 'it is not JSON.');
98
+ }
99
+ const candidate = parsed;
100
+ if (candidate === null ||
101
+ typeof candidate !== 'object' ||
102
+ typeof candidate.format !== 'number' ||
103
+ candidate.meta === undefined ||
104
+ candidate.payload === undefined) {
105
+ throw new UnreadableArtifactFileError(file, 'it is not an artifact envelope.');
106
+ }
107
+ if (candidate.format > FILE_FORMAT) {
108
+ throw new UnreadableArtifactFileError(file, `it was written with format ${candidate.format} and this runtime reads format ` +
109
+ `${FILE_FORMAT}; roll agentfootprint forward rather than half-read it.`);
110
+ }
111
+ return candidate;
112
+ };
113
+ /** Read a LIVE envelope; sweep the file when the calendar says it is gone. */
114
+ const liveEnvelope = (scope, ref) => {
115
+ if (!isArtifactRef(ref))
116
+ return undefined;
117
+ const file = fileFor(scope, ref);
118
+ const envelope = readEnvelope(file);
119
+ if (envelope === undefined)
120
+ return undefined;
121
+ if (envelope.meta.expiresAt !== undefined && envelope.meta.expiresAt <= now()) {
122
+ fs.rmSync(file, { force: true });
123
+ return undefined;
124
+ }
125
+ return envelope;
126
+ };
127
+ /** Every live meta in a scope (expired files swept as they are found). */
128
+ const scopeMetas = (scope) => {
129
+ const dir = scopeDir(scope);
130
+ let names;
131
+ try {
132
+ names = fs.readdirSync(dir);
133
+ }
134
+ catch {
135
+ return []; // scope never wrote anything.
136
+ }
137
+ const at = now();
138
+ const metas = [];
139
+ for (const name of names) {
140
+ if (!name.endsWith('.json'))
141
+ continue;
142
+ const ref = name.slice(0, -'.json'.length);
143
+ if (!isArtifactRef(ref))
144
+ continue; // not ours; leave foreign files alone.
145
+ const envelope = readEnvelope(path.join(dir, name));
146
+ if (envelope === undefined)
147
+ continue;
148
+ if (envelope.meta.expiresAt !== undefined && envelope.meta.expiresAt <= at) {
149
+ fs.rmSync(path.join(dir, name), { force: true });
150
+ continue;
151
+ }
152
+ metas.push(envelope.meta);
153
+ }
154
+ return metas;
155
+ };
156
+ return {
157
+ async put(scope, input) {
158
+ const at = now();
159
+ const { meta } = await prepareArtifact(input, (parent) => liveEnvelope(scope, parent) !== undefined, retention, at);
160
+ const rows = scopeMetas(scope).map((held) => ({
161
+ ref: held.ref,
162
+ kind: held.kind,
163
+ bytes: held.bytes,
164
+ ...(held.expiresAt !== undefined && { expiresAt: held.expiresAt }),
165
+ // A directory has no cheap read-recency; oldest-first is the stated law.
166
+ lastAccessedAt: held.createdAt,
167
+ }));
168
+ const plan = planRetention(rows, meta.bytes, retention, at);
169
+ if (plan.refusal !== undefined)
170
+ throw new InvalidArtifactError(plan.refusal);
171
+ for (const swept of plan.swept)
172
+ fs.rmSync(fileFor(scope, swept.ref), { force: true });
173
+ const envelope = {
174
+ format: FILE_FORMAT,
175
+ meta,
176
+ payload: encodeArtifactData(input.data),
177
+ };
178
+ fs.mkdirSync(scopeDir(scope), { recursive: true });
179
+ fs.writeFileSync(fileFor(scope, meta.ref), JSON.stringify(envelope));
180
+ return { meta, swept: plan.swept };
181
+ },
182
+ // eslint-disable-next-line @typescript-eslint/require-await
183
+ async head(scope, ref) {
184
+ return liveEnvelope(scope, ref)?.meta ?? null;
185
+ },
186
+ async get(scope, ref) {
187
+ const envelope = liveEnvelope(scope, ref);
188
+ if (envelope === undefined)
189
+ return null;
190
+ const data = decodeArtifactData(envelope.payload);
191
+ if (envelope.meta.digest !== undefined) {
192
+ const actual = await computeArtifactDigest(data);
193
+ if (actual !== envelope.meta.digest) {
194
+ throw new ArtifactIntegrityError(envelope.meta.ref, envelope.meta.digest, actual);
195
+ }
196
+ }
197
+ return { meta: envelope.meta, data };
198
+ },
199
+ // eslint-disable-next-line @typescript-eslint/require-await
200
+ async delete(scope, ref) {
201
+ if (!isArtifactRef(ref))
202
+ return;
203
+ fs.rmSync(fileFor(scope, ref), { force: true });
204
+ },
205
+ // eslint-disable-next-line @typescript-eslint/require-await
206
+ async list(scope, listOptions) {
207
+ const all = scopeMetas(scope).sort((a, b) => b.createdAt - a.createdAt || (a.ref < b.ref ? -1 : 1));
208
+ const offset = decodeCursor(listOptions?.cursor);
209
+ const limit = Math.max(1, Math.floor(listOptions?.limit ?? 50));
210
+ const page = all.slice(offset, offset + limit);
211
+ const nextOffset = offset + page.length;
212
+ return {
213
+ artifacts: page,
214
+ ...(nextOffset < all.length && { cursor: String(nextOffset) }),
215
+ };
216
+ },
217
+ };
218
+ }
219
+ function decodeCursor(cursor) {
220
+ if (cursor === undefined)
221
+ return 0;
222
+ const parsed = Number(cursor);
223
+ return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : 0;
224
+ }
225
+ //# sourceMappingURL=fileArtifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileArtifacts.js","sourceRoot":"","sources":["../../../src/artifacts/fileArtifacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * artifacts/inMemoryArtifacts — the claim-check store in a Map.
3
+ *
4
+ * For tests, local development, and single-process agents whose artifacts may
5
+ * die with the process. Exactly as durable as the process — which is the
6
+ * point of the port: swap the one argument for `fileArtifacts` or
7
+ * `sqliteArtifacts` and nothing else changes.
8
+ *
9
+ * ── Bounded, and counting its drops (the innerRunRecords laws) ─────────────
10
+ * A retained payload is retained memory, and an agent minting a dataset per
11
+ * turn for a week would otherwise pin every one of them — the failure would
12
+ * look like a leak rather than like a feature. So this adapter is ALWAYS
13
+ * bounded: it has a default byte budget and row budget per scope, an explicit
14
+ * retention only replaces those dials, and there is deliberately no spelling
15
+ * for "unbounded" here — a memory store without a ceiling is a leak wearing
16
+ * configuration. When the budget forces an eviction the least-recently-USED
17
+ * artifact leaves first (reading refreshes recency, so the dataset a chart is
18
+ * actively rendered from is not the next casualty), every eviction is
19
+ * reported by the `put` that caused it, and `dropped` COUNTS them — "we kept
20
+ * the last 200 of 340" is an answer a debugging session can act on; a
21
+ * silently missing ref is not.
22
+ */
23
+ import { type ArtifactRetention } from './retention.js';
24
+ import { type ArtifactStore } from './types.js';
25
+ /** The always-on bounds. Override dials via `retention`; there is no "off". */
26
+ export declare const DEFAULT_IN_MEMORY_ARTIFACT_RETENTION: Required<Pick<ArtifactRetention, 'maxBytesPerScope' | 'maxCountPerScope'>>;
27
+ /** Options for {@link inMemoryArtifacts}. */
28
+ export interface InMemoryArtifactsOptions {
29
+ /**
30
+ * Retention dials. Merged OVER the defaults — name a dial to change it;
31
+ * the byte and row budgets always exist (see the header for why).
32
+ */
33
+ readonly retention?: ArtifactRetention;
34
+ /** @internal Test seam — the clock. Defaults to `Date.now`. */
35
+ readonly _now?: () => number;
36
+ }
37
+ /** The in-memory store, plus the accounting a bounded store owes its owner. */
38
+ export interface InMemoryArtifacts extends ArtifactStore {
39
+ /** Artifacts evicted by the byte/row budgets since construction (TTL expiry
40
+ * is the calendar doing its job and is not counted here). Non-zero means
41
+ * "resolve sooner, or raise the budget". */
42
+ readonly dropped: number;
43
+ /** The dials in force, defaults included. */
44
+ readonly retention: ArtifactRetention;
45
+ }
46
+ /**
47
+ * A bounded, drop-counting, per-scope-isolated artifact store in process
48
+ * memory.
49
+ *
50
+ * @example
51
+ * const store = inMemoryArtifacts({ retention: { ttlMs: 15 * 60_000 } });
52
+ * const agent = Agent.create({ provider, artifacts: store });
53
+ */
54
+ export declare function inMemoryArtifacts(options?: InMemoryArtifactsOptions): InMemoryArtifacts;