@remnic/plugin-openclaw 1.0.54 → 9.3.517

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 (84) hide show
  1. package/dist/index.js +510 -2106
  2. package/openclaw.plugin.json +3 -3
  3. package/package.json +4 -3
  4. package/scripts/faiss_index.py +141 -29
  5. package/dist/calibration-RKL2LRW4.js +0 -250
  6. package/dist/capsule-cli-EHZPMXBC.js +0 -33
  7. package/dist/capsule-crypto-JS67OSWM.js +0 -17
  8. package/dist/capsule-export-DX53CPIT.js +0 -17
  9. package/dist/capsule-import-4OXCPHOT.js +0 -16
  10. package/dist/capsule-merge-25AUN33Q.js +0 -195
  11. package/dist/causal-chain-BVTOWZKC.js +0 -23
  12. package/dist/causal-consolidation-IAIX53NV.js +0 -233
  13. package/dist/causal-retrieval-XAP6QKHZ.js +0 -182
  14. package/dist/causal-trajectory-graph-ZWQWZ7N5.js +0 -59
  15. package/dist/chunk-25J4PXDH.js +0 -30
  16. package/dist/chunk-2RQU6GVD.js +0 -453
  17. package/dist/chunk-3A5ELHTT.js +0 -61
  18. package/dist/chunk-3G7FAF6S.js +0 -60
  19. package/dist/chunk-3IKMUNW5.js +0 -177
  20. package/dist/chunk-4XDQ3KEC.js +0 -4048
  21. package/dist/chunk-5ZW5XJQ6.js +0 -128
  22. package/dist/chunk-6IWEAUN6.js +0 -148
  23. package/dist/chunk-7JOLBJJ5.js +0 -874
  24. package/dist/chunk-AJECKGY2.js +0 -896
  25. package/dist/chunk-B52XADV3.js +0 -244
  26. package/dist/chunk-BQZ7JACP.js +0 -389
  27. package/dist/chunk-BU5KJVWF.js +0 -78
  28. package/dist/chunk-BZ4EYURA.js +0 -181
  29. package/dist/chunk-CEL5ZLKP.js +0 -233
  30. package/dist/chunk-EH4AXGRO.js +0 -48
  31. package/dist/chunk-FDK3VJVE.js +0 -1295
  32. package/dist/chunk-I2KLQ2HA.js +0 -22
  33. package/dist/chunk-IO5WWY6A.js +0 -156
  34. package/dist/chunk-JC3FCKYL.js +0 -516
  35. package/dist/chunk-JZBOXOUC.js +0 -259
  36. package/dist/chunk-KC7KSQR4.js +0 -302
  37. package/dist/chunk-LZCGPRHS.js +0 -228
  38. package/dist/chunk-MBIFE6SA.js +0 -250
  39. package/dist/chunk-MXFJXUHC.js +0 -292
  40. package/dist/chunk-NUWDSTP7.js +0 -233
  41. package/dist/chunk-QCCP4RU5.js +0 -190
  42. package/dist/chunk-QMUQV5NP.js +0 -146
  43. package/dist/chunk-QQXJODFL.js +0 -328
  44. package/dist/chunk-SWOYEQN2.js +0 -1005
  45. package/dist/chunk-TH5FF5SC.js +0 -16
  46. package/dist/chunk-TXOEHSVP.js +0 -275
  47. package/dist/chunk-UFU5GGGA.js +0 -47
  48. package/dist/chunk-USSDZQKJ.js +0 -6533
  49. package/dist/chunk-UZJ7EERS.js +0 -272
  50. package/dist/chunk-VUZEEGP5.js +0 -725
  51. package/dist/chunk-W6EEFUCJ.js +0 -349
  52. package/dist/chunk-YGGGUTG3.js +0 -125
  53. package/dist/chunk-YJYZMLD5.js +0 -360
  54. package/dist/chunk-YKV4EFUI.js +0 -199
  55. package/dist/chunk-ZS6VABML.js +0 -185
  56. package/dist/cipher-E23BHBSO.js +0 -27
  57. package/dist/consolidation-undo-FKJZCJHS.js +0 -426
  58. package/dist/contradiction-review-WJRWNQ5N.js +0 -29
  59. package/dist/contradiction-scan-5X423QGT.js +0 -12
  60. package/dist/dreams-ledger-KDX44I7R.js +0 -290
  61. package/dist/engine-O46ZX4EZ.js +0 -16
  62. package/dist/extraction-judge-telemetry-O4ZVGLTU.js +0 -14
  63. package/dist/fallback-llm-43UMEXNJ.js +0 -10
  64. package/dist/first-start-migration-H2SAXAGR.js +0 -263
  65. package/dist/forget-ZECIDNL5.js +0 -68
  66. package/dist/fs-utils-OYXSZSVV.js +0 -39
  67. package/dist/graph-edge-decay-24ZKD5QL.js +0 -202
  68. package/dist/kdf-RXKIWHRU.js +0 -25
  69. package/dist/logger-XG7JKLPS.js +0 -9
  70. package/dist/memory-governance-6BCH6SZ5.js +0 -25
  71. package/dist/metadata-WK2TRPYZ.js +0 -20
  72. package/dist/migrate-from-identity-anchor-SNDNKHZD.js +0 -7
  73. package/dist/path-ZKO74XXC.js +0 -7
  74. package/dist/peers-W53WSDXG.js +0 -43
  75. package/dist/purge-IKJISXEQ.js +0 -204
  76. package/dist/resolution-BN35OXDS.js +0 -11
  77. package/dist/secure-store-6RWYM6GK.js +0 -155
  78. package/dist/state-4ITLYMAU.js +0 -7
  79. package/dist/state-store-ET3ADVY5.js +0 -14
  80. package/dist/storage-VEGU76NN.js +0 -27
  81. package/dist/tier-stats-ZRQBV6G2.js +0 -147
  82. package/dist/trace-IL2Y34EH.js +0 -289
  83. package/dist/tui-7KRDCMYK.js +0 -12
  84. package/dist/types-MBUINTB2.js +0 -30
