@remnic/cli 9.54.8 → 9.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +582 -381
- package/package.json +31 -31
package/dist/index.js
CHANGED
|
@@ -18,21 +18,21 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
|
-
import
|
|
21
|
+
import fs15 from "fs";
|
|
22
22
|
import os3 from "os";
|
|
23
|
-
import
|
|
23
|
+
import path18 from "path";
|
|
24
24
|
import { createHash as createHash4 } from "crypto";
|
|
25
25
|
import * as childProcess2 from "child_process";
|
|
26
26
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
27
27
|
import { gzipSync } from "zlib";
|
|
28
28
|
import {
|
|
29
|
-
parseConfig as
|
|
29
|
+
parseConfig as parseConfig7,
|
|
30
30
|
isOpenaiApiKeyDisabled,
|
|
31
31
|
resolveEnvVars,
|
|
32
|
-
resolveRemnicConfigRecord as
|
|
33
|
-
Orchestrator as
|
|
32
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord6,
|
|
33
|
+
Orchestrator as Orchestrator4,
|
|
34
34
|
EngramAccessService as EngramAccessService2,
|
|
35
|
-
initLogger as
|
|
35
|
+
initLogger as initLogger3,
|
|
36
36
|
onboard,
|
|
37
37
|
curate,
|
|
38
38
|
listReviewItems,
|
|
@@ -2466,8 +2466,53 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
2466
2466
|
assertLocalBenchBuildFreshForDevelopment(import.meta.url);
|
|
2467
2467
|
}
|
|
2468
2468
|
|
|
2469
|
-
// src/
|
|
2469
|
+
// src/cmd-security.ts
|
|
2470
2470
|
import fs7 from "fs";
|
|
2471
|
+
import {
|
|
2472
|
+
Orchestrator as Orchestrator3,
|
|
2473
|
+
parseConfig as parseConfig6,
|
|
2474
|
+
initLogger as initLogger2,
|
|
2475
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord5,
|
|
2476
|
+
runAuditMemoryCliCommand,
|
|
2477
|
+
formatAuditMemoryReport
|
|
2478
|
+
} from "@remnic/core";
|
|
2479
|
+
async function cmdSecurity(rest) {
|
|
2480
|
+
const action = rest[0] ?? "help";
|
|
2481
|
+
if (action !== "audit-memory") {
|
|
2482
|
+
console.error(
|
|
2483
|
+
"Unknown security subcommand. Usage: remnic security audit-memory [--since <iso-date>] [--quarantine] [--json]"
|
|
2484
|
+
);
|
|
2485
|
+
process.exitCode = 1;
|
|
2486
|
+
return;
|
|
2487
|
+
}
|
|
2488
|
+
initLogger2();
|
|
2489
|
+
const configPath = resolveConfigPath();
|
|
2490
|
+
const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
|
|
2491
|
+
const config = parseConfig6(resolveRemnicConfigRecord5(raw));
|
|
2492
|
+
const orchestrator = new Orchestrator3(config);
|
|
2493
|
+
await orchestrator.initialize();
|
|
2494
|
+
try {
|
|
2495
|
+
const sinceFlag = rest.indexOf("--since");
|
|
2496
|
+
if (sinceFlag >= 0 && !rest[sinceFlag + 1]) {
|
|
2497
|
+
console.error("--since requires a value");
|
|
2498
|
+
process.exitCode = 1;
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
const json = rest.includes("--json");
|
|
2502
|
+
const report = await runAuditMemoryCliCommand({
|
|
2503
|
+
memoryDir: config.memoryDir,
|
|
2504
|
+
storage: orchestrator.storage,
|
|
2505
|
+
since: sinceFlag >= 0 ? rest[sinceFlag + 1] : void 0,
|
|
2506
|
+
quarantine: rest.includes("--quarantine")
|
|
2507
|
+
});
|
|
2508
|
+
console.log(json ? JSON.stringify(report, null, 2) : formatAuditMemoryReport(report));
|
|
2509
|
+
} finally {
|
|
2510
|
+
orchestrator.abortDeferredInit();
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
// src/daemon-service-candidates.ts
|
|
2515
|
+
import fs8 from "fs";
|
|
2471
2516
|
import path5 from "path";
|
|
2472
2517
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
2473
2518
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -2489,7 +2534,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
2489
2534
|
function anyFileExists(paths) {
|
|
2490
2535
|
return paths.some((candidate) => {
|
|
2491
2536
|
try {
|
|
2492
|
-
return
|
|
2537
|
+
return fs8.statSync(candidate).isFile();
|
|
2493
2538
|
} catch {
|
|
2494
2539
|
return false;
|
|
2495
2540
|
}
|
|
@@ -2501,7 +2546,7 @@ function commandNames(command) {
|
|
|
2501
2546
|
}
|
|
2502
2547
|
function isRunnableNodeScript(filePath) {
|
|
2503
2548
|
try {
|
|
2504
|
-
const text =
|
|
2549
|
+
const text = fs8.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
2505
2550
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
2506
2551
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
2507
2552
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -2514,7 +2559,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
2514
2559
|
function resolveShimNodeScript(filePath) {
|
|
2515
2560
|
let text;
|
|
2516
2561
|
try {
|
|
2517
|
-
text =
|
|
2562
|
+
text = fs8.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
2518
2563
|
} catch {
|
|
2519
2564
|
return void 0;
|
|
2520
2565
|
}
|
|
@@ -2526,8 +2571,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
2526
2571
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
2527
2572
|
const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
|
|
2528
2573
|
try {
|
|
2529
|
-
if (
|
|
2530
|
-
return
|
|
2574
|
+
if (fs8.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
2575
|
+
return fs8.realpathSync(resolved);
|
|
2531
2576
|
}
|
|
2532
2577
|
} catch {
|
|
2533
2578
|
}
|
|
@@ -2535,7 +2580,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
2535
2580
|
return void 0;
|
|
2536
2581
|
}
|
|
2537
2582
|
function resolveRunnableNodeScript(filePath) {
|
|
2538
|
-
const realPath =
|
|
2583
|
+
const realPath = fs8.realpathSync(filePath);
|
|
2539
2584
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
2540
2585
|
return resolveShimNodeScript(realPath);
|
|
2541
2586
|
}
|
|
@@ -2545,9 +2590,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
2545
2590
|
for (const name of commandNames(command)) {
|
|
2546
2591
|
const candidate = path5.join(dir, name);
|
|
2547
2592
|
try {
|
|
2548
|
-
const stat2 =
|
|
2593
|
+
const stat2 = fs8.statSync(candidate);
|
|
2549
2594
|
if (!stat2.isFile()) continue;
|
|
2550
|
-
if (process.platform !== "win32")
|
|
2595
|
+
if (process.platform !== "win32") fs8.accessSync(candidate, fs8.constants.X_OK);
|
|
2551
2596
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
2552
2597
|
if (runnable) return runnable;
|
|
2553
2598
|
} catch {
|
|
@@ -4038,7 +4083,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
4038
4083
|
}
|
|
4039
4084
|
|
|
4040
4085
|
// src/bench-fallback.ts
|
|
4041
|
-
import
|
|
4086
|
+
import fs9 from "fs";
|
|
4042
4087
|
import path9 from "path";
|
|
4043
4088
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
4044
4089
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -4110,7 +4155,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
4110
4155
|
);
|
|
4111
4156
|
}
|
|
4112
4157
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
4113
|
-
const entries =
|
|
4158
|
+
const entries = fs9.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
4114
4159
|
if (entries.length === 0) {
|
|
4115
4160
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
4116
4161
|
}
|
|
@@ -4118,7 +4163,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
4118
4163
|
}
|
|
4119
4164
|
|
|
4120
4165
|
// src/openclaw-upgrade-swap.ts
|
|
4121
|
-
import
|
|
4166
|
+
import fs10 from "fs";
|
|
4122
4167
|
import path10 from "path";
|
|
4123
4168
|
function describeError(error) {
|
|
4124
4169
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -4130,7 +4175,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
4130
4175
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
4131
4176
|
if (explicitMode !== void 0) return explicitMode;
|
|
4132
4177
|
try {
|
|
4133
|
-
return
|
|
4178
|
+
return fs10.statSync(targetPath).mode & 4095;
|
|
4134
4179
|
} catch (error) {
|
|
4135
4180
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
4136
4181
|
return 384;
|
|
@@ -4140,8 +4185,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
4140
4185
|
}
|
|
4141
4186
|
function resolveAtomicReplacementPath(targetPath) {
|
|
4142
4187
|
try {
|
|
4143
|
-
if (
|
|
4144
|
-
return
|
|
4188
|
+
if (fs10.lstatSync(targetPath).isSymbolicLink()) {
|
|
4189
|
+
return fs10.realpathSync(targetPath);
|
|
4145
4190
|
}
|
|
4146
4191
|
} catch (error) {
|
|
4147
4192
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -4158,7 +4203,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
4158
4203
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
4159
4204
|
if (!displacedDir) return void 0;
|
|
4160
4205
|
try {
|
|
4161
|
-
|
|
4206
|
+
fs10.rmSync(displacedDir, { recursive: true, force: true });
|
|
4162
4207
|
return void 0;
|
|
4163
4208
|
} catch (error) {
|
|
4164
4209
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -4166,43 +4211,43 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
4166
4211
|
}
|
|
4167
4212
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
4168
4213
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4169
|
-
|
|
4214
|
+
fs10.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
4170
4215
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
4171
4216
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
4172
4217
|
try {
|
|
4173
4218
|
if (options.hooks?.writeTempFileSync) {
|
|
4174
4219
|
options.hooks.writeTempFileSync(tempPath);
|
|
4175
4220
|
} else {
|
|
4176
|
-
|
|
4221
|
+
fs10.writeFileSync(tempPath, data, { mode });
|
|
4177
4222
|
}
|
|
4178
|
-
|
|
4179
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
4223
|
+
fs10.chmodSync(tempPath, mode);
|
|
4224
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs10.renameSync;
|
|
4180
4225
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4181
4226
|
} catch (error) {
|
|
4182
|
-
|
|
4227
|
+
fs10.rmSync(tempPath, { force: true });
|
|
4183
4228
|
throw error;
|
|
4184
4229
|
}
|
|
4185
4230
|
}
|
|
4186
4231
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
4187
|
-
if (!
|
|
4232
|
+
if (!fs10.existsSync(sourcePath)) return;
|
|
4188
4233
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
4189
|
-
|
|
4234
|
+
fs10.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
4190
4235
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
4191
|
-
const mode =
|
|
4236
|
+
const mode = fs10.statSync(sourcePath).mode & 4095;
|
|
4192
4237
|
try {
|
|
4193
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
4238
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs10.copyFileSync;
|
|
4194
4239
|
copyTempFileSync(sourcePath, tempPath);
|
|
4195
|
-
|
|
4196
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
4240
|
+
fs10.chmodSync(tempPath, mode);
|
|
4241
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs10.renameSync;
|
|
4197
4242
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
4198
4243
|
} catch (error) {
|
|
4199
|
-
|
|
4244
|
+
fs10.rmSync(tempPath, { force: true });
|
|
4200
4245
|
throw error;
|
|
4201
4246
|
}
|
|
4202
4247
|
}
|
|
4203
4248
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
4204
4249
|
if (!rollbackDir) return;
|
|
4205
|
-
|
|
4250
|
+
fs10.rmSync(rollbackDir, { recursive: true, force: true });
|
|
4206
4251
|
}
|
|
4207
4252
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
4208
4253
|
if (!rollbackDir) return void 0;
|
|
@@ -4214,20 +4259,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
4214
4259
|
}
|
|
4215
4260
|
}
|
|
4216
4261
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
4217
|
-
if (!
|
|
4262
|
+
if (!fs10.existsSync(rollbackDir)) {
|
|
4218
4263
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
4219
4264
|
}
|
|
4220
|
-
|
|
4221
|
-
const displacedDir =
|
|
4265
|
+
fs10.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
4266
|
+
const displacedDir = fs10.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
4222
4267
|
if (displacedDir) {
|
|
4223
|
-
|
|
4268
|
+
fs10.renameSync(targetDir, displacedDir);
|
|
4224
4269
|
}
|
|
4225
4270
|
try {
|
|
4226
|
-
|
|
4271
|
+
fs10.renameSync(rollbackDir, targetDir);
|
|
4227
4272
|
} catch (restoreError) {
|
|
4228
|
-
if (displacedDir &&
|
|
4273
|
+
if (displacedDir && fs10.existsSync(displacedDir)) {
|
|
4229
4274
|
try {
|
|
4230
|
-
|
|
4275
|
+
fs10.renameSync(displacedDir, targetDir);
|
|
4231
4276
|
} catch (revertError) {
|
|
4232
4277
|
throw new AggregateError(
|
|
4233
4278
|
[restoreError, revertError],
|
|
@@ -4243,23 +4288,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
4243
4288
|
return cleanupDisplacedDirectoryBestEffort(displacedDir, `restored the previous plugin copy into ${targetDir}`);
|
|
4244
4289
|
}
|
|
4245
4290
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
4246
|
-
if (!
|
|
4291
|
+
if (!fs10.existsSync(backupDir)) {
|
|
4247
4292
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
4248
4293
|
}
|
|
4249
|
-
|
|
4294
|
+
fs10.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
4250
4295
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
4251
|
-
const displacedDir =
|
|
4252
|
-
|
|
4296
|
+
const displacedDir = fs10.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
4297
|
+
fs10.cpSync(backupDir, stagedDir, { recursive: true });
|
|
4253
4298
|
if (displacedDir) {
|
|
4254
|
-
|
|
4299
|
+
fs10.renameSync(targetDir, displacedDir);
|
|
4255
4300
|
}
|
|
4256
4301
|
try {
|
|
4257
|
-
|
|
4302
|
+
fs10.renameSync(stagedDir, targetDir);
|
|
4258
4303
|
} catch (restoreError) {
|
|
4259
|
-
|
|
4260
|
-
if (displacedDir &&
|
|
4304
|
+
fs10.rmSync(targetDir, { recursive: true, force: true });
|
|
4305
|
+
if (displacedDir && fs10.existsSync(displacedDir)) {
|
|
4261
4306
|
try {
|
|
4262
|
-
|
|
4307
|
+
fs10.renameSync(displacedDir, targetDir);
|
|
4263
4308
|
} catch (revertError) {
|
|
4264
4309
|
throw new AggregateError(
|
|
4265
4310
|
[restoreError, revertError],
|
|
@@ -4267,7 +4312,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
4267
4312
|
);
|
|
4268
4313
|
}
|
|
4269
4314
|
}
|
|
4270
|
-
|
|
4315
|
+
fs10.rmSync(stagedDir, { recursive: true, force: true });
|
|
4271
4316
|
throw new Error(
|
|
4272
4317
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
4273
4318
|
{ cause: restoreError }
|
|
@@ -4292,7 +4337,7 @@ function rollbackOpenclawUpgrade({
|
|
|
4292
4337
|
let configRemovalAttempted = false;
|
|
4293
4338
|
let pluginRestored = false;
|
|
4294
4339
|
try {
|
|
4295
|
-
if (rollbackDir &&
|
|
4340
|
+
if (rollbackDir && fs10.existsSync(rollbackDir)) {
|
|
4296
4341
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
4297
4342
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
4298
4343
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -4302,7 +4347,7 @@ function rollbackOpenclawUpgrade({
|
|
|
4302
4347
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
4303
4348
|
}
|
|
4304
4349
|
try {
|
|
4305
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
4350
|
+
if (!pluginRestored && pluginBackupDir && fs10.existsSync(pluginBackupDir)) {
|
|
4306
4351
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
4307
4352
|
if (rollbackRestoreError) {
|
|
4308
4353
|
notes.push(`Rollback copy restore failed; restored previous plugin from durable backup at ${pluginBackupDir}`);
|
|
@@ -4327,12 +4372,12 @@ function rollbackOpenclawUpgrade({
|
|
|
4327
4372
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
4328
4373
|
}
|
|
4329
4374
|
try {
|
|
4330
|
-
if (configBackupPath &&
|
|
4375
|
+
if (configBackupPath && fs10.existsSync(configBackupPath)) {
|
|
4331
4376
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
4332
4377
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
4333
|
-
} else if (removeConfigIfUnbacked &&
|
|
4378
|
+
} else if (removeConfigIfUnbacked && fs10.existsSync(configPath)) {
|
|
4334
4379
|
configRemovalAttempted = true;
|
|
4335
|
-
|
|
4380
|
+
fs10.rmSync(configPath, { force: true });
|
|
4336
4381
|
notes.push("Removed OpenClaw config created during the failed upgrade");
|
|
4337
4382
|
}
|
|
4338
4383
|
} catch (error) {
|
|
@@ -4385,7 +4430,7 @@ Run this manually when you're ready:
|
|
|
4385
4430
|
|
|
4386
4431
|
// src/openclaw-managed-upgrade-loader.ts
|
|
4387
4432
|
import { execFileSync } from "child_process";
|
|
4388
|
-
import
|
|
4433
|
+
import fs11 from "fs";
|
|
4389
4434
|
import os from "os";
|
|
4390
4435
|
import path11 from "path";
|
|
4391
4436
|
import { fileURLToPath as fileURLToPath3, pathToFileURL as pathToFileURL2 } from "url";
|
|
@@ -4461,7 +4506,7 @@ function buildOpenclawManagedUpgradePackageSpec(version = "latest") {
|
|
|
4461
4506
|
function readCliAdapterRange() {
|
|
4462
4507
|
const moduleDir = path11.dirname(fileURLToPath3(import.meta.url));
|
|
4463
4508
|
const manifestPath = path11.resolve(moduleDir, "../package.json");
|
|
4464
|
-
const manifest = JSON.parse(
|
|
4509
|
+
const manifest = JSON.parse(fs11.readFileSync(manifestPath, "utf8"));
|
|
4465
4510
|
if (manifest.name !== "@remnic/cli") {
|
|
4466
4511
|
throw new Error(`Invalid @remnic/cli package manifest at ${manifestPath}.`);
|
|
4467
4512
|
}
|
|
@@ -4505,7 +4550,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
4505
4550
|
const adapterMissing = isSpecifierNotFoundError(error, OPENCLAW_PLUGIN_PACKAGE) || isSpecifierNotFoundError(error, MANAGED_UPGRADE_SPECIFIER) || isManagedUpgradeSubpathMissing(error);
|
|
4506
4551
|
if (!adapterMissing) throw error;
|
|
4507
4552
|
}
|
|
4508
|
-
const temporaryRoot =
|
|
4553
|
+
const temporaryRoot = fs11.mkdtempSync(path11.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
4509
4554
|
try {
|
|
4510
4555
|
const toolingPackageSpec = `${OPENCLAW_PLUGIN_PACKAGE}@${readCliAdapterRange()}`;
|
|
4511
4556
|
const installArgs = [
|
|
@@ -4520,12 +4565,12 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
4520
4565
|
];
|
|
4521
4566
|
(hooks.runNpmInstall ?? runNpmInstall)(installArgs);
|
|
4522
4567
|
const resolverPath = path11.join(temporaryRoot, "load-managed-upgrade.mjs");
|
|
4523
|
-
|
|
4568
|
+
fs11.writeFileSync(resolverPath, `export * from ${JSON.stringify(MANAGED_UPGRADE_SPECIFIER)};
|
|
4524
4569
|
`, "utf8");
|
|
4525
4570
|
return await importModule(pathToFileURL2(resolverPath).href);
|
|
4526
4571
|
} finally {
|
|
4527
4572
|
try {
|
|
4528
|
-
|
|
4573
|
+
fs11.rmSync(temporaryRoot, { recursive: true, force: true });
|
|
4529
4574
|
} catch (error) {
|
|
4530
4575
|
const detail = error instanceof Error ? error.message : String(error);
|
|
4531
4576
|
console.warn(`Could not remove temporary managed upgrade project at ${temporaryRoot}: ${detail}`);
|
|
@@ -4534,7 +4579,7 @@ async function loadOpenclawManagedUpgradeModule(packageSpec, hooks = {}) {
|
|
|
4534
4579
|
}
|
|
4535
4580
|
|
|
4536
4581
|
// src/daemon-service.ts
|
|
4537
|
-
import
|
|
4582
|
+
import fs12 from "fs";
|
|
4538
4583
|
import path12 from "path";
|
|
4539
4584
|
import * as childProcess from "child_process";
|
|
4540
4585
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
@@ -4546,7 +4591,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
4546
4591
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
4547
4592
|
}
|
|
4548
4593
|
function resolveServerBinDetails(options = {}) {
|
|
4549
|
-
const existsSync4 = options.existsSync ??
|
|
4594
|
+
const existsSync4 = options.existsSync ?? fs12.existsSync;
|
|
4550
4595
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
4551
4596
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
4552
4597
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -4605,8 +4650,8 @@ function resolveServerBin(options = {}) {
|
|
|
4605
4650
|
return resolveServerBinDetails(options).path;
|
|
4606
4651
|
}
|
|
4607
4652
|
function readVerifiedDaemonPid(options) {
|
|
4608
|
-
const readFileSync4 = options.readFileSync ??
|
|
4609
|
-
const unlinkSync = options.unlinkSync ??
|
|
4653
|
+
const readFileSync4 = options.readFileSync ?? fs12.readFileSync;
|
|
4654
|
+
const unlinkSync = options.unlinkSync ?? fs12.unlinkSync;
|
|
4610
4655
|
const processKill = options.processKill ?? process.kill;
|
|
4611
4656
|
const platform = options.platform ?? process.platform;
|
|
4612
4657
|
const execFileSync4 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
@@ -4706,8 +4751,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
4706
4751
|
}
|
|
4707
4752
|
}
|
|
4708
4753
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
4709
|
-
const existsSync4 = options.existsSync ??
|
|
4710
|
-
const readFileSync4 = options.readFileSync ??
|
|
4754
|
+
const existsSync4 = options.existsSync ?? fs12.existsSync;
|
|
4755
|
+
const readFileSync4 = options.readFileSync ?? fs12.readFileSync;
|
|
4711
4756
|
if (!existsSync4(plistPath)) {
|
|
4712
4757
|
return {
|
|
4713
4758
|
installed: false,
|
|
@@ -4941,7 +4986,7 @@ function stripConfigArgv(args) {
|
|
|
4941
4986
|
}
|
|
4942
4987
|
|
|
4943
4988
|
// src/import-dispatch.ts
|
|
4944
|
-
import
|
|
4989
|
+
import fs13 from "fs";
|
|
4945
4990
|
import {
|
|
4946
4991
|
runImporter,
|
|
4947
4992
|
validateImportBatchSize,
|
|
@@ -5455,7 +5500,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
5455
5500
|
let materializedTarget;
|
|
5456
5501
|
let materializePromise;
|
|
5457
5502
|
const io = {
|
|
5458
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
5503
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs13.promises.readFile(p, "utf-8")),
|
|
5459
5504
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
5460
5505
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
5461
5506
|
getWriteTarget: async () => {
|
|
@@ -5568,7 +5613,7 @@ async function cmdCapture(rest, io) {
|
|
|
5568
5613
|
}
|
|
5569
5614
|
|
|
5570
5615
|
// src/import-lossless-claw-cmd.ts
|
|
5571
|
-
import
|
|
5616
|
+
import fs14 from "fs";
|
|
5572
5617
|
import path14 from "path";
|
|
5573
5618
|
import {
|
|
5574
5619
|
applyLcmSchema,
|
|
@@ -5680,15 +5725,15 @@ async function loadImportLosslessClawModule() {
|
|
|
5680
5725
|
|
|
5681
5726
|
// src/import-lossless-claw-cmd.ts
|
|
5682
5727
|
function assertDirectoryOrAbsent(p, label) {
|
|
5683
|
-
if (
|
|
5728
|
+
if (fs14.existsSync(p) && !fs14.statSync(p).isDirectory()) {
|
|
5684
5729
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
5685
5730
|
}
|
|
5686
5731
|
}
|
|
5687
5732
|
function assertFile(p, label) {
|
|
5688
|
-
if (!
|
|
5733
|
+
if (!fs14.existsSync(p)) {
|
|
5689
5734
|
throw new Error(`${label} does not exist: ${p}`);
|
|
5690
5735
|
}
|
|
5691
|
-
if (!
|
|
5736
|
+
if (!fs14.statSync(p).isFile()) {
|
|
5692
5737
|
throw new Error(`${label} is not a file: ${p}`);
|
|
5693
5738
|
}
|
|
5694
5739
|
}
|
|
@@ -5720,7 +5765,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
5720
5765
|
try {
|
|
5721
5766
|
if (parsed.dryRun) {
|
|
5722
5767
|
const lcmPath = path14.join(memoryDir, "state", "lcm.sqlite");
|
|
5723
|
-
if (
|
|
5768
|
+
if (fs14.existsSync(lcmPath)) {
|
|
5724
5769
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
5725
5770
|
} else {
|
|
5726
5771
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -6459,8 +6504,158 @@ async function cmdBenchCoding(args) {
|
|
|
6459
6504
|
if (result.exitCode !== 0) process.exitCode = result.exitCode;
|
|
6460
6505
|
}
|
|
6461
6506
|
|
|
6462
|
-
// src/bench-
|
|
6507
|
+
// src/bench-security-commands.ts
|
|
6463
6508
|
import path16 from "path";
|
|
6509
|
+
var DEFAULT_OUTPUT_DIR = path16.join(
|
|
6510
|
+
resolveHomeDir(),
|
|
6511
|
+
".remnic",
|
|
6512
|
+
"bench",
|
|
6513
|
+
"results",
|
|
6514
|
+
"h5-injection-suite"
|
|
6515
|
+
);
|
|
6516
|
+
var BENCH_SECURITY_USAGE = `Usage: remnic bench security injection-suite --seeds N [options]
|
|
6517
|
+
|
|
6518
|
+
H5 injection-suite runner. Resume, host-fault pause, multi-host claim
|
|
6519
|
+
leases, and --limit follow the H6 contract (issue #1963 / PR #2312).
|
|
6520
|
+
|
|
6521
|
+
Options:
|
|
6522
|
+
--seeds N Positive seed count (required)
|
|
6523
|
+
--variants-per-family N Variants per attack family (default: 25)
|
|
6524
|
+
--model-profile ID Profile label recorded on each row (default: local-dry)
|
|
6525
|
+
--executor local|ollama|openai-compat
|
|
6526
|
+
local = deterministic screen/fence (default)
|
|
6527
|
+
ollama = native /api/chat
|
|
6528
|
+
openai-compat = /v1/chat/completions
|
|
6529
|
+
--base-url URL Endpoint (default: http://127.0.0.1:11434)
|
|
6530
|
+
--model NAME Model id (default: qwen2.5:7b-instruct)
|
|
6531
|
+
--request-timeout-ms N Per-call timeout (default: 120000)
|
|
6532
|
+
--out DIR New run directory (default: ~/.remnic/bench/results/h5-injection-suite)
|
|
6533
|
+
--run DIR Existing run directory; implies --resume
|
|
6534
|
+
--resume Continue an existing run (required if DIR already has run.json)
|
|
6535
|
+
--limit N Execute at most N planned rows (dry-run / smoke)
|
|
6536
|
+
`;
|
|
6537
|
+
function parsePositiveInteger(raw, flag) {
|
|
6538
|
+
const value = Number(raw);
|
|
6539
|
+
if (!Number.isInteger(value) || value < 1) {
|
|
6540
|
+
throw new Error(`${flag} must be a positive integer`);
|
|
6541
|
+
}
|
|
6542
|
+
return value;
|
|
6543
|
+
}
|
|
6544
|
+
function parseBenchSecurityArgs(args) {
|
|
6545
|
+
if (args.length === 0 || args[0] === "--help" || args[0] === "-h") return { help: true };
|
|
6546
|
+
if (args[0] !== "injection-suite") {
|
|
6547
|
+
throw new Error(`unknown bench security subcommand ${args[0]}`);
|
|
6548
|
+
}
|
|
6549
|
+
let seeds;
|
|
6550
|
+
let variantsPerFamily = 25;
|
|
6551
|
+
let modelProfileId = "local-dry";
|
|
6552
|
+
let outputDir = DEFAULT_OUTPUT_DIR;
|
|
6553
|
+
let resume = false;
|
|
6554
|
+
let limit;
|
|
6555
|
+
let executor = "local";
|
|
6556
|
+
let baseUrl;
|
|
6557
|
+
let model;
|
|
6558
|
+
let requestTimeoutMs;
|
|
6559
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
6560
|
+
const flag = args[index] ?? "";
|
|
6561
|
+
const next = args[index + 1];
|
|
6562
|
+
if (flag === "--seeds") {
|
|
6563
|
+
seeds = parsePositiveInteger(next, "--seeds");
|
|
6564
|
+
index += 1;
|
|
6565
|
+
} else if (flag === "--variants-per-family") {
|
|
6566
|
+
variantsPerFamily = parsePositiveInteger(next, "--variants-per-family");
|
|
6567
|
+
index += 1;
|
|
6568
|
+
} else if (flag === "--model-profile") {
|
|
6569
|
+
if (next === void 0 || next.startsWith("-")) throw new Error("missing value for --model-profile");
|
|
6570
|
+
modelProfileId = next;
|
|
6571
|
+
index += 1;
|
|
6572
|
+
} else if (flag === "--executor") {
|
|
6573
|
+
if (next !== "local" && next !== "ollama" && next !== "openai-compat") {
|
|
6574
|
+
throw new Error("--executor must be local, ollama, or openai-compat");
|
|
6575
|
+
}
|
|
6576
|
+
executor = next;
|
|
6577
|
+
index += 1;
|
|
6578
|
+
} else if (flag === "--base-url") {
|
|
6579
|
+
if (next === void 0 || next.startsWith("-")) throw new Error("missing value for --base-url");
|
|
6580
|
+
baseUrl = next;
|
|
6581
|
+
index += 1;
|
|
6582
|
+
} else if (flag === "--model") {
|
|
6583
|
+
if (next === void 0 || next.startsWith("-")) throw new Error("missing value for --model");
|
|
6584
|
+
model = next;
|
|
6585
|
+
index += 1;
|
|
6586
|
+
} else if (flag === "--request-timeout-ms") {
|
|
6587
|
+
requestTimeoutMs = parsePositiveInteger(next, "--request-timeout-ms");
|
|
6588
|
+
index += 1;
|
|
6589
|
+
} else if (flag === "--out") {
|
|
6590
|
+
if (next === void 0 || next.startsWith("-")) throw new Error("missing value for --out");
|
|
6591
|
+
outputDir = expandTilde(next);
|
|
6592
|
+
index += 1;
|
|
6593
|
+
} else if (flag === "--run") {
|
|
6594
|
+
if (next === void 0 || next.startsWith("-")) throw new Error("missing value for --run");
|
|
6595
|
+
outputDir = expandTilde(next);
|
|
6596
|
+
resume = true;
|
|
6597
|
+
index += 1;
|
|
6598
|
+
} else if (flag === "--resume") {
|
|
6599
|
+
resume = true;
|
|
6600
|
+
} else if (flag === "--limit") {
|
|
6601
|
+
limit = parsePositiveInteger(next, "--limit");
|
|
6602
|
+
index += 1;
|
|
6603
|
+
} else {
|
|
6604
|
+
throw new Error(`unknown option ${flag}`);
|
|
6605
|
+
}
|
|
6606
|
+
}
|
|
6607
|
+
if (seeds === void 0) throw new Error("injection-suite requires --seeds N");
|
|
6608
|
+
return {
|
|
6609
|
+
seeds,
|
|
6610
|
+
variantsPerFamily,
|
|
6611
|
+
modelProfileId,
|
|
6612
|
+
outputDir,
|
|
6613
|
+
resume,
|
|
6614
|
+
executor,
|
|
6615
|
+
...limit === void 0 ? {} : { limit },
|
|
6616
|
+
...baseUrl === void 0 ? {} : { baseUrl },
|
|
6617
|
+
...model === void 0 ? {} : { model },
|
|
6618
|
+
...requestTimeoutMs === void 0 ? {} : { requestTimeoutMs }
|
|
6619
|
+
};
|
|
6620
|
+
}
|
|
6621
|
+
async function cmdBenchSecurity(args) {
|
|
6622
|
+
try {
|
|
6623
|
+
const parsed = parseBenchSecurityArgs(args);
|
|
6624
|
+
if ("help" in parsed) {
|
|
6625
|
+
console.log(BENCH_SECURITY_USAGE);
|
|
6626
|
+
return;
|
|
6627
|
+
}
|
|
6628
|
+
const bench = await loadBenchModule();
|
|
6629
|
+
const run = bench.runInjectionSuiteCliCommand;
|
|
6630
|
+
if (typeof run !== "function") {
|
|
6631
|
+
throw new Error("Installed @remnic/bench is missing runInjectionSuiteCliCommand");
|
|
6632
|
+
}
|
|
6633
|
+
const result = await run({
|
|
6634
|
+
seeds: parsed.seeds,
|
|
6635
|
+
variantsPerFamily: parsed.variantsPerFamily,
|
|
6636
|
+
modelProfileId: parsed.modelProfileId,
|
|
6637
|
+
outputDir: parsed.outputDir,
|
|
6638
|
+
executor: parsed.executor,
|
|
6639
|
+
...parsed.resume ? { resume: true } : {},
|
|
6640
|
+
...parsed.limit === void 0 ? {} : { limit: parsed.limit },
|
|
6641
|
+
...parsed.baseUrl === void 0 ? {} : { baseUrl: parsed.baseUrl },
|
|
6642
|
+
...parsed.model === void 0 ? {} : { model: parsed.model },
|
|
6643
|
+
...parsed.requestTimeoutMs === void 0 ? {} : { requestTimeoutMs: parsed.requestTimeoutMs }
|
|
6644
|
+
});
|
|
6645
|
+
if (result.exitCode === 0) console.log(result.output);
|
|
6646
|
+
else console.error(result.output);
|
|
6647
|
+
if (result.exitCode !== 0) process.exitCode = result.exitCode;
|
|
6648
|
+
} catch (error) {
|
|
6649
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
6650
|
+
console.error(`${message}
|
|
6651
|
+
|
|
6652
|
+
${BENCH_SECURITY_USAGE}`);
|
|
6653
|
+
process.exitCode = 1;
|
|
6654
|
+
}
|
|
6655
|
+
}
|
|
6656
|
+
|
|
6657
|
+
// src/bench-research-commands.ts
|
|
6658
|
+
import path17 from "path";
|
|
6464
6659
|
function emit(result) {
|
|
6465
6660
|
if (result.output) {
|
|
6466
6661
|
console.log(result.output);
|
|
@@ -6478,7 +6673,7 @@ async function runBenchResearchCommand(parsed) {
|
|
|
6478
6673
|
emit(
|
|
6479
6674
|
await runAttributeCliCommand({
|
|
6480
6675
|
runRef: parsed.runRef,
|
|
6481
|
-
resultsDir: parsed.resultsDir ??
|
|
6676
|
+
resultsDir: parsed.resultsDir ?? path17.join(resolveHomeDir(), ".remnic", "bench", "results"),
|
|
6482
6677
|
memoryDir: parsed.memoryDir,
|
|
6483
6678
|
qmdPath: parsed.qmdPath,
|
|
6484
6679
|
collection: parsed.collection,
|
|
@@ -6507,8 +6702,8 @@ async function runBenchResearchCommand(parsed) {
|
|
|
6507
6702
|
|
|
6508
6703
|
// src/bench-usage.ts
|
|
6509
6704
|
function getBenchUsageText() {
|
|
6510
|
-
return `Usage: remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|attribute|drift-gen|coding> [options] [benchmark...]
|
|
6511
|
-
remnic benchmark <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|check|report|attribute|drift-gen|coding> [options] [benchmark...]
|
|
6705
|
+
return `Usage: remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|attribute|drift-gen|coding|security> [options] [benchmark...]
|
|
6706
|
+
remnic benchmark <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|check|report|attribute|drift-gen|coding|security> [options] [benchmark...]
|
|
6512
6707
|
|
|
6513
6708
|
Commands:
|
|
6514
6709
|
list List published benchmark packs
|
|
@@ -6546,6 +6741,8 @@ Commands:
|
|
|
6546
6741
|
coding H6 synthetic coding benchmark commands
|
|
6547
6742
|
Run \`remnic bench coding --help\` for repo generation,
|
|
6548
6743
|
repeated-failure runs, resume, and offline stats replay
|
|
6744
|
+
security H5 injection-suite runner (resume/pause/--limit)
|
|
6745
|
+
Run \`remnic bench security --help\`
|
|
6549
6746
|
check Legacy latency regression gate (compatibility)
|
|
6550
6747
|
attribute --run <id> [--results-dir <path>] [--memory-dir <path>] [--threshold <value>]
|
|
6551
6748
|
[--qmd <path> --collection <name>]
|
|
@@ -6748,15 +6945,15 @@ registerPublisher("omp", () => new LazyPluginPiPublisher("omp", (mod) => mod.Omp
|
|
|
6748
6945
|
function readCompatEnv(primary, legacy) {
|
|
6749
6946
|
return process.env[primary] ?? process.env[legacy];
|
|
6750
6947
|
}
|
|
6751
|
-
var PID_DIR =
|
|
6752
|
-
var LEGACY_PID_DIR =
|
|
6753
|
-
var PID_FILE =
|
|
6754
|
-
var LEGACY_PID_FILE =
|
|
6755
|
-
var LOG_FILE =
|
|
6756
|
-
var LEGACY_LOG_FILE =
|
|
6757
|
-
var CLI_MODULE_DIR =
|
|
6758
|
-
var CLI_REPO_ROOT =
|
|
6759
|
-
var EVAL_RUNNER_PATH =
|
|
6948
|
+
var PID_DIR = path18.join(resolveHomeDir(), ".remnic");
|
|
6949
|
+
var LEGACY_PID_DIR = path18.join(resolveHomeDir(), ".engram");
|
|
6950
|
+
var PID_FILE = path18.join(PID_DIR, "server.pid");
|
|
6951
|
+
var LEGACY_PID_FILE = path18.join(LEGACY_PID_DIR, "server.pid");
|
|
6952
|
+
var LOG_FILE = path18.join(PID_DIR, "server.log");
|
|
6953
|
+
var LEGACY_LOG_FILE = path18.join(LEGACY_PID_DIR, "server.log");
|
|
6954
|
+
var CLI_MODULE_DIR = path18.dirname(fileURLToPath5(import.meta.url));
|
|
6955
|
+
var CLI_REPO_ROOT = path18.resolve(CLI_MODULE_DIR, "../../..");
|
|
6956
|
+
var EVAL_RUNNER_PATH = path18.join(CLI_REPO_ROOT, "evals", "run.ts");
|
|
6760
6957
|
var OPENCLAW_GATEWAY_LABEL = "ai.openclaw.gateway";
|
|
6761
6958
|
var CLI_SUCCESS_EXIT_GRACE_MS = 5e3;
|
|
6762
6959
|
var CLI_OUTPUT_FLUSH_GRACE_MS = 250;
|
|
@@ -6921,7 +7118,7 @@ async function resolveAllBenchmarks() {
|
|
|
6921
7118
|
if (packageBenchmarks) {
|
|
6922
7119
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
6923
7120
|
}
|
|
6924
|
-
if (!
|
|
7121
|
+
if (!fs15.existsSync(EVAL_RUNNER_PATH)) {
|
|
6925
7122
|
return [];
|
|
6926
7123
|
}
|
|
6927
7124
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -6969,17 +7166,17 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
6969
7166
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
6970
7167
|
);
|
|
6971
7168
|
}
|
|
6972
|
-
if (!
|
|
7169
|
+
if (!fs15.existsSync(EVAL_RUNNER_PATH)) {
|
|
6973
7170
|
console.error(
|
|
6974
7171
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
6975
7172
|
);
|
|
6976
7173
|
process.exit(1);
|
|
6977
7174
|
}
|
|
6978
7175
|
const tsxCandidates = [
|
|
6979
|
-
|
|
6980
|
-
|
|
7176
|
+
path18.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
7177
|
+
path18.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
6981
7178
|
];
|
|
6982
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
7179
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs15.existsSync(candidate)) ?? "tsx";
|
|
6983
7180
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
6984
7181
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
6985
7182
|
benchmarkId,
|
|
@@ -6996,7 +7193,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
6996
7193
|
return resolveFallbackBenchResultPath(fallbackOutputDir);
|
|
6997
7194
|
}
|
|
6998
7195
|
function resolveBenchOutputDir() {
|
|
6999
|
-
return
|
|
7196
|
+
return path18.join(resolveHomeDir(), ".remnic", "bench", "results");
|
|
7000
7197
|
}
|
|
7001
7198
|
var DOWNLOADABLE_BENCHMARK_DATASETS = [
|
|
7002
7199
|
"ama-bench",
|
|
@@ -7041,8 +7238,8 @@ var MEMORY_AGENT_BENCH_SPLIT_FILENAMES = [
|
|
|
7041
7238
|
];
|
|
7042
7239
|
var MEMORY_AGENT_BENCH_ENTITY_MAPPING_CANDIDATES = [
|
|
7043
7240
|
"entity2id.json",
|
|
7044
|
-
|
|
7045
|
-
|
|
7241
|
+
path18.join("processed_data", "Recsys_Redial", "entity2id.json"),
|
|
7242
|
+
path18.join("Recsys_Redial", "entity2id.json")
|
|
7046
7243
|
];
|
|
7047
7244
|
var DOWNLOADED_DATASET_MARKERS = {
|
|
7048
7245
|
"ama-bench": { anyOf: ["open_end_qa_set.jsonl"] },
|
|
@@ -7117,18 +7314,18 @@ var PERSONAMEM_DATASET_FILE_CANDIDATES = [
|
|
|
7117
7314
|
"benchmark/benchmark.csv",
|
|
7118
7315
|
"benchmark.csv"
|
|
7119
7316
|
];
|
|
7120
|
-
var PERSONAMEM_COMPLETION_MARKER =
|
|
7317
|
+
var PERSONAMEM_COMPLETION_MARKER = path18.join(
|
|
7121
7318
|
"data",
|
|
7122
7319
|
"chat_history_32k",
|
|
7123
7320
|
".download-complete"
|
|
7124
7321
|
);
|
|
7125
7322
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
7126
7323
|
try {
|
|
7127
|
-
const datasetRoot =
|
|
7128
|
-
const candidatePath =
|
|
7129
|
-
const candidateRealPath =
|
|
7130
|
-
const relativeToRoot =
|
|
7131
|
-
if (relativeToRoot.startsWith("..") ||
|
|
7324
|
+
const datasetRoot = fs15.realpathSync(datasetPath);
|
|
7325
|
+
const candidatePath = path18.resolve(datasetRoot, relativePath);
|
|
7326
|
+
const candidateRealPath = fs15.realpathSync(candidatePath);
|
|
7327
|
+
const relativeToRoot = path18.relative(datasetRoot, candidateRealPath);
|
|
7328
|
+
if (relativeToRoot.startsWith("..") || path18.isAbsolute(relativeToRoot)) {
|
|
7132
7329
|
return null;
|
|
7133
7330
|
}
|
|
7134
7331
|
return candidateRealPath;
|
|
@@ -7184,15 +7381,15 @@ function parseCsvRows(raw) {
|
|
|
7184
7381
|
}
|
|
7185
7382
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
7186
7383
|
try {
|
|
7187
|
-
const completionMarkerPath =
|
|
7188
|
-
if (
|
|
7384
|
+
const completionMarkerPath = path18.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
7385
|
+
if (fs15.statSync(completionMarkerPath).isFile()) {
|
|
7189
7386
|
return true;
|
|
7190
7387
|
}
|
|
7191
7388
|
} catch {
|
|
7192
7389
|
}
|
|
7193
7390
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
7194
7391
|
try {
|
|
7195
|
-
return
|
|
7392
|
+
return fs15.statSync(path18.join(datasetPath, candidate)).isFile();
|
|
7196
7393
|
} catch {
|
|
7197
7394
|
return false;
|
|
7198
7395
|
}
|
|
@@ -7201,7 +7398,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
7201
7398
|
return false;
|
|
7202
7399
|
}
|
|
7203
7400
|
try {
|
|
7204
|
-
const rows = parseCsvRows(
|
|
7401
|
+
const rows = parseCsvRows(fs15.readFileSync(path18.join(datasetPath, datasetFile), "utf8"));
|
|
7205
7402
|
if (rows.length < 2) {
|
|
7206
7403
|
return false;
|
|
7207
7404
|
}
|
|
@@ -7216,7 +7413,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
7216
7413
|
}
|
|
7217
7414
|
return historyPaths.every((relativePath) => {
|
|
7218
7415
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
7219
|
-
return resolvedPath !== null &&
|
|
7416
|
+
return resolvedPath !== null && fs15.statSync(resolvedPath).isFile();
|
|
7220
7417
|
});
|
|
7221
7418
|
} catch {
|
|
7222
7419
|
return false;
|
|
@@ -7224,14 +7421,14 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
7224
7421
|
}
|
|
7225
7422
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
7226
7423
|
try {
|
|
7227
|
-
return
|
|
7424
|
+
return fs15.statSync(path18.join(datasetPath, relativePath)).isFile();
|
|
7228
7425
|
} catch {
|
|
7229
7426
|
return false;
|
|
7230
7427
|
}
|
|
7231
7428
|
}
|
|
7232
7429
|
function hasMemoryAgentBenchEntityMapping(datasetPath) {
|
|
7233
|
-
const absoluteDatasetPath =
|
|
7234
|
-
const roots = [absoluteDatasetPath,
|
|
7430
|
+
const absoluteDatasetPath = path18.resolve(datasetPath);
|
|
7431
|
+
const roots = [absoluteDatasetPath, path18.dirname(absoluteDatasetPath)];
|
|
7235
7432
|
return hasDatasetFile(absoluteDatasetPath, "entity2id.json") || roots.some(
|
|
7236
7433
|
(root) => MEMORY_AGENT_BENCH_ENTITY_MAPPING_CANDIDATES.filter((relativePath) => relativePath !== "entity2id.json").some((relativePath) => hasDatasetFile(root, relativePath))
|
|
7237
7434
|
);
|
|
@@ -7242,12 +7439,12 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
7242
7439
|
...MEMORY_AGENT_BENCH_SPLIT_FILENAMES
|
|
7243
7440
|
];
|
|
7244
7441
|
return candidateFilenames.some((filename) => {
|
|
7245
|
-
const filePath =
|
|
7442
|
+
const filePath = path18.join(datasetPath, filename);
|
|
7246
7443
|
try {
|
|
7247
|
-
if (!
|
|
7444
|
+
if (!fs15.statSync(filePath).isFile()) {
|
|
7248
7445
|
return false;
|
|
7249
7446
|
}
|
|
7250
|
-
const raw =
|
|
7447
|
+
const raw = fs15.readFileSync(filePath, "utf8");
|
|
7251
7448
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
7252
7449
|
} catch {
|
|
7253
7450
|
return false;
|
|
@@ -7263,7 +7460,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
7263
7460
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
7264
7461
|
let stats;
|
|
7265
7462
|
try {
|
|
7266
|
-
stats =
|
|
7463
|
+
stats = fs15.statSync(datasetPath);
|
|
7267
7464
|
} catch {
|
|
7268
7465
|
return false;
|
|
7269
7466
|
}
|
|
@@ -7273,7 +7470,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7273
7470
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
7274
7471
|
if (!marker) {
|
|
7275
7472
|
try {
|
|
7276
|
-
return
|
|
7473
|
+
return fs15.readdirSync(datasetPath).length > 0;
|
|
7277
7474
|
} catch {
|
|
7278
7475
|
return false;
|
|
7279
7476
|
}
|
|
@@ -7281,7 +7478,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7281
7478
|
if (marker.allOf) {
|
|
7282
7479
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
7283
7480
|
try {
|
|
7284
|
-
return
|
|
7481
|
+
return fs15.statSync(path18.join(datasetPath, name)).isFile();
|
|
7285
7482
|
} catch {
|
|
7286
7483
|
return false;
|
|
7287
7484
|
}
|
|
@@ -7293,7 +7490,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7293
7490
|
if (marker.anyOf) {
|
|
7294
7491
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
7295
7492
|
try {
|
|
7296
|
-
return
|
|
7493
|
+
return fs15.statSync(path18.join(datasetPath, name)).isFile();
|
|
7297
7494
|
} catch {
|
|
7298
7495
|
return false;
|
|
7299
7496
|
}
|
|
@@ -7311,7 +7508,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7311
7508
|
}
|
|
7312
7509
|
if (marker.ext) {
|
|
7313
7510
|
try {
|
|
7314
|
-
return
|
|
7511
|
+
return fs15.readdirSync(datasetPath).some(
|
|
7315
7512
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
7316
7513
|
);
|
|
7317
7514
|
} catch {
|
|
@@ -7321,9 +7518,9 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
7321
7518
|
return false;
|
|
7322
7519
|
}
|
|
7323
7520
|
async function launchBenchUi(resultsDir) {
|
|
7324
|
-
const benchUiDir =
|
|
7521
|
+
const benchUiDir = path18.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
7325
7522
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
7326
|
-
if (!
|
|
7523
|
+
if (!fs15.existsSync(path18.join(benchUiDir, "package.json"))) {
|
|
7327
7524
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
7328
7525
|
process.exit(1);
|
|
7329
7526
|
}
|
|
@@ -7350,24 +7547,24 @@ async function launchBenchUi(resultsDir) {
|
|
|
7350
7547
|
});
|
|
7351
7548
|
}
|
|
7352
7549
|
function resolveRepoDatasetRoot() {
|
|
7353
|
-
const repoCandidate =
|
|
7550
|
+
const repoCandidate = path18.join(CLI_REPO_ROOT, "evals", "datasets");
|
|
7354
7551
|
if (isRepoCheckout()) {
|
|
7355
7552
|
return repoCandidate;
|
|
7356
7553
|
}
|
|
7357
|
-
return
|
|
7554
|
+
return path18.join(resolveHomeDir(), ".remnic", "bench", "datasets");
|
|
7358
7555
|
}
|
|
7359
7556
|
function listDownloadableBenchmarks() {
|
|
7360
7557
|
return [...DOWNLOADABLE_BENCHMARK_DATASETS];
|
|
7361
7558
|
}
|
|
7362
7559
|
function resolveDatasetDownloadScriptPath() {
|
|
7363
|
-
const bundled =
|
|
7364
|
-
if (
|
|
7560
|
+
const bundled = path18.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
7561
|
+
if (fs15.existsSync(bundled)) {
|
|
7365
7562
|
return bundled;
|
|
7366
7563
|
}
|
|
7367
|
-
return
|
|
7564
|
+
return path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
7368
7565
|
}
|
|
7369
7566
|
function isRepoCheckout() {
|
|
7370
|
-
return
|
|
7567
|
+
return fs15.existsSync(path18.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs15.existsSync(path18.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
7371
7568
|
}
|
|
7372
7569
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
7373
7570
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -7418,7 +7615,7 @@ function resolveBenchDatasetDir(benchmarkId, quick, datasetDirOverride) {
|
|
|
7418
7615
|
if (quick) {
|
|
7419
7616
|
return void 0;
|
|
7420
7617
|
}
|
|
7421
|
-
const datasetDir =
|
|
7618
|
+
const datasetDir = path18.join(resolveRepoDatasetRoot(), benchmarkId);
|
|
7422
7619
|
if (isDatasetDownloaded(datasetDir, benchmarkId)) {
|
|
7423
7620
|
return datasetDir;
|
|
7424
7621
|
}
|
|
@@ -7675,13 +7872,13 @@ async function exportBenchPackageResult(parsed) {
|
|
|
7675
7872
|
process.exit(1);
|
|
7676
7873
|
}
|
|
7677
7874
|
const result = await loadBenchmarkResult(summary.path);
|
|
7678
|
-
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(
|
|
7875
|
+
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(path18.dirname(summary.path), result.meta.id) : void 0;
|
|
7679
7876
|
const rendered = renderBenchmarkResultExport(result, parsed.format, {
|
|
7680
7877
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
7681
7878
|
});
|
|
7682
7879
|
if (parsed.output) {
|
|
7683
|
-
|
|
7684
|
-
|
|
7880
|
+
fs15.mkdirSync(path18.dirname(parsed.output), { recursive: true });
|
|
7881
|
+
fs15.writeFileSync(parsed.output, rendered);
|
|
7685
7882
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
7686
7883
|
return;
|
|
7687
7884
|
}
|
|
@@ -7698,7 +7895,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
7698
7895
|
process.exit(1);
|
|
7699
7896
|
}
|
|
7700
7897
|
const status = supported.map((benchmarkId) => {
|
|
7701
|
-
const datasetPath =
|
|
7898
|
+
const datasetPath = path18.join(datasetRoot, benchmarkId);
|
|
7702
7899
|
return {
|
|
7703
7900
|
benchmark: benchmarkId,
|
|
7704
7901
|
downloaded: isDatasetDownloaded(datasetPath, benchmarkId),
|
|
@@ -7726,7 +7923,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
7726
7923
|
process.exit(1);
|
|
7727
7924
|
}
|
|
7728
7925
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
7729
|
-
if (!
|
|
7926
|
+
if (!fs15.existsSync(scriptPath)) {
|
|
7730
7927
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
7731
7928
|
process.exit(1);
|
|
7732
7929
|
}
|
|
@@ -7736,7 +7933,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
7736
7933
|
runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, parsed.json === true);
|
|
7737
7934
|
downloaded.push({
|
|
7738
7935
|
benchmark: benchmarkId,
|
|
7739
|
-
path:
|
|
7936
|
+
path: path18.join(datasetRoot, benchmarkId)
|
|
7740
7937
|
});
|
|
7741
7938
|
}
|
|
7742
7939
|
if (parsed.json) {
|
|
@@ -7875,10 +8072,10 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
7875
8072
|
}
|
|
7876
8073
|
const bench = await loadBenchModule();
|
|
7877
8074
|
const resultsDir = expandTilde(
|
|
7878
|
-
parsed.resultsDir ??
|
|
8075
|
+
parsed.resultsDir ?? path18.join(resolveHomeDir(), ".remnic", "bench", "results")
|
|
7879
8076
|
);
|
|
7880
8077
|
const calibrationDir = expandTilde(
|
|
7881
|
-
parsed.calibrationDir ??
|
|
8078
|
+
parsed.calibrationDir ?? path18.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
7882
8079
|
);
|
|
7883
8080
|
const stored = await bench.listBenchmarkResults(resultsDir);
|
|
7884
8081
|
const allForBenchmark = stored.filter((entry) => entry.benchmark === benchmarkId);
|
|
@@ -7926,7 +8123,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
7926
8123
|
);
|
|
7927
8124
|
process.exit(1);
|
|
7928
8125
|
}
|
|
7929
|
-
const sourceResultSha256 = createHash4("sha256").update(
|
|
8126
|
+
const sourceResultSha256 = createHash4("sha256").update(fs15.readFileSync(latest.path)).digest("hex");
|
|
7930
8127
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
7931
8128
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
7932
8129
|
console.error(
|
|
@@ -8341,7 +8538,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
8341
8538
|
}
|
|
8342
8539
|
let decoded;
|
|
8343
8540
|
try {
|
|
8344
|
-
decoded = JSON.parse(
|
|
8541
|
+
decoded = JSON.parse(fs15.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
8345
8542
|
} catch (error) {
|
|
8346
8543
|
throw new Error(
|
|
8347
8544
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -8438,7 +8635,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
8438
8635
|
return {
|
|
8439
8636
|
async promoteArtifactsToPublished(args) {
|
|
8440
8637
|
const { mkdirSync, readFileSync: readFileSync4, writeFileSync } = await import("fs");
|
|
8441
|
-
const
|
|
8638
|
+
const path19 = await import("path");
|
|
8442
8639
|
mkdirSync(args.publishedOutDir, { recursive: true });
|
|
8443
8640
|
if (args.artifactPaths.length === 0) {
|
|
8444
8641
|
console.warn(
|
|
@@ -8455,13 +8652,13 @@ async function loadPublishedPromotionHelpers() {
|
|
|
8455
8652
|
const modelSlug = args.model.replace(/[^a-zA-Z0-9_.-]/g, "-");
|
|
8456
8653
|
const rawProfile = parsedObj.config?.runtimeProfile;
|
|
8457
8654
|
const profileSlug = typeof rawProfile === "string" && rawProfile.length > 0 ? `-${rawProfile.replace(/[^a-zA-Z0-9_.-]/g, "-")}` : "";
|
|
8458
|
-
const target =
|
|
8655
|
+
const target = path19.join(
|
|
8459
8656
|
args.publishedOutDir,
|
|
8460
8657
|
`${today}-${args.benchmarkId}-${modelSlug}${profileSlug}-${gitShaShort}.json`
|
|
8461
8658
|
);
|
|
8462
8659
|
writeFileSync(target, raw, "utf8");
|
|
8463
8660
|
console.log(
|
|
8464
|
-
`[bench published] Promoted ${
|
|
8661
|
+
`[bench published] Promoted ${path19.basename(artifactPath)} \u2192 ${target}`
|
|
8465
8662
|
);
|
|
8466
8663
|
}
|
|
8467
8664
|
void benchModule;
|
|
@@ -8568,7 +8765,7 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
|
|
|
8568
8765
|
const previousCodexDiagnosticsDir = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV];
|
|
8569
8766
|
const previousCodexDiagnosticsMode = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_MODE_ENV];
|
|
8570
8767
|
if (!previousCodexDiagnosticsDir) {
|
|
8571
|
-
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] =
|
|
8768
|
+
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] = path18.join(
|
|
8572
8769
|
outputDir,
|
|
8573
8770
|
"codex-cli-diagnostics"
|
|
8574
8771
|
);
|
|
@@ -8718,7 +8915,7 @@ async function preparePersistedJudgeCalibrationAttachment(benchModule, benchmark
|
|
|
8718
8915
|
);
|
|
8719
8916
|
}
|
|
8720
8917
|
const calibrationDir = expandTilde(
|
|
8721
|
-
calibrationBinding.calibrationDir ??
|
|
8918
|
+
calibrationBinding.calibrationDir ?? path18.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
8722
8919
|
);
|
|
8723
8920
|
const state = await benchModule.loadJudgeCalibrationState?.(benchmarkId, calibrationDir);
|
|
8724
8921
|
if (!state) {
|
|
@@ -9016,7 +9213,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
9016
9213
|
return void 0;
|
|
9017
9214
|
}
|
|
9018
9215
|
try {
|
|
9019
|
-
return
|
|
9216
|
+
return fs15.realpathSync(datasetDir);
|
|
9020
9217
|
} catch {
|
|
9021
9218
|
return datasetDir;
|
|
9022
9219
|
}
|
|
@@ -9070,13 +9267,13 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
9070
9267
|
}
|
|
9071
9268
|
function loadStandaloneConvergeCommandConfig() {
|
|
9072
9269
|
const configPath = resolveConfigPath();
|
|
9073
|
-
const raw =
|
|
9074
|
-
return
|
|
9270
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
9271
|
+
return parseConfig7(resolveRemnicConfigRecord6(raw));
|
|
9075
9272
|
}
|
|
9076
9273
|
function parseConvergePluginConfig(value) {
|
|
9077
9274
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
9078
9275
|
if (Object.keys(value).length === 0) return void 0;
|
|
9079
|
-
return
|
|
9276
|
+
return parseConfig7(resolveRemnicConfigRecord6(value));
|
|
9080
9277
|
}
|
|
9081
9278
|
function loadConvergeCommandConfig() {
|
|
9082
9279
|
if (readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH")) {
|
|
@@ -9089,23 +9286,23 @@ function loadConvergeCommandConfig() {
|
|
|
9089
9286
|
return loadStandaloneConvergeCommandConfig();
|
|
9090
9287
|
}
|
|
9091
9288
|
function resolveConfigPath(cliPath) {
|
|
9092
|
-
if (cliPath) return
|
|
9289
|
+
if (cliPath) return path18.resolve(expandTilde(cliPath));
|
|
9093
9290
|
const envPath = readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH");
|
|
9094
|
-
if (envPath) return
|
|
9291
|
+
if (envPath) return path18.resolve(expandTilde(envPath));
|
|
9095
9292
|
const candidates = [
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9293
|
+
path18.join(process.cwd(), "remnic.config.json"),
|
|
9294
|
+
path18.join(process.cwd(), "engram.config.json"),
|
|
9295
|
+
path18.join(resolveHomeDir(), ".config", "remnic", "config.json"),
|
|
9296
|
+
path18.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
9100
9297
|
];
|
|
9101
9298
|
for (const candidate of candidates) {
|
|
9102
|
-
if (
|
|
9299
|
+
if (fs15.existsSync(candidate)) return candidate;
|
|
9103
9300
|
}
|
|
9104
|
-
return
|
|
9301
|
+
return path18.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
9105
9302
|
}
|
|
9106
9303
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
9107
9304
|
const configPath = resolveConfigPath(cliPath);
|
|
9108
|
-
if (
|
|
9305
|
+
if (fs15.existsSync(configPath)) {
|
|
9109
9306
|
return configPath;
|
|
9110
9307
|
}
|
|
9111
9308
|
if (cliPath) {
|
|
@@ -9115,7 +9312,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
9115
9312
|
}
|
|
9116
9313
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
9117
9314
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
9118
|
-
if (
|
|
9315
|
+
if (fs15.existsSync(configPath)) {
|
|
9119
9316
|
return configPath;
|
|
9120
9317
|
}
|
|
9121
9318
|
if (cliPath) {
|
|
@@ -9215,34 +9412,34 @@ async function resolvePackageBenchRuntime(benchModule, parsed, runtimeProfile) {
|
|
|
9215
9412
|
);
|
|
9216
9413
|
}
|
|
9217
9414
|
function normalizeMemoryDirPath(memoryDir) {
|
|
9218
|
-
return
|
|
9415
|
+
return path18.resolve(expandTilde(memoryDir));
|
|
9219
9416
|
}
|
|
9220
9417
|
function resolveMemoryDir() {
|
|
9221
9418
|
const configMemoryDir = (() => {
|
|
9222
9419
|
const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
9223
9420
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
9224
9421
|
const configPath = resolveConfigPath();
|
|
9225
|
-
const raw =
|
|
9226
|
-
const remnicCfg =
|
|
9422
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
9423
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
9227
9424
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
9228
9425
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
9229
9426
|
}
|
|
9230
9427
|
const home = resolveHomeDir();
|
|
9231
|
-
const standalonePath =
|
|
9232
|
-
const legacyStandalonePath =
|
|
9233
|
-
const openclawPath =
|
|
9234
|
-
if (
|
|
9235
|
-
if (
|
|
9428
|
+
const standalonePath = path18.join(home, ".remnic", "memory");
|
|
9429
|
+
const legacyStandalonePath = path18.join(home, ".engram", "memory");
|
|
9430
|
+
const openclawPath = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
9431
|
+
if (fs15.existsSync(standalonePath)) return standalonePath;
|
|
9432
|
+
if (fs15.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
9236
9433
|
return openclawPath;
|
|
9237
9434
|
})();
|
|
9238
9435
|
const manifestPath = getManifestPath();
|
|
9239
|
-
if (
|
|
9436
|
+
if (fs15.existsSync(manifestPath)) {
|
|
9240
9437
|
try {
|
|
9241
9438
|
const active = getActiveSpace();
|
|
9242
9439
|
if (active?.memoryDir) {
|
|
9243
9440
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
9244
|
-
if (!
|
|
9245
|
-
|
|
9441
|
+
if (!fs15.existsSync(activeMemoryDir)) {
|
|
9442
|
+
fs15.mkdirSync(activeMemoryDir, { recursive: true });
|
|
9246
9443
|
}
|
|
9247
9444
|
return activeMemoryDir;
|
|
9248
9445
|
}
|
|
@@ -9279,25 +9476,25 @@ function resolveFlagStrict(args, flag) {
|
|
|
9279
9476
|
var REMNIC_OPENCLAW_LEGACY_PLUGIN_ID = "openclaw-engram";
|
|
9280
9477
|
function resolveOpenclawStateDir() {
|
|
9281
9478
|
const configuredStateDir = process.env.OPENCLAW_STATE_DIR?.trim();
|
|
9282
|
-
return configuredStateDir ?
|
|
9479
|
+
return configuredStateDir ? path18.resolve(expandTilde(configuredStateDir)) : path18.join(resolveHomeDir(), ".openclaw");
|
|
9283
9480
|
}
|
|
9284
9481
|
var DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR = [
|
|
9285
9482
|
process.env.OPENCLAW_CONFIG_PATH,
|
|
9286
9483
|
process.env.OPENCLAW_ENGRAM_CONFIG_PATH,
|
|
9287
|
-
|
|
9484
|
+
path18.join(resolveOpenclawStateDir(), "openclaw.json")
|
|
9288
9485
|
].filter(Boolean);
|
|
9289
9486
|
function resolveOpenclawConfigPath(cliPath) {
|
|
9290
|
-
if (cliPath) return
|
|
9487
|
+
if (cliPath) return path18.resolve(expandTilde(cliPath));
|
|
9291
9488
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
9292
|
-
if (envPath) return
|
|
9489
|
+
if (envPath) return path18.resolve(expandTilde(envPath));
|
|
9293
9490
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
9294
|
-
if (
|
|
9491
|
+
if (fs15.existsSync(candidate)) return candidate;
|
|
9295
9492
|
}
|
|
9296
|
-
return
|
|
9493
|
+
return path18.join(resolveOpenclawStateDir(), "openclaw.json");
|
|
9297
9494
|
}
|
|
9298
9495
|
function readOpenclawConfig(configPath) {
|
|
9299
|
-
if (!
|
|
9300
|
-
const raw =
|
|
9496
|
+
if (!fs15.existsSync(configPath)) return {};
|
|
9497
|
+
const raw = fs15.readFileSync(configPath, "utf-8");
|
|
9301
9498
|
let parsed;
|
|
9302
9499
|
try {
|
|
9303
9500
|
parsed = JSON.parse(raw);
|
|
@@ -9352,10 +9549,10 @@ function buildRemnicOpenclawHooksPolicy(legacyHooks, existingHooks) {
|
|
|
9352
9549
|
function resolveOpenclawInstallMemoryDir(args) {
|
|
9353
9550
|
const existingMemoryDir = (typeof args.existingNewEntryConfig.memoryDir === "string" ? args.existingNewEntryConfig.memoryDir : void 0) || (args.migrateLegacy && typeof args.legacyConfigToMerge.memoryDir === "string" ? args.legacyConfigToMerge.memoryDir : void 0);
|
|
9354
9551
|
if (args.requestedMemoryDir) {
|
|
9355
|
-
return
|
|
9552
|
+
return path18.resolve(expandTilde(args.requestedMemoryDir));
|
|
9356
9553
|
}
|
|
9357
9554
|
if (existingMemoryDir) {
|
|
9358
|
-
return
|
|
9555
|
+
return path18.resolve(expandTilde(existingMemoryDir));
|
|
9359
9556
|
}
|
|
9360
9557
|
return args.fallbackMemoryDir;
|
|
9361
9558
|
}
|
|
@@ -9373,21 +9570,21 @@ function resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir) {
|
|
|
9373
9570
|
if (!config || typeof config !== "object" || Array.isArray(config)) continue;
|
|
9374
9571
|
const memoryDir = config.memoryDir;
|
|
9375
9572
|
if (typeof memoryDir === "string" && memoryDir.trim().length > 0) {
|
|
9376
|
-
return
|
|
9573
|
+
return path18.resolve(expandTilde(memoryDir));
|
|
9377
9574
|
}
|
|
9378
9575
|
}
|
|
9379
9576
|
return fallbackMemoryDir;
|
|
9380
9577
|
}
|
|
9381
9578
|
function resolveOpenclawPluginDir(cliPath) {
|
|
9382
|
-
if (cliPath) return
|
|
9579
|
+
if (cliPath) return path18.resolve(expandTilde(cliPath));
|
|
9383
9580
|
return resolveOpenclawManagedPluginDir();
|
|
9384
9581
|
}
|
|
9385
9582
|
function resolveOpenclawManagedPluginDir() {
|
|
9386
|
-
return
|
|
9583
|
+
return path18.join(resolveOpenclawStateDir(), "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
9387
9584
|
}
|
|
9388
9585
|
function resolveOpenclawLegacyPluginDir(cliPath) {
|
|
9389
|
-
if (cliPath) return
|
|
9390
|
-
return
|
|
9586
|
+
if (cliPath) return path18.resolve(expandTilde(cliPath));
|
|
9587
|
+
return path18.join(resolveOpenclawStateDir(), "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID);
|
|
9391
9588
|
}
|
|
9392
9589
|
function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
9393
9590
|
const yyyy = now.getFullYear().toString();
|
|
@@ -9399,9 +9596,9 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
9399
9596
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
9400
9597
|
}
|
|
9401
9598
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
9402
|
-
if (!
|
|
9403
|
-
|
|
9404
|
-
|
|
9599
|
+
if (!fs15.existsSync(sourcePath)) return false;
|
|
9600
|
+
fs15.mkdirSync(path18.dirname(backupPath), { recursive: true });
|
|
9601
|
+
fs15.cpSync(sourcePath, backupPath, { recursive: true });
|
|
9405
9602
|
return true;
|
|
9406
9603
|
}
|
|
9407
9604
|
function restartOpenclawGateway() {
|
|
@@ -9419,15 +9616,15 @@ function restartOpenclawGateway() {
|
|
|
9419
9616
|
});
|
|
9420
9617
|
}
|
|
9421
9618
|
function cmdInit() {
|
|
9422
|
-
const configPath =
|
|
9423
|
-
if (
|
|
9619
|
+
const configPath = path18.join(process.cwd(), "remnic.config.json");
|
|
9620
|
+
if (fs15.existsSync(configPath)) {
|
|
9424
9621
|
console.log(`Config already exists: ${configPath}`);
|
|
9425
9622
|
return;
|
|
9426
9623
|
}
|
|
9427
9624
|
const template = {
|
|
9428
9625
|
remnic: {
|
|
9429
9626
|
openaiApiKey: "${OPENAI_API_KEY}",
|
|
9430
|
-
memoryDir:
|
|
9627
|
+
memoryDir: path18.join(process.cwd(), ".remnic", "memory"),
|
|
9431
9628
|
memoryOsPreset: "balanced"
|
|
9432
9629
|
},
|
|
9433
9630
|
server: {
|
|
@@ -9436,7 +9633,7 @@ function cmdInit() {
|
|
|
9436
9633
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
9437
9634
|
}
|
|
9438
9635
|
};
|
|
9439
|
-
|
|
9636
|
+
fs15.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
9440
9637
|
console.log(`Created ${configPath}`);
|
|
9441
9638
|
console.log("\nSet these environment variables:");
|
|
9442
9639
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -9506,7 +9703,7 @@ async function cmdStatus(json) {
|
|
|
9506
9703
|
}
|
|
9507
9704
|
function oauthReadConfigRecord(configPath) {
|
|
9508
9705
|
try {
|
|
9509
|
-
const parsed = JSON.parse(
|
|
9706
|
+
const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
|
|
9510
9707
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
9511
9708
|
return parsed;
|
|
9512
9709
|
}
|
|
@@ -9564,7 +9761,7 @@ function oauthResolveOperatorToken() {
|
|
|
9564
9761
|
}
|
|
9565
9762
|
return void 0;
|
|
9566
9763
|
}
|
|
9567
|
-
async function oauthFetch(method,
|
|
9764
|
+
async function oauthFetch(method, path19, token, body) {
|
|
9568
9765
|
const controller = new AbortController();
|
|
9569
9766
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
9570
9767
|
try {
|
|
@@ -9583,7 +9780,7 @@ async function oauthFetch(method, path18, token, body) {
|
|
|
9583
9780
|
if (body !== void 0) {
|
|
9584
9781
|
init.body = JSON.stringify(body);
|
|
9585
9782
|
}
|
|
9586
|
-
const response = await fetch(`${oauthResolveBaseUrl()}${
|
|
9783
|
+
const response = await fetch(`${oauthResolveBaseUrl()}${path19}`, init);
|
|
9587
9784
|
if (response.status === 401) {
|
|
9588
9785
|
throw new Error(
|
|
9589
9786
|
"operator token rejected by remnic-server (HTTP 401). Update `server.authToken` or `REMNIC_AUTH_TOKEN` to match the running daemon."
|
|
@@ -9920,12 +10117,12 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
9920
10117
|
console.error("Usage: remnic query <text>");
|
|
9921
10118
|
process.exit(1);
|
|
9922
10119
|
}
|
|
9923
|
-
|
|
10120
|
+
initLogger3();
|
|
9924
10121
|
const configPath = resolveConfigPath();
|
|
9925
|
-
const raw =
|
|
9926
|
-
const remnicCfg =
|
|
9927
|
-
const config =
|
|
9928
|
-
const orchestrator = new
|
|
10122
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10123
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10124
|
+
const config = parseConfig7(remnicCfg);
|
|
10125
|
+
const orchestrator = new Orchestrator4(config);
|
|
9929
10126
|
await orchestrator.initialize();
|
|
9930
10127
|
const service = new EngramAccessService2(orchestrator);
|
|
9931
10128
|
const recallRequest = buildQueryRecallRequest(queryText);
|
|
@@ -10091,12 +10288,12 @@ async function runXrayCommand(rest, io) {
|
|
|
10091
10288
|
async function cmdXray(rest) {
|
|
10092
10289
|
const { rawQuery, options } = extractXrayRawArgs(rest);
|
|
10093
10290
|
parseXrayCliOptions(rawQuery, options);
|
|
10094
|
-
|
|
10291
|
+
initLogger3();
|
|
10095
10292
|
const configPath = resolveConfigPath();
|
|
10096
|
-
const raw =
|
|
10097
|
-
const remnicCfg =
|
|
10098
|
-
const config =
|
|
10099
|
-
const orchestrator = new
|
|
10293
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10294
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10295
|
+
const config = parseConfig7(remnicCfg);
|
|
10296
|
+
const orchestrator = new Orchestrator4(config);
|
|
10100
10297
|
await orchestrator.initialize();
|
|
10101
10298
|
await orchestrator.deferredReady;
|
|
10102
10299
|
const service = new EngramAccessService2(orchestrator);
|
|
@@ -10114,11 +10311,11 @@ async function cmdXray(rest) {
|
|
|
10114
10311
|
}
|
|
10115
10312
|
}
|
|
10116
10313
|
async function cmdVersions(rest) {
|
|
10117
|
-
|
|
10314
|
+
initLogger3();
|
|
10118
10315
|
const configPath = resolveConfigPath();
|
|
10119
|
-
const raw =
|
|
10120
|
-
const remnicCfg =
|
|
10121
|
-
const config =
|
|
10316
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10317
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10318
|
+
const config = parseConfig7(remnicCfg);
|
|
10122
10319
|
if (!config.versioningEnabled) {
|
|
10123
10320
|
console.error("Page versioning is disabled (versioningEnabled = false).");
|
|
10124
10321
|
process.exit(1);
|
|
@@ -10138,7 +10335,7 @@ async function cmdVersions(rest) {
|
|
|
10138
10335
|
console.error("Usage: remnic versions list <page-path>");
|
|
10139
10336
|
process.exit(1);
|
|
10140
10337
|
}
|
|
10141
|
-
const absPath =
|
|
10338
|
+
const absPath = path18.resolve(pagePath);
|
|
10142
10339
|
const history = await listVersions(absPath, versioningConfig, memDir);
|
|
10143
10340
|
if (json) {
|
|
10144
10341
|
console.log(JSON.stringify(history, null, 2));
|
|
@@ -10163,7 +10360,7 @@ async function cmdVersions(rest) {
|
|
|
10163
10360
|
console.error("Usage: remnic versions show <page-path> <version-id>");
|
|
10164
10361
|
process.exit(1);
|
|
10165
10362
|
}
|
|
10166
|
-
const absPath =
|
|
10363
|
+
const absPath = path18.resolve(pagePath);
|
|
10167
10364
|
try {
|
|
10168
10365
|
const content = await getVersion(absPath, versionId, versioningConfig, memDir);
|
|
10169
10366
|
console.log(content);
|
|
@@ -10181,7 +10378,7 @@ async function cmdVersions(rest) {
|
|
|
10181
10378
|
console.error("Usage: remnic versions diff <page-path> <v1> <v2>");
|
|
10182
10379
|
process.exit(1);
|
|
10183
10380
|
}
|
|
10184
|
-
const absPath =
|
|
10381
|
+
const absPath = path18.resolve(pagePath);
|
|
10185
10382
|
try {
|
|
10186
10383
|
const diffOutput = await diffVersions(absPath, v1, v2, versioningConfig, memDir);
|
|
10187
10384
|
console.log(diffOutput);
|
|
@@ -10198,7 +10395,7 @@ async function cmdVersions(rest) {
|
|
|
10198
10395
|
console.error("Usage: remnic versions revert <page-path> <version-id>");
|
|
10199
10396
|
process.exit(1);
|
|
10200
10397
|
}
|
|
10201
|
-
const absPath =
|
|
10398
|
+
const absPath = path18.resolve(pagePath);
|
|
10202
10399
|
try {
|
|
10203
10400
|
const version = await revertToVersion(absPath, versionId, versioningConfig, void 0, memDir);
|
|
10204
10401
|
if (json) {
|
|
@@ -10230,15 +10427,15 @@ Options:
|
|
|
10230
10427
|
}
|
|
10231
10428
|
}
|
|
10232
10429
|
async function cmdEnrich(rest) {
|
|
10233
|
-
|
|
10430
|
+
initLogger3();
|
|
10234
10431
|
const configPath = resolveConfigPath();
|
|
10235
|
-
const raw =
|
|
10236
|
-
const remnicCfg =
|
|
10237
|
-
const config =
|
|
10432
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10433
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10434
|
+
const config = parseConfig7(remnicCfg);
|
|
10238
10435
|
const subcommand = rest[0];
|
|
10239
10436
|
if (subcommand === "audit") {
|
|
10240
10437
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
10241
|
-
const auditDir2 =
|
|
10438
|
+
const auditDir2 = path18.join(memoryDir2, "enrichment");
|
|
10242
10439
|
const sinceFlag = resolveFlag(rest.slice(1), "--since");
|
|
10243
10440
|
const entries = await readAuditLog(auditDir2, sinceFlag ?? void 0);
|
|
10244
10441
|
if (entries.length === 0) {
|
|
@@ -10262,7 +10459,7 @@ async function cmdEnrich(rest) {
|
|
|
10262
10459
|
pipelineConfig2.providers = [
|
|
10263
10460
|
{ id: "web-search", enabled: true, costTier: "cheap" }
|
|
10264
10461
|
];
|
|
10265
|
-
const orchestrator2 = new
|
|
10462
|
+
const orchestrator2 = new Orchestrator4(config);
|
|
10266
10463
|
await orchestrator2.initialize();
|
|
10267
10464
|
await orchestrator2.deferredReady;
|
|
10268
10465
|
const searchBackend2 = orchestrator2.qmd;
|
|
@@ -10298,7 +10495,7 @@ Registered providers:`);
|
|
|
10298
10495
|
console.error("Usage: remnic enrich <entity-name> | --all | --dry-run | audit | providers");
|
|
10299
10496
|
process.exit(1);
|
|
10300
10497
|
}
|
|
10301
|
-
const orchestrator = new
|
|
10498
|
+
const orchestrator = new Orchestrator4(config);
|
|
10302
10499
|
await orchestrator.initialize();
|
|
10303
10500
|
await orchestrator.deferredReady;
|
|
10304
10501
|
const storage = await orchestrator.getStorage(config.defaultNamespace);
|
|
@@ -10363,7 +10560,7 @@ Registered providers:`);
|
|
|
10363
10560
|
return;
|
|
10364
10561
|
}
|
|
10365
10562
|
const memoryDir = expandTilde(config.memoryDir);
|
|
10366
|
-
const auditDir =
|
|
10563
|
+
const auditDir = path18.join(memoryDir, "enrichment");
|
|
10367
10564
|
let totalPersisted = 0;
|
|
10368
10565
|
for (const result of results) {
|
|
10369
10566
|
for (const candidate of result.acceptedCandidates) {
|
|
@@ -10424,7 +10621,7 @@ Registered providers:`);
|
|
|
10424
10621
|
}
|
|
10425
10622
|
}
|
|
10426
10623
|
async function cmdProcedural(rest) {
|
|
10427
|
-
|
|
10624
|
+
initLogger3();
|
|
10428
10625
|
const subcommand = rest[0];
|
|
10429
10626
|
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
10430
10627
|
console.log(`remnic procedural \u2014 Procedural memory operations (issue #567)
|
|
@@ -10477,9 +10674,9 @@ Shared with:
|
|
|
10477
10674
|
process.exit(1);
|
|
10478
10675
|
}
|
|
10479
10676
|
const configPath = resolveConfigPath();
|
|
10480
|
-
const raw =
|
|
10481
|
-
const remnicCfg =
|
|
10482
|
-
const config =
|
|
10677
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10678
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10679
|
+
const config = parseConfig7(remnicCfg);
|
|
10483
10680
|
const memoryDir = expandTilde(
|
|
10484
10681
|
typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
10485
10682
|
);
|
|
@@ -10492,11 +10689,11 @@ Shared with:
|
|
|
10492
10689
|
process.stdout.write(formatProcedureStatsText(report));
|
|
10493
10690
|
}
|
|
10494
10691
|
async function cmdExtensions(action, rest) {
|
|
10495
|
-
|
|
10692
|
+
initLogger3();
|
|
10496
10693
|
const configPath = resolveConfigPath();
|
|
10497
|
-
const raw =
|
|
10498
|
-
const remnicCfg =
|
|
10499
|
-
const config =
|
|
10694
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10695
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10696
|
+
const config = parseConfig7(remnicCfg);
|
|
10500
10697
|
const root = resolveExtensionsRoot(config);
|
|
10501
10698
|
const noopLog = { warn: () => {
|
|
10502
10699
|
}, debug: () => {
|
|
@@ -10545,7 +10742,7 @@ Root: ${root}`);
|
|
|
10545
10742
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
10546
10743
|
let entries = [];
|
|
10547
10744
|
try {
|
|
10548
|
-
entries =
|
|
10745
|
+
entries = fs15.readdirSync(root);
|
|
10549
10746
|
} catch {
|
|
10550
10747
|
console.log(`Extensions root does not exist: ${root}`);
|
|
10551
10748
|
process.exitCode = 0;
|
|
@@ -10554,9 +10751,9 @@ Root: ${root}`);
|
|
|
10554
10751
|
const validNames = new Set(extensions.map((e) => e.name));
|
|
10555
10752
|
let errors = 0;
|
|
10556
10753
|
for (const entry of entries) {
|
|
10557
|
-
const entryPath =
|
|
10754
|
+
const entryPath = path18.join(root, entry);
|
|
10558
10755
|
try {
|
|
10559
|
-
if (!
|
|
10756
|
+
if (!fs15.statSync(entryPath).isDirectory()) continue;
|
|
10560
10757
|
} catch {
|
|
10561
10758
|
continue;
|
|
10562
10759
|
}
|
|
@@ -10586,11 +10783,11 @@ Root: ${root}`);
|
|
|
10586
10783
|
}
|
|
10587
10784
|
}
|
|
10588
10785
|
async function cmdBriefing(rest) {
|
|
10589
|
-
|
|
10786
|
+
initLogger3();
|
|
10590
10787
|
const configPath = resolveConfigPath();
|
|
10591
|
-
const raw =
|
|
10592
|
-
const remnicCfg =
|
|
10593
|
-
const config =
|
|
10788
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
10789
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10790
|
+
const config = parseConfig7(remnicCfg);
|
|
10594
10791
|
if (!config.briefing.enabled) {
|
|
10595
10792
|
console.error("Briefing is disabled in config (briefing.enabled = false).");
|
|
10596
10793
|
process.exit(1);
|
|
@@ -10643,7 +10840,7 @@ async function cmdBriefing(rest) {
|
|
|
10643
10840
|
process.exit(1);
|
|
10644
10841
|
}
|
|
10645
10842
|
const format = effectiveFormatFlag === "json" ? "json" : effectiveFormatFlag === "markdown" ? "markdown" : config.briefing.defaultFormat;
|
|
10646
|
-
const orchestrator = new
|
|
10843
|
+
const orchestrator = new Orchestrator4(config);
|
|
10647
10844
|
await orchestrator.initialize();
|
|
10648
10845
|
const storage = await orchestrator.getStorage(config.defaultNamespace);
|
|
10649
10846
|
const calendarSource = config.briefing.calendarSource ? new FileCalendarSource(config.briefing.calendarSource) : void 0;
|
|
@@ -10668,10 +10865,10 @@ async function cmdBriefing(rest) {
|
|
|
10668
10865
|
if (save) {
|
|
10669
10866
|
try {
|
|
10670
10867
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
10671
|
-
|
|
10868
|
+
fs15.mkdirSync(saveDir, { recursive: true });
|
|
10672
10869
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
10673
|
-
const filePath =
|
|
10674
|
-
|
|
10870
|
+
const filePath = path18.join(saveDir, filename);
|
|
10871
|
+
fs15.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
10675
10872
|
console.error(`Saved briefing: ${filePath}`);
|
|
10676
10873
|
} catch (err) {
|
|
10677
10874
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -10689,7 +10886,7 @@ async function cmdDoctor() {
|
|
|
10689
10886
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
10690
10887
|
});
|
|
10691
10888
|
const configPath = resolveConfigPath();
|
|
10692
|
-
const configExists =
|
|
10889
|
+
const configExists = fs15.existsSync(configPath);
|
|
10693
10890
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
10694
10891
|
let standaloneConfig;
|
|
10695
10892
|
let standaloneConfigError;
|
|
@@ -10697,11 +10894,11 @@ async function cmdDoctor() {
|
|
|
10697
10894
|
let configuredNs = { invalid: false };
|
|
10698
10895
|
if (configExists) {
|
|
10699
10896
|
try {
|
|
10700
|
-
const raw = JSON.parse(
|
|
10701
|
-
const remnicCfg =
|
|
10897
|
+
const raw = JSON.parse(fs15.readFileSync(configPath, "utf8"));
|
|
10898
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
10702
10899
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
10703
10900
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
10704
|
-
standaloneConfig =
|
|
10901
|
+
standaloneConfig = parseConfig7(remnicCfg);
|
|
10705
10902
|
} catch (err) {
|
|
10706
10903
|
standaloneConfigError = err instanceof Error ? err.message : String(err);
|
|
10707
10904
|
}
|
|
@@ -10710,10 +10907,10 @@ async function cmdDoctor() {
|
|
|
10710
10907
|
try {
|
|
10711
10908
|
memoryDir = resolveMemoryDir();
|
|
10712
10909
|
} catch {
|
|
10713
|
-
memoryDir =
|
|
10910
|
+
memoryDir = parseConfig7({}).memoryDir;
|
|
10714
10911
|
}
|
|
10715
10912
|
try {
|
|
10716
|
-
|
|
10913
|
+
fs15.mkdirSync(memoryDir, { recursive: true });
|
|
10717
10914
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
10718
10915
|
} catch {
|
|
10719
10916
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -10742,7 +10939,7 @@ async function cmdDoctor() {
|
|
|
10742
10939
|
});
|
|
10743
10940
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
10744
10941
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
10745
|
-
const openclawConfigExists =
|
|
10942
|
+
const openclawConfigExists = fs15.existsSync(openclawConfigPath);
|
|
10746
10943
|
let openclawConfig = {};
|
|
10747
10944
|
let openclawConfigValid = false;
|
|
10748
10945
|
let openclawPluginModeConfigured = false;
|
|
@@ -10750,7 +10947,7 @@ async function cmdDoctor() {
|
|
|
10750
10947
|
let activeOpenclawEntryConfig = null;
|
|
10751
10948
|
if (openclawConfigExists) {
|
|
10752
10949
|
try {
|
|
10753
|
-
const parsed = JSON.parse(
|
|
10950
|
+
const parsed = JSON.parse(fs15.readFileSync(openclawConfigPath, "utf-8"));
|
|
10754
10951
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
10755
10952
|
openclawConfig = parsed;
|
|
10756
10953
|
openclawConfigValid = true;
|
|
@@ -10826,13 +11023,13 @@ async function cmdDoctor() {
|
|
|
10826
11023
|
const rawMemoryDir = entryConfig?.memoryDir;
|
|
10827
11024
|
const configuredMemoryDir = typeof rawMemoryDir === "string" ? rawMemoryDir : void 0;
|
|
10828
11025
|
if (configuredMemoryDir) {
|
|
10829
|
-
const resolvedMemDir =
|
|
11026
|
+
const resolvedMemDir = path18.resolve(expandTilde(configuredMemoryDir));
|
|
10830
11027
|
let memDirOk = false;
|
|
10831
11028
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
10832
11029
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
10833
|
-
if (
|
|
11030
|
+
if (fs15.existsSync(resolvedMemDir)) {
|
|
10834
11031
|
try {
|
|
10835
|
-
const stat2 =
|
|
11032
|
+
const stat2 = fs15.statSync(resolvedMemDir);
|
|
10836
11033
|
if (stat2.isDirectory()) {
|
|
10837
11034
|
memDirOk = true;
|
|
10838
11035
|
memDirDetail = resolvedMemDir;
|
|
@@ -10974,12 +11171,12 @@ async function cmdDoctor() {
|
|
|
10974
11171
|
}
|
|
10975
11172
|
function cmdConfig() {
|
|
10976
11173
|
const configPath = resolveConfigPath();
|
|
10977
|
-
if (!
|
|
11174
|
+
if (!fs15.existsSync(configPath)) {
|
|
10978
11175
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
10979
11176
|
return;
|
|
10980
11177
|
}
|
|
10981
11178
|
console.log(`Config: ${configPath}`);
|
|
10982
|
-
const rawConfig =
|
|
11179
|
+
const rawConfig = fs15.readFileSync(configPath, "utf8");
|
|
10983
11180
|
const redacted = rawConfig.replace(
|
|
10984
11181
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
10985
11182
|
"$1[REDACTED]$3"
|
|
@@ -11026,7 +11223,7 @@ async function cmdMigrate(json, rollback) {
|
|
|
11026
11223
|
console.log(` Rollback: ${result.rollbackCommand}`);
|
|
11027
11224
|
}
|
|
11028
11225
|
function cmdOnboard(dirPath, json) {
|
|
11029
|
-
const directory =
|
|
11226
|
+
const directory = path18.resolve(dirPath || process.cwd());
|
|
11030
11227
|
const result = onboard({ directory });
|
|
11031
11228
|
if (json) {
|
|
11032
11229
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -11045,7 +11242,7 @@ Suggested namespace: ${result.plan.suggestedNamespace}`);
|
|
|
11045
11242
|
async function cmdCurate(targetPath, json) {
|
|
11046
11243
|
const memoryDir = resolveMemoryDir();
|
|
11047
11244
|
const result = await curate({
|
|
11048
|
-
targetPath:
|
|
11245
|
+
targetPath: path18.resolve(targetPath),
|
|
11049
11246
|
memoryDir,
|
|
11050
11247
|
source: "curation",
|
|
11051
11248
|
checkDuplicates: true,
|
|
@@ -11087,9 +11284,9 @@ async function cmdReview(action, rest) {
|
|
|
11087
11284
|
const configPath = resolveConfigPath();
|
|
11088
11285
|
let tombstonesConfig = null;
|
|
11089
11286
|
try {
|
|
11090
|
-
const rawCfg =
|
|
11091
|
-
const remnicCfg =
|
|
11092
|
-
const config =
|
|
11287
|
+
const rawCfg = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
11288
|
+
const remnicCfg = resolveRemnicConfigRecord6(rawCfg);
|
|
11289
|
+
const config = parseConfig7(remnicCfg);
|
|
11093
11290
|
tombstonesConfig = {
|
|
11094
11291
|
enabled: config.tombstonesEnabled,
|
|
11095
11292
|
semanticMatch: config.tombstonesSemanticMatch,
|
|
@@ -11175,7 +11372,7 @@ async function cmdSync(action, rest, json) {
|
|
|
11175
11372
|
}
|
|
11176
11373
|
function localOfflineSourceId(memoryDir) {
|
|
11177
11374
|
const host = os3.hostname() || "unknown-host";
|
|
11178
|
-
const dirHash = createHash4("sha256").update(
|
|
11375
|
+
const dirHash = createHash4("sha256").update(path18.resolve(memoryDir)).digest("hex").slice(0, 16);
|
|
11179
11376
|
return `remnic-local:${host}:${dirHash}`;
|
|
11180
11377
|
}
|
|
11181
11378
|
function normalizeOfflineRemoteUrl(raw) {
|
|
@@ -11573,10 +11770,10 @@ var OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX = 3;
|
|
|
11573
11770
|
var OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS = 250;
|
|
11574
11771
|
var OfflineRemoteFileChangedError = class extends Error {
|
|
11575
11772
|
path;
|
|
11576
|
-
constructor(
|
|
11577
|
-
super(`remote file changed while fetching offline content: ${
|
|
11773
|
+
constructor(path19) {
|
|
11774
|
+
super(`remote file changed while fetching offline content: ${path19}`);
|
|
11578
11775
|
this.name = "OfflineRemoteFileChangedError";
|
|
11579
|
-
this.path =
|
|
11776
|
+
this.path = path19;
|
|
11580
11777
|
}
|
|
11581
11778
|
};
|
|
11582
11779
|
function isOfflineRemoteFileChangedError(error) {
|
|
@@ -11831,13 +12028,13 @@ async function pushOfflineFileContent(args) {
|
|
|
11831
12028
|
}
|
|
11832
12029
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
11833
12030
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
11834
|
-
const stat2 =
|
|
12031
|
+
const stat2 = fs15.statSync(filePath);
|
|
11835
12032
|
if (stat2.mtimeMs !== args.file.mtimeMs) {
|
|
11836
12033
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
11837
12034
|
}
|
|
11838
12035
|
const hash = createHash4("sha256");
|
|
11839
12036
|
const chunks = args.readFileChunks({
|
|
11840
|
-
root:
|
|
12037
|
+
root: path18.resolve(args.memoryDir),
|
|
11841
12038
|
path: args.file.path,
|
|
11842
12039
|
filePath,
|
|
11843
12040
|
chunkSize: OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES
|
|
@@ -12322,7 +12519,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
12322
12519
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
12323
12520
|
}
|
|
12324
12521
|
async function runOfflineSyncOnce(options) {
|
|
12325
|
-
|
|
12522
|
+
fs15.mkdirSync(options.memoryDir, { recursive: true });
|
|
12326
12523
|
let activeStatePath = options.statePath;
|
|
12327
12524
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
12328
12525
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -12947,7 +13144,7 @@ Environment fallbacks:
|
|
|
12947
13144
|
REMNIC_OFFLINE_REMOTE_URL, REMNIC_OFFLINE_TOKEN, REMNIC_AUTH_TOKEN`);
|
|
12948
13145
|
return;
|
|
12949
13146
|
}
|
|
12950
|
-
const memoryDir =
|
|
13147
|
+
const memoryDir = path18.resolve(expandTilde(resolveRequiredValueFlag(rest, "--memory-dir") ?? resolveMemoryDir()));
|
|
12951
13148
|
const namespace = resolveRequiredValueFlag(rest, "--namespace");
|
|
12952
13149
|
const includeTranscripts = !hasFlag(rest, "--no-transcripts");
|
|
12953
13150
|
const stateOverride = resolveRequiredValueFlag(rest, "--state");
|
|
@@ -12955,7 +13152,7 @@ Environment fallbacks:
|
|
|
12955
13152
|
const configPath = resolveConfigPath();
|
|
12956
13153
|
let config;
|
|
12957
13154
|
try {
|
|
12958
|
-
const rawConfig =
|
|
13155
|
+
const rawConfig = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
12959
13156
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
12960
13157
|
} catch {
|
|
12961
13158
|
throw new Error(
|
|
@@ -12967,10 +13164,10 @@ Environment fallbacks:
|
|
|
12967
13164
|
const needsRemote = action === "prepare" || action === "sync" || action === "watch";
|
|
12968
13165
|
const remoteUrl = needsRemote ? resolveOfflineRemoteUrl(rest) : resolveOptionalOfflineRemoteUrl(rest);
|
|
12969
13166
|
const token = needsRemote ? resolveOfflineToken(rest) : void 0;
|
|
12970
|
-
const statePath = statePathExplicit ?
|
|
13167
|
+
const statePath = statePathExplicit ? path18.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
12971
13168
|
if (action === "prepare") {
|
|
12972
13169
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
12973
|
-
|
|
13170
|
+
fs15.mkdirSync(memoryDir, { recursive: true });
|
|
12974
13171
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
12975
13172
|
remoteUrl,
|
|
12976
13173
|
token,
|
|
@@ -13069,7 +13266,7 @@ Environment fallbacks:
|
|
|
13069
13266
|
return;
|
|
13070
13267
|
}
|
|
13071
13268
|
if (action === "status") {
|
|
13072
|
-
|
|
13269
|
+
fs15.mkdirSync(memoryDir, { recursive: true });
|
|
13073
13270
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
13074
13271
|
if (state && remoteUrl && statePath) {
|
|
13075
13272
|
assertOfflineStateMatches({
|
|
@@ -13149,11 +13346,11 @@ Environment fallbacks:
|
|
|
13149
13346
|
failures: result.largeFilePushFailures
|
|
13150
13347
|
});
|
|
13151
13348
|
largeFileFailureCounts = advanced.counts;
|
|
13152
|
-
for (const
|
|
13153
|
-
if (skippedLargeFiles.has(
|
|
13154
|
-
skippedLargeFiles.add(
|
|
13349
|
+
for (const path19 of advanced.newlySkipped) {
|
|
13350
|
+
if (skippedLargeFiles.has(path19)) continue;
|
|
13351
|
+
skippedLargeFiles.add(path19);
|
|
13155
13352
|
console.warn(
|
|
13156
|
-
`offline sync: permanently skipping ${
|
|
13353
|
+
`offline sync: permanently skipping ${path19} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
13157
13354
|
);
|
|
13158
13355
|
}
|
|
13159
13356
|
const pulled = result.pull ? result.pull.upserted + result.pull.deleted : 0;
|
|
@@ -13168,11 +13365,11 @@ Environment fallbacks:
|
|
|
13168
13365
|
failures: error.failures
|
|
13169
13366
|
});
|
|
13170
13367
|
largeFileFailureCounts = advanced.counts;
|
|
13171
|
-
for (const
|
|
13172
|
-
if (skippedLargeFiles.has(
|
|
13173
|
-
skippedLargeFiles.add(
|
|
13368
|
+
for (const path19 of advanced.newlySkipped) {
|
|
13369
|
+
if (skippedLargeFiles.has(path19)) continue;
|
|
13370
|
+
skippedLargeFiles.add(path19);
|
|
13174
13371
|
console.warn(
|
|
13175
|
-
`offline sync: permanently skipping ${
|
|
13372
|
+
`offline sync: permanently skipping ${path19} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
13176
13373
|
);
|
|
13177
13374
|
}
|
|
13178
13375
|
}
|
|
@@ -13207,7 +13404,7 @@ function cmdDedup(json) {
|
|
|
13207
13404
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
13208
13405
|
if (!configPath) return fallback;
|
|
13209
13406
|
try {
|
|
13210
|
-
const parsed = JSON.parse(
|
|
13407
|
+
const parsed = JSON.parse(fs15.readFileSync(configPath, "utf8"));
|
|
13211
13408
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
13212
13409
|
const { token: _token, ...config } = parsed;
|
|
13213
13410
|
return config;
|
|
@@ -13313,7 +13510,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
13313
13510
|
const connectorDaemonUrl = typeof effectiveConnectorConfig.remnicDaemonUrl === "string" && effectiveConnectorConfig.remnicDaemonUrl.trim().length > 0 ? effectiveConnectorConfig.remnicDaemonUrl.trim() : void 0;
|
|
13314
13511
|
const pubResult = await pub.publish({
|
|
13315
13512
|
config: { memoryDir, namespace: connectorNamespace, daemonUrl: connectorDaemonUrl },
|
|
13316
|
-
skillsRoot:
|
|
13513
|
+
skillsRoot: path18.join(memoryDir, "skills"),
|
|
13317
13514
|
rollbackTokenEntry: preInstallTokenEntry,
|
|
13318
13515
|
log: { info: console.log, warn: console.warn, error: console.error }
|
|
13319
13516
|
});
|
|
@@ -13385,7 +13582,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
13385
13582
|
const pub = factory();
|
|
13386
13583
|
const available = await pub.isHostAvailable();
|
|
13387
13584
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
13388
|
-
const extensionExists = available && extRoot ?
|
|
13585
|
+
const extensionExists = available && extRoot ? fs15.existsSync(extRoot) : false;
|
|
13389
13586
|
publisherChecks.push({
|
|
13390
13587
|
name: `Publisher: ${targetHostId}`,
|
|
13391
13588
|
ok: !available || extensionExists,
|
|
@@ -13459,7 +13656,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
13459
13656
|
let connectorsCfg;
|
|
13460
13657
|
const configPath = resolveConfigPath();
|
|
13461
13658
|
try {
|
|
13462
|
-
const raw =
|
|
13659
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
13463
13660
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
13464
13661
|
} catch {
|
|
13465
13662
|
process.stderr.write(
|
|
@@ -13533,12 +13730,12 @@ async function cmdConnectors(action, rest, json) {
|
|
|
13533
13730
|
process.exitCode = 2;
|
|
13534
13731
|
return;
|
|
13535
13732
|
}
|
|
13536
|
-
|
|
13733
|
+
initLogger3();
|
|
13537
13734
|
const configPath = resolveConfigPath();
|
|
13538
|
-
const raw =
|
|
13539
|
-
const remnicCfg =
|
|
13540
|
-
const config =
|
|
13541
|
-
const orchestrator = new
|
|
13735
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
13736
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
13737
|
+
const config = parseConfig7(remnicCfg);
|
|
13738
|
+
const orchestrator = new Orchestrator4(config);
|
|
13542
13739
|
try {
|
|
13543
13740
|
await orchestrator.initialize();
|
|
13544
13741
|
await orchestrator.deferredReady;
|
|
@@ -13660,9 +13857,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
13660
13857
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
13661
13858
|
process.exit(1);
|
|
13662
13859
|
}
|
|
13663
|
-
const rawConfig =
|
|
13664
|
-
const pluginConfig =
|
|
13665
|
-
const config =
|
|
13860
|
+
const rawConfig = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
13861
|
+
const pluginConfig = resolveRemnicConfigRecord6(rawConfig);
|
|
13862
|
+
const config = parseConfig7(pluginConfig);
|
|
13666
13863
|
if (subAction === "generate") {
|
|
13667
13864
|
let outputDir;
|
|
13668
13865
|
try {
|
|
@@ -13673,22 +13870,22 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
13673
13870
|
}
|
|
13674
13871
|
const manifest = generateMarketplaceManifest();
|
|
13675
13872
|
await writeMarketplaceManifest(outputDir, manifest);
|
|
13676
|
-
const outPath =
|
|
13873
|
+
const outPath = path18.join(outputDir, "marketplace.json");
|
|
13677
13874
|
if (json) {
|
|
13678
13875
|
console.log(JSON.stringify({ status: "generated", path: outPath }, null, 2));
|
|
13679
13876
|
} else {
|
|
13680
13877
|
console.log(`Generated marketplace.json at ${outPath}`);
|
|
13681
13878
|
}
|
|
13682
13879
|
} else if (subAction === "validate") {
|
|
13683
|
-
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ??
|
|
13684
|
-
const resolved =
|
|
13685
|
-
if (!
|
|
13880
|
+
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path18.join(process.cwd(), "marketplace.json");
|
|
13881
|
+
const resolved = path18.resolve(targetPath);
|
|
13882
|
+
if (!fs15.existsSync(resolved)) {
|
|
13686
13883
|
console.error(`File not found: ${resolved}`);
|
|
13687
13884
|
process.exit(1);
|
|
13688
13885
|
}
|
|
13689
13886
|
let parsed;
|
|
13690
13887
|
try {
|
|
13691
|
-
parsed = JSON.parse(
|
|
13888
|
+
parsed = JSON.parse(fs15.readFileSync(resolved, "utf8"));
|
|
13692
13889
|
} catch {
|
|
13693
13890
|
console.error(`Invalid JSON in ${resolved}`);
|
|
13694
13891
|
process.exit(1);
|
|
@@ -13887,12 +14084,12 @@ async function cmdSpace(action, rest, json) {
|
|
|
13887
14084
|
}
|
|
13888
14085
|
}
|
|
13889
14086
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
13890
|
-
|
|
14087
|
+
initLogger3();
|
|
13891
14088
|
const configPath = resolveConfigPath();
|
|
13892
|
-
const raw =
|
|
13893
|
-
const remnicCfg =
|
|
13894
|
-
const config =
|
|
13895
|
-
const orchestrator = new
|
|
14089
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
14090
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
14091
|
+
const config = parseConfig7(remnicCfg);
|
|
14092
|
+
const orchestrator = new Orchestrator4(config);
|
|
13896
14093
|
const service = new EngramAccessService2(orchestrator);
|
|
13897
14094
|
const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
|
|
13898
14095
|
const benchConfig = {
|
|
@@ -13964,6 +14161,7 @@ async function cmdLegacyBenchmark(action, rest, json) {
|
|
|
13964
14161
|
}
|
|
13965
14162
|
async function cmdBench(rest) {
|
|
13966
14163
|
if (rest[0] === "coding") return cmdBenchCoding(rest.slice(1));
|
|
14164
|
+
if (rest[0] === "security") return cmdBenchSecurity(rest.slice(1));
|
|
13967
14165
|
if (rest[0] === "procedural-ablation") {
|
|
13968
14166
|
await cmdBenchProceduralAblation(rest.slice(1));
|
|
13969
14167
|
return;
|
|
@@ -14090,7 +14288,7 @@ async function cmdBench(rest) {
|
|
|
14090
14288
|
}
|
|
14091
14289
|
const completeCount = prevStatus.benchmarks.filter((b) => b.status === "complete").length;
|
|
14092
14290
|
const failedCount = prevStatus.benchmarks.filter((b) => b.status === "failed").length;
|
|
14093
|
-
printBenchStatusLine(parsed.json, `Resuming from: ${
|
|
14291
|
+
printBenchStatusLine(parsed.json, `Resuming from: ${path18.basename(latestStatusPath)}`);
|
|
14094
14292
|
printBenchStatusLine(parsed.json, ` Previous run: ${prevStatus.startedAt}`);
|
|
14095
14293
|
printBenchStatusLine(parsed.json, ` Benchmarks: ${prevStatus.benchmarks.length} total, ${completeCount} complete, ${failedCount} failed`);
|
|
14096
14294
|
const before = selectedBenchmarks.length;
|
|
@@ -14258,9 +14456,9 @@ Options:
|
|
|
14258
14456
|
);
|
|
14259
14457
|
process.exit(1);
|
|
14260
14458
|
} else {
|
|
14261
|
-
fixturePath =
|
|
14459
|
+
fixturePath = path18.resolve(expandTilde(fixturePathRaw));
|
|
14262
14460
|
}
|
|
14263
|
-
const outPath =
|
|
14461
|
+
const outPath = path18.resolve(expandTilde(outPathRaw));
|
|
14264
14462
|
const benchModule = await loadBenchModule();
|
|
14265
14463
|
const runner = benchModule.runProceduralAblationCli;
|
|
14266
14464
|
if (typeof runner !== "function") {
|
|
@@ -14279,7 +14477,7 @@ Options:
|
|
|
14279
14477
|
);
|
|
14280
14478
|
console.log(`wrote ${outPath}`);
|
|
14281
14479
|
}
|
|
14282
|
-
var LOGS_DIR =
|
|
14480
|
+
var LOGS_DIR = path18.join(PID_DIR, "logs");
|
|
14283
14481
|
var LAUNCHD_PLIST_PATHS = launchdPlistPaths(resolveHomeDir());
|
|
14284
14482
|
var [LAUNCHD_PLIST_PATH] = LAUNCHD_PLIST_PATHS;
|
|
14285
14483
|
var SYSTEMD_UNIT_PATHS = systemdUnitPaths(resolveHomeDir());
|
|
@@ -14293,7 +14491,7 @@ function readPid() {
|
|
|
14293
14491
|
function inferPort() {
|
|
14294
14492
|
try {
|
|
14295
14493
|
const configPath = resolveConfigPath();
|
|
14296
|
-
const raw = JSON.parse(
|
|
14494
|
+
const raw = JSON.parse(fs15.readFileSync(configPath, "utf8"));
|
|
14297
14495
|
return raw.server?.port ?? 4318;
|
|
14298
14496
|
} catch {
|
|
14299
14497
|
return 4318;
|
|
@@ -14356,7 +14554,7 @@ function selectLaunchdInspection(openclawPluginModeConfigured) {
|
|
|
14356
14554
|
for (const plistPath of LAUNCHD_PLIST_PATHS.slice(1)) {
|
|
14357
14555
|
const legacy = inspectLaunchdPlist(plistPath);
|
|
14358
14556
|
if (!legacy.installed) continue;
|
|
14359
|
-
const label =
|
|
14557
|
+
const label = path18.basename(plistPath, ".plist");
|
|
14360
14558
|
return legacy.ok ? {
|
|
14361
14559
|
...legacy,
|
|
14362
14560
|
warn: true,
|
|
@@ -14388,13 +14586,13 @@ function daemonInstall() {
|
|
|
14388
14586
|
process.exit(1);
|
|
14389
14587
|
}
|
|
14390
14588
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
14391
|
-
|
|
14589
|
+
fs15.mkdirSync(LOGS_DIR, { recursive: true });
|
|
14392
14590
|
if (isMacOS()) {
|
|
14393
|
-
const templatePath =
|
|
14394
|
-
const template =
|
|
14591
|
+
const templatePath = path18.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
14592
|
+
const template = fs15.readFileSync(templatePath, "utf8");
|
|
14395
14593
|
const plist = renderTemplate(template, vars);
|
|
14396
|
-
|
|
14397
|
-
|
|
14594
|
+
fs15.mkdirSync(path18.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
14595
|
+
fs15.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
14398
14596
|
try {
|
|
14399
14597
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
14400
14598
|
} catch (err) {
|
|
@@ -14410,11 +14608,11 @@ function daemonInstall() {
|
|
|
14410
14608
|
console.log(` RunAtLoad: true, KeepAlive: true`);
|
|
14411
14609
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
14412
14610
|
} else if (isLinux()) {
|
|
14413
|
-
const templatePath =
|
|
14414
|
-
const template =
|
|
14611
|
+
const templatePath = path18.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
14612
|
+
const template = fs15.readFileSync(templatePath, "utf8");
|
|
14415
14613
|
const unit = renderTemplate(template, vars);
|
|
14416
|
-
|
|
14417
|
-
|
|
14614
|
+
fs15.mkdirSync(path18.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
14615
|
+
fs15.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
14418
14616
|
try {
|
|
14419
14617
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
14420
14618
|
} catch (err) {
|
|
@@ -14450,7 +14648,7 @@ function daemonUninstall() {
|
|
|
14450
14648
|
} catch {
|
|
14451
14649
|
}
|
|
14452
14650
|
try {
|
|
14453
|
-
|
|
14651
|
+
fs15.unlinkSync(plistPath);
|
|
14454
14652
|
removed = true;
|
|
14455
14653
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
14456
14654
|
} catch {
|
|
@@ -14470,7 +14668,7 @@ function daemonUninstall() {
|
|
|
14470
14668
|
let removed = false;
|
|
14471
14669
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
14472
14670
|
try {
|
|
14473
|
-
|
|
14671
|
+
fs15.unlinkSync(unitPath);
|
|
14474
14672
|
removed = true;
|
|
14475
14673
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
14476
14674
|
} catch {
|
|
@@ -14537,13 +14735,13 @@ async function daemonStatus() {
|
|
|
14537
14735
|
console.log(` Port: ${port}`);
|
|
14538
14736
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
14539
14737
|
console.log(` Platform: ${process.platform}`);
|
|
14540
|
-
console.log(` PID file: ${
|
|
14541
|
-
console.log(` Log file: ${
|
|
14738
|
+
console.log(` PID file: ${fs15.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
14739
|
+
console.log(` Log file: ${fs15.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
14542
14740
|
try {
|
|
14543
14741
|
const configPath = resolveConfigPath();
|
|
14544
|
-
const raw =
|
|
14545
|
-
const remnicCfg =
|
|
14546
|
-
const config =
|
|
14742
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
14743
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
14744
|
+
const config = parseConfig7(remnicCfg);
|
|
14547
14745
|
const extRoot = resolveExtensionsRoot(config);
|
|
14548
14746
|
const noopLog = { warn: () => {
|
|
14549
14747
|
}, debug: () => {
|
|
@@ -14582,9 +14780,9 @@ function daemonStart() {
|
|
|
14582
14780
|
return;
|
|
14583
14781
|
}
|
|
14584
14782
|
}
|
|
14585
|
-
|
|
14586
|
-
|
|
14587
|
-
const logStream =
|
|
14783
|
+
fs15.mkdirSync(PID_DIR, { recursive: true });
|
|
14784
|
+
fs15.mkdirSync(LOGS_DIR, { recursive: true });
|
|
14785
|
+
const logStream = fs15.openSync(LOG_FILE, "a");
|
|
14588
14786
|
const serverBin = resolveServerBin();
|
|
14589
14787
|
const isSource = serverBin.endsWith(".ts");
|
|
14590
14788
|
let cmd;
|
|
@@ -14606,7 +14804,7 @@ function daemonStart() {
|
|
|
14606
14804
|
}
|
|
14607
14805
|
});
|
|
14608
14806
|
child.unref();
|
|
14609
|
-
|
|
14807
|
+
fs15.writeFileSync(PID_FILE, String(child.pid));
|
|
14610
14808
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
14611
14809
|
console.log(` Log: ${LOG_FILE}`);
|
|
14612
14810
|
}
|
|
@@ -14640,11 +14838,11 @@ function daemonStop() {
|
|
|
14640
14838
|
console.log("Process not found (cleaning up PID file)");
|
|
14641
14839
|
}
|
|
14642
14840
|
try {
|
|
14643
|
-
|
|
14841
|
+
fs15.unlinkSync(PID_FILE);
|
|
14644
14842
|
} catch {
|
|
14645
14843
|
}
|
|
14646
14844
|
try {
|
|
14647
|
-
|
|
14845
|
+
fs15.unlinkSync(LEGACY_PID_FILE);
|
|
14648
14846
|
} catch {
|
|
14649
14847
|
}
|
|
14650
14848
|
}
|
|
@@ -14770,11 +14968,11 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
14770
14968
|
});
|
|
14771
14969
|
}
|
|
14772
14970
|
async function cmdBinary(rest) {
|
|
14773
|
-
|
|
14971
|
+
initLogger3();
|
|
14774
14972
|
const configPath = resolveConfigPath();
|
|
14775
|
-
const raw =
|
|
14776
|
-
const remnicCfg =
|
|
14777
|
-
const config =
|
|
14973
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
14974
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
14975
|
+
const config = parseConfig7(remnicCfg);
|
|
14778
14976
|
const memoryDir = resolveMemoryDir();
|
|
14779
14977
|
const blConfig = {
|
|
14780
14978
|
enabled: config.binaryLifecycleEnabled,
|
|
@@ -14892,7 +15090,7 @@ Clean complete: cleaned=${result.cleaned}`
|
|
|
14892
15090
|
}
|
|
14893
15091
|
async function cmdOpenclawInstall(opts) {
|
|
14894
15092
|
const configPath = resolveOpenclawConfigPath(opts.configPath);
|
|
14895
|
-
const fallbackMemoryDir =
|
|
15093
|
+
const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
14896
15094
|
console.log(`OpenClaw config: ${configPath}`);
|
|
14897
15095
|
const existingConfig = readOpenclawConfig(configPath);
|
|
14898
15096
|
const { plugins, entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
@@ -14963,7 +15161,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
14963
15161
|
} else if (slotIsActiveLegacy) {
|
|
14964
15162
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
14965
15163
|
}
|
|
14966
|
-
if (!
|
|
15164
|
+
if (!fs15.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
14967
15165
|
if (hasLegacy && migrateLegacy) {
|
|
14968
15166
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
14969
15167
|
}
|
|
@@ -14983,8 +15181,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
14983
15181
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
14984
15182
|
return;
|
|
14985
15183
|
}
|
|
14986
|
-
if (
|
|
14987
|
-
const st =
|
|
15184
|
+
if (fs15.existsSync(memoryDir)) {
|
|
15185
|
+
const st = fs15.statSync(memoryDir);
|
|
14988
15186
|
if (!st.isDirectory()) {
|
|
14989
15187
|
throw new Error(
|
|
14990
15188
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -14992,12 +15190,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
14992
15190
|
);
|
|
14993
15191
|
}
|
|
14994
15192
|
} else {
|
|
14995
|
-
|
|
15193
|
+
fs15.mkdirSync(memoryDir, { recursive: true });
|
|
14996
15194
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
14997
15195
|
}
|
|
14998
|
-
const configDir =
|
|
14999
|
-
if (!
|
|
15000
|
-
|
|
15196
|
+
const configDir = path18.dirname(configPath);
|
|
15197
|
+
if (!fs15.existsSync(configDir)) {
|
|
15198
|
+
fs15.mkdirSync(configDir, { recursive: true });
|
|
15001
15199
|
}
|
|
15002
15200
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
15003
15201
|
console.log("\nDone! Summary of changes:");
|
|
@@ -15024,12 +15222,12 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15024
15222
|
const pluginDir = resolveOpenclawPluginDir(opts.pluginDir);
|
|
15025
15223
|
const managedTargetDir = resolveOpenclawManagedPluginDir();
|
|
15026
15224
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
15027
|
-
const fallbackMemoryDir =
|
|
15225
|
+
const fallbackMemoryDir = path18.join(resolveOpenclawStateDir(), "workspace", "memory", "local");
|
|
15028
15226
|
const packageSpec = buildOpenclawManagedUpgradePackageSpec(opts.version);
|
|
15029
|
-
const configExistedBefore =
|
|
15227
|
+
const configExistedBefore = fs15.existsSync(configPath);
|
|
15030
15228
|
const existingConfig = readOpenclawConfig(configPath);
|
|
15031
15229
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
15032
|
-
const preservedMemoryDir = opts.memoryDir ?
|
|
15230
|
+
const preservedMemoryDir = opts.memoryDir ? path18.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
15033
15231
|
console.log(`OpenClaw config: ${configPath}`);
|
|
15034
15232
|
console.log(`Plugin dir: ${pluginDir}`);
|
|
15035
15233
|
if (legacyPluginDirForBackup) {
|
|
@@ -15037,7 +15235,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15037
15235
|
}
|
|
15038
15236
|
console.log(`Memory dir: ${preservedMemoryDir}`);
|
|
15039
15237
|
console.log(`Package spec: ${packageSpec}`);
|
|
15040
|
-
console.log(`Backup root: ${
|
|
15238
|
+
console.log(`Backup root: ${path18.join(resolveOpenclawStateDir(), "backups")}`);
|
|
15041
15239
|
const plannedActions = [
|
|
15042
15240
|
`backup openclaw.json and the existing ${REMNIC_OPENCLAW_PLUGIN_ID} extension`,
|
|
15043
15241
|
...legacyPluginDirForBackup ? [`backup the existing ${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID} extension without modifying it`] : [],
|
|
@@ -15075,9 +15273,9 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15075
15273
|
assertDirectoryPathOrMissing(legacyPluginDirForBackup, "Legacy OpenClaw plugin dir");
|
|
15076
15274
|
}
|
|
15077
15275
|
const backupDir = createOpenclawUpgradeBackupDir();
|
|
15078
|
-
const configBackupPath =
|
|
15079
|
-
const pluginBackupDir =
|
|
15080
|
-
const legacyPluginBackupDir = legacyPluginDirForBackup ?
|
|
15276
|
+
const configBackupPath = path18.join(backupDir, "openclaw.json");
|
|
15277
|
+
const pluginBackupDir = path18.join(backupDir, "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
15278
|
+
const legacyPluginBackupDir = legacyPluginDirForBackup ? path18.join(backupDir, "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID) : void 0;
|
|
15081
15279
|
const backupNotes = [];
|
|
15082
15280
|
if (backupPathIfPresent(configPath, configBackupPath)) {
|
|
15083
15281
|
backupNotes.push(`+ Backed up config to ${configBackupPath}`);
|
|
@@ -15127,7 +15325,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15127
15325
|
const managedRollbackDir = publishedInstallError ? publishedInstallError.managedRollbackDir : installResult?.managedRollbackDir;
|
|
15128
15326
|
const managedRollbackTargetDir = publishedInstallError?.managedRollbackTargetDir ?? installResult?.managedRollbackTargetDir ?? managedTargetDir;
|
|
15129
15327
|
const requiresHostManagedRestore = publishedInstallError?.requiresHostManagedRestore ?? installResult?.requiresHostManagedRestore ?? false;
|
|
15130
|
-
const managedRollbackSharesPluginDir = managedRollbackDir &&
|
|
15328
|
+
const managedRollbackSharesPluginDir = managedRollbackDir && path18.resolve(managedRollbackTargetDir) === path18.resolve(pluginDir);
|
|
15131
15329
|
const pluginRollbackDir = managedRollbackSharesPluginDir ? requiresHostManagedRestore ? rollbackDir : rollbackDir ?? managedRollbackDir : rollbackDir;
|
|
15132
15330
|
const shouldRestorePlugin = Boolean(
|
|
15133
15331
|
installResult && !requiresHostManagedRestore || pluginRollbackDir || publishedInstallError?.shouldRestoreBackup
|
|
@@ -15184,7 +15382,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
15184
15382
|
rollbackErrors.push(error);
|
|
15185
15383
|
}
|
|
15186
15384
|
if (pendingConfigRestoreError) rollbackErrors.push(pendingConfigRestoreError);
|
|
15187
|
-
if (managedRollbackDir &&
|
|
15385
|
+
if (managedRollbackDir && path18.resolve(managedRollbackTargetDir) !== path18.resolve(pluginDir) && !requiresHostManagedRestore) {
|
|
15188
15386
|
try {
|
|
15189
15387
|
rollbackNotes.push(
|
|
15190
15388
|
...rollbackOpenclawUpgrade({
|
|
@@ -15250,16 +15448,16 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
15250
15448
|
console.log(" - Re-apply any local source patches to the new package only after verifying the published build.");
|
|
15251
15449
|
}
|
|
15252
15450
|
function createOpenclawUpgradeBackupDir() {
|
|
15253
|
-
const backupsRoot =
|
|
15254
|
-
|
|
15255
|
-
return
|
|
15451
|
+
const backupsRoot = path18.join(resolveOpenclawStateDir(), "backups");
|
|
15452
|
+
fs15.mkdirSync(backupsRoot, { recursive: true });
|
|
15453
|
+
return fs15.mkdtempSync(path18.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
15256
15454
|
}
|
|
15257
15455
|
async function cmdTaxonomy(rest) {
|
|
15258
|
-
|
|
15456
|
+
initLogger3();
|
|
15259
15457
|
const configPath = resolveConfigPath();
|
|
15260
|
-
const raw =
|
|
15261
|
-
const remnicCfg =
|
|
15262
|
-
const config =
|
|
15458
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
15459
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
15460
|
+
const config = parseConfig7(remnicCfg);
|
|
15263
15461
|
if (!config.taxonomyEnabled) {
|
|
15264
15462
|
console.error(
|
|
15265
15463
|
"Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
|
|
@@ -15294,9 +15492,9 @@ async function cmdTaxonomy(rest) {
|
|
|
15294
15492
|
const doc = generateResolverDocument(taxonomy);
|
|
15295
15493
|
console.log(doc);
|
|
15296
15494
|
if (config.taxonomyAutoGenResolver) {
|
|
15297
|
-
const resolverPath =
|
|
15298
|
-
|
|
15299
|
-
|
|
15495
|
+
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
15496
|
+
fs15.mkdirSync(path18.dirname(resolverPath), { recursive: true });
|
|
15497
|
+
fs15.writeFileSync(resolverPath, doc);
|
|
15300
15498
|
console.error(`Written: ${resolverPath}`);
|
|
15301
15499
|
}
|
|
15302
15500
|
break;
|
|
@@ -15341,8 +15539,8 @@ async function cmdTaxonomy(rest) {
|
|
|
15341
15539
|
console.log(`Added category "${id}" (${name}).`);
|
|
15342
15540
|
if (config.taxonomyAutoGenResolver) {
|
|
15343
15541
|
const doc = generateResolverDocument(taxonomy);
|
|
15344
|
-
const resolverPath =
|
|
15345
|
-
|
|
15542
|
+
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
15543
|
+
fs15.writeFileSync(resolverPath, doc);
|
|
15346
15544
|
console.error(`Regenerated: ${resolverPath}`);
|
|
15347
15545
|
}
|
|
15348
15546
|
break;
|
|
@@ -15372,8 +15570,8 @@ async function cmdTaxonomy(rest) {
|
|
|
15372
15570
|
console.log(`Removed category "${id}".`);
|
|
15373
15571
|
if (config.taxonomyAutoGenResolver) {
|
|
15374
15572
|
const doc = generateResolverDocument(taxonomy);
|
|
15375
|
-
const resolverPath =
|
|
15376
|
-
|
|
15573
|
+
const resolverPath = path18.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
15574
|
+
fs15.writeFileSync(resolverPath, doc);
|
|
15377
15575
|
console.error(`Regenerated: ${resolverPath}`);
|
|
15378
15576
|
}
|
|
15379
15577
|
break;
|
|
@@ -15564,12 +15762,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
15564
15762
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
15565
15763
|
);
|
|
15566
15764
|
}
|
|
15567
|
-
if (!
|
|
15765
|
+
if (!fs15.existsSync(args.memoryDir)) {
|
|
15568
15766
|
throw new Error(
|
|
15569
15767
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
15570
15768
|
);
|
|
15571
15769
|
}
|
|
15572
|
-
if (!
|
|
15770
|
+
if (!fs15.statSync(args.memoryDir).isDirectory()) {
|
|
15573
15771
|
throw new Error(
|
|
15574
15772
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
15575
15773
|
);
|
|
@@ -15654,11 +15852,11 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
15654
15852
|
);
|
|
15655
15853
|
}
|
|
15656
15854
|
const formatted = adapter.formatRecords(records);
|
|
15657
|
-
const outDir =
|
|
15658
|
-
|
|
15855
|
+
const outDir = path18.dirname(args.output);
|
|
15856
|
+
fs15.mkdirSync(outDir, { recursive: true });
|
|
15659
15857
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
15660
|
-
|
|
15661
|
-
|
|
15858
|
+
fs15.writeFileSync(tmpPath, formatted, "utf-8");
|
|
15859
|
+
fs15.renameSync(tmpPath, args.output);
|
|
15662
15860
|
stdout.write(
|
|
15663
15861
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
15664
15862
|
`
|
|
@@ -15707,6 +15905,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15707
15905
|
case "xray":
|
|
15708
15906
|
await cmdXray(rest);
|
|
15709
15907
|
break;
|
|
15908
|
+
case "security":
|
|
15909
|
+
await cmdSecurity(rest);
|
|
15910
|
+
break;
|
|
15710
15911
|
case "doctor":
|
|
15711
15912
|
await cmdDoctor();
|
|
15712
15913
|
break;
|
|
@@ -15762,7 +15963,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15762
15963
|
case "tree": {
|
|
15763
15964
|
const subAction = rest[0];
|
|
15764
15965
|
const json = rest.includes("--json");
|
|
15765
|
-
const outputDir = resolveFlag(rest, "--output") ??
|
|
15966
|
+
const outputDir = resolveFlag(rest, "--output") ?? path18.join(process.cwd(), ".remnic", "context-tree");
|
|
15766
15967
|
const categoriesFlag = resolveFlag(rest, "--categories");
|
|
15767
15968
|
const categories = categoriesFlag ? categoriesFlag.split(",") : void 0;
|
|
15768
15969
|
const maxPerCategoryRaw = resolveFlag(rest, "--max-per-category");
|
|
@@ -15827,7 +16028,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15827
16028
|
}
|
|
15828
16029
|
}, 500);
|
|
15829
16030
|
};
|
|
15830
|
-
|
|
16031
|
+
fs15.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
15831
16032
|
if (filename && filename.startsWith(".")) return;
|
|
15832
16033
|
rebuild();
|
|
15833
16034
|
});
|
|
@@ -15835,12 +16036,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15835
16036
|
});
|
|
15836
16037
|
} else if (subAction === "validate") {
|
|
15837
16038
|
const treeDir = outputDir;
|
|
15838
|
-
if (!
|
|
16039
|
+
if (!fs15.existsSync(treeDir)) {
|
|
15839
16040
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
15840
16041
|
process.exit(1);
|
|
15841
16042
|
}
|
|
15842
|
-
const indexPath =
|
|
15843
|
-
if (!
|
|
16043
|
+
const indexPath = path18.join(treeDir, "INDEX.md");
|
|
16044
|
+
if (!fs15.existsSync(indexPath)) {
|
|
15844
16045
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
15845
16046
|
process.exit(1);
|
|
15846
16047
|
}
|
|
@@ -16022,10 +16223,10 @@ Other:
|
|
|
16022
16223
|
let wearablesService;
|
|
16023
16224
|
try {
|
|
16024
16225
|
const configPath = resolveConfigPath();
|
|
16025
|
-
const raw =
|
|
16026
|
-
const remnicCfg =
|
|
16027
|
-
const config =
|
|
16028
|
-
wearablesOrchestrator = new
|
|
16226
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
16227
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
16228
|
+
const config = parseConfig7(remnicCfg);
|
|
16229
|
+
wearablesOrchestrator = new Orchestrator4(config);
|
|
16029
16230
|
await wearablesOrchestrator.initialize();
|
|
16030
16231
|
await wearablesOrchestrator.deferredReady;
|
|
16031
16232
|
wearablesService = wearablesOrchestrator.getWearablesService();
|
|
@@ -16077,10 +16278,10 @@ Other:
|
|
|
16077
16278
|
const targetFactory = async () => {
|
|
16078
16279
|
if (!orchestratorSingleton) {
|
|
16079
16280
|
const configPath = resolveConfigPath();
|
|
16080
|
-
const raw =
|
|
16081
|
-
const remnicCfg =
|
|
16082
|
-
const config =
|
|
16083
|
-
orchestratorSingleton = new
|
|
16281
|
+
const raw = fs15.existsSync(configPath) ? JSON.parse(fs15.readFileSync(configPath, "utf8")) : {};
|
|
16282
|
+
const remnicCfg = resolveRemnicConfigRecord6(raw);
|
|
16283
|
+
const config = parseConfig7(remnicCfg);
|
|
16284
|
+
orchestratorSingleton = new Orchestrator4(config);
|
|
16084
16285
|
await orchestratorSingleton.initialize();
|
|
16085
16286
|
await orchestratorSingleton.deferredReady;
|
|
16086
16287
|
}
|
|
@@ -16310,9 +16511,9 @@ Usage:
|
|
|
16310
16511
|
remnic extensions <list|show|validate|reload> Manage memory extensions
|
|
16311
16512
|
remnic space <list|switch|create|delete|push|pull|share|promote|audit> Manage spaces
|
|
16312
16513
|
create accepts --parent <id> to set parent-child relationship
|
|
16313
|
-
remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|attribute|drift-gen|coding> [benchmark...] [--quick] [--all] [--dataset-dir <path>] [--results-dir <path>] [--baselines-dir <path>] [--threshold <value>] [--detail] [--format <json|csv|html>] [--output <path>] [--target remnic-ai] [--json]
|
|
16514
|
+
remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|attribute|drift-gen|coding|security> [benchmark...] [--quick] [--all] [--dataset-dir <path>] [--results-dir <path>] [--baselines-dir <path>] [--threshold <value>] [--detail] [--format <json|csv|html>] [--output <path>] [--target remnic-ai] [--json]
|
|
16314
16515
|
benchmark is kept as a compatibility alias. check/report remain under that alias.
|
|
16315
|
-
remnic benchmark <list|run|datasets|runs|compare|results|baseline|export|publish|ui|providers|check|report|attribute|drift-gen|coding> [queries...] [--explain] [--baseline=<path>] [--report=<path>]
|
|
16516
|
+
remnic benchmark <list|run|datasets|runs|compare|results|baseline|export|publish|ui|providers|check|report|attribute|drift-gen|coding|security> [queries...] [--explain] [--baseline=<path>] [--report=<path>]
|
|
16316
16517
|
remnic briefing [--since <window>] [--focus <filter>] [--save] [--format markdown|json]
|
|
16317
16518
|
Daily context briefing. Windows: yesterday, today, NNh, NNd, NNw.
|
|
16318
16519
|
Focus: person:<name>, project:<name>, topic:<name>.
|