@tangle-network/agent-runtime 0.338.0 → 0.340.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 (144) hide show
  1. package/dist/{activation-kbkAuSmY.js → activation-D2PVljaw.js} +5 -18
  2. package/dist/{activation-kbkAuSmY.js.map → activation-D2PVljaw.js.map} +1 -1
  3. package/dist/{activation-CsbNax2X.d.ts → activation-DGDl4wwI.d.ts} +4 -24
  4. package/dist/agent.d.ts +4 -18
  5. package/dist/agent.js +3 -21
  6. package/dist/agent.js.map +1 -1
  7. package/dist/analyst-loop.d.ts +2 -2
  8. package/dist/{bundle-DM60AI2B.js → bundle-DNUq-OPW.js} +2 -2
  9. package/dist/{bundle-DM60AI2B.js.map → bundle-DNUq-OPW.js.map} +1 -1
  10. package/dist/candidate-execution/index.d.ts +4 -101
  11. package/dist/candidate-execution/index.js +10 -395
  12. package/dist/candidate-execution/index.js.map +1 -1
  13. package/dist/{delegate-Se1YZKMb.js → delegate-CtJIS-tp.js} +2 -2
  14. package/dist/{delegate-Se1YZKMb.js.map → delegate-CtJIS-tp.js.map} +1 -1
  15. package/dist/{driver-control-acknowledgers-T2a1Ouay.js → driver-control-acknowledgers-MTrs8HAF.js} +15 -11
  16. package/dist/driver-control-acknowledgers-MTrs8HAF.js.map +1 -0
  17. package/dist/{durable-file-B_eJr6Mb.js → durable-file-gNI9ILAn.js} +1 -3
  18. package/dist/durable-file-gNI9ILAn.js.map +1 -0
  19. package/dist/durable.d.ts +3 -35
  20. package/dist/durable.js +10 -10
  21. package/dist/durable.js.map +1 -1
  22. package/dist/{graph-CY0wH838.js → graph-DfWqp_1e.js} +4 -4
  23. package/dist/graph-DfWqp_1e.js.map +1 -0
  24. package/dist/{graph-registry-By0tUj4S.js → graph-registry-BnO64cn8.js} +3 -3
  25. package/dist/{graph-registry-By0tUj4S.js.map → graph-registry-BnO64cn8.js.map} +1 -1
  26. package/dist/{improve-CWGBT13K.js → improve-CKRVQqzt.js} +8 -35
  27. package/dist/improve-CKRVQqzt.js.map +1 -0
  28. package/dist/{improvement-adapter-D5gwwoXQ.d.ts → improvement-adapter-sIthWkcN.d.ts} +3 -21
  29. package/dist/index.d.ts +10 -215
  30. package/dist/index.js +91 -302
  31. package/dist/index.js.map +1 -1
  32. package/dist/intelligence.d.ts +11 -143
  33. package/dist/intelligence.js +7 -81
  34. package/dist/intelligence.js.map +1 -1
  35. package/dist/{jsonl-file-DBv31uPi.js → jsonl-file-C9Kde_0Z.js} +2 -2
  36. package/dist/{jsonl-file-DBv31uPi.js.map → jsonl-file-C9Kde_0Z.js.map} +1 -1
  37. package/dist/kernel.d.ts +4 -3
  38. package/dist/kernel.js +12 -14
  39. package/dist/loop-runner-C4EWEcXf.d.ts +32 -0
  40. package/dist/loop-runner-DNWbTcVm.js +59 -0
  41. package/dist/loop-runner-DNWbTcVm.js.map +1 -0
  42. package/dist/loop-runner-bin.d.ts +32 -2
  43. package/dist/loop-runner-bin.js +93 -1
  44. package/dist/loop-runner-bin.js.map +1 -0
  45. package/dist/mcp/bin.js +3 -3
  46. package/dist/mcp/index.d.ts +99 -418
  47. package/dist/mcp/index.js +121 -203
  48. package/dist/mcp/index.js.map +1 -1
  49. package/dist/mcp/memory-bin.js +231 -1
  50. package/dist/mcp/memory-bin.js.map +1 -1
  51. package/dist/model-policy-CyCUwHed.js.map +1 -1
  52. package/dist/placement.d.ts +2 -33
  53. package/dist/placement.js +1 -35
  54. package/dist/placement.js.map +1 -1
  55. package/dist/platform.d.ts +188 -1
  56. package/dist/platform.js +129 -1
  57. package/dist/platform.js.map +1 -1
  58. package/dist/{prepare-Bt0IouPq.js → prepare-FzJoS68l.js} +8 -160
  59. package/dist/prepare-FzJoS68l.js.map +1 -0
  60. package/dist/{profile-Do-5xO_D.js → profile-DToH0XEs.js} +2 -2
  61. package/dist/profile-DToH0XEs.js.map +1 -0
  62. package/dist/profile-materialization-bPm0gGLO.d.ts +49 -0
  63. package/dist/profiles.d.ts +2 -2
  64. package/dist/profiles.js +3 -40
  65. package/dist/profiles.js.map +1 -1
  66. package/dist/{protected-model-port-DGxQ8_YM.d.ts → protected-model-port-DVVh-hEk.d.ts} +3 -33
  67. package/dist/protected-redaction-DFCeo4vg.js.map +1 -1
  68. package/dist/{provision-supervisor-0jMufp4h.js → provision-supervisor-DqvWXmAE.js} +6 -6
  69. package/dist/{provision-supervisor-0jMufp4h.js.map → provision-supervisor-DqvWXmAE.js.map} +1 -1
  70. package/dist/{run-cancellation-BoW5Sg9Y.js → run-cancellation-C9oL62sW.js} +3 -7
  71. package/dist/{run-cancellation-BoW5Sg9Y.js.map → run-cancellation-C9oL62sW.js.map} +1 -1
  72. package/dist/{runtime-D37zRSs7.js → runtime-C55Zgo1R.js} +2531 -2889
  73. package/dist/runtime-C55Zgo1R.js.map +1 -0
  74. package/dist/{runtime-hooks-Bj6wJHlH.d.ts → runtime-hooks-nsqxSUFL.d.ts} +2 -6
  75. package/dist/{sandbox-profile-compat-xSoVtdWw.js → sandbox-profile-compat-DRr3JwDx.js} +2 -4
  76. package/dist/sandbox-profile-compat-DRr3JwDx.js.map +1 -0
  77. package/dist/{search-executor-DmgUm5p7.js → search-executor-ChOlRBgg.js} +3 -3
  78. package/dist/search-executor-ChOlRBgg.js.map +1 -0
  79. package/dist/{server-DQHJszfk.js → server-DkVBSN_S.js} +362 -67
  80. package/dist/server-DkVBSN_S.js.map +1 -0
  81. package/dist/{structural-rollout-DAvIE8mw.js → structural-rollout-C1LEk_zq.js} +80 -80
  82. package/dist/structural-rollout-C1LEk_zq.js.map +1 -0
  83. package/dist/{substrate-B0TYNrXn.js → substrate-CGDFTSRh.js} +2 -9
  84. package/dist/substrate-CGDFTSRh.js.map +1 -0
  85. package/dist/{supervise-WuPAwfPh.js → supervise-CaUAxZZP.js} +92 -75
  86. package/dist/supervise-CaUAxZZP.js.map +1 -0
  87. package/dist/{supervisor-CPG1I9UN.js → supervisor-VXuN2OHT.js} +205 -319
  88. package/dist/supervisor-VXuN2OHT.js.map +1 -0
  89. package/dist/testing.d.ts +2 -2
  90. package/dist/testing.js +13 -13
  91. package/dist/testing.js.map +1 -1
  92. package/dist/tool-loop.d.ts +1 -1
  93. package/dist/{tool-server-Dqer2M4_.js → tool-server-XV4aJwoQ.js} +2 -2
  94. package/dist/tool-server-XV4aJwoQ.js.map +1 -0
  95. package/dist/top-snapshot-CbZE1JsU.js +502 -0
  96. package/dist/top-snapshot-CbZE1JsU.js.map +1 -0
  97. package/dist/tui/bin.js +711 -1
  98. package/dist/tui/bin.js.map +1 -1
  99. package/dist/tui/index.d.ts +2 -70
  100. package/dist/tui/index.js +3 -3
  101. package/dist/{types-zWfqDjeL.d.ts → types-Cwrea-bU.d.ts} +2 -17
  102. package/dist/{types-CrNWif8-.d.ts → types-DZ6L0Bv3.d.ts} +765 -2152
  103. package/dist/workspace-store/index.d.ts +1 -107
  104. package/dist/workspace-store/index.js +1 -415
  105. package/dist/workspace-store/index.js.map +1 -1
  106. package/dist/{workspace-streams-BZZds1Fw.d.ts → workspace-streams-BiS4ABah.d.ts} +3 -18
  107. package/package.json +1 -1
  108. package/skills/agent-graphs/references/authoring.md +3 -2
  109. package/dist/coder-yhVWbdWc.js +0 -40
  110. package/dist/coder-yhVWbdWc.js.map +0 -1
  111. package/dist/delegation-status-CF4D0NZ_.js +0 -358
  112. package/dist/delegation-status-CF4D0NZ_.js.map +0 -1
  113. package/dist/driver-control-acknowledgers-T2a1Ouay.js.map +0 -1
  114. package/dist/durable-file-B_eJr6Mb.js.map +0 -1
  115. package/dist/graph-CY0wH838.js.map +0 -1
  116. package/dist/improve-CWGBT13K.js.map +0 -1
  117. package/dist/integrations-6xttbPi9.d.ts +0 -190
  118. package/dist/integrations-dFi-ALk7.js +0 -132
  119. package/dist/integrations-dFi-ALk7.js.map +0 -1
  120. package/dist/kb-gate-C8z2juK8.d.ts +0 -80
  121. package/dist/kb-gate-DpaSwXVx.js +0 -80
  122. package/dist/kb-gate-DpaSwXVx.js.map +0 -1
  123. package/dist/loop-runner-bin-CFnrAHpl.d.ts +0 -164
  124. package/dist/loop-runner-bin-CdPlhy9g.js +0 -246
  125. package/dist/loop-runner-bin-CdPlhy9g.js.map +0 -1
  126. package/dist/memory-server-DXQ8IxGR.js +0 -234
  127. package/dist/memory-server-DXQ8IxGR.js.map +0 -1
  128. package/dist/openai-tools-DoQ32vpe.js +0 -44
  129. package/dist/openai-tools-DoQ32vpe.js.map +0 -1
  130. package/dist/openai-tools-zh2I_uD7.d.ts +0 -24
  131. package/dist/prepare-Bt0IouPq.js.map +0 -1
  132. package/dist/profile-Do-5xO_D.js.map +0 -1
  133. package/dist/profile-materialization-BnoEf1co.d.ts +0 -96
  134. package/dist/runtime-D37zRSs7.js.map +0 -1
  135. package/dist/sandbox-profile-compat-xSoVtdWw.js.map +0 -1
  136. package/dist/search-executor-DmgUm5p7.js.map +0 -1
  137. package/dist/server-DQHJszfk.js.map +0 -1
  138. package/dist/structural-rollout-DAvIE8mw.js.map +0 -1
  139. package/dist/substrate-B0TYNrXn.js.map +0 -1
  140. package/dist/supervise-WuPAwfPh.js.map +0 -1
  141. package/dist/supervisor-CPG1I9UN.js.map +0 -1
  142. package/dist/tool-server-Dqer2M4_.js.map +0 -1
  143. package/dist/top-app-C55Wa7uy.js +0 -1214
  144. package/dist/top-app-C55Wa7uy.js.map +0 -1