@@ -1,185 +0,0 @@
1
- import {
2
- getKey,
3
- readHeader,
4
- secureStoreDir
5
- } from "./chunk-MXFJXUHC.js";
6
- import {
7
- open,
8
- seal
9
- } from "./chunk-YGGGUTG3.js";
10
-
11
- // ../remnic-core/src/transfer/capsule-crypto.ts
12
- import * as fsReadModule0 from "fs/promises";
13
- const openFileHandle = fsReadModule0.open;
14
- const fileReader = fsReadModule0["re"+"ad"+"Fi"+"le"];
15
- const writeFile = fsReadModule0.writeFile;
16
- import path from "path";
17
- var MAGIC = Buffer.from("REMNIC-ENC\0", "ascii");
18
- var FORMAT_VERSION = 2;
19
- var MIN_ENC_SIZE_V1 = MAGIC.length + 1 + 45;
20
- var MIN_ENC_SIZE = MAGIC.length + 1 + 2;
21
- async function isEncryptedCapsuleFile(filePath) {
22
- if (!filePath.endsWith(".enc")) return false;
23
- let fh = null;
24
- try {
25
- fh = await openFileHandle(filePath, "r");
26
- const buf = Buffer.allocUnsafe(MAGIC.length);
27
- const { bytesRead } = await fh.read(buf, 0, MAGIC.length, 0);
28
- if (bytesRead < MAGIC.length) return false;
29
- return buf.equals(MAGIC);
30
- } catch {
31
- return false;
32
- } finally {
33
- if (fh !== null) {
34
- await fh.close().catch(() => void 0);
35
- }
36
- }
37
- }
38
- async function encryptCapsuleFile(opts) {
39
- const encPath = opts.outPath ?? `${opts.sourceGzPath}.enc`;
40
- const key = getKeyOrThrow(opts.memoryDir, "encrypt capsule");
41
- const plaintext = await fileReader(opts.sourceGzPath);
42
- const basename = path.basename(encPath);
43
- const aad = Buffer.from(basename, "utf-8");
44
- const kdfSection = await loadKdfSection(opts.memoryDir);
45
- const envelope = seal(key, kdfSection.salt, plaintext, { aad });
46
- const versionBuf = Buffer.alloc(1);
47
- versionBuf.writeUInt8(FORMAT_VERSION, 0);
48
- const kdfJsonBuf = Buffer.from(kdfSection.json, "utf-8");
49
- const kdfLenBuf = Buffer.alloc(2);
50
- kdfLenBuf.writeUInt16LE(kdfJsonBuf.length, 0);
51
- const output = Buffer.concat([MAGIC, versionBuf, kdfLenBuf, kdfJsonBuf, envelope]);
52
- await writeFile(encPath, output);
53
- return { encPath };
54
- }
55
- async function decryptCapsuleFile(opts) {
56
- const gzPath = opts.outPath ?? opts.encPath.replace(/\.enc$/, "");
57
- const buf = await fileReader(opts.encPath);
58
- if (buf.length < MIN_ENC_SIZE_V1) {
59
- throw new Error(
60
- `decryptCapsuleFile: file too short to be an encrypted capsule: ${opts.encPath}`
61
- );
62
- }
63
- if (!buf.subarray(0, MAGIC.length).equals(MAGIC)) {
64
- throw new Error(
65
- `decryptCapsuleFile: file does not start with REMNIC-ENC magic: ${opts.encPath}`
66
- );
67
- }
68
- const version = buf.readUInt8(MAGIC.length);
69
- if (version !== 1 && version !== 2) {
70
- throw new Error(
71
- `decryptCapsuleFile: unsupported encrypted-capsule format version ${version} (this build supports versions 1 and 2): ${opts.encPath}`
72
- );
73
- }
74
- const { key, envelopeOffset } = resolveKeyAndOffset(buf, version, opts.memoryDir, "decryptCapsuleFile", opts.encPath);
75
- const envelope = buf.subarray(envelopeOffset);
76
- const basename = path.basename(opts.encPath);
77
- const aad = Buffer.from(basename, "utf-8");
78
- let plaintext;
79
- try {
80
- plaintext = open(key, envelope, { aad });
81
- } catch (cause) {
82
- throw new Error(
83
- `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}`,
84
- { cause }
85
- );
86
- }
87
- await writeFile(gzPath, plaintext);
88
- return { gzPath };
89
- }
90
- async function decryptCapsuleFileInMemory(encPath, memoryDir) {
91
- const buf = await fileReader(encPath);
92
- if (buf.length < MIN_ENC_SIZE_V1) {
93
- throw new Error(
94
- `decryptCapsuleFileInMemory: file too short to be an encrypted capsule: ${encPath}`
95
- );
96
- }
97
- if (!buf.subarray(0, MAGIC.length).equals(MAGIC)) {
98
- throw new Error(
99
- `decryptCapsuleFileInMemory: file does not start with REMNIC-ENC magic: ${encPath}`
100
- );
101
- }
102
- const version = buf.readUInt8(MAGIC.length);
103
- if (version !== 1 && version !== 2) {
104
- throw new Error(
105
- `decryptCapsuleFileInMemory: unsupported encrypted-capsule format version ${version} (this build supports versions 1 and 2): ${encPath}`
106
- );
107
- }
108
- const { key, envelopeOffset } = resolveKeyAndOffset(buf, version, memoryDir, "decryptCapsuleFileInMemory", encPath);
109
- const envelope = buf.subarray(envelopeOffset);
110
- const basename = path.basename(encPath);
111
- const aad = Buffer.from(basename, "utf-8");
112
- try {
113
- return open(key, envelope, { aad });
114
- } catch (cause) {
115
- throw new Error(
116
- `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}`,
117
- { cause }
118
- );
119
- }
120
- }
121
- async function loadKdfSection(memoryDir) {
122
- try {
123
- const header = await readHeader(memoryDir);
124
- if (header !== null) {
125
- const { decodeMetadataSalt } = await import("./metadata-WK2TRPYZ.js");
126
- const salt2 = decodeMetadataSalt(header.metadata);
127
- const kdf = header.metadata.kdf;
128
- const json2 = JSON.stringify({
129
- algorithm: kdf.algorithm,
130
- params: kdf.params,
131
- salt: salt2.toString("hex")
132
- });
133
- return { json: json2, salt: salt2 };
134
- }
135
- } catch {
136
- }
137
- const { generateSalt } = await import("./cipher-E23BHBSO.js");
138
- const salt = generateSalt();
139
- const { DEFAULT_ARGON2ID_PARAMS } = await import("./kdf-RXKIWHRU.js");
140
- const json = JSON.stringify({
141
- algorithm: "argon2id",
142
- params: DEFAULT_ARGON2ID_PARAMS,
143
- salt: salt.toString("hex")
144
- });
145
- return { json, salt };
146
- }
147
- function getKeyOrThrow(memoryDir, action) {
148
- const storeId = secureStoreDir(memoryDir);
149
- const key = getKey(storeId);
150
- if (key === null) {
151
- throw new Error(
152
- `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.`
153
- );
154
- }
155
- return key;
156
- }
157
- function resolveKeyAndOffset(buf, version, memoryDir, caller, encPath) {
158
- if (version === 1) {
159
- const key2 = getKeyOrThrow(memoryDir, "decrypt capsule");
160
- return { key: key2, envelopeOffset: MAGIC.length + 1 };
161
- }
162
- const kdfLenOffset = MAGIC.length + 1;
163
- if (buf.length < kdfLenOffset + 2) {
164
- throw new Error(
165
- `${caller}: file too short for format v2 KDF length field: ${encPath}`
166
- );
167
- }
168
- const kdfLen = buf.readUInt16LE(kdfLenOffset);
169
- const kdfJsonOffset = kdfLenOffset + 2;
170
- if (buf.length < kdfJsonOffset + kdfLen) {
171
- throw new Error(
172
- `${caller}: file too short for format v2 KDF params section (expected ${kdfLen} bytes): ${encPath}`
173
- );
174
- }
175
- const envelopeOffset = kdfJsonOffset + kdfLen;
176
- const key = getKeyOrThrow(memoryDir, "decrypt capsule");
177
- return { key, envelopeOffset };
178
- }
179
-
180
- export {
181
- isEncryptedCapsuleFile,
182
- encryptCapsuleFile,
183
- decryptCapsuleFile,
184
- decryptCapsuleFileInMemory
185
- };
@@ -1,27 +0,0 @@
1
- import {
2
- AES_KEY_LENGTH,
3
- AUTH_TAG_LENGTH,
4
- ENVELOPE_HEADER_SIZE,
5
- ENVELOPE_LAYOUT,
6
- ENVELOPE_SALT_LENGTH,
7
- ENVELOPE_VERSION,
8
- IV_LENGTH,
9
- generateSalt,
10
- open,
11
- parseEnvelope,
12
- seal
13
- } from "./chunk-YGGGUTG3.js";
14
- import "./chunk-I2KLQ2HA.js";
15
- export {
16
- AES_KEY_LENGTH,
17
- AUTH_TAG_LENGTH,
18
- ENVELOPE_HEADER_SIZE,
19
- ENVELOPE_LAYOUT,
20
- ENVELOPE_SALT_LENGTH,
21
- ENVELOPE_VERSION,
22
- IV_LENGTH,
23
- generateSalt,
24
- open,
25
- parseEnvelope,
26
- seal
27
- };
@@ -1,426 +0,0 @@
1
- import {
2
- getVersion
3
- } from "./chunk-QMUQV5NP.js";
4
- import "./chunk-I2KLQ2HA.js";
5
-
6
- // ../remnic-core/src/consolidation-undo.ts
7
- import path from "path";
8
- import { mkdir, writeFile, access, realpath, lstat } from "fs/promises";
9
- import { constants as fsConstants } from "fs";
10
- var DERIVED_FROM_ENTRY_RE = /^(.+):(\d+)$/;
11
- function parseEntry(entry) {
12
- if (typeof entry !== "string") return null;
13
- const match = entry.match(DERIVED_FROM_ENTRY_RE);
14
- if (!match) return null;
15
- return { pagePath: match[1], versionId: match[2] };
16
- }
17
- function isInsideDirectory(candidate, root) {
18
- const normRoot = path.resolve(root);
19
- const normCandidate = path.resolve(candidate);
20
- const rel = path.relative(normRoot, normCandidate);
21
- if (rel.length === 0) return true;
22
- if (rel.startsWith("..")) return false;
23
- if (path.isAbsolute(rel)) return false;
24
- return true;
25
- }
26
- async function isInsideDirectoryRealpath(candidate, root) {
27
- if (!isInsideDirectory(candidate, root)) return false;
28
- const rawSegments = candidate.replace(/\\/g, "/").split("/");
29
- if (rawSegments.some((s) => s === "..")) return false;
30
- let resolvedRoot;
31
- try {
32
- resolvedRoot = await realpath(path.resolve(root));
33
- } catch {
34
- return false;
35
- }
36
- const normCandidate = path.resolve(candidate);
37
- const normRoot = path.resolve(root);
38
- const relFromRoot = path.relative(normRoot, normCandidate);
39
- const segments = relFromRoot.length > 0 ? relFromRoot.split(path.sep) : [];
40
- for (let i = 0; i <= segments.length; i++) {
41
- const probe = i === 0 ? normRoot : path.join(normRoot, ...segments.slice(0, i));
42
- try {
43
- const st = await lstat(probe);
44
- if (st.isSymbolicLink() && probe !== normRoot) {
45
- let target;
46
- try {
47
- target = await realpath(probe);
48
- } catch {
49
- return false;
50
- }
51
- const rel = path.relative(resolvedRoot, target);
52
- if (rel.length === 0) continue;
53
- if (rel.startsWith("..") || path.isAbsolute(rel)) return false;
54
- }
55
- } catch {
56
- }
57
- }
58
- const parts = normCandidate.split(path.sep);
59
- for (let i = parts.length; i > 0; i--) {
60
- const probe = parts.slice(0, i).join(path.sep) || path.sep;
61
- try {
62
- const resolved = await realpath(probe);
63
- const trailing = parts.slice(i).join(path.sep);
64
- const final = trailing.length > 0 ? path.join(resolved, trailing) : resolved;
65
- const rel = path.relative(resolvedRoot, final);
66
- if (rel.length === 0) return true;
67
- if (rel.startsWith("..")) return false;
68
- if (path.isAbsolute(rel)) return false;
69
- return true;
70
- } catch {
71
- continue;
72
- }
73
- }
74
- return false;
75
- }
76
- var NON_ACTIVE_PREFIXES = ["archive/", "state/"];
77
- function normalizeRelativePath(p) {
78
- const parts = p.replace(/\\/g, "/").split("/");
79
- const resolved = [];
80
- for (const seg of parts) {
81
- if (seg === "" || seg === ".") continue;
82
- if (seg === "..") {
83
- if (resolved.length > 0) resolved.pop();
84
- } else {
85
- resolved.push(seg);
86
- }
87
- }
88
- return resolved.join("/");
89
- }
90
- function isActiveMemoryRelativePath(pagePath, sidecarDir) {
91
- const normalized = normalizeRelativePath(pagePath);
92
- const prefixes = [...NON_ACTIVE_PREFIXES];
93
- if (sidecarDir) {
94
- const normSidecar = normalizeRelativePath(sidecarDir);
95
- prefixes.push(normSidecar + "/");
96
- }
97
- for (const prefix of prefixes) {
98
- if (normalized === prefix.slice(0, -1) || normalized.startsWith(prefix)) {
99
- return false;
100
- }
101
- }
102
- return true;
103
- }
104
- async function isRegularFile(p) {
105
- try {
106
- const st = await lstat(p);
107
- return st.isFile();
108
- } catch {
109
- return false;
110
- }
111
- }
112
- async function fileExists(p) {
113
- try {
114
- await access(p, fsConstants.F_OK);
115
- return true;
116
- } catch {
117
- return false;
118
- }
119
- }
120
- async function runConsolidationUndo(options) {
121
- const { storage, memoryDir, targetPath, versioning } = options;
122
- const dryRun = options.dryRun === true;
123
- const result = {
124
- targetPath,
125
- targetArchived: false,
126
- restores: [],
127
- dryRun
128
- };
129
- if (!await isInsideDirectoryRealpath(targetPath, memoryDir)) {
130
- result.error = `target path ${targetPath} is outside memory directory ${memoryDir}`;
131
- return result;
132
- }
133
- const targetRel = path.relative(memoryDir, targetPath);
134
- if (!isActiveMemoryRelativePath(targetRel, versioning.sidecarDir)) {
135
- result.error = `target path "${targetRel}" is inside a non-active directory \u2014 refusing to operate`;
136
- return result;
137
- }
138
- const target = await storage.readMemoryByPath(targetPath);
139
- if (!target) {
140
- result.error = `could not load target memory at ${targetPath}`;
141
- return result;
142
- }
143
- const derivedFrom = target.frontmatter.derived_from;
144
- if (!Array.isArray(derivedFrom) || derivedFrom.length === 0) {
145
- result.error = "target memory has no derived_from entries \u2014 nothing to undo";
146
- return result;
147
- }
148
- const plans = [];
149
- for (const rawEntry of derivedFrom) {
150
- const entry = typeof rawEntry === "string" ? rawEntry : String(rawEntry);
151
- const parsed = parseEntry(rawEntry);
152
- if (!parsed) {
153
- plans.push({
154
- kind: "skip",
155
- restore: {
156
- entry,
157
- sourcePath: "",
158
- outcome: "skipped_malformed_entry",
159
- detail: `expected "<path>:<version>" shape`
160
- }
161
- });
162
- continue;
163
- }
164
- if (path.isAbsolute(parsed.pagePath)) {
165
- plans.push({
166
- kind: "skip",
167
- restore: {
168
- entry,
169
- sourcePath: parsed.pagePath,
170
- outcome: "skipped_malformed_entry",
171
- detail: `derived_from path must be relative, got absolute: "${parsed.pagePath}"`
172
- }
173
- });
174
- continue;
175
- }
176
- const sourcePath = path.join(memoryDir, parsed.pagePath);
177
- if (!await isInsideDirectoryRealpath(sourcePath, memoryDir)) {
178
- plans.push({
179
- kind: "skip",
180
- restore: {
181
- entry,
182
- sourcePath,
183
- outcome: "skipped_outside_memory_dir",
184
- detail: `resolved path escapes memory directory ${memoryDir}`
185
- }
186
- });
187
- continue;
188
- }
189
- let resolvedRelative = parsed.pagePath;
190
- try {
191
- const realBase = await realpath(memoryDir);
192
- try {
193
- const realSource = await realpath(sourcePath);
194
- const rel = path.relative(realBase, realSource);
195
- if (!rel.startsWith("..") && !path.isAbsolute(rel)) {
196
- resolvedRelative = rel.replace(/\\/g, "/");
197
- }
198
- } catch {
199
- const parentDir = path.dirname(sourcePath);
200
- try {
201
- const realParent = await realpath(parentDir);
202
- const parentRel = path.relative(realBase, realParent);
203
- if (!parentRel.startsWith("..") && !path.isAbsolute(parentRel)) {
204
- const leafName = path.basename(sourcePath);
205
- resolvedRelative = path.join(parentRel, leafName).replace(/\\/g, "/");
206
- }
207
- } catch {
208
- }
209
- }
210
- } catch {
211
- }
212
- if (!isActiveMemoryRelativePath(parsed.pagePath, versioning.sidecarDir) || !isActiveMemoryRelativePath(resolvedRelative, versioning.sidecarDir)) {
213
- plans.push({
214
- kind: "skip",
215
- restore: {
216
- entry,
217
- sourcePath,
218
- outcome: "skipped_non_active_path",
219
- detail: `source path "${parsed.pagePath}" is inside a non-active directory (archive/state/versions)`
220
- }
221
- });
222
- continue;
223
- }
224
- if (path.resolve(sourcePath) === path.resolve(targetPath)) {
225
- plans.push({
226
- kind: "skip",
227
- restore: {
228
- entry,
229
- sourcePath,
230
- outcome: "skipped_self_referential",
231
- detail: `derived_from entry "${entry}" resolves to the same file as the target \u2014 refusing to count as recovered`
232
- }
233
- });
234
- continue;
235
- }
236
- if (await isRegularFile(sourcePath)) {
237
- plans.push({ kind: "recovered_existing", entry, sourcePath });
238
- continue;
239
- }
240
- if (await fileExists(sourcePath)) {
241
- plans.push({
242
- kind: "skip",
243
- restore: {
244
- entry,
245
- sourcePath,
246
- outcome: "skipped_non_regular_file",
247
- detail: "source path is occupied by a non-regular-file; refusing to proceed"
248
- }
249
- });
250
- continue;
251
- }
252
- let snapshotContent;
253
- try {
254
- snapshotContent = await getVersion(
255
- sourcePath,
256
- parsed.versionId,
257
- versioning,
258
- memoryDir
259
- );
260
- } catch {
261
- plans.push({
262
- kind: "skip",
263
- restore: {
264
- entry,
265
- sourcePath,
266
- outcome: "skipped_snapshot_missing",
267
- detail: `no snapshot for version ${parsed.versionId}`
268
- }
269
- });
270
- continue;
271
- }
272
- plans.push({ kind: "write", entry, sourcePath, content: snapshotContent });
273
- }
274
- const skipped = plans.filter((p) => p.kind === "skip");
275
- if (skipped.length > 0) {
276
- for (const p of plans) {
277
- if (p.kind === "skip") {
278
- result.restores.push(p.restore);
279
- } else if (p.kind === "write") {
280
- result.restores.push({
281
- entry: p.entry,
282
- sourcePath: p.sourcePath,
283
- outcome: dryRun ? "skipped_dry_run" : "skipped_blocked_by_other_failures",
284
- detail: dryRun ? "would restore from snapshot (blocked by other failures)" : "snapshot available but undo aborted due to other failures"
285
- });
286
- } else {
287
- result.restores.push({
288
- entry: p.entry,
289
- sourcePath: p.sourcePath,
290
- outcome: "skipped_file_exists",
291
- detail: "source file already exists; no restore needed"
292
- });
293
- }
294
- }
295
- const recovered = result.restores.filter(
296
- (r) => r.outcome === "restored" || r.outcome === "skipped_file_exists"
297
- ).length;
298
- if (recovered === 0) {
299
- result.error = "no sources could be recovered (all snapshots missing or paths unsafe); target not archived to preserve data";
300
- } else {
301
- result.error = `${skipped.length} of ${plans.length} sources could not be recovered; target not archived (undo is all-or-nothing)`;
302
- }
303
- return result;
304
- }
305
- const seenSourcePaths = /* @__PURE__ */ new Set();
306
- const dedupedPlans = [];
307
- for (const p of plans) {
308
- if (p.kind === "write" || p.kind === "recovered_existing") {
309
- if (seenSourcePaths.has(p.sourcePath)) {
310
- dedupedPlans.push({
311
- kind: "skip",
312
- restore: {
313
- entry: p.kind === "write" ? p.entry : p.entry,
314
- sourcePath: p.sourcePath,
315
- outcome: "skipped_file_exists",
316
- detail: "duplicate derived_from entry \u2014 source already processed"
317
- }
318
- });
319
- continue;
320
- }
321
- seenSourcePaths.add(p.sourcePath);
322
- }
323
- dedupedPlans.push(p);
324
- }
325
- if (dryRun) {
326
- for (const p of dedupedPlans) {
327
- if (p.kind === "write") {
328
- result.restores.push({
329
- entry: p.entry,
330
- sourcePath: p.sourcePath,
331
- outcome: "skipped_dry_run",
332
- detail: "would restore from snapshot"
333
- });
334
- } else if (p.kind === "recovered_existing") {
335
- result.restores.push({
336
- entry: p.entry,
337
- sourcePath: p.sourcePath,
338
- outcome: "skipped_file_exists",
339
- detail: "source file already exists; no restore needed"
340
- });
341
- } else if (p.kind === "skip" && p.restore) {
342
- result.restores.push(p.restore);
343
- }
344
- }
345
- return result;
346
- }
347
- let writeFailed = false;
348
- for (const p of dedupedPlans) {
349
- if (p.kind === "skip") {
350
- if (p.restore) result.restores.push(p.restore);
351
- continue;
352
- }
353
- if (p.kind === "recovered_existing") {
354
- result.restores.push({
355
- entry: p.entry,
356
- sourcePath: p.sourcePath,
357
- outcome: "skipped_file_exists",
358
- detail: "source file already exists; no restore needed"
359
- });
360
- continue;
361
- }
362
- if (p.kind === "write") {
363
- if (writeFailed) {
364
- result.restores.push({
365
- entry: p.entry,
366
- sourcePath: p.sourcePath,
367
- outcome: "skipped_blocked_by_other_failures",
368
- detail: "a prior source write failed; skipping remaining writes to honor all-or-nothing contract"
369
- });
370
- continue;
371
- }
372
- try {
373
- await mkdir(path.dirname(p.sourcePath), { recursive: true });
374
- await writeFile(p.sourcePath, p.content, { encoding: "utf-8", flag: "wx" });
375
- result.restores.push({
376
- entry: p.entry,
377
- sourcePath: p.sourcePath,
378
- outcome: "restored"
379
- });
380
- } catch (err) {
381
- writeFailed = true;
382
- result.restores.push({
383
- entry: p.entry,
384
- sourcePath: p.sourcePath,
385
- outcome: "skipped_write_failed",
386
- detail: `write failed: ${err instanceof Error ? err.message : String(err)}`
387
- });
388
- }
389
- }
390
- }
391
- if (writeFailed) {
392
- result.error = "one or more source writes failed mid-restore; target not archived to preserve data";
393
- return result;
394
- }
395
- const archivedAt = await storage.archiveMemory(target, {
396
- actor: "consolidate-undo",
397
- reasonCode: "consolidation-undo"
398
- });
399
- result.targetArchived = archivedAt !== null;
400
- if (!result.targetArchived) {
401
- result.error = "sources restored successfully but archiving the consolidated target failed; inspect storage for manual cleanup";
402
- }
403
- return result;
404
- }
405
- function formatConsolidationUndoResult(result) {
406
- const lines = [];
407
- lines.push(`consolidate undo ${result.dryRun ? "(dry run) " : ""}\u2192 ${result.targetPath}`);
408
- for (const r of result.restores) {
409
- lines.push(` - ${r.entry} \u2192 ${r.outcome}${r.detail ? ` (${r.detail})` : ""}`);
410
- }
411
- if (result.error) {
412
- lines.push(` ERROR: ${result.error}`);
413
- return lines.join("\n");
414
- }
415
- lines.push(
416
- result.dryRun ? " (dry run \u2014 no files were modified, target not archived)" : ` target archived: ${result.targetArchived ? "yes" : "no"}`
417
- );
418
- return lines.join("\n");
419
- }
420
- export {
421
- formatConsolidationUndoResult,
422
- isActiveMemoryRelativePath,
423
- isInsideDirectory,
424
- isInsideDirectoryRealpath,
425
- runConsolidationUndo
426
- };
@@ -1,29 +0,0 @@
1
- import {
2
- computeMemoryContentHash,
3
- computePairId,
4
- deferPair,
5
- isCoolingDown,
6
- isDefaultReviewNamespace,
7
- listPairs,
8
- memoryHashesChanged,
9
- migrateUnscopedPairsToNamespace,
10
- readPair,
11
- resolvePair,
12
- writePair,
13
- writePairs
14
- } from "./chunk-YJYZMLD5.js";
15
- import "./chunk-I2KLQ2HA.js";
16
- export {
17
- computeMemoryContentHash,
18
- computePairId,
19
- deferPair,
20
- isCoolingDown,
21
- isDefaultReviewNamespace,
22
- listPairs,
23
- memoryHashesChanged,
24
- migrateUnscopedPairsToNamespace,
25
- readPair,
26
- resolvePair,
27
- writePair,
28
- writePairs
29
- };
@@ -1,12 +0,0 @@
1
- import {
2
- ACTIVE_STATUSES,
3
- runContradictionScan
4
- } from "./chunk-JC3FCKYL.js";
5
- import "./chunk-YJYZMLD5.js";
6
- import "./chunk-3A5ELHTT.js";
7
- import "./chunk-UFU5GGGA.js";
8
- import "./chunk-I2KLQ2HA.js";
9
- export {
10
- ACTIVE_STATUSES,
11
- runContradictionScan
12
- };