@remnic/plugin-openclaw 1.0.10 → 1.0.12

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 (70) hide show
  1. package/dist/{calibration-674TDQNV.js → calibration-WCHOK6DX.js} +12 -4
  2. package/dist/capsule-cli-GBM3WPAM.js +33 -0
  3. package/dist/capsule-crypto-K3IRTKRH.js +17 -0
  4. package/dist/capsule-export-IXVERCQG.js +17 -0
  5. package/dist/capsule-import-IA6VIOPQ.js +16 -0
  6. package/dist/capsule-merge-IWOQ34KL.js +189 -0
  7. package/dist/{causal-chain-OKDZSDEB.js → causal-chain-WYN5QOPS.js} +3 -2
  8. package/dist/{causal-consolidation-5BEXLQV5.js → causal-consolidation-YI53C2AO.js} +16 -12
  9. package/dist/{causal-retrieval-3BKBXVXD.js → causal-retrieval-NZHQOZOE.js} +6 -5
  10. package/dist/{causal-trajectory-graph-RQIT37DN.js → causal-trajectory-graph-VBPE2WPM.js} +1 -1
  11. package/dist/chunk-37NKFWSO.js +233 -0
  12. package/dist/chunk-3G7FAF6S.js +60 -0
  13. package/dist/{chunk-Z7GRLVK3.js → chunk-3GUF7RQI.js} +235 -19
  14. package/dist/chunk-4G2XCSD2.js +186 -0
  15. package/dist/chunk-4LYQ4ONL.js +185 -0
  16. package/dist/chunk-6F6EKSVP.js +453 -0
  17. package/dist/chunk-6IWEAUN6.js +148 -0
  18. package/dist/{chunk-LN5UZQVG.js → chunk-6UFI73TJ.js} +5 -3
  19. package/dist/chunk-7OQEPGQF.js +529 -0
  20. package/dist/{chunk-JJSNPSCD.js → chunk-7UZNLMW5.js} +652 -174
  21. package/dist/chunk-B52XADV3.js +244 -0
  22. package/dist/chunk-BU5KJVWF.js +78 -0
  23. package/dist/chunk-CDAZGIGT.js +720 -0
  24. package/dist/chunk-CXM7EBAO.js +289 -0
  25. package/dist/{chunk-HCFFXBLV.js → chunk-EXDYWXMB.js} +6 -1861
  26. package/dist/chunk-FGTYFLL5.js +274 -0
  27. package/dist/chunk-FQRSVYY4.js +110 -0
  28. package/dist/chunk-HRGFO6AW.js +349 -0
  29. package/dist/chunk-I6B2W2IY.js +47 -0
  30. package/dist/chunk-JZBOXOUC.js +259 -0
  31. package/dist/chunk-L6I4MQKO.js +227 -0
  32. package/dist/chunk-LLUROTZJ.js +328 -0
  33. package/dist/chunk-MBIFE6SA.js +250 -0
  34. package/dist/chunk-NKVIN6RD.js +118 -0
  35. package/dist/chunk-OAE7AQ6R.js +1832 -0
  36. package/dist/chunk-OEI7GLV2.js +17 -0
  37. package/dist/chunk-RKR6PTPA.js +308 -0
  38. package/dist/{chunk-7TENHBV2.js → chunk-RQCTMECT.js} +10 -48
  39. package/dist/chunk-SSFTU6LP.js +182 -0
  40. package/dist/{chunk-BXTMZDRT.js → chunk-SVSQAG6M.js} +7 -5
  41. package/dist/{chunk-S2ISS4AH.js → chunk-TILAJIJR.js} +10 -10
  42. package/dist/chunk-TLVIQLB4.js +874 -0
  43. package/dist/{chunk-YHH3SXKD.js → chunk-WPINX4MF.js} +1 -59
  44. package/dist/chunk-YGGGUTG3.js +125 -0
  45. package/dist/cipher-VHAFCG7Z.js +27 -0
  46. package/dist/dreams-ledger-3I52ISYR.js +285 -0
  47. package/dist/{engine-65C2J63X.js → engine-BIYI3P4J.js} +7 -2
  48. package/dist/{fallback-llm-LVK5PDIM.js → fallback-llm-WCWNGIQ3.js} +2 -1
  49. package/dist/first-start-migration-I24M2JEE.js +258 -0
  50. package/dist/forget-NI4RBDPB.js +68 -0
  51. package/dist/fs-utils-PZRI2HDZ.js +29 -0
  52. package/dist/graph-edge-decay-5CVKWBYH.js +203 -0
  53. package/dist/index.js +10654 -3067
  54. package/dist/kdf-H5B23ZM2.js +25 -0
  55. package/dist/memory-governance-SJ5DGRB3.js +25 -0
  56. package/dist/metadata-JAGIWHEA.js +20 -0
  57. package/dist/migrate-from-identity-anchor-N3354WMP.js +7 -0
  58. package/dist/path-5LCUBAAZ.js +8 -0
  59. package/dist/peers-JF2I6RCR.js +43 -0
  60. package/dist/purge-XN2VSPZ2.js +204 -0
  61. package/dist/secure-store-A4NGCNXV.js +155 -0
  62. package/dist/state-PVISYXRH.js +7 -0
  63. package/dist/state-store-LP5BO6SF.js +15 -0
  64. package/dist/{storage-DM4ZGOCN.js → storage-PTQ2H2YJ.js} +3 -1
  65. package/dist/tier-stats-IZNW66NC.js +147 -0
  66. package/dist/trace-NJESSGH7.js +289 -0
  67. package/dist/tui-MGK2LYJY.js +12 -0
  68. package/dist/types-R4DO7AKM.js +30 -0
  69. package/openclaw.plugin.json +519 -4
  70. package/package.json +2 -2
