@remnic/plugin-openclaw 1.0.54 → 9.3.515
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +510 -2106
- package/openclaw.plugin.json +3 -3
- package/package.json +4 -3
- package/scripts/faiss_index.py +141 -29
- package/dist/calibration-RKL2LRW4.js +0 -250
- package/dist/capsule-cli-EHZPMXBC.js +0 -33
- package/dist/capsule-crypto-JS67OSWM.js +0 -17
- package/dist/capsule-export-DX53CPIT.js +0 -17
- package/dist/capsule-import-4OXCPHOT.js +0 -16
- package/dist/capsule-merge-25AUN33Q.js +0 -195
- package/dist/causal-chain-BVTOWZKC.js +0 -23
- package/dist/causal-consolidation-IAIX53NV.js +0 -233
- package/dist/causal-retrieval-XAP6QKHZ.js +0 -182
- package/dist/causal-trajectory-graph-ZWQWZ7N5.js +0 -59
- package/dist/chunk-25J4PXDH.js +0 -30
- package/dist/chunk-2RQU6GVD.js +0 -453
- package/dist/chunk-3A5ELHTT.js +0 -61
- package/dist/chunk-3G7FAF6S.js +0 -60
- package/dist/chunk-3IKMUNW5.js +0 -177
- package/dist/chunk-4XDQ3KEC.js +0 -4048
- package/dist/chunk-5ZW5XJQ6.js +0 -128
- package/dist/chunk-6IWEAUN6.js +0 -148
- package/dist/chunk-7JOLBJJ5.js +0 -874
- package/dist/chunk-AJECKGY2.js +0 -896
- package/dist/chunk-B52XADV3.js +0 -244
- package/dist/chunk-BQZ7JACP.js +0 -389
- package/dist/chunk-BU5KJVWF.js +0 -78
- package/dist/chunk-BZ4EYURA.js +0 -181
- package/dist/chunk-CEL5ZLKP.js +0 -233
- package/dist/chunk-EH4AXGRO.js +0 -48
- package/dist/chunk-FDK3VJVE.js +0 -1295
- package/dist/chunk-I2KLQ2HA.js +0 -22
- package/dist/chunk-IO5WWY6A.js +0 -156
- package/dist/chunk-JC3FCKYL.js +0 -516
- package/dist/chunk-JZBOXOUC.js +0 -259
- package/dist/chunk-KC7KSQR4.js +0 -302
- package/dist/chunk-LZCGPRHS.js +0 -228
- package/dist/chunk-MBIFE6SA.js +0 -250
- package/dist/chunk-MXFJXUHC.js +0 -292
- package/dist/chunk-NUWDSTP7.js +0 -233
- package/dist/chunk-QCCP4RU5.js +0 -190
- package/dist/chunk-QMUQV5NP.js +0 -146
- package/dist/chunk-QQXJODFL.js +0 -328
- package/dist/chunk-SWOYEQN2.js +0 -1005
- package/dist/chunk-TH5FF5SC.js +0 -16
- package/dist/chunk-TXOEHSVP.js +0 -275
- package/dist/chunk-UFU5GGGA.js +0 -47
- package/dist/chunk-USSDZQKJ.js +0 -6533
- package/dist/chunk-UZJ7EERS.js +0 -272
- package/dist/chunk-VUZEEGP5.js +0 -725
- package/dist/chunk-W6EEFUCJ.js +0 -349
- package/dist/chunk-YGGGUTG3.js +0 -125
- package/dist/chunk-YJYZMLD5.js +0 -360
- package/dist/chunk-YKV4EFUI.js +0 -199
- package/dist/chunk-ZS6VABML.js +0 -185
- package/dist/cipher-E23BHBSO.js +0 -27
- package/dist/consolidation-undo-FKJZCJHS.js +0 -426
- package/dist/contradiction-review-WJRWNQ5N.js +0 -29
- package/dist/contradiction-scan-5X423QGT.js +0 -12
- package/dist/dreams-ledger-KDX44I7R.js +0 -290
- package/dist/engine-O46ZX4EZ.js +0 -16
- package/dist/extraction-judge-telemetry-O4ZVGLTU.js +0 -14
- package/dist/fallback-llm-43UMEXNJ.js +0 -10
- package/dist/first-start-migration-H2SAXAGR.js +0 -263
- package/dist/forget-ZECIDNL5.js +0 -68
- package/dist/fs-utils-OYXSZSVV.js +0 -39
- package/dist/graph-edge-decay-24ZKD5QL.js +0 -202
- package/dist/kdf-RXKIWHRU.js +0 -25
- package/dist/logger-XG7JKLPS.js +0 -9
- package/dist/memory-governance-6BCH6SZ5.js +0 -25
- package/dist/metadata-WK2TRPYZ.js +0 -20
- package/dist/migrate-from-identity-anchor-SNDNKHZD.js +0 -7
- package/dist/path-ZKO74XXC.js +0 -7
- package/dist/peers-W53WSDXG.js +0 -43
- package/dist/purge-IKJISXEQ.js +0 -204
- package/dist/resolution-BN35OXDS.js +0 -11
- package/dist/secure-store-6RWYM6GK.js +0 -155
- package/dist/state-4ITLYMAU.js +0 -7
- package/dist/state-store-ET3ADVY5.js +0 -14
- package/dist/storage-VEGU76NN.js +0 -27
- package/dist/tier-stats-ZRQBV6G2.js +0 -147
- package/dist/trace-IL2Y34EH.js +0 -289
- package/dist/tui-7KRDCMYK.js +0 -12
- package/dist/types-MBUINTB2.js +0 -30
package/dist/chunk-B52XADV3.js
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
gatherConsoleState
|
|
3
|
-
} from "./chunk-MBIFE6SA.js";
|
|
4
|
-
|
|
5
|
-
// ../remnic-core/src/console/tui.ts
|
|
6
|
-
var ANSI_CLEAR_HOME = "\x1B[2J\x1B[H";
|
|
7
|
-
var ANSI_HIDE_CURSOR = "\x1B[?25l";
|
|
8
|
-
var ANSI_SHOW_CURSOR = "\x1B[?25h";
|
|
9
|
-
var FRAME_INNER_WIDTH = 70;
|
|
10
|
-
var DEFAULT_REFRESH_INTERVAL_MS = 2e3;
|
|
11
|
-
function runConsoleTui(orchestrator, options = {}) {
|
|
12
|
-
const refreshIntervalMs = Math.max(
|
|
13
|
-
50,
|
|
14
|
-
options.refreshIntervalMs ?? DEFAULT_REFRESH_INTERVAL_MS
|
|
15
|
-
);
|
|
16
|
-
const output = options.output ?? process.stdout;
|
|
17
|
-
const now = options.now ?? (() => Date.now());
|
|
18
|
-
const installSigintHandler = options.installSigintHandler ?? true;
|
|
19
|
-
let stopped = false;
|
|
20
|
-
let inFlight = false;
|
|
21
|
-
let inFlightTickPromise = null;
|
|
22
|
-
let traceWritePending = false;
|
|
23
|
-
let traceFramesDropped = 0;
|
|
24
|
-
let resolveDone;
|
|
25
|
-
const done = new Promise((resolve) => {
|
|
26
|
-
resolveDone = resolve;
|
|
27
|
-
});
|
|
28
|
-
safeWrite(output, ANSI_HIDE_CURSOR);
|
|
29
|
-
const tick = async () => {
|
|
30
|
-
if (stopped || inFlight) return;
|
|
31
|
-
inFlight = true;
|
|
32
|
-
try {
|
|
33
|
-
let snapshot = null;
|
|
34
|
-
let renderError = null;
|
|
35
|
-
try {
|
|
36
|
-
snapshot = await gatherConsoleState(orchestrator);
|
|
37
|
-
} catch (err) {
|
|
38
|
-
renderError = describeError(err);
|
|
39
|
-
}
|
|
40
|
-
if (stopped) return;
|
|
41
|
-
let frame;
|
|
42
|
-
try {
|
|
43
|
-
frame = renderFrame({ snapshot, renderError, now });
|
|
44
|
-
} catch (err) {
|
|
45
|
-
frame = `remnic console: render failed: ${describeError(err)}
|
|
46
|
-
`;
|
|
47
|
-
}
|
|
48
|
-
safeWrite(output, ANSI_CLEAR_HOME);
|
|
49
|
-
safeWrite(output, frame);
|
|
50
|
-
if (snapshot && options.traceRecorder && !traceWritePending) {
|
|
51
|
-
traceWritePending = true;
|
|
52
|
-
void options.traceRecorder.append(snapshot).catch(() => {
|
|
53
|
-
}).finally(() => {
|
|
54
|
-
traceWritePending = false;
|
|
55
|
-
});
|
|
56
|
-
} else if (snapshot && options.traceRecorder) {
|
|
57
|
-
traceFramesDropped += 1;
|
|
58
|
-
}
|
|
59
|
-
} finally {
|
|
60
|
-
inFlight = false;
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
const launchTick = () => {
|
|
64
|
-
const p = runTickSafely(tick);
|
|
65
|
-
inFlightTickPromise = p;
|
|
66
|
-
void p.then(() => {
|
|
67
|
-
if (inFlightTickPromise === p) {
|
|
68
|
-
inFlightTickPromise = null;
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
};
|
|
72
|
-
launchTick();
|
|
73
|
-
const handle = setInterval(launchTick, refreshIntervalMs);
|
|
74
|
-
const sigintHandler = () => {
|
|
75
|
-
stop();
|
|
76
|
-
};
|
|
77
|
-
if (installSigintHandler) {
|
|
78
|
-
process.on("SIGINT", sigintHandler);
|
|
79
|
-
}
|
|
80
|
-
const stop = () => {
|
|
81
|
-
if (stopped) return;
|
|
82
|
-
stopped = true;
|
|
83
|
-
clearInterval(handle);
|
|
84
|
-
if (installSigintHandler) {
|
|
85
|
-
try {
|
|
86
|
-
process.removeListener("SIGINT", sigintHandler);
|
|
87
|
-
} catch {
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
safeWrite(output, ANSI_SHOW_CURSOR);
|
|
91
|
-
void (async () => {
|
|
92
|
-
try {
|
|
93
|
-
const pendingTick = inFlightTickPromise;
|
|
94
|
-
if (pendingTick) {
|
|
95
|
-
await pendingTick;
|
|
96
|
-
}
|
|
97
|
-
} finally {
|
|
98
|
-
resolveDone();
|
|
99
|
-
}
|
|
100
|
-
})();
|
|
101
|
-
};
|
|
102
|
-
return {
|
|
103
|
-
stop,
|
|
104
|
-
done,
|
|
105
|
-
getDroppedTraceFrames: () => traceFramesDropped
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
function renderFrame(input) {
|
|
109
|
-
const ts = new Date(input.now()).toISOString();
|
|
110
|
-
const lines = [];
|
|
111
|
-
lines.push(renderHeader(ts));
|
|
112
|
-
for (const panel of renderPanels(input)) {
|
|
113
|
-
lines.push(panel);
|
|
114
|
-
}
|
|
115
|
-
lines.push(renderFooter());
|
|
116
|
-
return lines.join("\n") + "\n";
|
|
117
|
-
}
|
|
118
|
-
function renderHeader(ts) {
|
|
119
|
-
const title = " remnic console ";
|
|
120
|
-
const trailing = ` ${ts} `;
|
|
121
|
-
const fillerLen = Math.max(
|
|
122
|
-
1,
|
|
123
|
-
FRAME_INNER_WIDTH - title.length - trailing.length
|
|
124
|
-
);
|
|
125
|
-
const filler = "\u2550".repeat(fillerLen);
|
|
126
|
-
return `\u2554${title}${filler}${trailing}\u2557`;
|
|
127
|
-
}
|
|
128
|
-
function renderFooter() {
|
|
129
|
-
return `\u255A${"\u2550".repeat(FRAME_INNER_WIDTH)}\u255D`;
|
|
130
|
-
}
|
|
131
|
-
function renderPanels(input) {
|
|
132
|
-
const lines = [];
|
|
133
|
-
const snap = input.snapshot;
|
|
134
|
-
if (input.renderError !== null) {
|
|
135
|
-
lines.push(panelLine("Error", `refresh failed: ${input.renderError}`));
|
|
136
|
-
lines.push(panelLine("Buffer", "(unavailable)"));
|
|
137
|
-
lines.push(panelLine("Extraction", "(unavailable)"));
|
|
138
|
-
lines.push(panelLine("Dedup", "(unavailable)"));
|
|
139
|
-
lines.push(panelLine("Maintenance", "(unavailable)"));
|
|
140
|
-
lines.push(panelLine("QMD", "(unavailable)"));
|
|
141
|
-
return lines;
|
|
142
|
-
}
|
|
143
|
-
if (snap) {
|
|
144
|
-
lines.push(
|
|
145
|
-
panelLine(
|
|
146
|
-
"Buffer",
|
|
147
|
-
`turns=${snap.bufferState.turnsCount} bytes=${snap.bufferState.byteCount}`
|
|
148
|
-
)
|
|
149
|
-
);
|
|
150
|
-
const verdicts = snap.extractionQueue.recentVerdicts;
|
|
151
|
-
const accepts = verdicts.filter((v) => v.kind === "accept").length;
|
|
152
|
-
const rejects = verdicts.filter((v) => v.kind === "reject").length;
|
|
153
|
-
lines.push(
|
|
154
|
-
panelLine(
|
|
155
|
-
"Extraction",
|
|
156
|
-
`queue=${snap.extractionQueue.depth} recent verdicts: accept(${accepts})/reject(${rejects})`
|
|
157
|
-
)
|
|
158
|
-
);
|
|
159
|
-
const dedupSummary = formatDedupSummary(snap.dedupRecent, input.now);
|
|
160
|
-
lines.push(panelLine("Dedup", dedupSummary));
|
|
161
|
-
const maintSummary = formatMaintenanceTail(snap.maintenanceLedgerTail);
|
|
162
|
-
lines.push(panelLine("Maintenance", maintSummary));
|
|
163
|
-
lines.push(panelLine("QMD", formatQmdSummary(snap)));
|
|
164
|
-
}
|
|
165
|
-
if (snap && snap.errors.length > 0) {
|
|
166
|
-
const head = snap.errors[0];
|
|
167
|
-
lines.push(panelLine("Errors", head ?? ""));
|
|
168
|
-
}
|
|
169
|
-
return lines;
|
|
170
|
-
}
|
|
171
|
-
function formatDedupSummary(decisions, now) {
|
|
172
|
-
if (decisions.length === 0) return "no recent decisions";
|
|
173
|
-
const last = decisions[decisions.length - 1];
|
|
174
|
-
if (!last) return "no recent decisions";
|
|
175
|
-
const ageMs = ageMsFromIso(last.ts, now);
|
|
176
|
-
const ageStr = ageMs === null ? "T-?" : `T-${Math.round(ageMs / 1e3)}s`;
|
|
177
|
-
const fp = last.fingerprint ? `hash=${last.fingerprint}` : "hash=?";
|
|
178
|
-
return `recent: ${fp} decision=${last.decision} (${ageStr})`;
|
|
179
|
-
}
|
|
180
|
-
function formatMaintenanceTail(events) {
|
|
181
|
-
if (events.length === 0) return "no events";
|
|
182
|
-
const last = events[events.length - 1];
|
|
183
|
-
if (!last) return "no events";
|
|
184
|
-
return `n=${events.length} last: ${last.category} ${truncate(last.summary, 40)}`;
|
|
185
|
-
}
|
|
186
|
-
function formatQmdSummary(snap) {
|
|
187
|
-
const probe = snap.qmdProbe.available ? "ok" : "down";
|
|
188
|
-
const uptimeH = snap.daemon.uptimeMs / 36e5;
|
|
189
|
-
const uptimeStr = uptimeH < 1 ? `${Math.round(snap.daemon.uptimeMs / 1e3)}s` : `${uptimeH.toFixed(1)}h`;
|
|
190
|
-
const mode = snap.qmdProbe.daemonMode ? "daemon" : "cli";
|
|
191
|
-
return `probe=${probe} mode=${mode} uptime=${uptimeStr}`;
|
|
192
|
-
}
|
|
193
|
-
function panelLine(label, value) {
|
|
194
|
-
const LABEL_WIDTH = 13;
|
|
195
|
-
const labelCol = padRight(label, LABEL_WIDTH);
|
|
196
|
-
const remaining = FRAME_INNER_WIDTH - LABEL_WIDTH - 2;
|
|
197
|
-
const valueCol = padRight(truncate(value, remaining), remaining);
|
|
198
|
-
return `\u2551 ${labelCol}${valueCol} \u2551`;
|
|
199
|
-
}
|
|
200
|
-
function padRight(s, width) {
|
|
201
|
-
if (s.length >= width) return s;
|
|
202
|
-
return s + " ".repeat(width - s.length);
|
|
203
|
-
}
|
|
204
|
-
function truncate(s, max) {
|
|
205
|
-
if (max <= 0) return "";
|
|
206
|
-
if (s.length <= max) return s;
|
|
207
|
-
if (max <= 1) return s.slice(0, max);
|
|
208
|
-
return s.slice(0, max - 1) + "\u2026";
|
|
209
|
-
}
|
|
210
|
-
function ageMsFromIso(iso, now) {
|
|
211
|
-
const ms = Date.parse(iso);
|
|
212
|
-
if (!Number.isFinite(ms)) return null;
|
|
213
|
-
const delta = now() - ms;
|
|
214
|
-
return delta < 0 ? 0 : delta;
|
|
215
|
-
}
|
|
216
|
-
async function runTickSafely(tick) {
|
|
217
|
-
try {
|
|
218
|
-
await tick();
|
|
219
|
-
} catch {
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
function safeWrite(output, chunk) {
|
|
223
|
-
try {
|
|
224
|
-
output.write(chunk);
|
|
225
|
-
} catch {
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
function describeError(err) {
|
|
229
|
-
if (err instanceof Error) return err.message;
|
|
230
|
-
try {
|
|
231
|
-
return String(err);
|
|
232
|
-
} catch {
|
|
233
|
-
return "unknown error";
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
function stripAnsi(s) {
|
|
237
|
-
return s.replace(/\x1b\[[0-9;?]*[A-Za-z]/g, "");
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
export {
|
|
241
|
-
runConsoleTui,
|
|
242
|
-
renderFrame,
|
|
243
|
-
stripAnsi
|
|
244
|
-
};
|
package/dist/chunk-BQZ7JACP.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AUTH_TAG_LENGTH,
|
|
3
|
-
ENVELOPE_HEADER_SIZE,
|
|
4
|
-
ENVELOPE_LAYOUT,
|
|
5
|
-
ENVELOPE_SALT_LENGTH,
|
|
6
|
-
ENVELOPE_VERSION,
|
|
7
|
-
IV_LENGTH,
|
|
8
|
-
generateSalt,
|
|
9
|
-
open,
|
|
10
|
-
seal
|
|
11
|
-
} from "./chunk-YGGGUTG3.js";
|
|
12
|
-
|
|
13
|
-
// ../remnic-core/src/secure-store/secure-fs.ts
|
|
14
|
-
import { createCipheriv, randomBytes } from "crypto";
|
|
15
|
-
import * as fsReadModule0 from "fs/promises";
|
|
16
|
-
const lstat = fsReadModule0.lstat;
|
|
17
|
-
const mkdir = fsReadModule0.mkdir;
|
|
18
|
-
const openFile = fsReadModule0.open;
|
|
19
|
-
const fileReader = fsReadModule0["re"+"ad"+"Fi"+"le"];
|
|
20
|
-
const readdir = fsReadModule0.readdir;
|
|
21
|
-
const rename = fsReadModule0.rename;
|
|
22
|
-
const unlink = fsReadModule0.unlink;
|
|
23
|
-
const writeFile = fsReadModule0.writeFile;
|
|
24
|
-
import path from "path";
|
|
25
|
-
var SecureStoreLockedError = class extends Error {
|
|
26
|
-
constructor(message = "secure-store is locked \u2014 run `remnic secure-store unlock` to decrypt") {
|
|
27
|
-
super(message);
|
|
28
|
-
this.name = "SecureStoreLockedError";
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
var SecureStoreDecryptError = class extends Error {
|
|
32
|
-
constructor(message = "secure-store decryption failed \u2014 wrong key or tampered ciphertext") {
|
|
33
|
-
super(message);
|
|
34
|
-
this.name = "SecureStoreDecryptError";
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var MAGIC_BYTES = Buffer.from("REMNIC-ENC", "ascii");
|
|
38
|
-
var FILE_FORMAT_VERSION = 1;
|
|
39
|
-
var FILE_FORMAT_FLAGS = 0;
|
|
40
|
-
var MAGIC_HEADER_SIZE = MAGIC_BYTES.length + 2;
|
|
41
|
-
function isEncryptedFile(buf) {
|
|
42
|
-
if (buf.length < MAGIC_HEADER_SIZE) return false;
|
|
43
|
-
const b = Buffer.isBuffer(buf) ? buf : Buffer.from(buf);
|
|
44
|
-
return b.subarray(0, MAGIC_BYTES.length).equals(MAGIC_BYTES);
|
|
45
|
-
}
|
|
46
|
-
function encryptFileBody(plain, key, aad) {
|
|
47
|
-
const plainBuf = typeof plain === "string" ? Buffer.from(plain, "utf8") : plain;
|
|
48
|
-
const salt = generateSalt();
|
|
49
|
-
const envelope = seal(key, salt, plainBuf, aad ? { aad } : {});
|
|
50
|
-
const header = Buffer.alloc(MAGIC_HEADER_SIZE);
|
|
51
|
-
MAGIC_BYTES.copy(header, 0);
|
|
52
|
-
header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);
|
|
53
|
-
header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);
|
|
54
|
-
return Buffer.concat([header, envelope]);
|
|
55
|
-
}
|
|
56
|
-
function decryptFileBody(buf, key, aad) {
|
|
57
|
-
if (!isEncryptedFile(buf)) {
|
|
58
|
-
throw new Error("decryptFileBody: buffer does not start with REMNIC-ENC magic header");
|
|
59
|
-
}
|
|
60
|
-
const version = buf.readUInt8(MAGIC_BYTES.length);
|
|
61
|
-
if (version !== FILE_FORMAT_VERSION) {
|
|
62
|
-
throw new Error(
|
|
63
|
-
`decryptFileBody: unsupported file format version ${version} (this build supports ${FILE_FORMAT_VERSION})`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
const flags = buf.readUInt8(MAGIC_BYTES.length + 1);
|
|
67
|
-
if (flags !== FILE_FORMAT_FLAGS) {
|
|
68
|
-
throw new Error(`decryptFileBody: unknown flags byte 0x${flags.toString(16).padStart(2, "0")}`);
|
|
69
|
-
}
|
|
70
|
-
const envelope = buf.subarray(MAGIC_HEADER_SIZE);
|
|
71
|
-
try {
|
|
72
|
-
return open(key, envelope, aad ? { aad } : {});
|
|
73
|
-
} catch (err) {
|
|
74
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
75
|
-
throw new SecureStoreDecryptError(
|
|
76
|
-
`secure-store decryption failed: ${msg}`
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function buildHeaderAad(salt) {
|
|
81
|
-
const out = Buffer.alloc(1 + ENVELOPE_SALT_LENGTH);
|
|
82
|
-
out.writeUInt8(ENVELOPE_VERSION, 0);
|
|
83
|
-
Buffer.from(salt).copy(out, 1);
|
|
84
|
-
return out;
|
|
85
|
-
}
|
|
86
|
-
function filePathAad(filePath, memoryDir) {
|
|
87
|
-
let rel = filePath;
|
|
88
|
-
if (memoryDir && path.isAbsolute(filePath)) {
|
|
89
|
-
rel = path.relative(memoryDir, filePath);
|
|
90
|
-
}
|
|
91
|
-
return Buffer.from(rel, "utf8");
|
|
92
|
-
}
|
|
93
|
-
async function readMaybeEncryptedFileBuffer(filePath, key, memoryDir) {
|
|
94
|
-
const buf = await fileReader(filePath);
|
|
95
|
-
if (!isEncryptedFile(buf)) {
|
|
96
|
-
return buf;
|
|
97
|
-
}
|
|
98
|
-
if (key === null) {
|
|
99
|
-
throw new SecureStoreLockedError(
|
|
100
|
-
`secure-store is locked \u2014 cannot read encrypted file at ${filePath}. Run \`remnic secure-store unlock\` to decrypt.`
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
const aad = filePathAad(filePath, memoryDir);
|
|
104
|
-
return decryptFileBody(buf, key, aad);
|
|
105
|
-
}
|
|
106
|
-
async function readMaybeEncryptedFile(filePath, key, memoryDir) {
|
|
107
|
-
return (await readMaybeEncryptedFileBuffer(filePath, key, memoryDir)).toString("utf8");
|
|
108
|
-
}
|
|
109
|
-
async function writeMaybeEncryptedFile(filePath, content, key, options = {}, memoryDir) {
|
|
110
|
-
const { mode = 384, atomic = true } = options;
|
|
111
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
112
|
-
let data;
|
|
113
|
-
if (key !== null) {
|
|
114
|
-
const aad = filePathAad(filePath, memoryDir);
|
|
115
|
-
data = encryptFileBody(content, key, aad);
|
|
116
|
-
} else {
|
|
117
|
-
data = content;
|
|
118
|
-
}
|
|
119
|
-
if (atomic) {
|
|
120
|
-
const tempPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
121
|
-
try {
|
|
122
|
-
await writeFile(tempPath, data, { mode });
|
|
123
|
-
await rename(tempPath, filePath);
|
|
124
|
-
} catch (err) {
|
|
125
|
-
try {
|
|
126
|
-
await unlink(tempPath);
|
|
127
|
-
} catch {
|
|
128
|
-
}
|
|
129
|
-
throw err;
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
await writeFile(filePath, data, { mode });
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
async function writeMaybeEncryptedFileFromChunks(filePath, chunks, key, options = {}, memoryDir) {
|
|
136
|
-
const { mode = 384, atomic = true } = options;
|
|
137
|
-
await mkdir(path.dirname(filePath), { recursive: true });
|
|
138
|
-
const writePath = atomic ? `${filePath}.tmp-${process.pid}-${Date.now()}` : filePath;
|
|
139
|
-
let completed = false;
|
|
140
|
-
try {
|
|
141
|
-
const handle = await openFile(writePath, "w", mode);
|
|
142
|
-
try {
|
|
143
|
-
if (key !== null) {
|
|
144
|
-
const salt = generateSalt();
|
|
145
|
-
const iv = randomBytes(IV_LENGTH);
|
|
146
|
-
const header = Buffer.alloc(MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE);
|
|
147
|
-
MAGIC_BYTES.copy(header, 0);
|
|
148
|
-
header.writeUInt8(FILE_FORMAT_VERSION, MAGIC_BYTES.length);
|
|
149
|
-
header.writeUInt8(FILE_FORMAT_FLAGS, MAGIC_BYTES.length + 1);
|
|
150
|
-
const envelopeOffset = MAGIC_HEADER_SIZE;
|
|
151
|
-
header.writeUInt8(ENVELOPE_VERSION, envelopeOffset + ENVELOPE_LAYOUT.version);
|
|
152
|
-
salt.copy(header, envelopeOffset + ENVELOPE_LAYOUT.salt);
|
|
153
|
-
iv.copy(header, envelopeOffset + ENVELOPE_LAYOUT.iv);
|
|
154
|
-
await handle.write(header);
|
|
155
|
-
const cipher = createCipheriv("aes-256-gcm", key, iv, { authTagLength: AUTH_TAG_LENGTH });
|
|
156
|
-
const aad = filePathAad(filePath, memoryDir);
|
|
157
|
-
cipher.setAAD(Buffer.concat([buildHeaderAad(salt), aad]));
|
|
158
|
-
for await (const chunk of chunks) {
|
|
159
|
-
if (chunk.length === 0) continue;
|
|
160
|
-
const encrypted = cipher.update(chunk);
|
|
161
|
-
if (encrypted.length > 0) await handle.write(encrypted);
|
|
162
|
-
}
|
|
163
|
-
const final = cipher.final();
|
|
164
|
-
if (final.length > 0) await handle.write(final);
|
|
165
|
-
const authTag = cipher.getAuthTag();
|
|
166
|
-
await handle.write(
|
|
167
|
-
authTag,
|
|
168
|
-
0,
|
|
169
|
-
authTag.length,
|
|
170
|
-
MAGIC_HEADER_SIZE + ENVELOPE_LAYOUT.authTag
|
|
171
|
-
);
|
|
172
|
-
} else {
|
|
173
|
-
for await (const chunk of chunks) {
|
|
174
|
-
if (chunk.length > 0) await handle.write(chunk);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
} finally {
|
|
178
|
-
await handle.close();
|
|
179
|
-
}
|
|
180
|
-
if (atomic) {
|
|
181
|
-
await rename(writePath, filePath);
|
|
182
|
-
}
|
|
183
|
-
completed = true;
|
|
184
|
-
} finally {
|
|
185
|
-
if (!completed && atomic) {
|
|
186
|
-
await unlink(writePath).catch(() => {
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
async function migrateMemoryDirToEncrypted(dir, key, onBeforeEncrypt) {
|
|
192
|
-
const result = { encrypted: 0, skipped: 0, errors: [] };
|
|
193
|
-
const files = await collectEncryptableStorageFiles(dir);
|
|
194
|
-
for (const filePath of files) {
|
|
195
|
-
try {
|
|
196
|
-
const buf = await fileReader(filePath);
|
|
197
|
-
if (isEncryptedFile(buf)) {
|
|
198
|
-
result.skipped++;
|
|
199
|
-
continue;
|
|
200
|
-
}
|
|
201
|
-
if (onBeforeEncrypt) {
|
|
202
|
-
try {
|
|
203
|
-
await onBeforeEncrypt(filePath);
|
|
204
|
-
} catch {
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
const content = buf.toString("utf8");
|
|
208
|
-
const aad = filePathAad(filePath, storageAadRootForFile(filePath, dir));
|
|
209
|
-
const encrypted = encryptFileBody(content, key, aad);
|
|
210
|
-
const tempPath = `${filePath}.enc-tmp-${process.pid}-${Date.now()}`;
|
|
211
|
-
try {
|
|
212
|
-
await writeFile(tempPath, encrypted, { mode: 384 });
|
|
213
|
-
await rename(tempPath, filePath);
|
|
214
|
-
result.encrypted++;
|
|
215
|
-
} catch (writeErr) {
|
|
216
|
-
try {
|
|
217
|
-
const { unlink: unlink2 } = await import("fs/promises");
|
|
218
|
-
await unlink2(tempPath);
|
|
219
|
-
} catch {
|
|
220
|
-
}
|
|
221
|
-
throw writeErr;
|
|
222
|
-
}
|
|
223
|
-
} catch (err) {
|
|
224
|
-
result.errors.push({
|
|
225
|
-
filePath,
|
|
226
|
-
error: err instanceof Error ? err.message : String(err)
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return result;
|
|
231
|
-
}
|
|
232
|
-
async function decryptMemoryDirToPlaintext(dir, key) {
|
|
233
|
-
const result = { decrypted: 0, skipped: 0, errors: [] };
|
|
234
|
-
const files = await collectStorageManagedFiles(dir, isDecryptableStoragePath);
|
|
235
|
-
for (const filePath of files) {
|
|
236
|
-
try {
|
|
237
|
-
const buf = await fileReader(filePath);
|
|
238
|
-
if (!isEncryptedFile(buf)) {
|
|
239
|
-
result.skipped++;
|
|
240
|
-
continue;
|
|
241
|
-
}
|
|
242
|
-
const aad = filePathAad(filePath, storageAadRootForFile(filePath, dir));
|
|
243
|
-
const plaintext = decryptFileBody(buf, key, aad);
|
|
244
|
-
const tempPath = `${filePath}.dec-tmp-${process.pid}-${Date.now()}`;
|
|
245
|
-
try {
|
|
246
|
-
await writeFile(tempPath, plaintext, { mode: 384 });
|
|
247
|
-
await rename(tempPath, filePath);
|
|
248
|
-
result.decrypted++;
|
|
249
|
-
} catch (writeErr) {
|
|
250
|
-
try {
|
|
251
|
-
await unlink(tempPath);
|
|
252
|
-
} catch {
|
|
253
|
-
}
|
|
254
|
-
throw writeErr;
|
|
255
|
-
}
|
|
256
|
-
} catch (err) {
|
|
257
|
-
result.errors.push({
|
|
258
|
-
filePath,
|
|
259
|
-
error: err instanceof Error ? err.message : String(err)
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
return result;
|
|
264
|
-
}
|
|
265
|
-
async function collectEncryptableStorageFiles(dir, rootDir = dir) {
|
|
266
|
-
return collectStorageManagedFiles(dir, isEncryptableStoragePath, rootDir);
|
|
267
|
-
}
|
|
268
|
-
async function collectStorageManagedFiles(dir, includeFile, rootDir = dir) {
|
|
269
|
-
const results = [];
|
|
270
|
-
let names;
|
|
271
|
-
try {
|
|
272
|
-
names = await readdir(dir, { encoding: "utf8" });
|
|
273
|
-
} catch {
|
|
274
|
-
return results;
|
|
275
|
-
}
|
|
276
|
-
for (const name of names) {
|
|
277
|
-
if (name.startsWith(".secure-store")) continue;
|
|
278
|
-
const full = path.join(dir, name);
|
|
279
|
-
let isDir = false;
|
|
280
|
-
let isFile = false;
|
|
281
|
-
try {
|
|
282
|
-
const s = await lstat(full);
|
|
283
|
-
if (s.isSymbolicLink()) continue;
|
|
284
|
-
isDir = s.isDirectory();
|
|
285
|
-
isFile = s.isFile();
|
|
286
|
-
} catch {
|
|
287
|
-
continue;
|
|
288
|
-
}
|
|
289
|
-
if (isDir) {
|
|
290
|
-
const sub = await collectStorageManagedFiles(full, includeFile, rootDir);
|
|
291
|
-
results.push(...sub);
|
|
292
|
-
} else if (isFile && includeFile(full, rootDir)) {
|
|
293
|
-
results.push(full);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
return results;
|
|
297
|
-
}
|
|
298
|
-
function isEncryptableStoragePath(filePath, rootDir) {
|
|
299
|
-
const rel = path.relative(rootDir, filePath);
|
|
300
|
-
if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return false;
|
|
301
|
-
const normalized = normalizeStorageRelativePath(rel);
|
|
302
|
-
if (normalized === "profile.md") return true;
|
|
303
|
-
if (isEncryptableStateSidecar(normalized)) return true;
|
|
304
|
-
if (isEncryptableSummarySidecar(normalized)) return true;
|
|
305
|
-
const firstSegment = normalized.split("/", 1)[0];
|
|
306
|
-
return ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS.has(firstSegment) && normalized.endsWith(".md");
|
|
307
|
-
}
|
|
308
|
-
function isDecryptableStoragePath(filePath, rootDir) {
|
|
309
|
-
if (isEncryptableStoragePath(filePath, rootDir)) return true;
|
|
310
|
-
const rel = path.relative(rootDir, filePath);
|
|
311
|
-
if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return false;
|
|
312
|
-
const normalized = normalizeStorageRelativePath(rel);
|
|
313
|
-
const firstSegment = normalized.split("/", 1)[0];
|
|
314
|
-
return DECRYPTABLE_SIDECAR_ROOTS.has(firstSegment);
|
|
315
|
-
}
|
|
316
|
-
function normalizeStorageRelativePath(rel) {
|
|
317
|
-
const normalized = rel.split(path.sep).join("/");
|
|
318
|
-
const parts = normalized.split("/");
|
|
319
|
-
if (parts[0] === "namespaces" && parts.length >= 3) {
|
|
320
|
-
return parts.slice(2).join("/");
|
|
321
|
-
}
|
|
322
|
-
return normalized;
|
|
323
|
-
}
|
|
324
|
-
function storageAadRootForFile(filePath, rootDir) {
|
|
325
|
-
const rel = path.relative(rootDir, filePath);
|
|
326
|
-
if (rel === "" || rel.startsWith("..") || path.isAbsolute(rel)) return rootDir;
|
|
327
|
-
const parts = rel.split(path.sep);
|
|
328
|
-
if (parts[0] === "namespaces" && parts.length >= 3 && parts[1]) {
|
|
329
|
-
return path.join(rootDir, "namespaces", parts[1]);
|
|
330
|
-
}
|
|
331
|
-
return rootDir;
|
|
332
|
-
}
|
|
333
|
-
var ENCRYPTABLE_MARKDOWN_STORAGE_ROOTS = /* @__PURE__ */ new Set([
|
|
334
|
-
"facts",
|
|
335
|
-
"corrections",
|
|
336
|
-
"procedures",
|
|
337
|
-
"reasoning-traces",
|
|
338
|
-
"artifacts",
|
|
339
|
-
"archive",
|
|
340
|
-
"entities",
|
|
341
|
-
"identity"
|
|
342
|
-
]);
|
|
343
|
-
var ENCRYPTABLE_STATE_SIDECARS = /* @__PURE__ */ new Set([
|
|
344
|
-
"state/behavior-signals.jsonl",
|
|
345
|
-
"state/buffer-surprise-ledger.jsonl",
|
|
346
|
-
"state/buffer.json",
|
|
347
|
-
"state/compression-guideline-draft-state.json",
|
|
348
|
-
"state/compression-guideline-state.json",
|
|
349
|
-
"state/compression-guidelines.draft.md",
|
|
350
|
-
"state/compression-guidelines.md",
|
|
351
|
-
"state/entity-synthesis-queue.json",
|
|
352
|
-
"state/fact-hashes.txt",
|
|
353
|
-
"state/memory-actions.jsonl",
|
|
354
|
-
"state/memory-lifecycle-ledger.jsonl",
|
|
355
|
-
"state/meta.json",
|
|
356
|
-
"state/reextract-jobs.jsonl",
|
|
357
|
-
"state/topics.json"
|
|
358
|
-
]);
|
|
359
|
-
function isEncryptableStateSidecar(normalized) {
|
|
360
|
-
return ENCRYPTABLE_STATE_SIDECARS.has(normalized);
|
|
361
|
-
}
|
|
362
|
-
function isEncryptableSummarySidecar(normalized) {
|
|
363
|
-
return normalized.startsWith("summaries/") && normalized.endsWith(".json");
|
|
364
|
-
}
|
|
365
|
-
var DECRYPTABLE_SIDECAR_ROOTS = /* @__PURE__ */ new Set([
|
|
366
|
-
"state",
|
|
367
|
-
"indexes",
|
|
368
|
-
"index",
|
|
369
|
-
"provenance"
|
|
370
|
-
]);
|
|
371
|
-
|
|
372
|
-
export {
|
|
373
|
-
SecureStoreLockedError,
|
|
374
|
-
SecureStoreDecryptError,
|
|
375
|
-
MAGIC_BYTES,
|
|
376
|
-
FILE_FORMAT_VERSION,
|
|
377
|
-
FILE_FORMAT_FLAGS,
|
|
378
|
-
MAGIC_HEADER_SIZE,
|
|
379
|
-
isEncryptedFile,
|
|
380
|
-
encryptFileBody,
|
|
381
|
-
decryptFileBody,
|
|
382
|
-
filePathAad,
|
|
383
|
-
readMaybeEncryptedFileBuffer,
|
|
384
|
-
readMaybeEncryptedFile,
|
|
385
|
-
writeMaybeEncryptedFile,
|
|
386
|
-
writeMaybeEncryptedFileFromChunks,
|
|
387
|
-
migrateMemoryDirToEncrypted,
|
|
388
|
-
decryptMemoryDirToPlaintext
|
|
389
|
-
};
|
package/dist/chunk-BU5KJVWF.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// ../remnic-core/src/tier-migration.ts
|
|
2
|
-
import { appendFile, mkdir } from "fs/promises";
|
|
3
|
-
import path from "path";
|
|
4
|
-
var TierMigrationExecutor = class {
|
|
5
|
-
storage;
|
|
6
|
-
qmd;
|
|
7
|
-
hotCollection;
|
|
8
|
-
coldCollection;
|
|
9
|
-
autoEmbed;
|
|
10
|
-
journalPath;
|
|
11
|
-
constructor(options) {
|
|
12
|
-
this.storage = options.storage;
|
|
13
|
-
this.qmd = options.qmd;
|
|
14
|
-
this.hotCollection = options.hotCollection;
|
|
15
|
-
this.coldCollection = options.coldCollection;
|
|
16
|
-
this.autoEmbed = options.autoEmbed === true;
|
|
17
|
-
this.journalPath = options.journalPath ?? path.join(this.storage.dir, "state", "tier-migration-journal.jsonl");
|
|
18
|
-
}
|
|
19
|
-
async migrateMemory(request) {
|
|
20
|
-
const { memory, fromTier, toTier, reason } = request;
|
|
21
|
-
const targetPath = this.storage.buildTierMemoryPath(memory, toTier);
|
|
22
|
-
if (fromTier === toTier) {
|
|
23
|
-
const noChange = {
|
|
24
|
-
memoryId: memory.frontmatter.id,
|
|
25
|
-
fromTier,
|
|
26
|
-
toTier,
|
|
27
|
-
changed: false,
|
|
28
|
-
reason,
|
|
29
|
-
targetPath
|
|
30
|
-
};
|
|
31
|
-
await this.appendJournal(noChange);
|
|
32
|
-
return noChange;
|
|
33
|
-
}
|
|
34
|
-
const moved = await this.storage.migrateMemoryToTier(memory, toTier);
|
|
35
|
-
const result = {
|
|
36
|
-
memoryId: memory.frontmatter.id,
|
|
37
|
-
fromTier,
|
|
38
|
-
toTier,
|
|
39
|
-
changed: moved.changed,
|
|
40
|
-
reason,
|
|
41
|
-
targetPath: moved.targetPath
|
|
42
|
-
};
|
|
43
|
-
await this.appendJournal(result);
|
|
44
|
-
if (result.changed) {
|
|
45
|
-
const destinationCollection = this.collectionForTier(toTier);
|
|
46
|
-
const sourceCollection = this.collectionForTier(fromTier);
|
|
47
|
-
await this.qmd.updateCollection(destinationCollection);
|
|
48
|
-
if (this.autoEmbed) {
|
|
49
|
-
await this.qmd.embedCollection(destinationCollection);
|
|
50
|
-
if (sourceCollection !== destinationCollection) {
|
|
51
|
-
await this.qmd.embedCollection(sourceCollection);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return result;
|
|
56
|
-
}
|
|
57
|
-
collectionForTier(tier) {
|
|
58
|
-
return tier === "cold" ? this.coldCollection : this.hotCollection;
|
|
59
|
-
}
|
|
60
|
-
async appendJournal(result) {
|
|
61
|
-
const entry = {
|
|
62
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
63
|
-
memoryId: result.memoryId,
|
|
64
|
-
fromTier: result.fromTier,
|
|
65
|
-
toTier: result.toTier,
|
|
66
|
-
changed: result.changed,
|
|
67
|
-
reason: result.reason,
|
|
68
|
-
targetPath: result.targetPath
|
|
69
|
-
};
|
|
70
|
-
await mkdir(path.dirname(this.journalPath), { recursive: true });
|
|
71
|
-
await appendFile(this.journalPath, `${JSON.stringify(entry)}
|
|
72
|
-
`, "utf-8");
|
|
73
|
-
}
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
export {
|
|
77
|
-
TierMigrationExecutor
|
|
78
|
-
};
|