@remnic/cli 9.8.0 → 9.9.1
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 +477 -317
- package/package.json +28 -28
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
|
-
import
|
|
21
|
+
import fs10 from "fs";
|
|
22
22
|
import os from "os";
|
|
23
23
|
import path12 from "path";
|
|
24
24
|
import { createHash as createHash2 } from "crypto";
|
|
@@ -26,13 +26,13 @@ import * as childProcess2 from "child_process";
|
|
|
26
26
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
27
27
|
import { gzipSync } from "zlib";
|
|
28
28
|
import {
|
|
29
|
-
parseConfig as
|
|
29
|
+
parseConfig as parseConfig3,
|
|
30
30
|
isOpenaiApiKeyDisabled,
|
|
31
31
|
resolveEnvVars,
|
|
32
|
-
resolveRemnicConfigRecord as
|
|
33
|
-
Orchestrator,
|
|
34
|
-
EngramAccessService,
|
|
35
|
-
initLogger,
|
|
32
|
+
resolveRemnicConfigRecord as resolveRemnicConfigRecord3,
|
|
33
|
+
Orchestrator as Orchestrator2,
|
|
34
|
+
EngramAccessService as EngramAccessService2,
|
|
35
|
+
initLogger as initLogger2,
|
|
36
36
|
onboard,
|
|
37
37
|
curate,
|
|
38
38
|
listReviewItems,
|
|
@@ -219,9 +219,10 @@ function buildNamespacePolicyCheck(args) {
|
|
|
219
219
|
}
|
|
220
220
|
|
|
221
221
|
// src/index.ts
|
|
222
|
-
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
222
|
+
import { WriteQuarantineStore as WriteQuarantineStore2 } from "@remnic/core/write-quarantine.js";
|
|
223
223
|
|
|
224
224
|
// src/quarantine-cli.ts
|
|
225
|
+
import { basename } from "path";
|
|
225
226
|
function renderQuarantineList(records, format) {
|
|
226
227
|
if (format === "json") {
|
|
227
228
|
const summary = records.map((record) => ({
|
|
@@ -244,17 +245,172 @@ function renderQuarantineList(records, format) {
|
|
|
244
245
|
}
|
|
245
246
|
return lines.join("\n");
|
|
246
247
|
}
|
|
248
|
+
async function replayQuarantine(opts) {
|
|
249
|
+
const result = { replayed: 0, failures: [], deleteFailures: [] };
|
|
250
|
+
for (const entry of await opts.store.entries()) {
|
|
251
|
+
const { record } = entry;
|
|
252
|
+
const basePayload = record.payload;
|
|
253
|
+
const principal = opts.principal ?? record.principal ?? void 0;
|
|
254
|
+
const idempotencyKey = typeof basePayload.idempotencyKey === "string" && basePayload.idempotencyKey.length > 0 ? basePayload.idempotencyKey : `quarantine-replay:${basename(entry.path)}`;
|
|
255
|
+
const request = {
|
|
256
|
+
...basePayload,
|
|
257
|
+
namespace: opts.targetNamespace,
|
|
258
|
+
suppressQuarantine: true,
|
|
259
|
+
idempotencyKey,
|
|
260
|
+
...principal ? { authenticatedPrincipal: principal } : {}
|
|
261
|
+
};
|
|
262
|
+
try {
|
|
263
|
+
await opts.submit(record.operation, request);
|
|
264
|
+
} catch (err) {
|
|
265
|
+
result.failures.push({
|
|
266
|
+
operation: record.operation,
|
|
267
|
+
attemptedNamespace: opts.targetNamespace,
|
|
268
|
+
error: err instanceof Error ? err.message : String(err)
|
|
269
|
+
});
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
const removed = await opts.store.removeEntry(entry.path);
|
|
274
|
+
if (removed) {
|
|
275
|
+
result.replayed += 1;
|
|
276
|
+
} else {
|
|
277
|
+
result.deleteFailures.push({
|
|
278
|
+
path: entry.path,
|
|
279
|
+
error: "entry not removed (outside quarantine root or already absent)"
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
} catch (err) {
|
|
283
|
+
result.deleteFailures.push({
|
|
284
|
+
path: entry.path,
|
|
285
|
+
error: err instanceof Error ? err.message : String(err)
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return result;
|
|
290
|
+
}
|
|
291
|
+
function renderReplayResult(result, targetNamespace, format) {
|
|
292
|
+
if (format === "json") {
|
|
293
|
+
return JSON.stringify(
|
|
294
|
+
{
|
|
295
|
+
targetNamespace,
|
|
296
|
+
replayed: result.replayed,
|
|
297
|
+
failures: result.failures,
|
|
298
|
+
deleteFailures: result.deleteFailures
|
|
299
|
+
},
|
|
300
|
+
null,
|
|
301
|
+
2
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
if (format !== "text") {
|
|
305
|
+
throw new Error(`Unsupported quarantine format: ${String(format)}`);
|
|
306
|
+
}
|
|
307
|
+
const lines = [`Replayed ${result.replayed} quarantined write(s) into namespace ${targetNamespace}.`];
|
|
308
|
+
if (result.failures.length > 0) {
|
|
309
|
+
lines.push("", `Failures (${result.failures.length}); left parked:`);
|
|
310
|
+
for (const failure of result.failures) {
|
|
311
|
+
lines.push(` ${failure.operation} attemptedNamespace=${failure.attemptedNamespace} error=${failure.error}`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
if (result.deleteFailures.length > 0) {
|
|
315
|
+
lines.push("", `Delete failures (${result.deleteFailures.length}); re-submitted but still parked:`);
|
|
316
|
+
for (const del of result.deleteFailures) {
|
|
317
|
+
lines.push(` ${del.path} error=${del.error}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return lines.join("\n");
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// src/quarantine-replay.ts
|
|
324
|
+
import * as fs from "fs";
|
|
325
|
+
import { EngramAccessService, Orchestrator, initLogger, parseConfig, resolveRemnicConfigRecord } from "@remnic/core";
|
|
326
|
+
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
327
|
+
function valueFlag(args, flag) {
|
|
328
|
+
const occurrences = args.filter((a) => a === flag).length;
|
|
329
|
+
if (occurrences === 0) return void 0;
|
|
330
|
+
if (occurrences > 1) {
|
|
331
|
+
throw new Error(`${flag} may be given at most once.`);
|
|
332
|
+
}
|
|
333
|
+
const value = args[args.indexOf(flag) + 1];
|
|
334
|
+
if (value === void 0 || value.startsWith("--")) {
|
|
335
|
+
throw new Error(`${flag} requires a value. Provide it as \`${flag} <value>\`, not a bare flag.`);
|
|
336
|
+
}
|
|
337
|
+
if (value.trim().length === 0) {
|
|
338
|
+
throw new Error(`${flag} requires a non-empty value.`);
|
|
339
|
+
}
|
|
340
|
+
return value;
|
|
341
|
+
}
|
|
342
|
+
async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
343
|
+
let targetNamespace;
|
|
344
|
+
let principal;
|
|
345
|
+
try {
|
|
346
|
+
targetNamespace = valueFlag(rest, "--namespace");
|
|
347
|
+
principal = valueFlag(rest, "--principal");
|
|
348
|
+
} catch (err) {
|
|
349
|
+
process.stderr.write(`quarantine replay: ${err instanceof Error ? err.message : String(err)}
|
|
350
|
+
`);
|
|
351
|
+
process.exitCode = 2;
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (!targetNamespace || targetNamespace.trim().length === 0) {
|
|
355
|
+
process.stderr.write("quarantine replay: --namespace <ns> is required.\n");
|
|
356
|
+
process.exitCode = 2;
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
const valued = /* @__PURE__ */ new Set(["--namespace", "--principal"]);
|
|
360
|
+
const bad = rest.filter((a, i) => a.startsWith("--") ? a !== "--json" && !valued.has(a) : !valued.has(rest[i - 1]));
|
|
361
|
+
if (bad.length > 0) {
|
|
362
|
+
process.stderr.write(
|
|
363
|
+
`quarantine replay: unexpected argument(s): ${bad.join(", ")}. Use: replay --namespace <ns> [--principal <p>] [--json].
|
|
364
|
+
`
|
|
365
|
+
);
|
|
366
|
+
process.exitCode = 2;
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
initLogger();
|
|
370
|
+
let orchestrator;
|
|
371
|
+
try {
|
|
372
|
+
const configPath = resolveConfigPath2();
|
|
373
|
+
const raw = fs.existsSync(configPath) ? JSON.parse(fs.readFileSync(configPath, "utf8")) : {};
|
|
374
|
+
const config = parseConfig(resolveRemnicConfigRecord(raw));
|
|
375
|
+
orchestrator = new Orchestrator(config);
|
|
376
|
+
await orchestrator.initialize();
|
|
377
|
+
await orchestrator.deferredReady;
|
|
378
|
+
const service = new EngramAccessService(orchestrator);
|
|
379
|
+
const store = new WriteQuarantineStore(config.memoryDir);
|
|
380
|
+
const result = await replayQuarantine({
|
|
381
|
+
store,
|
|
382
|
+
targetNamespace,
|
|
383
|
+
principal,
|
|
384
|
+
submit: async (operation, request) => {
|
|
385
|
+
if (operation === "observe") {
|
|
386
|
+
await service.observe(request);
|
|
387
|
+
} else if (operation === "memory_store") {
|
|
388
|
+
await service.memoryStore(request);
|
|
389
|
+
} else {
|
|
390
|
+
await service.suggestionSubmit(request);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
});
|
|
394
|
+
console.log(renderReplayResult(result, targetNamespace, format));
|
|
395
|
+
if (result.failures.length > 0 || result.deleteFailures.length > 0) process.exitCode = 1;
|
|
396
|
+
} catch {
|
|
397
|
+
process.stderr.write("quarantine replay: unable to replay quarantine store\n");
|
|
398
|
+
process.exitCode = 2;
|
|
399
|
+
} finally {
|
|
400
|
+
if (orchestrator) await orchestrator.destroy();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
247
403
|
|
|
248
404
|
// src/offline-impression-rotation.ts
|
|
249
|
-
import
|
|
250
|
-
import { parseConfig, resolveRemnicConfigRecord, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
405
|
+
import fs2 from "fs";
|
|
406
|
+
import { parseConfig as parseConfig2, resolveRemnicConfigRecord as resolveRemnicConfigRecord2, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
251
407
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
252
408
|
function parseConfigQuietly(raw) {
|
|
253
409
|
const originalWarn = console.warn;
|
|
254
410
|
console.warn = () => {
|
|
255
411
|
};
|
|
256
412
|
try {
|
|
257
|
-
return
|
|
413
|
+
return parseConfig2(resolveRemnicConfigRecord2(raw));
|
|
258
414
|
} finally {
|
|
259
415
|
console.warn = originalWarn;
|
|
260
416
|
}
|
|
@@ -268,7 +424,7 @@ var OFFLINE_CONFIG_KEYS = [
|
|
|
268
424
|
function pickOfflineConfigRecord(raw) {
|
|
269
425
|
let resolved;
|
|
270
426
|
try {
|
|
271
|
-
resolved =
|
|
427
|
+
resolved = resolveRemnicConfigRecord2(raw);
|
|
272
428
|
} catch {
|
|
273
429
|
resolved = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
274
430
|
}
|
|
@@ -281,7 +437,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
281
437
|
function resolveOfflineImpressionRotation(configPath) {
|
|
282
438
|
let raw;
|
|
283
439
|
try {
|
|
284
|
-
raw =
|
|
440
|
+
raw = fs2.existsSync(configPath) ? JSON.parse(fs2.readFileSync(configPath, "utf8")) : {};
|
|
285
441
|
} catch {
|
|
286
442
|
throw new Error(
|
|
287
443
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -311,7 +467,7 @@ async function drainOfflineSyncImpressions(memoryDir, rotation) {
|
|
|
311
467
|
|
|
312
468
|
// src/offline-storage-io.ts
|
|
313
469
|
import { mkdtemp, readdir, lstat, rm } from "fs/promises";
|
|
314
|
-
import
|
|
470
|
+
import fs3 from "fs";
|
|
315
471
|
import path from "path";
|
|
316
472
|
import { createHash, createDecipheriv } from "crypto";
|
|
317
473
|
import {
|
|
@@ -447,7 +603,7 @@ async function* readOfflineSyncFileChunks(options) {
|
|
|
447
603
|
});
|
|
448
604
|
}
|
|
449
605
|
async function readFilePrefix(filePath, length) {
|
|
450
|
-
const handle = await
|
|
606
|
+
const handle = await fs3.promises.open(filePath, "r");
|
|
451
607
|
try {
|
|
452
608
|
const out = Buffer.alloc(length);
|
|
453
609
|
const { bytesRead } = await handle.read(out, 0, length, 0);
|
|
@@ -457,7 +613,7 @@ async function readFilePrefix(filePath, length) {
|
|
|
457
613
|
}
|
|
458
614
|
}
|
|
459
615
|
async function* readPlainOfflineFileChunks(filePath, chunkSize) {
|
|
460
|
-
const stream =
|
|
616
|
+
const stream = fs3.createReadStream(filePath, { highWaterMark: chunkSize });
|
|
461
617
|
for await (const chunk of stream) {
|
|
462
618
|
yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
463
619
|
}
|
|
@@ -500,9 +656,9 @@ async function* readEncryptedOfflineFileChunks(options) {
|
|
|
500
656
|
});
|
|
501
657
|
decipher.setAuthTag(authTag);
|
|
502
658
|
decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
|
|
503
|
-
const output =
|
|
659
|
+
const output = fs3.createWriteStream(tempPath, { mode: 384 });
|
|
504
660
|
try {
|
|
505
|
-
const stream =
|
|
661
|
+
const stream = fs3.createReadStream(options.filePath, {
|
|
506
662
|
start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
|
|
507
663
|
highWaterMark: options.chunkSize
|
|
508
664
|
});
|
|
@@ -570,10 +726,10 @@ function secureStoreEnvelopeHeaderAad(salt) {
|
|
|
570
726
|
|
|
571
727
|
// src/bench-build-freshness.ts
|
|
572
728
|
import {
|
|
573
|
-
existsSync,
|
|
729
|
+
existsSync as existsSync2,
|
|
574
730
|
lstatSync,
|
|
575
731
|
readdirSync,
|
|
576
|
-
readFileSync,
|
|
732
|
+
readFileSync as readFileSync2,
|
|
577
733
|
statSync
|
|
578
734
|
} from "fs";
|
|
579
735
|
import path2 from "path";
|
|
@@ -602,12 +758,12 @@ function assertLocalBenchBuildFreshForDevelopment(currentModuleUrl) {
|
|
|
602
758
|
}
|
|
603
759
|
function checkBenchBuildFreshness(benchPackageDir) {
|
|
604
760
|
const packageJsonPath = path2.join(benchPackageDir, "package.json");
|
|
605
|
-
if (!
|
|
761
|
+
if (!existsSync2(packageJsonPath)) {
|
|
606
762
|
return { stale: false };
|
|
607
763
|
}
|
|
608
764
|
let packageName;
|
|
609
765
|
try {
|
|
610
|
-
packageName = JSON.parse(
|
|
766
|
+
packageName = JSON.parse(readFileSync2(packageJsonPath, "utf8")).name;
|
|
611
767
|
} catch {
|
|
612
768
|
return { stale: false };
|
|
613
769
|
}
|
|
@@ -625,7 +781,7 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
625
781
|
path2.join(benchPackageDir, "tsconfig.json")
|
|
626
782
|
];
|
|
627
783
|
const distPath = path2.join(benchPackageDir, "dist", "index.js");
|
|
628
|
-
if (!
|
|
784
|
+
if (!existsSync2(distPath)) {
|
|
629
785
|
return {
|
|
630
786
|
stale: true,
|
|
631
787
|
reason: `Missing build output: ${distPath}`,
|
|
@@ -658,7 +814,7 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
658
814
|
function newestMtime(roots) {
|
|
659
815
|
let newest;
|
|
660
816
|
const visit = (entryPath) => {
|
|
661
|
-
if (!
|
|
817
|
+
if (!existsSync2(entryPath)) {
|
|
662
818
|
return;
|
|
663
819
|
}
|
|
664
820
|
const stat = lstatSync(entryPath);
|
|
@@ -699,7 +855,7 @@ function isTruthyEnv(value) {
|
|
|
699
855
|
}
|
|
700
856
|
|
|
701
857
|
// src/optional-bench.ts
|
|
702
|
-
import { existsSync as
|
|
858
|
+
import { existsSync as existsSync3 } from "fs";
|
|
703
859
|
import path3 from "path";
|
|
704
860
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
705
861
|
var SPECIFIER2 = "@remnic/bench";
|
|
@@ -719,7 +875,7 @@ async function tryImportLocalWorkspaceBenchSource(err) {
|
|
|
719
875
|
return null;
|
|
720
876
|
}
|
|
721
877
|
const { sourceEntry } = resolveLocalWorkspaceBenchPaths();
|
|
722
|
-
if (!
|
|
878
|
+
if (!existsSync3(sourceEntry)) {
|
|
723
879
|
return null;
|
|
724
880
|
}
|
|
725
881
|
const { tsImport } = await import(TSX_ESM_API_SPECIFIER);
|
|
@@ -737,7 +893,7 @@ function isMissingLocalWorkspaceBenchDistError(err) {
|
|
|
737
893
|
return false;
|
|
738
894
|
}
|
|
739
895
|
const { distEntry, sourceEntry } = resolveLocalWorkspaceBenchPaths();
|
|
740
|
-
if (
|
|
896
|
+
if (existsSync3(distEntry) || !existsSync3(sourceEntry)) {
|
|
741
897
|
return false;
|
|
742
898
|
}
|
|
743
899
|
const message = err.message;
|
|
@@ -798,7 +954,7 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
798
954
|
}
|
|
799
955
|
|
|
800
956
|
// src/daemon-service-candidates.ts
|
|
801
|
-
import
|
|
957
|
+
import fs4 from "fs";
|
|
802
958
|
import path4 from "path";
|
|
803
959
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
804
960
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
@@ -820,7 +976,7 @@ function systemdUnitPaths(homeDir) {
|
|
|
820
976
|
function anyFileExists(paths) {
|
|
821
977
|
return paths.some((candidate) => {
|
|
822
978
|
try {
|
|
823
|
-
return
|
|
979
|
+
return fs4.statSync(candidate).isFile();
|
|
824
980
|
} catch {
|
|
825
981
|
return false;
|
|
826
982
|
}
|
|
@@ -832,7 +988,7 @@ function commandNames(command) {
|
|
|
832
988
|
}
|
|
833
989
|
function isRunnableNodeScript(filePath) {
|
|
834
990
|
try {
|
|
835
|
-
const text =
|
|
991
|
+
const text = fs4.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
836
992
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
837
993
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
838
994
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -845,7 +1001,7 @@ function isRunnableNodeScript(filePath) {
|
|
|
845
1001
|
function resolveShimNodeScript(filePath) {
|
|
846
1002
|
let text;
|
|
847
1003
|
try {
|
|
848
|
-
text =
|
|
1004
|
+
text = fs4.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
849
1005
|
} catch {
|
|
850
1006
|
return void 0;
|
|
851
1007
|
}
|
|
@@ -857,8 +1013,8 @@ function resolveShimNodeScript(filePath) {
|
|
|
857
1013
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
858
1014
|
const resolved = path4.isAbsolute(candidate) ? candidate : path4.resolve(basedir, candidate);
|
|
859
1015
|
try {
|
|
860
|
-
if (
|
|
861
|
-
return
|
|
1016
|
+
if (fs4.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
1017
|
+
return fs4.realpathSync(resolved);
|
|
862
1018
|
}
|
|
863
1019
|
} catch {
|
|
864
1020
|
}
|
|
@@ -866,7 +1022,7 @@ function resolveShimNodeScript(filePath) {
|
|
|
866
1022
|
return void 0;
|
|
867
1023
|
}
|
|
868
1024
|
function resolveRunnableNodeScript(filePath) {
|
|
869
|
-
const realPath =
|
|
1025
|
+
const realPath = fs4.realpathSync(filePath);
|
|
870
1026
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
871
1027
|
return resolveShimNodeScript(realPath);
|
|
872
1028
|
}
|
|
@@ -876,9 +1032,9 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
876
1032
|
for (const name of commandNames(command)) {
|
|
877
1033
|
const candidate = path4.join(dir, name);
|
|
878
1034
|
try {
|
|
879
|
-
const stat =
|
|
1035
|
+
const stat = fs4.statSync(candidate);
|
|
880
1036
|
if (!stat.isFile()) continue;
|
|
881
|
-
if (process.platform !== "win32")
|
|
1037
|
+
if (process.platform !== "win32") fs4.accessSync(candidate, fs4.constants.X_OK);
|
|
882
1038
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
883
1039
|
if (runnable) return runnable;
|
|
884
1040
|
} catch {
|
|
@@ -2233,7 +2389,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
2233
2389
|
}
|
|
2234
2390
|
|
|
2235
2391
|
// src/bench-fallback.ts
|
|
2236
|
-
import
|
|
2392
|
+
import fs5 from "fs";
|
|
2237
2393
|
import path7 from "path";
|
|
2238
2394
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
2239
2395
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
@@ -2305,7 +2461,7 @@ function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs
|
|
|
2305
2461
|
);
|
|
2306
2462
|
}
|
|
2307
2463
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
2308
|
-
const entries =
|
|
2464
|
+
const entries = fs5.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
2309
2465
|
if (entries.length === 0) {
|
|
2310
2466
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
2311
2467
|
}
|
|
@@ -2313,7 +2469,7 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
2313
2469
|
}
|
|
2314
2470
|
|
|
2315
2471
|
// src/openclaw-upgrade-swap.ts
|
|
2316
|
-
import
|
|
2472
|
+
import fs6 from "fs";
|
|
2317
2473
|
import path8 from "path";
|
|
2318
2474
|
function describeError(error) {
|
|
2319
2475
|
return error instanceof Error ? error.message : String(error);
|
|
@@ -2325,7 +2481,7 @@ function createSiblingTempFilePath(targetPath, label) {
|
|
|
2325
2481
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
2326
2482
|
if (explicitMode !== void 0) return explicitMode;
|
|
2327
2483
|
try {
|
|
2328
|
-
return
|
|
2484
|
+
return fs6.statSync(targetPath).mode & 4095;
|
|
2329
2485
|
} catch (error) {
|
|
2330
2486
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2331
2487
|
return 384;
|
|
@@ -2335,8 +2491,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
2335
2491
|
}
|
|
2336
2492
|
function resolveAtomicReplacementPath(targetPath) {
|
|
2337
2493
|
try {
|
|
2338
|
-
if (
|
|
2339
|
-
return
|
|
2494
|
+
if (fs6.lstatSync(targetPath).isSymbolicLink()) {
|
|
2495
|
+
return fs6.realpathSync(targetPath);
|
|
2340
2496
|
}
|
|
2341
2497
|
} catch (error) {
|
|
2342
2498
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2353,7 +2509,7 @@ function createSiblingSwapPath(targetDir, label) {
|
|
|
2353
2509
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
2354
2510
|
if (!displacedDir) return void 0;
|
|
2355
2511
|
try {
|
|
2356
|
-
|
|
2512
|
+
fs6.rmSync(displacedDir, { recursive: true, force: true });
|
|
2357
2513
|
return void 0;
|
|
2358
2514
|
} catch (error) {
|
|
2359
2515
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -2361,55 +2517,55 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
2361
2517
|
}
|
|
2362
2518
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
2363
2519
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
2364
|
-
|
|
2520
|
+
fs6.mkdirSync(path8.dirname(resolvedTargetPath), { recursive: true });
|
|
2365
2521
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
2366
2522
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
2367
2523
|
try {
|
|
2368
2524
|
if (options.hooks?.writeTempFileSync) {
|
|
2369
2525
|
options.hooks.writeTempFileSync(tempPath);
|
|
2370
2526
|
} else {
|
|
2371
|
-
|
|
2527
|
+
fs6.writeFileSync(tempPath, data, { mode });
|
|
2372
2528
|
}
|
|
2373
|
-
|
|
2374
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
2529
|
+
fs6.chmodSync(tempPath, mode);
|
|
2530
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs6.renameSync;
|
|
2375
2531
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
2376
2532
|
} catch (error) {
|
|
2377
|
-
|
|
2533
|
+
fs6.rmSync(tempPath, { force: true });
|
|
2378
2534
|
throw error;
|
|
2379
2535
|
}
|
|
2380
2536
|
}
|
|
2381
2537
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
2382
|
-
if (!
|
|
2538
|
+
if (!fs6.existsSync(sourcePath)) return;
|
|
2383
2539
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
2384
|
-
|
|
2540
|
+
fs6.mkdirSync(path8.dirname(resolvedTargetPath), { recursive: true });
|
|
2385
2541
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
2386
|
-
const mode =
|
|
2542
|
+
const mode = fs6.statSync(sourcePath).mode & 4095;
|
|
2387
2543
|
try {
|
|
2388
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
2544
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs6.copyFileSync;
|
|
2389
2545
|
copyTempFileSync(sourcePath, tempPath);
|
|
2390
|
-
|
|
2391
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
2546
|
+
fs6.chmodSync(tempPath, mode);
|
|
2547
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs6.renameSync;
|
|
2392
2548
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
2393
2549
|
} catch (error) {
|
|
2394
|
-
|
|
2550
|
+
fs6.rmSync(tempPath, { force: true });
|
|
2395
2551
|
throw error;
|
|
2396
2552
|
}
|
|
2397
2553
|
}
|
|
2398
2554
|
function swapDirectoryWithRollback(stagedDir, targetDir, rollbackDir) {
|
|
2399
2555
|
let hasRollbackCopy = false;
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
if (
|
|
2403
|
-
|
|
2556
|
+
fs6.mkdirSync(path8.dirname(targetDir), { recursive: true });
|
|
2557
|
+
fs6.rmSync(rollbackDir, { recursive: true, force: true });
|
|
2558
|
+
if (fs6.existsSync(targetDir)) {
|
|
2559
|
+
fs6.renameSync(targetDir, rollbackDir);
|
|
2404
2560
|
hasRollbackCopy = true;
|
|
2405
2561
|
}
|
|
2406
2562
|
try {
|
|
2407
|
-
|
|
2563
|
+
fs6.renameSync(stagedDir, targetDir);
|
|
2408
2564
|
} catch (swapError) {
|
|
2409
|
-
|
|
2410
|
-
if (hasRollbackCopy &&
|
|
2565
|
+
fs6.rmSync(targetDir, { recursive: true, force: true });
|
|
2566
|
+
if (hasRollbackCopy && fs6.existsSync(rollbackDir)) {
|
|
2411
2567
|
try {
|
|
2412
|
-
|
|
2568
|
+
fs6.renameSync(rollbackDir, targetDir);
|
|
2413
2569
|
hasRollbackCopy = false;
|
|
2414
2570
|
} catch (restoreError) {
|
|
2415
2571
|
throw new AggregateError(
|
|
@@ -2424,7 +2580,7 @@ function swapDirectoryWithRollback(stagedDir, targetDir, rollbackDir) {
|
|
|
2424
2580
|
}
|
|
2425
2581
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
2426
2582
|
if (!rollbackDir) return;
|
|
2427
|
-
|
|
2583
|
+
fs6.rmSync(rollbackDir, { recursive: true, force: true });
|
|
2428
2584
|
}
|
|
2429
2585
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
2430
2586
|
if (!rollbackDir) return void 0;
|
|
@@ -2436,20 +2592,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
2436
2592
|
}
|
|
2437
2593
|
}
|
|
2438
2594
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
2439
|
-
if (!
|
|
2595
|
+
if (!fs6.existsSync(rollbackDir)) {
|
|
2440
2596
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
2441
2597
|
}
|
|
2442
|
-
|
|
2443
|
-
const displacedDir =
|
|
2598
|
+
fs6.mkdirSync(path8.dirname(targetDir), { recursive: true });
|
|
2599
|
+
const displacedDir = fs6.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
2444
2600
|
if (displacedDir) {
|
|
2445
|
-
|
|
2601
|
+
fs6.renameSync(targetDir, displacedDir);
|
|
2446
2602
|
}
|
|
2447
2603
|
try {
|
|
2448
|
-
|
|
2604
|
+
fs6.renameSync(rollbackDir, targetDir);
|
|
2449
2605
|
} catch (restoreError) {
|
|
2450
|
-
if (displacedDir &&
|
|
2606
|
+
if (displacedDir && fs6.existsSync(displacedDir)) {
|
|
2451
2607
|
try {
|
|
2452
|
-
|
|
2608
|
+
fs6.renameSync(displacedDir, targetDir);
|
|
2453
2609
|
} catch (revertError) {
|
|
2454
2610
|
throw new AggregateError(
|
|
2455
2611
|
[restoreError, revertError],
|
|
@@ -2468,23 +2624,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
2468
2624
|
);
|
|
2469
2625
|
}
|
|
2470
2626
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
2471
|
-
if (!
|
|
2627
|
+
if (!fs6.existsSync(backupDir)) {
|
|
2472
2628
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
2473
2629
|
}
|
|
2474
|
-
|
|
2630
|
+
fs6.mkdirSync(path8.dirname(targetDir), { recursive: true });
|
|
2475
2631
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
2476
|
-
const displacedDir =
|
|
2477
|
-
|
|
2632
|
+
const displacedDir = fs6.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
2633
|
+
fs6.cpSync(backupDir, stagedDir, { recursive: true });
|
|
2478
2634
|
if (displacedDir) {
|
|
2479
|
-
|
|
2635
|
+
fs6.renameSync(targetDir, displacedDir);
|
|
2480
2636
|
}
|
|
2481
2637
|
try {
|
|
2482
|
-
|
|
2638
|
+
fs6.renameSync(stagedDir, targetDir);
|
|
2483
2639
|
} catch (restoreError) {
|
|
2484
|
-
|
|
2485
|
-
if (displacedDir &&
|
|
2640
|
+
fs6.rmSync(targetDir, { recursive: true, force: true });
|
|
2641
|
+
if (displacedDir && fs6.existsSync(displacedDir)) {
|
|
2486
2642
|
try {
|
|
2487
|
-
|
|
2643
|
+
fs6.renameSync(displacedDir, targetDir);
|
|
2488
2644
|
} catch (revertError) {
|
|
2489
2645
|
throw new AggregateError(
|
|
2490
2646
|
[restoreError, revertError],
|
|
@@ -2492,7 +2648,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
2492
2648
|
);
|
|
2493
2649
|
}
|
|
2494
2650
|
}
|
|
2495
|
-
|
|
2651
|
+
fs6.rmSync(stagedDir, { recursive: true, force: true });
|
|
2496
2652
|
throw new Error(
|
|
2497
2653
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
2498
2654
|
{ cause: restoreError }
|
|
@@ -2518,7 +2674,7 @@ function rollbackOpenclawUpgrade({
|
|
|
2518
2674
|
let rollbackRestoreError;
|
|
2519
2675
|
let pluginRestored = false;
|
|
2520
2676
|
try {
|
|
2521
|
-
if (rollbackDir &&
|
|
2677
|
+
if (rollbackDir && fs6.existsSync(rollbackDir)) {
|
|
2522
2678
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
2523
2679
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
2524
2680
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -2528,7 +2684,7 @@ function rollbackOpenclawUpgrade({
|
|
|
2528
2684
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
2529
2685
|
}
|
|
2530
2686
|
try {
|
|
2531
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
2687
|
+
if (!pluginRestored && pluginBackupDir && fs6.existsSync(pluginBackupDir)) {
|
|
2532
2688
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
2533
2689
|
if (rollbackRestoreError) {
|
|
2534
2690
|
notes.push(
|
|
@@ -2555,7 +2711,7 @@ function rollbackOpenclawUpgrade({
|
|
|
2555
2711
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
2556
2712
|
}
|
|
2557
2713
|
try {
|
|
2558
|
-
if (configBackupPath &&
|
|
2714
|
+
if (configBackupPath && fs6.existsSync(configBackupPath)) {
|
|
2559
2715
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
2560
2716
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
2561
2717
|
}
|
|
@@ -2595,7 +2751,7 @@ Run this manually when you're ready:
|
|
|
2595
2751
|
}
|
|
2596
2752
|
|
|
2597
2753
|
// src/daemon-service.ts
|
|
2598
|
-
import
|
|
2754
|
+
import fs7 from "fs";
|
|
2599
2755
|
import path9 from "path";
|
|
2600
2756
|
import * as childProcess from "child_process";
|
|
2601
2757
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -2607,7 +2763,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
2607
2763
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
2608
2764
|
}
|
|
2609
2765
|
function resolveServerBinDetails(options = {}) {
|
|
2610
|
-
const
|
|
2766
|
+
const existsSync4 = options.existsSync ?? fs7.existsSync;
|
|
2611
2767
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
2612
2768
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
2613
2769
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -2646,12 +2802,12 @@ function resolveServerBinDetails(options = {}) {
|
|
|
2646
2802
|
path: path9.resolve(moduleDir, "../../remnic-server/src/index.ts"),
|
|
2647
2803
|
source: "workspace-source"
|
|
2648
2804
|
});
|
|
2649
|
-
const selected = candidates.find((candidate) => isCandidateReady(candidate,
|
|
2805
|
+
const selected = candidates.find((candidate) => isCandidateReady(candidate, existsSync4)) ?? candidates.find((candidate) => existsSync4(candidate.path)) ?? candidates[0] ?? {
|
|
2650
2806
|
path: path9.resolve(moduleDir, "../../remnic-server/dist/index.js"),
|
|
2651
2807
|
source: "workspace-dist"
|
|
2652
2808
|
};
|
|
2653
|
-
const exists =
|
|
2654
|
-
const requiredExists = selected.requiredPath ?
|
|
2809
|
+
const exists = existsSync4(selected.path);
|
|
2810
|
+
const requiredExists = selected.requiredPath ? existsSync4(selected.requiredPath) : true;
|
|
2655
2811
|
const { requiredPath: _requiredPath, ...publicSelected } = selected;
|
|
2656
2812
|
return {
|
|
2657
2813
|
...publicSelected,
|
|
@@ -2659,22 +2815,22 @@ function resolveServerBinDetails(options = {}) {
|
|
|
2659
2815
|
loadableByNode: exists && requiredExists && !selected.path.endsWith(".ts")
|
|
2660
2816
|
};
|
|
2661
2817
|
}
|
|
2662
|
-
function isCandidateReady(candidate,
|
|
2663
|
-
return
|
|
2818
|
+
function isCandidateReady(candidate, existsSync4) {
|
|
2819
|
+
return existsSync4(candidate.path) && (candidate.requiredPath ? existsSync4(candidate.requiredPath) : true);
|
|
2664
2820
|
}
|
|
2665
2821
|
function resolveServerBin(options = {}) {
|
|
2666
2822
|
return resolveServerBinDetails(options).path;
|
|
2667
2823
|
}
|
|
2668
2824
|
function readVerifiedDaemonPid(options) {
|
|
2669
|
-
const
|
|
2670
|
-
const unlinkSync = options.unlinkSync ??
|
|
2825
|
+
const readFileSync4 = options.readFileSync ?? fs7.readFileSync;
|
|
2826
|
+
const unlinkSync = options.unlinkSync ?? fs7.unlinkSync;
|
|
2671
2827
|
const processKill = options.processKill ?? process.kill;
|
|
2672
2828
|
const platform = options.platform ?? process.platform;
|
|
2673
2829
|
const execFileSync3 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
2674
2830
|
for (const file of options.pidFiles) {
|
|
2675
2831
|
let pid;
|
|
2676
2832
|
try {
|
|
2677
|
-
pid = parseDaemonPid(
|
|
2833
|
+
pid = parseDaemonPid(readFileSync4(file, "utf8"));
|
|
2678
2834
|
} catch {
|
|
2679
2835
|
continue;
|
|
2680
2836
|
}
|
|
@@ -2767,9 +2923,9 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
2767
2923
|
}
|
|
2768
2924
|
}
|
|
2769
2925
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
2770
|
-
const
|
|
2771
|
-
const
|
|
2772
|
-
if (!
|
|
2926
|
+
const existsSync4 = options.existsSync ?? fs7.existsSync;
|
|
2927
|
+
const readFileSync4 = options.readFileSync ?? fs7.readFileSync;
|
|
2928
|
+
if (!existsSync4(plistPath)) {
|
|
2773
2929
|
return {
|
|
2774
2930
|
installed: false,
|
|
2775
2931
|
ok: true,
|
|
@@ -2779,7 +2935,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
2779
2935
|
}
|
|
2780
2936
|
let content;
|
|
2781
2937
|
try {
|
|
2782
|
-
content =
|
|
2938
|
+
content = readFileSync4(plistPath, "utf8");
|
|
2783
2939
|
} catch {
|
|
2784
2940
|
return {
|
|
2785
2941
|
installed: true,
|
|
@@ -2815,7 +2971,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
2815
2971
|
remediation: "Run `remnic daemon install` so launchd uses an absolute Remnic server path."
|
|
2816
2972
|
};
|
|
2817
2973
|
}
|
|
2818
|
-
if (!
|
|
2974
|
+
if (!existsSync4(expandedServerArg)) {
|
|
2819
2975
|
return {
|
|
2820
2976
|
installed: true,
|
|
2821
2977
|
ok: false,
|
|
@@ -3002,7 +3158,7 @@ function stripConfigArgv(args) {
|
|
|
3002
3158
|
}
|
|
3003
3159
|
|
|
3004
3160
|
// src/import-dispatch.ts
|
|
3005
|
-
import
|
|
3161
|
+
import fs8 from "fs";
|
|
3006
3162
|
import {
|
|
3007
3163
|
runImporter,
|
|
3008
3164
|
validateImportBatchSize,
|
|
@@ -3010,7 +3166,7 @@ import {
|
|
|
3010
3166
|
} from "@remnic/core";
|
|
3011
3167
|
|
|
3012
3168
|
// src/import-bundle-detect.ts
|
|
3013
|
-
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as
|
|
3169
|
+
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
|
|
3014
3170
|
import path10 from "path";
|
|
3015
3171
|
function detectBundleEntries(bundleDir, options = {}) {
|
|
3016
3172
|
const readdir3 = options.readdirImpl ?? defaultReaddir;
|
|
@@ -3132,7 +3288,7 @@ function defaultReaddir(dir) {
|
|
|
3132
3288
|
return readdirSync2(dir);
|
|
3133
3289
|
}
|
|
3134
3290
|
function defaultReadFile(p) {
|
|
3135
|
-
return
|
|
3291
|
+
return readFileSync3(p, "utf-8");
|
|
3136
3292
|
}
|
|
3137
3293
|
function defaultIsDirectory(p) {
|
|
3138
3294
|
try {
|
|
@@ -3516,7 +3672,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
3516
3672
|
let materializedTarget;
|
|
3517
3673
|
let materializePromise;
|
|
3518
3674
|
const io = {
|
|
3519
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
3675
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs8.promises.readFile(p, "utf-8")),
|
|
3520
3676
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
3521
3677
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
3522
3678
|
getWriteTarget: async () => {
|
|
@@ -3589,7 +3745,7 @@ function takeOptionalValue(args, flag) {
|
|
|
3589
3745
|
}
|
|
3590
3746
|
|
|
3591
3747
|
// src/import-lossless-claw-cmd.ts
|
|
3592
|
-
import
|
|
3748
|
+
import fs9 from "fs";
|
|
3593
3749
|
import path11 from "path";
|
|
3594
3750
|
import {
|
|
3595
3751
|
applyLcmSchema,
|
|
@@ -3701,15 +3857,15 @@ async function loadImportLosslessClawModule() {
|
|
|
3701
3857
|
|
|
3702
3858
|
// src/import-lossless-claw-cmd.ts
|
|
3703
3859
|
function assertDirectoryOrAbsent(p, label) {
|
|
3704
|
-
if (
|
|
3860
|
+
if (fs9.existsSync(p) && !fs9.statSync(p).isDirectory()) {
|
|
3705
3861
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
3706
3862
|
}
|
|
3707
3863
|
}
|
|
3708
3864
|
function assertFile(p, label) {
|
|
3709
|
-
if (!
|
|
3865
|
+
if (!fs9.existsSync(p)) {
|
|
3710
3866
|
throw new Error(`${label} does not exist: ${p}`);
|
|
3711
3867
|
}
|
|
3712
|
-
if (!
|
|
3868
|
+
if (!fs9.statSync(p).isFile()) {
|
|
3713
3869
|
throw new Error(`${label} is not a file: ${p}`);
|
|
3714
3870
|
}
|
|
3715
3871
|
}
|
|
@@ -3741,7 +3897,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
3741
3897
|
try {
|
|
3742
3898
|
if (parsed.dryRun) {
|
|
3743
3899
|
const lcmPath = path11.join(memoryDir, "state", "lcm.sqlite");
|
|
3744
|
-
if (
|
|
3900
|
+
if (fs9.existsSync(lcmPath)) {
|
|
3745
3901
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
3746
3902
|
} else {
|
|
3747
3903
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -4174,7 +4330,7 @@ async function resolveAllBenchmarks() {
|
|
|
4174
4330
|
if (packageBenchmarks) {
|
|
4175
4331
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
4176
4332
|
}
|
|
4177
|
-
if (!
|
|
4333
|
+
if (!fs10.existsSync(EVAL_RUNNER_PATH)) {
|
|
4178
4334
|
return [];
|
|
4179
4335
|
}
|
|
4180
4336
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -4222,7 +4378,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
4222
4378
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
4223
4379
|
);
|
|
4224
4380
|
}
|
|
4225
|
-
if (!
|
|
4381
|
+
if (!fs10.existsSync(EVAL_RUNNER_PATH)) {
|
|
4226
4382
|
console.error(
|
|
4227
4383
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
4228
4384
|
);
|
|
@@ -4232,7 +4388,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
4232
4388
|
path12.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
4233
4389
|
path12.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
4234
4390
|
];
|
|
4235
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
4391
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs10.existsSync(candidate)) ?? "tsx";
|
|
4236
4392
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
4237
4393
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
4238
4394
|
benchmarkId,
|
|
@@ -4377,9 +4533,9 @@ var PERSONAMEM_COMPLETION_MARKER = path12.join(
|
|
|
4377
4533
|
);
|
|
4378
4534
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
4379
4535
|
try {
|
|
4380
|
-
const datasetRoot =
|
|
4536
|
+
const datasetRoot = fs10.realpathSync(datasetPath);
|
|
4381
4537
|
const candidatePath = path12.resolve(datasetRoot, relativePath);
|
|
4382
|
-
const candidateRealPath =
|
|
4538
|
+
const candidateRealPath = fs10.realpathSync(candidatePath);
|
|
4383
4539
|
const relativeToRoot = path12.relative(datasetRoot, candidateRealPath);
|
|
4384
4540
|
if (relativeToRoot.startsWith("..") || path12.isAbsolute(relativeToRoot)) {
|
|
4385
4541
|
return null;
|
|
@@ -4438,14 +4594,14 @@ function parseCsvRows(raw) {
|
|
|
4438
4594
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
4439
4595
|
try {
|
|
4440
4596
|
const completionMarkerPath = path12.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
4441
|
-
if (
|
|
4597
|
+
if (fs10.statSync(completionMarkerPath).isFile()) {
|
|
4442
4598
|
return true;
|
|
4443
4599
|
}
|
|
4444
4600
|
} catch {
|
|
4445
4601
|
}
|
|
4446
4602
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
4447
4603
|
try {
|
|
4448
|
-
return
|
|
4604
|
+
return fs10.statSync(path12.join(datasetPath, candidate)).isFile();
|
|
4449
4605
|
} catch {
|
|
4450
4606
|
return false;
|
|
4451
4607
|
}
|
|
@@ -4454,7 +4610,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4454
4610
|
return false;
|
|
4455
4611
|
}
|
|
4456
4612
|
try {
|
|
4457
|
-
const rows = parseCsvRows(
|
|
4613
|
+
const rows = parseCsvRows(fs10.readFileSync(path12.join(datasetPath, datasetFile), "utf8"));
|
|
4458
4614
|
if (rows.length < 2) {
|
|
4459
4615
|
return false;
|
|
4460
4616
|
}
|
|
@@ -4469,7 +4625,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4469
4625
|
}
|
|
4470
4626
|
return historyPaths.every((relativePath) => {
|
|
4471
4627
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
4472
|
-
return resolvedPath !== null &&
|
|
4628
|
+
return resolvedPath !== null && fs10.statSync(resolvedPath).isFile();
|
|
4473
4629
|
});
|
|
4474
4630
|
} catch {
|
|
4475
4631
|
return false;
|
|
@@ -4477,7 +4633,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4477
4633
|
}
|
|
4478
4634
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
4479
4635
|
try {
|
|
4480
|
-
return
|
|
4636
|
+
return fs10.statSync(path12.join(datasetPath, relativePath)).isFile();
|
|
4481
4637
|
} catch {
|
|
4482
4638
|
return false;
|
|
4483
4639
|
}
|
|
@@ -4497,10 +4653,10 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
4497
4653
|
return candidateFilenames.some((filename) => {
|
|
4498
4654
|
const filePath = path12.join(datasetPath, filename);
|
|
4499
4655
|
try {
|
|
4500
|
-
if (!
|
|
4656
|
+
if (!fs10.statSync(filePath).isFile()) {
|
|
4501
4657
|
return false;
|
|
4502
4658
|
}
|
|
4503
|
-
const raw =
|
|
4659
|
+
const raw = fs10.readFileSync(filePath, "utf8");
|
|
4504
4660
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
4505
4661
|
} catch {
|
|
4506
4662
|
return false;
|
|
@@ -4516,7 +4672,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
4516
4672
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
4517
4673
|
let stats;
|
|
4518
4674
|
try {
|
|
4519
|
-
stats =
|
|
4675
|
+
stats = fs10.statSync(datasetPath);
|
|
4520
4676
|
} catch {
|
|
4521
4677
|
return false;
|
|
4522
4678
|
}
|
|
@@ -4526,7 +4682,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4526
4682
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
4527
4683
|
if (!marker) {
|
|
4528
4684
|
try {
|
|
4529
|
-
return
|
|
4685
|
+
return fs10.readdirSync(datasetPath).length > 0;
|
|
4530
4686
|
} catch {
|
|
4531
4687
|
return false;
|
|
4532
4688
|
}
|
|
@@ -4534,7 +4690,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4534
4690
|
if (marker.allOf) {
|
|
4535
4691
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
4536
4692
|
try {
|
|
4537
|
-
return
|
|
4693
|
+
return fs10.statSync(path12.join(datasetPath, name)).isFile();
|
|
4538
4694
|
} catch {
|
|
4539
4695
|
return false;
|
|
4540
4696
|
}
|
|
@@ -4546,7 +4702,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4546
4702
|
if (marker.anyOf) {
|
|
4547
4703
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
4548
4704
|
try {
|
|
4549
|
-
return
|
|
4705
|
+
return fs10.statSync(path12.join(datasetPath, name)).isFile();
|
|
4550
4706
|
} catch {
|
|
4551
4707
|
return false;
|
|
4552
4708
|
}
|
|
@@ -4564,7 +4720,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4564
4720
|
}
|
|
4565
4721
|
if (marker.ext) {
|
|
4566
4722
|
try {
|
|
4567
|
-
return
|
|
4723
|
+
return fs10.readdirSync(datasetPath).some(
|
|
4568
4724
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
4569
4725
|
);
|
|
4570
4726
|
} catch {
|
|
@@ -4576,7 +4732,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4576
4732
|
async function launchBenchUi(resultsDir) {
|
|
4577
4733
|
const benchUiDir = path12.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
4578
4734
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
4579
|
-
if (!
|
|
4735
|
+
if (!fs10.existsSync(path12.join(benchUiDir, "package.json"))) {
|
|
4580
4736
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
4581
4737
|
process.exit(1);
|
|
4582
4738
|
}
|
|
@@ -4614,13 +4770,13 @@ function listDownloadableBenchmarks() {
|
|
|
4614
4770
|
}
|
|
4615
4771
|
function resolveDatasetDownloadScriptPath() {
|
|
4616
4772
|
const bundled = path12.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
4617
|
-
if (
|
|
4773
|
+
if (fs10.existsSync(bundled)) {
|
|
4618
4774
|
return bundled;
|
|
4619
4775
|
}
|
|
4620
4776
|
return path12.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
4621
4777
|
}
|
|
4622
4778
|
function isRepoCheckout() {
|
|
4623
|
-
return
|
|
4779
|
+
return fs10.existsSync(path12.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs10.existsSync(path12.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
4624
4780
|
}
|
|
4625
4781
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
4626
4782
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -4994,8 +5150,8 @@ async function exportBenchPackageResult(parsed) {
|
|
|
4994
5150
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
4995
5151
|
});
|
|
4996
5152
|
if (parsed.output) {
|
|
4997
|
-
|
|
4998
|
-
|
|
5153
|
+
fs10.mkdirSync(path12.dirname(parsed.output), { recursive: true });
|
|
5154
|
+
fs10.writeFileSync(parsed.output, rendered);
|
|
4999
5155
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
5000
5156
|
return;
|
|
5001
5157
|
}
|
|
@@ -5040,7 +5196,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
5040
5196
|
process.exit(1);
|
|
5041
5197
|
}
|
|
5042
5198
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
5043
|
-
if (!
|
|
5199
|
+
if (!fs10.existsSync(scriptPath)) {
|
|
5044
5200
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
5045
5201
|
process.exit(1);
|
|
5046
5202
|
}
|
|
@@ -5240,7 +5396,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
5240
5396
|
);
|
|
5241
5397
|
process.exit(1);
|
|
5242
5398
|
}
|
|
5243
|
-
const sourceResultSha256 = createHash2("sha256").update(
|
|
5399
|
+
const sourceResultSha256 = createHash2("sha256").update(fs10.readFileSync(latest.path)).digest("hex");
|
|
5244
5400
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
5245
5401
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
5246
5402
|
console.error(
|
|
@@ -5648,7 +5804,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
5648
5804
|
}
|
|
5649
5805
|
let decoded;
|
|
5650
5806
|
try {
|
|
5651
|
-
decoded = JSON.parse(
|
|
5807
|
+
decoded = JSON.parse(fs10.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
5652
5808
|
} catch (error) {
|
|
5653
5809
|
throw new Error(
|
|
5654
5810
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -5744,7 +5900,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
5744
5900
|
const benchModule = await loadBenchModule();
|
|
5745
5901
|
return {
|
|
5746
5902
|
async promoteArtifactsToPublished(args) {
|
|
5747
|
-
const { mkdirSync, readFileSync:
|
|
5903
|
+
const { mkdirSync, readFileSync: readFileSync4, writeFileSync } = await import("fs");
|
|
5748
5904
|
const path13 = await import("path");
|
|
5749
5905
|
mkdirSync(args.publishedOutDir, { recursive: true });
|
|
5750
5906
|
if (args.artifactPaths.length === 0) {
|
|
@@ -5754,7 +5910,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
5754
5910
|
return;
|
|
5755
5911
|
}
|
|
5756
5912
|
for (const artifactPath of args.artifactPaths) {
|
|
5757
|
-
const raw =
|
|
5913
|
+
const raw = readFileSync4(artifactPath, "utf8");
|
|
5758
5914
|
const parsedUnknown = JSON.parse(raw);
|
|
5759
5915
|
const parsedObj = parsedUnknown !== null && typeof parsedUnknown === "object" && !Array.isArray(parsedUnknown) ? parsedUnknown : {};
|
|
5760
5916
|
const gitShaShort = (parsedObj.meta?.gitSha ?? "unknown").slice(0, 7);
|
|
@@ -6288,7 +6444,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
6288
6444
|
return void 0;
|
|
6289
6445
|
}
|
|
6290
6446
|
try {
|
|
6291
|
-
return
|
|
6447
|
+
return fs10.realpathSync(datasetDir);
|
|
6292
6448
|
} catch {
|
|
6293
6449
|
return datasetDir;
|
|
6294
6450
|
}
|
|
@@ -6351,13 +6507,13 @@ function resolveConfigPath(cliPath) {
|
|
|
6351
6507
|
path12.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
6352
6508
|
];
|
|
6353
6509
|
for (const candidate of candidates) {
|
|
6354
|
-
if (
|
|
6510
|
+
if (fs10.existsSync(candidate)) return candidate;
|
|
6355
6511
|
}
|
|
6356
6512
|
return path12.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
6357
6513
|
}
|
|
6358
6514
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
6359
6515
|
const configPath = resolveConfigPath(cliPath);
|
|
6360
|
-
if (
|
|
6516
|
+
if (fs10.existsSync(configPath)) {
|
|
6361
6517
|
return configPath;
|
|
6362
6518
|
}
|
|
6363
6519
|
if (cliPath) {
|
|
@@ -6367,7 +6523,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
6367
6523
|
}
|
|
6368
6524
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
6369
6525
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
6370
|
-
if (
|
|
6526
|
+
if (fs10.existsSync(configPath)) {
|
|
6371
6527
|
return configPath;
|
|
6372
6528
|
}
|
|
6373
6529
|
if (cliPath) {
|
|
@@ -6474,8 +6630,8 @@ function resolveMemoryDir() {
|
|
|
6474
6630
|
const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
6475
6631
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
6476
6632
|
const configPath = resolveConfigPath();
|
|
6477
|
-
const raw =
|
|
6478
|
-
const remnicCfg =
|
|
6633
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
6634
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
6479
6635
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
6480
6636
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
6481
6637
|
}
|
|
@@ -6483,18 +6639,18 @@ function resolveMemoryDir() {
|
|
|
6483
6639
|
const standalonePath = path12.join(home, ".remnic", "memory");
|
|
6484
6640
|
const legacyStandalonePath = path12.join(home, ".engram", "memory");
|
|
6485
6641
|
const openclawPath = path12.join(home, ".openclaw", "workspace", "memory", "local");
|
|
6486
|
-
if (
|
|
6487
|
-
if (
|
|
6642
|
+
if (fs10.existsSync(standalonePath)) return standalonePath;
|
|
6643
|
+
if (fs10.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
6488
6644
|
return openclawPath;
|
|
6489
6645
|
})();
|
|
6490
6646
|
const manifestPath = getManifestPath();
|
|
6491
|
-
if (
|
|
6647
|
+
if (fs10.existsSync(manifestPath)) {
|
|
6492
6648
|
try {
|
|
6493
6649
|
const active = getActiveSpace();
|
|
6494
6650
|
if (active?.memoryDir) {
|
|
6495
6651
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
6496
|
-
if (!
|
|
6497
|
-
|
|
6652
|
+
if (!fs10.existsSync(activeMemoryDir)) {
|
|
6653
|
+
fs10.mkdirSync(activeMemoryDir, { recursive: true });
|
|
6498
6654
|
}
|
|
6499
6655
|
return activeMemoryDir;
|
|
6500
6656
|
}
|
|
@@ -6540,13 +6696,13 @@ function resolveOpenclawConfigPath(cliPath) {
|
|
|
6540
6696
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
6541
6697
|
if (envPath) return path12.resolve(expandTilde(envPath));
|
|
6542
6698
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
6543
|
-
if (
|
|
6699
|
+
if (fs10.existsSync(candidate)) return candidate;
|
|
6544
6700
|
}
|
|
6545
6701
|
return path12.join(resolveHomeDir(), ".openclaw", "openclaw.json");
|
|
6546
6702
|
}
|
|
6547
6703
|
function readOpenclawConfig(configPath) {
|
|
6548
|
-
if (!
|
|
6549
|
-
const raw =
|
|
6704
|
+
if (!fs10.existsSync(configPath)) return {};
|
|
6705
|
+
const raw = fs10.readFileSync(configPath, "utf-8");
|
|
6550
6706
|
let parsed;
|
|
6551
6707
|
try {
|
|
6552
6708
|
parsed = JSON.parse(raw);
|
|
@@ -6645,14 +6801,14 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
6645
6801
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
6646
6802
|
}
|
|
6647
6803
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
6648
|
-
if (!
|
|
6649
|
-
|
|
6650
|
-
|
|
6804
|
+
if (!fs10.existsSync(sourcePath)) return false;
|
|
6805
|
+
fs10.mkdirSync(path12.dirname(backupPath), { recursive: true });
|
|
6806
|
+
fs10.cpSync(sourcePath, backupPath, { recursive: true });
|
|
6651
6807
|
return true;
|
|
6652
6808
|
}
|
|
6653
6809
|
function assertDirectoryPathOrMissing(targetPath, label) {
|
|
6654
|
-
if (!
|
|
6655
|
-
const stat =
|
|
6810
|
+
if (!fs10.existsSync(targetPath)) return;
|
|
6811
|
+
const stat = fs10.statSync(targetPath);
|
|
6656
6812
|
if (!stat.isDirectory()) {
|
|
6657
6813
|
throw new Error(`${label} must be a directory when it already exists: ${targetPath}`);
|
|
6658
6814
|
}
|
|
@@ -6677,7 +6833,7 @@ var PublishedOpenclawPluginInstallError = class extends Error {
|
|
|
6677
6833
|
}
|
|
6678
6834
|
};
|
|
6679
6835
|
function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
6680
|
-
const tempRoot =
|
|
6836
|
+
const tempRoot = fs10.mkdtempSync(path12.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
6681
6837
|
const stagedDir = `${pluginDir}.next-${process.pid}-${Date.now()}`;
|
|
6682
6838
|
const rollbackDir = `${pluginDir}.rollback-${process.pid}-${Date.now()}`;
|
|
6683
6839
|
let swapRollbackDir;
|
|
@@ -6693,16 +6849,16 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
6693
6849
|
throw new Error(`npm pack ${spec} did not return a tarball name`);
|
|
6694
6850
|
}
|
|
6695
6851
|
const unpackDir = path12.join(tempRoot, "unpacked");
|
|
6696
|
-
|
|
6852
|
+
fs10.mkdirSync(unpackDir, { recursive: true });
|
|
6697
6853
|
childProcess2.execFileSync("tar", ["-xzf", path12.join(tempRoot, tarballName), "-C", unpackDir], {
|
|
6698
6854
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6699
6855
|
});
|
|
6700
6856
|
const packagedDir = path12.join(unpackDir, "package");
|
|
6701
|
-
if (!
|
|
6857
|
+
if (!fs10.existsSync(packagedDir)) {
|
|
6702
6858
|
throw new Error(`npm pack ${spec} did not contain a package/ directory`);
|
|
6703
6859
|
}
|
|
6704
|
-
|
|
6705
|
-
|
|
6860
|
+
fs10.rmSync(stagedDir, { recursive: true, force: true });
|
|
6861
|
+
fs10.cpSync(packagedDir, stagedDir, { recursive: true });
|
|
6706
6862
|
childProcess2.execFileSync("npm", ["install", "--omit=dev"], {
|
|
6707
6863
|
cwd: stagedDir,
|
|
6708
6864
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -6718,7 +6874,7 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
6718
6874
|
})();
|
|
6719
6875
|
swapRollbackDir = swapResult.rollbackDir;
|
|
6720
6876
|
const installedPackageJsonPath = path12.join(pluginDir, "package.json");
|
|
6721
|
-
const installedPackage =
|
|
6877
|
+
const installedPackage = fs10.existsSync(installedPackageJsonPath) ? JSON.parse(fs10.readFileSync(installedPackageJsonPath, "utf8")) : {};
|
|
6722
6878
|
return {
|
|
6723
6879
|
rollbackDir: swapRollbackDir,
|
|
6724
6880
|
version: typeof installedPackage.version === "string" ? installedPackage.version : void 0
|
|
@@ -6733,8 +6889,8 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
6733
6889
|
}
|
|
6734
6890
|
);
|
|
6735
6891
|
} finally {
|
|
6736
|
-
|
|
6737
|
-
|
|
6892
|
+
fs10.rmSync(stagedDir, { recursive: true, force: true });
|
|
6893
|
+
fs10.rmSync(tempRoot, { recursive: true, force: true });
|
|
6738
6894
|
}
|
|
6739
6895
|
}
|
|
6740
6896
|
function restartOpenclawGateway() {
|
|
@@ -6753,7 +6909,7 @@ function restartOpenclawGateway() {
|
|
|
6753
6909
|
}
|
|
6754
6910
|
function cmdInit() {
|
|
6755
6911
|
const configPath = path12.join(process.cwd(), "remnic.config.json");
|
|
6756
|
-
if (
|
|
6912
|
+
if (fs10.existsSync(configPath)) {
|
|
6757
6913
|
console.log(`Config already exists: ${configPath}`);
|
|
6758
6914
|
return;
|
|
6759
6915
|
}
|
|
@@ -6769,7 +6925,7 @@ function cmdInit() {
|
|
|
6769
6925
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
6770
6926
|
}
|
|
6771
6927
|
};
|
|
6772
|
-
|
|
6928
|
+
fs10.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
6773
6929
|
console.log(`Created ${configPath}`);
|
|
6774
6930
|
console.log("\nSet these environment variables:");
|
|
6775
6931
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -6839,7 +6995,7 @@ async function cmdStatus(json) {
|
|
|
6839
6995
|
}
|
|
6840
6996
|
function oauthReadConfigRecord(configPath) {
|
|
6841
6997
|
try {
|
|
6842
|
-
const parsed = JSON.parse(
|
|
6998
|
+
const parsed = JSON.parse(fs10.readFileSync(configPath, "utf8"));
|
|
6843
6999
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
6844
7000
|
return parsed;
|
|
6845
7001
|
}
|
|
@@ -7253,14 +7409,14 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
7253
7409
|
console.error("Usage: remnic query <text>");
|
|
7254
7410
|
process.exit(1);
|
|
7255
7411
|
}
|
|
7256
|
-
|
|
7412
|
+
initLogger2();
|
|
7257
7413
|
const configPath = resolveConfigPath();
|
|
7258
|
-
const raw =
|
|
7259
|
-
const remnicCfg =
|
|
7260
|
-
const config =
|
|
7261
|
-
const orchestrator = new
|
|
7414
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
7415
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
7416
|
+
const config = parseConfig3(remnicCfg);
|
|
7417
|
+
const orchestrator = new Orchestrator2(config);
|
|
7262
7418
|
await orchestrator.initialize();
|
|
7263
|
-
const service = new
|
|
7419
|
+
const service = new EngramAccessService2(orchestrator);
|
|
7264
7420
|
const recallRequest = buildQueryRecallRequest(queryText);
|
|
7265
7421
|
try {
|
|
7266
7422
|
if (explain) {
|
|
@@ -7424,15 +7580,15 @@ async function runXrayCommand(rest, io) {
|
|
|
7424
7580
|
async function cmdXray(rest) {
|
|
7425
7581
|
const { rawQuery, options } = extractXrayRawArgs(rest);
|
|
7426
7582
|
parseXrayCliOptions(rawQuery, options);
|
|
7427
|
-
|
|
7583
|
+
initLogger2();
|
|
7428
7584
|
const configPath = resolveConfigPath();
|
|
7429
|
-
const raw =
|
|
7430
|
-
const remnicCfg =
|
|
7431
|
-
const config =
|
|
7432
|
-
const orchestrator = new
|
|
7585
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
7586
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
7587
|
+
const config = parseConfig3(remnicCfg);
|
|
7588
|
+
const orchestrator = new Orchestrator2(config);
|
|
7433
7589
|
await orchestrator.initialize();
|
|
7434
7590
|
await orchestrator.deferredReady;
|
|
7435
|
-
const service = new
|
|
7591
|
+
const service = new EngramAccessService2(orchestrator);
|
|
7436
7592
|
try {
|
|
7437
7593
|
await runXrayCommand(rest, {
|
|
7438
7594
|
recallXray: (request) => service.recallXray(request),
|
|
@@ -7447,11 +7603,11 @@ async function cmdXray(rest) {
|
|
|
7447
7603
|
}
|
|
7448
7604
|
}
|
|
7449
7605
|
async function cmdVersions(rest) {
|
|
7450
|
-
|
|
7606
|
+
initLogger2();
|
|
7451
7607
|
const configPath = resolveConfigPath();
|
|
7452
|
-
const raw =
|
|
7453
|
-
const remnicCfg =
|
|
7454
|
-
const config =
|
|
7608
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
7609
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
7610
|
+
const config = parseConfig3(remnicCfg);
|
|
7455
7611
|
if (!config.versioningEnabled) {
|
|
7456
7612
|
console.error("Page versioning is disabled (versioningEnabled = false).");
|
|
7457
7613
|
process.exit(1);
|
|
@@ -7563,11 +7719,11 @@ Options:
|
|
|
7563
7719
|
}
|
|
7564
7720
|
}
|
|
7565
7721
|
async function cmdEnrich(rest) {
|
|
7566
|
-
|
|
7722
|
+
initLogger2();
|
|
7567
7723
|
const configPath = resolveConfigPath();
|
|
7568
|
-
const raw =
|
|
7569
|
-
const remnicCfg =
|
|
7570
|
-
const config =
|
|
7724
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
7725
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
7726
|
+
const config = parseConfig3(remnicCfg);
|
|
7571
7727
|
const subcommand = rest[0];
|
|
7572
7728
|
if (subcommand === "audit") {
|
|
7573
7729
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
@@ -7595,7 +7751,7 @@ async function cmdEnrich(rest) {
|
|
|
7595
7751
|
pipelineConfig2.providers = [
|
|
7596
7752
|
{ id: "web-search", enabled: true, costTier: "cheap" }
|
|
7597
7753
|
];
|
|
7598
|
-
const orchestrator2 = new
|
|
7754
|
+
const orchestrator2 = new Orchestrator2(config);
|
|
7599
7755
|
await orchestrator2.initialize();
|
|
7600
7756
|
await orchestrator2.deferredReady;
|
|
7601
7757
|
const searchBackend2 = orchestrator2.qmd;
|
|
@@ -7631,7 +7787,7 @@ Registered providers:`);
|
|
|
7631
7787
|
console.error("Usage: remnic enrich <entity-name> | --all | --dry-run | audit | providers");
|
|
7632
7788
|
process.exit(1);
|
|
7633
7789
|
}
|
|
7634
|
-
const orchestrator = new
|
|
7790
|
+
const orchestrator = new Orchestrator2(config);
|
|
7635
7791
|
await orchestrator.initialize();
|
|
7636
7792
|
await orchestrator.deferredReady;
|
|
7637
7793
|
const storage = await orchestrator.getStorage(config.defaultNamespace);
|
|
@@ -7757,7 +7913,7 @@ Registered providers:`);
|
|
|
7757
7913
|
}
|
|
7758
7914
|
}
|
|
7759
7915
|
async function cmdProcedural(rest) {
|
|
7760
|
-
|
|
7916
|
+
initLogger2();
|
|
7761
7917
|
const subcommand = rest[0];
|
|
7762
7918
|
if (!subcommand || subcommand === "--help" || subcommand === "-h") {
|
|
7763
7919
|
console.log(`remnic procedural \u2014 Procedural memory operations (issue #567)
|
|
@@ -7810,9 +7966,9 @@ Shared with:
|
|
|
7810
7966
|
process.exit(1);
|
|
7811
7967
|
}
|
|
7812
7968
|
const configPath = resolveConfigPath();
|
|
7813
|
-
const raw =
|
|
7814
|
-
const remnicCfg =
|
|
7815
|
-
const config =
|
|
7969
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
7970
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
7971
|
+
const config = parseConfig3(remnicCfg);
|
|
7816
7972
|
const memoryDir = expandTilde(
|
|
7817
7973
|
typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
7818
7974
|
);
|
|
@@ -7825,11 +7981,11 @@ Shared with:
|
|
|
7825
7981
|
process.stdout.write(formatProcedureStatsText(report));
|
|
7826
7982
|
}
|
|
7827
7983
|
async function cmdExtensions(action, rest) {
|
|
7828
|
-
|
|
7984
|
+
initLogger2();
|
|
7829
7985
|
const configPath = resolveConfigPath();
|
|
7830
|
-
const raw =
|
|
7831
|
-
const remnicCfg =
|
|
7832
|
-
const config =
|
|
7986
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
7987
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
7988
|
+
const config = parseConfig3(remnicCfg);
|
|
7833
7989
|
const root = resolveExtensionsRoot(config);
|
|
7834
7990
|
const noopLog = { warn: () => {
|
|
7835
7991
|
}, debug: () => {
|
|
@@ -7878,7 +8034,7 @@ Root: ${root}`);
|
|
|
7878
8034
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
7879
8035
|
let entries = [];
|
|
7880
8036
|
try {
|
|
7881
|
-
entries =
|
|
8037
|
+
entries = fs10.readdirSync(root);
|
|
7882
8038
|
} catch {
|
|
7883
8039
|
console.log(`Extensions root does not exist: ${root}`);
|
|
7884
8040
|
process.exitCode = 0;
|
|
@@ -7889,7 +8045,7 @@ Root: ${root}`);
|
|
|
7889
8045
|
for (const entry of entries) {
|
|
7890
8046
|
const entryPath = path12.join(root, entry);
|
|
7891
8047
|
try {
|
|
7892
|
-
if (!
|
|
8048
|
+
if (!fs10.statSync(entryPath).isDirectory()) continue;
|
|
7893
8049
|
} catch {
|
|
7894
8050
|
continue;
|
|
7895
8051
|
}
|
|
@@ -7919,11 +8075,11 @@ Root: ${root}`);
|
|
|
7919
8075
|
}
|
|
7920
8076
|
}
|
|
7921
8077
|
async function cmdBriefing(rest) {
|
|
7922
|
-
|
|
8078
|
+
initLogger2();
|
|
7923
8079
|
const configPath = resolveConfigPath();
|
|
7924
|
-
const raw =
|
|
7925
|
-
const remnicCfg =
|
|
7926
|
-
const config =
|
|
8080
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
8081
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
8082
|
+
const config = parseConfig3(remnicCfg);
|
|
7927
8083
|
if (!config.briefing.enabled) {
|
|
7928
8084
|
console.error("Briefing is disabled in config (briefing.enabled = false).");
|
|
7929
8085
|
process.exit(1);
|
|
@@ -7976,7 +8132,7 @@ async function cmdBriefing(rest) {
|
|
|
7976
8132
|
process.exit(1);
|
|
7977
8133
|
}
|
|
7978
8134
|
const format = effectiveFormatFlag === "json" ? "json" : effectiveFormatFlag === "markdown" ? "markdown" : config.briefing.defaultFormat;
|
|
7979
|
-
const orchestrator = new
|
|
8135
|
+
const orchestrator = new Orchestrator2(config);
|
|
7980
8136
|
await orchestrator.initialize();
|
|
7981
8137
|
const storage = await orchestrator.getStorage(config.defaultNamespace);
|
|
7982
8138
|
const calendarSource = config.briefing.calendarSource ? new FileCalendarSource(config.briefing.calendarSource) : void 0;
|
|
@@ -8001,10 +8157,10 @@ async function cmdBriefing(rest) {
|
|
|
8001
8157
|
if (save) {
|
|
8002
8158
|
try {
|
|
8003
8159
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
8004
|
-
|
|
8160
|
+
fs10.mkdirSync(saveDir, { recursive: true });
|
|
8005
8161
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
8006
8162
|
const filePath = path12.join(saveDir, filename);
|
|
8007
|
-
|
|
8163
|
+
fs10.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
8008
8164
|
console.error(`Saved briefing: ${filePath}`);
|
|
8009
8165
|
} catch (err) {
|
|
8010
8166
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -8022,7 +8178,7 @@ async function cmdDoctor() {
|
|
|
8022
8178
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
8023
8179
|
});
|
|
8024
8180
|
const configPath = resolveConfigPath();
|
|
8025
|
-
const configExists =
|
|
8181
|
+
const configExists = fs10.existsSync(configPath);
|
|
8026
8182
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
8027
8183
|
let standaloneConfig;
|
|
8028
8184
|
let standaloneConfigError;
|
|
@@ -8030,11 +8186,11 @@ async function cmdDoctor() {
|
|
|
8030
8186
|
let configuredNs = { invalid: false };
|
|
8031
8187
|
if (configExists) {
|
|
8032
8188
|
try {
|
|
8033
|
-
const raw = JSON.parse(
|
|
8034
|
-
const remnicCfg =
|
|
8189
|
+
const raw = JSON.parse(fs10.readFileSync(configPath, "utf8"));
|
|
8190
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
8035
8191
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
8036
8192
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
8037
|
-
standaloneConfig =
|
|
8193
|
+
standaloneConfig = parseConfig3(remnicCfg);
|
|
8038
8194
|
} catch (err) {
|
|
8039
8195
|
standaloneConfigError = err instanceof Error ? err.message : String(err);
|
|
8040
8196
|
}
|
|
@@ -8043,16 +8199,16 @@ async function cmdDoctor() {
|
|
|
8043
8199
|
try {
|
|
8044
8200
|
memoryDir = resolveMemoryDir();
|
|
8045
8201
|
} catch {
|
|
8046
|
-
memoryDir =
|
|
8202
|
+
memoryDir = parseConfig3({}).memoryDir;
|
|
8047
8203
|
}
|
|
8048
8204
|
try {
|
|
8049
|
-
|
|
8205
|
+
fs10.mkdirSync(memoryDir, { recursive: true });
|
|
8050
8206
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
8051
8207
|
} catch {
|
|
8052
8208
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
8053
8209
|
}
|
|
8054
8210
|
try {
|
|
8055
|
-
const quarantined = await new
|
|
8211
|
+
const quarantined = await new WriteQuarantineStore2(memoryDir).count();
|
|
8056
8212
|
checks.push({
|
|
8057
8213
|
name: "Quarantined writes",
|
|
8058
8214
|
ok: quarantined === 0,
|
|
@@ -8075,7 +8231,7 @@ async function cmdDoctor() {
|
|
|
8075
8231
|
});
|
|
8076
8232
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
8077
8233
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
8078
|
-
const openclawConfigExists =
|
|
8234
|
+
const openclawConfigExists = fs10.existsSync(openclawConfigPath);
|
|
8079
8235
|
let openclawConfig = {};
|
|
8080
8236
|
let openclawConfigValid = false;
|
|
8081
8237
|
let openclawPluginModeConfigured = false;
|
|
@@ -8083,7 +8239,7 @@ async function cmdDoctor() {
|
|
|
8083
8239
|
let activeOpenclawEntryConfig = null;
|
|
8084
8240
|
if (openclawConfigExists) {
|
|
8085
8241
|
try {
|
|
8086
|
-
const parsed = JSON.parse(
|
|
8242
|
+
const parsed = JSON.parse(fs10.readFileSync(openclawConfigPath, "utf-8"));
|
|
8087
8243
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
8088
8244
|
openclawConfig = parsed;
|
|
8089
8245
|
openclawConfigValid = true;
|
|
@@ -8163,9 +8319,9 @@ async function cmdDoctor() {
|
|
|
8163
8319
|
let memDirOk = false;
|
|
8164
8320
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
8165
8321
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
8166
|
-
if (
|
|
8322
|
+
if (fs10.existsSync(resolvedMemDir)) {
|
|
8167
8323
|
try {
|
|
8168
|
-
const stat =
|
|
8324
|
+
const stat = fs10.statSync(resolvedMemDir);
|
|
8169
8325
|
if (stat.isDirectory()) {
|
|
8170
8326
|
memDirOk = true;
|
|
8171
8327
|
memDirDetail = resolvedMemDir;
|
|
@@ -8307,12 +8463,12 @@ async function cmdDoctor() {
|
|
|
8307
8463
|
}
|
|
8308
8464
|
function cmdConfig() {
|
|
8309
8465
|
const configPath = resolveConfigPath();
|
|
8310
|
-
if (!
|
|
8466
|
+
if (!fs10.existsSync(configPath)) {
|
|
8311
8467
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
8312
8468
|
return;
|
|
8313
8469
|
}
|
|
8314
8470
|
console.log(`Config: ${configPath}`);
|
|
8315
|
-
const rawConfig =
|
|
8471
|
+
const rawConfig = fs10.readFileSync(configPath, "utf8");
|
|
8316
8472
|
const redacted = rawConfig.replace(
|
|
8317
8473
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
8318
8474
|
"$1[REDACTED]$3"
|
|
@@ -8420,9 +8576,9 @@ async function cmdReview(action, rest) {
|
|
|
8420
8576
|
const configPath = resolveConfigPath();
|
|
8421
8577
|
let tombstonesConfig = null;
|
|
8422
8578
|
try {
|
|
8423
|
-
const rawCfg =
|
|
8424
|
-
const remnicCfg =
|
|
8425
|
-
const config =
|
|
8579
|
+
const rawCfg = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
8580
|
+
const remnicCfg = resolveRemnicConfigRecord3(rawCfg);
|
|
8581
|
+
const config = parseConfig3(remnicCfg);
|
|
8426
8582
|
tombstonesConfig = {
|
|
8427
8583
|
enabled: config.tombstonesEnabled,
|
|
8428
8584
|
semanticMatch: config.tombstonesSemanticMatch,
|
|
@@ -8872,8 +9028,8 @@ var APPEND_TOLERANT_RUNTIME_STATE_FILES = /* @__PURE__ */ new Set([
|
|
|
8872
9028
|
function isAppendTolerantOfflineRuntimeFile(relPath) {
|
|
8873
9029
|
if (!shouldPreferIncomingOfflineRuntimeFile(relPath)) return false;
|
|
8874
9030
|
const parts = relPath.split("/");
|
|
8875
|
-
const
|
|
8876
|
-
return APPEND_TOLERANT_RUNTIME_STATE_FILES.has(
|
|
9031
|
+
const basename2 = parts[parts.length - 1] ?? "";
|
|
9032
|
+
return APPEND_TOLERANT_RUNTIME_STATE_FILES.has(basename2);
|
|
8877
9033
|
}
|
|
8878
9034
|
function offlineFileContentChunkMatchesExpected(options) {
|
|
8879
9035
|
const { chunk, expected, offset } = options;
|
|
@@ -9173,7 +9329,7 @@ async function pushOfflineFileContent(args) {
|
|
|
9173
9329
|
}
|
|
9174
9330
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
9175
9331
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
9176
|
-
const stat =
|
|
9332
|
+
const stat = fs10.statSync(filePath);
|
|
9177
9333
|
if (stat.mtimeMs !== args.file.mtimeMs) {
|
|
9178
9334
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
9179
9335
|
}
|
|
@@ -9664,7 +9820,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
9664
9820
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
9665
9821
|
}
|
|
9666
9822
|
async function runOfflineSyncOnce(options) {
|
|
9667
|
-
|
|
9823
|
+
fs10.mkdirSync(options.memoryDir, { recursive: true });
|
|
9668
9824
|
let activeStatePath = options.statePath;
|
|
9669
9825
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
9670
9826
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -10290,7 +10446,7 @@ Environment fallbacks:
|
|
|
10290
10446
|
const configPath = resolveConfigPath();
|
|
10291
10447
|
let config;
|
|
10292
10448
|
try {
|
|
10293
|
-
const rawConfig =
|
|
10449
|
+
const rawConfig = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
10294
10450
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
10295
10451
|
} catch {
|
|
10296
10452
|
throw new Error(
|
|
@@ -10305,7 +10461,7 @@ Environment fallbacks:
|
|
|
10305
10461
|
const statePath = statePathExplicit ? path12.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
10306
10462
|
if (action === "prepare") {
|
|
10307
10463
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
10308
|
-
|
|
10464
|
+
fs10.mkdirSync(memoryDir, { recursive: true });
|
|
10309
10465
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
10310
10466
|
remoteUrl,
|
|
10311
10467
|
token,
|
|
@@ -10403,7 +10559,7 @@ Environment fallbacks:
|
|
|
10403
10559
|
return;
|
|
10404
10560
|
}
|
|
10405
10561
|
if (action === "status") {
|
|
10406
|
-
|
|
10562
|
+
fs10.mkdirSync(memoryDir, { recursive: true });
|
|
10407
10563
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
10408
10564
|
if (state && remoteUrl && statePath) {
|
|
10409
10565
|
assertOfflineStateMatches({
|
|
@@ -10541,7 +10697,7 @@ function cmdDedup(json) {
|
|
|
10541
10697
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
10542
10698
|
if (!configPath) return fallback;
|
|
10543
10699
|
try {
|
|
10544
|
-
const parsed = JSON.parse(
|
|
10700
|
+
const parsed = JSON.parse(fs10.readFileSync(configPath, "utf8"));
|
|
10545
10701
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
10546
10702
|
const { token: _token, ...config } = parsed;
|
|
10547
10703
|
return config;
|
|
@@ -10554,27 +10710,31 @@ function snapshotConnectorTokenEntry(connectorId) {
|
|
|
10554
10710
|
return entry ? { ...entry } : null;
|
|
10555
10711
|
}
|
|
10556
10712
|
async function cmdQuarantine(action, rest, json) {
|
|
10557
|
-
if (action !== "list") {
|
|
10558
|
-
process.stderr.write(`quarantine: unknown action "${action}". Use: list [--json].
|
|
10713
|
+
if (action !== "list" && action !== "replay") {
|
|
10714
|
+
process.stderr.write(`quarantine: unknown action "${action}". Use: list|replay [--namespace <ns>] [--principal <p>] [--json].
|
|
10559
10715
|
`);
|
|
10560
10716
|
process.exitCode = 2;
|
|
10561
10717
|
return;
|
|
10562
10718
|
}
|
|
10563
|
-
const
|
|
10564
|
-
if (
|
|
10565
|
-
|
|
10719
|
+
const format = json ? "json" : "text";
|
|
10720
|
+
if (action === "list") {
|
|
10721
|
+
const extra = rest.filter((a) => !a.startsWith("--"));
|
|
10722
|
+
if (extra.length > 0) {
|
|
10723
|
+
process.stderr.write(`quarantine list: unexpected argument(s): ${extra.join(", ")}. Use: list [--json].
|
|
10566
10724
|
`);
|
|
10567
|
-
|
|
10725
|
+
process.exitCode = 2;
|
|
10726
|
+
return;
|
|
10727
|
+
}
|
|
10728
|
+
try {
|
|
10729
|
+
const store = new WriteQuarantineStore2(resolveMemoryDir());
|
|
10730
|
+
console.log(renderQuarantineList(await store.list(), format));
|
|
10731
|
+
} catch {
|
|
10732
|
+
process.stderr.write("quarantine list: unable to inspect quarantine store\n");
|
|
10733
|
+
process.exitCode = 2;
|
|
10734
|
+
}
|
|
10568
10735
|
return;
|
|
10569
10736
|
}
|
|
10570
|
-
|
|
10571
|
-
try {
|
|
10572
|
-
const store = new WriteQuarantineStore(resolveMemoryDir());
|
|
10573
|
-
console.log(renderQuarantineList(await store.list(), format));
|
|
10574
|
-
} catch {
|
|
10575
|
-
process.stderr.write("quarantine list: unable to inspect quarantine store\n");
|
|
10576
|
-
process.exitCode = 2;
|
|
10577
|
-
}
|
|
10737
|
+
await runQuarantineReplay(rest, format, resolveConfigPath);
|
|
10578
10738
|
}
|
|
10579
10739
|
async function cmdConnectors(action, rest, json) {
|
|
10580
10740
|
const rawNonFlagArgs = rest.filter((a) => !a.startsWith("--"));
|
|
@@ -10715,7 +10875,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
10715
10875
|
const pub = factory();
|
|
10716
10876
|
const available = await pub.isHostAvailable();
|
|
10717
10877
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
10718
|
-
const extensionExists = available && extRoot ?
|
|
10878
|
+
const extensionExists = available && extRoot ? fs10.existsSync(extRoot) : false;
|
|
10719
10879
|
publisherChecks.push({
|
|
10720
10880
|
name: `Publisher: ${targetHostId}`,
|
|
10721
10881
|
ok: !available || extensionExists,
|
|
@@ -10789,7 +10949,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
10789
10949
|
let connectorsCfg;
|
|
10790
10950
|
const configPath = resolveConfigPath();
|
|
10791
10951
|
try {
|
|
10792
|
-
const raw =
|
|
10952
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
10793
10953
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
10794
10954
|
} catch {
|
|
10795
10955
|
process.stderr.write(
|
|
@@ -10863,12 +11023,12 @@ async function cmdConnectors(action, rest, json) {
|
|
|
10863
11023
|
process.exitCode = 2;
|
|
10864
11024
|
return;
|
|
10865
11025
|
}
|
|
10866
|
-
|
|
11026
|
+
initLogger2();
|
|
10867
11027
|
const configPath = resolveConfigPath();
|
|
10868
|
-
const raw =
|
|
10869
|
-
const remnicCfg =
|
|
10870
|
-
const config =
|
|
10871
|
-
const orchestrator = new
|
|
11028
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
11029
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
11030
|
+
const config = parseConfig3(remnicCfg);
|
|
11031
|
+
const orchestrator = new Orchestrator2(config);
|
|
10872
11032
|
try {
|
|
10873
11033
|
await orchestrator.initialize();
|
|
10874
11034
|
await orchestrator.deferredReady;
|
|
@@ -10990,9 +11150,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
10990
11150
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
10991
11151
|
process.exit(1);
|
|
10992
11152
|
}
|
|
10993
|
-
const rawConfig =
|
|
10994
|
-
const pluginConfig =
|
|
10995
|
-
const config =
|
|
11153
|
+
const rawConfig = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
11154
|
+
const pluginConfig = resolveRemnicConfigRecord3(rawConfig);
|
|
11155
|
+
const config = parseConfig3(pluginConfig);
|
|
10996
11156
|
if (subAction === "generate") {
|
|
10997
11157
|
let outputDir;
|
|
10998
11158
|
try {
|
|
@@ -11012,13 +11172,13 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
11012
11172
|
} else if (subAction === "validate") {
|
|
11013
11173
|
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path12.join(process.cwd(), "marketplace.json");
|
|
11014
11174
|
const resolved = path12.resolve(targetPath);
|
|
11015
|
-
if (!
|
|
11175
|
+
if (!fs10.existsSync(resolved)) {
|
|
11016
11176
|
console.error(`File not found: ${resolved}`);
|
|
11017
11177
|
process.exit(1);
|
|
11018
11178
|
}
|
|
11019
11179
|
let parsed;
|
|
11020
11180
|
try {
|
|
11021
|
-
parsed = JSON.parse(
|
|
11181
|
+
parsed = JSON.parse(fs10.readFileSync(resolved, "utf8"));
|
|
11022
11182
|
} catch {
|
|
11023
11183
|
console.error(`Invalid JSON in ${resolved}`);
|
|
11024
11184
|
process.exit(1);
|
|
@@ -11217,13 +11377,13 @@ async function cmdSpace(action, rest, json) {
|
|
|
11217
11377
|
}
|
|
11218
11378
|
}
|
|
11219
11379
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
11220
|
-
|
|
11380
|
+
initLogger2();
|
|
11221
11381
|
const configPath = resolveConfigPath();
|
|
11222
|
-
const raw =
|
|
11223
|
-
const remnicCfg =
|
|
11224
|
-
const config =
|
|
11225
|
-
const orchestrator = new
|
|
11226
|
-
const service = new
|
|
11382
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
11383
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
11384
|
+
const config = parseConfig3(remnicCfg);
|
|
11385
|
+
const orchestrator = new Orchestrator2(config);
|
|
11386
|
+
const service = new EngramAccessService2(orchestrator);
|
|
11227
11387
|
const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
|
|
11228
11388
|
const benchConfig = {
|
|
11229
11389
|
queries: rest.filter((a) => !a.startsWith("--")).length > 0 ? rest.filter((a) => !a.startsWith("--")) : void 0,
|
|
@@ -11612,7 +11772,7 @@ function readPid() {
|
|
|
11612
11772
|
function inferPort() {
|
|
11613
11773
|
try {
|
|
11614
11774
|
const configPath = resolveConfigPath();
|
|
11615
|
-
const raw = JSON.parse(
|
|
11775
|
+
const raw = JSON.parse(fs10.readFileSync(configPath, "utf8"));
|
|
11616
11776
|
return raw.server?.port ?? 4318;
|
|
11617
11777
|
} catch {
|
|
11618
11778
|
return 4318;
|
|
@@ -11707,13 +11867,13 @@ function daemonInstall() {
|
|
|
11707
11867
|
process.exit(1);
|
|
11708
11868
|
}
|
|
11709
11869
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
11710
|
-
|
|
11870
|
+
fs10.mkdirSync(LOGS_DIR, { recursive: true });
|
|
11711
11871
|
if (isMacOS()) {
|
|
11712
11872
|
const templatePath = path12.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
11713
|
-
const template =
|
|
11873
|
+
const template = fs10.readFileSync(templatePath, "utf8");
|
|
11714
11874
|
const plist = renderTemplate(template, vars);
|
|
11715
|
-
|
|
11716
|
-
|
|
11875
|
+
fs10.mkdirSync(path12.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
11876
|
+
fs10.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
11717
11877
|
try {
|
|
11718
11878
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
11719
11879
|
} catch (err) {
|
|
@@ -11730,10 +11890,10 @@ function daemonInstall() {
|
|
|
11730
11890
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
11731
11891
|
} else if (isLinux()) {
|
|
11732
11892
|
const templatePath = path12.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
11733
|
-
const template =
|
|
11893
|
+
const template = fs10.readFileSync(templatePath, "utf8");
|
|
11734
11894
|
const unit = renderTemplate(template, vars);
|
|
11735
|
-
|
|
11736
|
-
|
|
11895
|
+
fs10.mkdirSync(path12.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
11896
|
+
fs10.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
11737
11897
|
try {
|
|
11738
11898
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
11739
11899
|
} catch (err) {
|
|
@@ -11769,7 +11929,7 @@ function daemonUninstall() {
|
|
|
11769
11929
|
} catch {
|
|
11770
11930
|
}
|
|
11771
11931
|
try {
|
|
11772
|
-
|
|
11932
|
+
fs10.unlinkSync(plistPath);
|
|
11773
11933
|
removed = true;
|
|
11774
11934
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
11775
11935
|
} catch {
|
|
@@ -11789,7 +11949,7 @@ function daemonUninstall() {
|
|
|
11789
11949
|
let removed = false;
|
|
11790
11950
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
11791
11951
|
try {
|
|
11792
|
-
|
|
11952
|
+
fs10.unlinkSync(unitPath);
|
|
11793
11953
|
removed = true;
|
|
11794
11954
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
11795
11955
|
} catch {
|
|
@@ -11856,13 +12016,13 @@ async function daemonStatus() {
|
|
|
11856
12016
|
console.log(` Port: ${port}`);
|
|
11857
12017
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
11858
12018
|
console.log(` Platform: ${process.platform}`);
|
|
11859
|
-
console.log(` PID file: ${
|
|
11860
|
-
console.log(` Log file: ${
|
|
12019
|
+
console.log(` PID file: ${fs10.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
12020
|
+
console.log(` Log file: ${fs10.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
11861
12021
|
try {
|
|
11862
12022
|
const configPath = resolveConfigPath();
|
|
11863
|
-
const raw =
|
|
11864
|
-
const remnicCfg =
|
|
11865
|
-
const config =
|
|
12023
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
12024
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
12025
|
+
const config = parseConfig3(remnicCfg);
|
|
11866
12026
|
const extRoot = resolveExtensionsRoot(config);
|
|
11867
12027
|
const noopLog = { warn: () => {
|
|
11868
12028
|
}, debug: () => {
|
|
@@ -11901,9 +12061,9 @@ function daemonStart() {
|
|
|
11901
12061
|
return;
|
|
11902
12062
|
}
|
|
11903
12063
|
}
|
|
11904
|
-
|
|
11905
|
-
|
|
11906
|
-
const logStream =
|
|
12064
|
+
fs10.mkdirSync(PID_DIR, { recursive: true });
|
|
12065
|
+
fs10.mkdirSync(LOGS_DIR, { recursive: true });
|
|
12066
|
+
const logStream = fs10.openSync(LOG_FILE, "a");
|
|
11907
12067
|
const serverBin = resolveServerBin();
|
|
11908
12068
|
const isSource = serverBin.endsWith(".ts");
|
|
11909
12069
|
let cmd;
|
|
@@ -11925,7 +12085,7 @@ function daemonStart() {
|
|
|
11925
12085
|
}
|
|
11926
12086
|
});
|
|
11927
12087
|
child.unref();
|
|
11928
|
-
|
|
12088
|
+
fs10.writeFileSync(PID_FILE, String(child.pid));
|
|
11929
12089
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
11930
12090
|
console.log(` Log: ${LOG_FILE}`);
|
|
11931
12091
|
}
|
|
@@ -11959,11 +12119,11 @@ function daemonStop() {
|
|
|
11959
12119
|
console.log("Process not found (cleaning up PID file)");
|
|
11960
12120
|
}
|
|
11961
12121
|
try {
|
|
11962
|
-
|
|
12122
|
+
fs10.unlinkSync(PID_FILE);
|
|
11963
12123
|
} catch {
|
|
11964
12124
|
}
|
|
11965
12125
|
try {
|
|
11966
|
-
|
|
12126
|
+
fs10.unlinkSync(LEGACY_PID_FILE);
|
|
11967
12127
|
} catch {
|
|
11968
12128
|
}
|
|
11969
12129
|
}
|
|
@@ -12089,11 +12249,11 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
12089
12249
|
});
|
|
12090
12250
|
}
|
|
12091
12251
|
async function cmdBinary(rest) {
|
|
12092
|
-
|
|
12252
|
+
initLogger2();
|
|
12093
12253
|
const configPath = resolveConfigPath();
|
|
12094
|
-
const raw =
|
|
12095
|
-
const remnicCfg =
|
|
12096
|
-
const config =
|
|
12254
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
12255
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
12256
|
+
const config = parseConfig3(remnicCfg);
|
|
12097
12257
|
const memoryDir = resolveMemoryDir();
|
|
12098
12258
|
const blConfig = {
|
|
12099
12259
|
enabled: config.binaryLifecycleEnabled,
|
|
@@ -12282,7 +12442,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
12282
12442
|
} else if (slotIsActiveLegacy) {
|
|
12283
12443
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
12284
12444
|
}
|
|
12285
|
-
if (!
|
|
12445
|
+
if (!fs10.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
12286
12446
|
if (hasLegacy && migrateLegacy) {
|
|
12287
12447
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
12288
12448
|
}
|
|
@@ -12302,8 +12462,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
12302
12462
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
12303
12463
|
return;
|
|
12304
12464
|
}
|
|
12305
|
-
if (
|
|
12306
|
-
const st =
|
|
12465
|
+
if (fs10.existsSync(memoryDir)) {
|
|
12466
|
+
const st = fs10.statSync(memoryDir);
|
|
12307
12467
|
if (!st.isDirectory()) {
|
|
12308
12468
|
throw new Error(
|
|
12309
12469
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -12311,12 +12471,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
12311
12471
|
);
|
|
12312
12472
|
}
|
|
12313
12473
|
} else {
|
|
12314
|
-
|
|
12474
|
+
fs10.mkdirSync(memoryDir, { recursive: true });
|
|
12315
12475
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
12316
12476
|
}
|
|
12317
12477
|
const configDir = path12.dirname(configPath);
|
|
12318
|
-
if (!
|
|
12319
|
-
|
|
12478
|
+
if (!fs10.existsSync(configDir)) {
|
|
12479
|
+
fs10.mkdirSync(configDir, { recursive: true });
|
|
12320
12480
|
}
|
|
12321
12481
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
12322
12482
|
console.log("\nDone! Summary of changes:");
|
|
@@ -12488,15 +12648,15 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
12488
12648
|
}
|
|
12489
12649
|
function createOpenclawUpgradeBackupDir() {
|
|
12490
12650
|
const backupsRoot = path12.join(resolveHomeDir(), ".openclaw", "backups");
|
|
12491
|
-
|
|
12492
|
-
return
|
|
12651
|
+
fs10.mkdirSync(backupsRoot, { recursive: true });
|
|
12652
|
+
return fs10.mkdtempSync(path12.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
12493
12653
|
}
|
|
12494
12654
|
async function cmdTaxonomy(rest) {
|
|
12495
|
-
|
|
12655
|
+
initLogger2();
|
|
12496
12656
|
const configPath = resolveConfigPath();
|
|
12497
|
-
const raw =
|
|
12498
|
-
const remnicCfg =
|
|
12499
|
-
const config =
|
|
12657
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
12658
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
12659
|
+
const config = parseConfig3(remnicCfg);
|
|
12500
12660
|
if (!config.taxonomyEnabled) {
|
|
12501
12661
|
console.error(
|
|
12502
12662
|
"Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
|
|
@@ -12532,8 +12692,8 @@ async function cmdTaxonomy(rest) {
|
|
|
12532
12692
|
console.log(doc);
|
|
12533
12693
|
if (config.taxonomyAutoGenResolver) {
|
|
12534
12694
|
const resolverPath = path12.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
12535
|
-
|
|
12536
|
-
|
|
12695
|
+
fs10.mkdirSync(path12.dirname(resolverPath), { recursive: true });
|
|
12696
|
+
fs10.writeFileSync(resolverPath, doc);
|
|
12537
12697
|
console.error(`Written: ${resolverPath}`);
|
|
12538
12698
|
}
|
|
12539
12699
|
break;
|
|
@@ -12579,7 +12739,7 @@ async function cmdTaxonomy(rest) {
|
|
|
12579
12739
|
if (config.taxonomyAutoGenResolver) {
|
|
12580
12740
|
const doc = generateResolverDocument(taxonomy);
|
|
12581
12741
|
const resolverPath = path12.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
12582
|
-
|
|
12742
|
+
fs10.writeFileSync(resolverPath, doc);
|
|
12583
12743
|
console.error(`Regenerated: ${resolverPath}`);
|
|
12584
12744
|
}
|
|
12585
12745
|
break;
|
|
@@ -12610,7 +12770,7 @@ async function cmdTaxonomy(rest) {
|
|
|
12610
12770
|
if (config.taxonomyAutoGenResolver) {
|
|
12611
12771
|
const doc = generateResolverDocument(taxonomy);
|
|
12612
12772
|
const resolverPath = path12.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
12613
|
-
|
|
12773
|
+
fs10.writeFileSync(resolverPath, doc);
|
|
12614
12774
|
console.error(`Regenerated: ${resolverPath}`);
|
|
12615
12775
|
}
|
|
12616
12776
|
break;
|
|
@@ -12801,12 +12961,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
12801
12961
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
12802
12962
|
);
|
|
12803
12963
|
}
|
|
12804
|
-
if (!
|
|
12964
|
+
if (!fs10.existsSync(args.memoryDir)) {
|
|
12805
12965
|
throw new Error(
|
|
12806
12966
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
12807
12967
|
);
|
|
12808
12968
|
}
|
|
12809
|
-
if (!
|
|
12969
|
+
if (!fs10.statSync(args.memoryDir).isDirectory()) {
|
|
12810
12970
|
throw new Error(
|
|
12811
12971
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
12812
12972
|
);
|
|
@@ -12892,10 +13052,10 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
12892
13052
|
}
|
|
12893
13053
|
const formatted = adapter.formatRecords(records);
|
|
12894
13054
|
const outDir = path12.dirname(args.output);
|
|
12895
|
-
|
|
13055
|
+
fs10.mkdirSync(outDir, { recursive: true });
|
|
12896
13056
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
12897
|
-
|
|
12898
|
-
|
|
13057
|
+
fs10.writeFileSync(tmpPath, formatted, "utf-8");
|
|
13058
|
+
fs10.renameSync(tmpPath, args.output);
|
|
12899
13059
|
stdout.write(
|
|
12900
13060
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
12901
13061
|
`
|
|
@@ -13064,7 +13224,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13064
13224
|
}
|
|
13065
13225
|
}, 500);
|
|
13066
13226
|
};
|
|
13067
|
-
|
|
13227
|
+
fs10.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
13068
13228
|
if (filename && filename.startsWith(".")) return;
|
|
13069
13229
|
rebuild();
|
|
13070
13230
|
});
|
|
@@ -13072,12 +13232,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13072
13232
|
});
|
|
13073
13233
|
} else if (subAction === "validate") {
|
|
13074
13234
|
const treeDir = outputDir;
|
|
13075
|
-
if (!
|
|
13235
|
+
if (!fs10.existsSync(treeDir)) {
|
|
13076
13236
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
13077
13237
|
process.exit(1);
|
|
13078
13238
|
}
|
|
13079
13239
|
const indexPath = path12.join(treeDir, "INDEX.md");
|
|
13080
|
-
if (!
|
|
13240
|
+
if (!fs10.existsSync(indexPath)) {
|
|
13081
13241
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
13082
13242
|
process.exit(1);
|
|
13083
13243
|
}
|
|
@@ -13247,10 +13407,10 @@ Other:
|
|
|
13247
13407
|
let wearablesService;
|
|
13248
13408
|
try {
|
|
13249
13409
|
const configPath = resolveConfigPath();
|
|
13250
|
-
const raw =
|
|
13251
|
-
const remnicCfg =
|
|
13252
|
-
const config =
|
|
13253
|
-
wearablesOrchestrator = new
|
|
13410
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
13411
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
13412
|
+
const config = parseConfig3(remnicCfg);
|
|
13413
|
+
wearablesOrchestrator = new Orchestrator2(config);
|
|
13254
13414
|
await wearablesOrchestrator.initialize();
|
|
13255
13415
|
await wearablesOrchestrator.deferredReady;
|
|
13256
13416
|
wearablesService = wearablesOrchestrator.getWearablesService();
|
|
@@ -13291,10 +13451,10 @@ Other:
|
|
|
13291
13451
|
const targetFactory = async () => {
|
|
13292
13452
|
if (!orchestratorSingleton) {
|
|
13293
13453
|
const configPath = resolveConfigPath();
|
|
13294
|
-
const raw =
|
|
13295
|
-
const remnicCfg =
|
|
13296
|
-
const config =
|
|
13297
|
-
orchestratorSingleton = new
|
|
13454
|
+
const raw = fs10.existsSync(configPath) ? JSON.parse(fs10.readFileSync(configPath, "utf8")) : {};
|
|
13455
|
+
const remnicCfg = resolveRemnicConfigRecord3(raw);
|
|
13456
|
+
const config = parseConfig3(remnicCfg);
|
|
13457
|
+
orchestratorSingleton = new Orchestrator2(config);
|
|
13298
13458
|
await orchestratorSingleton.initialize();
|
|
13299
13459
|
await orchestratorSingleton.deferredReady;
|
|
13300
13460
|
}
|
|
@@ -13507,7 +13667,7 @@ Usage:
|
|
|
13507
13667
|
marketplace generate Generate marketplace.json for Codex
|
|
13508
13668
|
marketplace validate Validate a marketplace.json file
|
|
13509
13669
|
marketplace install Install from a marketplace source
|
|
13510
|
-
remnic quarantine list [--
|
|
13670
|
+
remnic quarantine <list|replay> [--namespace <ns>] [--principal <p>] [--json] Inspect/replay ACL-rejected writes
|
|
13511
13671
|
remnic extensions <list|show|validate|reload> Manage memory extensions
|
|
13512
13672
|
remnic space <list|switch|create|delete|push|pull|share|promote|audit> Manage spaces
|
|
13513
13673
|
create accepts --parent <id> to set parent-child relationship
|