@@ -0,0 +1,17 @@
1
+ import {
2
+ resolveHomeDir
3
+ } from "./chunk-I6B2W2IY.js";
4
+
5
+ // ../remnic-core/src/utils/path.ts
6
+ import path from "path";
7
+ function expandTildePath(p) {
8
+ if (p === "~") return resolveHomeDir();
9
+ if (p.startsWith("~/") || p.startsWith("~\\")) {
10
+ return path.join(resolveHomeDir(), p.slice(2));
11
+ }
12
+ return p;
13
+ }
14
+
15
+ export {
16
+ expandTildePath
17
+ };
@@ -0,0 +1,308 @@
1
+ import {
2
+ generateSalt,
3
+ open,
4
+ seal
5
+ } from "./chunk-YGGGUTG3.js";
6
+
7
+ // ../remnic-core/src/secure-store/secure-fs.ts
8
+ import { lstat, mkdir, readFile, readdir, rename, unlink, writeFile } from "fs/promises";
9
+ import path from "path";
10
+ var SecureStoreLockedError = class extends Error {
11
+ constructor(message = "secure-store is locked \u2014 run `remnic secure-store unlock` to decrypt") {
12
+ super(message);
13
+ this.name = "SecureStoreLockedError";
14
+ }
15
+ };
16
+ var SecureStoreDecryptError = class extends Error {
17
+ constructor(message = "secure-store decryption failed \u2014 wrong key or tampered ciphertext") {
18
+ super(message);
19
+ this.name = "SecureStoreDecryptError";
20
+ }
21
+ };
22
+ var MAGIC_BYTES = Buffer.from("REMNIC-ENC", "ascii");
23
+ var FILE_FORMAT_VERSION = 1;
24
+ var FILE_FORMAT_FLAGS = 0;
25
+ var MAGIC_HEADER_SIZE = MAGIC_BYTES.length + 2;
26
+ function isEncryptedFile(buf) {
27
+ if (buf.length < MAGIC_HEADER_SIZE) return false;
28
+ const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
29
+ return b.subarray(0, MAGIC_BYTES.length).equals(MAGIC_BYTES);
30
+ }
31
+ function encryptFileBody(plain, key, aad) {
32
+ const plainBuf = typeof plain === "string" ? Buffer.from(plain, "utf8") : plain;
33
+ const salt = generateSalt();
34
+ const envelope = seal(key, salt, plainBuf, aad ? { aad } : {});
35
+ const header = Buffer.alloc(MAGIC_HEADER_SIZE);
36
+ MAGIC_BYTES.copy(header, 0);
37
+ header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);
38
+ header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);
39
+ return Buffer.concat([header, envelope]);
40
+ }
41
+ function decryptFileBody(buf, key, aad) {
42
+ if (!isEncryptedFile(buf)) {
43
+ throw new Error("decryptFileBody: buffer does not start with REMNIC-ENC magic header");
44
+ }
45
+ const version = buf.readUInt8(MAGIC_BYTES.length);
46
+ if (version !== FILE_FORMAT_VERSION) {
47
+ throw new Error(
48
+ `decryptFileBody: unsupported file format version ${version} (this build supports ${FILE_FORMAT_VERSION})`
49
+ );
50
+ }
51
+ const flags = buf.readUInt8(MAGIC_BYTES.length + 1);
52
+ if (flags !== FILE_FORMAT_FLAGS) {
53
+ throw new Error(`decryptFileBody: unknown flags byte 0x${flags.toString(16).padStart(2, "0")}`);
54
+ }
55
+ const envelope = buf.subarray(MAGIC_HEADER_SIZE);
56
+ try {
57
+ return open(key, envelope, aad ? { aad } : {});
58
+ } catch (err) {
59
+ const msg = err instanceof Error ? err.message : String(err);
60
+ throw new SecureStoreDecryptError(
61
+ `secure-store decryption failed: ${msg}`
62
+ );
63
+ }
64
+ }
65
+ function filePathAad(filePath, memoryDir) {
66
+ let rel = filePath;
67
+ if (memoryDir && path.isAbsolute(filePath)) {
68
+ rel = path.relative(memoryDir, filePath);
69
+ }
70
+ return Buffer.from(rel, "utf8");
71
+ }
72
+ async function readMaybeEncryptedFile(filePath, key, memoryDir) {
73
+ const buf = await readFile(filePath);
74
+ if (!isEncryptedFile(buf)) {
75
+ return buf.toString("utf8");
76
+ }
77
+ if (key === null) {
78
+ throw new SecureStoreLockedError(
79
+ `secure-store is locked \u2014 cannot read encrypted file at ${filePath}. Run \`remnic secure-store unlock\` to decrypt.`
80
+ );
81
+ }
82
+ const aad = filePathAad(filePath, memoryDir);
83
+ const plain = decryptFileBody(buf, key, aad);
84
+ return plain.toString("utf8");
85
+ }
86
+ async function writeMaybeEncryptedFile(filePath, content, key, options = {}, memoryDir) {
87
+ const { mode = 384, atomic = true } = options;
88
+ await mkdir(path.dirname(filePath), { recursive: true });
89
+ let data;
90
+ if (key !== null) {
91
+ const aad = filePathAad(filePath, memoryDir);
92
+ data = encryptFileBody(content, key, aad);
93
+ } else {
94
+ data = content;
95
+ }
96
+ if (atomic) {
97
+ const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
98
+ try {
99
+ await writeFile(tempPath, data, { mode });
100
+ await rename(tempPath, filePath);
101
+ } catch (err) {
102
+ try {
103
+ await unlink(tempPath);
104
+ } catch {
105
+ }
106
+ throw err;
107
+ }
108
+ } else {
109
+ await writeFile(filePath, data, { mode });
110
+ }
111
+ }
112
+ async function migrateMemoryDirToEncrypted(dir, key, onBeforeEncrypt) {
113
+ const result = { encrypted: 0, skipped: 0, errors: [] };
114
+ const files = await collectEncryptableStorageFiles(dir);
115
+ for (const filePath of files) {
116
+ try {
117
+ const buf = await readFile(filePath);
118
+ if (isEncryptedFile(buf)) {
119
+ result.skipped++;
120
+ continue;
121
+ }
122
+ if (onBeforeEncrypt) {
123
+ try {
124
+ await onBeforeEncrypt(filePath);
125
+ } catch {
126
+ }
127
+ }
128
+ const content = buf.toString("utf8");
129
+ const aad = filePathAad(filePath, storageAadRootForFile(filePath, dir));
130
+ const encrypted = encryptFileBody(content, key, aad);
131
+ const tempPath = `${filePath}.enc-tmp-${process.pid}-${Date.now()}`;
132
+ try {
133
+ await writeFile(tempPath, encrypted, { mode: 384 });
134
+ await rename(tempPath, filePath);
135
+ result.encrypted++;
136
+ } catch (writeErr) {
137
+ try {
138
+ const { unlink: unlink2 } = await import("fs/promises");
139
+ await unlink2(tempPath);
140
+ } catch {
141
+ }
142
+ throw writeErr;
143
+ }
144
+ } catch (err) {
145
+ result.errors.push({
146
+ filePath,
147
+ error: err instanceof Error ? err.message : String(err)
148
+ });
149
+ }
150
+ }
151
+ return result;
152
+ }
153
+ async function decryptMemoryDirToPlaintext(dir, key) {
154
+ const result = { decrypted: 0, skipped: 0, errors: [] };
155
+ const files = await collectStorageManagedFiles(dir, isDecryptableStoragePath);
156
+ for (const filePath of files) {
157
+ try {
158
+ const buf = await readFile(filePath);
159
+ if (!isEncryptedFile(buf)) {
160
+ result.skipped++;
161
+ continue;
162
+ }
163
+ const aad = filePathAad(filePath, storageAadRootForFile(filePath, dir));
164
+ const plaintext = decryptFileBody(buf, key, aad);
165
+ const tempPath = `${filePath}.dec-tmp-${process.pid}-${Date.now()}`;
166
+ try {
167
+ await writeFile(tempPath, plaintext, { mode: 384 });
168
+ await rename(tempPath, filePath);
169
+ result.decrypted++;
170
+ } catch (writeErr) {
171
+ try {
172
+ await unlink(tempPath);
173
+ } catch {
174
+ }
175
+ throw writeErr;
176
+ }
177
+ } catch (err) {
178
+ result.errors.push({
179
+ filePath,
180
+ error: err instanceof Error ? err.message : String(err)
181
+ });
182
+ }
183
+ }
184
+ return result;
185
+ }
186
+ async function collectEncryptableStorageFiles(dir, rootDir = dir) {
187
+ return collectStorageManagedFiles(dir, isEncryptableStoragePath, rootDir);
188
+ }
189
+ async function collectStorageManagedFiles(dir, includeFile, rootDir = dir) {
190
+ const results = [];
191
+ let names;
192
+ try {
193
+ names = await readdir(dir, { encoding: "utf8" });
194
+ } catch {
195
+ return results;
196
+ }
197
+ for (const name of names) {
198
+ if (name.startsWith(".secure-store")) continue;
199
+ const full = path.join(dir, name);
200
+ let isDir = false;
201
+ let isFile = false;
202
+ try {
203
+ const s = await lstat(full);
204
+ if (s.isSymbolicLink()) continue;
205
+ isDir = s.isDirectory();
206
+ isFile = s.isFile();
207
+ } catch {
208
+ continue;
209
+ }
210
+ if (isDir) {
211
+ const sub = await collectStorageManagedFiles(full, includeFile, rootDir);
212
+ results.push(...sub);
213
+ } else if (isFile && includeFile(full, rootDir)) {
214
+ results.push(full);
215
+ }
216
+ }
217
+ return results;
218
+ }
219
+ function isEncryptableStoragePath(filePath, rootDir) {
220
+ const rel = path.relative(rootDir, filePath);
221
+ if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return false;
222
+ const normalized = normalizeStorageRelativePath(rel);
223
+ if (normalized === "profile.md") return true;
224
+ if (isEncryptableStateSidecar(normalized)) return true;
225
+ if (isEncryptableSummarySidecar(normalized)) return true;
226
+ const firstSegment = normalized.split("/", 1)[0];
227
+ return ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS.has(firstSegment) && normalized.endsWith(".md");
228
+ }
229
+ function isDecryptableStoragePath(filePath, rootDir) {
230
+ if (isEncryptableStoragePath(filePath, rootDir)) return true;
231
+ const rel = path.relative(rootDir, filePath);
232
+ if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return false;
233
+ const normalized = normalizeStorageRelativePath(rel);
234
+ const firstSegment = normalized.split("/", 1)[0];
235
+ return DECRYPTABLE_SIDECAR_ROOTS.has(firstSegment);
236
+ }
237
+ function normalizeStorageRelativePath(rel) {
238
+ const normalized = rel.split(path.sep).join("/");
239
+ const parts = normalized.split("/");
240
+ if (parts[0] === "namespaces" && parts.length >= 3) {
241
+ return parts.slice(2).join("/");
242
+ }
243
+ return normalized;
244
+ }
245
+ function storageAadRootForFile(filePath, rootDir) {
246
+ const rel = path.relative(rootDir, filePath);
247
+ if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return rootDir;
248
+ const parts = rel.split(path.sep);
249
+ if (parts[0] === "namespaces" && parts.length >= 3 && parts[1]) {
250
+ return path.join(rootDir, "namespaces", parts[1]);
251
+ }
252
+ return rootDir;
253
+ }
254
+ var ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS = /* @__PURE__ */ new Set([
255
+ "facts",
256
+ "corrections",
257
+ "procedures",
258
+ "reasoning-traces",
259
+ "artifacts",
260
+ "archive",
261
+ "entities",
262
+ "identity"
263
+ ]);
264
+ var ENCRYPTABLE_STATE_SIDECARS = /* @__PURE__ */ new Set([
265
+ "state/behavior-signals.jsonl",
266
+ "state/buffer-surprise-ledger.jsonl",
267
+ "state/buffer.json",
268
+ "state/compression-guideline-draft-state.json",
269
+ "state/compression-guideline-state.json",
270
+ "state/compression-guidelines.draft.md",
271
+ "state/compression-guidelines.md",
272
+ "state/entity-synthesis-queue.json",
273
+ "state/fact-hashes.txt",
274
+ "state/memory-actions.jsonl",
275
+ "state/memory-lifecycle-ledger.jsonl",
276
+ "state/meta.json",
277
+ "state/reextract-jobs.jsonl",
278
+ "state/topics.json"
279
+ ]);
280
+ function isEncryptableStateSidecar(normalized) {
281
+ return ENCRYPTABLE_STATE_SIDECARS.has(normalized);
282
+ }
283
+ function isEncryptableSummarySidecar(normalized) {
284
+ return normalized.startsWith("summaries/") && normalized.endsWith(".json");
285
+ }
286
+ var DECRYPTABLE_SIDECAR_ROOTS = /* @__PURE__ */ new Set([
287
+ "state",
288
+ "indexes",
289
+ "index",
290
+ "provenance"
291
+ ]);
292
+
293
+ export {
294
+ SecureStoreLockedError,
295
+ SecureStoreDecryptError,
296
+ MAGIC_BYTES,
297
+ FILE_FORMAT_VERSION,
298
+ FILE_FORMAT_FLAGS,
299
+ MAGIC_HEADER_SIZE,
300
+ isEncryptedFile,
301
+ encryptFileBody,
302
+ decryptFileBody,
303
+ filePathAad,
304
+ readMaybeEncryptedFile,
305
+ writeMaybeEncryptedFile,
306
+ migrateMemoryDirToEncrypted,
307
+ decryptMemoryDirToPlaintext
308
+ };
@@ -4,6 +4,9 @@ import {
4
4
  import {
5
5
  log
6
6
  } from "./chunk-UFU5GGGA.js";
7
+ import {
8
+ readEnvVar
9
+ } from "./chunk-I6B2W2IY.js";
7
10
 
8
11
  // ../remnic-core/src/openai-chat-compat.ts
9
12
  function normalizedModel(model) {
@@ -38,51 +41,9 @@ function buildChatCompletionTokenLimit(model, maxTokens, options) {
38
41
  return { max_tokens: safeMaxTokens };
39
42
  }
40
43
 
41
- // ../remnic-core/src/runtime/env.ts
42
- import os from "os";
43
- var REMNIC_ENGRAM_PREFIX_PAIRS = [
44
- ["REMNIC_", "ENGRAM_"],
45
- ["ENGRAM_", "REMNIC_"]
46
- ];
47
- function getEnvMap() {
48
- const runtimeProcess = globalThis.process;
49
- return runtimeProcess?.["env"];
50
- }
51
- function legacyEnvCandidates(name) {
52
- const candidates = [name];
53
- for (const [primary, legacy] of REMNIC_ENGRAM_PREFIX_PAIRS) {
54
- if (name.startsWith(primary)) {
55
- candidates.push(`${legacy}${name.slice(primary.length)}`);
56
- }
57
- }
58
- return candidates;
59
- }
60
- function readEnvVar(name) {
61
- const env = getEnvMap();
62
- for (const candidate of legacyEnvCandidates(name)) {
63
- const value = env?.[candidate];
64
- if (typeof value === "string") return value;
65
- }
66
- return void 0;
67
- }
68
- function resolveHomeDir() {
69
- return readEnvVar("HOME") || os.homedir();
70
- }
71
- function cloneEnv() {
72
- return { ...getEnvMap() ?? {} };
73
- }
74
- function mergeEnv(overrides) {
75
- const merged = cloneEnv();
76
- for (const [key, value] of Object.entries(overrides)) {
77
- if (typeof value === "string") merged[key] = value;
78
- else delete merged[key];
79
- }
80
- return merged;
81
- }
82
-
83
44
  // ../remnic-core/src/resolve-provider-secret.ts
84
45
  import path from "path";
85
- import os2 from "os";
46
+ import os from "os";
86
47
  var _resolveApiKeyForProvider = null;
87
48
  var _getRuntimeAuthForModel = null;
88
49
  var _resolverLoaded = false;
@@ -126,6 +87,9 @@ async function getGatewayResolver() {
126
87
  return null;
127
88
  }
128
89
  async function findRuntimeModules() {
90
+ return findGatewayRuntimeModules("runtime-model-auth.runtime-");
91
+ }
92
+ async function findGatewayRuntimeModules(filePrefix) {
129
93
  const { accessSync, constants, readdirSync, realpathSync, statSync } = await import("fs");
130
94
  const { createRequire } = await import("module");
131
95
  const candidates = [];
@@ -169,7 +133,7 @@ async function findRuntimeModules() {
169
133
  try {
170
134
  const files = readdirSync(dir);
171
135
  for (const f of files) {
172
- if (f.startsWith("runtime-model-auth.runtime-") && f.endsWith(".js")) {
136
+ if (f.startsWith(filePrefix) && f.endsWith(".js")) {
173
137
  candidates.push(path.join(dir, f));
174
138
  }
175
139
  }
@@ -200,7 +164,7 @@ function findExecutableOnPath(executableName, access, stat, executableMode) {
200
164
  }
201
165
  async function resolveProviderApiKey(providerId, apiKeyValue, gatewayConfig, agentDir) {
202
166
  const resolvedAgentDir = path.resolve(
203
- agentDir ?? path.join(os2.homedir(), ".openclaw", "agents", "main", "agent")
167
+ agentDir ?? path.join(os.homedir(), ".openclaw", "agents", "main", "agent")
204
168
  );
205
169
  const cacheKey = `provider:${providerId}:agentDir:${resolvedAgentDir}`;
206
170
  if (resolvedCache.has(cacheKey)) {
@@ -730,10 +694,8 @@ function extractResponsesOutputText(data) {
730
694
  }
731
695
 
732
696
  export {
733
- readEnvVar,
734
- resolveHomeDir,
735
- mergeEnv,
736
697
  shouldAssumeOpenAiChatCompletions,
737
698
  buildChatCompletionTokenLimit,
699
+ findGatewayRuntimeModules,
738
700
  FallbackLlmClient
739
701
  };
@@ -0,0 +1,182 @@
1
+ import {
2
+ getKey,
3
+ readHeader,
4
+ secureStoreDir
5
+ } from "./chunk-CXM7EBAO.js";
6
+ import {
7
+ open,
8
+ seal
9
+ } from "./chunk-YGGGUTG3.js";
10
+
11
+ // ../remnic-core/src/transfer/capsule-crypto.ts
12
+ import { open as openFileHandle, readFile, writeFile } from "fs/promises";
13
+ import path from "path";
14
+ var MAGIC = Buffer.from("REMNIC-ENC\0", "ascii");
15
+ var FORMAT_VERSION = 2;
16
+ var MIN_ENC_SIZE_V1 = MAGIC.length + 1 + 45;
17
+ var MIN_ENC_SIZE = MAGIC.length + 1 + 2;
18
+ async function isEncryptedCapsuleFile(filePath) {
19
+ if (!filePath.endsWith(".enc")) return false;
20
+ let fh = null;
21
+ try {
22
+ fh = await openFileHandle(filePath, "r");
23
+ const buf = Buffer.allocUnsafe(MAGIC.length);
24
+ const { bytesRead } = await fh.read(buf, 0, MAGIC.length, 0);
25
+ if (bytesRead < MAGIC.length) return false;
26
+ return buf.equals(MAGIC);
27
+ } catch {
28
+ return false;
29
+ } finally {
30
+ if (fh !== null) {
31
+ await fh.close().catch(() => void 0);
32
+ }
33
+ }
34
+ }
35
+ async function encryptCapsuleFile(opts) {
36
+ const encPath = opts.outPath ?? `${opts.sourceGzPath}.enc`;
37
+ const key = getKeyOrThrow(opts.memoryDir, "encrypt capsule");
38
+ const plaintext = await readFile(opts.sourceGzPath);
39
+ const basename = path.basename(encPath);
40
+ const aad = Buffer.from(basename, "utf-8");
41
+ const kdfSection = await loadKdfSection(opts.memoryDir);
42
+ const envelope = seal(key, kdfSection.salt, plaintext, { aad });
43
+ const versionBuf = Buffer.alloc(1);
44
+ versionBuf.writeUInt8(FORMAT_VERSION, 0);
45
+ const kdfJsonBuf = Buffer.from(kdfSection.json, "utf-8");
46
+ const kdfLenBuf = Buffer.alloc(2);
47
+ kdfLenBuf.writeUInt16LE(kdfJsonBuf.length, 0);
48
+ const output = Buffer.concat([MAGIC, versionBuf, kdfLenBuf, kdfJsonBuf, envelope]);
49
+ await writeFile(encPath, output);
50
+ return { encPath };
51
+ }
52
+ async function decryptCapsuleFile(opts) {
53
+ const gzPath = opts.outPath ?? opts.encPath.replace(/\.enc$/, "");
54
+ const buf = await readFile(opts.encPath);
55
+ if (buf.length < MIN_ENC_SIZE_V1) {
56
+ throw new Error(
57
+ `decryptCapsuleFile: file too short to be an encrypted capsule: ${opts.encPath}`
58
+ );
59
+ }
60
+ if (!buf.subarray(0, MAGIC.length).equals(MAGIC)) {
61
+ throw new Error(
62
+ `decryptCapsuleFile: file does not start with REMNIC-ENC magic: ${opts.encPath}`
63
+ );
64
+ }
65
+ const version = buf.readUInt8(MAGIC.length);
66
+ if (version !== 1 && version !== 2) {
67
+ throw new Error(
68
+ `decryptCapsuleFile: unsupported encrypted-capsule format version ${version} (this build supports versions 1 and 2): ${opts.encPath}`
69
+ );
70
+ }
71
+ const { key, envelopeOffset } = resolveKeyAndOffset(buf, version, opts.memoryDir, "decryptCapsuleFile", opts.encPath);
72
+ const envelope = buf.subarray(envelopeOffset);
73
+ const basename = path.basename(opts.encPath);
74
+ const aad = Buffer.from(basename, "utf-8");
75
+ let plaintext;
76
+ try {
77
+ plaintext = open(key, envelope, { aad });
78
+ } catch (cause) {
79
+ throw new Error(
80
+ `decryptCapsuleFile: authentication failed \u2014 wrong passphrase, tampered archive, or key mismatch. Ensure the secure-store is unlocked with the correct passphrase and the archive has not been modified: ${opts.encPath}`,
81
+ { cause }
82
+ );
83
+ }
84
+ await writeFile(gzPath, plaintext);
85
+ return { gzPath };
86
+ }
87
+ async function decryptCapsuleFileInMemory(encPath, memoryDir) {
88
+ const buf = await readFile(encPath);
89
+ if (buf.length < MIN_ENC_SIZE_V1) {
90
+ throw new Error(
91
+ `decryptCapsuleFileInMemory: file too short to be an encrypted capsule: ${encPath}`
92
+ );
93
+ }
94
+ if (!buf.subarray(0, MAGIC.length).equals(MAGIC)) {
95
+ throw new Error(
96
+ `decryptCapsuleFileInMemory: file does not start with REMNIC-ENC magic: ${encPath}`
97
+ );
98
+ }
99
+ const version = buf.readUInt8(MAGIC.length);
100
+ if (version !== 1 && version !== 2) {
101
+ throw new Error(
102
+ `decryptCapsuleFileInMemory: unsupported encrypted-capsule format version ${version} (this build supports versions 1 and 2): ${encPath}`
103
+ );
104
+ }
105
+ const { key, envelopeOffset } = resolveKeyAndOffset(buf, version, memoryDir, "decryptCapsuleFileInMemory", encPath);
106
+ const envelope = buf.subarray(envelopeOffset);
107
+ const basename = path.basename(encPath);
108
+ const aad = Buffer.from(basename, "utf-8");
109
+ try {
110
+ return open(key, envelope, { aad });
111
+ } catch (cause) {
112
+ throw new Error(
113
+ `decryptCapsuleFileInMemory: authentication failed \u2014 wrong passphrase, tampered archive, or key mismatch. Ensure the secure-store is unlocked with the correct passphrase and the archive has not been modified: ${encPath}`,
114
+ { cause }
115
+ );
116
+ }
117
+ }
118
+ async function loadKdfSection(memoryDir) {
119
+ try {
120
+ const header = await readHeader(memoryDir);
121
+ if (header !== null) {
122
+ const { decodeMetadataSalt } = await import("./metadata-JAGIWHEA.js");
123
+ const salt2 = decodeMetadataSalt(header.metadata);
124
+ const kdf = header.metadata.kdf;
125
+ const json2 = JSON.stringify({
126
+ algorithm: kdf.algorithm,
127
+ params: kdf.params,
128
+ salt: salt2.toString("hex")
129
+ });
130
+ return { json: json2, salt: salt2 };
131
+ }
132
+ } catch {
133
+ }
134
+ const { generateSalt } = await import("./cipher-VHAFCG7Z.js");
135
+ const salt = generateSalt();
136
+ const { DEFAULT_ARGON2ID_PARAMS } = await import("./kdf-H5B23ZM2.js");
137
+ const json = JSON.stringify({
138
+ algorithm: "argon2id",
139
+ params: DEFAULT_ARGON2ID_PARAMS,
140
+ salt: salt.toString("hex")
141
+ });
142
+ return { json, salt };
143
+ }
144
+ function getKeyOrThrow(memoryDir, action) {
145
+ const storeId = secureStoreDir(memoryDir);
146
+ const key = getKey(storeId);
147
+ if (key === null) {
148
+ throw new Error(
149
+ `Secure-store is locked or not initialized \u2014 cannot ${action}. Run \`remnic secure-store unlock\` first, or \`remnic secure-store init\` if the store has never been initialized.`
150
+ );
151
+ }
152
+ return key;
153
+ }
154
+ function resolveKeyAndOffset(buf, version, memoryDir, caller, encPath) {
155
+ if (version === 1) {
156
+ const key2 = getKeyOrThrow(memoryDir, "decrypt capsule");
157
+ return { key: key2, envelopeOffset: MAGIC.length + 1 };
158
+ }
159
+ const kdfLenOffset = MAGIC.length + 1;
160
+ if (buf.length < kdfLenOffset + 2) {
161
+ throw new Error(
162
+ `${caller}: file too short for format v2 KDF length field: ${encPath}`
163
+ );
164
+ }
165
+ const kdfLen = buf.readUInt16LE(kdfLenOffset);
166
+ const kdfJsonOffset = kdfLenOffset + 2;
167
+ if (buf.length < kdfJsonOffset + kdfLen) {
168
+ throw new Error(
169
+ `${caller}: file too short for format v2 KDF params section (expected ${kdfLen} bytes): ${encPath}`
170
+ );
171
+ }
172
+ const envelopeOffset = kdfJsonOffset + kdfLen;
173
+ const key = getKeyOrThrow(memoryDir, "decrypt capsule");
174
+ return { key, envelopeOffset };
175
+ }
176
+
177
+ export {
178
+ isEncryptedCapsuleFile,
179
+ encryptCapsuleFile,
180
+ decryptCapsuleFile,
181
+ decryptCapsuleFileInMemory
182
+ };
@@ -1,12 +1,14 @@
1
1
  import {
2
- assertIsoRecordedAt,
3
- assertString,
4
2
  countRecallTokenOverlap,
5
- isRecord,
6
3
  normalizeRecallTokens,
7
- recordStoreDay,
8
4
  topicOverlapScore
9
- } from "./chunk-YHH3SXKD.js";
5
+ } from "./chunk-WPINX4MF.js";
6
+ import {
7
+ assertIsoRecordedAt,
8
+ assertString,
9
+ isRecord,
10
+ recordStoreDay
11
+ } from "./chunk-3G7FAF6S.js";
10
12
  import {
11
13
  listJsonFiles,
12
14
  readJsonFile
@@ -1,18 +1,18 @@
1
- import {
2
- readEnvVar,
3
- resolveHomeDir
4
- } from "./chunk-7TENHBV2.js";
5
- import {
6
- StorageManager,
7
- isConsolidationOperator
8
- } from "./chunk-JJSNPSCD.js";
9
1
  import {
10
2
  countRecallTokenOverlap,
11
3
  normalizeRecallTokens
12
- } from "./chunk-YHH3SXKD.js";
4
+ } from "./chunk-WPINX4MF.js";
5
+ import {
6
+ StorageManager,
7
+ isSemanticConsolidationLlmOperator
8
+ } from "./chunk-7UZNLMW5.js";
13
9
  import {
14
10
  log
15
11
  } from "./chunk-UFU5GGGA.js";
12
+ import {
13
+ readEnvVar,
14
+ resolveHomeDir
15
+ } from "./chunk-I6B2W2IY.js";
16
16
 
17
17
  // ../remnic-core/src/connectors/codex-materialize-runner.ts
18
18
  import path2 from "path";
@@ -990,7 +990,7 @@ function parseOperatorAwareConsolidationResponse(response, cluster) {
990
990
  const obj = parsed;
991
991
  const rawOperator = typeof obj.operator === "string" ? obj.operator.trim().toLowerCase() : "";
992
992
  const rawOutput = typeof obj.output === "string" ? obj.output : "";
993
- const operator = isConsolidationOperator(rawOperator) ? rawOperator : chooseConsolidationOperator(cluster);
993
+ const operator = isSemanticConsolidationLlmOperator(rawOperator) ? rawOperator : chooseConsolidationOperator(cluster);
994
994
  const output = rawOutput.trim().length > 0 ? rawOutput.trim() : response.trim();
995
995
  return { operator, output };
996
996
  }