@remnic/plugin-openclaw 1.0.9 → 1.0.11
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/{calibration-674TDQNV.js → calibration-WCHOK6DX.js} +12 -4
- package/dist/capsule-cli-TFKLAG3S.js +329 -0
- package/dist/capsule-crypto-K3IRTKRH.js +17 -0
- package/dist/capsule-export-CVA3CKUQ.js +265 -0
- package/dist/capsule-import-CFX7BY5W.js +16 -0
- package/dist/capsule-merge-7RVOHJK3.js +189 -0
- package/dist/{causal-chain-OKDZSDEB.js → causal-chain-WYN5QOPS.js} +3 -2
- package/dist/{causal-consolidation-5BEXLQV5.js → causal-consolidation-JD6KJJH6.js} +16 -12
- package/dist/{causal-retrieval-3BKBXVXD.js → causal-retrieval-NZHQOZOE.js} +6 -5
- package/dist/{causal-trajectory-graph-RQIT37DN.js → causal-trajectory-graph-VBPE2WPM.js} +1 -1
- package/dist/chunk-37NKFWSO.js +233 -0
- package/dist/chunk-3G7FAF6S.js +60 -0
- package/dist/{chunk-Z7GRLVK3.js → chunk-3GUF7RQI.js} +235 -19
- package/dist/chunk-3I7RHWYT.js +214 -0
- package/dist/chunk-4G2XCSD2.js +186 -0
- package/dist/chunk-6IWEAUN6.js +148 -0
- package/dist/{chunk-LN5UZQVG.js → chunk-6UFI73TJ.js} +5 -3
- package/dist/chunk-7OQEPGQF.js +529 -0
- package/dist/chunk-B52XADV3.js +244 -0
- package/dist/chunk-BU5KJVWF.js +78 -0
- package/dist/chunk-CXM7EBAO.js +289 -0
- package/dist/chunk-ETJZRIAM.js +227 -0
- package/dist/chunk-FQRSVYY4.js +110 -0
- package/dist/chunk-HRGFO6AW.js +349 -0
- package/dist/chunk-I6B2W2IY.js +47 -0
- package/dist/chunk-JZBOXOUC.js +259 -0
- package/dist/chunk-K7EUBNDD.js +185 -0
- package/dist/chunk-L4PRBB2A.js +1860 -0
- package/dist/chunk-MBIFE6SA.js +250 -0
- package/dist/chunk-N7EOZY6F.js +400 -0
- package/dist/chunk-NKVIN6RD.js +118 -0
- package/dist/chunk-OEI7GLV2.js +17 -0
- package/dist/{chunk-S2ISS4AH.js → chunk-P3DIW2SD.js} +10 -10
- package/dist/{chunk-7TENHBV2.js → chunk-RQCTMECT.js} +10 -48
- package/dist/chunk-SSFTU6LP.js +182 -0
- package/dist/{chunk-BXTMZDRT.js → chunk-SVSQAG6M.js} +7 -5
- package/dist/chunk-TLVIQLB4.js +874 -0
- package/dist/{chunk-JJSNPSCD.js → chunk-TNH24SF6.js} +352 -50
- package/dist/chunk-TVKKIS53.js +720 -0
- package/dist/{chunk-YHH3SXKD.js → chunk-WPINX4MF.js} +1 -59
- package/dist/{chunk-HCFFXBLV.js → chunk-XMSDA5WA.js} +5 -1861
- package/dist/chunk-YGGGUTG3.js +125 -0
- package/dist/chunk-YGXXBRV7.js +10 -0
- package/dist/cipher-VHAFCG7Z.js +27 -0
- package/dist/dreams-ledger-3I52ISYR.js +285 -0
- package/dist/{engine-65C2J63X.js → engine-VMTFKFGO.js} +5 -2
- package/dist/{fallback-llm-LVK5PDIM.js → fallback-llm-WCWNGIQ3.js} +2 -1
- package/dist/first-start-migration-I24M2JEE.js +258 -0
- package/dist/forget-NI4RBDPB.js +68 -0
- package/dist/fs-utils-PZRI2HDZ.js +29 -0
- package/dist/graph-edge-decay-5CVKWBYH.js +203 -0
- package/dist/index.js +9791 -2902
- package/dist/kdf-H5B23ZM2.js +25 -0
- package/dist/memory-governance-DWGFV4FX.js +25 -0
- package/dist/metadata-JAGIWHEA.js +20 -0
- package/dist/migrate-from-identity-anchor-N3354WMP.js +7 -0
- package/dist/path-5LCUBAAZ.js +8 -0
- package/dist/peers-JF2I6RCR.js +43 -0
- package/dist/purge-XN2VSPZ2.js +204 -0
- package/dist/secure-store-FWJ7LBPH.js +149 -0
- package/dist/state-PVISYXRH.js +7 -0
- package/dist/state-store-LP5BO6SF.js +15 -0
- package/dist/{storage-DM4ZGOCN.js → storage-T2OGFUF4.js} +3 -1
- package/dist/tier-stats-IZNW66NC.js +147 -0
- package/dist/trace-NJESSGH7.js +289 -0
- package/dist/tui-MGK2LYJY.js +12 -0
- package/dist/types-H5R5D3WF.js +30 -0
- package/openclaw.plugin.json +519 -4
- package/package.json +1 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// ../remnic-core/src/transfer/fs-utils.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import {
|
|
4
|
+
lstat,
|
|
5
|
+
mkdir,
|
|
6
|
+
readdir,
|
|
7
|
+
readFile,
|
|
8
|
+
realpath,
|
|
9
|
+
stat,
|
|
10
|
+
writeFile
|
|
11
|
+
} from "fs/promises";
|
|
12
|
+
import path from "path";
|
|
13
|
+
async function sha256File(filePath) {
|
|
14
|
+
const buf = await readFile(filePath);
|
|
15
|
+
const sha256 = createHash("sha256").update(buf).digest("hex");
|
|
16
|
+
return { sha256, bytes: buf.byteLength };
|
|
17
|
+
}
|
|
18
|
+
function sha256String(content) {
|
|
19
|
+
const buf = Buffer.from(content, "utf-8");
|
|
20
|
+
const sha256 = createHash("sha256").update(buf).digest("hex");
|
|
21
|
+
return { sha256, bytes: buf.byteLength };
|
|
22
|
+
}
|
|
23
|
+
async function writeJsonFile(filePath, value) {
|
|
24
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
25
|
+
await writeFile(filePath, JSON.stringify(value, null, 2) + "\n", "utf-8");
|
|
26
|
+
}
|
|
27
|
+
async function readJsonFile(filePath) {
|
|
28
|
+
const raw = await readFile(filePath, "utf-8");
|
|
29
|
+
return JSON.parse(raw);
|
|
30
|
+
}
|
|
31
|
+
async function listFilesRecursive(rootDir) {
|
|
32
|
+
const out = [];
|
|
33
|
+
async function walk(dir) {
|
|
34
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
35
|
+
for (const ent of entries) {
|
|
36
|
+
const fp = path.join(dir, ent.name);
|
|
37
|
+
if (ent.isDirectory()) {
|
|
38
|
+
await walk(fp);
|
|
39
|
+
} else if (ent.isFile()) {
|
|
40
|
+
out.push(fp);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
await walk(rootDir);
|
|
45
|
+
return out.sort();
|
|
46
|
+
}
|
|
47
|
+
async function ensureDirExists(dirPath) {
|
|
48
|
+
await mkdir(dirPath, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
async function fileExists(filePath) {
|
|
51
|
+
try {
|
|
52
|
+
await stat(filePath);
|
|
53
|
+
return true;
|
|
54
|
+
} catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function toPosixRelPath(absPath, rootDir) {
|
|
59
|
+
const rel = path.relative(rootDir, absPath);
|
|
60
|
+
return rel.split(path.sep).join("/");
|
|
61
|
+
}
|
|
62
|
+
function fromPosixRelPath(relPath) {
|
|
63
|
+
return relPath.split("/").join(path.sep);
|
|
64
|
+
}
|
|
65
|
+
function isPathInsideRoot(rootReal, absPath) {
|
|
66
|
+
const rel = path.relative(rootReal, absPath);
|
|
67
|
+
if (rel === "") return true;
|
|
68
|
+
if (rel === "..") return false;
|
|
69
|
+
if (rel.startsWith(`..${path.sep}`)) return false;
|
|
70
|
+
if (path.isAbsolute(rel)) return false;
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
async function assertIsDirectoryNotSymlink(absPath, errorPrefix, argName) {
|
|
74
|
+
const st = await stat(absPath).catch(() => null);
|
|
75
|
+
if (!st || !st.isDirectory()) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
`${errorPrefix}: '${argName}' must be an existing directory: ${absPath}`
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const lst = await lstat(absPath).catch(() => null);
|
|
81
|
+
if (lst && lst.isSymbolicLink()) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`${errorPrefix}: '${argName}' must not be a symlink \u2014 resolve it to its real path first: ${absPath}`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async function assertRealpathInsideRoot(rootReal, targetAbs, sourcePath, errorPrefix) {
|
|
88
|
+
let existing = targetAbs;
|
|
89
|
+
const suffix = [];
|
|
90
|
+
while (existing !== path.dirname(existing)) {
|
|
91
|
+
const st = await lstat(existing).catch(() => null);
|
|
92
|
+
if (st !== null) break;
|
|
93
|
+
suffix.unshift(path.basename(existing));
|
|
94
|
+
existing = path.dirname(existing);
|
|
95
|
+
}
|
|
96
|
+
const existingReal = await realpath(existing).catch(() => existing);
|
|
97
|
+
const targetReal = suffix.length > 0 ? path.join(existingReal, ...suffix) : existingReal;
|
|
98
|
+
if (!isPathInsideRoot(rootReal, targetReal)) {
|
|
99
|
+
throw new Error(
|
|
100
|
+
`${errorPrefix}: record path escapes target root via symlink: ${sourcePath}`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export {
|
|
106
|
+
sha256File,
|
|
107
|
+
sha256String,
|
|
108
|
+
writeJsonFile,
|
|
109
|
+
readJsonFile,
|
|
110
|
+
listFilesRecursive,
|
|
111
|
+
ensureDirExists,
|
|
112
|
+
fileExists,
|
|
113
|
+
toPosixRelPath,
|
|
114
|
+
fromPosixRelPath,
|
|
115
|
+
isPathInsideRoot,
|
|
116
|
+
assertIsDirectoryNotSymlink,
|
|
117
|
+
assertRealpathInsideRoot
|
|
118
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -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-
|
|
4
|
+
} from "./chunk-WPINX4MF.js";
|
|
5
|
+
import {
|
|
6
|
+
StorageManager,
|
|
7
|
+
isSemanticConsolidationLlmOperator
|
|
8
|
+
} from "./chunk-TNH24SF6.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 =
|
|
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
|
}
|
|
@@ -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
|
|
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(
|
|
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(
|
|
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-
|
|
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
|