@remnic/cli 9.40.0 → 9.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +691 -451
- package/package.json +29 -29
package/dist/index.js
CHANGED
|
@@ -18,15 +18,15 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
// src/index.ts
|
|
21
|
-
import
|
|
21
|
+
import fs12 from "fs";
|
|
22
22
|
import os from "os";
|
|
23
|
-
import
|
|
23
|
+
import path15 from "path";
|
|
24
24
|
import { createHash as createHash2 } from "crypto";
|
|
25
25
|
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 parseConfig5,
|
|
30
30
|
isOpenaiApiKeyDisabled,
|
|
31
31
|
resolveEnvVars,
|
|
32
32
|
resolveRemnicConfigRecord as resolveRemnicConfigRecord4,
|
|
@@ -118,7 +118,7 @@ import {
|
|
|
118
118
|
buildOfflineSyncChangesetFromSnapshot,
|
|
119
119
|
drainPendingLifecycleForOfflineSync,
|
|
120
120
|
compileOfflineSyncExcludeGlobs,
|
|
121
|
-
buildOfflineSyncSnapshotFromBase,
|
|
121
|
+
buildOfflineSyncSnapshotFromBase as buildOfflineSyncSnapshotFromBase2,
|
|
122
122
|
defaultOfflineSyncStatePath,
|
|
123
123
|
normalizeOfflineSyncSnapshot,
|
|
124
124
|
offlineSyncStateFromSnapshot,
|
|
@@ -238,6 +238,240 @@ async function loadWecloneExportModule() {
|
|
|
238
238
|
return cached;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
+
// src/converge.ts
|
|
242
|
+
import * as fs2 from "fs";
|
|
243
|
+
import * as path from "path";
|
|
244
|
+
import {
|
|
245
|
+
parseConfig as parseConfig2,
|
|
246
|
+
buildOfflineSyncSnapshotFromBase
|
|
247
|
+
} from "@remnic/core";
|
|
248
|
+
import { resolveCorpusNamespaceRoots } from "@remnic/core/corpus-watermark.js";
|
|
249
|
+
import { listNamespaces } from "@remnic/core/namespaces/migrate.js";
|
|
250
|
+
import {
|
|
251
|
+
planReconciliation
|
|
252
|
+
} from "@remnic/core/reconcile/plan.js";
|
|
253
|
+
import { resolveAgentAccessAuthToken } from "@remnic/core/resolve-auth-token.js";
|
|
254
|
+
async function readLocalTombstones(rootDir) {
|
|
255
|
+
const shaSet = /* @__PURE__ */ new Set();
|
|
256
|
+
const candidates = [
|
|
257
|
+
path.join(rootDir, "state", "tombstones.jsonl"),
|
|
258
|
+
path.join(rootDir, "tombstones.jsonl")
|
|
259
|
+
];
|
|
260
|
+
for (const tombPath of candidates) {
|
|
261
|
+
try {
|
|
262
|
+
const content = await fs2.promises.readFile(tombPath, "utf-8");
|
|
263
|
+
for (const line of content.split("\n")) {
|
|
264
|
+
const trimmed = line.trim();
|
|
265
|
+
if (!trimmed) continue;
|
|
266
|
+
try {
|
|
267
|
+
const record = JSON.parse(trimmed);
|
|
268
|
+
if (typeof record.contentHash === "string" && /^[0-9a-f]{64}$/i.test(record.contentHash)) {
|
|
269
|
+
shaSet.add(record.contentHash.toLowerCase());
|
|
270
|
+
}
|
|
271
|
+
if (typeof record.fileSha256 === "string" && /^[0-9a-f]{64}$/i.test(record.fileSha256)) {
|
|
272
|
+
shaSet.add(record.fileSha256.toLowerCase());
|
|
273
|
+
}
|
|
274
|
+
} catch {
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
} catch {
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return shaSet;
|
|
281
|
+
}
|
|
282
|
+
async function fetchPeerSnapshot(peerUrl, namespace, token, fetchImpl = globalThis.fetch) {
|
|
283
|
+
let base = peerUrl;
|
|
284
|
+
while (base.endsWith("/")) {
|
|
285
|
+
base = base.slice(0, -1);
|
|
286
|
+
}
|
|
287
|
+
const routes = [
|
|
288
|
+
`/remnic/v1/offline-sync/snapshot?namespace=${encodeURIComponent(namespace)}&content=false`,
|
|
289
|
+
`/engram/v1/offline-sync/snapshot?namespace=${encodeURIComponent(namespace)}&content=false`
|
|
290
|
+
];
|
|
291
|
+
const headers = token ? { authorization: `Bearer ${token}` } : {};
|
|
292
|
+
for (const route of routes) {
|
|
293
|
+
try {
|
|
294
|
+
const res = await fetchImpl(`${base}${route}`, { headers });
|
|
295
|
+
if (!res.ok) continue;
|
|
296
|
+
const data = await res.json();
|
|
297
|
+
const files = [];
|
|
298
|
+
if (Array.isArray(data.files)) {
|
|
299
|
+
for (const item of data.files) {
|
|
300
|
+
if (item && typeof item.path === "string" && typeof item.sha256 === "string") {
|
|
301
|
+
files.push({
|
|
302
|
+
path: item.path,
|
|
303
|
+
sha256: item.sha256,
|
|
304
|
+
mtimeMs: typeof item.mtimeMs === "number" ? item.mtimeMs : void 0,
|
|
305
|
+
bytes: typeof item.bytes === "number" ? item.bytes : void 0
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
const tombstones = /* @__PURE__ */ new Set();
|
|
311
|
+
if (Array.isArray(data.tombstones)) {
|
|
312
|
+
for (const tomb of data.tombstones) {
|
|
313
|
+
if (typeof tomb === "string" && /^[0-9a-f]{64}$/i.test(tomb)) {
|
|
314
|
+
tombstones.add(tomb.toLowerCase());
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return { files, tombstones };
|
|
319
|
+
} catch {
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return { files: [], tombstones: /* @__PURE__ */ new Set() };
|
|
323
|
+
}
|
|
324
|
+
async function computeConvergePlan(options = {}) {
|
|
325
|
+
const namespacesToPlan = /* @__PURE__ */ new Set();
|
|
326
|
+
const localMap = /* @__PURE__ */ new Map();
|
|
327
|
+
const localTombstones = /* @__PURE__ */ new Map();
|
|
328
|
+
const peerMap = /* @__PURE__ */ new Map();
|
|
329
|
+
const peerTombstones = /* @__PURE__ */ new Map();
|
|
330
|
+
if (options.localFilesByNamespace) {
|
|
331
|
+
for (const [ns, files] of options.localFilesByNamespace) {
|
|
332
|
+
namespacesToPlan.add(ns);
|
|
333
|
+
localMap.set(ns, files);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (options.localTombstonesByNamespace) {
|
|
337
|
+
for (const [ns, tombstones] of options.localTombstonesByNamespace) {
|
|
338
|
+
localTombstones.set(ns, new Set(tombstones));
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (options.peerFilesByNamespace) {
|
|
342
|
+
for (const [ns, files] of options.peerFilesByNamespace) {
|
|
343
|
+
namespacesToPlan.add(ns);
|
|
344
|
+
peerMap.set(ns, files);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (options.peerTombstonesByNamespace) {
|
|
348
|
+
for (const [ns, tombstones] of options.peerTombstonesByNamespace) {
|
|
349
|
+
peerTombstones.set(ns, new Set(tombstones));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
let config = options.config;
|
|
353
|
+
if (!config) {
|
|
354
|
+
try {
|
|
355
|
+
config = parseConfig2({});
|
|
356
|
+
} catch {
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
if (!options.localFilesByNamespace && config) {
|
|
360
|
+
const roots = await resolveCorpusNamespaceRoots({ config });
|
|
361
|
+
const discovered = await listNamespaces({ config });
|
|
362
|
+
for (const entry of discovered) {
|
|
363
|
+
namespacesToPlan.add(entry.namespace);
|
|
364
|
+
}
|
|
365
|
+
for (const rootInfo of roots) {
|
|
366
|
+
const ns = rootInfo.namespace;
|
|
367
|
+
namespacesToPlan.add(ns);
|
|
368
|
+
try {
|
|
369
|
+
const snapshot = await buildOfflineSyncSnapshotFromBase({
|
|
370
|
+
root: rootInfo.rootDir,
|
|
371
|
+
sourceId: "local",
|
|
372
|
+
includeContent: false
|
|
373
|
+
});
|
|
374
|
+
const files = snapshot.files.map((record) => ({
|
|
375
|
+
path: record.path,
|
|
376
|
+
sha256: record.sha256,
|
|
377
|
+
mtimeMs: record.mtimeMs,
|
|
378
|
+
bytes: record.bytes
|
|
379
|
+
}));
|
|
380
|
+
localMap.set(ns, files);
|
|
381
|
+
const tombstones = await readLocalTombstones(rootInfo.rootDir);
|
|
382
|
+
localTombstones.set(ns, tombstones);
|
|
383
|
+
} catch {
|
|
384
|
+
localMap.set(ns, []);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (!options.peerFilesByNamespace && options.peerUrl) {
|
|
389
|
+
let resolvedToken;
|
|
390
|
+
if (options.peerToken) {
|
|
391
|
+
try {
|
|
392
|
+
resolvedToken = await resolveAgentAccessAuthToken(options.peerToken, {
|
|
393
|
+
resolveSecretRef: options.resolveSecretRef
|
|
394
|
+
});
|
|
395
|
+
} catch {
|
|
396
|
+
resolvedToken = options.peerToken;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
const fetchFn = options.fetchImpl ?? globalThis.fetch;
|
|
400
|
+
for (const ns of namespacesToPlan) {
|
|
401
|
+
const peerData = await fetchPeerSnapshot(options.peerUrl, ns, resolvedToken, fetchFn);
|
|
402
|
+
peerMap.set(ns, peerData.files);
|
|
403
|
+
peerTombstones.set(ns, peerData.tombstones);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
const inputs = [];
|
|
407
|
+
for (const ns of [...namespacesToPlan].sort()) {
|
|
408
|
+
inputs.push({
|
|
409
|
+
namespace: ns,
|
|
410
|
+
local: localMap.get(ns) ?? [],
|
|
411
|
+
peer: peerMap.get(ns) ?? [],
|
|
412
|
+
tombstonedFileSha256: localTombstones.get(ns) ?? [],
|
|
413
|
+
peerTombstonedFileSha256: peerTombstones.get(ns) ?? []
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
return planReconciliation(inputs);
|
|
417
|
+
}
|
|
418
|
+
function formatConvergeReport(plan) {
|
|
419
|
+
const lines = [];
|
|
420
|
+
lines.push(`Convergence Status: ${plan.converged ? "CONVERGED" : "DIVERGED"}`);
|
|
421
|
+
lines.push("");
|
|
422
|
+
lines.push("Per-Namespace Summary:");
|
|
423
|
+
if (plan.byNamespace.length === 0) {
|
|
424
|
+
lines.push(" (no namespaces evaluated)");
|
|
425
|
+
} else {
|
|
426
|
+
for (const report of plan.byNamespace) {
|
|
427
|
+
lines.push(` [${report.namespace}]`);
|
|
428
|
+
lines.push(` identical: ${report.identical}`);
|
|
429
|
+
lines.push(` pull: ${report.pull}`);
|
|
430
|
+
lines.push(` push: ${report.push}`);
|
|
431
|
+
lines.push(` conflict: ${report.conflict}`);
|
|
432
|
+
lines.push(` suppress: ${report.suppress}`);
|
|
433
|
+
lines.push(` unresolved: ${report.unresolved}`);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return lines.join("\n");
|
|
437
|
+
}
|
|
438
|
+
async function cmdConverge(action, rest, json) {
|
|
439
|
+
if (action === "help" || action === "--help" || action === "-h" || rest.includes("--help") || rest.includes("-h")) {
|
|
440
|
+
console.log(`Usage: remnic converge plan [--peer <url>] [--token <token>] [--json]
|
|
441
|
+
|
|
442
|
+
Options:
|
|
443
|
+
--peer <url> Peer server URL (or --remote-url / --remote)
|
|
444
|
+
--token <token> Bearer token or SecretRef for peer authentication
|
|
445
|
+
--json Output detailed JSON plan report
|
|
446
|
+
`);
|
|
447
|
+
return;
|
|
448
|
+
}
|
|
449
|
+
if (action !== "plan") {
|
|
450
|
+
process.stderr.write(`converge: unknown action "${action}". Use: plan [options].
|
|
451
|
+
`);
|
|
452
|
+
process.exitCode = 2;
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
let peerUrl;
|
|
456
|
+
let peerToken;
|
|
457
|
+
for (let i = 0; i < rest.length; i += 1) {
|
|
458
|
+
const arg = rest[i];
|
|
459
|
+
if ((arg === "--peer" || arg === "--remote-url" || arg === "--remote") && rest[i + 1]) {
|
|
460
|
+
peerUrl = rest[i + 1];
|
|
461
|
+
i += 1;
|
|
462
|
+
} else if (arg === "--token" && rest[i + 1]) {
|
|
463
|
+
peerToken = rest[i + 1];
|
|
464
|
+
i += 1;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
const plan = await computeConvergePlan({ peerUrl, peerToken });
|
|
468
|
+
if (json) {
|
|
469
|
+
console.log(JSON.stringify(plan, null, 2));
|
|
470
|
+
} else {
|
|
471
|
+
console.log(formatConvergeReport(plan));
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
241
475
|
// src/doctor-namespace-lint.ts
|
|
242
476
|
import { isNamespacePolicyCovered } from "@remnic/core";
|
|
243
477
|
function readConfiguredNamespace(remnicCfg) {
|
|
@@ -371,8 +605,8 @@ function renderReplayResult(result, targetNamespace, format) {
|
|
|
371
605
|
}
|
|
372
606
|
|
|
373
607
|
// src/quarantine-replay.ts
|
|
374
|
-
import * as
|
|
375
|
-
import { EngramAccessService, Orchestrator as Orchestrator2, initLogger, parseConfig as
|
|
608
|
+
import * as fs3 from "fs";
|
|
609
|
+
import { EngramAccessService, Orchestrator as Orchestrator2, initLogger, parseConfig as parseConfig3, resolveRemnicConfigRecord as resolveRemnicConfigRecord2 } from "@remnic/core";
|
|
376
610
|
import { WriteQuarantineStore } from "@remnic/core/write-quarantine.js";
|
|
377
611
|
function valueFlag(args, flag) {
|
|
378
612
|
const occurrences = args.filter((a) => a === flag).length;
|
|
@@ -420,8 +654,8 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
420
654
|
let orchestrator;
|
|
421
655
|
try {
|
|
422
656
|
const configPath = resolveConfigPath2();
|
|
423
|
-
const raw =
|
|
424
|
-
const config =
|
|
657
|
+
const raw = fs3.existsSync(configPath) ? JSON.parse(fs3.readFileSync(configPath, "utf8")) : {};
|
|
658
|
+
const config = parseConfig3(resolveRemnicConfigRecord2(raw));
|
|
425
659
|
orchestrator = new Orchestrator2(config);
|
|
426
660
|
await orchestrator.initialize();
|
|
427
661
|
await orchestrator.deferredReady;
|
|
@@ -452,15 +686,15 @@ async function runQuarantineReplay(rest, format, resolveConfigPath2) {
|
|
|
452
686
|
}
|
|
453
687
|
|
|
454
688
|
// src/offline-impression-rotation.ts
|
|
455
|
-
import
|
|
456
|
-
import { parseConfig as
|
|
689
|
+
import fs4 from "fs";
|
|
690
|
+
import { parseConfig as parseConfig4, resolveRemnicConfigRecord as resolveRemnicConfigRecord3, drainPendingImpressionsForOfflineSync } from "@remnic/core";
|
|
457
691
|
import { LastRecallStore } from "@remnic/core/recall-state";
|
|
458
692
|
function parseConfigQuietly(raw) {
|
|
459
693
|
const originalWarn = console.warn;
|
|
460
694
|
console.warn = () => {
|
|
461
695
|
};
|
|
462
696
|
try {
|
|
463
|
-
return
|
|
697
|
+
return parseConfig4(resolveRemnicConfigRecord3(raw));
|
|
464
698
|
} finally {
|
|
465
699
|
console.warn = originalWarn;
|
|
466
700
|
}
|
|
@@ -487,7 +721,7 @@ function pickOfflineConfigRecord(raw) {
|
|
|
487
721
|
function resolveOfflineImpressionRotation(configPath) {
|
|
488
722
|
let raw;
|
|
489
723
|
try {
|
|
490
|
-
raw =
|
|
724
|
+
raw = fs4.existsSync(configPath) ? JSON.parse(fs4.readFileSync(configPath, "utf8")) : {};
|
|
491
725
|
} catch {
|
|
492
726
|
throw new Error(
|
|
493
727
|
`cannot read recall-impression rotation from ${configPath}: config file could not be read as JSON`
|
|
@@ -517,8 +751,8 @@ async function drainOfflineSyncImpressions(memoryDir, rotation) {
|
|
|
517
751
|
|
|
518
752
|
// src/offline-storage-io.ts
|
|
519
753
|
import { mkdtemp, readdir, lstat, rm } from "fs/promises";
|
|
520
|
-
import
|
|
521
|
-
import
|
|
754
|
+
import fs5 from "fs";
|
|
755
|
+
import path2 from "path";
|
|
522
756
|
import { createHash, createDecipheriv } from "crypto";
|
|
523
757
|
import {
|
|
524
758
|
OFFLINE_SYNC_FILE_CONTENT_TRANSFER_CHUNK_BYTES,
|
|
@@ -560,13 +794,13 @@ async function createConfiguredOfflineStorage(memoryDir, secureStoreEncryptOnWri
|
|
|
560
794
|
return { storage, secureStoreKey, secureStoreRequired };
|
|
561
795
|
}
|
|
562
796
|
async function createOfflineStorageForPath(memoryDir, filePath, configured, secureStoreEncryptOnWrite) {
|
|
563
|
-
const memoryRoot =
|
|
564
|
-
const stateDir =
|
|
565
|
-
if (
|
|
797
|
+
const memoryRoot = path2.resolve(memoryDir);
|
|
798
|
+
const stateDir = path2.dirname(filePath);
|
|
799
|
+
if (path2.basename(stateDir) !== "state" || path2.basename(filePath) !== "memory-lifecycle-ledger.jsonl") {
|
|
566
800
|
throw new Error(`invalid lifecycle ledger path: ${filePath}`);
|
|
567
801
|
}
|
|
568
|
-
const storageRoot =
|
|
569
|
-
if (storageRoot !== memoryRoot && !storageRoot.startsWith(`${memoryRoot}${
|
|
802
|
+
const storageRoot = path2.resolve(path2.dirname(stateDir));
|
|
803
|
+
if (storageRoot !== memoryRoot && !storageRoot.startsWith(`${memoryRoot}${path2.sep}`)) {
|
|
570
804
|
throw new Error(`lifecycle ledger path is outside the offline memory directory: ${filePath}`);
|
|
571
805
|
}
|
|
572
806
|
const storage = new StorageManager(storageRoot);
|
|
@@ -624,7 +858,7 @@ async function cleanupOrphanedOfflineDecryptStaging(memoryDir) {
|
|
|
624
858
|
const now = Date.now();
|
|
625
859
|
for (const name of entries) {
|
|
626
860
|
if (!name.startsWith(OFFLINE_DECRYPT_STAGING_DIR_PREFIX)) continue;
|
|
627
|
-
const dir =
|
|
861
|
+
const dir = path2.join(memoryDir, name);
|
|
628
862
|
try {
|
|
629
863
|
const info = await lstat(dir);
|
|
630
864
|
if (!info.isDirectory() || info.isSymbolicLink()) continue;
|
|
@@ -653,7 +887,7 @@ async function* readOfflineSyncFileChunks(options) {
|
|
|
653
887
|
});
|
|
654
888
|
}
|
|
655
889
|
async function readFilePrefix(filePath, length) {
|
|
656
|
-
const handle = await
|
|
890
|
+
const handle = await fs5.promises.open(filePath, "r");
|
|
657
891
|
try {
|
|
658
892
|
const out = Buffer.alloc(length);
|
|
659
893
|
const { bytesRead } = await handle.read(out, 0, length, 0);
|
|
@@ -663,7 +897,7 @@ async function readFilePrefix(filePath, length) {
|
|
|
663
897
|
}
|
|
664
898
|
}
|
|
665
899
|
async function* readPlainOfflineFileChunks(filePath, chunkSize) {
|
|
666
|
-
const stream =
|
|
900
|
+
const stream = fs5.createReadStream(filePath, { highWaterMark: chunkSize });
|
|
667
901
|
for await (const chunk of stream) {
|
|
668
902
|
yield Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
669
903
|
}
|
|
@@ -698,17 +932,17 @@ async function* readEncryptedOfflineFileChunks(options) {
|
|
|
698
932
|
const aadCandidates = offlineFileAadCandidates(options.filePath, options.memoryDir);
|
|
699
933
|
let lastError;
|
|
700
934
|
for (const aad of aadCandidates) {
|
|
701
|
-
const tempDir = await mkdtemp(
|
|
702
|
-
const tempPath =
|
|
935
|
+
const tempDir = await mkdtemp(path2.join(options.memoryDir, OFFLINE_DECRYPT_STAGING_DIR_PREFIX));
|
|
936
|
+
const tempPath = path2.join(tempDir, "content");
|
|
703
937
|
try {
|
|
704
938
|
const decipher = createDecipheriv("aes-256-gcm", options.key, iv, {
|
|
705
939
|
authTagLength: AUTH_TAG_LENGTH
|
|
706
940
|
});
|
|
707
941
|
decipher.setAuthTag(authTag);
|
|
708
942
|
decipher.setAAD(Buffer.concat([secureStoreEnvelopeHeaderAad(salt), aad]));
|
|
709
|
-
const output =
|
|
943
|
+
const output = fs5.createWriteStream(tempPath, { mode: 384 });
|
|
710
944
|
try {
|
|
711
|
-
const stream =
|
|
945
|
+
const stream = fs5.createReadStream(options.filePath, {
|
|
712
946
|
start: MAGIC_HEADER_SIZE + ENVELOPE_HEADER_SIZE,
|
|
713
947
|
highWaterMark: options.chunkSize
|
|
714
948
|
});
|
|
@@ -745,17 +979,17 @@ async function* readEncryptedOfflineFileChunks(options) {
|
|
|
745
979
|
}
|
|
746
980
|
function offlineFileAadCandidates(filePath, memoryDir) {
|
|
747
981
|
const candidates = [filePathAad(filePath, memoryDir)];
|
|
748
|
-
const relative =
|
|
749
|
-
if (!relative || relative.startsWith("..") ||
|
|
750
|
-
const parts = relative.split(
|
|
982
|
+
const relative = path2.relative(memoryDir, filePath);
|
|
983
|
+
if (!relative || relative.startsWith("..") || path2.isAbsolute(relative)) return candidates;
|
|
984
|
+
const parts = relative.split(path2.sep);
|
|
751
985
|
if (parts[0] === "namespaces" && parts.length >= 3 && parts[1]) {
|
|
752
|
-
candidates.push(filePathAad(filePath,
|
|
986
|
+
candidates.push(filePathAad(filePath, path2.join(memoryDir, "namespaces", parts[1])));
|
|
753
987
|
}
|
|
754
|
-
const memoryParts =
|
|
988
|
+
const memoryParts = path2.resolve(memoryDir).split(path2.sep);
|
|
755
989
|
if (memoryParts.length >= 3 && memoryParts.at(-2) === "namespaces" && memoryParts.at(-1)) {
|
|
756
|
-
const topLevelRoot = memoryParts.slice(0, -2).join(
|
|
757
|
-
const topRelative =
|
|
758
|
-
if (topRelative && !topRelative.startsWith("..") && !
|
|
990
|
+
const topLevelRoot = memoryParts.slice(0, -2).join(path2.sep) || path2.sep;
|
|
991
|
+
const topRelative = path2.relative(topLevelRoot, filePath);
|
|
992
|
+
if (topRelative && !topRelative.startsWith("..") && !path2.isAbsolute(topRelative) && topRelative.split(path2.sep)[0] === "namespaces" && topRelative.split(path2.sep)[1] === memoryParts.at(-1)) {
|
|
759
993
|
candidates.push(filePathAad(filePath, topLevelRoot));
|
|
760
994
|
}
|
|
761
995
|
}
|
|
@@ -782,15 +1016,15 @@ import {
|
|
|
782
1016
|
readFileSync as readFileSync2,
|
|
783
1017
|
statSync
|
|
784
1018
|
} from "fs";
|
|
785
|
-
import
|
|
1019
|
+
import path3 from "path";
|
|
786
1020
|
import { fileURLToPath } from "url";
|
|
787
1021
|
var STALE_BUILD_TOLERANCE_MS = 1e3;
|
|
788
1022
|
function assertLocalBenchBuildFreshForDevelopment(currentModuleUrl) {
|
|
789
1023
|
if (isTruthyEnv(process.env.REMNIC_BENCH_ALLOW_STALE_DIST)) {
|
|
790
1024
|
return;
|
|
791
1025
|
}
|
|
792
|
-
const currentDir =
|
|
793
|
-
const benchPackageDir =
|
|
1026
|
+
const currentDir = path3.dirname(fileURLToPath(currentModuleUrl));
|
|
1027
|
+
const benchPackageDir = path3.resolve(currentDir, "../../bench");
|
|
794
1028
|
const freshness = checkBenchBuildFreshness(benchPackageDir);
|
|
795
1029
|
if (!freshness.stale) {
|
|
796
1030
|
return;
|
|
@@ -807,7 +1041,7 @@ function assertLocalBenchBuildFreshForDevelopment(currentModuleUrl) {
|
|
|
807
1041
|
);
|
|
808
1042
|
}
|
|
809
1043
|
function checkBenchBuildFreshness(benchPackageDir) {
|
|
810
|
-
const packageJsonPath =
|
|
1044
|
+
const packageJsonPath = path3.join(benchPackageDir, "package.json");
|
|
811
1045
|
if (!existsSync2(packageJsonPath)) {
|
|
812
1046
|
return { stale: false };
|
|
813
1047
|
}
|
|
@@ -820,17 +1054,17 @@ function checkBenchBuildFreshness(benchPackageDir) {
|
|
|
820
1054
|
if (packageName !== "@remnic/bench") {
|
|
821
1055
|
return { stale: false };
|
|
822
1056
|
}
|
|
823
|
-
const srcDir =
|
|
1057
|
+
const srcDir = path3.join(benchPackageDir, "src");
|
|
824
1058
|
if (!isDirectory(srcDir)) {
|
|
825
1059
|
return { stale: false };
|
|
826
1060
|
}
|
|
827
1061
|
const sourceRoots = [
|
|
828
1062
|
srcDir,
|
|
829
1063
|
packageJsonPath,
|
|
830
|
-
|
|
831
|
-
|
|
1064
|
+
path3.join(benchPackageDir, "tsup.config.ts"),
|
|
1065
|
+
path3.join(benchPackageDir, "tsconfig.json")
|
|
832
1066
|
];
|
|
833
|
-
const distPath =
|
|
1067
|
+
const distPath = path3.join(benchPackageDir, "dist", "index.js");
|
|
834
1068
|
if (!existsSync2(distPath)) {
|
|
835
1069
|
return {
|
|
836
1070
|
stale: true,
|
|
@@ -873,7 +1107,7 @@ function newestMtime(roots) {
|
|
|
873
1107
|
}
|
|
874
1108
|
if (stat.isDirectory()) {
|
|
875
1109
|
for (const child of readdirSync(entryPath)) {
|
|
876
|
-
visit(
|
|
1110
|
+
visit(path3.join(entryPath, child));
|
|
877
1111
|
}
|
|
878
1112
|
return;
|
|
879
1113
|
}
|
|
@@ -906,18 +1140,18 @@ function isTruthyEnv(value) {
|
|
|
906
1140
|
|
|
907
1141
|
// src/optional-bench.ts
|
|
908
1142
|
import { existsSync as existsSync3 } from "fs";
|
|
909
|
-
import
|
|
1143
|
+
import path4 from "path";
|
|
910
1144
|
import { fileURLToPath as fileURLToPath2, pathToFileURL } from "url";
|
|
911
1145
|
var SPECIFIER2 = "@remnic/bench";
|
|
912
1146
|
var TSX_ESM_API_SPECIFIER = "tsx/esm/api";
|
|
913
1147
|
var cached2;
|
|
914
1148
|
var cachedFromLocalWorkspaceBenchSource = false;
|
|
915
1149
|
function resolveLocalWorkspaceBenchPaths() {
|
|
916
|
-
const currentDir =
|
|
917
|
-
const benchPackageDir =
|
|
1150
|
+
const currentDir = path4.dirname(fileURLToPath2(import.meta.url));
|
|
1151
|
+
const benchPackageDir = path4.resolve(currentDir, "../../bench");
|
|
918
1152
|
return {
|
|
919
|
-
distEntry:
|
|
920
|
-
sourceEntry:
|
|
1153
|
+
distEntry: path4.join(benchPackageDir, "dist", "index.js"),
|
|
1154
|
+
sourceEntry: path4.join(benchPackageDir, "src", "index.ts")
|
|
921
1155
|
};
|
|
922
1156
|
}
|
|
923
1157
|
async function tryImportLocalWorkspaceBenchSource(err) {
|
|
@@ -1004,8 +1238,8 @@ function assertBenchModuleFreshForDevelopment() {
|
|
|
1004
1238
|
}
|
|
1005
1239
|
|
|
1006
1240
|
// src/daemon-service-candidates.ts
|
|
1007
|
-
import
|
|
1008
|
-
import
|
|
1241
|
+
import fs6 from "fs";
|
|
1242
|
+
import path5 from "path";
|
|
1009
1243
|
var LAUNCHD_LABEL = "ai.remnic.daemon";
|
|
1010
1244
|
var LEGACY_REMNIC_SERVER_LAUNCHD_LABEL = "ai.remnic.server";
|
|
1011
1245
|
var LEGACY_LAUNCHD_LABEL = "ai.engram.daemon";
|
|
@@ -1018,15 +1252,15 @@ var SYSTEMD_SERVICE = "remnic.service";
|
|
|
1018
1252
|
var LEGACY_SYSTEMD_SERVICE = "engram.service";
|
|
1019
1253
|
var SYSTEMD_SERVICE_CANDIDATES = [SYSTEMD_SERVICE, LEGACY_SYSTEMD_SERVICE];
|
|
1020
1254
|
function launchdPlistPaths(homeDir) {
|
|
1021
|
-
return LAUNCHD_LABEL_CANDIDATES.map((label) =>
|
|
1255
|
+
return LAUNCHD_LABEL_CANDIDATES.map((label) => path5.join(homeDir, "Library", "LaunchAgents", `${label}.plist`));
|
|
1022
1256
|
}
|
|
1023
1257
|
function systemdUnitPaths(homeDir) {
|
|
1024
|
-
return SYSTEMD_SERVICE_CANDIDATES.map((service) =>
|
|
1258
|
+
return SYSTEMD_SERVICE_CANDIDATES.map((service) => path5.join(homeDir, ".config", "systemd", "user", service));
|
|
1025
1259
|
}
|
|
1026
1260
|
function anyFileExists(paths) {
|
|
1027
1261
|
return paths.some((candidate) => {
|
|
1028
1262
|
try {
|
|
1029
|
-
return
|
|
1263
|
+
return fs6.statSync(candidate).isFile();
|
|
1030
1264
|
} catch {
|
|
1031
1265
|
return false;
|
|
1032
1266
|
}
|
|
@@ -1038,7 +1272,7 @@ function commandNames(command) {
|
|
|
1038
1272
|
}
|
|
1039
1273
|
function isRunnableNodeScript(filePath) {
|
|
1040
1274
|
try {
|
|
1041
|
-
const text =
|
|
1275
|
+
const text = fs6.readFileSync(filePath, "utf8").slice(0, 4096);
|
|
1042
1276
|
const firstLine = text.split(/\r?\n/, 1)[0] ?? "";
|
|
1043
1277
|
if (/^#!.*\bnode\b/.test(firstLine)) return true;
|
|
1044
1278
|
if (firstLine.startsWith("#!")) return false;
|
|
@@ -1051,20 +1285,20 @@ function isRunnableNodeScript(filePath) {
|
|
|
1051
1285
|
function resolveShimNodeScript(filePath) {
|
|
1052
1286
|
let text;
|
|
1053
1287
|
try {
|
|
1054
|
-
text =
|
|
1288
|
+
text = fs6.readFileSync(filePath, "utf8").slice(0, 16384);
|
|
1055
1289
|
} catch {
|
|
1056
1290
|
return void 0;
|
|
1057
1291
|
}
|
|
1058
|
-
const basedir =
|
|
1292
|
+
const basedir = path5.dirname(filePath);
|
|
1059
1293
|
const jsReferencePattern = /"([^"]+\.js)"|'([^']+\.js)'|([^\s"'`]+\.js)/g;
|
|
1060
1294
|
for (const match of text.matchAll(jsReferencePattern)) {
|
|
1061
1295
|
const raw = match[1] ?? match[2] ?? match[3];
|
|
1062
1296
|
if (!raw) continue;
|
|
1063
1297
|
const candidate = raw.replaceAll("${basedir}", basedir).replaceAll("$basedir", basedir).replaceAll("\\ ", " ");
|
|
1064
|
-
const resolved =
|
|
1298
|
+
const resolved = path5.isAbsolute(candidate) ? candidate : path5.resolve(basedir, candidate);
|
|
1065
1299
|
try {
|
|
1066
|
-
if (
|
|
1067
|
-
return
|
|
1300
|
+
if (fs6.statSync(resolved).isFile() && isRunnableNodeScript(resolved)) {
|
|
1301
|
+
return fs6.realpathSync(resolved);
|
|
1068
1302
|
}
|
|
1069
1303
|
} catch {
|
|
1070
1304
|
}
|
|
@@ -1072,19 +1306,19 @@ function resolveShimNodeScript(filePath) {
|
|
|
1072
1306
|
return void 0;
|
|
1073
1307
|
}
|
|
1074
1308
|
function resolveRunnableNodeScript(filePath) {
|
|
1075
|
-
const realPath =
|
|
1309
|
+
const realPath = fs6.realpathSync(filePath);
|
|
1076
1310
|
if (isRunnableNodeScript(realPath)) return realPath;
|
|
1077
1311
|
return resolveShimNodeScript(realPath);
|
|
1078
1312
|
}
|
|
1079
1313
|
function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
1080
|
-
for (const dir of pathEnv.split(
|
|
1314
|
+
for (const dir of pathEnv.split(path5.delimiter)) {
|
|
1081
1315
|
if (!dir) continue;
|
|
1082
1316
|
for (const name of commandNames(command)) {
|
|
1083
|
-
const candidate =
|
|
1317
|
+
const candidate = path5.join(dir, name);
|
|
1084
1318
|
try {
|
|
1085
|
-
const stat =
|
|
1319
|
+
const stat = fs6.statSync(candidate);
|
|
1086
1320
|
if (!stat.isFile()) continue;
|
|
1087
|
-
if (process.platform !== "win32")
|
|
1321
|
+
if (process.platform !== "win32") fs6.accessSync(candidate, fs6.constants.X_OK);
|
|
1088
1322
|
const runnable = resolveRunnableNodeScript(candidate);
|
|
1089
1323
|
if (runnable) return runnable;
|
|
1090
1324
|
} catch {
|
|
@@ -1094,11 +1328,11 @@ function findCommandOnPath(command, pathEnv = process.env.PATH ?? "") {
|
|
|
1094
1328
|
return void 0;
|
|
1095
1329
|
}
|
|
1096
1330
|
function serverBinWrapperRequiredPath(candidate) {
|
|
1097
|
-
const filename =
|
|
1331
|
+
const filename = path5.basename(candidate);
|
|
1098
1332
|
if (filename !== "remnic-server.js" && filename !== "engram-server.js") return void 0;
|
|
1099
|
-
const binDir =
|
|
1100
|
-
if (
|
|
1101
|
-
return
|
|
1333
|
+
const binDir = path5.dirname(candidate);
|
|
1334
|
+
if (path5.basename(binDir) !== "bin") return void 0;
|
|
1335
|
+
return path5.join(path5.dirname(binDir), "dist", "index.js");
|
|
1102
1336
|
}
|
|
1103
1337
|
|
|
1104
1338
|
// src/service-candidates.ts
|
|
@@ -1120,7 +1354,7 @@ function firstSuccessfulCandidate(candidates, attempt) {
|
|
|
1120
1354
|
}
|
|
1121
1355
|
|
|
1122
1356
|
// src/bench-args.ts
|
|
1123
|
-
import
|
|
1357
|
+
import path7 from "path";
|
|
1124
1358
|
|
|
1125
1359
|
// src/bench-flags.ts
|
|
1126
1360
|
function readBenchOptionValue(argv, flag) {
|
|
@@ -1498,7 +1732,7 @@ function expandTilde(p) {
|
|
|
1498
1732
|
}
|
|
1499
1733
|
|
|
1500
1734
|
// src/bench-args-research.ts
|
|
1501
|
-
import
|
|
1735
|
+
import path6 from "path";
|
|
1502
1736
|
function readPositiveInteger(args, flag) {
|
|
1503
1737
|
const raw = readBenchOptionValue(args, flag);
|
|
1504
1738
|
if (raw === void 0) return void 0;
|
|
@@ -1536,7 +1770,7 @@ function parseBenchResearchArgs(action, args) {
|
|
|
1536
1770
|
}
|
|
1537
1771
|
const outRaw = readBenchOptionValue(args, "--out");
|
|
1538
1772
|
if (outRaw !== void 0) {
|
|
1539
|
-
out =
|
|
1773
|
+
out = path6.resolve(expandTilde(outRaw));
|
|
1540
1774
|
}
|
|
1541
1775
|
}
|
|
1542
1776
|
const epochs = readPositiveInteger(args, "--epochs");
|
|
@@ -1550,7 +1784,7 @@ function parseBenchResearchArgs(action, args) {
|
|
|
1550
1784
|
}
|
|
1551
1785
|
return {
|
|
1552
1786
|
runRef,
|
|
1553
|
-
memoryDir: memoryDirRaw ?
|
|
1787
|
+
memoryDir: memoryDirRaw ? path6.resolve(expandTilde(memoryDirRaw)) : void 0,
|
|
1554
1788
|
users: readPositiveInteger(args, "--users"),
|
|
1555
1789
|
epochs,
|
|
1556
1790
|
seed,
|
|
@@ -1769,7 +2003,7 @@ function parseBenchArgs(argv) {
|
|
|
1769
2003
|
}
|
|
1770
2004
|
validateBenchFlags(action, args);
|
|
1771
2005
|
const driftGenPositionals = action === "drift-gen" && driftGenAction === "validate" ? collectBenchmarks(args.slice(1)) : [];
|
|
1772
|
-
const driftGenDir = driftGenPositionals[0] ?
|
|
2006
|
+
const driftGenDir = driftGenPositionals[0] ? path7.resolve(expandTilde(driftGenPositionals[0])) : void 0;
|
|
1773
2007
|
const benchmarkArgs = action === "baseline" || action === "datasets" || action === "providers" || action === "runs" || action === "drift-gen" && (args[0] === "validate" || args[0] === "generate") ? args.slice(1) : args;
|
|
1774
2008
|
const benchmarks = collectBenchmarks(benchmarkArgs);
|
|
1775
2009
|
const datasetDir = readBenchOptionValue(args, "--dataset-dir") ?? readBenchOptionValue(args, "--dataset");
|
|
@@ -2319,13 +2553,13 @@ function parseBenchArgs(argv) {
|
|
|
2319
2553
|
mcpUrl,
|
|
2320
2554
|
mcpToolMap,
|
|
2321
2555
|
mcpDemo,
|
|
2322
|
-
datasetDir: datasetDir ?
|
|
2323
|
-
resultsDir: resultsDir ?
|
|
2324
|
-
baselinesDir: baselinesDir ?
|
|
2556
|
+
datasetDir: datasetDir ? path7.resolve(expandTilde(datasetDir)) : void 0,
|
|
2557
|
+
resultsDir: resultsDir ? path7.resolve(expandTilde(resultsDir)) : void 0,
|
|
2558
|
+
baselinesDir: baselinesDir ? path7.resolve(expandTilde(baselinesDir)) : void 0,
|
|
2325
2559
|
runtimeProfile,
|
|
2326
2560
|
matrixProfiles,
|
|
2327
|
-
remnicConfigPath: remnicConfigRaw ?
|
|
2328
|
-
openclawConfigPath: openclawConfigRaw ?
|
|
2561
|
+
remnicConfigPath: remnicConfigRaw ? path7.resolve(expandTilde(remnicConfigRaw)) : void 0,
|
|
2562
|
+
openclawConfigPath: openclawConfigRaw ? path7.resolve(expandTilde(openclawConfigRaw)) : void 0,
|
|
2329
2563
|
modelSource,
|
|
2330
2564
|
gatewayAgentId,
|
|
2331
2565
|
fastGatewayAgentId,
|
|
@@ -2348,13 +2582,13 @@ function parseBenchArgs(argv) {
|
|
|
2348
2582
|
internalDisableThinking: args.includes("--internal-disable-thinking"),
|
|
2349
2583
|
internalCodexReasoningEffort,
|
|
2350
2584
|
threshold,
|
|
2351
|
-
custom: customRaw ?
|
|
2585
|
+
custom: customRaw ? path7.resolve(expandTilde(customRaw)) : void 0,
|
|
2352
2586
|
baselineAction,
|
|
2353
2587
|
datasetAction,
|
|
2354
2588
|
providerAction,
|
|
2355
2589
|
runAction,
|
|
2356
2590
|
format,
|
|
2357
|
-
output: output ?
|
|
2591
|
+
output: output ? path7.resolve(expandTilde(output)) : void 0,
|
|
2358
2592
|
target,
|
|
2359
2593
|
publishedName,
|
|
2360
2594
|
publishedSeed,
|
|
@@ -2364,24 +2598,24 @@ function parseBenchArgs(argv) {
|
|
|
2364
2598
|
publishedIngestConcurrency,
|
|
2365
2599
|
publishedTaskFilter,
|
|
2366
2600
|
memcorrectAdapter,
|
|
2367
|
-
publishedOut: publishedOutRaw ?
|
|
2601
|
+
publishedOut: publishedOutRaw ? path7.resolve(expandTilde(publishedOutRaw)) : void 0,
|
|
2368
2602
|
publishedDryRun: args.includes("--dry-run"),
|
|
2369
2603
|
requestTimeout,
|
|
2370
2604
|
localJudgeRequestTimeout,
|
|
2371
2605
|
frontierJudgeRequestTimeout,
|
|
2372
|
-
calibrationDir: calibrationDirRaw ?
|
|
2606
|
+
calibrationDir: calibrationDirRaw ? path7.resolve(expandTilde(calibrationDirRaw)) : void 0,
|
|
2373
2607
|
calibrationLocalConfigSha256,
|
|
2374
2608
|
calibrationFrontierConfigSha256,
|
|
2375
2609
|
sourceResultId,
|
|
2376
2610
|
expectedAnswerSetSha256,
|
|
2377
2611
|
expectedQuestionIdListSha256,
|
|
2378
|
-
taskIdsFile: taskIdsFileRaw ?
|
|
2612
|
+
taskIdsFile: taskIdsFileRaw ? path7.resolve(expandTilde(taskIdsFileRaw)) : void 0,
|
|
2379
2613
|
expectedTaskIdListSha256,
|
|
2380
2614
|
drainTimeout,
|
|
2381
2615
|
// Issue #1573 PR1: surface judge-cache flags into the runner options.
|
|
2382
2616
|
noJudgeCache: args.includes("--no-judge-cache"),
|
|
2383
|
-
judgeCacheDir: judgeCacheDirRaw ?
|
|
2384
|
-
localLabManifestPath: localLabManifestRaw ?
|
|
2617
|
+
judgeCacheDir: judgeCacheDirRaw ? path7.resolve(expandTilde(judgeCacheDirRaw)) : void 0,
|
|
2618
|
+
localLabManifestPath: localLabManifestRaw ? path7.resolve(expandTilde(localLabManifestRaw)) : void 0,
|
|
2385
2619
|
max429WaitMs,
|
|
2386
2620
|
disableThinking: args.includes("--disable-thinking"),
|
|
2387
2621
|
amaBenchJudgeProtocol,
|
|
@@ -2400,9 +2634,9 @@ function parseBenchArgs(argv) {
|
|
|
2400
2634
|
|
|
2401
2635
|
// src/bench-status.ts
|
|
2402
2636
|
import { mkdir, readFile, readdir as readdir2, rename, writeFile } from "fs/promises";
|
|
2403
|
-
import
|
|
2637
|
+
import path8 from "path";
|
|
2404
2638
|
function createBenchStatusPath(resultsDir, pid, startedAtMs = Date.now()) {
|
|
2405
|
-
return
|
|
2639
|
+
return path8.join(resultsDir, `bench-status-${startedAtMs}-${pid}.json`);
|
|
2406
2640
|
}
|
|
2407
2641
|
var BENCH_STATUS_FILENAME = /^bench-status-\d+-\d+\.json$/;
|
|
2408
2642
|
var VALID_BENCH_ENTRY_STATUSES = /* @__PURE__ */ new Set(["pending", "running", "complete", "failed"]);
|
|
@@ -2415,7 +2649,7 @@ async function findLatestBenchStatusFile(resultsDir) {
|
|
|
2415
2649
|
}
|
|
2416
2650
|
const candidates = entries.filter((name) => BENCH_STATUS_FILENAME.test(name)).sort().reverse();
|
|
2417
2651
|
for (const name of candidates) {
|
|
2418
|
-
const filePath =
|
|
2652
|
+
const filePath = path8.join(resultsDir, name);
|
|
2419
2653
|
const status = await readBenchStatus(filePath);
|
|
2420
2654
|
if (status) {
|
|
2421
2655
|
return filePath;
|
|
@@ -2424,7 +2658,7 @@ async function findLatestBenchStatusFile(resultsDir) {
|
|
|
2424
2658
|
return null;
|
|
2425
2659
|
}
|
|
2426
2660
|
async function atomicWriteJSON(filePath, data) {
|
|
2427
|
-
await mkdir(
|
|
2661
|
+
await mkdir(path8.dirname(filePath), { recursive: true });
|
|
2428
2662
|
const tmp = `${filePath}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;
|
|
2429
2663
|
await writeFile(tmp, JSON.stringify(data, null, 2) + "\n");
|
|
2430
2664
|
await rename(tmp, filePath);
|
|
@@ -2541,8 +2775,8 @@ function finalizeBenchStatus(filePath) {
|
|
|
2541
2775
|
}
|
|
2542
2776
|
|
|
2543
2777
|
// src/bench-fallback.ts
|
|
2544
|
-
import
|
|
2545
|
-
import
|
|
2778
|
+
import fs7 from "fs";
|
|
2779
|
+
import path9 from "path";
|
|
2546
2780
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
2547
2781
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
2548
2782
|
const args = ["--benchmark", benchmarkId];
|
|
@@ -2606,34 +2840,34 @@ function findUnsupportedFallbackBenchOptions(parsed) {
|
|
|
2606
2840
|
return unsupported;
|
|
2607
2841
|
}
|
|
2608
2842
|
function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs = Date.now()) {
|
|
2609
|
-
return
|
|
2843
|
+
return path9.join(
|
|
2610
2844
|
resultsDir,
|
|
2611
2845
|
FALLBACK_RESULTS_DIRNAME,
|
|
2612
2846
|
`${benchmarkId}-${startedAtMs}-${pid}`
|
|
2613
2847
|
);
|
|
2614
2848
|
}
|
|
2615
2849
|
function resolveFallbackBenchResultPath(outputDir) {
|
|
2616
|
-
const entries =
|
|
2850
|
+
const entries = fs7.readdirSync(outputDir, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
|
|
2617
2851
|
if (entries.length === 0) {
|
|
2618
2852
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
2619
2853
|
}
|
|
2620
|
-
return
|
|
2854
|
+
return path9.join(outputDir, entries[0]);
|
|
2621
2855
|
}
|
|
2622
2856
|
|
|
2623
2857
|
// src/openclaw-upgrade-swap.ts
|
|
2624
|
-
import
|
|
2625
|
-
import
|
|
2858
|
+
import fs8 from "fs";
|
|
2859
|
+
import path10 from "path";
|
|
2626
2860
|
function describeError(error) {
|
|
2627
2861
|
return error instanceof Error ? error.message : String(error);
|
|
2628
2862
|
}
|
|
2629
2863
|
function createSiblingTempFilePath(targetPath, label) {
|
|
2630
2864
|
const nonce = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
|
|
2631
|
-
return
|
|
2865
|
+
return path10.join(path10.dirname(targetPath), `.${path10.basename(targetPath)}.${label}.${nonce}.tmp`);
|
|
2632
2866
|
}
|
|
2633
2867
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
2634
2868
|
if (explicitMode !== void 0) return explicitMode;
|
|
2635
2869
|
try {
|
|
2636
|
-
return
|
|
2870
|
+
return fs8.statSync(targetPath).mode & 4095;
|
|
2637
2871
|
} catch (error) {
|
|
2638
2872
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
2639
2873
|
return 384;
|
|
@@ -2643,8 +2877,8 @@ function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
|
2643
2877
|
}
|
|
2644
2878
|
function resolveAtomicReplacementPath(targetPath) {
|
|
2645
2879
|
try {
|
|
2646
|
-
if (
|
|
2647
|
-
return
|
|
2880
|
+
if (fs8.lstatSync(targetPath).isSymbolicLink()) {
|
|
2881
|
+
return fs8.realpathSync(targetPath);
|
|
2648
2882
|
}
|
|
2649
2883
|
} catch (error) {
|
|
2650
2884
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -2656,12 +2890,12 @@ function resolveAtomicReplacementPath(targetPath) {
|
|
|
2656
2890
|
}
|
|
2657
2891
|
function createSiblingSwapPath(targetDir, label) {
|
|
2658
2892
|
const nonce = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
|
|
2659
|
-
return
|
|
2893
|
+
return path10.join(path10.dirname(targetDir), `.${path10.basename(targetDir)}.${label}.${nonce}`);
|
|
2660
2894
|
}
|
|
2661
2895
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
2662
2896
|
if (!displacedDir) return void 0;
|
|
2663
2897
|
try {
|
|
2664
|
-
|
|
2898
|
+
fs8.rmSync(displacedDir, { recursive: true, force: true });
|
|
2665
2899
|
return void 0;
|
|
2666
2900
|
} catch (error) {
|
|
2667
2901
|
return `Warning: ${context}, but failed to remove the displaced plugin copy at ${displacedDir}: ${describeError(error)}`;
|
|
@@ -2669,55 +2903,55 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
2669
2903
|
}
|
|
2670
2904
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
2671
2905
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
2672
|
-
|
|
2906
|
+
fs8.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
2673
2907
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
2674
2908
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
2675
2909
|
try {
|
|
2676
2910
|
if (options.hooks?.writeTempFileSync) {
|
|
2677
2911
|
options.hooks.writeTempFileSync(tempPath);
|
|
2678
2912
|
} else {
|
|
2679
|
-
|
|
2913
|
+
fs8.writeFileSync(tempPath, data, { mode });
|
|
2680
2914
|
}
|
|
2681
|
-
|
|
2682
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
2915
|
+
fs8.chmodSync(tempPath, mode);
|
|
2916
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs8.renameSync;
|
|
2683
2917
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
2684
2918
|
} catch (error) {
|
|
2685
|
-
|
|
2919
|
+
fs8.rmSync(tempPath, { force: true });
|
|
2686
2920
|
throw error;
|
|
2687
2921
|
}
|
|
2688
2922
|
}
|
|
2689
2923
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
2690
|
-
if (!
|
|
2924
|
+
if (!fs8.existsSync(sourcePath)) return;
|
|
2691
2925
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
2692
|
-
|
|
2926
|
+
fs8.mkdirSync(path10.dirname(resolvedTargetPath), { recursive: true });
|
|
2693
2927
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
2694
|
-
const mode =
|
|
2928
|
+
const mode = fs8.statSync(sourcePath).mode & 4095;
|
|
2695
2929
|
try {
|
|
2696
|
-
const copyTempFileSync = options.hooks?.copyTempFileSync ??
|
|
2930
|
+
const copyTempFileSync = options.hooks?.copyTempFileSync ?? fs8.copyFileSync;
|
|
2697
2931
|
copyTempFileSync(sourcePath, tempPath);
|
|
2698
|
-
|
|
2699
|
-
const renameTempFileSync = options.hooks?.renameTempFileSync ??
|
|
2932
|
+
fs8.chmodSync(tempPath, mode);
|
|
2933
|
+
const renameTempFileSync = options.hooks?.renameTempFileSync ?? fs8.renameSync;
|
|
2700
2934
|
renameTempFileSync(tempPath, resolvedTargetPath);
|
|
2701
2935
|
} catch (error) {
|
|
2702
|
-
|
|
2936
|
+
fs8.rmSync(tempPath, { force: true });
|
|
2703
2937
|
throw error;
|
|
2704
2938
|
}
|
|
2705
2939
|
}
|
|
2706
2940
|
function swapDirectoryWithRollback(stagedDir, targetDir, rollbackDir) {
|
|
2707
2941
|
let hasRollbackCopy = false;
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
if (
|
|
2711
|
-
|
|
2942
|
+
fs8.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
2943
|
+
fs8.rmSync(rollbackDir, { recursive: true, force: true });
|
|
2944
|
+
if (fs8.existsSync(targetDir)) {
|
|
2945
|
+
fs8.renameSync(targetDir, rollbackDir);
|
|
2712
2946
|
hasRollbackCopy = true;
|
|
2713
2947
|
}
|
|
2714
2948
|
try {
|
|
2715
|
-
|
|
2949
|
+
fs8.renameSync(stagedDir, targetDir);
|
|
2716
2950
|
} catch (swapError) {
|
|
2717
|
-
|
|
2718
|
-
if (hasRollbackCopy &&
|
|
2951
|
+
fs8.rmSync(targetDir, { recursive: true, force: true });
|
|
2952
|
+
if (hasRollbackCopy && fs8.existsSync(rollbackDir)) {
|
|
2719
2953
|
try {
|
|
2720
|
-
|
|
2954
|
+
fs8.renameSync(rollbackDir, targetDir);
|
|
2721
2955
|
hasRollbackCopy = false;
|
|
2722
2956
|
} catch (restoreError) {
|
|
2723
2957
|
throw new AggregateError(
|
|
@@ -2732,7 +2966,7 @@ function swapDirectoryWithRollback(stagedDir, targetDir, rollbackDir) {
|
|
|
2732
2966
|
}
|
|
2733
2967
|
function cleanupRollbackDirectory(rollbackDir) {
|
|
2734
2968
|
if (!rollbackDir) return;
|
|
2735
|
-
|
|
2969
|
+
fs8.rmSync(rollbackDir, { recursive: true, force: true });
|
|
2736
2970
|
}
|
|
2737
2971
|
function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
2738
2972
|
if (!rollbackDir) return void 0;
|
|
@@ -2744,20 +2978,20 @@ function cleanupRollbackDirectoryBestEffort(rollbackDir) {
|
|
|
2744
2978
|
}
|
|
2745
2979
|
}
|
|
2746
2980
|
function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
2747
|
-
if (!
|
|
2981
|
+
if (!fs8.existsSync(rollbackDir)) {
|
|
2748
2982
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
2749
2983
|
}
|
|
2750
|
-
|
|
2751
|
-
const displacedDir =
|
|
2984
|
+
fs8.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
2985
|
+
const displacedDir = fs8.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
2752
2986
|
if (displacedDir) {
|
|
2753
|
-
|
|
2987
|
+
fs8.renameSync(targetDir, displacedDir);
|
|
2754
2988
|
}
|
|
2755
2989
|
try {
|
|
2756
|
-
|
|
2990
|
+
fs8.renameSync(rollbackDir, targetDir);
|
|
2757
2991
|
} catch (restoreError) {
|
|
2758
|
-
if (displacedDir &&
|
|
2992
|
+
if (displacedDir && fs8.existsSync(displacedDir)) {
|
|
2759
2993
|
try {
|
|
2760
|
-
|
|
2994
|
+
fs8.renameSync(displacedDir, targetDir);
|
|
2761
2995
|
} catch (revertError) {
|
|
2762
2996
|
throw new AggregateError(
|
|
2763
2997
|
[restoreError, revertError],
|
|
@@ -2776,23 +3010,23 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
2776
3010
|
);
|
|
2777
3011
|
}
|
|
2778
3012
|
function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
2779
|
-
if (!
|
|
3013
|
+
if (!fs8.existsSync(backupDir)) {
|
|
2780
3014
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
2781
3015
|
}
|
|
2782
|
-
|
|
3016
|
+
fs8.mkdirSync(path10.dirname(targetDir), { recursive: true });
|
|
2783
3017
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
2784
|
-
const displacedDir =
|
|
2785
|
-
|
|
3018
|
+
const displacedDir = fs8.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
3019
|
+
fs8.cpSync(backupDir, stagedDir, { recursive: true });
|
|
2786
3020
|
if (displacedDir) {
|
|
2787
|
-
|
|
3021
|
+
fs8.renameSync(targetDir, displacedDir);
|
|
2788
3022
|
}
|
|
2789
3023
|
try {
|
|
2790
|
-
|
|
3024
|
+
fs8.renameSync(stagedDir, targetDir);
|
|
2791
3025
|
} catch (restoreError) {
|
|
2792
|
-
|
|
2793
|
-
if (displacedDir &&
|
|
3026
|
+
fs8.rmSync(targetDir, { recursive: true, force: true });
|
|
3027
|
+
if (displacedDir && fs8.existsSync(displacedDir)) {
|
|
2794
3028
|
try {
|
|
2795
|
-
|
|
3029
|
+
fs8.renameSync(displacedDir, targetDir);
|
|
2796
3030
|
} catch (revertError) {
|
|
2797
3031
|
throw new AggregateError(
|
|
2798
3032
|
[restoreError, revertError],
|
|
@@ -2800,7 +3034,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
2800
3034
|
);
|
|
2801
3035
|
}
|
|
2802
3036
|
}
|
|
2803
|
-
|
|
3037
|
+
fs8.rmSync(stagedDir, { recursive: true, force: true });
|
|
2804
3038
|
throw new Error(
|
|
2805
3039
|
`Failed to restore the plugin backup into ${targetDir}. The durable backup remains preserved at ${backupDir}.`,
|
|
2806
3040
|
{ cause: restoreError }
|
|
@@ -2826,7 +3060,7 @@ function rollbackOpenclawUpgrade({
|
|
|
2826
3060
|
let rollbackRestoreError;
|
|
2827
3061
|
let pluginRestored = false;
|
|
2828
3062
|
try {
|
|
2829
|
-
if (rollbackDir &&
|
|
3063
|
+
if (rollbackDir && fs8.existsSync(rollbackDir)) {
|
|
2830
3064
|
const cleanupWarning = restoreDirectoryFromRollback(pluginDir, rollbackDir);
|
|
2831
3065
|
notes.push(`Restored previous plugin from rollback copy at ${rollbackDir}`);
|
|
2832
3066
|
if (cleanupWarning) notes.push(cleanupWarning);
|
|
@@ -2836,7 +3070,7 @@ function rollbackOpenclawUpgrade({
|
|
|
2836
3070
|
rollbackRestoreError = error instanceof Error ? error.message : String(error);
|
|
2837
3071
|
}
|
|
2838
3072
|
try {
|
|
2839
|
-
if (!pluginRestored && pluginBackupDir &&
|
|
3073
|
+
if (!pluginRestored && pluginBackupDir && fs8.existsSync(pluginBackupDir)) {
|
|
2840
3074
|
const cleanupWarning = restoreDirectoryFromBackup(pluginDir, pluginBackupDir);
|
|
2841
3075
|
if (rollbackRestoreError) {
|
|
2842
3076
|
notes.push(
|
|
@@ -2863,7 +3097,7 @@ function rollbackOpenclawUpgrade({
|
|
|
2863
3097
|
notes.push("No previous plugin copy was available for automatic restore");
|
|
2864
3098
|
}
|
|
2865
3099
|
try {
|
|
2866
|
-
if (configBackupPath &&
|
|
3100
|
+
if (configBackupPath && fs8.existsSync(configBackupPath)) {
|
|
2867
3101
|
restoreFileFromBackup(configPath, configBackupPath);
|
|
2868
3102
|
notes.push(`Restored OpenClaw config from backup at ${configBackupPath}`);
|
|
2869
3103
|
}
|
|
@@ -2903,11 +3137,11 @@ Run this manually when you're ready:
|
|
|
2903
3137
|
}
|
|
2904
3138
|
|
|
2905
3139
|
// src/daemon-service.ts
|
|
2906
|
-
import
|
|
2907
|
-
import
|
|
3140
|
+
import fs9 from "fs";
|
|
3141
|
+
import path11 from "path";
|
|
2908
3142
|
import * as childProcess from "child_process";
|
|
2909
3143
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2910
|
-
var thisModuleDir =
|
|
3144
|
+
var thisModuleDir = path11.dirname(fileURLToPath3(import.meta.url));
|
|
2911
3145
|
function launchdLoadPlist(plistPath, processApi = childProcess) {
|
|
2912
3146
|
processApi.execFileSync("launchctl", ["load", "-w", plistPath], { stdio: "pipe" });
|
|
2913
3147
|
}
|
|
@@ -2915,7 +3149,7 @@ function launchdUnloadPlist(plistPath, processApi = childProcess) {
|
|
|
2915
3149
|
processApi.execFileSync("launchctl", ["unload", plistPath], { stdio: "pipe" });
|
|
2916
3150
|
}
|
|
2917
3151
|
function resolveServerBinDetails(options = {}) {
|
|
2918
|
-
const existsSync4 = options.existsSync ??
|
|
3152
|
+
const existsSync4 = options.existsSync ?? fs9.existsSync;
|
|
2919
3153
|
const findCommandOnPath2 = options.findCommandOnPath ?? findCommandOnPath;
|
|
2920
3154
|
const moduleDir = options.moduleDir ?? thisModuleDir;
|
|
2921
3155
|
const packageResolve = options.packageResolve ?? resolveImportSpecifier;
|
|
@@ -2929,8 +3163,8 @@ function resolveServerBinDetails(options = {}) {
|
|
|
2929
3163
|
});
|
|
2930
3164
|
} catch {
|
|
2931
3165
|
}
|
|
2932
|
-
const workspaceServerBin =
|
|
2933
|
-
const workspaceDistIndex =
|
|
3166
|
+
const workspaceServerBin = path11.resolve(moduleDir, "../../remnic-server/bin/remnic-server.js");
|
|
3167
|
+
const workspaceDistIndex = path11.resolve(moduleDir, "../../remnic-server/dist/index.js");
|
|
2934
3168
|
candidates.push(
|
|
2935
3169
|
{
|
|
2936
3170
|
path: workspaceServerBin,
|
|
@@ -2951,11 +3185,11 @@ function resolveServerBinDetails(options = {}) {
|
|
|
2951
3185
|
});
|
|
2952
3186
|
}
|
|
2953
3187
|
candidates.push({
|
|
2954
|
-
path:
|
|
3188
|
+
path: path11.resolve(moduleDir, "../../remnic-server/src/index.ts"),
|
|
2955
3189
|
source: "workspace-source"
|
|
2956
3190
|
});
|
|
2957
3191
|
const selected = candidates.find((candidate) => isCandidateReady(candidate, existsSync4)) ?? candidates.find((candidate) => existsSync4(candidate.path)) ?? candidates[0] ?? {
|
|
2958
|
-
path:
|
|
3192
|
+
path: path11.resolve(moduleDir, "../../remnic-server/dist/index.js"),
|
|
2959
3193
|
source: "workspace-dist"
|
|
2960
3194
|
};
|
|
2961
3195
|
const exists = existsSync4(selected.path);
|
|
@@ -2974,8 +3208,8 @@ function resolveServerBin(options = {}) {
|
|
|
2974
3208
|
return resolveServerBinDetails(options).path;
|
|
2975
3209
|
}
|
|
2976
3210
|
function readVerifiedDaemonPid(options) {
|
|
2977
|
-
const readFileSync4 = options.readFileSync ??
|
|
2978
|
-
const unlinkSync = options.unlinkSync ??
|
|
3211
|
+
const readFileSync4 = options.readFileSync ?? fs9.readFileSync;
|
|
3212
|
+
const unlinkSync = options.unlinkSync ?? fs9.unlinkSync;
|
|
2979
3213
|
const processKill = options.processKill ?? process.kill;
|
|
2980
3214
|
const platform = options.platform ?? process.platform;
|
|
2981
3215
|
const execFileSync3 = options.execFileSync ?? ((command, args, execOptions) => childProcess.execFileSync(command, args, execOptions));
|
|
@@ -3010,7 +3244,7 @@ function readVerifiedDaemonPid(options) {
|
|
|
3010
3244
|
}
|
|
3011
3245
|
function doesProcessCommandLookLikeRemnicDaemon(command, expectedServerBin) {
|
|
3012
3246
|
const normalizedCommand = command.trim();
|
|
3013
|
-
const normalizedExpected =
|
|
3247
|
+
const normalizedExpected = path11.resolve(expandTilde(expectedServerBin));
|
|
3014
3248
|
return normalizedCommand.includes(normalizedExpected) || /(?:^|\s|[/\\])(?:remnic-server|engram-server)(?:\.js)?(?:\s|$)/.test(normalizedCommand) || /@remnic[/\\]server[/\\]/.test(normalizedCommand) || /packages[/\\]remnic-server[/\\](?:bin[/\\]remnic-server\.js|dist[/\\]index\.js|src[/\\]index\.ts)/.test(normalizedCommand);
|
|
3015
3249
|
}
|
|
3016
3250
|
function parseDaemonPid(raw) {
|
|
@@ -3075,8 +3309,8 @@ function removePidFileBestEffort(file, unlinkSync) {
|
|
|
3075
3309
|
}
|
|
3076
3310
|
}
|
|
3077
3311
|
function inspectLaunchdPlist(plistPath, options = {}) {
|
|
3078
|
-
const existsSync4 = options.existsSync ??
|
|
3079
|
-
const readFileSync4 = options.readFileSync ??
|
|
3312
|
+
const existsSync4 = options.existsSync ?? fs9.existsSync;
|
|
3313
|
+
const readFileSync4 = options.readFileSync ?? fs9.readFileSync;
|
|
3080
3314
|
if (!existsSync4(plistPath)) {
|
|
3081
3315
|
return {
|
|
3082
3316
|
installed: false,
|
|
@@ -3115,7 +3349,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
3115
3349
|
};
|
|
3116
3350
|
}
|
|
3117
3351
|
const expandedServerArg = expandTilde(serverArg);
|
|
3118
|
-
if (!
|
|
3352
|
+
if (!path11.isAbsolute(expandedServerArg)) {
|
|
3119
3353
|
return {
|
|
3120
3354
|
installed: true,
|
|
3121
3355
|
ok: false,
|
|
@@ -3187,8 +3421,8 @@ function normalizeResolvedPath(resolved) {
|
|
|
3187
3421
|
return resolved;
|
|
3188
3422
|
}
|
|
3189
3423
|
function packageServerBinFromEntry(packageEntry) {
|
|
3190
|
-
if (
|
|
3191
|
-
return
|
|
3424
|
+
if (path11.basename(packageEntry) === "index.js" && path11.basename(path11.dirname(packageEntry)) === "dist") {
|
|
3425
|
+
return path11.join(path11.dirname(path11.dirname(packageEntry)), "bin", "remnic-server.js");
|
|
3192
3426
|
}
|
|
3193
3427
|
return packageEntry;
|
|
3194
3428
|
}
|
|
@@ -3310,7 +3544,7 @@ function stripConfigArgv(args) {
|
|
|
3310
3544
|
}
|
|
3311
3545
|
|
|
3312
3546
|
// src/import-dispatch.ts
|
|
3313
|
-
import
|
|
3547
|
+
import fs10 from "fs";
|
|
3314
3548
|
import {
|
|
3315
3549
|
runImporter,
|
|
3316
3550
|
validateImportBatchSize,
|
|
@@ -3319,7 +3553,7 @@ import {
|
|
|
3319
3553
|
|
|
3320
3554
|
// src/import-bundle-detect.ts
|
|
3321
3555
|
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
|
|
3322
|
-
import
|
|
3556
|
+
import path12 from "path";
|
|
3323
3557
|
function detectBundleEntries(bundleDir, options = {}) {
|
|
3324
3558
|
const readdir3 = options.readdirImpl ?? defaultReaddir;
|
|
3325
3559
|
const readFileImpl = options.readFileImpl ?? defaultReadFile;
|
|
@@ -3350,7 +3584,7 @@ function detectBundleEntries(bundleDir, options = {}) {
|
|
|
3350
3584
|
for (const filePath of roots) {
|
|
3351
3585
|
if (seenFiles.has(filePath)) continue;
|
|
3352
3586
|
seenFiles.add(filePath);
|
|
3353
|
-
const name =
|
|
3587
|
+
const name = path12.basename(filePath);
|
|
3354
3588
|
const match = classifyFile(name, filePath, readFileImpl);
|
|
3355
3589
|
if (match) entries.push(match);
|
|
3356
3590
|
}
|
|
@@ -3388,7 +3622,7 @@ function collectCandidatePaths(root, readdir3, isDirectory2, isRegularFile) {
|
|
|
3388
3622
|
return;
|
|
3389
3623
|
}
|
|
3390
3624
|
for (const entry of entries) {
|
|
3391
|
-
const full =
|
|
3625
|
+
const full = path12.join(dir, entry);
|
|
3392
3626
|
if (isDirectory2(full)) {
|
|
3393
3627
|
walk(full, depth + 1);
|
|
3394
3628
|
} else if (isRegularFile(full)) {
|
|
@@ -3824,7 +4058,7 @@ async function cmdImport(rest, targetFactory, disposeTarget, ioOverrides = {}) {
|
|
|
3824
4058
|
let materializedTarget;
|
|
3825
4059
|
let materializePromise;
|
|
3826
4060
|
const io = {
|
|
3827
|
-
readFile: ioOverrides.readFile ?? (async (p) =>
|
|
4061
|
+
readFile: ioOverrides.readFile ?? (async (p) => fs10.promises.readFile(p, "utf-8")),
|
|
3828
4062
|
loadAdapter: ioOverrides.loadAdapter ?? (async (name) => (await loadImporterModule(name)).adapter),
|
|
3829
4063
|
runImporter: ioOverrides.runImporter ?? runImporter,
|
|
3830
4064
|
getWriteTarget: async () => {
|
|
@@ -3937,8 +4171,8 @@ async function cmdCapture(rest, io) {
|
|
|
3937
4171
|
}
|
|
3938
4172
|
|
|
3939
4173
|
// src/import-lossless-claw-cmd.ts
|
|
3940
|
-
import
|
|
3941
|
-
import
|
|
4174
|
+
import fs11 from "fs";
|
|
4175
|
+
import path13 from "path";
|
|
3942
4176
|
import {
|
|
3943
4177
|
applyLcmSchema,
|
|
3944
4178
|
ensureLcmStateDir,
|
|
@@ -4049,15 +4283,15 @@ async function loadImportLosslessClawModule() {
|
|
|
4049
4283
|
|
|
4050
4284
|
// src/import-lossless-claw-cmd.ts
|
|
4051
4285
|
function assertDirectoryOrAbsent(p, label) {
|
|
4052
|
-
if (
|
|
4286
|
+
if (fs11.existsSync(p) && !fs11.statSync(p).isDirectory()) {
|
|
4053
4287
|
throw new Error(`${label} is not a directory: ${p}`);
|
|
4054
4288
|
}
|
|
4055
4289
|
}
|
|
4056
4290
|
function assertFile(p, label) {
|
|
4057
|
-
if (!
|
|
4291
|
+
if (!fs11.existsSync(p)) {
|
|
4058
4292
|
throw new Error(`${label} does not exist: ${p}`);
|
|
4059
4293
|
}
|
|
4060
|
-
if (!
|
|
4294
|
+
if (!fs11.statSync(p).isFile()) {
|
|
4061
4295
|
throw new Error(`${label} is not a file: ${p}`);
|
|
4062
4296
|
}
|
|
4063
4297
|
}
|
|
@@ -4088,8 +4322,8 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
4088
4322
|
let destDb;
|
|
4089
4323
|
try {
|
|
4090
4324
|
if (parsed.dryRun) {
|
|
4091
|
-
const lcmPath =
|
|
4092
|
-
if (
|
|
4325
|
+
const lcmPath = path13.join(memoryDir, "state", "lcm.sqlite");
|
|
4326
|
+
if (fs11.existsSync(lcmPath)) {
|
|
4093
4327
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
4094
4328
|
} else {
|
|
4095
4329
|
destDb = mod.openInMemoryDestinationDatabase();
|
|
@@ -4207,7 +4441,7 @@ function printBenchComparisonSummary(comparison, baseline, candidate) {
|
|
|
4207
4441
|
}
|
|
4208
4442
|
|
|
4209
4443
|
// src/bench-research-commands.ts
|
|
4210
|
-
import
|
|
4444
|
+
import path14 from "path";
|
|
4211
4445
|
function emit(result) {
|
|
4212
4446
|
if (result.output) {
|
|
4213
4447
|
console.log(result.output);
|
|
@@ -4225,7 +4459,7 @@ async function runBenchResearchCommand(parsed) {
|
|
|
4225
4459
|
emit(
|
|
4226
4460
|
await runAttributeCliCommand({
|
|
4227
4461
|
runRef: parsed.runRef,
|
|
4228
|
-
resultsDir: parsed.resultsDir ??
|
|
4462
|
+
resultsDir: parsed.resultsDir ?? path14.join(resolveHomeDir(), ".remnic", "bench", "results"),
|
|
4229
4463
|
memoryDir: parsed.memoryDir,
|
|
4230
4464
|
threshold: parsed.threshold,
|
|
4231
4465
|
json: parsed.json
|
|
@@ -4480,15 +4714,15 @@ registerPublisher("omp", () => new LazyPluginPiPublisher("omp", (mod) => mod.Omp
|
|
|
4480
4714
|
function readCompatEnv(primary, legacy) {
|
|
4481
4715
|
return process.env[primary] ?? process.env[legacy];
|
|
4482
4716
|
}
|
|
4483
|
-
var PID_DIR =
|
|
4484
|
-
var LEGACY_PID_DIR =
|
|
4485
|
-
var PID_FILE =
|
|
4486
|
-
var LEGACY_PID_FILE =
|
|
4487
|
-
var LOG_FILE =
|
|
4488
|
-
var LEGACY_LOG_FILE =
|
|
4489
|
-
var CLI_MODULE_DIR =
|
|
4490
|
-
var CLI_REPO_ROOT =
|
|
4491
|
-
var EVAL_RUNNER_PATH =
|
|
4717
|
+
var PID_DIR = path15.join(resolveHomeDir(), ".remnic");
|
|
4718
|
+
var LEGACY_PID_DIR = path15.join(resolveHomeDir(), ".engram");
|
|
4719
|
+
var PID_FILE = path15.join(PID_DIR, "server.pid");
|
|
4720
|
+
var LEGACY_PID_FILE = path15.join(LEGACY_PID_DIR, "server.pid");
|
|
4721
|
+
var LOG_FILE = path15.join(PID_DIR, "server.log");
|
|
4722
|
+
var LEGACY_LOG_FILE = path15.join(LEGACY_PID_DIR, "server.log");
|
|
4723
|
+
var CLI_MODULE_DIR = path15.dirname(fileURLToPath4(import.meta.url));
|
|
4724
|
+
var CLI_REPO_ROOT = path15.resolve(CLI_MODULE_DIR, "../../..");
|
|
4725
|
+
var EVAL_RUNNER_PATH = path15.join(CLI_REPO_ROOT, "evals", "run.ts");
|
|
4492
4726
|
var OPENCLAW_GATEWAY_LABEL = "ai.openclaw.gateway";
|
|
4493
4727
|
var CLI_SUCCESS_EXIT_GRACE_MS = 5e3;
|
|
4494
4728
|
var CLI_OUTPUT_FLUSH_GRACE_MS = 250;
|
|
@@ -4653,7 +4887,7 @@ async function resolveAllBenchmarks() {
|
|
|
4653
4887
|
if (packageBenchmarks) {
|
|
4654
4888
|
return packageBenchmarks.filter((entry) => entry.runnerAvailable).map((entry) => entry.id);
|
|
4655
4889
|
}
|
|
4656
|
-
if (!
|
|
4890
|
+
if (!fs12.existsSync(EVAL_RUNNER_PATH)) {
|
|
4657
4891
|
return [];
|
|
4658
4892
|
}
|
|
4659
4893
|
return BENCHMARK_CATALOG.filter((entry) => entry.category !== "ingestion").map((entry) => entry.id);
|
|
@@ -4701,17 +4935,17 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
4701
4935
|
`Fallback benchmark runner does not support provider-backed, gateway, or thinking/timeout flags (${unsupportedOptions.join(", ")}). Build/install @remnic/bench to use those options.`
|
|
4702
4936
|
);
|
|
4703
4937
|
}
|
|
4704
|
-
if (!
|
|
4938
|
+
if (!fs12.existsSync(EVAL_RUNNER_PATH)) {
|
|
4705
4939
|
console.error(
|
|
4706
4940
|
"Benchmark runner not found. Expected eval runner at evals/run.ts or a phase-1 @remnic/bench runtime export."
|
|
4707
4941
|
);
|
|
4708
4942
|
process.exit(1);
|
|
4709
4943
|
}
|
|
4710
4944
|
const tsxCandidates = [
|
|
4711
|
-
|
|
4712
|
-
|
|
4945
|
+
path15.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
4946
|
+
path15.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
4713
4947
|
];
|
|
4714
|
-
const tsxCmd = tsxCandidates.find((candidate) =>
|
|
4948
|
+
const tsxCmd = tsxCandidates.find((candidate) => fs12.existsSync(candidate)) ?? "tsx";
|
|
4715
4949
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
4716
4950
|
parsed.resultsDir ?? resolveBenchOutputDir(),
|
|
4717
4951
|
benchmarkId,
|
|
@@ -4728,7 +4962,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
4728
4962
|
return resolveFallbackBenchResultPath(fallbackOutputDir);
|
|
4729
4963
|
}
|
|
4730
4964
|
function resolveBenchOutputDir() {
|
|
4731
|
-
return
|
|
4965
|
+
return path15.join(resolveHomeDir(), ".remnic", "bench", "results");
|
|
4732
4966
|
}
|
|
4733
4967
|
var DOWNLOADABLE_BENCHMARK_DATASETS = [
|
|
4734
4968
|
"ama-bench",
|
|
@@ -4773,8 +5007,8 @@ var MEMORY_AGENT_BENCH_SPLIT_FILENAMES = [
|
|
|
4773
5007
|
];
|
|
4774
5008
|
var MEMORY_AGENT_BENCH_ENTITY_MAPPING_CANDIDATES = [
|
|
4775
5009
|
"entity2id.json",
|
|
4776
|
-
|
|
4777
|
-
|
|
5010
|
+
path15.join("processed_data", "Recsys_Redial", "entity2id.json"),
|
|
5011
|
+
path15.join("Recsys_Redial", "entity2id.json")
|
|
4778
5012
|
];
|
|
4779
5013
|
var DOWNLOADED_DATASET_MARKERS = {
|
|
4780
5014
|
"ama-bench": { anyOf: ["open_end_qa_set.jsonl"] },
|
|
@@ -4849,18 +5083,18 @@ var PERSONAMEM_DATASET_FILE_CANDIDATES = [
|
|
|
4849
5083
|
"benchmark/benchmark.csv",
|
|
4850
5084
|
"benchmark.csv"
|
|
4851
5085
|
];
|
|
4852
|
-
var PERSONAMEM_COMPLETION_MARKER =
|
|
5086
|
+
var PERSONAMEM_COMPLETION_MARKER = path15.join(
|
|
4853
5087
|
"data",
|
|
4854
5088
|
"chat_history_32k",
|
|
4855
5089
|
".download-complete"
|
|
4856
5090
|
);
|
|
4857
5091
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
4858
5092
|
try {
|
|
4859
|
-
const datasetRoot =
|
|
4860
|
-
const candidatePath =
|
|
4861
|
-
const candidateRealPath =
|
|
4862
|
-
const relativeToRoot =
|
|
4863
|
-
if (relativeToRoot.startsWith("..") ||
|
|
5093
|
+
const datasetRoot = fs12.realpathSync(datasetPath);
|
|
5094
|
+
const candidatePath = path15.resolve(datasetRoot, relativePath);
|
|
5095
|
+
const candidateRealPath = fs12.realpathSync(candidatePath);
|
|
5096
|
+
const relativeToRoot = path15.relative(datasetRoot, candidateRealPath);
|
|
5097
|
+
if (relativeToRoot.startsWith("..") || path15.isAbsolute(relativeToRoot)) {
|
|
4864
5098
|
return null;
|
|
4865
5099
|
}
|
|
4866
5100
|
return candidateRealPath;
|
|
@@ -4916,15 +5150,15 @@ function parseCsvRows(raw) {
|
|
|
4916
5150
|
}
|
|
4917
5151
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
4918
5152
|
try {
|
|
4919
|
-
const completionMarkerPath =
|
|
4920
|
-
if (
|
|
5153
|
+
const completionMarkerPath = path15.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
5154
|
+
if (fs12.statSync(completionMarkerPath).isFile()) {
|
|
4921
5155
|
return true;
|
|
4922
5156
|
}
|
|
4923
5157
|
} catch {
|
|
4924
5158
|
}
|
|
4925
5159
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
4926
5160
|
try {
|
|
4927
|
-
return
|
|
5161
|
+
return fs12.statSync(path15.join(datasetPath, candidate)).isFile();
|
|
4928
5162
|
} catch {
|
|
4929
5163
|
return false;
|
|
4930
5164
|
}
|
|
@@ -4933,7 +5167,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4933
5167
|
return false;
|
|
4934
5168
|
}
|
|
4935
5169
|
try {
|
|
4936
|
-
const rows = parseCsvRows(
|
|
5170
|
+
const rows = parseCsvRows(fs12.readFileSync(path15.join(datasetPath, datasetFile), "utf8"));
|
|
4937
5171
|
if (rows.length < 2) {
|
|
4938
5172
|
return false;
|
|
4939
5173
|
}
|
|
@@ -4948,7 +5182,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4948
5182
|
}
|
|
4949
5183
|
return historyPaths.every((relativePath) => {
|
|
4950
5184
|
const resolvedPath = resolveRealpathWithinDataset(datasetPath, relativePath);
|
|
4951
|
-
return resolvedPath !== null &&
|
|
5185
|
+
return resolvedPath !== null && fs12.statSync(resolvedPath).isFile();
|
|
4952
5186
|
});
|
|
4953
5187
|
} catch {
|
|
4954
5188
|
return false;
|
|
@@ -4956,14 +5190,14 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4956
5190
|
}
|
|
4957
5191
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
4958
5192
|
try {
|
|
4959
|
-
return
|
|
5193
|
+
return fs12.statSync(path15.join(datasetPath, relativePath)).isFile();
|
|
4960
5194
|
} catch {
|
|
4961
5195
|
return false;
|
|
4962
5196
|
}
|
|
4963
5197
|
}
|
|
4964
5198
|
function hasMemoryAgentBenchEntityMapping(datasetPath) {
|
|
4965
|
-
const absoluteDatasetPath =
|
|
4966
|
-
const roots = [absoluteDatasetPath,
|
|
5199
|
+
const absoluteDatasetPath = path15.resolve(datasetPath);
|
|
5200
|
+
const roots = [absoluteDatasetPath, path15.dirname(absoluteDatasetPath)];
|
|
4967
5201
|
return hasDatasetFile(absoluteDatasetPath, "entity2id.json") || roots.some(
|
|
4968
5202
|
(root) => MEMORY_AGENT_BENCH_ENTITY_MAPPING_CANDIDATES.filter((relativePath) => relativePath !== "entity2id.json").some((relativePath) => hasDatasetFile(root, relativePath))
|
|
4969
5203
|
);
|
|
@@ -4974,12 +5208,12 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
4974
5208
|
...MEMORY_AGENT_BENCH_SPLIT_FILENAMES
|
|
4975
5209
|
];
|
|
4976
5210
|
return candidateFilenames.some((filename) => {
|
|
4977
|
-
const filePath =
|
|
5211
|
+
const filePath = path15.join(datasetPath, filename);
|
|
4978
5212
|
try {
|
|
4979
|
-
if (!
|
|
5213
|
+
if (!fs12.statSync(filePath).isFile()) {
|
|
4980
5214
|
return false;
|
|
4981
5215
|
}
|
|
4982
|
-
const raw =
|
|
5216
|
+
const raw = fs12.readFileSync(filePath, "utf8");
|
|
4983
5217
|
return /"source"\s*:\s*"recsys[_-]/i.test(raw);
|
|
4984
5218
|
} catch {
|
|
4985
5219
|
return false;
|
|
@@ -4995,7 +5229,7 @@ function isMemoryAgentBenchDatasetComplete(datasetPath) {
|
|
|
4995
5229
|
function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
4996
5230
|
let stats;
|
|
4997
5231
|
try {
|
|
4998
|
-
stats =
|
|
5232
|
+
stats = fs12.statSync(datasetPath);
|
|
4999
5233
|
} catch {
|
|
5000
5234
|
return false;
|
|
5001
5235
|
}
|
|
@@ -5005,7 +5239,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
5005
5239
|
const marker = DOWNLOADED_DATASET_MARKERS[benchmarkId];
|
|
5006
5240
|
if (!marker) {
|
|
5007
5241
|
try {
|
|
5008
|
-
return
|
|
5242
|
+
return fs12.readdirSync(datasetPath).length > 0;
|
|
5009
5243
|
} catch {
|
|
5010
5244
|
return false;
|
|
5011
5245
|
}
|
|
@@ -5013,7 +5247,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
5013
5247
|
if (marker.allOf) {
|
|
5014
5248
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
5015
5249
|
try {
|
|
5016
|
-
return
|
|
5250
|
+
return fs12.statSync(path15.join(datasetPath, name)).isFile();
|
|
5017
5251
|
} catch {
|
|
5018
5252
|
return false;
|
|
5019
5253
|
}
|
|
@@ -5025,7 +5259,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
5025
5259
|
if (marker.anyOf) {
|
|
5026
5260
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
5027
5261
|
try {
|
|
5028
|
-
return
|
|
5262
|
+
return fs12.statSync(path15.join(datasetPath, name)).isFile();
|
|
5029
5263
|
} catch {
|
|
5030
5264
|
return false;
|
|
5031
5265
|
}
|
|
@@ -5043,7 +5277,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
5043
5277
|
}
|
|
5044
5278
|
if (marker.ext) {
|
|
5045
5279
|
try {
|
|
5046
|
-
return
|
|
5280
|
+
return fs12.readdirSync(datasetPath).some(
|
|
5047
5281
|
(name) => name.endsWith(marker.ext) && !marker.exclude?.includes(name)
|
|
5048
5282
|
);
|
|
5049
5283
|
} catch {
|
|
@@ -5053,9 +5287,9 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
5053
5287
|
return false;
|
|
5054
5288
|
}
|
|
5055
5289
|
async function launchBenchUi(resultsDir) {
|
|
5056
|
-
const benchUiDir =
|
|
5290
|
+
const benchUiDir = path15.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
5057
5291
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
5058
|
-
if (!
|
|
5292
|
+
if (!fs12.existsSync(path15.join(benchUiDir, "package.json"))) {
|
|
5059
5293
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
5060
5294
|
process.exit(1);
|
|
5061
5295
|
}
|
|
@@ -5082,24 +5316,24 @@ async function launchBenchUi(resultsDir) {
|
|
|
5082
5316
|
});
|
|
5083
5317
|
}
|
|
5084
5318
|
function resolveRepoDatasetRoot() {
|
|
5085
|
-
const repoCandidate =
|
|
5319
|
+
const repoCandidate = path15.join(CLI_REPO_ROOT, "evals", "datasets");
|
|
5086
5320
|
if (isRepoCheckout()) {
|
|
5087
5321
|
return repoCandidate;
|
|
5088
5322
|
}
|
|
5089
|
-
return
|
|
5323
|
+
return path15.join(resolveHomeDir(), ".remnic", "bench", "datasets");
|
|
5090
5324
|
}
|
|
5091
5325
|
function listDownloadableBenchmarks() {
|
|
5092
5326
|
return [...DOWNLOADABLE_BENCHMARK_DATASETS];
|
|
5093
5327
|
}
|
|
5094
5328
|
function resolveDatasetDownloadScriptPath() {
|
|
5095
|
-
const bundled =
|
|
5096
|
-
if (
|
|
5329
|
+
const bundled = path15.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
5330
|
+
if (fs12.existsSync(bundled)) {
|
|
5097
5331
|
return bundled;
|
|
5098
5332
|
}
|
|
5099
|
-
return
|
|
5333
|
+
return path15.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
5100
5334
|
}
|
|
5101
5335
|
function isRepoCheckout() {
|
|
5102
|
-
return
|
|
5336
|
+
return fs12.existsSync(path15.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs12.existsSync(path15.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
5103
5337
|
}
|
|
5104
5338
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
5105
5339
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -5150,7 +5384,7 @@ function resolveBenchDatasetDir(benchmarkId, quick, datasetDirOverride) {
|
|
|
5150
5384
|
if (quick) {
|
|
5151
5385
|
return void 0;
|
|
5152
5386
|
}
|
|
5153
|
-
const datasetDir =
|
|
5387
|
+
const datasetDir = path15.join(resolveRepoDatasetRoot(), benchmarkId);
|
|
5154
5388
|
if (isDatasetDownloaded(datasetDir, benchmarkId)) {
|
|
5155
5389
|
return datasetDir;
|
|
5156
5390
|
}
|
|
@@ -5407,13 +5641,13 @@ async function exportBenchPackageResult(parsed) {
|
|
|
5407
5641
|
process.exit(1);
|
|
5408
5642
|
}
|
|
5409
5643
|
const result = await loadBenchmarkResult(summary.path);
|
|
5410
|
-
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(
|
|
5644
|
+
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(path15.dirname(summary.path), result.meta.id) : void 0;
|
|
5411
5645
|
const rendered = renderBenchmarkResultExport(result, parsed.format, {
|
|
5412
5646
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
5413
5647
|
});
|
|
5414
5648
|
if (parsed.output) {
|
|
5415
|
-
|
|
5416
|
-
|
|
5649
|
+
fs12.mkdirSync(path15.dirname(parsed.output), { recursive: true });
|
|
5650
|
+
fs12.writeFileSync(parsed.output, rendered);
|
|
5417
5651
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
5418
5652
|
return;
|
|
5419
5653
|
}
|
|
@@ -5430,7 +5664,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
5430
5664
|
process.exit(1);
|
|
5431
5665
|
}
|
|
5432
5666
|
const status = supported.map((benchmarkId) => {
|
|
5433
|
-
const datasetPath =
|
|
5667
|
+
const datasetPath = path15.join(datasetRoot, benchmarkId);
|
|
5434
5668
|
return {
|
|
5435
5669
|
benchmark: benchmarkId,
|
|
5436
5670
|
downloaded: isDatasetDownloaded(datasetPath, benchmarkId),
|
|
@@ -5458,7 +5692,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
5458
5692
|
process.exit(1);
|
|
5459
5693
|
}
|
|
5460
5694
|
const scriptPath = resolveDatasetDownloadScriptPath();
|
|
5461
|
-
if (!
|
|
5695
|
+
if (!fs12.existsSync(scriptPath)) {
|
|
5462
5696
|
console.error(`ERROR: dataset download script not found: ${scriptPath}`);
|
|
5463
5697
|
process.exit(1);
|
|
5464
5698
|
}
|
|
@@ -5468,7 +5702,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
5468
5702
|
runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, parsed.json === true);
|
|
5469
5703
|
downloaded.push({
|
|
5470
5704
|
benchmark: benchmarkId,
|
|
5471
|
-
path:
|
|
5705
|
+
path: path15.join(datasetRoot, benchmarkId)
|
|
5472
5706
|
});
|
|
5473
5707
|
}
|
|
5474
5708
|
if (parsed.json) {
|
|
@@ -5607,10 +5841,10 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
5607
5841
|
}
|
|
5608
5842
|
const bench = await loadBenchModule();
|
|
5609
5843
|
const resultsDir = expandTilde(
|
|
5610
|
-
parsed.resultsDir ??
|
|
5844
|
+
parsed.resultsDir ?? path15.join(resolveHomeDir(), ".remnic", "bench", "results")
|
|
5611
5845
|
);
|
|
5612
5846
|
const calibrationDir = expandTilde(
|
|
5613
|
-
parsed.calibrationDir ??
|
|
5847
|
+
parsed.calibrationDir ?? path15.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
5614
5848
|
);
|
|
5615
5849
|
const stored = await bench.listBenchmarkResults(resultsDir);
|
|
5616
5850
|
const allForBenchmark = stored.filter((entry) => entry.benchmark === benchmarkId);
|
|
@@ -5658,7 +5892,7 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
5658
5892
|
);
|
|
5659
5893
|
process.exit(1);
|
|
5660
5894
|
}
|
|
5661
|
-
const sourceResultSha256 = createHash2("sha256").update(
|
|
5895
|
+
const sourceResultSha256 = createHash2("sha256").update(fs12.readFileSync(latest.path)).digest("hex");
|
|
5662
5896
|
const expandedManifestPath = expandTilde(manifestPath);
|
|
5663
5897
|
if (!bench.resolveLocalLabJudgeProviderConfig) {
|
|
5664
5898
|
console.error(
|
|
@@ -6073,7 +6307,7 @@ function loadPinnedLoCoMoTaskSelector(parsed) {
|
|
|
6073
6307
|
}
|
|
6074
6308
|
let decoded;
|
|
6075
6309
|
try {
|
|
6076
|
-
decoded = JSON.parse(
|
|
6310
|
+
decoded = JSON.parse(fs12.readFileSync(parsed.taskIdsFile, "utf8"));
|
|
6077
6311
|
} catch (error) {
|
|
6078
6312
|
throw new Error(
|
|
6079
6313
|
`Unable to read --task-ids-file ${parsed.taskIdsFile}: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -6170,7 +6404,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
6170
6404
|
return {
|
|
6171
6405
|
async promoteArtifactsToPublished(args) {
|
|
6172
6406
|
const { mkdirSync, readFileSync: readFileSync4, writeFileSync } = await import("fs");
|
|
6173
|
-
const
|
|
6407
|
+
const path16 = await import("path");
|
|
6174
6408
|
mkdirSync(args.publishedOutDir, { recursive: true });
|
|
6175
6409
|
if (args.artifactPaths.length === 0) {
|
|
6176
6410
|
console.warn(
|
|
@@ -6187,13 +6421,13 @@ async function loadPublishedPromotionHelpers() {
|
|
|
6187
6421
|
const modelSlug = args.model.replace(/[^a-zA-Z0-9_.-]/g, "-");
|
|
6188
6422
|
const rawProfile = parsedObj.config?.runtimeProfile;
|
|
6189
6423
|
const profileSlug = typeof rawProfile === "string" && rawProfile.length > 0 ? `-${rawProfile.replace(/[^a-zA-Z0-9_.-]/g, "-")}` : "";
|
|
6190
|
-
const target =
|
|
6424
|
+
const target = path16.join(
|
|
6191
6425
|
args.publishedOutDir,
|
|
6192
6426
|
`${today}-${args.benchmarkId}-${modelSlug}${profileSlug}-${gitShaShort}.json`
|
|
6193
6427
|
);
|
|
6194
6428
|
writeFileSync(target, raw, "utf8");
|
|
6195
6429
|
console.log(
|
|
6196
|
-
`[bench published] Promoted ${
|
|
6430
|
+
`[bench published] Promoted ${path16.basename(artifactPath)} \u2192 ${target}`
|
|
6197
6431
|
);
|
|
6198
6432
|
}
|
|
6199
6433
|
void benchModule;
|
|
@@ -6300,7 +6534,7 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
|
|
|
6300
6534
|
const previousCodexDiagnosticsDir = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV];
|
|
6301
6535
|
const previousCodexDiagnosticsMode = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_MODE_ENV];
|
|
6302
6536
|
if (!previousCodexDiagnosticsDir) {
|
|
6303
|
-
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] =
|
|
6537
|
+
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] = path15.join(
|
|
6304
6538
|
outputDir,
|
|
6305
6539
|
"codex-cli-diagnostics"
|
|
6306
6540
|
);
|
|
@@ -6448,7 +6682,7 @@ async function preparePersistedJudgeCalibrationAttachment(benchModule, benchmark
|
|
|
6448
6682
|
);
|
|
6449
6683
|
}
|
|
6450
6684
|
const calibrationDir = expandTilde(
|
|
6451
|
-
calibrationBinding.calibrationDir ??
|
|
6685
|
+
calibrationBinding.calibrationDir ?? path15.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
6452
6686
|
);
|
|
6453
6687
|
const state = await benchModule.loadJudgeCalibrationState?.(benchmarkId, calibrationDir);
|
|
6454
6688
|
if (!state) {
|
|
@@ -6745,7 +6979,7 @@ function resolveBenchReproDatasetDir(datasetDir) {
|
|
|
6745
6979
|
return void 0;
|
|
6746
6980
|
}
|
|
6747
6981
|
try {
|
|
6748
|
-
return
|
|
6982
|
+
return fs12.realpathSync(datasetDir);
|
|
6749
6983
|
} catch {
|
|
6750
6984
|
return datasetDir;
|
|
6751
6985
|
}
|
|
@@ -6798,23 +7032,23 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
6798
7032
|
}
|
|
6799
7033
|
}
|
|
6800
7034
|
function resolveConfigPath(cliPath) {
|
|
6801
|
-
if (cliPath) return
|
|
7035
|
+
if (cliPath) return path15.resolve(expandTilde(cliPath));
|
|
6802
7036
|
const envPath = readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH");
|
|
6803
|
-
if (envPath) return
|
|
7037
|
+
if (envPath) return path15.resolve(expandTilde(envPath));
|
|
6804
7038
|
const candidates = [
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
7039
|
+
path15.join(process.cwd(), "remnic.config.json"),
|
|
7040
|
+
path15.join(process.cwd(), "engram.config.json"),
|
|
7041
|
+
path15.join(resolveHomeDir(), ".config", "remnic", "config.json"),
|
|
7042
|
+
path15.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
6809
7043
|
];
|
|
6810
7044
|
for (const candidate of candidates) {
|
|
6811
|
-
if (
|
|
7045
|
+
if (fs12.existsSync(candidate)) return candidate;
|
|
6812
7046
|
}
|
|
6813
|
-
return
|
|
7047
|
+
return path15.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
6814
7048
|
}
|
|
6815
7049
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
6816
7050
|
const configPath = resolveConfigPath(cliPath);
|
|
6817
|
-
if (
|
|
7051
|
+
if (fs12.existsSync(configPath)) {
|
|
6818
7052
|
return configPath;
|
|
6819
7053
|
}
|
|
6820
7054
|
if (cliPath) {
|
|
@@ -6824,7 +7058,7 @@ function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
|
6824
7058
|
}
|
|
6825
7059
|
function resolveExistingBenchOpenclawConfigPath(cliPath) {
|
|
6826
7060
|
const configPath = resolveOpenclawConfigPath(cliPath);
|
|
6827
|
-
if (
|
|
7061
|
+
if (fs12.existsSync(configPath)) {
|
|
6828
7062
|
return configPath;
|
|
6829
7063
|
}
|
|
6830
7064
|
if (cliPath) {
|
|
@@ -6924,34 +7158,34 @@ async function resolvePackageBenchRuntime(benchModule, parsed, runtimeProfile) {
|
|
|
6924
7158
|
);
|
|
6925
7159
|
}
|
|
6926
7160
|
function normalizeMemoryDirPath(memoryDir) {
|
|
6927
|
-
return
|
|
7161
|
+
return path15.resolve(expandTilde(memoryDir));
|
|
6928
7162
|
}
|
|
6929
7163
|
function resolveMemoryDir() {
|
|
6930
7164
|
const configMemoryDir = (() => {
|
|
6931
7165
|
const envMemoryDir = readCompatEnv("REMNIC_MEMORY_DIR", "ENGRAM_MEMORY_DIR");
|
|
6932
7166
|
if (envMemoryDir) return normalizeMemoryDirPath(envMemoryDir);
|
|
6933
7167
|
const configPath = resolveConfigPath();
|
|
6934
|
-
const raw =
|
|
7168
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
6935
7169
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
6936
7170
|
if (typeof remnicCfg.memoryDir === "string" && remnicCfg.memoryDir.length > 0) {
|
|
6937
7171
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
6938
7172
|
}
|
|
6939
7173
|
const home = resolveHomeDir();
|
|
6940
|
-
const standalonePath =
|
|
6941
|
-
const legacyStandalonePath =
|
|
6942
|
-
const openclawPath =
|
|
6943
|
-
if (
|
|
6944
|
-
if (
|
|
7174
|
+
const standalonePath = path15.join(home, ".remnic", "memory");
|
|
7175
|
+
const legacyStandalonePath = path15.join(home, ".engram", "memory");
|
|
7176
|
+
const openclawPath = path15.join(home, ".openclaw", "workspace", "memory", "local");
|
|
7177
|
+
if (fs12.existsSync(standalonePath)) return standalonePath;
|
|
7178
|
+
if (fs12.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
6945
7179
|
return openclawPath;
|
|
6946
7180
|
})();
|
|
6947
7181
|
const manifestPath = getManifestPath();
|
|
6948
|
-
if (
|
|
7182
|
+
if (fs12.existsSync(manifestPath)) {
|
|
6949
7183
|
try {
|
|
6950
7184
|
const active = getActiveSpace();
|
|
6951
7185
|
if (active?.memoryDir) {
|
|
6952
7186
|
const activeMemoryDir = normalizeMemoryDirPath(active.memoryDir);
|
|
6953
|
-
if (!
|
|
6954
|
-
|
|
7187
|
+
if (!fs12.existsSync(activeMemoryDir)) {
|
|
7188
|
+
fs12.mkdirSync(activeMemoryDir, { recursive: true });
|
|
6955
7189
|
}
|
|
6956
7190
|
return activeMemoryDir;
|
|
6957
7191
|
}
|
|
@@ -6990,20 +7224,20 @@ var REMNIC_OPENCLAW_LEGACY_PLUGIN_ID = "openclaw-engram";
|
|
|
6990
7224
|
var DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR = [
|
|
6991
7225
|
process.env.OPENCLAW_CONFIG_PATH,
|
|
6992
7226
|
process.env.OPENCLAW_ENGRAM_CONFIG_PATH,
|
|
6993
|
-
|
|
7227
|
+
path15.join(resolveHomeDir(), ".openclaw", "openclaw.json")
|
|
6994
7228
|
].filter(Boolean);
|
|
6995
7229
|
function resolveOpenclawConfigPath(cliPath) {
|
|
6996
|
-
if (cliPath) return
|
|
7230
|
+
if (cliPath) return path15.resolve(expandTilde(cliPath));
|
|
6997
7231
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
6998
|
-
if (envPath) return
|
|
7232
|
+
if (envPath) return path15.resolve(expandTilde(envPath));
|
|
6999
7233
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
7000
|
-
if (
|
|
7234
|
+
if (fs12.existsSync(candidate)) return candidate;
|
|
7001
7235
|
}
|
|
7002
|
-
return
|
|
7236
|
+
return path15.join(resolveHomeDir(), ".openclaw", "openclaw.json");
|
|
7003
7237
|
}
|
|
7004
7238
|
function readOpenclawConfig(configPath) {
|
|
7005
|
-
if (!
|
|
7006
|
-
const raw =
|
|
7239
|
+
if (!fs12.existsSync(configPath)) return {};
|
|
7240
|
+
const raw = fs12.readFileSync(configPath, "utf-8");
|
|
7007
7241
|
let parsed;
|
|
7008
7242
|
try {
|
|
7009
7243
|
parsed = JSON.parse(raw);
|
|
@@ -7058,10 +7292,10 @@ function buildRemnicOpenclawHooksPolicy(legacyHooks, existingHooks) {
|
|
|
7058
7292
|
function resolveOpenclawInstallMemoryDir(args) {
|
|
7059
7293
|
const existingMemoryDir = (typeof args.existingNewEntryConfig.memoryDir === "string" ? args.existingNewEntryConfig.memoryDir : void 0) || (args.migrateLegacy && typeof args.legacyConfigToMerge.memoryDir === "string" ? args.legacyConfigToMerge.memoryDir : void 0);
|
|
7060
7294
|
if (args.requestedMemoryDir) {
|
|
7061
|
-
return
|
|
7295
|
+
return path15.resolve(expandTilde(args.requestedMemoryDir));
|
|
7062
7296
|
}
|
|
7063
7297
|
if (existingMemoryDir) {
|
|
7064
|
-
return
|
|
7298
|
+
return path15.resolve(expandTilde(existingMemoryDir));
|
|
7065
7299
|
}
|
|
7066
7300
|
return args.fallbackMemoryDir;
|
|
7067
7301
|
}
|
|
@@ -7079,18 +7313,18 @@ function resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir) {
|
|
|
7079
7313
|
if (!config || typeof config !== "object" || Array.isArray(config)) continue;
|
|
7080
7314
|
const memoryDir = config.memoryDir;
|
|
7081
7315
|
if (typeof memoryDir === "string" && memoryDir.trim().length > 0) {
|
|
7082
|
-
return
|
|
7316
|
+
return path15.resolve(expandTilde(memoryDir));
|
|
7083
7317
|
}
|
|
7084
7318
|
}
|
|
7085
7319
|
return fallbackMemoryDir;
|
|
7086
7320
|
}
|
|
7087
7321
|
function resolveOpenclawPluginDir(cliPath) {
|
|
7088
|
-
if (cliPath) return
|
|
7089
|
-
return
|
|
7322
|
+
if (cliPath) return path15.resolve(expandTilde(cliPath));
|
|
7323
|
+
return path15.join(resolveHomeDir(), ".openclaw", "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
7090
7324
|
}
|
|
7091
7325
|
function resolveOpenclawLegacyPluginDir(cliPath) {
|
|
7092
|
-
if (cliPath) return
|
|
7093
|
-
return
|
|
7326
|
+
if (cliPath) return path15.resolve(expandTilde(cliPath));
|
|
7327
|
+
return path15.join(resolveHomeDir(), ".openclaw", "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID);
|
|
7094
7328
|
}
|
|
7095
7329
|
function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
7096
7330
|
const yyyy = now.getFullYear().toString();
|
|
@@ -7102,14 +7336,14 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
7102
7336
|
return `${yyyy}${mm}${dd}-${hh}${min}${ss}`;
|
|
7103
7337
|
}
|
|
7104
7338
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
7105
|
-
if (!
|
|
7106
|
-
|
|
7107
|
-
|
|
7339
|
+
if (!fs12.existsSync(sourcePath)) return false;
|
|
7340
|
+
fs12.mkdirSync(path15.dirname(backupPath), { recursive: true });
|
|
7341
|
+
fs12.cpSync(sourcePath, backupPath, { recursive: true });
|
|
7108
7342
|
return true;
|
|
7109
7343
|
}
|
|
7110
7344
|
function assertDirectoryPathOrMissing(targetPath, label) {
|
|
7111
|
-
if (!
|
|
7112
|
-
const stat =
|
|
7345
|
+
if (!fs12.existsSync(targetPath)) return;
|
|
7346
|
+
const stat = fs12.statSync(targetPath);
|
|
7113
7347
|
if (!stat.isDirectory()) {
|
|
7114
7348
|
throw new Error(`${label} must be a directory when it already exists: ${targetPath}`);
|
|
7115
7349
|
}
|
|
@@ -7134,7 +7368,7 @@ var PublishedOpenclawPluginInstallError = class extends Error {
|
|
|
7134
7368
|
}
|
|
7135
7369
|
};
|
|
7136
7370
|
function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
7137
|
-
const tempRoot =
|
|
7371
|
+
const tempRoot = fs12.mkdtempSync(path15.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
7138
7372
|
const stagedDir = `${pluginDir}.next-${process.pid}-${Date.now()}`;
|
|
7139
7373
|
const rollbackDir = `${pluginDir}.rollback-${process.pid}-${Date.now()}`;
|
|
7140
7374
|
let swapRollbackDir;
|
|
@@ -7149,17 +7383,17 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
7149
7383
|
if (!tarballName) {
|
|
7150
7384
|
throw new Error(`npm pack ${spec} did not return a tarball name`);
|
|
7151
7385
|
}
|
|
7152
|
-
const unpackDir =
|
|
7153
|
-
|
|
7154
|
-
childProcess2.execFileSync("tar", ["-xzf",
|
|
7386
|
+
const unpackDir = path15.join(tempRoot, "unpacked");
|
|
7387
|
+
fs12.mkdirSync(unpackDir, { recursive: true });
|
|
7388
|
+
childProcess2.execFileSync("tar", ["-xzf", path15.join(tempRoot, tarballName), "-C", unpackDir], {
|
|
7155
7389
|
stdio: ["ignore", "pipe", "pipe"]
|
|
7156
7390
|
});
|
|
7157
|
-
const packagedDir =
|
|
7158
|
-
if (!
|
|
7391
|
+
const packagedDir = path15.join(unpackDir, "package");
|
|
7392
|
+
if (!fs12.existsSync(packagedDir)) {
|
|
7159
7393
|
throw new Error(`npm pack ${spec} did not contain a package/ directory`);
|
|
7160
7394
|
}
|
|
7161
|
-
|
|
7162
|
-
|
|
7395
|
+
fs12.rmSync(stagedDir, { recursive: true, force: true });
|
|
7396
|
+
fs12.cpSync(packagedDir, stagedDir, { recursive: true });
|
|
7163
7397
|
childProcess2.execFileSync("npm", ["install", "--omit=dev"], {
|
|
7164
7398
|
cwd: stagedDir,
|
|
7165
7399
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -7174,8 +7408,8 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
7174
7408
|
}
|
|
7175
7409
|
})();
|
|
7176
7410
|
swapRollbackDir = swapResult.rollbackDir;
|
|
7177
|
-
const installedPackageJsonPath =
|
|
7178
|
-
const installedPackage =
|
|
7411
|
+
const installedPackageJsonPath = path15.join(pluginDir, "package.json");
|
|
7412
|
+
const installedPackage = fs12.existsSync(installedPackageJsonPath) ? JSON.parse(fs12.readFileSync(installedPackageJsonPath, "utf8")) : {};
|
|
7179
7413
|
return {
|
|
7180
7414
|
rollbackDir: swapRollbackDir,
|
|
7181
7415
|
version: typeof installedPackage.version === "string" ? installedPackage.version : void 0
|
|
@@ -7190,8 +7424,8 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
7190
7424
|
}
|
|
7191
7425
|
);
|
|
7192
7426
|
} finally {
|
|
7193
|
-
|
|
7194
|
-
|
|
7427
|
+
fs12.rmSync(stagedDir, { recursive: true, force: true });
|
|
7428
|
+
fs12.rmSync(tempRoot, { recursive: true, force: true });
|
|
7195
7429
|
}
|
|
7196
7430
|
}
|
|
7197
7431
|
function restartOpenclawGateway() {
|
|
@@ -7209,15 +7443,15 @@ function restartOpenclawGateway() {
|
|
|
7209
7443
|
});
|
|
7210
7444
|
}
|
|
7211
7445
|
function cmdInit() {
|
|
7212
|
-
const configPath =
|
|
7213
|
-
if (
|
|
7446
|
+
const configPath = path15.join(process.cwd(), "remnic.config.json");
|
|
7447
|
+
if (fs12.existsSync(configPath)) {
|
|
7214
7448
|
console.log(`Config already exists: ${configPath}`);
|
|
7215
7449
|
return;
|
|
7216
7450
|
}
|
|
7217
7451
|
const template = {
|
|
7218
7452
|
remnic: {
|
|
7219
7453
|
openaiApiKey: "${OPENAI_API_KEY}",
|
|
7220
|
-
memoryDir:
|
|
7454
|
+
memoryDir: path15.join(process.cwd(), ".remnic", "memory"),
|
|
7221
7455
|
memoryOsPreset: "balanced"
|
|
7222
7456
|
},
|
|
7223
7457
|
server: {
|
|
@@ -7226,7 +7460,7 @@ function cmdInit() {
|
|
|
7226
7460
|
authToken: "${REMNIC_AUTH_TOKEN}"
|
|
7227
7461
|
}
|
|
7228
7462
|
};
|
|
7229
|
-
|
|
7463
|
+
fs12.writeFileSync(configPath, JSON.stringify(template, null, 2) + "\n");
|
|
7230
7464
|
console.log(`Created ${configPath}`);
|
|
7231
7465
|
console.log("\nSet these environment variables:");
|
|
7232
7466
|
console.log(" export OPENAI_API_KEY=sk-...");
|
|
@@ -7296,7 +7530,7 @@ async function cmdStatus(json) {
|
|
|
7296
7530
|
}
|
|
7297
7531
|
function oauthReadConfigRecord(configPath) {
|
|
7298
7532
|
try {
|
|
7299
|
-
const parsed = JSON.parse(
|
|
7533
|
+
const parsed = JSON.parse(fs12.readFileSync(configPath, "utf8"));
|
|
7300
7534
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
7301
7535
|
return parsed;
|
|
7302
7536
|
}
|
|
@@ -7354,7 +7588,7 @@ function oauthResolveOperatorToken() {
|
|
|
7354
7588
|
}
|
|
7355
7589
|
return void 0;
|
|
7356
7590
|
}
|
|
7357
|
-
async function oauthFetch(method,
|
|
7591
|
+
async function oauthFetch(method, path16, token, body) {
|
|
7358
7592
|
const controller = new AbortController();
|
|
7359
7593
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
7360
7594
|
try {
|
|
@@ -7373,7 +7607,7 @@ async function oauthFetch(method, path15, token, body) {
|
|
|
7373
7607
|
if (body !== void 0) {
|
|
7374
7608
|
init.body = JSON.stringify(body);
|
|
7375
7609
|
}
|
|
7376
|
-
const response = await fetch(`${oauthResolveBaseUrl()}${
|
|
7610
|
+
const response = await fetch(`${oauthResolveBaseUrl()}${path16}`, init);
|
|
7377
7611
|
if (response.status === 401) {
|
|
7378
7612
|
throw new Error(
|
|
7379
7613
|
"operator token rejected by remnic-server (HTTP 401). Update `server.authToken` or `REMNIC_AUTH_TOKEN` to match the running daemon."
|
|
@@ -7712,9 +7946,9 @@ async function cmdQuery(queryText, json, explain) {
|
|
|
7712
7946
|
}
|
|
7713
7947
|
initLogger2();
|
|
7714
7948
|
const configPath = resolveConfigPath();
|
|
7715
|
-
const raw =
|
|
7949
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
7716
7950
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
7717
|
-
const config =
|
|
7951
|
+
const config = parseConfig5(remnicCfg);
|
|
7718
7952
|
const orchestrator = new Orchestrator3(config);
|
|
7719
7953
|
await orchestrator.initialize();
|
|
7720
7954
|
const service = new EngramAccessService2(orchestrator);
|
|
@@ -7883,9 +8117,9 @@ async function cmdXray(rest) {
|
|
|
7883
8117
|
parseXrayCliOptions(rawQuery, options);
|
|
7884
8118
|
initLogger2();
|
|
7885
8119
|
const configPath = resolveConfigPath();
|
|
7886
|
-
const raw =
|
|
8120
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
7887
8121
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
7888
|
-
const config =
|
|
8122
|
+
const config = parseConfig5(remnicCfg);
|
|
7889
8123
|
const orchestrator = new Orchestrator3(config);
|
|
7890
8124
|
await orchestrator.initialize();
|
|
7891
8125
|
await orchestrator.deferredReady;
|
|
@@ -7906,9 +8140,9 @@ async function cmdXray(rest) {
|
|
|
7906
8140
|
async function cmdVersions(rest) {
|
|
7907
8141
|
initLogger2();
|
|
7908
8142
|
const configPath = resolveConfigPath();
|
|
7909
|
-
const raw =
|
|
8143
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
7910
8144
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
7911
|
-
const config =
|
|
8145
|
+
const config = parseConfig5(remnicCfg);
|
|
7912
8146
|
if (!config.versioningEnabled) {
|
|
7913
8147
|
console.error("Page versioning is disabled (versioningEnabled = false).");
|
|
7914
8148
|
process.exit(1);
|
|
@@ -7928,7 +8162,7 @@ async function cmdVersions(rest) {
|
|
|
7928
8162
|
console.error("Usage: remnic versions list <page-path>");
|
|
7929
8163
|
process.exit(1);
|
|
7930
8164
|
}
|
|
7931
|
-
const absPath =
|
|
8165
|
+
const absPath = path15.resolve(pagePath);
|
|
7932
8166
|
const history = await listVersions(absPath, versioningConfig, memDir);
|
|
7933
8167
|
if (json) {
|
|
7934
8168
|
console.log(JSON.stringify(history, null, 2));
|
|
@@ -7953,7 +8187,7 @@ async function cmdVersions(rest) {
|
|
|
7953
8187
|
console.error("Usage: remnic versions show <page-path> <version-id>");
|
|
7954
8188
|
process.exit(1);
|
|
7955
8189
|
}
|
|
7956
|
-
const absPath =
|
|
8190
|
+
const absPath = path15.resolve(pagePath);
|
|
7957
8191
|
try {
|
|
7958
8192
|
const content = await getVersion(absPath, versionId, versioningConfig, memDir);
|
|
7959
8193
|
console.log(content);
|
|
@@ -7971,7 +8205,7 @@ async function cmdVersions(rest) {
|
|
|
7971
8205
|
console.error("Usage: remnic versions diff <page-path> <v1> <v2>");
|
|
7972
8206
|
process.exit(1);
|
|
7973
8207
|
}
|
|
7974
|
-
const absPath =
|
|
8208
|
+
const absPath = path15.resolve(pagePath);
|
|
7975
8209
|
try {
|
|
7976
8210
|
const diffOutput = await diffVersions(absPath, v1, v2, versioningConfig, memDir);
|
|
7977
8211
|
console.log(diffOutput);
|
|
@@ -7988,7 +8222,7 @@ async function cmdVersions(rest) {
|
|
|
7988
8222
|
console.error("Usage: remnic versions revert <page-path> <version-id>");
|
|
7989
8223
|
process.exit(1);
|
|
7990
8224
|
}
|
|
7991
|
-
const absPath =
|
|
8225
|
+
const absPath = path15.resolve(pagePath);
|
|
7992
8226
|
try {
|
|
7993
8227
|
const version = await revertToVersion(absPath, versionId, versioningConfig, void 0, memDir);
|
|
7994
8228
|
if (json) {
|
|
@@ -8022,13 +8256,13 @@ Options:
|
|
|
8022
8256
|
async function cmdEnrich(rest) {
|
|
8023
8257
|
initLogger2();
|
|
8024
8258
|
const configPath = resolveConfigPath();
|
|
8025
|
-
const raw =
|
|
8259
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
8026
8260
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
8027
|
-
const config =
|
|
8261
|
+
const config = parseConfig5(remnicCfg);
|
|
8028
8262
|
const subcommand = rest[0];
|
|
8029
8263
|
if (subcommand === "audit") {
|
|
8030
8264
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
8031
|
-
const auditDir2 =
|
|
8265
|
+
const auditDir2 = path15.join(memoryDir2, "enrichment");
|
|
8032
8266
|
const sinceFlag = resolveFlag(rest.slice(1), "--since");
|
|
8033
8267
|
const entries = await readAuditLog(auditDir2, sinceFlag ?? void 0);
|
|
8034
8268
|
if (entries.length === 0) {
|
|
@@ -8153,7 +8387,7 @@ Registered providers:`);
|
|
|
8153
8387
|
return;
|
|
8154
8388
|
}
|
|
8155
8389
|
const memoryDir = expandTilde(config.memoryDir);
|
|
8156
|
-
const auditDir =
|
|
8390
|
+
const auditDir = path15.join(memoryDir, "enrichment");
|
|
8157
8391
|
let totalPersisted = 0;
|
|
8158
8392
|
for (const result of results) {
|
|
8159
8393
|
for (const candidate of result.acceptedCandidates) {
|
|
@@ -8267,9 +8501,9 @@ Shared with:
|
|
|
8267
8501
|
process.exit(1);
|
|
8268
8502
|
}
|
|
8269
8503
|
const configPath = resolveConfigPath();
|
|
8270
|
-
const raw =
|
|
8504
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
8271
8505
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
8272
|
-
const config =
|
|
8506
|
+
const config = parseConfig5(remnicCfg);
|
|
8273
8507
|
const memoryDir = expandTilde(
|
|
8274
8508
|
typeof memoryDirOverride === "string" && memoryDirOverride.length > 0 ? memoryDirOverride : config.memoryDir ?? resolveMemoryDir()
|
|
8275
8509
|
);
|
|
@@ -8284,9 +8518,9 @@ Shared with:
|
|
|
8284
8518
|
async function cmdExtensions(action, rest) {
|
|
8285
8519
|
initLogger2();
|
|
8286
8520
|
const configPath = resolveConfigPath();
|
|
8287
|
-
const raw =
|
|
8521
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
8288
8522
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
8289
|
-
const config =
|
|
8523
|
+
const config = parseConfig5(remnicCfg);
|
|
8290
8524
|
const root = resolveExtensionsRoot(config);
|
|
8291
8525
|
const noopLog = { warn: () => {
|
|
8292
8526
|
}, debug: () => {
|
|
@@ -8335,7 +8569,7 @@ Root: ${root}`);
|
|
|
8335
8569
|
const extensions = await discoverMemoryExtensions(root, warnLog);
|
|
8336
8570
|
let entries = [];
|
|
8337
8571
|
try {
|
|
8338
|
-
entries =
|
|
8572
|
+
entries = fs12.readdirSync(root);
|
|
8339
8573
|
} catch {
|
|
8340
8574
|
console.log(`Extensions root does not exist: ${root}`);
|
|
8341
8575
|
process.exitCode = 0;
|
|
@@ -8344,9 +8578,9 @@ Root: ${root}`);
|
|
|
8344
8578
|
const validNames = new Set(extensions.map((e) => e.name));
|
|
8345
8579
|
let errors = 0;
|
|
8346
8580
|
for (const entry of entries) {
|
|
8347
|
-
const entryPath =
|
|
8581
|
+
const entryPath = path15.join(root, entry);
|
|
8348
8582
|
try {
|
|
8349
|
-
if (!
|
|
8583
|
+
if (!fs12.statSync(entryPath).isDirectory()) continue;
|
|
8350
8584
|
} catch {
|
|
8351
8585
|
continue;
|
|
8352
8586
|
}
|
|
@@ -8378,9 +8612,9 @@ Root: ${root}`);
|
|
|
8378
8612
|
async function cmdBriefing(rest) {
|
|
8379
8613
|
initLogger2();
|
|
8380
8614
|
const configPath = resolveConfigPath();
|
|
8381
|
-
const raw =
|
|
8615
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
8382
8616
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
8383
|
-
const config =
|
|
8617
|
+
const config = parseConfig5(remnicCfg);
|
|
8384
8618
|
if (!config.briefing.enabled) {
|
|
8385
8619
|
console.error("Briefing is disabled in config (briefing.enabled = false).");
|
|
8386
8620
|
process.exit(1);
|
|
@@ -8458,10 +8692,10 @@ async function cmdBriefing(rest) {
|
|
|
8458
8692
|
if (save) {
|
|
8459
8693
|
try {
|
|
8460
8694
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
8461
|
-
|
|
8695
|
+
fs12.mkdirSync(saveDir, { recursive: true });
|
|
8462
8696
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
8463
|
-
const filePath =
|
|
8464
|
-
|
|
8697
|
+
const filePath = path15.join(saveDir, filename);
|
|
8698
|
+
fs12.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
8465
8699
|
console.error(`Saved briefing: ${filePath}`);
|
|
8466
8700
|
} catch (err) {
|
|
8467
8701
|
console.error(`Failed to save briefing: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -8479,7 +8713,7 @@ async function cmdDoctor() {
|
|
|
8479
8713
|
detail: `${nodeVersion} (requires >= 22.12.0)`
|
|
8480
8714
|
});
|
|
8481
8715
|
const configPath = resolveConfigPath();
|
|
8482
|
-
const configExists =
|
|
8716
|
+
const configExists = fs12.existsSync(configPath);
|
|
8483
8717
|
checks.push({ name: "Config file", ok: configExists, detail: configPath });
|
|
8484
8718
|
let standaloneConfig;
|
|
8485
8719
|
let standaloneConfigError;
|
|
@@ -8487,11 +8721,11 @@ async function cmdDoctor() {
|
|
|
8487
8721
|
let configuredNs = { invalid: false };
|
|
8488
8722
|
if (configExists) {
|
|
8489
8723
|
try {
|
|
8490
|
-
const raw = JSON.parse(
|
|
8724
|
+
const raw = JSON.parse(fs12.readFileSync(configPath, "utf8"));
|
|
8491
8725
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
8492
8726
|
standaloneOpenaiApiKeyExplicitlyFalse = isOpenaiApiKeyDisabled(remnicCfg.openaiApiKey);
|
|
8493
8727
|
configuredNs = readConfiguredNamespace(remnicCfg);
|
|
8494
|
-
standaloneConfig =
|
|
8728
|
+
standaloneConfig = parseConfig5(remnicCfg);
|
|
8495
8729
|
} catch (err) {
|
|
8496
8730
|
standaloneConfigError = err instanceof Error ? err.message : String(err);
|
|
8497
8731
|
}
|
|
@@ -8500,10 +8734,10 @@ async function cmdDoctor() {
|
|
|
8500
8734
|
try {
|
|
8501
8735
|
memoryDir = resolveMemoryDir();
|
|
8502
8736
|
} catch {
|
|
8503
|
-
memoryDir =
|
|
8737
|
+
memoryDir = parseConfig5({}).memoryDir;
|
|
8504
8738
|
}
|
|
8505
8739
|
try {
|
|
8506
|
-
|
|
8740
|
+
fs12.mkdirSync(memoryDir, { recursive: true });
|
|
8507
8741
|
checks.push({ name: "Memory directory", ok: true, detail: memoryDir });
|
|
8508
8742
|
} catch {
|
|
8509
8743
|
checks.push({ name: "Memory directory", ok: false, detail: `cannot create ${memoryDir}` });
|
|
@@ -8532,7 +8766,7 @@ async function cmdDoctor() {
|
|
|
8532
8766
|
});
|
|
8533
8767
|
if (nsPolicyCheck) checks.push(nsPolicyCheck);
|
|
8534
8768
|
const openclawConfigPath = resolveOpenclawConfigPath();
|
|
8535
|
-
const openclawConfigExists =
|
|
8769
|
+
const openclawConfigExists = fs12.existsSync(openclawConfigPath);
|
|
8536
8770
|
let openclawConfig = {};
|
|
8537
8771
|
let openclawConfigValid = false;
|
|
8538
8772
|
let openclawPluginModeConfigured = false;
|
|
@@ -8540,7 +8774,7 @@ async function cmdDoctor() {
|
|
|
8540
8774
|
let activeOpenclawEntryConfig = null;
|
|
8541
8775
|
if (openclawConfigExists) {
|
|
8542
8776
|
try {
|
|
8543
|
-
const parsed = JSON.parse(
|
|
8777
|
+
const parsed = JSON.parse(fs12.readFileSync(openclawConfigPath, "utf-8"));
|
|
8544
8778
|
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
8545
8779
|
openclawConfig = parsed;
|
|
8546
8780
|
openclawConfigValid = true;
|
|
@@ -8616,13 +8850,13 @@ async function cmdDoctor() {
|
|
|
8616
8850
|
const rawMemoryDir = entryConfig?.memoryDir;
|
|
8617
8851
|
const configuredMemoryDir = typeof rawMemoryDir === "string" ? rawMemoryDir : void 0;
|
|
8618
8852
|
if (configuredMemoryDir) {
|
|
8619
|
-
const resolvedMemDir =
|
|
8853
|
+
const resolvedMemDir = path15.resolve(expandTilde(configuredMemoryDir));
|
|
8620
8854
|
let memDirOk = false;
|
|
8621
8855
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
8622
8856
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
8623
|
-
if (
|
|
8857
|
+
if (fs12.existsSync(resolvedMemDir)) {
|
|
8624
8858
|
try {
|
|
8625
|
-
const stat =
|
|
8859
|
+
const stat = fs12.statSync(resolvedMemDir);
|
|
8626
8860
|
if (stat.isDirectory()) {
|
|
8627
8861
|
memDirOk = true;
|
|
8628
8862
|
memDirDetail = resolvedMemDir;
|
|
@@ -8764,12 +8998,12 @@ async function cmdDoctor() {
|
|
|
8764
8998
|
}
|
|
8765
8999
|
function cmdConfig() {
|
|
8766
9000
|
const configPath = resolveConfigPath();
|
|
8767
|
-
if (!
|
|
9001
|
+
if (!fs12.existsSync(configPath)) {
|
|
8768
9002
|
console.log("No config file found. Run `remnic init` to create one.");
|
|
8769
9003
|
return;
|
|
8770
9004
|
}
|
|
8771
9005
|
console.log(`Config: ${configPath}`);
|
|
8772
|
-
const rawConfig =
|
|
9006
|
+
const rawConfig = fs12.readFileSync(configPath, "utf8");
|
|
8773
9007
|
const redacted = rawConfig.replace(
|
|
8774
9008
|
/("(?:openaiApiKey|localLlmApiKey|authToken|apiKey|remoteSearchApiKey|meilisearchApiKey|opikApiKey)"\s*:\s*")([^"]*)(")/g,
|
|
8775
9009
|
"$1[REDACTED]$3"
|
|
@@ -8816,7 +9050,7 @@ async function cmdMigrate(json, rollback) {
|
|
|
8816
9050
|
console.log(` Rollback: ${result.rollbackCommand}`);
|
|
8817
9051
|
}
|
|
8818
9052
|
function cmdOnboard(dirPath, json) {
|
|
8819
|
-
const directory =
|
|
9053
|
+
const directory = path15.resolve(dirPath || process.cwd());
|
|
8820
9054
|
const result = onboard({ directory });
|
|
8821
9055
|
if (json) {
|
|
8822
9056
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -8835,7 +9069,7 @@ Suggested namespace: ${result.plan.suggestedNamespace}`);
|
|
|
8835
9069
|
async function cmdCurate(targetPath, json) {
|
|
8836
9070
|
const memoryDir = resolveMemoryDir();
|
|
8837
9071
|
const result = await curate({
|
|
8838
|
-
targetPath:
|
|
9072
|
+
targetPath: path15.resolve(targetPath),
|
|
8839
9073
|
memoryDir,
|
|
8840
9074
|
source: "curation",
|
|
8841
9075
|
checkDuplicates: true,
|
|
@@ -8877,9 +9111,9 @@ async function cmdReview(action, rest) {
|
|
|
8877
9111
|
const configPath = resolveConfigPath();
|
|
8878
9112
|
let tombstonesConfig = null;
|
|
8879
9113
|
try {
|
|
8880
|
-
const rawCfg =
|
|
9114
|
+
const rawCfg = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
8881
9115
|
const remnicCfg = resolveRemnicConfigRecord4(rawCfg);
|
|
8882
|
-
const config =
|
|
9116
|
+
const config = parseConfig5(remnicCfg);
|
|
8883
9117
|
tombstonesConfig = {
|
|
8884
9118
|
enabled: config.tombstonesEnabled,
|
|
8885
9119
|
semanticMatch: config.tombstonesSemanticMatch,
|
|
@@ -8965,7 +9199,7 @@ async function cmdSync(action, rest, json) {
|
|
|
8965
9199
|
}
|
|
8966
9200
|
function localOfflineSourceId(memoryDir) {
|
|
8967
9201
|
const host = os.hostname() || "unknown-host";
|
|
8968
|
-
const dirHash = createHash2("sha256").update(
|
|
9202
|
+
const dirHash = createHash2("sha256").update(path15.resolve(memoryDir)).digest("hex").slice(0, 16);
|
|
8969
9203
|
return `remnic-local:${host}:${dirHash}`;
|
|
8970
9204
|
}
|
|
8971
9205
|
function normalizeOfflineRemoteUrl(raw) {
|
|
@@ -9363,10 +9597,10 @@ var OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX = 3;
|
|
|
9363
9597
|
var OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS = 250;
|
|
9364
9598
|
var OfflineRemoteFileChangedError = class extends Error {
|
|
9365
9599
|
path;
|
|
9366
|
-
constructor(
|
|
9367
|
-
super(`remote file changed while fetching offline content: ${
|
|
9600
|
+
constructor(path16) {
|
|
9601
|
+
super(`remote file changed while fetching offline content: ${path16}`);
|
|
9368
9602
|
this.name = "OfflineRemoteFileChangedError";
|
|
9369
|
-
this.path =
|
|
9603
|
+
this.path = path16;
|
|
9370
9604
|
}
|
|
9371
9605
|
};
|
|
9372
9606
|
function isOfflineRemoteFileChangedError(error) {
|
|
@@ -9557,10 +9791,10 @@ function offlineDirectPushFiles(options) {
|
|
|
9557
9791
|
}).sort((left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path));
|
|
9558
9792
|
}
|
|
9559
9793
|
function resolveOfflineDirectHydrationPath(memoryDir, relPath) {
|
|
9560
|
-
const base =
|
|
9561
|
-
const target =
|
|
9562
|
-
const relative =
|
|
9563
|
-
if (relative === "" || relative === ".." || relative.startsWith(`..${
|
|
9794
|
+
const base = path15.resolve(memoryDir);
|
|
9795
|
+
const target = path15.resolve(base, relPath);
|
|
9796
|
+
const relative = path15.relative(base, target);
|
|
9797
|
+
if (relative === "" || relative === ".." || relative.startsWith(`..${path15.sep}`) || path15.isAbsolute(relative)) {
|
|
9564
9798
|
throw new Error(`offline sync direct hydration path escapes memory dir: ${relPath}`);
|
|
9565
9799
|
}
|
|
9566
9800
|
return target;
|
|
@@ -9630,13 +9864,13 @@ async function pushOfflineFileContent(args) {
|
|
|
9630
9864
|
}
|
|
9631
9865
|
async function pushOfflineFileContentFromChunkReader(args) {
|
|
9632
9866
|
const filePath = resolveOfflineDirectHydrationPath(args.memoryDir, args.file.path);
|
|
9633
|
-
const stat =
|
|
9867
|
+
const stat = fs12.statSync(filePath);
|
|
9634
9868
|
if (stat.mtimeMs !== args.file.mtimeMs) {
|
|
9635
9869
|
throw new Error(`local file changed while pushing offline content: ${args.file.path}`);
|
|
9636
9870
|
}
|
|
9637
9871
|
const hash = createHash2("sha256");
|
|
9638
9872
|
const chunks = args.readFileChunks({
|
|
9639
|
-
root:
|
|
9873
|
+
root: path15.resolve(args.memoryDir),
|
|
9640
9874
|
path: args.file.path,
|
|
9641
9875
|
filePath,
|
|
9642
9876
|
chunkSize: OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES
|
|
@@ -10121,7 +10355,7 @@ function advanceOfflineBaseFilesForSuccessfulPush(options) {
|
|
|
10121
10355
|
return [...next.values()].sort((left, right) => left.path.localeCompare(right.path));
|
|
10122
10356
|
}
|
|
10123
10357
|
async function runOfflineSyncOnce(options) {
|
|
10124
|
-
|
|
10358
|
+
fs12.mkdirSync(options.memoryDir, { recursive: true });
|
|
10125
10359
|
let activeStatePath = options.statePath;
|
|
10126
10360
|
let priorState = await readOfflineSyncState(activeStatePath);
|
|
10127
10361
|
let syncNamespace = options.namespace ?? priorState?.namespace;
|
|
@@ -10175,7 +10409,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
10175
10409
|
options.secureStoreEncryptOnWrite ?? true
|
|
10176
10410
|
)).drainPendingMemoryLifecycleEventsForSyncAt(ledgerPath)
|
|
10177
10411
|
);
|
|
10178
|
-
const currentSnapshotForPush = await
|
|
10412
|
+
const currentSnapshotForPush = await buildOfflineSyncSnapshotFromBase2({
|
|
10179
10413
|
root: options.memoryDir,
|
|
10180
10414
|
sourceId: localSourceId,
|
|
10181
10415
|
baseFiles,
|
|
@@ -10324,7 +10558,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
10324
10558
|
if (pushed) return writePartialPushState(error);
|
|
10325
10559
|
throw error;
|
|
10326
10560
|
}
|
|
10327
|
-
let currentSnapshotForChangeset = directPushedPaths.size > 0 ? await
|
|
10561
|
+
let currentSnapshotForChangeset = directPushedPaths.size > 0 ? await buildOfflineSyncSnapshotFromBase2({
|
|
10328
10562
|
root: options.memoryDir,
|
|
10329
10563
|
sourceId: localSourceId,
|
|
10330
10564
|
baseFiles,
|
|
@@ -10377,7 +10611,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
10377
10611
|
}
|
|
10378
10612
|
changesetRetryCount += 1;
|
|
10379
10613
|
directPushDeferredPaths.add(changedPath);
|
|
10380
|
-
currentSnapshotForChangeset = await
|
|
10614
|
+
currentSnapshotForChangeset = await buildOfflineSyncSnapshotFromBase2({
|
|
10381
10615
|
root: options.memoryDir,
|
|
10382
10616
|
sourceId: localSourceId,
|
|
10383
10617
|
baseFiles,
|
|
@@ -10432,7 +10666,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
10432
10666
|
}
|
|
10433
10667
|
let currentSnapshot;
|
|
10434
10668
|
try {
|
|
10435
|
-
currentSnapshot = await
|
|
10669
|
+
currentSnapshot = await buildOfflineSyncSnapshotFromBase2({
|
|
10436
10670
|
root: options.memoryDir,
|
|
10437
10671
|
sourceId: localSourceId,
|
|
10438
10672
|
baseFiles,
|
|
@@ -10495,7 +10729,7 @@ async function runOfflineSyncOnce(options) {
|
|
|
10495
10729
|
resolvedNamespace: resolvedOfflineSnapshotNamespace(remoteSnapshotMetadata, syncNamespace),
|
|
10496
10730
|
remoteFileCount: remoteSnapshotMetadata.files.length
|
|
10497
10731
|
};
|
|
10498
|
-
const buildCurrentSnapshotForApply = async () =>
|
|
10732
|
+
const buildCurrentSnapshotForApply = async () => buildOfflineSyncSnapshotFromBase2({
|
|
10499
10733
|
root: options.memoryDir,
|
|
10500
10734
|
sourceId: localSourceId,
|
|
10501
10735
|
baseFiles,
|
|
@@ -10739,7 +10973,7 @@ Environment fallbacks:
|
|
|
10739
10973
|
REMNIC_OFFLINE_REMOTE_URL, REMNIC_OFFLINE_TOKEN, REMNIC_AUTH_TOKEN`);
|
|
10740
10974
|
return;
|
|
10741
10975
|
}
|
|
10742
|
-
const memoryDir =
|
|
10976
|
+
const memoryDir = path15.resolve(expandTilde(resolveRequiredValueFlag(rest, "--memory-dir") ?? resolveMemoryDir()));
|
|
10743
10977
|
const namespace = resolveRequiredValueFlag(rest, "--namespace");
|
|
10744
10978
|
const includeTranscripts = !hasFlag(rest, "--no-transcripts");
|
|
10745
10979
|
const stateOverride = resolveRequiredValueFlag(rest, "--state");
|
|
@@ -10747,7 +10981,7 @@ Environment fallbacks:
|
|
|
10747
10981
|
const configPath = resolveConfigPath();
|
|
10748
10982
|
let config;
|
|
10749
10983
|
try {
|
|
10750
|
-
const rawConfig =
|
|
10984
|
+
const rawConfig = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
10751
10985
|
config = parseConfigQuietly(pickOfflineConfigRecord(rawConfig));
|
|
10752
10986
|
} catch {
|
|
10753
10987
|
throw new Error(
|
|
@@ -10759,10 +10993,10 @@ Environment fallbacks:
|
|
|
10759
10993
|
const needsRemote = action === "prepare" || action === "sync" || action === "watch";
|
|
10760
10994
|
const remoteUrl = needsRemote ? resolveOfflineRemoteUrl(rest) : resolveOptionalOfflineRemoteUrl(rest);
|
|
10761
10995
|
const token = needsRemote ? resolveOfflineToken(rest) : void 0;
|
|
10762
|
-
const statePath = statePathExplicit ?
|
|
10996
|
+
const statePath = statePathExplicit ? path15.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
10763
10997
|
if (action === "prepare") {
|
|
10764
10998
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
10765
|
-
|
|
10999
|
+
fs12.mkdirSync(memoryDir, { recursive: true });
|
|
10766
11000
|
const remoteSnapshot = await fetchOfflineSnapshot({
|
|
10767
11001
|
remoteUrl,
|
|
10768
11002
|
token,
|
|
@@ -10860,7 +11094,7 @@ Environment fallbacks:
|
|
|
10860
11094
|
return;
|
|
10861
11095
|
}
|
|
10862
11096
|
if (action === "status") {
|
|
10863
|
-
|
|
11097
|
+
fs12.mkdirSync(memoryDir, { recursive: true });
|
|
10864
11098
|
const state = statePath ? await readOfflineSyncState(statePath) : null;
|
|
10865
11099
|
if (state && remoteUrl && statePath) {
|
|
10866
11100
|
assertOfflineStateMatches({
|
|
@@ -10940,11 +11174,11 @@ Environment fallbacks:
|
|
|
10940
11174
|
failures: result.largeFilePushFailures
|
|
10941
11175
|
});
|
|
10942
11176
|
largeFileFailureCounts = advanced.counts;
|
|
10943
|
-
for (const
|
|
10944
|
-
if (skippedLargeFiles.has(
|
|
10945
|
-
skippedLargeFiles.add(
|
|
11177
|
+
for (const path16 of advanced.newlySkipped) {
|
|
11178
|
+
if (skippedLargeFiles.has(path16)) continue;
|
|
11179
|
+
skippedLargeFiles.add(path16);
|
|
10946
11180
|
console.warn(
|
|
10947
|
-
`offline sync: permanently skipping ${
|
|
11181
|
+
`offline sync: permanently skipping ${path16} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
10948
11182
|
);
|
|
10949
11183
|
}
|
|
10950
11184
|
const pulled = result.pull ? result.pull.upserted + result.pull.deleted : 0;
|
|
@@ -10959,11 +11193,11 @@ Environment fallbacks:
|
|
|
10959
11193
|
failures: error.failures
|
|
10960
11194
|
});
|
|
10961
11195
|
largeFileFailureCounts = advanced.counts;
|
|
10962
|
-
for (const
|
|
10963
|
-
if (skippedLargeFiles.has(
|
|
10964
|
-
skippedLargeFiles.add(
|
|
11196
|
+
for (const path16 of advanced.newlySkipped) {
|
|
11197
|
+
if (skippedLargeFiles.has(path16)) continue;
|
|
11198
|
+
skippedLargeFiles.add(path16);
|
|
10965
11199
|
console.warn(
|
|
10966
|
-
`offline sync: permanently skipping ${
|
|
11200
|
+
`offline sync: permanently skipping ${path16} after ${OFFLINE_LARGE_FILE_SKIP_AFTER_FAILURES} failed large-file pushes for this watcher process (see issue #1786; use --exclude or offlineSyncExcludes to silence permanently)`
|
|
10967
11201
|
);
|
|
10968
11202
|
}
|
|
10969
11203
|
}
|
|
@@ -10998,7 +11232,7 @@ function cmdDedup(json) {
|
|
|
10998
11232
|
function readInstalledConnectorConfig(configPath, fallback) {
|
|
10999
11233
|
if (!configPath) return fallback;
|
|
11000
11234
|
try {
|
|
11001
|
-
const parsed = JSON.parse(
|
|
11235
|
+
const parsed = JSON.parse(fs12.readFileSync(configPath, "utf8"));
|
|
11002
11236
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return fallback;
|
|
11003
11237
|
const { token: _token, ...config } = parsed;
|
|
11004
11238
|
return config;
|
|
@@ -11104,7 +11338,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
11104
11338
|
const connectorDaemonUrl = typeof effectiveConnectorConfig.remnicDaemonUrl === "string" && effectiveConnectorConfig.remnicDaemonUrl.trim().length > 0 ? effectiveConnectorConfig.remnicDaemonUrl.trim() : void 0;
|
|
11105
11339
|
const pubResult = await pub.publish({
|
|
11106
11340
|
config: { memoryDir, namespace: connectorNamespace, daemonUrl: connectorDaemonUrl },
|
|
11107
|
-
skillsRoot:
|
|
11341
|
+
skillsRoot: path15.join(memoryDir, "skills"),
|
|
11108
11342
|
rollbackTokenEntry: preInstallTokenEntry,
|
|
11109
11343
|
log: { info: console.log, warn: console.warn, error: console.error }
|
|
11110
11344
|
});
|
|
@@ -11176,7 +11410,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
11176
11410
|
const pub = factory();
|
|
11177
11411
|
const available = await pub.isHostAvailable();
|
|
11178
11412
|
const extRoot = available ? await pub.resolveExtensionRoot() : "(host not installed)";
|
|
11179
|
-
const extensionExists = available && extRoot ?
|
|
11413
|
+
const extensionExists = available && extRoot ? fs12.existsSync(extRoot) : false;
|
|
11180
11414
|
publisherChecks.push({
|
|
11181
11415
|
name: `Publisher: ${targetHostId}`,
|
|
11182
11416
|
ok: !available || extensionExists,
|
|
@@ -11250,7 +11484,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
11250
11484
|
let connectorsCfg;
|
|
11251
11485
|
const configPath = resolveConfigPath();
|
|
11252
11486
|
try {
|
|
11253
|
-
const raw =
|
|
11487
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
11254
11488
|
connectorsCfg = parseConfigQuietly(raw).connectors;
|
|
11255
11489
|
} catch {
|
|
11256
11490
|
process.stderr.write(
|
|
@@ -11326,9 +11560,9 @@ async function cmdConnectors(action, rest, json) {
|
|
|
11326
11560
|
}
|
|
11327
11561
|
initLogger2();
|
|
11328
11562
|
const configPath = resolveConfigPath();
|
|
11329
|
-
const raw =
|
|
11563
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
11330
11564
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
11331
|
-
const config =
|
|
11565
|
+
const config = parseConfig5(remnicCfg);
|
|
11332
11566
|
const orchestrator = new Orchestrator3(config);
|
|
11333
11567
|
try {
|
|
11334
11568
|
await orchestrator.initialize();
|
|
@@ -11451,9 +11685,9 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
11451
11685
|
console.error(`connectors marketplace: ${err instanceof Error ? err.message : String(err)}`);
|
|
11452
11686
|
process.exit(1);
|
|
11453
11687
|
}
|
|
11454
|
-
const rawConfig =
|
|
11688
|
+
const rawConfig = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
11455
11689
|
const pluginConfig = resolveRemnicConfigRecord4(rawConfig);
|
|
11456
|
-
const config =
|
|
11690
|
+
const config = parseConfig5(pluginConfig);
|
|
11457
11691
|
if (subAction === "generate") {
|
|
11458
11692
|
let outputDir;
|
|
11459
11693
|
try {
|
|
@@ -11464,22 +11698,22 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
11464
11698
|
}
|
|
11465
11699
|
const manifest = generateMarketplaceManifest();
|
|
11466
11700
|
await writeMarketplaceManifest(outputDir, manifest);
|
|
11467
|
-
const outPath =
|
|
11701
|
+
const outPath = path15.join(outputDir, "marketplace.json");
|
|
11468
11702
|
if (json) {
|
|
11469
11703
|
console.log(JSON.stringify({ status: "generated", path: outPath }, null, 2));
|
|
11470
11704
|
} else {
|
|
11471
11705
|
console.log(`Generated marketplace.json at ${outPath}`);
|
|
11472
11706
|
}
|
|
11473
11707
|
} else if (subAction === "validate") {
|
|
11474
|
-
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ??
|
|
11475
|
-
const resolved =
|
|
11476
|
-
if (!
|
|
11708
|
+
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path15.join(process.cwd(), "marketplace.json");
|
|
11709
|
+
const resolved = path15.resolve(targetPath);
|
|
11710
|
+
if (!fs12.existsSync(resolved)) {
|
|
11477
11711
|
console.error(`File not found: ${resolved}`);
|
|
11478
11712
|
process.exit(1);
|
|
11479
11713
|
}
|
|
11480
11714
|
let parsed;
|
|
11481
11715
|
try {
|
|
11482
|
-
parsed = JSON.parse(
|
|
11716
|
+
parsed = JSON.parse(fs12.readFileSync(resolved, "utf8"));
|
|
11483
11717
|
} catch {
|
|
11484
11718
|
console.error(`Invalid JSON in ${resolved}`);
|
|
11485
11719
|
process.exit(1);
|
|
@@ -11680,9 +11914,9 @@ async function cmdSpace(action, rest, json) {
|
|
|
11680
11914
|
async function cmdLegacyBenchmark(action, rest, json) {
|
|
11681
11915
|
initLogger2();
|
|
11682
11916
|
const configPath = resolveConfigPath();
|
|
11683
|
-
const raw =
|
|
11917
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
11684
11918
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
11685
|
-
const config =
|
|
11919
|
+
const config = parseConfig5(remnicCfg);
|
|
11686
11920
|
const orchestrator = new Orchestrator3(config);
|
|
11687
11921
|
const service = new EngramAccessService2(orchestrator);
|
|
11688
11922
|
const { runBenchSuite, loadBaseline, checkRegression } = await loadBenchModule();
|
|
@@ -11880,7 +12114,7 @@ async function cmdBench(rest) {
|
|
|
11880
12114
|
}
|
|
11881
12115
|
const completeCount = prevStatus.benchmarks.filter((b) => b.status === "complete").length;
|
|
11882
12116
|
const failedCount = prevStatus.benchmarks.filter((b) => b.status === "failed").length;
|
|
11883
|
-
printBenchStatusLine(parsed.json, `Resuming from: ${
|
|
12117
|
+
printBenchStatusLine(parsed.json, `Resuming from: ${path15.basename(latestStatusPath)}`);
|
|
11884
12118
|
printBenchStatusLine(parsed.json, ` Previous run: ${prevStatus.startedAt}`);
|
|
11885
12119
|
printBenchStatusLine(parsed.json, ` Benchmarks: ${prevStatus.benchmarks.length} total, ${completeCount} complete, ${failedCount} failed`);
|
|
11886
12120
|
const before = selectedBenchmarks.length;
|
|
@@ -12048,9 +12282,9 @@ Options:
|
|
|
12048
12282
|
);
|
|
12049
12283
|
process.exit(1);
|
|
12050
12284
|
} else {
|
|
12051
|
-
fixturePath =
|
|
12285
|
+
fixturePath = path15.resolve(expandTilde(fixturePathRaw));
|
|
12052
12286
|
}
|
|
12053
|
-
const outPath =
|
|
12287
|
+
const outPath = path15.resolve(expandTilde(outPathRaw));
|
|
12054
12288
|
const benchModule = await loadBenchModule();
|
|
12055
12289
|
const runner = benchModule.runProceduralAblationCli;
|
|
12056
12290
|
if (typeof runner !== "function") {
|
|
@@ -12069,7 +12303,7 @@ Options:
|
|
|
12069
12303
|
);
|
|
12070
12304
|
console.log(`wrote ${outPath}`);
|
|
12071
12305
|
}
|
|
12072
|
-
var LOGS_DIR =
|
|
12306
|
+
var LOGS_DIR = path15.join(PID_DIR, "logs");
|
|
12073
12307
|
var LAUNCHD_PLIST_PATHS = launchdPlistPaths(resolveHomeDir());
|
|
12074
12308
|
var [LAUNCHD_PLIST_PATH] = LAUNCHD_PLIST_PATHS;
|
|
12075
12309
|
var SYSTEMD_UNIT_PATHS = systemdUnitPaths(resolveHomeDir());
|
|
@@ -12083,7 +12317,7 @@ function readPid() {
|
|
|
12083
12317
|
function inferPort() {
|
|
12084
12318
|
try {
|
|
12085
12319
|
const configPath = resolveConfigPath();
|
|
12086
|
-
const raw = JSON.parse(
|
|
12320
|
+
const raw = JSON.parse(fs12.readFileSync(configPath, "utf8"));
|
|
12087
12321
|
return raw.server?.port ?? 4318;
|
|
12088
12322
|
} catch {
|
|
12089
12323
|
return 4318;
|
|
@@ -12146,7 +12380,7 @@ function selectLaunchdInspection(openclawPluginModeConfigured) {
|
|
|
12146
12380
|
for (const plistPath of LAUNCHD_PLIST_PATHS.slice(1)) {
|
|
12147
12381
|
const legacy = inspectLaunchdPlist(plistPath);
|
|
12148
12382
|
if (!legacy.installed) continue;
|
|
12149
|
-
const label =
|
|
12383
|
+
const label = path15.basename(plistPath, ".plist");
|
|
12150
12384
|
return legacy.ok ? {
|
|
12151
12385
|
...legacy,
|
|
12152
12386
|
warn: true,
|
|
@@ -12178,13 +12412,13 @@ function daemonInstall() {
|
|
|
12178
12412
|
process.exit(1);
|
|
12179
12413
|
}
|
|
12180
12414
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
12181
|
-
|
|
12415
|
+
fs12.mkdirSync(LOGS_DIR, { recursive: true });
|
|
12182
12416
|
if (isMacOS()) {
|
|
12183
|
-
const templatePath =
|
|
12184
|
-
const template =
|
|
12417
|
+
const templatePath = path15.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
12418
|
+
const template = fs12.readFileSync(templatePath, "utf8");
|
|
12185
12419
|
const plist = renderTemplate(template, vars);
|
|
12186
|
-
|
|
12187
|
-
|
|
12420
|
+
fs12.mkdirSync(path15.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
12421
|
+
fs12.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
12188
12422
|
try {
|
|
12189
12423
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
12190
12424
|
} catch (err) {
|
|
@@ -12200,11 +12434,11 @@ function daemonInstall() {
|
|
|
12200
12434
|
console.log(` RunAtLoad: true, KeepAlive: true`);
|
|
12201
12435
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
12202
12436
|
} else if (isLinux()) {
|
|
12203
|
-
const templatePath =
|
|
12204
|
-
const template =
|
|
12437
|
+
const templatePath = path15.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
12438
|
+
const template = fs12.readFileSync(templatePath, "utf8");
|
|
12205
12439
|
const unit = renderTemplate(template, vars);
|
|
12206
|
-
|
|
12207
|
-
|
|
12440
|
+
fs12.mkdirSync(path15.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
12441
|
+
fs12.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
12208
12442
|
try {
|
|
12209
12443
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
12210
12444
|
} catch (err) {
|
|
@@ -12240,7 +12474,7 @@ function daemonUninstall() {
|
|
|
12240
12474
|
} catch {
|
|
12241
12475
|
}
|
|
12242
12476
|
try {
|
|
12243
|
-
|
|
12477
|
+
fs12.unlinkSync(plistPath);
|
|
12244
12478
|
removed = true;
|
|
12245
12479
|
console.log(`Removed launchd service: ${plistPath}`);
|
|
12246
12480
|
} catch {
|
|
@@ -12260,7 +12494,7 @@ function daemonUninstall() {
|
|
|
12260
12494
|
let removed = false;
|
|
12261
12495
|
for (const unitPath of SYSTEMD_UNIT_PATHS) {
|
|
12262
12496
|
try {
|
|
12263
|
-
|
|
12497
|
+
fs12.unlinkSync(unitPath);
|
|
12264
12498
|
removed = true;
|
|
12265
12499
|
console.log(`Removed systemd service: ${unitPath}`);
|
|
12266
12500
|
} catch {
|
|
@@ -12327,13 +12561,13 @@ async function daemonStatus() {
|
|
|
12327
12561
|
console.log(` Port: ${port}`);
|
|
12328
12562
|
console.log(` Service: ${serviceInstalled ? "installed" : "not installed"}`);
|
|
12329
12563
|
console.log(` Platform: ${process.platform}`);
|
|
12330
|
-
console.log(` PID file: ${
|
|
12331
|
-
console.log(` Log file: ${
|
|
12564
|
+
console.log(` PID file: ${fs12.existsSync(PID_FILE) ? PID_FILE : LEGACY_PID_FILE}`);
|
|
12565
|
+
console.log(` Log file: ${fs12.existsSync(LOG_FILE) ? LOG_FILE : LEGACY_LOG_FILE}`);
|
|
12332
12566
|
try {
|
|
12333
12567
|
const configPath = resolveConfigPath();
|
|
12334
|
-
const raw =
|
|
12568
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
12335
12569
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
12336
|
-
const config =
|
|
12570
|
+
const config = parseConfig5(remnicCfg);
|
|
12337
12571
|
const extRoot = resolveExtensionsRoot(config);
|
|
12338
12572
|
const noopLog = { warn: () => {
|
|
12339
12573
|
}, debug: () => {
|
|
@@ -12372,9 +12606,9 @@ function daemonStart() {
|
|
|
12372
12606
|
return;
|
|
12373
12607
|
}
|
|
12374
12608
|
}
|
|
12375
|
-
|
|
12376
|
-
|
|
12377
|
-
const logStream =
|
|
12609
|
+
fs12.mkdirSync(PID_DIR, { recursive: true });
|
|
12610
|
+
fs12.mkdirSync(LOGS_DIR, { recursive: true });
|
|
12611
|
+
const logStream = fs12.openSync(LOG_FILE, "a");
|
|
12378
12612
|
const serverBin = resolveServerBin();
|
|
12379
12613
|
const isSource = serverBin.endsWith(".ts");
|
|
12380
12614
|
let cmd;
|
|
@@ -12396,7 +12630,7 @@ function daemonStart() {
|
|
|
12396
12630
|
}
|
|
12397
12631
|
});
|
|
12398
12632
|
child.unref();
|
|
12399
|
-
|
|
12633
|
+
fs12.writeFileSync(PID_FILE, String(child.pid));
|
|
12400
12634
|
console.log(`Started remnic server (pid ${child.pid})`);
|
|
12401
12635
|
console.log(` Log: ${LOG_FILE}`);
|
|
12402
12636
|
}
|
|
@@ -12430,11 +12664,11 @@ function daemonStop() {
|
|
|
12430
12664
|
console.log("Process not found (cleaning up PID file)");
|
|
12431
12665
|
}
|
|
12432
12666
|
try {
|
|
12433
|
-
|
|
12667
|
+
fs12.unlinkSync(PID_FILE);
|
|
12434
12668
|
} catch {
|
|
12435
12669
|
}
|
|
12436
12670
|
try {
|
|
12437
|
-
|
|
12671
|
+
fs12.unlinkSync(LEGACY_PID_FILE);
|
|
12438
12672
|
} catch {
|
|
12439
12673
|
}
|
|
12440
12674
|
}
|
|
@@ -12562,9 +12796,9 @@ async function promptYesNo(question, defaultYes = true) {
|
|
|
12562
12796
|
async function cmdBinary(rest) {
|
|
12563
12797
|
initLogger2();
|
|
12564
12798
|
const configPath = resolveConfigPath();
|
|
12565
|
-
const raw =
|
|
12799
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
12566
12800
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
12567
|
-
const config =
|
|
12801
|
+
const config = parseConfig5(remnicCfg);
|
|
12568
12802
|
const memoryDir = resolveMemoryDir();
|
|
12569
12803
|
const blConfig = {
|
|
12570
12804
|
enabled: config.binaryLifecycleEnabled,
|
|
@@ -12682,7 +12916,7 @@ Clean complete: cleaned=${result.cleaned}`
|
|
|
12682
12916
|
}
|
|
12683
12917
|
async function cmdOpenclawInstall(opts) {
|
|
12684
12918
|
const configPath = resolveOpenclawConfigPath(opts.configPath);
|
|
12685
|
-
const fallbackMemoryDir =
|
|
12919
|
+
const fallbackMemoryDir = path15.join(resolveHomeDir(), ".openclaw", "workspace", "memory", "local");
|
|
12686
12920
|
console.log(`OpenClaw config: ${configPath}`);
|
|
12687
12921
|
const existingConfig = readOpenclawConfig(configPath);
|
|
12688
12922
|
const { plugins, entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
@@ -12753,7 +12987,7 @@ async function cmdOpenclawInstall(opts) {
|
|
|
12753
12987
|
} else if (slotIsActiveLegacy) {
|
|
12754
12988
|
changes.push(` Slot left as "${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}" \u2014 re-run with --yes to activate the new entry`);
|
|
12755
12989
|
}
|
|
12756
|
-
if (!
|
|
12990
|
+
if (!fs12.existsSync(memoryDir)) changes.push(`+ Will create memory directory: ${memoryDir}`);
|
|
12757
12991
|
if (hasLegacy && migrateLegacy) {
|
|
12758
12992
|
changes.push(`~ Legacy '${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID}' entry retained (safe to remove after verifying hooks fire)`);
|
|
12759
12993
|
}
|
|
@@ -12773,8 +13007,8 @@ async function cmdOpenclawInstall(opts) {
|
|
|
12773
13007
|
Resulting plugins.slots.memory: ${dryRunPlugins.slots?.memory ?? "(unset)"}`);
|
|
12774
13008
|
return;
|
|
12775
13009
|
}
|
|
12776
|
-
if (
|
|
12777
|
-
const st =
|
|
13010
|
+
if (fs12.existsSync(memoryDir)) {
|
|
13011
|
+
const st = fs12.statSync(memoryDir);
|
|
12778
13012
|
if (!st.isDirectory()) {
|
|
12779
13013
|
throw new Error(
|
|
12780
13014
|
`Cannot use ${memoryDir} as the memory directory \u2014 a file already exists at that path.
|
|
@@ -12782,12 +13016,12 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
12782
13016
|
);
|
|
12783
13017
|
}
|
|
12784
13018
|
} else {
|
|
12785
|
-
|
|
13019
|
+
fs12.mkdirSync(memoryDir, { recursive: true });
|
|
12786
13020
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
12787
13021
|
}
|
|
12788
|
-
const configDir =
|
|
12789
|
-
if (!
|
|
12790
|
-
|
|
13022
|
+
const configDir = path15.dirname(configPath);
|
|
13023
|
+
if (!fs12.existsSync(configDir)) {
|
|
13024
|
+
fs12.mkdirSync(configDir, { recursive: true });
|
|
12791
13025
|
}
|
|
12792
13026
|
atomicWriteFileSync(configPath, JSON.stringify(updatedConfig, null, 2) + "\n");
|
|
12793
13027
|
console.log("\nDone! Summary of changes:");
|
|
@@ -12813,11 +13047,11 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
12813
13047
|
const configPath = resolveOpenclawConfigPath(opts.configPath);
|
|
12814
13048
|
const pluginDir = resolveOpenclawPluginDir(opts.pluginDir);
|
|
12815
13049
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
12816
|
-
const fallbackMemoryDir =
|
|
13050
|
+
const fallbackMemoryDir = path15.join(resolveHomeDir(), ".openclaw", "workspace", "memory", "local");
|
|
12817
13051
|
const packageSpec = `@remnic/plugin-openclaw@${opts.version ?? "latest"}`;
|
|
12818
13052
|
const existingConfig = readOpenclawConfig(configPath);
|
|
12819
13053
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
12820
|
-
const preservedMemoryDir = opts.memoryDir ?
|
|
13054
|
+
const preservedMemoryDir = opts.memoryDir ? path15.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
12821
13055
|
assertDirectoryPathOrMissing(pluginDir, "OpenClaw plugin dir");
|
|
12822
13056
|
if (legacyPluginDirForBackup) {
|
|
12823
13057
|
assertDirectoryPathOrMissing(legacyPluginDirForBackup, "Legacy OpenClaw plugin dir");
|
|
@@ -12829,7 +13063,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
12829
13063
|
}
|
|
12830
13064
|
console.log(`Memory dir: ${preservedMemoryDir}`);
|
|
12831
13065
|
console.log(`Package spec: ${packageSpec}`);
|
|
12832
|
-
console.log(`Backup root: ${
|
|
13066
|
+
console.log(`Backup root: ${path15.join(resolveHomeDir(), ".openclaw", "backups")}`);
|
|
12833
13067
|
const plannedActions = [
|
|
12834
13068
|
`backup openclaw.json and the existing ${REMNIC_OPENCLAW_PLUGIN_ID} extension`,
|
|
12835
13069
|
...legacyPluginDirForBackup ? [`backup the existing ${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID} extension without modifying it`] : [],
|
|
@@ -12855,9 +13089,9 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
12855
13089
|
}
|
|
12856
13090
|
}
|
|
12857
13091
|
const backupDir = createOpenclawUpgradeBackupDir();
|
|
12858
|
-
const configBackupPath =
|
|
12859
|
-
const pluginBackupDir =
|
|
12860
|
-
const legacyPluginBackupDir = legacyPluginDirForBackup ?
|
|
13092
|
+
const configBackupPath = path15.join(backupDir, "openclaw.json");
|
|
13093
|
+
const pluginBackupDir = path15.join(backupDir, "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
13094
|
+
const legacyPluginBackupDir = legacyPluginDirForBackup ? path15.join(backupDir, "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID) : void 0;
|
|
12861
13095
|
const backupNotes = [];
|
|
12862
13096
|
if (backupPathIfPresent(configPath, configBackupPath)) {
|
|
12863
13097
|
backupNotes.push(`+ Backed up config to ${configBackupPath}`);
|
|
@@ -12958,16 +13192,16 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
12958
13192
|
console.log(" - Re-apply any local source patches to the new package only after verifying the published build.");
|
|
12959
13193
|
}
|
|
12960
13194
|
function createOpenclawUpgradeBackupDir() {
|
|
12961
|
-
const backupsRoot =
|
|
12962
|
-
|
|
12963
|
-
return
|
|
13195
|
+
const backupsRoot = path15.join(resolveHomeDir(), ".openclaw", "backups");
|
|
13196
|
+
fs12.mkdirSync(backupsRoot, { recursive: true });
|
|
13197
|
+
return fs12.mkdtempSync(path15.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
12964
13198
|
}
|
|
12965
13199
|
async function cmdTaxonomy(rest) {
|
|
12966
13200
|
initLogger2();
|
|
12967
13201
|
const configPath = resolveConfigPath();
|
|
12968
|
-
const raw =
|
|
13202
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
12969
13203
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
12970
|
-
const config =
|
|
13204
|
+
const config = parseConfig5(remnicCfg);
|
|
12971
13205
|
if (!config.taxonomyEnabled) {
|
|
12972
13206
|
console.error(
|
|
12973
13207
|
"Taxonomy is disabled in config (taxonomyEnabled = false). Enable it to use taxonomy commands."
|
|
@@ -13002,9 +13236,9 @@ async function cmdTaxonomy(rest) {
|
|
|
13002
13236
|
const doc = generateResolverDocument(taxonomy);
|
|
13003
13237
|
console.log(doc);
|
|
13004
13238
|
if (config.taxonomyAutoGenResolver) {
|
|
13005
|
-
const resolverPath =
|
|
13006
|
-
|
|
13007
|
-
|
|
13239
|
+
const resolverPath = path15.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
13240
|
+
fs12.mkdirSync(path15.dirname(resolverPath), { recursive: true });
|
|
13241
|
+
fs12.writeFileSync(resolverPath, doc);
|
|
13008
13242
|
console.error(`Written: ${resolverPath}`);
|
|
13009
13243
|
}
|
|
13010
13244
|
break;
|
|
@@ -13049,8 +13283,8 @@ async function cmdTaxonomy(rest) {
|
|
|
13049
13283
|
console.log(`Added category "${id}" (${name}).`);
|
|
13050
13284
|
if (config.taxonomyAutoGenResolver) {
|
|
13051
13285
|
const doc = generateResolverDocument(taxonomy);
|
|
13052
|
-
const resolverPath =
|
|
13053
|
-
|
|
13286
|
+
const resolverPath = path15.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
13287
|
+
fs12.writeFileSync(resolverPath, doc);
|
|
13054
13288
|
console.error(`Regenerated: ${resolverPath}`);
|
|
13055
13289
|
}
|
|
13056
13290
|
break;
|
|
@@ -13080,8 +13314,8 @@ async function cmdTaxonomy(rest) {
|
|
|
13080
13314
|
console.log(`Removed category "${id}".`);
|
|
13081
13315
|
if (config.taxonomyAutoGenResolver) {
|
|
13082
13316
|
const doc = generateResolverDocument(taxonomy);
|
|
13083
|
-
const resolverPath =
|
|
13084
|
-
|
|
13317
|
+
const resolverPath = path15.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
13318
|
+
fs12.writeFileSync(resolverPath, doc);
|
|
13085
13319
|
console.error(`Regenerated: ${resolverPath}`);
|
|
13086
13320
|
}
|
|
13087
13321
|
break;
|
|
@@ -13272,12 +13506,12 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
13272
13506
|
`Unknown training-export format "${args.format}". ${validList}`
|
|
13273
13507
|
);
|
|
13274
13508
|
}
|
|
13275
|
-
if (!
|
|
13509
|
+
if (!fs12.existsSync(args.memoryDir)) {
|
|
13276
13510
|
throw new Error(
|
|
13277
13511
|
`--memory-dir "${args.memoryDir}" does not exist. Provide the path to an existing memory directory.`
|
|
13278
13512
|
);
|
|
13279
13513
|
}
|
|
13280
|
-
if (!
|
|
13514
|
+
if (!fs12.statSync(args.memoryDir).isDirectory()) {
|
|
13281
13515
|
throw new Error(
|
|
13282
13516
|
`--memory-dir "${args.memoryDir}" is not a directory. Provide the path to a memory directory, not a file.`
|
|
13283
13517
|
);
|
|
@@ -13362,11 +13596,11 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
13362
13596
|
);
|
|
13363
13597
|
}
|
|
13364
13598
|
const formatted = adapter.formatRecords(records);
|
|
13365
|
-
const outDir =
|
|
13366
|
-
|
|
13599
|
+
const outDir = path15.dirname(args.output);
|
|
13600
|
+
fs12.mkdirSync(outDir, { recursive: true });
|
|
13367
13601
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
13368
|
-
|
|
13369
|
-
|
|
13602
|
+
fs12.writeFileSync(tmpPath, formatted, "utf-8");
|
|
13603
|
+
fs12.renameSync(tmpPath, args.output);
|
|
13370
13604
|
stdout.write(
|
|
13371
13605
|
`Exported ${records.length} records to ${args.output} (${adapter.name} format)
|
|
13372
13606
|
`
|
|
@@ -13470,7 +13704,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13470
13704
|
case "tree": {
|
|
13471
13705
|
const subAction = rest[0];
|
|
13472
13706
|
const json = rest.includes("--json");
|
|
13473
|
-
const outputDir = resolveFlag(rest, "--output") ??
|
|
13707
|
+
const outputDir = resolveFlag(rest, "--output") ?? path15.join(process.cwd(), ".remnic", "context-tree");
|
|
13474
13708
|
const categoriesFlag = resolveFlag(rest, "--categories");
|
|
13475
13709
|
const categories = categoriesFlag ? categoriesFlag.split(",") : void 0;
|
|
13476
13710
|
const maxPerCategoryRaw = resolveFlag(rest, "--max-per-category");
|
|
@@ -13535,7 +13769,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13535
13769
|
}
|
|
13536
13770
|
}, 500);
|
|
13537
13771
|
};
|
|
13538
|
-
|
|
13772
|
+
fs12.watch(memoryDir, { recursive: true }, (_event, filename) => {
|
|
13539
13773
|
if (filename && filename.startsWith(".")) return;
|
|
13540
13774
|
rebuild();
|
|
13541
13775
|
});
|
|
@@ -13543,12 +13777,12 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13543
13777
|
});
|
|
13544
13778
|
} else if (subAction === "validate") {
|
|
13545
13779
|
const treeDir = outputDir;
|
|
13546
|
-
if (!
|
|
13780
|
+
if (!fs12.existsSync(treeDir)) {
|
|
13547
13781
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
13548
13782
|
process.exit(1);
|
|
13549
13783
|
}
|
|
13550
|
-
const indexPath =
|
|
13551
|
-
if (!
|
|
13784
|
+
const indexPath = path15.join(treeDir, "INDEX.md");
|
|
13785
|
+
if (!fs12.existsSync(indexPath)) {
|
|
13552
13786
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
13553
13787
|
process.exit(1);
|
|
13554
13788
|
}
|
|
@@ -13602,6 +13836,12 @@ Options:
|
|
|
13602
13836
|
await cmdOffline(action, rest.slice(1), json);
|
|
13603
13837
|
break;
|
|
13604
13838
|
}
|
|
13839
|
+
case "converge": {
|
|
13840
|
+
const action = rest[0] ?? "plan";
|
|
13841
|
+
const json = rest.includes("--json");
|
|
13842
|
+
await cmdConverge(action, rest.slice(1), json);
|
|
13843
|
+
break;
|
|
13844
|
+
}
|
|
13605
13845
|
case "oauth": {
|
|
13606
13846
|
await cmdOAuth(rest);
|
|
13607
13847
|
break;
|
|
@@ -13718,9 +13958,9 @@ Other:
|
|
|
13718
13958
|
let wearablesService;
|
|
13719
13959
|
try {
|
|
13720
13960
|
const configPath = resolveConfigPath();
|
|
13721
|
-
const raw =
|
|
13961
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
13722
13962
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
13723
|
-
const config =
|
|
13963
|
+
const config = parseConfig5(remnicCfg);
|
|
13724
13964
|
wearablesOrchestrator = new Orchestrator3(config);
|
|
13725
13965
|
await wearablesOrchestrator.initialize();
|
|
13726
13966
|
await wearablesOrchestrator.deferredReady;
|
|
@@ -13769,9 +14009,9 @@ Other:
|
|
|
13769
14009
|
const targetFactory = async () => {
|
|
13770
14010
|
if (!orchestratorSingleton) {
|
|
13771
14011
|
const configPath = resolveConfigPath();
|
|
13772
|
-
const raw =
|
|
14012
|
+
const raw = fs12.existsSync(configPath) ? JSON.parse(fs12.readFileSync(configPath, "utf8")) : {};
|
|
13773
14013
|
const remnicCfg = resolveRemnicConfigRecord4(raw);
|
|
13774
|
-
const config =
|
|
14014
|
+
const config = parseConfig5(remnicCfg);
|
|
13775
14015
|
orchestratorSingleton = new Orchestrator3(config);
|
|
13776
14016
|
await orchestratorSingleton.initialize();
|
|
13777
14017
|
await orchestratorSingleton.deferredReady;
|