@@ -105,14 +105,8 @@ declare class WorkspaceConflictError extends Error {
105
105
  }
106
106
  /** Refuse anything but an absolute, normalized path such as `/files/report.md`. */
107
107
  declare function assertWorkspacePath(path: string): void;
108
- /** The member a path belongs to, or `null` for workspace-scoped paths. */
109
- declare function memberIdFromPath(path: string): string | null;
110
108
  /** Validate a put before any adapter touches storage; adapters call this first. */
111
109
  declare function checkWorkspacePut(input: WorkspacePutInput): void;
112
- /** Refuse an `operationId` that is present but empty, not a string, or over 256 chars. */
113
- declare function checkOperationId(path: string, operationId: unknown): void;
114
- /** Whether `entry` is exactly what `input` would write: same kind, content and bytes. */
115
- declare function isSameWorkspaceWrite(entry: WorkspaceEntry, input: WorkspacePutInput): boolean;
116
110
  /** Process-local adapter for tests, previews, and single-instance hosts. */
117
111
  declare function createInMemoryWorkspaceStore(options?: {
118
112
  now?: () => Date;
@@ -134,41 +128,6 @@ interface WorkspaceContentCodec {
134
128
  seal(plain: Uint8Array, context: WorkspaceCodecContext): Promise<Uint8Array>;
135
129
  open(sealed: Uint8Array, context: WorkspaceCodecContext): Promise<Uint8Array>;
136
130
  }
137
- /** A value did not open: unknown key, wrong tenant or path, tampering, or plaintext where a seal was required. */
138
- declare class WorkspaceCodecError extends Error {
139
- readonly code: "codec";
140
- constructor(message: string);
141
- }
142
- /**
143
- * AES-256-GCM with a key id per value. `keys` maps key id to 32 raw bytes
144
- * (base64 or base64url when a string). The encryption key and the key that
145
- * derives replay-stable IVs are both derived from the raw key with HKDF, so the
146
- * raw key is never used for two algorithms.
147
- *
148
- * Without an `operationId` every seal uses a random 96-bit IV. With one, the IV
149
- * is an HMAC of the tenant, path, operation and plaintext, as in SIV: only an
150
- * identical write repeats it, and that repeat reveals only that the write was
151
- * repeated.
152
- */
153
- declare function createAesGcmContentCodec(options: {
154
- keys: Readonly<Record<string, string | Uint8Array>>;
155
- activeKeyId: string;
156
- }): WorkspaceContentCodec;
157
- /**
158
- * The AES-256-GCM codec from an app's env, or `null` when neither variable is
159
- * set. `WORKSPACE_STORE_KEYS` is `id:base64,id:base64`; `WORKSPACE_STORE_KEY_ID`
160
- * names the key new writes use. Setting one without the other is refused.
161
- */
162
- declare function aesGcmContentCodecFromEnv(env: {
163
- WORKSPACE_STORE_KEYS?: string;
164
- WORKSPACE_STORE_KEY_ID?: string;
165
- }): WorkspaceContentCodec | null;
166
- /** Stored text of a sealed `content`: a prefix, then the sealed bytes in base64. */
167
- declare const SEALED_CONTENT_PREFIX = "wsc1:";
168
- /** Seal bytes a host is about to upload (an R2 object) under the entry's tenant and path. */
169
- declare function sealWorkspaceBytes(codec: WorkspaceContentCodec, context: WorkspaceCodecContext, bytes: Uint8Array): Promise<Uint8Array>;
170
- /** Open bytes a host downloaded for an entry's `bytes` reference. */
171
- declare function openWorkspaceBytes(codec: WorkspaceContentCodec, context: WorkspaceCodecContext, sealed: Uint8Array): Promise<Uint8Array>;
172
131
  interface ContentCodecOptions {
173
132
  /**
174
133
  * Return stored content that is not sealed as is, for a store being moved
@@ -176,13 +135,6 @@ interface ContentCodecOptions {
176
135
  */
177
136
  readonly readPlaintext?: boolean;
178
137
  }
179
- /**
180
- * `store` with every entry's `content` sealed at rest. Index fields, `bytes`
181
- * references and tombstones pass through untouched; the host seals the bytes
182
- * themselves. `idempotentOperations` is the inner store's: a replayed put with
183
- * an `operationId` seals to the same bytes, so the inner replay check holds.
184
- */
185
- declare function withContentCodec(store: WorkspaceStore, codec: WorkspaceContentCodec, options?: ContentCodecOptions): WorkspaceStore;
186
138
  //#endregion
187
139
  //#region src/workspace-store/contract.d.ts
188
140
  interface WorkspaceStoreContractCase {
@@ -242,11 +194,6 @@ interface MemoryPolicy {
242
194
  text: string;
243
195
  }): WorkspacePolicyDecision | Promise<WorkspacePolicyDecision>;
244
196
  }
245
- /** A policy or path rule refused the call. */
246
- declare class WorkspacePolicyError extends Error {
247
- readonly code: "refused";
248
- constructor(message: string);
249
- }
250
197
  /**
251
198
  * Default authority. Reads: workspace memory, the speaker's own member memory,
252
199
  * `/knowledge/**`, `/files/**`. Writes: viewers and guests none; any member may
@@ -273,14 +220,6 @@ declare function readTurnMemories(store: WorkspaceStore, turn: WorkspaceTurn): P
273
220
  declare function createMemoryTools(context: WorkspaceToolContext): WorkspaceToolDefinition[];
274
221
  /** `files.list`, `files.read`, `files.write`, `files.delete`, `files.search` over `/files/**` and `/knowledge/**`. */
275
222
  declare function createFileTools(context: WorkspaceToolContext): WorkspaceToolDefinition[];
276
- /**
277
- * BM25 over entry text (and path words), highest score first, ties by path.
278
- * Entries without inline text match on path words only.
279
- */
280
- declare function rankEntries(entries: readonly WorkspaceEntry[], query: string, limit: number): {
281
- entry: WorkspaceEntry;
282
- score: number;
283
- }[];
284
223
  /**
285
224
  * Render the memories a turn sees as one stable block for the per-turn preamble.
286
225
  * Order: instructions, preferences, facts; workspace before member; then path.
@@ -293,37 +232,12 @@ declare function renderPinnedMemory(entries: readonly WorkspaceEntry[], options?
293
232
  }): string;
294
233
  //#endregion
295
234
  //#region src/workspace-store/harness.d.ts
296
- /** Opening marker for the generated block in a harness's native memory file. */
297
- declare const HARNESS_MEMORY_BEGIN = "<!-- workspace-store:memory begin. Generated from the workspace store; save memories with memory.remember. -->";
298
- /** Closing marker for the generated block in a harness's native memory file. */
299
- declare const HARNESS_MEMORY_END = "<!-- workspace-store:memory end -->";
300
- /** The generated block a host writes into a harness's native memory location. */
301
- declare function renderHarnessMemory(entries: readonly WorkspaceEntry[], options?: {
302
- maxTokens?: number;
303
- }): string;
304
- /** Replace the generated block in `native`, or append one; text outside it is kept byte for byte. */
305
- declare function projectHarnessMemory(native: string, block: string): string;
306
- /** Native files keyed by path, as the host read them. A missing file is absent or `undefined`. */
307
- type HarnessNativeFiles = Readonly<Record<string, string | undefined>>;
308
- /** Lowercase, collapse spaces, drop a leading "Remember:" and trailing punctuation: the duplicate key. */
309
- declare function normalizeMemoryText(text: string): string;
310
- /**
311
- * What the harness added during the turn, outside the generated block: new
312
- * lines in files that existed, and the body of new files (a Claude Code memory
313
- * directory entry). Lines removed or present before are ignored; a removal is
314
- * not a forget, which only `memory.forget` performs.
315
- */
316
- declare function captureHarnessMemory(before: HarnessNativeFiles, after: HarnessNativeFiles): string[];
317
235
  /** Where a captured memory came from. */
318
236
  interface HarnessProvenance {
319
237
  readonly harness: string;
320
238
  readonly turnId: string;
321
239
  readonly memberId: string;
322
240
  }
323
- /** The entry `actor` for a captured memory, so `createdBy` carries its provenance. */
324
- declare function harnessActor({ harness, turnId, memberId }: HarnessProvenance): string;
325
- /** Read the harness, turn, and member provenance encoded by {@link harnessActor}. */
326
- declare function parseHarnessActor(actor: string): HarnessProvenance | null;
327
241
  interface HarnessIngestResult {
328
242
  readonly saved: WorkspaceEntry[];
329
243
  /** Facts already in the store, by normalized text. */
@@ -334,16 +248,6 @@ interface HarnessIngestResult {
334
248
  reason: string;
335
249
  }[];
336
250
  }
337
- /**
338
- * Save captured facts as workspace memories through the same policy as
339
- * `memory.remember`, with the harness and turn as the actor. Duplicates of a
340
- * memory the turn can see, or of an earlier fact in the batch, are skipped.
341
- */
342
- declare function ingestHarnessMemories(context: WorkspaceToolContext, input: {
343
- harness: string;
344
- turnId: string;
345
- facts: readonly string[];
346
- }): Promise<HarnessIngestResult>;
347
251
  interface MemoryDivergence {
348
252
  /** Sum of the counts below; 0 means every native copy agrees with the store. */
349
253
  readonly total: number;
@@ -359,16 +263,6 @@ interface MemoryDivergence {
359
263
  uncaptured: string[];
360
264
  }>;
361
265
  }
362
- /**
363
- * Compare each native file with the store as `turn` sees it, after ingest ran.
364
- * `before` is the files as projected at session start, `after` as they are now:
365
- * only what the harness added since then can be uncaptured, so the profile's own
366
- * generated text in the same file never counts. Files that held a generated
367
- * block at session start are projection targets: losing the block counts every
368
- * visible memory as missing. Other files (a new memory-directory entry) can
369
- * only hold uncaptured facts.
370
- */
371
- declare function memoryDivergence(store: WorkspaceStore, turn: WorkspaceTurn, before: HarnessNativeFiles, after: HarnessNativeFiles): Promise<MemoryDivergence>;
372
266
  //#endregion
373
- export { type ContentCodecOptions, HARNESS_MEMORY_BEGIN, HARNESS_MEMORY_END, type HarnessIngestResult, type HarnessNativeFiles, type HarnessProvenance, type MakeWorkspaceStore, type MemoryDivergence, type MemoryPolicy, SEALED_CONTENT_PREFIX, type WorkspaceAccess, type WorkspaceBytesRef, type WorkspaceCodecContext, WorkspaceCodecError, WorkspaceConflictError, type WorkspaceContentCodec, type WorkspaceDeleteInput, type WorkspaceEntry, type WorkspaceEntryKind, type WorkspaceEntryScope, type WorkspacePolicyDecision, WorkspacePolicyError, type WorkspacePutInput, type WorkspaceRole, type WorkspaceStore, type WorkspaceStoreContractCase, type WorkspaceStoreContractOptions, type WorkspaceStoreContractResult, type WorkspaceTombstone, type WorkspaceToolContext, type WorkspaceToolDefinition, type WorkspaceTurn, aesGcmContentCodecFromEnv, assertWorkspacePath, captureHarnessMemory, checkOperationId, checkWorkspacePut, createAesGcmContentCodec, createFileTools, createInMemoryWorkspaceStore, createMemoryTools, defaultMemoryPolicy, harnessActor, ingestHarnessMemories, isSameWorkspaceWrite, memberIdFromPath, memoryDivergence, normalizeMemoryText, openWorkspaceBytes, parseHarnessActor, projectHarnessMemory, rankEntries, readTurnMemories, renderHarnessMemory, renderPinnedMemory, runWorkspaceStoreContract, sealWorkspaceBytes, withContentCodec, workspaceStoreContractCases };
267
+ export { type ContentCodecOptions, type HarnessIngestResult, type HarnessProvenance, type MakeWorkspaceStore, type MemoryDivergence, type MemoryPolicy, type WorkspaceAccess, type WorkspaceBytesRef, type WorkspaceCodecContext, WorkspaceConflictError, type WorkspaceContentCodec, type WorkspaceDeleteInput, type WorkspaceEntry, type WorkspaceEntryKind, type WorkspaceEntryScope, type WorkspacePolicyDecision, type WorkspacePutInput, type WorkspaceRole, type WorkspaceStore, type WorkspaceStoreContractCase, type WorkspaceStoreContractOptions, type WorkspaceStoreContractResult, type WorkspaceTombstone, type WorkspaceToolContext, type WorkspaceToolDefinition, type WorkspaceTurn, assertWorkspacePath, checkWorkspacePut, createFileTools, createInMemoryWorkspaceStore, createMemoryTools, defaultMemoryPolicy, readTurnMemories, renderPinnedMemory, runWorkspaceStoreContract, workspaceStoreContractCases };
374
268
  //# sourceMappingURL=index.d.ts.map
@@ -1,215 +1,4 @@
1
1
  import { z } from "zod";
2
- //#region src/workspace-store/codec.ts
3
- /** A value did not open: unknown key, wrong tenant or path, tampering, or plaintext where a seal was required. */
4
- var WorkspaceCodecError = class extends Error {
5
- code = "codec";
6
- constructor(message) {
7
- super(message);
8
- this.name = "WorkspaceCodecError";
9
- }
10
- };
11
- const VERSION = 1;
12
- const IV_BYTES = 12;
13
- const KEY_ID = /^[A-Za-z0-9_-]{1,64}$/;
14
- const encoder = new TextEncoder();
15
- const decoder = new TextDecoder("utf-8", { fatal: true });
16
- function bytesOf(value) {
17
- if (typeof value !== "string") return value;
18
- const binary = atob(value.replace(/-/g, "+").replace(/_/g, "/"));
19
- return Uint8Array.from(binary, (char) => char.charCodeAt(0));
20
- }
21
- function base64(bytes) {
22
- let binary = "";
23
- for (let offset = 0; offset < bytes.length; offset += 32768) binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
24
- return btoa(binary);
25
- }
26
- /** A copy in a plain ArrayBuffer, which every Web Crypto typing accepts (this package has no DOM lib). */
27
- function arrayBuffer(bytes) {
28
- return bytes.slice().buffer;
29
- }
30
- function concat(...parts) {
31
- const out = new Uint8Array(parts.reduce((total, part) => total + part.length, 0));
32
- let offset = 0;
33
- for (const part of parts) {
34
- out.set(part, offset);
35
- offset += part.length;
36
- }
37
- return out;
38
- }
39
- /** Strings joined with a 4-byte length before each, so no two lists encode alike. */
40
- function framed(...values) {
41
- return concat(...values.flatMap((value) => {
42
- const bytes = encoder.encode(value);
43
- const length = /* @__PURE__ */ new Uint8Array(4);
44
- new DataView(length.buffer).setUint32(0, bytes.length);
45
- return [length, bytes];
46
- }));
47
- }
48
- /** The authenticated data: the tenant and path a value belongs to. */
49
- const associated = ({ tenant, path }) => framed(tenant, path);
50
- /**
51
- * AES-256-GCM with a key id per value. `keys` maps key id to 32 raw bytes
52
- * (base64 or base64url when a string). The encryption key and the key that
53
- * derives replay-stable IVs are both derived from the raw key with HKDF, so the
54
- * raw key is never used for two algorithms.
55
- *
56
- * Without an `operationId` every seal uses a random 96-bit IV. With one, the IV
57
- * is an HMAC of the tenant, path, operation and plaintext, as in SIV: only an
58
- * identical write repeats it, and that repeat reveals only that the write was
59
- * repeated.
60
- */
61
- function createAesGcmContentCodec(options) {
62
- const raw = /* @__PURE__ */ new Map();
63
- for (const [id, value] of Object.entries(options.keys)) {
64
- if (!KEY_ID.test(id)) throw new TypeError(`workspace store key id is not [A-Za-z0-9_-]{1,64}: ${id}`);
65
- const bytes = bytesOf(value);
66
- if (bytes.length !== 32) throw new TypeError(`workspace store key ${id} must be 32 bytes, got ${bytes.length}`);
67
- raw.set(id, bytes);
68
- }
69
- if (!raw.has(options.activeKeyId)) throw new TypeError(`the active workspace store key ${options.activeKeyId} is not among the keys`);
70
- const derived = /* @__PURE__ */ new Map();
71
- const keyFor = (id) => {
72
- const bytes = raw.get(id);
73
- if (!bytes) return Promise.reject(new WorkspaceCodecError(`unknown workspace store key id: ${id}`));
74
- let key = derived.get(id);
75
- if (!key) {
76
- key = (async () => {
77
- const base = await crypto.subtle.importKey("raw", arrayBuffer(bytes), "HKDF", false, ["deriveKey"]);
78
- const hkdf = (info) => ({
79
- name: "HKDF",
80
- hash: "SHA-256",
81
- salt: /* @__PURE__ */ new Uint8Array(32),
82
- info: encoder.encode(`workspace-store/${info}`)
83
- });
84
- return {
85
- seal: await crypto.subtle.deriveKey(hkdf("aes-256-gcm"), base, {
86
- name: "AES-GCM",
87
- length: 256
88
- }, false, ["encrypt", "decrypt"]),
89
- iv: await crypto.subtle.deriveKey(hkdf("siv"), base, {
90
- name: "HMAC",
91
- hash: "SHA-256",
92
- length: 256
93
- }, false, ["sign"])
94
- };
95
- })();
96
- derived.set(id, key);
97
- }
98
- return key;
99
- };
100
- return {
101
- async seal(plain, context) {
102
- const id = options.activeKeyId;
103
- const key = await keyFor(id);
104
- const aad = associated(context);
105
- const iv = context.operationId === void 0 ? crypto.getRandomValues(new Uint8Array(IV_BYTES)) : new Uint8Array(await crypto.subtle.sign("HMAC", key.iv, arrayBuffer(concat(framed(context.tenant, context.path, context.operationId), plain)))).slice(0, IV_BYTES);
106
- const sealed = new Uint8Array(await crypto.subtle.encrypt({
107
- name: "AES-GCM",
108
- iv: arrayBuffer(iv),
109
- additionalData: arrayBuffer(aad)
110
- }, key.seal, arrayBuffer(plain)));
111
- const keyId = encoder.encode(id);
112
- return concat(Uint8Array.of(VERSION, keyId.length), keyId, iv, sealed);
113
- },
114
- async open(sealed, context) {
115
- if (sealed.length < 2 || sealed[0] !== VERSION) throw new WorkspaceCodecError("not a sealed workspace value");
116
- const start = 2 + sealed[1];
117
- if (sealed.length < start + IV_BYTES + 16) throw new WorkspaceCodecError("a sealed workspace value is truncated");
118
- const key = await keyFor(new TextDecoder().decode(sealed.subarray(2, start)));
119
- try {
120
- return new Uint8Array(await crypto.subtle.decrypt({
121
- name: "AES-GCM",
122
- iv: arrayBuffer(sealed.subarray(start, start + IV_BYTES)),
123
- additionalData: arrayBuffer(associated(context))
124
- }, key.seal, arrayBuffer(sealed.subarray(start + IV_BYTES))));
125
- } catch {
126
- throw new WorkspaceCodecError(`${context.path}: the sealed value does not open for this tenant and path`);
127
- }
128
- }
129
- };
130
- }
131
- /**
132
- * The AES-256-GCM codec from an app's env, or `null` when neither variable is
133
- * set. `WORKSPACE_STORE_KEYS` is `id:base64,id:base64`; `WORKSPACE_STORE_KEY_ID`
134
- * names the key new writes use. Setting one without the other is refused.
135
- */
136
- function aesGcmContentCodecFromEnv(env) {
137
- const list = env.WORKSPACE_STORE_KEYS?.trim();
138
- const active = env.WORKSPACE_STORE_KEY_ID?.trim();
139
- if (!list && !active) return null;
140
- if (!list || !active) throw new TypeError("set both WORKSPACE_STORE_KEYS and WORKSPACE_STORE_KEY_ID");
141
- const keys = {};
142
- for (const pair of list.split(",")) {
143
- const at = pair.indexOf(":");
144
- if (at <= 0) throw new TypeError("WORKSPACE_STORE_KEYS is id:base64,id:base64");
145
- keys[pair.slice(0, at).trim()] = pair.slice(at + 1).trim();
146
- }
147
- return createAesGcmContentCodec({
148
- keys,
149
- activeKeyId: active
150
- });
151
- }
152
- /** Stored text of a sealed `content`: a prefix, then the sealed bytes in base64. */
153
- const SEALED_CONTENT_PREFIX = "wsc1:";
154
- /** Seal bytes a host is about to upload (an R2 object) under the entry's tenant and path. */
155
- function sealWorkspaceBytes(codec, context, bytes) {
156
- return codec.seal(bytes, context);
157
- }
158
- /** Open bytes a host downloaded for an entry's `bytes` reference. */
159
- function openWorkspaceBytes(codec, context, sealed) {
160
- return codec.open(sealed, context);
161
- }
162
- /**
163
- * `store` with every entry's `content` sealed at rest. Index fields, `bytes`
164
- * references and tombstones pass through untouched; the host seals the bytes
165
- * themselves. `idempotentOperations` is the inner store's: a replayed put with
166
- * an `operationId` seals to the same bytes, so the inner replay check holds.
167
- */
168
- function withContentCodec(store, codec, options = {}) {
169
- const open = async (entry) => {
170
- if (entry.content === void 0) return entry;
171
- if (!entry.content.startsWith("wsc1:")) {
172
- if (options.readPlaintext) return entry;
173
- throw new WorkspaceCodecError(`${entry.path}: stored content is not sealed`);
174
- }
175
- const plain = await codec.open(bytesOf(entry.content.slice(5)), {
176
- tenant: entry.workspaceId,
177
- path: entry.path
178
- });
179
- return {
180
- ...entry,
181
- content: decoder.decode(plain)
182
- };
183
- };
184
- return {
185
- ...store.idempotentOperations !== void 0 ? { idempotentOperations: store.idempotentOperations } : {},
186
- async get(workspaceId, path) {
187
- const entry = await store.get(workspaceId, path);
188
- return entry ? open(entry) : null;
189
- },
190
- async list(workspaceId, prefix) {
191
- return Promise.all((await store.list(workspaceId, prefix)).map(open));
192
- },
193
- async put(input) {
194
- if (input.content === void 0) return store.put(input);
195
- const sealed = await codec.seal(encoder.encode(input.content), {
196
- tenant: input.workspaceId,
197
- path: input.path,
198
- ...input.operationId !== void 0 ? { operationId: input.operationId } : {}
199
- });
200
- return {
201
- ...await store.put({
202
- ...input,
203
- content: `${SEALED_CONTENT_PREFIX}${base64(sealed)}`
204
- }),
205
- content: input.content
206
- };
207
- },
208
- delete: (input) => store.delete(input),
209
- tombstones: (workspaceId, prefix) => store.tombstones(workspaceId, prefix)
210
- };
211
- }
212
- //#endregion
213
2
  //#region src/workspace-store/store.ts
214
3
  /** A write lost a compare-and-set race or targeted the wrong revision. Re-read and retry. */
215
4
  var WorkspaceConflictError = class extends Error {
@@ -1168,209 +957,6 @@ async function runWorkspaceStoreContract(makeStore, options = {}) {
1168
957
  return results;
1169
958
  }
1170
959
  //#endregion
1171
- //#region src/workspace-store/harness.ts
1172
- /** Opening marker for the generated block in a harness's native memory file. */
1173
- const HARNESS_MEMORY_BEGIN = "<!-- workspace-store:memory begin. Generated from the workspace store; save memories with memory.remember. -->";
1174
- /** Closing marker for the generated block in a harness's native memory file. */
1175
- const HARNESS_MEMORY_END = "<!-- workspace-store:memory end -->";
1176
- /** The generated block a host writes into a harness's native memory location. */
1177
- function renderHarnessMemory(entries, options = {}) {
1178
- return [
1179
- HARNESS_MEMORY_BEGIN,
1180
- renderPinnedMemory(entries, options),
1181
- HARNESS_MEMORY_END
1182
- ].join("\n");
1183
- }
1184
- /** Replace the generated block in `native`, or append one; text outside it is kept byte for byte. */
1185
- function projectHarnessMemory(native, block) {
1186
- const { before, after, found } = splitGenerated(native);
1187
- if (found) return `${before}${block}${after}`;
1188
- return native.length === 0 ? `${block}\n` : `${native}${native.endsWith("\n") ? "\n" : "\n\n"}${block}\n`;
1189
- }
1190
- function splitGenerated(native) {
1191
- const start = native.indexOf(HARNESS_MEMORY_BEGIN);
1192
- const end = start < 0 ? -1 : native.indexOf(HARNESS_MEMORY_END, start);
1193
- if (start < 0 || end < 0) return {
1194
- before: native,
1195
- block: "",
1196
- after: "",
1197
- found: false
1198
- };
1199
- const stop = end + 35;
1200
- return {
1201
- before: native.slice(0, start),
1202
- block: native.slice(start, stop),
1203
- after: native.slice(stop),
1204
- found: true
1205
- };
1206
- }
1207
- /** Ids listed in a generated block (`- [id] kind, scope: text`). */
1208
- function projectedIds(block) {
1209
- const ids = /* @__PURE__ */ new Map();
1210
- for (const match of block.matchAll(/^- \[([A-Za-z0-9_-]{1,64})\] [a-z]+, (?:me|workspace): (.*)$/gm)) ids.set(match[1], match[2]);
1211
- return ids;
1212
- }
1213
- /** Lowercase, collapse spaces, drop a leading "Remember:" and trailing punctuation: the duplicate key. */
1214
- function normalizeMemoryText(text) {
1215
- return text.replace(/^\s*(?:[-*+]\s+|\d+[.)]\s+)?/, "").replace(/^(?:remember|note)\b\s*(?:that\b)?\s*:?\s*/i, "").replace(/\s+/g, " ").trim().replace(/[.!;,\s]+$/, "").toLowerCase();
1216
- }
1217
- function stripFrontmatter(text) {
1218
- return text.startsWith("---\n") ? text.slice(text.indexOf("\n---", 4) + 4).replace(/^\n+/, "") : text;
1219
- }
1220
- /** Lines that read as one memory: bullets and plain sentences, not headings, markers or fences. */
1221
- function memoryLines(text) {
1222
- const lines = [];
1223
- let fenced = false;
1224
- for (const raw of stripFrontmatter(text).split("\n")) {
1225
- const line = raw.trim();
1226
- if (line.startsWith("```")) {
1227
- fenced = !fenced;
1228
- continue;
1229
- }
1230
- if (fenced || !line || line.startsWith("#") || line.startsWith("<!--") || line.startsWith("@")) continue;
1231
- const fact = line.replace(/^(?:[-*+]\s+|\d+[.)]\s+)/, "").trim();
1232
- if (fact.length >= 3 && fact.length <= 1e3) lines.push(fact);
1233
- }
1234
- return lines;
1235
- }
1236
- /**
1237
- * What the harness added during the turn, outside the generated block: new
1238
- * lines in files that existed, and the body of new files (a Claude Code memory
1239
- * directory entry). Lines removed or present before are ignored; a removal is
1240
- * not a forget, which only `memory.forget` performs.
1241
- */
1242
- function captureHarnessMemory(before, after) {
1243
- const seen = /* @__PURE__ */ new Set();
1244
- const facts = [];
1245
- for (const [path, next] of Object.entries(after)) {
1246
- if (next === void 0) continue;
1247
- const old = new Set(memoryLines(outside(before[path] ?? "")).map(normalizeMemoryText));
1248
- for (const fact of memoryLines(outside(next))) {
1249
- const key = normalizeMemoryText(fact);
1250
- if (!key || old.has(key) || seen.has(key)) continue;
1251
- seen.add(key);
1252
- facts.push(fact);
1253
- }
1254
- }
1255
- return facts;
1256
- }
1257
- function outside(native) {
1258
- const { before, after, found } = splitGenerated(native);
1259
- return found ? `${before}\n${after}` : native;
1260
- }
1261
- const ACTOR = /^harness:([a-z0-9][a-z0-9._-]{0,40})\/turn:([^/\s]{1,128})\/member:([^/\s]{1,128})$/;
1262
- /** The entry `actor` for a captured memory, so `createdBy` carries its provenance. */
1263
- function harnessActor({ harness, turnId, memberId }) {
1264
- const actor = `harness:${harness}/turn:${turnId}/member:${memberId}`;
1265
- if (!ACTOR.test(actor)) throw new TypeError(`invalid harness provenance: ${actor}`);
1266
- return actor;
1267
- }
1268
- /** Read the harness, turn, and member provenance encoded by {@link harnessActor}. */
1269
- function parseHarnessActor(actor) {
1270
- const match = ACTOR.exec(actor);
1271
- return match ? {
1272
- harness: match[1],
1273
- turnId: match[2],
1274
- memberId: match[3]
1275
- } : null;
1276
- }
1277
- /**
1278
- * Save captured facts as workspace memories through the same policy as
1279
- * `memory.remember`, with the harness and turn as the actor. Duplicates of a
1280
- * memory the turn can see, or of an earlier fact in the batch, are skipped.
1281
- */
1282
- async function ingestHarnessMemories(context, input) {
1283
- const turn = await context.activeTurn();
1284
- const actor = harnessActor({
1285
- harness: input.harness,
1286
- turnId: input.turnId,
1287
- memberId: turn.memberId
1288
- });
1289
- const newId = context.newId ?? (() => crypto.randomUUID());
1290
- const known = new Set((await readTurnMemories(context.store, turn)).map((entry) => normalizeMemoryText(entry.content ?? "")));
1291
- const saved = [];
1292
- const duplicates = [];
1293
- const refused = [];
1294
- for (const raw of input.facts) {
1295
- const text = raw.replace(/\s+/g, " ").trim();
1296
- const key = normalizeMemoryText(text);
1297
- if (!key) continue;
1298
- if (known.has(key)) {
1299
- duplicates.push(text);
1300
- continue;
1301
- }
1302
- const id = newId();
1303
- const path = `/memories/workspace/${id}`;
1304
- try {
1305
- await guard(context, turn, {
1306
- op: "write",
1307
- path,
1308
- kind: "fact"
1309
- }, text);
1310
- } catch (error) {
1311
- refused.push({
1312
- text,
1313
- reason: error instanceof Error ? error.message : String(error)
1314
- });
1315
- continue;
1316
- }
1317
- known.add(key);
1318
- saved.push(await context.store.put({
1319
- workspaceId: turn.workspaceId,
1320
- path,
1321
- kind: "fact",
1322
- ifRevision: null,
1323
- actor,
1324
- content: text,
1325
- id
1326
- }));
1327
- }
1328
- return {
1329
- saved,
1330
- duplicates,
1331
- refused
1332
- };
1333
- }
1334
- /**
1335
- * Compare each native file with the store as `turn` sees it, after ingest ran.
1336
- * `before` is the files as projected at session start, `after` as they are now:
1337
- * only what the harness added since then can be uncaptured, so the profile's own
1338
- * generated text in the same file never counts. Files that held a generated
1339
- * block at session start are projection targets: losing the block counts every
1340
- * visible memory as missing. Other files (a new memory-directory entry) can
1341
- * only hold uncaptured facts.
1342
- */
1343
- async function memoryDivergence(store, turn, before, after) {
1344
- const entries = (await readTurnMemories(store, turn)).filter((entry) => entry.content !== void 0);
1345
- const byId = new Map(entries.map((entry) => [entry.id, entry.content.replace(/\s+/g, " ").trim()]));
1346
- const stored = new Set(entries.map((entry) => normalizeMemoryText(entry.content)));
1347
- const files = {};
1348
- let missing = 0;
1349
- let stale = 0;
1350
- let uncaptured = 0;
1351
- for (const [path, native] of Object.entries(after)) {
1352
- if (native === void 0) continue;
1353
- const target = splitGenerated(before[path] ?? "").found || splitGenerated(native).found;
1354
- const listed = projectedIds(splitGenerated(native).block);
1355
- const report = {
1356
- missing: target ? [...byId.keys()].filter((id) => !listed.has(id)) : [],
1357
- stale: [...listed].filter(([id, text]) => byId.get(id) !== text).map(([id]) => id),
1358
- uncaptured: captureHarnessMemory({ [path]: before[path] }, { [path]: native }).filter((fact) => !stored.has(normalizeMemoryText(fact)))
1359
- };
1360
- missing += report.missing.length;
1361
- stale += report.stale.length;
1362
- uncaptured += report.uncaptured.length;
1363
- files[path] = report;
1364
- }
1365
- return {
1366
- total: missing + stale + uncaptured,
1367
- missing,
1368
- stale,
1369
- uncaptured,
1370
- files
1371
- };
1372
- }
1373
- //#endregion
1374
- export { HARNESS_MEMORY_BEGIN, HARNESS_MEMORY_END, SEALED_CONTENT_PREFIX, WorkspaceCodecError, WorkspaceConflictError, WorkspacePolicyError, aesGcmContentCodecFromEnv, assertWorkspacePath, captureHarnessMemory, checkOperationId, checkWorkspacePut, createAesGcmContentCodec, createFileTools, createInMemoryWorkspaceStore, createMemoryTools, defaultMemoryPolicy, harnessActor, ingestHarnessMemories, isSameWorkspaceWrite, memberIdFromPath, memoryDivergence, normalizeMemoryText, openWorkspaceBytes, parseHarnessActor, projectHarnessMemory, rankEntries, readTurnMemories, renderHarnessMemory, renderPinnedMemory, runWorkspaceStoreContract, sealWorkspaceBytes, withContentCodec, workspaceStoreContractCases };
960
+ export { WorkspaceConflictError, assertWorkspacePath, checkWorkspacePut, createFileTools, createInMemoryWorkspaceStore, createMemoryTools, defaultMemoryPolicy, readTurnMemories, renderPinnedMemory, runWorkspaceStoreContract, workspaceStoreContractCases };
1375
961
 
1376
962
  //# sourceMappingURL=index.js.map