@remnic/cli 9.35.5 → 9.36.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 +655 -487
- package/package.json +29 -29
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ async function persistEnrichmentCandidate(storage, entityName, candidate) {
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
import fs11 from "fs";
|
|
22
22
|
import os from "os";
|
|
23
|
-
import
|
|
23
|
+
import path14 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";
|
|
@@ -1120,199 +1120,16 @@ function firstSuccessfulCandidate(candidates, attempt) {
|
|
|
1120
1120
|
}
|
|
1121
1121
|
|
|
1122
1122
|
// src/bench-args.ts
|
|
1123
|
-
import
|
|
1124
|
-
|
|
1125
|
-
// src/path-utils.ts
|
|
1126
|
-
function resolveHomeDir() {
|
|
1127
|
-
return process.env.HOME ?? process.env.USERPROFILE ?? "~";
|
|
1128
|
-
}
|
|
1129
|
-
function expandTilde(p) {
|
|
1130
|
-
if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
|
|
1131
|
-
return resolveHomeDir() + p.slice(1);
|
|
1132
|
-
}
|
|
1133
|
-
const home = resolveHomeDir();
|
|
1134
|
-
if (p === "$HOME" || p.startsWith("$HOME/") || p.startsWith("$HOME\\")) {
|
|
1135
|
-
return home + p.slice(5);
|
|
1136
|
-
}
|
|
1137
|
-
if (p === "${HOME}" || p.startsWith("${HOME}/") || p.startsWith("${HOME}\\")) {
|
|
1138
|
-
return home + p.slice(7);
|
|
1139
|
-
}
|
|
1140
|
-
return p;
|
|
1141
|
-
}
|
|
1123
|
+
import path6 from "path";
|
|
1142
1124
|
|
|
1143
|
-
// src/bench-
|
|
1144
|
-
function createBenchWorkItems(benchmarks, runtimeProfiles) {
|
|
1145
|
-
return benchmarks.flatMap(
|
|
1146
|
-
(benchmarkId) => runtimeProfiles.map((runtimeProfile) => ({ benchmarkId, runtimeProfile }))
|
|
1147
|
-
);
|
|
1148
|
-
}
|
|
1149
|
-
function deriveRuntimeProfilesFromBenchWorkItems(workItems) {
|
|
1150
|
-
return [...new Set(workItems.map((item) => item.runtimeProfile))];
|
|
1151
|
-
}
|
|
1152
|
-
function filterBenchWorkItemsForPreviousStatus(workItems, previousEntries, mode) {
|
|
1153
|
-
const statusById = new Map(previousEntries.map((entry) => [entry.id, entry.status]));
|
|
1154
|
-
const hasMatrixWork = new Set(workItems.map((item) => item.benchmarkId)).size !== workItems.length;
|
|
1155
|
-
function statusFor(item) {
|
|
1156
|
-
const profileStatus = statusById.get(`${item.benchmarkId} [${item.runtimeProfile}]`);
|
|
1157
|
-
if (profileStatus !== void 0) return profileStatus;
|
|
1158
|
-
if (hasMatrixWork) {
|
|
1159
|
-
return mode === "retry-failed" ? statusById.get(item.benchmarkId) : void 0;
|
|
1160
|
-
}
|
|
1161
|
-
return statusById.get(item.benchmarkId);
|
|
1162
|
-
}
|
|
1163
|
-
return workItems.filter((item) => {
|
|
1164
|
-
const status = statusFor(item);
|
|
1165
|
-
if (mode === "retry-failed") {
|
|
1166
|
-
return status === "failed";
|
|
1167
|
-
}
|
|
1168
|
-
return status !== "complete";
|
|
1169
|
-
});
|
|
1170
|
-
}
|
|
1171
|
-
var PUBLISHED_BENCHMARK_NAMES = Object.freeze([
|
|
1172
|
-
"ama-bench",
|
|
1173
|
-
"memory-arena",
|
|
1174
|
-
"amemgym",
|
|
1175
|
-
"longmemeval",
|
|
1176
|
-
"locomo",
|
|
1177
|
-
"beam",
|
|
1178
|
-
"personamem",
|
|
1179
|
-
"memoryagentbench",
|
|
1180
|
-
"membench"
|
|
1181
|
-
]);
|
|
1182
|
-
function isBenchRuntimeProfile(value) {
|
|
1183
|
-
return value === "baseline" || value === "real" || value === "openclaw-chain" || value === "local-lab";
|
|
1184
|
-
}
|
|
1185
|
-
function parseBenchRuntimeProfile(value, flagName) {
|
|
1186
|
-
if (isBenchRuntimeProfile(value)) {
|
|
1187
|
-
return value;
|
|
1188
|
-
}
|
|
1189
|
-
if (flagName === "--runtime-profile") {
|
|
1190
|
-
throw new Error(
|
|
1191
|
-
'ERROR: --runtime-profile must be "baseline", "real", "openclaw-chain", or "local-lab".'
|
|
1192
|
-
);
|
|
1193
|
-
}
|
|
1194
|
-
throw new Error(
|
|
1195
|
-
'ERROR: --matrix must contain only "baseline", "real", "openclaw-chain", or "local-lab".'
|
|
1196
|
-
);
|
|
1197
|
-
}
|
|
1198
|
-
var BENCH_PROVIDER_ALLOWED = Object.freeze([
|
|
1199
|
-
"openai",
|
|
1200
|
-
"anthropic",
|
|
1201
|
-
"ollama",
|
|
1202
|
-
"litellm",
|
|
1203
|
-
"local-llm",
|
|
1204
|
-
"codex-cli",
|
|
1205
|
-
"claude-cli"
|
|
1206
|
-
]);
|
|
1207
|
-
var BENCH_INTERNAL_PROVIDER_ALLOWED = Object.freeze(
|
|
1208
|
-
BENCH_PROVIDER_ALLOWED.filter((provider) => provider !== "claude-cli")
|
|
1209
|
-
);
|
|
1210
|
-
function isBuiltInProvider(value) {
|
|
1211
|
-
return BENCH_PROVIDER_ALLOWED.includes(value);
|
|
1212
|
-
}
|
|
1213
|
-
function isBuiltInInternalProvider(value) {
|
|
1214
|
-
return BENCH_INTERNAL_PROVIDER_ALLOWED.includes(value);
|
|
1215
|
-
}
|
|
1216
|
-
function parseBenchProvider(raw, flag) {
|
|
1217
|
-
if (!isBuiltInProvider(raw)) {
|
|
1218
|
-
throw new Error(
|
|
1219
|
-
`ERROR: ${flag} must be one of "openai", "anthropic", "ollama", "litellm", "local-llm", "codex-cli", or "claude-cli".`
|
|
1220
|
-
);
|
|
1221
|
-
}
|
|
1222
|
-
return raw;
|
|
1223
|
-
}
|
|
1224
|
-
function parseBenchInternalProvider(raw, flag) {
|
|
1225
|
-
if (!isBuiltInInternalProvider(raw)) {
|
|
1226
|
-
if (raw === "claude-cli") {
|
|
1227
|
-
throw new Error(
|
|
1228
|
-
`ERROR: ${flag} does not support "claude-cli" (no @remnic/core gateway wiring); use --provider, --system-provider, or --judge-provider instead.`
|
|
1229
|
-
);
|
|
1230
|
-
}
|
|
1231
|
-
throw new Error(
|
|
1232
|
-
`ERROR: ${flag} must be one of "openai", "anthropic", "ollama", "litellm", "local-llm", or "codex-cli".`
|
|
1233
|
-
);
|
|
1234
|
-
}
|
|
1235
|
-
return raw;
|
|
1236
|
-
}
|
|
1237
|
-
function parseCodexReasoningEffort(raw, flag) {
|
|
1238
|
-
if (raw !== "low" && raw !== "medium" && raw !== "high" && raw !== "xhigh") {
|
|
1239
|
-
throw new Error(
|
|
1240
|
-
`ERROR: ${flag} must be "low", "medium", "high", or "xhigh".`
|
|
1241
|
-
);
|
|
1242
|
-
}
|
|
1243
|
-
return raw;
|
|
1244
|
-
}
|
|
1245
|
-
var MCP_TOOL_OPERATIONS = /* @__PURE__ */ new Set(["store", "recall", "correct", "reset"]);
|
|
1246
|
-
var MCP_ARGUMENT_SEMANTICS = /* @__PURE__ */ new Set([
|
|
1247
|
-
"namespace",
|
|
1248
|
-
"sessionId",
|
|
1249
|
-
"content",
|
|
1250
|
-
"role",
|
|
1251
|
-
"timestamp",
|
|
1252
|
-
"query",
|
|
1253
|
-
"limit"
|
|
1254
|
-
]);
|
|
1255
|
-
function parseMcpToolMapping(value) {
|
|
1256
|
-
if (!isPlainObject(value)) throw new Error("expected a JSON object");
|
|
1257
|
-
for (const operation of Object.keys(value).sort()) {
|
|
1258
|
-
if (!MCP_TOOL_OPERATIONS.has(operation)) {
|
|
1259
|
-
throw new Error(`unknown operation ${operation}`);
|
|
1260
|
-
}
|
|
1261
|
-
const entry = value[operation];
|
|
1262
|
-
if (typeof entry === "string") {
|
|
1263
|
-
if (entry.trim().length === 0) throw new Error(`${operation} tool name must not be empty`);
|
|
1264
|
-
continue;
|
|
1265
|
-
}
|
|
1266
|
-
if (!isPlainObject(entry)) {
|
|
1267
|
-
throw new Error(`${operation} must be a tool-name string or mapping object`);
|
|
1268
|
-
}
|
|
1269
|
-
for (const field of Object.keys(entry).sort()) {
|
|
1270
|
-
if (field !== "name" && field !== "arguments" && field !== "resultPath") {
|
|
1271
|
-
throw new Error(`${operation} contains unknown field ${field}`);
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
if (typeof entry.name !== "string" || entry.name.trim().length === 0) {
|
|
1275
|
-
throw new Error(`${operation}.name must be a non-empty string`);
|
|
1276
|
-
}
|
|
1277
|
-
if (entry.resultPath !== void 0) {
|
|
1278
|
-
if (typeof entry.resultPath !== "string" || !isSafeMcpResultPath(entry.resultPath)) {
|
|
1279
|
-
throw new Error(`${operation}.resultPath must be a non-empty safe dot path`);
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
if (entry.arguments !== void 0) {
|
|
1283
|
-
if (!isPlainObject(entry.arguments)) {
|
|
1284
|
-
throw new Error(`${operation}.arguments must be an object`);
|
|
1285
|
-
}
|
|
1286
|
-
for (const semantic of Object.keys(entry.arguments).sort()) {
|
|
1287
|
-
if (!MCP_ARGUMENT_SEMANTICS.has(semantic)) {
|
|
1288
|
-
throw new Error(`${operation}.arguments contains unknown semantic ${semantic}`);
|
|
1289
|
-
}
|
|
1290
|
-
const argumentName = entry.arguments[semantic];
|
|
1291
|
-
if (typeof argumentName !== "string" || argumentName.trim().length === 0) {
|
|
1292
|
-
throw new Error(`${operation}.arguments.${semantic} must be a non-empty string`);
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
return value;
|
|
1298
|
-
}
|
|
1299
|
-
function isPlainObject(value) {
|
|
1300
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1301
|
-
const prototype = Object.getPrototypeOf(value);
|
|
1302
|
-
return prototype === Object.prototype || prototype === null;
|
|
1303
|
-
}
|
|
1304
|
-
function isSafeMcpResultPath(value) {
|
|
1305
|
-
return value.split(".").every(
|
|
1306
|
-
(segment) => segment.length > 0 && segment !== "__proto__" && segment !== "prototype" && segment !== "constructor" && /^[A-Za-z0-9_-]+$/.test(segment)
|
|
1307
|
-
);
|
|
1308
|
-
}
|
|
1125
|
+
// src/bench-flags.ts
|
|
1309
1126
|
function readBenchOptionValue(argv, flag) {
|
|
1310
1127
|
const index = argv.indexOf(flag);
|
|
1311
1128
|
if (index === -1) {
|
|
1312
1129
|
return void 0;
|
|
1313
1130
|
}
|
|
1314
1131
|
const value = argv[index + 1];
|
|
1315
|
-
if (!value || value.startsWith("-")) {
|
|
1132
|
+
if (!value || value.startsWith("-") && !/^-\d/.test(value)) {
|
|
1316
1133
|
throw new Error(`ERROR: ${flag} requires a value.`);
|
|
1317
1134
|
}
|
|
1318
1135
|
return value;
|
|
@@ -1389,7 +1206,14 @@ var BENCH_VALUE_FLAGS = Object.freeze([
|
|
|
1389
1206
|
"--ama-bench-cross-judge-api-key",
|
|
1390
1207
|
"--ama-bench-cross-judge-codex-reasoning-effort",
|
|
1391
1208
|
"--local-lab-manifest",
|
|
1392
|
-
"--memcorrect-adapter"
|
|
1209
|
+
"--memcorrect-adapter",
|
|
1210
|
+
"--run",
|
|
1211
|
+
"--memory-dir",
|
|
1212
|
+
"--users",
|
|
1213
|
+
"--epochs",
|
|
1214
|
+
"--facts-per-epoch",
|
|
1215
|
+
"--drifting-ratio",
|
|
1216
|
+
"--contradicted-ratio"
|
|
1393
1217
|
]);
|
|
1394
1218
|
var BENCH_BOOLEAN_FLAGS = Object.freeze([
|
|
1395
1219
|
"--mcp-demo",
|
|
@@ -1564,6 +1388,22 @@ var BENCH_ACTION_FLAGS = {
|
|
|
1564
1388
|
value: [],
|
|
1565
1389
|
boolean: ["--json", "--explain", "--help", "-h"],
|
|
1566
1390
|
legacyEqualsPrefixes: ["--baseline=", "--report="]
|
|
1391
|
+
},
|
|
1392
|
+
attribute: {
|
|
1393
|
+
value: ["--run", "--results-dir", "--memory-dir", "--threshold"],
|
|
1394
|
+
boolean: ["--json", "--help", "-h"]
|
|
1395
|
+
},
|
|
1396
|
+
"drift-gen": {
|
|
1397
|
+
value: [
|
|
1398
|
+
"--users",
|
|
1399
|
+
"--epochs",
|
|
1400
|
+
"--seed",
|
|
1401
|
+
"--out",
|
|
1402
|
+
"--facts-per-epoch",
|
|
1403
|
+
"--drifting-ratio",
|
|
1404
|
+
"--contradicted-ratio"
|
|
1405
|
+
],
|
|
1406
|
+
boolean: ["--json", "--help", "-h"]
|
|
1567
1407
|
}
|
|
1568
1408
|
};
|
|
1569
1409
|
function formatBenchOptions(valueFlags, booleanFlags, legacyEqualsPrefixes = []) {
|
|
@@ -1602,45 +1442,294 @@ function validateBenchFlags(action, args) {
|
|
|
1602
1442
|
);
|
|
1603
1443
|
}
|
|
1604
1444
|
const value = args[index + 1];
|
|
1605
|
-
if (!value || value.startsWith("-")) {
|
|
1445
|
+
if (!value || value.startsWith("-") && !/^-\d/.test(value)) {
|
|
1606
1446
|
throw new Error(`ERROR: ${arg} requires a value.`);
|
|
1607
1447
|
}
|
|
1608
1448
|
index += 1;
|
|
1609
1449
|
continue;
|
|
1610
1450
|
}
|
|
1611
|
-
if (isBenchBooleanFlag(arg)) {
|
|
1612
|
-
if (!allowedBoolean.has(arg)) {
|
|
1613
|
-
throw new Error(
|
|
1614
|
-
`ERROR: ${arg} is not supported for bench ${action}. Supported options: ${supportedOptions || "(none)"}.`
|
|
1615
|
-
);
|
|
1451
|
+
if (isBenchBooleanFlag(arg)) {
|
|
1452
|
+
if (!allowedBoolean.has(arg)) {
|
|
1453
|
+
throw new Error(
|
|
1454
|
+
`ERROR: ${arg} is not supported for bench ${action}. Supported options: ${supportedOptions || "(none)"}.`
|
|
1455
|
+
);
|
|
1456
|
+
}
|
|
1457
|
+
continue;
|
|
1458
|
+
}
|
|
1459
|
+
throw new Error(
|
|
1460
|
+
`ERROR: unknown bench option ${arg}. Supported options: ${allOptions}.`
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
function collectBenchmarks(argv) {
|
|
1465
|
+
const benchmarks = [];
|
|
1466
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
1467
|
+
const arg = argv[index];
|
|
1468
|
+
if (isBenchValueFlag(arg)) {
|
|
1469
|
+
index += 1;
|
|
1470
|
+
continue;
|
|
1471
|
+
}
|
|
1472
|
+
if (isBenchBooleanFlag(arg)) {
|
|
1473
|
+
continue;
|
|
1474
|
+
}
|
|
1475
|
+
if (!arg.startsWith("-")) {
|
|
1476
|
+
benchmarks.push(arg);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
return benchmarks;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
// src/path-utils.ts
|
|
1483
|
+
function resolveHomeDir() {
|
|
1484
|
+
return process.env.HOME ?? process.env.USERPROFILE ?? "~";
|
|
1485
|
+
}
|
|
1486
|
+
function expandTilde(p) {
|
|
1487
|
+
if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) {
|
|
1488
|
+
return resolveHomeDir() + p.slice(1);
|
|
1489
|
+
}
|
|
1490
|
+
const home = resolveHomeDir();
|
|
1491
|
+
if (p === "$HOME" || p.startsWith("$HOME/") || p.startsWith("$HOME\\")) {
|
|
1492
|
+
return home + p.slice(5);
|
|
1493
|
+
}
|
|
1494
|
+
if (p === "${HOME}" || p.startsWith("${HOME}/") || p.startsWith("${HOME}\\")) {
|
|
1495
|
+
return home + p.slice(7);
|
|
1496
|
+
}
|
|
1497
|
+
return p;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// src/bench-args-research.ts
|
|
1501
|
+
import path5 from "path";
|
|
1502
|
+
function readPositiveInteger(args, flag) {
|
|
1503
|
+
const raw = readBenchOptionValue(args, flag);
|
|
1504
|
+
if (raw === void 0) return void 0;
|
|
1505
|
+
const parsed = Number(raw);
|
|
1506
|
+
if (!Number.isSafeInteger(parsed) || parsed <= 0) {
|
|
1507
|
+
throw new Error(`ERROR: ${flag} must be a positive safe integer.`);
|
|
1508
|
+
}
|
|
1509
|
+
return parsed;
|
|
1510
|
+
}
|
|
1511
|
+
function readUnitRatio(args, flag) {
|
|
1512
|
+
const raw = readBenchOptionValue(args, flag);
|
|
1513
|
+
if (raw === void 0) return void 0;
|
|
1514
|
+
const parsed = Number(raw);
|
|
1515
|
+
if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
|
|
1516
|
+
throw new Error(`ERROR: ${flag} must be a number between 0 and 1.`);
|
|
1517
|
+
}
|
|
1518
|
+
return parsed;
|
|
1519
|
+
}
|
|
1520
|
+
function parseBenchResearchArgs(action, args) {
|
|
1521
|
+
const runRef = readBenchOptionValue(args, "--run");
|
|
1522
|
+
if (action === "attribute" && !runRef) {
|
|
1523
|
+
throw new Error("ERROR: bench attribute requires --run <id>.");
|
|
1524
|
+
}
|
|
1525
|
+
const memoryDirRaw = readBenchOptionValue(args, "--memory-dir");
|
|
1526
|
+
let seed;
|
|
1527
|
+
let out;
|
|
1528
|
+
if (action === "drift-gen") {
|
|
1529
|
+
const seedRaw = readBenchOptionValue(args, "--seed");
|
|
1530
|
+
if (seedRaw !== void 0) {
|
|
1531
|
+
const parsed = Number(seedRaw);
|
|
1532
|
+
if (!Number.isSafeInteger(parsed) || parsed < 0) {
|
|
1533
|
+
throw new Error("ERROR: --seed must be a non-negative safe integer.");
|
|
1534
|
+
}
|
|
1535
|
+
seed = parsed;
|
|
1536
|
+
}
|
|
1537
|
+
const outRaw = readBenchOptionValue(args, "--out");
|
|
1538
|
+
if (outRaw !== void 0) {
|
|
1539
|
+
out = path5.resolve(expandTilde(outRaw));
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
const epochs = readPositiveInteger(args, "--epochs");
|
|
1543
|
+
if (action === "drift-gen" && epochs !== void 0 && epochs < 2) {
|
|
1544
|
+
throw new Error("ERROR: --epochs must be at least 2 (supersession needs two epochs).");
|
|
1545
|
+
}
|
|
1546
|
+
const driftingRatio = readUnitRatio(args, "--drifting-ratio");
|
|
1547
|
+
const contradictedRatio = readUnitRatio(args, "--contradicted-ratio");
|
|
1548
|
+
if ((driftingRatio ?? 0.2) + (contradictedRatio ?? 0.1) > 1) {
|
|
1549
|
+
throw new Error("ERROR: --drifting-ratio and --contradicted-ratio must sum to at most 1.");
|
|
1550
|
+
}
|
|
1551
|
+
return {
|
|
1552
|
+
runRef,
|
|
1553
|
+
memoryDir: memoryDirRaw ? path5.resolve(expandTilde(memoryDirRaw)) : void 0,
|
|
1554
|
+
users: readPositiveInteger(args, "--users"),
|
|
1555
|
+
epochs,
|
|
1556
|
+
seed,
|
|
1557
|
+
out,
|
|
1558
|
+
factsPerEpoch: readPositiveInteger(args, "--facts-per-epoch"),
|
|
1559
|
+
driftingRatio,
|
|
1560
|
+
contradictedRatio
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
// src/bench-args.ts
|
|
1565
|
+
function createBenchWorkItems(benchmarks, runtimeProfiles) {
|
|
1566
|
+
return benchmarks.flatMap(
|
|
1567
|
+
(benchmarkId) => runtimeProfiles.map((runtimeProfile) => ({ benchmarkId, runtimeProfile }))
|
|
1568
|
+
);
|
|
1569
|
+
}
|
|
1570
|
+
function deriveRuntimeProfilesFromBenchWorkItems(workItems) {
|
|
1571
|
+
return [...new Set(workItems.map((item) => item.runtimeProfile))];
|
|
1572
|
+
}
|
|
1573
|
+
function filterBenchWorkItemsForPreviousStatus(workItems, previousEntries, mode) {
|
|
1574
|
+
const statusById = new Map(previousEntries.map((entry) => [entry.id, entry.status]));
|
|
1575
|
+
const hasMatrixWork = new Set(workItems.map((item) => item.benchmarkId)).size !== workItems.length;
|
|
1576
|
+
function statusFor(item) {
|
|
1577
|
+
const profileStatus = statusById.get(`${item.benchmarkId} [${item.runtimeProfile}]`);
|
|
1578
|
+
if (profileStatus !== void 0) return profileStatus;
|
|
1579
|
+
if (hasMatrixWork) {
|
|
1580
|
+
return mode === "retry-failed" ? statusById.get(item.benchmarkId) : void 0;
|
|
1581
|
+
}
|
|
1582
|
+
return statusById.get(item.benchmarkId);
|
|
1583
|
+
}
|
|
1584
|
+
return workItems.filter((item) => {
|
|
1585
|
+
const status = statusFor(item);
|
|
1586
|
+
if (mode === "retry-failed") {
|
|
1587
|
+
return status === "failed";
|
|
1588
|
+
}
|
|
1589
|
+
return status !== "complete";
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
var PUBLISHED_BENCHMARK_NAMES = Object.freeze([
|
|
1593
|
+
"ama-bench",
|
|
1594
|
+
"memory-arena",
|
|
1595
|
+
"amemgym",
|
|
1596
|
+
"longmemeval",
|
|
1597
|
+
"locomo",
|
|
1598
|
+
"beam",
|
|
1599
|
+
"personamem",
|
|
1600
|
+
"memoryagentbench",
|
|
1601
|
+
"membench"
|
|
1602
|
+
]);
|
|
1603
|
+
function isBenchRuntimeProfile(value) {
|
|
1604
|
+
return value === "baseline" || value === "real" || value === "openclaw-chain" || value === "local-lab";
|
|
1605
|
+
}
|
|
1606
|
+
function parseBenchRuntimeProfile(value, flagName) {
|
|
1607
|
+
if (isBenchRuntimeProfile(value)) {
|
|
1608
|
+
return value;
|
|
1609
|
+
}
|
|
1610
|
+
if (flagName === "--runtime-profile") {
|
|
1611
|
+
throw new Error(
|
|
1612
|
+
'ERROR: --runtime-profile must be "baseline", "real", "openclaw-chain", or "local-lab".'
|
|
1613
|
+
);
|
|
1614
|
+
}
|
|
1615
|
+
throw new Error(
|
|
1616
|
+
'ERROR: --matrix must contain only "baseline", "real", "openclaw-chain", or "local-lab".'
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
var BENCH_PROVIDER_ALLOWED = Object.freeze([
|
|
1620
|
+
"openai",
|
|
1621
|
+
"anthropic",
|
|
1622
|
+
"ollama",
|
|
1623
|
+
"litellm",
|
|
1624
|
+
"local-llm",
|
|
1625
|
+
"codex-cli",
|
|
1626
|
+
"claude-cli"
|
|
1627
|
+
]);
|
|
1628
|
+
var BENCH_INTERNAL_PROVIDER_ALLOWED = Object.freeze(
|
|
1629
|
+
BENCH_PROVIDER_ALLOWED.filter((provider) => provider !== "claude-cli")
|
|
1630
|
+
);
|
|
1631
|
+
function isBuiltInProvider(value) {
|
|
1632
|
+
return BENCH_PROVIDER_ALLOWED.includes(value);
|
|
1633
|
+
}
|
|
1634
|
+
function isBuiltInInternalProvider(value) {
|
|
1635
|
+
return BENCH_INTERNAL_PROVIDER_ALLOWED.includes(value);
|
|
1636
|
+
}
|
|
1637
|
+
function parseBenchProvider(raw, flag) {
|
|
1638
|
+
if (!isBuiltInProvider(raw)) {
|
|
1639
|
+
throw new Error(
|
|
1640
|
+
`ERROR: ${flag} must be one of "openai", "anthropic", "ollama", "litellm", "local-llm", "codex-cli", or "claude-cli".`
|
|
1641
|
+
);
|
|
1642
|
+
}
|
|
1643
|
+
return raw;
|
|
1644
|
+
}
|
|
1645
|
+
function parseBenchInternalProvider(raw, flag) {
|
|
1646
|
+
if (!isBuiltInInternalProvider(raw)) {
|
|
1647
|
+
if (raw === "claude-cli") {
|
|
1648
|
+
throw new Error(
|
|
1649
|
+
`ERROR: ${flag} does not support "claude-cli" (no @remnic/core gateway wiring); use --provider, --system-provider, or --judge-provider instead.`
|
|
1650
|
+
);
|
|
1651
|
+
}
|
|
1652
|
+
throw new Error(
|
|
1653
|
+
`ERROR: ${flag} must be one of "openai", "anthropic", "ollama", "litellm", "local-llm", or "codex-cli".`
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
return raw;
|
|
1657
|
+
}
|
|
1658
|
+
function parseCodexReasoningEffort(raw, flag) {
|
|
1659
|
+
if (raw !== "low" && raw !== "medium" && raw !== "high" && raw !== "xhigh") {
|
|
1660
|
+
throw new Error(
|
|
1661
|
+
`ERROR: ${flag} must be "low", "medium", "high", or "xhigh".`
|
|
1662
|
+
);
|
|
1663
|
+
}
|
|
1664
|
+
return raw;
|
|
1665
|
+
}
|
|
1666
|
+
var MCP_TOOL_OPERATIONS = /* @__PURE__ */ new Set(["store", "recall", "correct", "reset"]);
|
|
1667
|
+
var MCP_ARGUMENT_SEMANTICS = /* @__PURE__ */ new Set([
|
|
1668
|
+
"namespace",
|
|
1669
|
+
"sessionId",
|
|
1670
|
+
"content",
|
|
1671
|
+
"role",
|
|
1672
|
+
"timestamp",
|
|
1673
|
+
"query",
|
|
1674
|
+
"limit"
|
|
1675
|
+
]);
|
|
1676
|
+
function parseMcpToolMapping(value) {
|
|
1677
|
+
if (!isPlainObject(value)) throw new Error("expected a JSON object");
|
|
1678
|
+
for (const operation of Object.keys(value).sort()) {
|
|
1679
|
+
if (!MCP_TOOL_OPERATIONS.has(operation)) {
|
|
1680
|
+
throw new Error(`unknown operation ${operation}`);
|
|
1681
|
+
}
|
|
1682
|
+
const entry = value[operation];
|
|
1683
|
+
if (typeof entry === "string") {
|
|
1684
|
+
if (entry.trim().length === 0) throw new Error(`${operation} tool name must not be empty`);
|
|
1685
|
+
continue;
|
|
1686
|
+
}
|
|
1687
|
+
if (!isPlainObject(entry)) {
|
|
1688
|
+
throw new Error(`${operation} must be a tool-name string or mapping object`);
|
|
1689
|
+
}
|
|
1690
|
+
for (const field of Object.keys(entry).sort()) {
|
|
1691
|
+
if (field !== "name" && field !== "arguments" && field !== "resultPath") {
|
|
1692
|
+
throw new Error(`${operation} contains unknown field ${field}`);
|
|
1616
1693
|
}
|
|
1617
|
-
continue;
|
|
1618
1694
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
);
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
function collectBenchmarks(argv) {
|
|
1625
|
-
const benchmarks = [];
|
|
1626
|
-
for (let index = 0; index < argv.length; index += 1) {
|
|
1627
|
-
const arg = argv[index];
|
|
1628
|
-
if (isBenchValueFlag(arg)) {
|
|
1629
|
-
index += 1;
|
|
1630
|
-
continue;
|
|
1695
|
+
if (typeof entry.name !== "string" || entry.name.trim().length === 0) {
|
|
1696
|
+
throw new Error(`${operation}.name must be a non-empty string`);
|
|
1631
1697
|
}
|
|
1632
|
-
if (
|
|
1633
|
-
|
|
1698
|
+
if (entry.resultPath !== void 0) {
|
|
1699
|
+
if (typeof entry.resultPath !== "string" || !isSafeMcpResultPath(entry.resultPath)) {
|
|
1700
|
+
throw new Error(`${operation}.resultPath must be a non-empty safe dot path`);
|
|
1701
|
+
}
|
|
1634
1702
|
}
|
|
1635
|
-
if (
|
|
1636
|
-
|
|
1703
|
+
if (entry.arguments !== void 0) {
|
|
1704
|
+
if (!isPlainObject(entry.arguments)) {
|
|
1705
|
+
throw new Error(`${operation}.arguments must be an object`);
|
|
1706
|
+
}
|
|
1707
|
+
for (const semantic of Object.keys(entry.arguments).sort()) {
|
|
1708
|
+
if (!MCP_ARGUMENT_SEMANTICS.has(semantic)) {
|
|
1709
|
+
throw new Error(`${operation}.arguments contains unknown semantic ${semantic}`);
|
|
1710
|
+
}
|
|
1711
|
+
const argumentName = entry.arguments[semantic];
|
|
1712
|
+
if (typeof argumentName !== "string" || argumentName.trim().length === 0) {
|
|
1713
|
+
throw new Error(`${operation}.arguments.${semantic} must be a non-empty string`);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1637
1716
|
}
|
|
1638
1717
|
}
|
|
1639
|
-
return
|
|
1718
|
+
return value;
|
|
1719
|
+
}
|
|
1720
|
+
function isPlainObject(value) {
|
|
1721
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
1722
|
+
const prototype = Object.getPrototypeOf(value);
|
|
1723
|
+
return prototype === Object.prototype || prototype === null;
|
|
1724
|
+
}
|
|
1725
|
+
function isSafeMcpResultPath(value) {
|
|
1726
|
+
return value.split(".").every(
|
|
1727
|
+
(segment) => segment.length > 0 && segment !== "__proto__" && segment !== "prototype" && segment !== "constructor" && /^[A-Za-z0-9_-]+$/.test(segment)
|
|
1728
|
+
);
|
|
1640
1729
|
}
|
|
1641
1730
|
function parseBenchActionArgs(argv) {
|
|
1642
1731
|
const [first, ...rest] = argv;
|
|
1643
|
-
const action = first === "list" || first === "run" || first === "datasets" || first === "runs" || first === "compare" || first === "ui" || first === "results" || first === "baseline" || first === "export" || first === "providers" || first === "publish" || first === "published" || first === "judge-calibrate" || first === "check" || first === "report" ? first : first === void 0 || first === "--help" || first === "-h" ? "help" : "run";
|
|
1732
|
+
const action = first === "list" || first === "run" || first === "datasets" || first === "runs" || first === "compare" || first === "ui" || first === "results" || first === "baseline" || first === "export" || first === "providers" || first === "publish" || first === "published" || first === "judge-calibrate" || first === "check" || first === "report" || first === "attribute" || first === "drift-gen" ? first : first === void 0 || first === "--help" || first === "-h" ? "help" : "run";
|
|
1644
1733
|
return {
|
|
1645
1734
|
action,
|
|
1646
1735
|
args: action === "run" && action !== first ? argv : rest
|
|
@@ -1662,6 +1751,7 @@ function parseBenchArgs(argv) {
|
|
|
1662
1751
|
const datasetAction = action === "datasets" ? args[0] === "download" || args[0] === "status" ? args[0] : void 0 : void 0;
|
|
1663
1752
|
const providerAction = action === "providers" ? args[0] === "discover" ? args[0] : void 0 : void 0;
|
|
1664
1753
|
const runAction = action === "runs" ? args[0] === "list" || args[0] === "show" || args[0] === "delete" ? args[0] : void 0 : void 0;
|
|
1754
|
+
const driftGenAction = action === "drift-gen" ? args[0] === "validate" ? "validate" : args[0] === "generate" ? "generate" : args[0] !== void 0 && !args[0].startsWith("-") ? void 0 : "generate" : void 0;
|
|
1665
1755
|
if (action === "baseline" && baselineAction === void 0) {
|
|
1666
1756
|
throw new Error("ERROR: baseline requires a subcommand: save or list.");
|
|
1667
1757
|
}
|
|
@@ -1674,8 +1764,13 @@ function parseBenchArgs(argv) {
|
|
|
1674
1764
|
if (action === "runs" && runAction === void 0) {
|
|
1675
1765
|
throw new Error("ERROR: runs requires a subcommand: list, show, or delete.");
|
|
1676
1766
|
}
|
|
1767
|
+
if (action === "drift-gen" && driftGenAction === void 0) {
|
|
1768
|
+
throw new Error('ERROR: drift-gen subcommand must be "generate" or "validate".');
|
|
1769
|
+
}
|
|
1677
1770
|
validateBenchFlags(action, args);
|
|
1678
|
-
const
|
|
1771
|
+
const driftGenPositionals = action === "drift-gen" && driftGenAction === "validate" ? collectBenchmarks(args.slice(1)) : [];
|
|
1772
|
+
const driftGenDir = driftGenPositionals[0] ? path6.resolve(expandTilde(driftGenPositionals[0])) : void 0;
|
|
1773
|
+
const benchmarkArgs = action === "baseline" || action === "datasets" || action === "providers" || action === "runs" || action === "drift-gen" && (args[0] === "validate" || args[0] === "generate") ? args.slice(1) : args;
|
|
1679
1774
|
const benchmarks = collectBenchmarks(benchmarkArgs);
|
|
1680
1775
|
const datasetDir = readBenchOptionValue(args, "--dataset-dir") ?? readBenchOptionValue(args, "--dataset");
|
|
1681
1776
|
const adapterRaw = readBenchOptionValue(args, "--adapter");
|
|
@@ -1757,6 +1852,7 @@ function parseBenchArgs(argv) {
|
|
|
1757
1852
|
}
|
|
1758
1853
|
adapter = adapterRaw;
|
|
1759
1854
|
}
|
|
1855
|
+
const research = parseBenchResearchArgs(action, args);
|
|
1760
1856
|
const hasMcpOptions = Boolean(
|
|
1761
1857
|
mcpCommand || mcpArgsRaw || mcpUrl || mcpToolMapRaw || mcpDemo
|
|
1762
1858
|
);
|
|
@@ -1887,6 +1983,9 @@ function parseBenchArgs(argv) {
|
|
|
1887
1983
|
if (!Number.isFinite(threshold) || threshold < 0) {
|
|
1888
1984
|
throw new Error("ERROR: --threshold must be a non-negative number.");
|
|
1889
1985
|
}
|
|
1986
|
+
if (action === "attribute" && threshold > 1) {
|
|
1987
|
+
throw new Error("ERROR: --threshold must be a number between 0 and 1.");
|
|
1988
|
+
}
|
|
1890
1989
|
}
|
|
1891
1990
|
let format;
|
|
1892
1991
|
if (formatRaw !== void 0) {
|
|
@@ -2220,13 +2319,13 @@ function parseBenchArgs(argv) {
|
|
|
2220
2319
|
mcpUrl,
|
|
2221
2320
|
mcpToolMap,
|
|
2222
2321
|
mcpDemo,
|
|
2223
|
-
datasetDir: datasetDir ?
|
|
2224
|
-
resultsDir: resultsDir ?
|
|
2225
|
-
baselinesDir: baselinesDir ?
|
|
2322
|
+
datasetDir: datasetDir ? path6.resolve(expandTilde(datasetDir)) : void 0,
|
|
2323
|
+
resultsDir: resultsDir ? path6.resolve(expandTilde(resultsDir)) : void 0,
|
|
2324
|
+
baselinesDir: baselinesDir ? path6.resolve(expandTilde(baselinesDir)) : void 0,
|
|
2226
2325
|
runtimeProfile,
|
|
2227
2326
|
matrixProfiles,
|
|
2228
|
-
remnicConfigPath: remnicConfigRaw ?
|
|
2229
|
-
openclawConfigPath: openclawConfigRaw ?
|
|
2327
|
+
remnicConfigPath: remnicConfigRaw ? path6.resolve(expandTilde(remnicConfigRaw)) : void 0,
|
|
2328
|
+
openclawConfigPath: openclawConfigRaw ? path6.resolve(expandTilde(openclawConfigRaw)) : void 0,
|
|
2230
2329
|
modelSource,
|
|
2231
2330
|
gatewayAgentId,
|
|
2232
2331
|
fastGatewayAgentId,
|
|
@@ -2249,13 +2348,13 @@ function parseBenchArgs(argv) {
|
|
|
2249
2348
|
internalDisableThinking: args.includes("--internal-disable-thinking"),
|
|
2250
2349
|
internalCodexReasoningEffort,
|
|
2251
2350
|
threshold,
|
|
2252
|
-
custom: customRaw ?
|
|
2351
|
+
custom: customRaw ? path6.resolve(expandTilde(customRaw)) : void 0,
|
|
2253
2352
|
baselineAction,
|
|
2254
2353
|
datasetAction,
|
|
2255
2354
|
providerAction,
|
|
2256
2355
|
runAction,
|
|
2257
2356
|
format,
|
|
2258
|
-
output: output ?
|
|
2357
|
+
output: output ? path6.resolve(expandTilde(output)) : void 0,
|
|
2259
2358
|
target,
|
|
2260
2359
|
publishedName,
|
|
2261
2360
|
publishedSeed,
|
|
@@ -2265,24 +2364,24 @@ function parseBenchArgs(argv) {
|
|
|
2265
2364
|
publishedIngestConcurrency,
|
|
2266
2365
|
publishedTaskFilter,
|
|
2267
2366
|
memcorrectAdapter,
|
|
2268
|
-
publishedOut: publishedOutRaw ?
|
|
2367
|
+
publishedOut: publishedOutRaw ? path6.resolve(expandTilde(publishedOutRaw)) : void 0,
|
|
2269
2368
|
publishedDryRun: args.includes("--dry-run"),
|
|
2270
2369
|
requestTimeout,
|
|
2271
2370
|
localJudgeRequestTimeout,
|
|
2272
2371
|
frontierJudgeRequestTimeout,
|
|
2273
|
-
calibrationDir: calibrationDirRaw ?
|
|
2372
|
+
calibrationDir: calibrationDirRaw ? path6.resolve(expandTilde(calibrationDirRaw)) : void 0,
|
|
2274
2373
|
calibrationLocalConfigSha256,
|
|
2275
2374
|
calibrationFrontierConfigSha256,
|
|
2276
2375
|
sourceResultId,
|
|
2277
2376
|
expectedAnswerSetSha256,
|
|
2278
2377
|
expectedQuestionIdListSha256,
|
|
2279
|
-
taskIdsFile: taskIdsFileRaw ?
|
|
2378
|
+
taskIdsFile: taskIdsFileRaw ? path6.resolve(expandTilde(taskIdsFileRaw)) : void 0,
|
|
2280
2379
|
expectedTaskIdListSha256,
|
|
2281
2380
|
drainTimeout,
|
|
2282
2381
|
// Issue #1573 PR1: surface judge-cache flags into the runner options.
|
|
2283
2382
|
noJudgeCache: args.includes("--no-judge-cache"),
|
|
2284
|
-
judgeCacheDir: judgeCacheDirRaw ?
|
|
2285
|
-
localLabManifestPath: localLabManifestRaw ?
|
|
2383
|
+
judgeCacheDir: judgeCacheDirRaw ? path6.resolve(expandTilde(judgeCacheDirRaw)) : void 0,
|
|
2384
|
+
localLabManifestPath: localLabManifestRaw ? path6.resolve(expandTilde(localLabManifestRaw)) : void 0,
|
|
2286
2385
|
max429WaitMs,
|
|
2287
2386
|
disableThinking: args.includes("--disable-thinking"),
|
|
2288
2387
|
amaBenchJudgeProtocol,
|
|
@@ -2292,15 +2391,18 @@ function parseBenchArgs(argv) {
|
|
|
2292
2391
|
amaBenchCrossJudgeApiKey,
|
|
2293
2392
|
amaBenchCrossJudgeCodexReasoningEffort,
|
|
2294
2393
|
resume,
|
|
2295
|
-
retryFailed
|
|
2394
|
+
retryFailed,
|
|
2395
|
+
...research,
|
|
2396
|
+
driftGenAction,
|
|
2397
|
+
driftGenDir
|
|
2296
2398
|
};
|
|
2297
2399
|
}
|
|
2298
2400
|
|
|
2299
2401
|
// src/bench-status.ts
|
|
2300
2402
|
import { mkdir, readFile, readdir as readdir2, rename, writeFile } from "fs/promises";
|
|
2301
|
-
import
|
|
2403
|
+
import path7 from "path";
|
|
2302
2404
|
function createBenchStatusPath(resultsDir, pid, startedAtMs = Date.now()) {
|
|
2303
|
-
return
|
|
2405
|
+
return path7.join(resultsDir, `bench-status-${startedAtMs}-${pid}.json`);
|
|
2304
2406
|
}
|
|
2305
2407
|
var BENCH_STATUS_FILENAME = /^bench-status-\d+-\d+\.json$/;
|
|
2306
2408
|
var VALID_BENCH_ENTRY_STATUSES = /* @__PURE__ */ new Set(["pending", "running", "complete", "failed"]);
|
|
@@ -2313,7 +2415,7 @@ async function findLatestBenchStatusFile(resultsDir) {
|
|
|
2313
2415
|
}
|
|
2314
2416
|
const candidates = entries.filter((name) => BENCH_STATUS_FILENAME.test(name)).sort().reverse();
|
|
2315
2417
|
for (const name of candidates) {
|
|
2316
|
-
const filePath =
|
|
2418
|
+
const filePath = path7.join(resultsDir, name);
|
|
2317
2419
|
const status = await readBenchStatus(filePath);
|
|
2318
2420
|
if (status) {
|
|
2319
2421
|
return filePath;
|
|
@@ -2322,7 +2424,7 @@ async function findLatestBenchStatusFile(resultsDir) {
|
|
|
2322
2424
|
return null;
|
|
2323
2425
|
}
|
|
2324
2426
|
async function atomicWriteJSON(filePath, data) {
|
|
2325
|
-
await mkdir(
|
|
2427
|
+
await mkdir(path7.dirname(filePath), { recursive: true });
|
|
2326
2428
|
const tmp = `${filePath}.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`;
|
|
2327
2429
|
await writeFile(tmp, JSON.stringify(data, null, 2) + "\n");
|
|
2328
2430
|
await rename(tmp, filePath);
|
|
@@ -2440,7 +2542,7 @@ function finalizeBenchStatus(filePath) {
|
|
|
2440
2542
|
|
|
2441
2543
|
// src/bench-fallback.ts
|
|
2442
2544
|
import fs6 from "fs";
|
|
2443
|
-
import
|
|
2545
|
+
import path8 from "path";
|
|
2444
2546
|
var FALLBACK_RESULTS_DIRNAME = "fallback-runs";
|
|
2445
2547
|
function buildBenchRunnerArgs(parsed, benchmarkId, outputDir) {
|
|
2446
2548
|
const args = ["--benchmark", benchmarkId];
|
|
@@ -2504,7 +2606,7 @@ function findUnsupportedFallbackBenchOptions(parsed) {
|
|
|
2504
2606
|
return unsupported;
|
|
2505
2607
|
}
|
|
2506
2608
|
function createFallbackBenchOutputDir(resultsDir, benchmarkId, pid, startedAtMs = Date.now()) {
|
|
2507
|
-
return
|
|
2609
|
+
return path8.join(
|
|
2508
2610
|
resultsDir,
|
|
2509
2611
|
FALLBACK_RESULTS_DIRNAME,
|
|
2510
2612
|
`${benchmarkId}-${startedAtMs}-${pid}`
|
|
@@ -2515,18 +2617,18 @@ function resolveFallbackBenchResultPath(outputDir) {
|
|
|
2515
2617
|
if (entries.length === 0) {
|
|
2516
2618
|
throw new Error(`Fallback benchmark runner did not write a JSON result artifact in ${outputDir}`);
|
|
2517
2619
|
}
|
|
2518
|
-
return
|
|
2620
|
+
return path8.join(outputDir, entries[0]);
|
|
2519
2621
|
}
|
|
2520
2622
|
|
|
2521
2623
|
// src/openclaw-upgrade-swap.ts
|
|
2522
2624
|
import fs7 from "fs";
|
|
2523
|
-
import
|
|
2625
|
+
import path9 from "path";
|
|
2524
2626
|
function describeError(error) {
|
|
2525
2627
|
return error instanceof Error ? error.message : String(error);
|
|
2526
2628
|
}
|
|
2527
2629
|
function createSiblingTempFilePath(targetPath, label) {
|
|
2528
2630
|
const nonce = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
|
|
2529
|
-
return
|
|
2631
|
+
return path9.join(path9.dirname(targetPath), `.${path9.basename(targetPath)}.${label}.${nonce}.tmp`);
|
|
2530
2632
|
}
|
|
2531
2633
|
function resolveAtomicWriteMode(targetPath, explicitMode) {
|
|
2532
2634
|
if (explicitMode !== void 0) return explicitMode;
|
|
@@ -2554,7 +2656,7 @@ function resolveAtomicReplacementPath(targetPath) {
|
|
|
2554
2656
|
}
|
|
2555
2657
|
function createSiblingSwapPath(targetDir, label) {
|
|
2556
2658
|
const nonce = `${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2, 10)}`;
|
|
2557
|
-
return
|
|
2659
|
+
return path9.join(path9.dirname(targetDir), `.${path9.basename(targetDir)}.${label}.${nonce}`);
|
|
2558
2660
|
}
|
|
2559
2661
|
function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
2560
2662
|
if (!displacedDir) return void 0;
|
|
@@ -2567,7 +2669,7 @@ function cleanupDisplacedDirectoryBestEffort(displacedDir, context) {
|
|
|
2567
2669
|
}
|
|
2568
2670
|
function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
2569
2671
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
2570
|
-
fs7.mkdirSync(
|
|
2672
|
+
fs7.mkdirSync(path9.dirname(resolvedTargetPath), { recursive: true });
|
|
2571
2673
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "write");
|
|
2572
2674
|
const mode = resolveAtomicWriteMode(resolvedTargetPath, options.mode);
|
|
2573
2675
|
try {
|
|
@@ -2587,7 +2689,7 @@ function atomicWriteFileSync(targetPath, data, options = {}) {
|
|
|
2587
2689
|
function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
2588
2690
|
if (!fs7.existsSync(sourcePath)) return;
|
|
2589
2691
|
const resolvedTargetPath = resolveAtomicReplacementPath(targetPath);
|
|
2590
|
-
fs7.mkdirSync(
|
|
2692
|
+
fs7.mkdirSync(path9.dirname(resolvedTargetPath), { recursive: true });
|
|
2591
2693
|
const tempPath = createSiblingTempFilePath(resolvedTargetPath, "copy");
|
|
2592
2694
|
const mode = fs7.statSync(sourcePath).mode & 4095;
|
|
2593
2695
|
try {
|
|
@@ -2603,7 +2705,7 @@ function atomicCopyFileSync(sourcePath, targetPath, options = {}) {
|
|
|
2603
2705
|
}
|
|
2604
2706
|
function swapDirectoryWithRollback(stagedDir, targetDir, rollbackDir) {
|
|
2605
2707
|
let hasRollbackCopy = false;
|
|
2606
|
-
fs7.mkdirSync(
|
|
2708
|
+
fs7.mkdirSync(path9.dirname(targetDir), { recursive: true });
|
|
2607
2709
|
fs7.rmSync(rollbackDir, { recursive: true, force: true });
|
|
2608
2710
|
if (fs7.existsSync(targetDir)) {
|
|
2609
2711
|
fs7.renameSync(targetDir, rollbackDir);
|
|
@@ -2645,7 +2747,7 @@ function restoreDirectoryFromRollback(targetDir, rollbackDir) {
|
|
|
2645
2747
|
if (!fs7.existsSync(rollbackDir)) {
|
|
2646
2748
|
throw new Error(`Rollback directory is missing: ${rollbackDir}`);
|
|
2647
2749
|
}
|
|
2648
|
-
fs7.mkdirSync(
|
|
2750
|
+
fs7.mkdirSync(path9.dirname(targetDir), { recursive: true });
|
|
2649
2751
|
const displacedDir = fs7.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "rollback-restore") : void 0;
|
|
2650
2752
|
if (displacedDir) {
|
|
2651
2753
|
fs7.renameSync(targetDir, displacedDir);
|
|
@@ -2677,7 +2779,7 @@ function restoreDirectoryFromBackup(targetDir, backupDir) {
|
|
|
2677
2779
|
if (!fs7.existsSync(backupDir)) {
|
|
2678
2780
|
throw new Error(`Plugin backup directory is missing: ${backupDir}`);
|
|
2679
2781
|
}
|
|
2680
|
-
fs7.mkdirSync(
|
|
2782
|
+
fs7.mkdirSync(path9.dirname(targetDir), { recursive: true });
|
|
2681
2783
|
const stagedDir = createSiblingSwapPath(targetDir, "backup-restore");
|
|
2682
2784
|
const displacedDir = fs7.existsSync(targetDir) ? createSiblingSwapPath(targetDir, "pre-backup-restore") : void 0;
|
|
2683
2785
|
fs7.cpSync(backupDir, stagedDir, { recursive: true });
|
|
@@ -2802,10 +2904,10 @@ Run this manually when you're ready:
|
|
|
2802
2904
|
|
|
2803
2905
|
// src/daemon-service.ts
|
|
2804
2906
|
import fs8 from "fs";
|
|
2805
|
-
import
|
|
2907
|
+
import path10 from "path";
|
|
2806
2908
|
import * as childProcess from "child_process";
|
|
2807
2909
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2808
|
-
var thisModuleDir =
|
|
2910
|
+
var thisModuleDir = path10.dirname(fileURLToPath3(import.meta.url));
|
|
2809
2911
|
function launchdLoadPlist(plistPath, processApi = childProcess) {
|
|
2810
2912
|
processApi.execFileSync("launchctl", ["load", "-w", plistPath], { stdio: "pipe" });
|
|
2811
2913
|
}
|
|
@@ -2827,8 +2929,8 @@ function resolveServerBinDetails(options = {}) {
|
|
|
2827
2929
|
});
|
|
2828
2930
|
} catch {
|
|
2829
2931
|
}
|
|
2830
|
-
const workspaceServerBin =
|
|
2831
|
-
const workspaceDistIndex =
|
|
2932
|
+
const workspaceServerBin = path10.resolve(moduleDir, "../../remnic-server/bin/remnic-server.js");
|
|
2933
|
+
const workspaceDistIndex = path10.resolve(moduleDir, "../../remnic-server/dist/index.js");
|
|
2832
2934
|
candidates.push(
|
|
2833
2935
|
{
|
|
2834
2936
|
path: workspaceServerBin,
|
|
@@ -2849,11 +2951,11 @@ function resolveServerBinDetails(options = {}) {
|
|
|
2849
2951
|
});
|
|
2850
2952
|
}
|
|
2851
2953
|
candidates.push({
|
|
2852
|
-
path:
|
|
2954
|
+
path: path10.resolve(moduleDir, "../../remnic-server/src/index.ts"),
|
|
2853
2955
|
source: "workspace-source"
|
|
2854
2956
|
});
|
|
2855
2957
|
const selected = candidates.find((candidate) => isCandidateReady(candidate, existsSync4)) ?? candidates.find((candidate) => existsSync4(candidate.path)) ?? candidates[0] ?? {
|
|
2856
|
-
path:
|
|
2958
|
+
path: path10.resolve(moduleDir, "../../remnic-server/dist/index.js"),
|
|
2857
2959
|
source: "workspace-dist"
|
|
2858
2960
|
};
|
|
2859
2961
|
const exists = existsSync4(selected.path);
|
|
@@ -2908,7 +3010,7 @@ function readVerifiedDaemonPid(options) {
|
|
|
2908
3010
|
}
|
|
2909
3011
|
function doesProcessCommandLookLikeRemnicDaemon(command, expectedServerBin) {
|
|
2910
3012
|
const normalizedCommand = command.trim();
|
|
2911
|
-
const normalizedExpected =
|
|
3013
|
+
const normalizedExpected = path10.resolve(expandTilde(expectedServerBin));
|
|
2912
3014
|
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);
|
|
2913
3015
|
}
|
|
2914
3016
|
function parseDaemonPid(raw) {
|
|
@@ -3013,7 +3115,7 @@ function inspectLaunchdPlist(plistPath, options = {}) {
|
|
|
3013
3115
|
};
|
|
3014
3116
|
}
|
|
3015
3117
|
const expandedServerArg = expandTilde(serverArg);
|
|
3016
|
-
if (!
|
|
3118
|
+
if (!path10.isAbsolute(expandedServerArg)) {
|
|
3017
3119
|
return {
|
|
3018
3120
|
installed: true,
|
|
3019
3121
|
ok: false,
|
|
@@ -3085,8 +3187,8 @@ function normalizeResolvedPath(resolved) {
|
|
|
3085
3187
|
return resolved;
|
|
3086
3188
|
}
|
|
3087
3189
|
function packageServerBinFromEntry(packageEntry) {
|
|
3088
|
-
if (
|
|
3089
|
-
return
|
|
3190
|
+
if (path10.basename(packageEntry) === "index.js" && path10.basename(path10.dirname(packageEntry)) === "dist") {
|
|
3191
|
+
return path10.join(path10.dirname(path10.dirname(packageEntry)), "bin", "remnic-server.js");
|
|
3090
3192
|
}
|
|
3091
3193
|
return packageEntry;
|
|
3092
3194
|
}
|
|
@@ -3217,7 +3319,7 @@ import {
|
|
|
3217
3319
|
|
|
3218
3320
|
// src/import-bundle-detect.ts
|
|
3219
3321
|
import { lstatSync as lstatSync2, readdirSync as readdirSync2, readFileSync as readFileSync3 } from "fs";
|
|
3220
|
-
import
|
|
3322
|
+
import path11 from "path";
|
|
3221
3323
|
function detectBundleEntries(bundleDir, options = {}) {
|
|
3222
3324
|
const readdir3 = options.readdirImpl ?? defaultReaddir;
|
|
3223
3325
|
const readFileImpl = options.readFileImpl ?? defaultReadFile;
|
|
@@ -3248,7 +3350,7 @@ function detectBundleEntries(bundleDir, options = {}) {
|
|
|
3248
3350
|
for (const filePath of roots) {
|
|
3249
3351
|
if (seenFiles.has(filePath)) continue;
|
|
3250
3352
|
seenFiles.add(filePath);
|
|
3251
|
-
const name =
|
|
3353
|
+
const name = path11.basename(filePath);
|
|
3252
3354
|
const match = classifyFile(name, filePath, readFileImpl);
|
|
3253
3355
|
if (match) entries.push(match);
|
|
3254
3356
|
}
|
|
@@ -3286,7 +3388,7 @@ function collectCandidatePaths(root, readdir3, isDirectory2, isRegularFile) {
|
|
|
3286
3388
|
return;
|
|
3287
3389
|
}
|
|
3288
3390
|
for (const entry of entries) {
|
|
3289
|
-
const full =
|
|
3391
|
+
const full = path11.join(dir, entry);
|
|
3290
3392
|
if (isDirectory2(full)) {
|
|
3291
3393
|
walk(full, depth + 1);
|
|
3292
3394
|
} else if (isRegularFile(full)) {
|
|
@@ -3836,7 +3938,7 @@ async function cmdCapture(rest, io) {
|
|
|
3836
3938
|
|
|
3837
3939
|
// src/import-lossless-claw-cmd.ts
|
|
3838
3940
|
import fs10 from "fs";
|
|
3839
|
-
import
|
|
3941
|
+
import path12 from "path";
|
|
3840
3942
|
import {
|
|
3841
3943
|
applyLcmSchema,
|
|
3842
3944
|
ensureLcmStateDir,
|
|
@@ -3986,7 +4088,7 @@ async function cmdImportLosslessClaw(argv, io, deps = {}) {
|
|
|
3986
4088
|
let destDb;
|
|
3987
4089
|
try {
|
|
3988
4090
|
if (parsed.dryRun) {
|
|
3989
|
-
const lcmPath =
|
|
4091
|
+
const lcmPath = path12.join(memoryDir, "state", "lcm.sqlite");
|
|
3990
4092
|
if (fs10.existsSync(lcmPath)) {
|
|
3991
4093
|
destDb = mod.openExistingLcmDatabaseReadOnly(lcmPath);
|
|
3992
4094
|
} else {
|
|
@@ -4104,106 +4206,54 @@ function printBenchComparisonSummary(comparison, baseline, candidate) {
|
|
|
4104
4206
|
}
|
|
4105
4207
|
}
|
|
4106
4208
|
|
|
4107
|
-
// src/
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
}
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4117
|
-
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
|
|
4123
|
-
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
this.delegate = void 0;
|
|
4134
|
-
throw err;
|
|
4135
|
-
});
|
|
4136
|
-
return this.delegate;
|
|
4137
|
-
}
|
|
4138
|
-
};
|
|
4139
|
-
async function loadPiPublisherModule() {
|
|
4140
|
-
return await import("@remnic/plugin-pi/publisher");
|
|
4141
|
-
}
|
|
4142
|
-
registerPublisher("codex", () => new CodexMemoryExtensionPublisher());
|
|
4143
|
-
registerPublisher("claude-code", () => new ClaudeCodeMemoryExtensionPublisher());
|
|
4144
|
-
registerPublisher("hermes", () => new HermesMemoryExtensionPublisher());
|
|
4145
|
-
registerPublisher("pi", () => new LazyPluginPiPublisher("pi", (mod) => mod.PiMemoryExtensionPublisher));
|
|
4146
|
-
registerPublisher("omp", () => new LazyPluginPiPublisher("omp", (mod) => mod.OmpMemoryExtensionPublisher));
|
|
4147
|
-
function readCompatEnv(primary, legacy) {
|
|
4148
|
-
return process.env[primary] ?? process.env[legacy];
|
|
4149
|
-
}
|
|
4150
|
-
var PID_DIR = path12.join(resolveHomeDir(), ".remnic");
|
|
4151
|
-
var LEGACY_PID_DIR = path12.join(resolveHomeDir(), ".engram");
|
|
4152
|
-
var PID_FILE = path12.join(PID_DIR, "server.pid");
|
|
4153
|
-
var LEGACY_PID_FILE = path12.join(LEGACY_PID_DIR, "server.pid");
|
|
4154
|
-
var LOG_FILE = path12.join(PID_DIR, "server.log");
|
|
4155
|
-
var LEGACY_LOG_FILE = path12.join(LEGACY_PID_DIR, "server.log");
|
|
4156
|
-
var CLI_MODULE_DIR = path12.dirname(fileURLToPath4(import.meta.url));
|
|
4157
|
-
var CLI_REPO_ROOT = path12.resolve(CLI_MODULE_DIR, "../../..");
|
|
4158
|
-
var EVAL_RUNNER_PATH = path12.join(CLI_REPO_ROOT, "evals", "run.ts");
|
|
4159
|
-
var OPENCLAW_GATEWAY_LABEL = "ai.openclaw.gateway";
|
|
4160
|
-
var CLI_SUCCESS_EXIT_GRACE_MS = 5e3;
|
|
4161
|
-
var CLI_OUTPUT_FLUSH_GRACE_MS = 250;
|
|
4162
|
-
var BENCHMARK_CATALOG = [
|
|
4163
|
-
{
|
|
4164
|
-
id: "ama-bench",
|
|
4165
|
-
title: "AMA-Bench",
|
|
4166
|
-
category: "agentic",
|
|
4167
|
-
summary: "Agent Memory Abilities benchmark for long-horizon agent workflows."
|
|
4168
|
-
},
|
|
4169
|
-
{
|
|
4170
|
-
id: "memory-arena",
|
|
4171
|
-
title: "Memory Arena",
|
|
4172
|
-
category: "agentic",
|
|
4173
|
-
summary: "Interdependent multi-session tasks that stress operational recall."
|
|
4174
|
-
},
|
|
4175
|
-
{
|
|
4176
|
-
id: "amemgym",
|
|
4177
|
-
title: "AMemGym",
|
|
4178
|
-
category: "agentic",
|
|
4179
|
-
summary: "Interactive personalization benchmark for agent memory adaptation."
|
|
4180
|
-
},
|
|
4181
|
-
{
|
|
4182
|
-
id: "longmemeval",
|
|
4183
|
-
title: "LongMemEval",
|
|
4184
|
-
category: "retrieval",
|
|
4185
|
-
summary: "Long-term memory retrieval benchmark across core memory abilities."
|
|
4186
|
-
},
|
|
4187
|
-
{
|
|
4188
|
-
id: "locomo",
|
|
4189
|
-
title: "LoCoMo",
|
|
4190
|
-
category: "conversational",
|
|
4191
|
-
summary: "Long-conversation memory benchmark for persistent dialogue context."
|
|
4192
|
-
},
|
|
4193
|
-
{
|
|
4194
|
-
id: "beam",
|
|
4195
|
-
title: "BEAM",
|
|
4196
|
-
category: "retrieval",
|
|
4197
|
-
summary: "Beyond a Million Tokens benchmark for long-term memory abilities."
|
|
4209
|
+
// src/bench-research-commands.ts
|
|
4210
|
+
import path13 from "path";
|
|
4211
|
+
function emit(result) {
|
|
4212
|
+
if (result.output) {
|
|
4213
|
+
console.log(result.output);
|
|
4214
|
+
}
|
|
4215
|
+
if (result.exitCode !== 0) {
|
|
4216
|
+
process.exitCode = result.exitCode;
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4219
|
+
async function runBenchResearchCommand(parsed) {
|
|
4220
|
+
if (parsed.action === "attribute") {
|
|
4221
|
+
if (!parsed.runRef) {
|
|
4222
|
+
throw new Error("ERROR: bench attribute requires --run <id>.");
|
|
4223
|
+
}
|
|
4224
|
+
const { runAttributeCliCommand } = await loadBenchModule();
|
|
4225
|
+
emit(
|
|
4226
|
+
await runAttributeCliCommand({
|
|
4227
|
+
runRef: parsed.runRef,
|
|
4228
|
+
resultsDir: parsed.resultsDir ?? path13.join(resolveHomeDir(), ".remnic", "bench", "results"),
|
|
4229
|
+
memoryDir: parsed.memoryDir,
|
|
4230
|
+
threshold: parsed.threshold,
|
|
4231
|
+
json: parsed.json
|
|
4232
|
+
})
|
|
4233
|
+
);
|
|
4234
|
+
return;
|
|
4198
4235
|
}
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4236
|
+
const { runDriftGenCliCommand } = await loadBenchModule();
|
|
4237
|
+
emit(
|
|
4238
|
+
await runDriftGenCliCommand({
|
|
4239
|
+
action: parsed.driftGenAction ?? "generate",
|
|
4240
|
+
dir: parsed.driftGenDir,
|
|
4241
|
+
users: parsed.users,
|
|
4242
|
+
epochs: parsed.epochs,
|
|
4243
|
+
seed: parsed.seed,
|
|
4244
|
+
out: parsed.out,
|
|
4245
|
+
factsPerEpoch: parsed.factsPerEpoch,
|
|
4246
|
+
driftingRatio: parsed.driftingRatio,
|
|
4247
|
+
contradictedRatio: parsed.contradictedRatio,
|
|
4248
|
+
json: parsed.json
|
|
4249
|
+
})
|
|
4250
|
+
);
|
|
4203
4251
|
}
|
|
4252
|
+
|
|
4253
|
+
// src/bench-usage.ts
|
|
4204
4254
|
function getBenchUsageText() {
|
|
4205
|
-
return `Usage: remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate> [options] [benchmark...]
|
|
4206
|
-
remnic benchmark <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|check|report> [options] [benchmark...]
|
|
4255
|
+
return `Usage: remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|attribute|drift-gen> [options] [benchmark...]
|
|
4256
|
+
remnic benchmark <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|check|report|attribute|drift-gen> [options] [benchmark...]
|
|
4207
4257
|
|
|
4208
4258
|
Commands:
|
|
4209
4259
|
list List published benchmark packs
|
|
@@ -4239,6 +4289,12 @@ Commands:
|
|
|
4239
4289
|
answers, reports Cohen's kappa, and persists it so
|
|
4240
4290
|
subsequent local artifacts carry the kappa + warning.
|
|
4241
4291
|
check Legacy latency regression gate (compatibility)
|
|
4292
|
+
attribute --run <id> [--results-dir <path>] [--memory-dir <path>] [--threshold <value>]
|
|
4293
|
+
Attribute operation-level benchmark failures to memory operations
|
|
4294
|
+
drift-gen [generate|validate <dir>] [--users <n>] [--epochs <n>] [--seed <n>]
|
|
4295
|
+
[--out <dir>] [--facts-per-epoch <n>] [--drifting-ratio <r>]
|
|
4296
|
+
[--contradicted-ratio <r>]
|
|
4297
|
+
Generate or validate synthetic memory drift bench corpora
|
|
4242
4298
|
report Legacy latency report generator (compatibility)
|
|
4243
4299
|
procedural-ablation --out <path> [--fixture <path>]
|
|
4244
4300
|
Run the procedural recall ablation harness (issue #567)
|
|
@@ -4327,7 +4383,8 @@ Options:
|
|
|
4327
4383
|
(defaults to --request-timeout; implicit codex-cli default: 600000)
|
|
4328
4384
|
--local-lab-manifest <path>
|
|
4329
4385
|
Path to a local-lab manifest JSON file (required for --runtime-profile local-lab)
|
|
4330
|
-
--threshold <value> Regression threshold for compare (default: 0.05)
|
|
4386
|
+
--threshold <value> Regression threshold for compare (default: 0.05);
|
|
4387
|
+
gold-memory similarity threshold for attribute (default: 0.6)
|
|
4331
4388
|
--trial-limit <n> Cap scored LoCoMo or MemoryAgentBench QA trials for staged published runs
|
|
4332
4389
|
--task-ids-file <path> Select an explicit JSON array of LoCoMo task IDs
|
|
4333
4390
|
--expected-task-id-list-sha256 <sha256>
|
|
@@ -4338,6 +4395,13 @@ Options:
|
|
|
4338
4395
|
--output <path> Write bench export output to a file
|
|
4339
4396
|
--target <name> Publish target for bench publish (remnic-ai)
|
|
4340
4397
|
--json Output JSON for \`list\`
|
|
4398
|
+
--run <id> Benchmark run reference for attribute
|
|
4399
|
+
--memory-dir <path> Memory directory for failure attribution
|
|
4400
|
+
--users <n> Synthetic user count for drift-gen
|
|
4401
|
+
--epochs <n> Synthetic timeline epochs for drift-gen
|
|
4402
|
+
--facts-per-epoch <n> Facts generated per user per epoch for drift-gen
|
|
4403
|
+
--drifting-ratio <r> Ratio of facts that undergo drift across epochs
|
|
4404
|
+
--contradicted-ratio <r> Ratio of drifting facts that are direct contradictions
|
|
4341
4405
|
|
|
4342
4406
|
Examples:
|
|
4343
4407
|
remnic bench list
|
|
@@ -4367,8 +4431,109 @@ Examples:
|
|
|
4367
4431
|
remnic bench providers discover
|
|
4368
4432
|
remnic bench run --custom ./my-bench.yaml
|
|
4369
4433
|
remnic bench procedural-ablation --out ./artifacts/procedural-ablation.json
|
|
4434
|
+
remnic bench attribute --run run-12345 --memory-dir ./memories
|
|
4435
|
+
remnic bench drift-gen generate --users 20 --epochs 10 --out ./corpus
|
|
4436
|
+
remnic bench drift-gen validate ./corpus
|
|
4370
4437
|
remnic benchmark run --quick longmemeval`;
|
|
4371
4438
|
}
|
|
4439
|
+
|
|
4440
|
+
// src/index.ts
|
|
4441
|
+
var LazyPluginPiPublisher = class {
|
|
4442
|
+
constructor(hostId, select) {
|
|
4443
|
+
this.hostId = hostId;
|
|
4444
|
+
this.select = select;
|
|
4445
|
+
}
|
|
4446
|
+
hostId;
|
|
4447
|
+
select;
|
|
4448
|
+
delegate;
|
|
4449
|
+
async resolveExtensionRoot(env) {
|
|
4450
|
+
return (await this.load()).resolveExtensionRoot(env);
|
|
4451
|
+
}
|
|
4452
|
+
async isHostAvailable() {
|
|
4453
|
+
return (await this.load()).isHostAvailable();
|
|
4454
|
+
}
|
|
4455
|
+
async renderInstructions(ctx) {
|
|
4456
|
+
return (await this.load()).renderInstructions(ctx);
|
|
4457
|
+
}
|
|
4458
|
+
async publish(ctx) {
|
|
4459
|
+
return (await this.load()).publish(ctx);
|
|
4460
|
+
}
|
|
4461
|
+
async unpublish() {
|
|
4462
|
+
return (await this.load()).unpublish();
|
|
4463
|
+
}
|
|
4464
|
+
async load() {
|
|
4465
|
+
this.delegate ??= loadPiPublisherModule().then((mod) => new (this.select(mod))()).catch((err) => {
|
|
4466
|
+
this.delegate = void 0;
|
|
4467
|
+
throw err;
|
|
4468
|
+
});
|
|
4469
|
+
return this.delegate;
|
|
4470
|
+
}
|
|
4471
|
+
};
|
|
4472
|
+
async function loadPiPublisherModule() {
|
|
4473
|
+
return await import("@remnic/plugin-pi/publisher");
|
|
4474
|
+
}
|
|
4475
|
+
registerPublisher("codex", () => new CodexMemoryExtensionPublisher());
|
|
4476
|
+
registerPublisher("claude-code", () => new ClaudeCodeMemoryExtensionPublisher());
|
|
4477
|
+
registerPublisher("hermes", () => new HermesMemoryExtensionPublisher());
|
|
4478
|
+
registerPublisher("pi", () => new LazyPluginPiPublisher("pi", (mod) => mod.PiMemoryExtensionPublisher));
|
|
4479
|
+
registerPublisher("omp", () => new LazyPluginPiPublisher("omp", (mod) => mod.OmpMemoryExtensionPublisher));
|
|
4480
|
+
function readCompatEnv(primary, legacy) {
|
|
4481
|
+
return process.env[primary] ?? process.env[legacy];
|
|
4482
|
+
}
|
|
4483
|
+
var PID_DIR = path14.join(resolveHomeDir(), ".remnic");
|
|
4484
|
+
var LEGACY_PID_DIR = path14.join(resolveHomeDir(), ".engram");
|
|
4485
|
+
var PID_FILE = path14.join(PID_DIR, "server.pid");
|
|
4486
|
+
var LEGACY_PID_FILE = path14.join(LEGACY_PID_DIR, "server.pid");
|
|
4487
|
+
var LOG_FILE = path14.join(PID_DIR, "server.log");
|
|
4488
|
+
var LEGACY_LOG_FILE = path14.join(LEGACY_PID_DIR, "server.log");
|
|
4489
|
+
var CLI_MODULE_DIR = path14.dirname(fileURLToPath4(import.meta.url));
|
|
4490
|
+
var CLI_REPO_ROOT = path14.resolve(CLI_MODULE_DIR, "../../..");
|
|
4491
|
+
var EVAL_RUNNER_PATH = path14.join(CLI_REPO_ROOT, "evals", "run.ts");
|
|
4492
|
+
var OPENCLAW_GATEWAY_LABEL = "ai.openclaw.gateway";
|
|
4493
|
+
var CLI_SUCCESS_EXIT_GRACE_MS = 5e3;
|
|
4494
|
+
var CLI_OUTPUT_FLUSH_GRACE_MS = 250;
|
|
4495
|
+
var BENCHMARK_CATALOG = [
|
|
4496
|
+
{
|
|
4497
|
+
id: "ama-bench",
|
|
4498
|
+
title: "AMA-Bench",
|
|
4499
|
+
category: "agentic",
|
|
4500
|
+
summary: "Agent Memory Abilities benchmark for long-horizon agent workflows."
|
|
4501
|
+
},
|
|
4502
|
+
{
|
|
4503
|
+
id: "memory-arena",
|
|
4504
|
+
title: "Memory Arena",
|
|
4505
|
+
category: "agentic",
|
|
4506
|
+
summary: "Interdependent multi-session tasks that stress operational recall."
|
|
4507
|
+
},
|
|
4508
|
+
{
|
|
4509
|
+
id: "amemgym",
|
|
4510
|
+
title: "AMemGym",
|
|
4511
|
+
category: "agentic",
|
|
4512
|
+
summary: "Interactive personalization benchmark for agent memory adaptation."
|
|
4513
|
+
},
|
|
4514
|
+
{
|
|
4515
|
+
id: "longmemeval",
|
|
4516
|
+
title: "LongMemEval",
|
|
4517
|
+
category: "retrieval",
|
|
4518
|
+
summary: "Long-term memory retrieval benchmark across core memory abilities."
|
|
4519
|
+
},
|
|
4520
|
+
{
|
|
4521
|
+
id: "locomo",
|
|
4522
|
+
title: "LoCoMo",
|
|
4523
|
+
category: "conversational",
|
|
4524
|
+
summary: "Long-conversation memory benchmark for persistent dialogue context."
|
|
4525
|
+
},
|
|
4526
|
+
{
|
|
4527
|
+
id: "beam",
|
|
4528
|
+
title: "BEAM",
|
|
4529
|
+
category: "retrieval",
|
|
4530
|
+
summary: "Beyond a Million Tokens benchmark for long-term memory abilities."
|
|
4531
|
+
}
|
|
4532
|
+
];
|
|
4533
|
+
var BENCHMARK_IDS = new Set(BENCHMARK_CATALOG.map((entry) => entry.id));
|
|
4534
|
+
async function loadTrainingExportCoreRuntime() {
|
|
4535
|
+
return await import("@remnic/core");
|
|
4536
|
+
}
|
|
4372
4537
|
function buildBenchRuntimeProfileRequest(parsed, runtimeProfile) {
|
|
4373
4538
|
return {
|
|
4374
4539
|
runtimeProfile,
|
|
@@ -4543,8 +4708,8 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
4543
4708
|
process.exit(1);
|
|
4544
4709
|
}
|
|
4545
4710
|
const tsxCandidates = [
|
|
4546
|
-
|
|
4547
|
-
|
|
4711
|
+
path14.join(CLI_REPO_ROOT, "node_modules", ".bin", "tsx"),
|
|
4712
|
+
path14.join(CLI_REPO_ROOT, "packages", "remnic-cli", "node_modules", ".bin", "tsx")
|
|
4548
4713
|
];
|
|
4549
4714
|
const tsxCmd = tsxCandidates.find((candidate) => fs11.existsSync(candidate)) ?? "tsx";
|
|
4550
4715
|
const fallbackOutputDir = createFallbackBenchOutputDir(
|
|
@@ -4563,7 +4728,7 @@ async function runBenchViaFallback(parsed, benchmarkId, runtimeProfile) {
|
|
|
4563
4728
|
return resolveFallbackBenchResultPath(fallbackOutputDir);
|
|
4564
4729
|
}
|
|
4565
4730
|
function resolveBenchOutputDir() {
|
|
4566
|
-
return
|
|
4731
|
+
return path14.join(resolveHomeDir(), ".remnic", "bench", "results");
|
|
4567
4732
|
}
|
|
4568
4733
|
var DOWNLOADABLE_BENCHMARK_DATASETS = [
|
|
4569
4734
|
"ama-bench",
|
|
@@ -4608,8 +4773,8 @@ var MEMORY_AGENT_BENCH_SPLIT_FILENAMES = [
|
|
|
4608
4773
|
];
|
|
4609
4774
|
var MEMORY_AGENT_BENCH_ENTITY_MAPPING_CANDIDATES = [
|
|
4610
4775
|
"entity2id.json",
|
|
4611
|
-
|
|
4612
|
-
|
|
4776
|
+
path14.join("processed_data", "Recsys_Redial", "entity2id.json"),
|
|
4777
|
+
path14.join("Recsys_Redial", "entity2id.json")
|
|
4613
4778
|
];
|
|
4614
4779
|
var DOWNLOADED_DATASET_MARKERS = {
|
|
4615
4780
|
"ama-bench": { anyOf: ["open_end_qa_set.jsonl"] },
|
|
@@ -4684,7 +4849,7 @@ var PERSONAMEM_DATASET_FILE_CANDIDATES = [
|
|
|
4684
4849
|
"benchmark/benchmark.csv",
|
|
4685
4850
|
"benchmark.csv"
|
|
4686
4851
|
];
|
|
4687
|
-
var PERSONAMEM_COMPLETION_MARKER =
|
|
4852
|
+
var PERSONAMEM_COMPLETION_MARKER = path14.join(
|
|
4688
4853
|
"data",
|
|
4689
4854
|
"chat_history_32k",
|
|
4690
4855
|
".download-complete"
|
|
@@ -4692,10 +4857,10 @@ var PERSONAMEM_COMPLETION_MARKER = path12.join(
|
|
|
4692
4857
|
function resolveRealpathWithinDataset(datasetPath, relativePath) {
|
|
4693
4858
|
try {
|
|
4694
4859
|
const datasetRoot = fs11.realpathSync(datasetPath);
|
|
4695
|
-
const candidatePath =
|
|
4860
|
+
const candidatePath = path14.resolve(datasetRoot, relativePath);
|
|
4696
4861
|
const candidateRealPath = fs11.realpathSync(candidatePath);
|
|
4697
|
-
const relativeToRoot =
|
|
4698
|
-
if (relativeToRoot.startsWith("..") ||
|
|
4862
|
+
const relativeToRoot = path14.relative(datasetRoot, candidateRealPath);
|
|
4863
|
+
if (relativeToRoot.startsWith("..") || path14.isAbsolute(relativeToRoot)) {
|
|
4699
4864
|
return null;
|
|
4700
4865
|
}
|
|
4701
4866
|
return candidateRealPath;
|
|
@@ -4751,7 +4916,7 @@ function parseCsvRows(raw) {
|
|
|
4751
4916
|
}
|
|
4752
4917
|
function isPersonaMemDatasetComplete(datasetPath) {
|
|
4753
4918
|
try {
|
|
4754
|
-
const completionMarkerPath =
|
|
4919
|
+
const completionMarkerPath = path14.join(datasetPath, PERSONAMEM_COMPLETION_MARKER);
|
|
4755
4920
|
if (fs11.statSync(completionMarkerPath).isFile()) {
|
|
4756
4921
|
return true;
|
|
4757
4922
|
}
|
|
@@ -4759,7 +4924,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4759
4924
|
}
|
|
4760
4925
|
const datasetFile = PERSONAMEM_DATASET_FILE_CANDIDATES.find((candidate) => {
|
|
4761
4926
|
try {
|
|
4762
|
-
return fs11.statSync(
|
|
4927
|
+
return fs11.statSync(path14.join(datasetPath, candidate)).isFile();
|
|
4763
4928
|
} catch {
|
|
4764
4929
|
return false;
|
|
4765
4930
|
}
|
|
@@ -4768,7 +4933,7 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4768
4933
|
return false;
|
|
4769
4934
|
}
|
|
4770
4935
|
try {
|
|
4771
|
-
const rows = parseCsvRows(fs11.readFileSync(
|
|
4936
|
+
const rows = parseCsvRows(fs11.readFileSync(path14.join(datasetPath, datasetFile), "utf8"));
|
|
4772
4937
|
if (rows.length < 2) {
|
|
4773
4938
|
return false;
|
|
4774
4939
|
}
|
|
@@ -4791,14 +4956,14 @@ function isPersonaMemDatasetComplete(datasetPath) {
|
|
|
4791
4956
|
}
|
|
4792
4957
|
function hasDatasetFile(datasetPath, relativePath) {
|
|
4793
4958
|
try {
|
|
4794
|
-
return fs11.statSync(
|
|
4959
|
+
return fs11.statSync(path14.join(datasetPath, relativePath)).isFile();
|
|
4795
4960
|
} catch {
|
|
4796
4961
|
return false;
|
|
4797
4962
|
}
|
|
4798
4963
|
}
|
|
4799
4964
|
function hasMemoryAgentBenchEntityMapping(datasetPath) {
|
|
4800
|
-
const absoluteDatasetPath =
|
|
4801
|
-
const roots = [absoluteDatasetPath,
|
|
4965
|
+
const absoluteDatasetPath = path14.resolve(datasetPath);
|
|
4966
|
+
const roots = [absoluteDatasetPath, path14.dirname(absoluteDatasetPath)];
|
|
4802
4967
|
return hasDatasetFile(absoluteDatasetPath, "entity2id.json") || roots.some(
|
|
4803
4968
|
(root) => MEMORY_AGENT_BENCH_ENTITY_MAPPING_CANDIDATES.filter((relativePath) => relativePath !== "entity2id.json").some((relativePath) => hasDatasetFile(root, relativePath))
|
|
4804
4969
|
);
|
|
@@ -4809,7 +4974,7 @@ function memoryAgentBenchDatasetHasRecSysSamples(datasetPath) {
|
|
|
4809
4974
|
...MEMORY_AGENT_BENCH_SPLIT_FILENAMES
|
|
4810
4975
|
];
|
|
4811
4976
|
return candidateFilenames.some((filename) => {
|
|
4812
|
-
const filePath =
|
|
4977
|
+
const filePath = path14.join(datasetPath, filename);
|
|
4813
4978
|
try {
|
|
4814
4979
|
if (!fs11.statSync(filePath).isFile()) {
|
|
4815
4980
|
return false;
|
|
@@ -4848,7 +5013,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4848
5013
|
if (marker.allOf) {
|
|
4849
5014
|
const hasAllRequiredFiles = marker.allOf.every((name) => {
|
|
4850
5015
|
try {
|
|
4851
|
-
return fs11.statSync(
|
|
5016
|
+
return fs11.statSync(path14.join(datasetPath, name)).isFile();
|
|
4852
5017
|
} catch {
|
|
4853
5018
|
return false;
|
|
4854
5019
|
}
|
|
@@ -4860,7 +5025,7 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4860
5025
|
if (marker.anyOf) {
|
|
4861
5026
|
const hasMarkerFile = marker.anyOf.some((name) => {
|
|
4862
5027
|
try {
|
|
4863
|
-
return fs11.statSync(
|
|
5028
|
+
return fs11.statSync(path14.join(datasetPath, name)).isFile();
|
|
4864
5029
|
} catch {
|
|
4865
5030
|
return false;
|
|
4866
5031
|
}
|
|
@@ -4888,9 +5053,9 @@ function isDatasetDownloaded(datasetPath, benchmarkId) {
|
|
|
4888
5053
|
return false;
|
|
4889
5054
|
}
|
|
4890
5055
|
async function launchBenchUi(resultsDir) {
|
|
4891
|
-
const benchUiDir =
|
|
5056
|
+
const benchUiDir = path14.join(CLI_REPO_ROOT, "packages", "bench-ui");
|
|
4892
5057
|
const pnpmCmd = process.platform === "win32" ? "pnpm.cmd" : "pnpm";
|
|
4893
|
-
if (!fs11.existsSync(
|
|
5058
|
+
if (!fs11.existsSync(path14.join(benchUiDir, "package.json"))) {
|
|
4894
5059
|
console.error("ERROR: @remnic/bench-ui is not available in this checkout.");
|
|
4895
5060
|
process.exit(1);
|
|
4896
5061
|
}
|
|
@@ -4917,24 +5082,24 @@ async function launchBenchUi(resultsDir) {
|
|
|
4917
5082
|
});
|
|
4918
5083
|
}
|
|
4919
5084
|
function resolveRepoDatasetRoot() {
|
|
4920
|
-
const repoCandidate =
|
|
5085
|
+
const repoCandidate = path14.join(CLI_REPO_ROOT, "evals", "datasets");
|
|
4921
5086
|
if (isRepoCheckout()) {
|
|
4922
5087
|
return repoCandidate;
|
|
4923
5088
|
}
|
|
4924
|
-
return
|
|
5089
|
+
return path14.join(resolveHomeDir(), ".remnic", "bench", "datasets");
|
|
4925
5090
|
}
|
|
4926
5091
|
function listDownloadableBenchmarks() {
|
|
4927
5092
|
return [...DOWNLOADABLE_BENCHMARK_DATASETS];
|
|
4928
5093
|
}
|
|
4929
5094
|
function resolveDatasetDownloadScriptPath() {
|
|
4930
|
-
const bundled =
|
|
5095
|
+
const bundled = path14.join(CLI_MODULE_DIR, "assets", "download-datasets.sh");
|
|
4931
5096
|
if (fs11.existsSync(bundled)) {
|
|
4932
5097
|
return bundled;
|
|
4933
5098
|
}
|
|
4934
|
-
return
|
|
5099
|
+
return path14.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh");
|
|
4935
5100
|
}
|
|
4936
5101
|
function isRepoCheckout() {
|
|
4937
|
-
return fs11.existsSync(
|
|
5102
|
+
return fs11.existsSync(path14.join(CLI_REPO_ROOT, "pnpm-workspace.yaml")) && fs11.existsSync(path14.join(CLI_REPO_ROOT, "evals", "scripts", "download-datasets.sh"));
|
|
4938
5103
|
}
|
|
4939
5104
|
function runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, jsonMode) {
|
|
4940
5105
|
const stdio = jsonMode ? ["inherit", process.stderr, "inherit"] : "inherit";
|
|
@@ -4985,7 +5150,7 @@ function resolveBenchDatasetDir(benchmarkId, quick, datasetDirOverride) {
|
|
|
4985
5150
|
if (quick) {
|
|
4986
5151
|
return void 0;
|
|
4987
5152
|
}
|
|
4988
|
-
const datasetDir =
|
|
5153
|
+
const datasetDir = path14.join(resolveRepoDatasetRoot(), benchmarkId);
|
|
4989
5154
|
if (isDatasetDownloaded(datasetDir, benchmarkId)) {
|
|
4990
5155
|
return datasetDir;
|
|
4991
5156
|
}
|
|
@@ -5242,12 +5407,12 @@ async function exportBenchPackageResult(parsed) {
|
|
|
5242
5407
|
process.exit(1);
|
|
5243
5408
|
}
|
|
5244
5409
|
const result = await loadBenchmarkResult(summary.path);
|
|
5245
|
-
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(
|
|
5410
|
+
const reportCardProvenance = parsed.format === "html" ? await loadBenchmarkReportCardProvenance(path14.dirname(summary.path), result.meta.id) : void 0;
|
|
5246
5411
|
const rendered = renderBenchmarkResultExport(result, parsed.format, {
|
|
5247
5412
|
...reportCardProvenance ? { reportCardProvenance } : {}
|
|
5248
5413
|
});
|
|
5249
5414
|
if (parsed.output) {
|
|
5250
|
-
fs11.mkdirSync(
|
|
5415
|
+
fs11.mkdirSync(path14.dirname(parsed.output), { recursive: true });
|
|
5251
5416
|
fs11.writeFileSync(parsed.output, rendered);
|
|
5252
5417
|
console.log(`Exported ${summary.id} as ${parsed.format} to ${parsed.output}`);
|
|
5253
5418
|
return;
|
|
@@ -5265,7 +5430,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
5265
5430
|
process.exit(1);
|
|
5266
5431
|
}
|
|
5267
5432
|
const status = supported.map((benchmarkId) => {
|
|
5268
|
-
const datasetPath =
|
|
5433
|
+
const datasetPath = path14.join(datasetRoot, benchmarkId);
|
|
5269
5434
|
return {
|
|
5270
5435
|
benchmark: benchmarkId,
|
|
5271
5436
|
downloaded: isDatasetDownloaded(datasetPath, benchmarkId),
|
|
@@ -5303,7 +5468,7 @@ async function manageBenchDatasets(parsed) {
|
|
|
5303
5468
|
runDatasetDownloadScript(scriptPath, benchmarkId, datasetRoot, parsed.json === true);
|
|
5304
5469
|
downloaded.push({
|
|
5305
5470
|
benchmark: benchmarkId,
|
|
5306
|
-
path:
|
|
5471
|
+
path: path14.join(datasetRoot, benchmarkId)
|
|
5307
5472
|
});
|
|
5308
5473
|
}
|
|
5309
5474
|
if (parsed.json) {
|
|
@@ -5442,10 +5607,10 @@ async function calibrateBenchJudges(parsed, rawArgs) {
|
|
|
5442
5607
|
}
|
|
5443
5608
|
const bench = await loadBenchModule();
|
|
5444
5609
|
const resultsDir = expandTilde(
|
|
5445
|
-
parsed.resultsDir ??
|
|
5610
|
+
parsed.resultsDir ?? path14.join(resolveHomeDir(), ".remnic", "bench", "results")
|
|
5446
5611
|
);
|
|
5447
5612
|
const calibrationDir = expandTilde(
|
|
5448
|
-
parsed.calibrationDir ??
|
|
5613
|
+
parsed.calibrationDir ?? path14.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
5449
5614
|
);
|
|
5450
5615
|
const stored = await bench.listBenchmarkResults(resultsDir);
|
|
5451
5616
|
const allForBenchmark = stored.filter((entry) => entry.benchmark === benchmarkId);
|
|
@@ -6005,7 +6170,7 @@ async function loadPublishedPromotionHelpers() {
|
|
|
6005
6170
|
return {
|
|
6006
6171
|
async promoteArtifactsToPublished(args) {
|
|
6007
6172
|
const { mkdirSync, readFileSync: readFileSync4, writeFileSync } = await import("fs");
|
|
6008
|
-
const
|
|
6173
|
+
const path15 = await import("path");
|
|
6009
6174
|
mkdirSync(args.publishedOutDir, { recursive: true });
|
|
6010
6175
|
if (args.artifactPaths.length === 0) {
|
|
6011
6176
|
console.warn(
|
|
@@ -6022,13 +6187,13 @@ async function loadPublishedPromotionHelpers() {
|
|
|
6022
6187
|
const modelSlug = args.model.replace(/[^a-zA-Z0-9_.-]/g, "-");
|
|
6023
6188
|
const rawProfile = parsedObj.config?.runtimeProfile;
|
|
6024
6189
|
const profileSlug = typeof rawProfile === "string" && rawProfile.length > 0 ? `-${rawProfile.replace(/[^a-zA-Z0-9_.-]/g, "-")}` : "";
|
|
6025
|
-
const target =
|
|
6190
|
+
const target = path15.join(
|
|
6026
6191
|
args.publishedOutDir,
|
|
6027
6192
|
`${today}-${args.benchmarkId}-${modelSlug}${profileSlug}-${gitShaShort}.json`
|
|
6028
6193
|
);
|
|
6029
6194
|
writeFileSync(target, raw, "utf8");
|
|
6030
6195
|
console.log(
|
|
6031
|
-
`[bench published] Promoted ${
|
|
6196
|
+
`[bench published] Promoted ${path15.basename(artifactPath)} \u2192 ${target}`
|
|
6032
6197
|
);
|
|
6033
6198
|
}
|
|
6034
6199
|
void benchModule;
|
|
@@ -6135,7 +6300,7 @@ async function runBenchViaPackage(parsed, benchmarkId, runtimeProfile, benchStat
|
|
|
6135
6300
|
const previousCodexDiagnosticsDir = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV];
|
|
6136
6301
|
const previousCodexDiagnosticsMode = process.env[CODEX_CLI_BENCH_DIAGNOSTICS_MODE_ENV];
|
|
6137
6302
|
if (!previousCodexDiagnosticsDir) {
|
|
6138
|
-
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] =
|
|
6303
|
+
process.env[CODEX_CLI_BENCH_DIAGNOSTICS_DIR_ENV] = path14.join(
|
|
6139
6304
|
outputDir,
|
|
6140
6305
|
"codex-cli-diagnostics"
|
|
6141
6306
|
);
|
|
@@ -6283,7 +6448,7 @@ async function preparePersistedJudgeCalibrationAttachment(benchModule, benchmark
|
|
|
6283
6448
|
);
|
|
6284
6449
|
}
|
|
6285
6450
|
const calibrationDir = expandTilde(
|
|
6286
|
-
calibrationBinding.calibrationDir ??
|
|
6451
|
+
calibrationBinding.calibrationDir ?? path14.join(resolveHomeDir(), ".remnic", "bench", "calibration")
|
|
6287
6452
|
);
|
|
6288
6453
|
const state = await benchModule.loadJudgeCalibrationState?.(benchmarkId, calibrationDir);
|
|
6289
6454
|
if (!state) {
|
|
@@ -6633,19 +6798,19 @@ async function writeBenchReproManifestForPackageRun(args) {
|
|
|
6633
6798
|
}
|
|
6634
6799
|
}
|
|
6635
6800
|
function resolveConfigPath(cliPath) {
|
|
6636
|
-
if (cliPath) return
|
|
6801
|
+
if (cliPath) return path14.resolve(expandTilde(cliPath));
|
|
6637
6802
|
const envPath = readCompatEnv("REMNIC_CONFIG_PATH", "ENGRAM_CONFIG_PATH");
|
|
6638
|
-
if (envPath) return
|
|
6803
|
+
if (envPath) return path14.resolve(expandTilde(envPath));
|
|
6639
6804
|
const candidates = [
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6805
|
+
path14.join(process.cwd(), "remnic.config.json"),
|
|
6806
|
+
path14.join(process.cwd(), "engram.config.json"),
|
|
6807
|
+
path14.join(resolveHomeDir(), ".config", "remnic", "config.json"),
|
|
6808
|
+
path14.join(resolveHomeDir(), ".config", "engram", "config.json")
|
|
6644
6809
|
];
|
|
6645
6810
|
for (const candidate of candidates) {
|
|
6646
6811
|
if (fs11.existsSync(candidate)) return candidate;
|
|
6647
6812
|
}
|
|
6648
|
-
return
|
|
6813
|
+
return path14.join(resolveHomeDir(), ".config", "remnic", "config.json");
|
|
6649
6814
|
}
|
|
6650
6815
|
function resolveExistingBenchRemnicConfigPath(cliPath) {
|
|
6651
6816
|
const configPath = resolveConfigPath(cliPath);
|
|
@@ -6759,7 +6924,7 @@ async function resolvePackageBenchRuntime(benchModule, parsed, runtimeProfile) {
|
|
|
6759
6924
|
);
|
|
6760
6925
|
}
|
|
6761
6926
|
function normalizeMemoryDirPath(memoryDir) {
|
|
6762
|
-
return
|
|
6927
|
+
return path14.resolve(expandTilde(memoryDir));
|
|
6763
6928
|
}
|
|
6764
6929
|
function resolveMemoryDir() {
|
|
6765
6930
|
const configMemoryDir = (() => {
|
|
@@ -6772,9 +6937,9 @@ function resolveMemoryDir() {
|
|
|
6772
6937
|
return normalizeMemoryDirPath(remnicCfg.memoryDir);
|
|
6773
6938
|
}
|
|
6774
6939
|
const home = resolveHomeDir();
|
|
6775
|
-
const standalonePath =
|
|
6776
|
-
const legacyStandalonePath =
|
|
6777
|
-
const openclawPath =
|
|
6940
|
+
const standalonePath = path14.join(home, ".remnic", "memory");
|
|
6941
|
+
const legacyStandalonePath = path14.join(home, ".engram", "memory");
|
|
6942
|
+
const openclawPath = path14.join(home, ".openclaw", "workspace", "memory", "local");
|
|
6778
6943
|
if (fs11.existsSync(standalonePath)) return standalonePath;
|
|
6779
6944
|
if (fs11.existsSync(legacyStandalonePath)) return legacyStandalonePath;
|
|
6780
6945
|
return openclawPath;
|
|
@@ -6825,16 +6990,16 @@ var REMNIC_OPENCLAW_LEGACY_PLUGIN_ID = "openclaw-engram";
|
|
|
6825
6990
|
var DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR = [
|
|
6826
6991
|
process.env.OPENCLAW_CONFIG_PATH,
|
|
6827
6992
|
process.env.OPENCLAW_ENGRAM_CONFIG_PATH,
|
|
6828
|
-
|
|
6993
|
+
path14.join(resolveHomeDir(), ".openclaw", "openclaw.json")
|
|
6829
6994
|
].filter(Boolean);
|
|
6830
6995
|
function resolveOpenclawConfigPath(cliPath) {
|
|
6831
|
-
if (cliPath) return
|
|
6996
|
+
if (cliPath) return path14.resolve(expandTilde(cliPath));
|
|
6832
6997
|
const envPath = process.env.OPENCLAW_CONFIG_PATH || process.env.OPENCLAW_ENGRAM_CONFIG_PATH;
|
|
6833
|
-
if (envPath) return
|
|
6998
|
+
if (envPath) return path14.resolve(expandTilde(envPath));
|
|
6834
6999
|
for (const candidate of DEFAULT_OPENCLAW_CONFIG_PATHS_FOR_DOCTOR) {
|
|
6835
7000
|
if (fs11.existsSync(candidate)) return candidate;
|
|
6836
7001
|
}
|
|
6837
|
-
return
|
|
7002
|
+
return path14.join(resolveHomeDir(), ".openclaw", "openclaw.json");
|
|
6838
7003
|
}
|
|
6839
7004
|
function readOpenclawConfig(configPath) {
|
|
6840
7005
|
if (!fs11.existsSync(configPath)) return {};
|
|
@@ -6893,10 +7058,10 @@ function buildRemnicOpenclawHooksPolicy(legacyHooks, existingHooks) {
|
|
|
6893
7058
|
function resolveOpenclawInstallMemoryDir(args) {
|
|
6894
7059
|
const existingMemoryDir = (typeof args.existingNewEntryConfig.memoryDir === "string" ? args.existingNewEntryConfig.memoryDir : void 0) || (args.migrateLegacy && typeof args.legacyConfigToMerge.memoryDir === "string" ? args.legacyConfigToMerge.memoryDir : void 0);
|
|
6895
7060
|
if (args.requestedMemoryDir) {
|
|
6896
|
-
return
|
|
7061
|
+
return path14.resolve(expandTilde(args.requestedMemoryDir));
|
|
6897
7062
|
}
|
|
6898
7063
|
if (existingMemoryDir) {
|
|
6899
|
-
return
|
|
7064
|
+
return path14.resolve(expandTilde(existingMemoryDir));
|
|
6900
7065
|
}
|
|
6901
7066
|
return args.fallbackMemoryDir;
|
|
6902
7067
|
}
|
|
@@ -6914,18 +7079,18 @@ function resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir) {
|
|
|
6914
7079
|
if (!config || typeof config !== "object" || Array.isArray(config)) continue;
|
|
6915
7080
|
const memoryDir = config.memoryDir;
|
|
6916
7081
|
if (typeof memoryDir === "string" && memoryDir.trim().length > 0) {
|
|
6917
|
-
return
|
|
7082
|
+
return path14.resolve(expandTilde(memoryDir));
|
|
6918
7083
|
}
|
|
6919
7084
|
}
|
|
6920
7085
|
return fallbackMemoryDir;
|
|
6921
7086
|
}
|
|
6922
7087
|
function resolveOpenclawPluginDir(cliPath) {
|
|
6923
|
-
if (cliPath) return
|
|
6924
|
-
return
|
|
7088
|
+
if (cliPath) return path14.resolve(expandTilde(cliPath));
|
|
7089
|
+
return path14.join(resolveHomeDir(), ".openclaw", "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
6925
7090
|
}
|
|
6926
7091
|
function resolveOpenclawLegacyPluginDir(cliPath) {
|
|
6927
|
-
if (cliPath) return
|
|
6928
|
-
return
|
|
7092
|
+
if (cliPath) return path14.resolve(expandTilde(cliPath));
|
|
7093
|
+
return path14.join(resolveHomeDir(), ".openclaw", "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID);
|
|
6929
7094
|
}
|
|
6930
7095
|
function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
6931
7096
|
const yyyy = now.getFullYear().toString();
|
|
@@ -6938,7 +7103,7 @@ function formatOpenclawUpgradeStamp(now = /* @__PURE__ */ new Date()) {
|
|
|
6938
7103
|
}
|
|
6939
7104
|
function backupPathIfPresent(sourcePath, backupPath) {
|
|
6940
7105
|
if (!fs11.existsSync(sourcePath)) return false;
|
|
6941
|
-
fs11.mkdirSync(
|
|
7106
|
+
fs11.mkdirSync(path14.dirname(backupPath), { recursive: true });
|
|
6942
7107
|
fs11.cpSync(sourcePath, backupPath, { recursive: true });
|
|
6943
7108
|
return true;
|
|
6944
7109
|
}
|
|
@@ -6969,7 +7134,7 @@ var PublishedOpenclawPluginInstallError = class extends Error {
|
|
|
6969
7134
|
}
|
|
6970
7135
|
};
|
|
6971
7136
|
function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
6972
|
-
const tempRoot = fs11.mkdtempSync(
|
|
7137
|
+
const tempRoot = fs11.mkdtempSync(path14.join(os.tmpdir(), "remnic-openclaw-upgrade-"));
|
|
6973
7138
|
const stagedDir = `${pluginDir}.next-${process.pid}-${Date.now()}`;
|
|
6974
7139
|
const rollbackDir = `${pluginDir}.rollback-${process.pid}-${Date.now()}`;
|
|
6975
7140
|
let swapRollbackDir;
|
|
@@ -6984,12 +7149,12 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
6984
7149
|
if (!tarballName) {
|
|
6985
7150
|
throw new Error(`npm pack ${spec} did not return a tarball name`);
|
|
6986
7151
|
}
|
|
6987
|
-
const unpackDir =
|
|
7152
|
+
const unpackDir = path14.join(tempRoot, "unpacked");
|
|
6988
7153
|
fs11.mkdirSync(unpackDir, { recursive: true });
|
|
6989
|
-
childProcess2.execFileSync("tar", ["-xzf",
|
|
7154
|
+
childProcess2.execFileSync("tar", ["-xzf", path14.join(tempRoot, tarballName), "-C", unpackDir], {
|
|
6990
7155
|
stdio: ["ignore", "pipe", "pipe"]
|
|
6991
7156
|
});
|
|
6992
|
-
const packagedDir =
|
|
7157
|
+
const packagedDir = path14.join(unpackDir, "package");
|
|
6993
7158
|
if (!fs11.existsSync(packagedDir)) {
|
|
6994
7159
|
throw new Error(`npm pack ${spec} did not contain a package/ directory`);
|
|
6995
7160
|
}
|
|
@@ -7009,7 +7174,7 @@ function installPublishedOpenclawPlugin(spec, pluginDir) {
|
|
|
7009
7174
|
}
|
|
7010
7175
|
})();
|
|
7011
7176
|
swapRollbackDir = swapResult.rollbackDir;
|
|
7012
|
-
const installedPackageJsonPath =
|
|
7177
|
+
const installedPackageJsonPath = path14.join(pluginDir, "package.json");
|
|
7013
7178
|
const installedPackage = fs11.existsSync(installedPackageJsonPath) ? JSON.parse(fs11.readFileSync(installedPackageJsonPath, "utf8")) : {};
|
|
7014
7179
|
return {
|
|
7015
7180
|
rollbackDir: swapRollbackDir,
|
|
@@ -7044,7 +7209,7 @@ function restartOpenclawGateway() {
|
|
|
7044
7209
|
});
|
|
7045
7210
|
}
|
|
7046
7211
|
function cmdInit() {
|
|
7047
|
-
const configPath =
|
|
7212
|
+
const configPath = path14.join(process.cwd(), "remnic.config.json");
|
|
7048
7213
|
if (fs11.existsSync(configPath)) {
|
|
7049
7214
|
console.log(`Config already exists: ${configPath}`);
|
|
7050
7215
|
return;
|
|
@@ -7052,7 +7217,7 @@ function cmdInit() {
|
|
|
7052
7217
|
const template = {
|
|
7053
7218
|
remnic: {
|
|
7054
7219
|
openaiApiKey: "${OPENAI_API_KEY}",
|
|
7055
|
-
memoryDir:
|
|
7220
|
+
memoryDir: path14.join(process.cwd(), ".remnic", "memory"),
|
|
7056
7221
|
memoryOsPreset: "balanced"
|
|
7057
7222
|
},
|
|
7058
7223
|
server: {
|
|
@@ -7189,7 +7354,7 @@ function oauthResolveOperatorToken() {
|
|
|
7189
7354
|
}
|
|
7190
7355
|
return void 0;
|
|
7191
7356
|
}
|
|
7192
|
-
async function oauthFetch(method,
|
|
7357
|
+
async function oauthFetch(method, path15, token, body) {
|
|
7193
7358
|
const controller = new AbortController();
|
|
7194
7359
|
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
7195
7360
|
try {
|
|
@@ -7208,7 +7373,7 @@ async function oauthFetch(method, path13, token, body) {
|
|
|
7208
7373
|
if (body !== void 0) {
|
|
7209
7374
|
init.body = JSON.stringify(body);
|
|
7210
7375
|
}
|
|
7211
|
-
const response = await fetch(`${oauthResolveBaseUrl()}${
|
|
7376
|
+
const response = await fetch(`${oauthResolveBaseUrl()}${path15}`, init);
|
|
7212
7377
|
if (response.status === 401) {
|
|
7213
7378
|
throw new Error(
|
|
7214
7379
|
"operator token rejected by remnic-server (HTTP 401). Update `server.authToken` or `REMNIC_AUTH_TOKEN` to match the running daemon."
|
|
@@ -7763,7 +7928,7 @@ async function cmdVersions(rest) {
|
|
|
7763
7928
|
console.error("Usage: remnic versions list <page-path>");
|
|
7764
7929
|
process.exit(1);
|
|
7765
7930
|
}
|
|
7766
|
-
const absPath =
|
|
7931
|
+
const absPath = path14.resolve(pagePath);
|
|
7767
7932
|
const history = await listVersions(absPath, versioningConfig, memDir);
|
|
7768
7933
|
if (json) {
|
|
7769
7934
|
console.log(JSON.stringify(history, null, 2));
|
|
@@ -7788,7 +7953,7 @@ async function cmdVersions(rest) {
|
|
|
7788
7953
|
console.error("Usage: remnic versions show <page-path> <version-id>");
|
|
7789
7954
|
process.exit(1);
|
|
7790
7955
|
}
|
|
7791
|
-
const absPath =
|
|
7956
|
+
const absPath = path14.resolve(pagePath);
|
|
7792
7957
|
try {
|
|
7793
7958
|
const content = await getVersion(absPath, versionId, versioningConfig, memDir);
|
|
7794
7959
|
console.log(content);
|
|
@@ -7806,7 +7971,7 @@ async function cmdVersions(rest) {
|
|
|
7806
7971
|
console.error("Usage: remnic versions diff <page-path> <v1> <v2>");
|
|
7807
7972
|
process.exit(1);
|
|
7808
7973
|
}
|
|
7809
|
-
const absPath =
|
|
7974
|
+
const absPath = path14.resolve(pagePath);
|
|
7810
7975
|
try {
|
|
7811
7976
|
const diffOutput = await diffVersions(absPath, v1, v2, versioningConfig, memDir);
|
|
7812
7977
|
console.log(diffOutput);
|
|
@@ -7823,7 +7988,7 @@ async function cmdVersions(rest) {
|
|
|
7823
7988
|
console.error("Usage: remnic versions revert <page-path> <version-id>");
|
|
7824
7989
|
process.exit(1);
|
|
7825
7990
|
}
|
|
7826
|
-
const absPath =
|
|
7991
|
+
const absPath = path14.resolve(pagePath);
|
|
7827
7992
|
try {
|
|
7828
7993
|
const version = await revertToVersion(absPath, versionId, versioningConfig, void 0, memDir);
|
|
7829
7994
|
if (json) {
|
|
@@ -7863,7 +8028,7 @@ async function cmdEnrich(rest) {
|
|
|
7863
8028
|
const subcommand = rest[0];
|
|
7864
8029
|
if (subcommand === "audit") {
|
|
7865
8030
|
const memoryDir2 = expandTilde(config.memoryDir);
|
|
7866
|
-
const auditDir2 =
|
|
8031
|
+
const auditDir2 = path14.join(memoryDir2, "enrichment");
|
|
7867
8032
|
const sinceFlag = resolveFlag(rest.slice(1), "--since");
|
|
7868
8033
|
const entries = await readAuditLog(auditDir2, sinceFlag ?? void 0);
|
|
7869
8034
|
if (entries.length === 0) {
|
|
@@ -7988,7 +8153,7 @@ Registered providers:`);
|
|
|
7988
8153
|
return;
|
|
7989
8154
|
}
|
|
7990
8155
|
const memoryDir = expandTilde(config.memoryDir);
|
|
7991
|
-
const auditDir =
|
|
8156
|
+
const auditDir = path14.join(memoryDir, "enrichment");
|
|
7992
8157
|
let totalPersisted = 0;
|
|
7993
8158
|
for (const result of results) {
|
|
7994
8159
|
for (const candidate of result.acceptedCandidates) {
|
|
@@ -8179,7 +8344,7 @@ Root: ${root}`);
|
|
|
8179
8344
|
const validNames = new Set(extensions.map((e) => e.name));
|
|
8180
8345
|
let errors = 0;
|
|
8181
8346
|
for (const entry of entries) {
|
|
8182
|
-
const entryPath =
|
|
8347
|
+
const entryPath = path14.join(root, entry);
|
|
8183
8348
|
try {
|
|
8184
8349
|
if (!fs11.statSync(entryPath).isDirectory()) continue;
|
|
8185
8350
|
} catch {
|
|
@@ -8295,7 +8460,7 @@ async function cmdBriefing(rest) {
|
|
|
8295
8460
|
const saveDir = resolveBriefingSaveDir(config.briefing.saveDir);
|
|
8296
8461
|
fs11.mkdirSync(saveDir, { recursive: true });
|
|
8297
8462
|
const filename = briefingFilename(new Date(result.window.to), format);
|
|
8298
|
-
const filePath =
|
|
8463
|
+
const filePath = path14.join(saveDir, filename);
|
|
8299
8464
|
fs11.writeFileSync(filePath, payload + (payload.endsWith("\n") ? "" : "\n"));
|
|
8300
8465
|
console.error(`Saved briefing: ${filePath}`);
|
|
8301
8466
|
} catch (err) {
|
|
@@ -8451,7 +8616,7 @@ async function cmdDoctor() {
|
|
|
8451
8616
|
const rawMemoryDir = entryConfig?.memoryDir;
|
|
8452
8617
|
const configuredMemoryDir = typeof rawMemoryDir === "string" ? rawMemoryDir : void 0;
|
|
8453
8618
|
if (configuredMemoryDir) {
|
|
8454
|
-
const resolvedMemDir =
|
|
8619
|
+
const resolvedMemDir = path14.resolve(expandTilde(configuredMemoryDir));
|
|
8455
8620
|
let memDirOk = false;
|
|
8456
8621
|
let memDirDetail = `${resolvedMemDir} (not found)`;
|
|
8457
8622
|
let memDirRemediation = `Run \`remnic openclaw install --memory-dir "${resolvedMemDir}"\` to create the directory.`;
|
|
@@ -8651,7 +8816,7 @@ async function cmdMigrate(json, rollback) {
|
|
|
8651
8816
|
console.log(` Rollback: ${result.rollbackCommand}`);
|
|
8652
8817
|
}
|
|
8653
8818
|
function cmdOnboard(dirPath, json) {
|
|
8654
|
-
const directory =
|
|
8819
|
+
const directory = path14.resolve(dirPath || process.cwd());
|
|
8655
8820
|
const result = onboard({ directory });
|
|
8656
8821
|
if (json) {
|
|
8657
8822
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -8670,7 +8835,7 @@ Suggested namespace: ${result.plan.suggestedNamespace}`);
|
|
|
8670
8835
|
async function cmdCurate(targetPath, json) {
|
|
8671
8836
|
const memoryDir = resolveMemoryDir();
|
|
8672
8837
|
const result = await curate({
|
|
8673
|
-
targetPath:
|
|
8838
|
+
targetPath: path14.resolve(targetPath),
|
|
8674
8839
|
memoryDir,
|
|
8675
8840
|
source: "curation",
|
|
8676
8841
|
checkDuplicates: true,
|
|
@@ -8800,7 +8965,7 @@ async function cmdSync(action, rest, json) {
|
|
|
8800
8965
|
}
|
|
8801
8966
|
function localOfflineSourceId(memoryDir) {
|
|
8802
8967
|
const host = os.hostname() || "unknown-host";
|
|
8803
|
-
const dirHash = createHash2("sha256").update(
|
|
8968
|
+
const dirHash = createHash2("sha256").update(path14.resolve(memoryDir)).digest("hex").slice(0, 16);
|
|
8804
8969
|
return `remnic-local:${host}:${dirHash}`;
|
|
8805
8970
|
}
|
|
8806
8971
|
function normalizeOfflineRemoteUrl(raw) {
|
|
@@ -9198,10 +9363,10 @@ var OFFLINE_SYNC_CONTENT_MISSING_RETRY_MAX = 3;
|
|
|
9198
9363
|
var OFFLINE_SYNC_CONTENT_MISSING_RETRY_DELAY_MS = 250;
|
|
9199
9364
|
var OfflineRemoteFileChangedError = class extends Error {
|
|
9200
9365
|
path;
|
|
9201
|
-
constructor(
|
|
9202
|
-
super(`remote file changed while fetching offline content: ${
|
|
9366
|
+
constructor(path15) {
|
|
9367
|
+
super(`remote file changed while fetching offline content: ${path15}`);
|
|
9203
9368
|
this.name = "OfflineRemoteFileChangedError";
|
|
9204
|
-
this.path =
|
|
9369
|
+
this.path = path15;
|
|
9205
9370
|
}
|
|
9206
9371
|
};
|
|
9207
9372
|
function isOfflineRemoteFileChangedError(error) {
|
|
@@ -9392,10 +9557,10 @@ function offlineDirectPushFiles(options) {
|
|
|
9392
9557
|
}).sort((left, right) => right.bytes - left.bytes || left.path.localeCompare(right.path));
|
|
9393
9558
|
}
|
|
9394
9559
|
function resolveOfflineDirectHydrationPath(memoryDir, relPath) {
|
|
9395
|
-
const base =
|
|
9396
|
-
const target =
|
|
9397
|
-
const relative =
|
|
9398
|
-
if (relative === "" || relative === ".." || relative.startsWith(`..${
|
|
9560
|
+
const base = path14.resolve(memoryDir);
|
|
9561
|
+
const target = path14.resolve(base, relPath);
|
|
9562
|
+
const relative = path14.relative(base, target);
|
|
9563
|
+
if (relative === "" || relative === ".." || relative.startsWith(`..${path14.sep}`) || path14.isAbsolute(relative)) {
|
|
9399
9564
|
throw new Error(`offline sync direct hydration path escapes memory dir: ${relPath}`);
|
|
9400
9565
|
}
|
|
9401
9566
|
return target;
|
|
@@ -9471,7 +9636,7 @@ async function pushOfflineFileContentFromChunkReader(args) {
|
|
|
9471
9636
|
}
|
|
9472
9637
|
const hash = createHash2("sha256");
|
|
9473
9638
|
const chunks = args.readFileChunks({
|
|
9474
|
-
root:
|
|
9639
|
+
root: path14.resolve(args.memoryDir),
|
|
9475
9640
|
path: args.file.path,
|
|
9476
9641
|
filePath,
|
|
9477
9642
|
chunkSize: OFFLINE_SYNC_FILE_CONTENT_UPLOAD_CHUNK_BYTES
|
|
@@ -10574,7 +10739,7 @@ Environment fallbacks:
|
|
|
10574
10739
|
REMNIC_OFFLINE_REMOTE_URL, REMNIC_OFFLINE_TOKEN, REMNIC_AUTH_TOKEN`);
|
|
10575
10740
|
return;
|
|
10576
10741
|
}
|
|
10577
|
-
const memoryDir =
|
|
10742
|
+
const memoryDir = path14.resolve(expandTilde(resolveRequiredValueFlag(rest, "--memory-dir") ?? resolveMemoryDir()));
|
|
10578
10743
|
const namespace = resolveRequiredValueFlag(rest, "--namespace");
|
|
10579
10744
|
const includeTranscripts = !hasFlag(rest, "--no-transcripts");
|
|
10580
10745
|
const stateOverride = resolveRequiredValueFlag(rest, "--state");
|
|
@@ -10594,7 +10759,7 @@ Environment fallbacks:
|
|
|
10594
10759
|
const needsRemote = action === "prepare" || action === "sync" || action === "watch";
|
|
10595
10760
|
const remoteUrl = needsRemote ? resolveOfflineRemoteUrl(rest) : resolveOptionalOfflineRemoteUrl(rest);
|
|
10596
10761
|
const token = needsRemote ? resolveOfflineToken(rest) : void 0;
|
|
10597
|
-
const statePath = statePathExplicit ?
|
|
10762
|
+
const statePath = statePathExplicit ? path14.resolve(expandTilde(stateOverride)) : remoteUrl !== void 0 ? defaultOfflineSyncStatePath(memoryDir, remoteUrl, namespace) : void 0;
|
|
10598
10763
|
if (action === "prepare") {
|
|
10599
10764
|
if (!remoteUrl || !token || !statePath) throw new Error("offline prepare requires remote URL and token");
|
|
10600
10765
|
fs11.mkdirSync(memoryDir, { recursive: true });
|
|
@@ -10775,11 +10940,11 @@ Environment fallbacks:
|
|
|
10775
10940
|
failures: result.largeFilePushFailures
|
|
10776
10941
|
});
|
|
10777
10942
|
largeFileFailureCounts = advanced.counts;
|
|
10778
|
-
for (const
|
|
10779
|
-
if (skippedLargeFiles.has(
|
|
10780
|
-
skippedLargeFiles.add(
|
|
10943
|
+
for (const path15 of advanced.newlySkipped) {
|
|
10944
|
+
if (skippedLargeFiles.has(path15)) continue;
|
|
10945
|
+
skippedLargeFiles.add(path15);
|
|
10781
10946
|
console.warn(
|
|
10782
|
-
`offline sync: permanently skipping ${
|
|
10947
|
+
`offline sync: permanently skipping ${path15} 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)`
|
|
10783
10948
|
);
|
|
10784
10949
|
}
|
|
10785
10950
|
const pulled = result.pull ? result.pull.upserted + result.pull.deleted : 0;
|
|
@@ -10794,11 +10959,11 @@ Environment fallbacks:
|
|
|
10794
10959
|
failures: error.failures
|
|
10795
10960
|
});
|
|
10796
10961
|
largeFileFailureCounts = advanced.counts;
|
|
10797
|
-
for (const
|
|
10798
|
-
if (skippedLargeFiles.has(
|
|
10799
|
-
skippedLargeFiles.add(
|
|
10962
|
+
for (const path15 of advanced.newlySkipped) {
|
|
10963
|
+
if (skippedLargeFiles.has(path15)) continue;
|
|
10964
|
+
skippedLargeFiles.add(path15);
|
|
10800
10965
|
console.warn(
|
|
10801
|
-
`offline sync: permanently skipping ${
|
|
10966
|
+
`offline sync: permanently skipping ${path15} 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)`
|
|
10802
10967
|
);
|
|
10803
10968
|
}
|
|
10804
10969
|
}
|
|
@@ -10939,7 +11104,7 @@ async function cmdConnectors(action, rest, json) {
|
|
|
10939
11104
|
const connectorDaemonUrl = typeof effectiveConnectorConfig.remnicDaemonUrl === "string" && effectiveConnectorConfig.remnicDaemonUrl.trim().length > 0 ? effectiveConnectorConfig.remnicDaemonUrl.trim() : void 0;
|
|
10940
11105
|
const pubResult = await pub.publish({
|
|
10941
11106
|
config: { memoryDir, namespace: connectorNamespace, daemonUrl: connectorDaemonUrl },
|
|
10942
|
-
skillsRoot:
|
|
11107
|
+
skillsRoot: path14.join(memoryDir, "skills"),
|
|
10943
11108
|
rollbackTokenEntry: preInstallTokenEntry,
|
|
10944
11109
|
log: { info: console.log, warn: console.warn, error: console.error }
|
|
10945
11110
|
});
|
|
@@ -11299,15 +11464,15 @@ async function cmdConnectorsMarketplace(subAction, rest, json) {
|
|
|
11299
11464
|
}
|
|
11300
11465
|
const manifest = generateMarketplaceManifest();
|
|
11301
11466
|
await writeMarketplaceManifest(outputDir, manifest);
|
|
11302
|
-
const outPath =
|
|
11467
|
+
const outPath = path14.join(outputDir, "marketplace.json");
|
|
11303
11468
|
if (json) {
|
|
11304
11469
|
console.log(JSON.stringify({ status: "generated", path: outPath }, null, 2));
|
|
11305
11470
|
} else {
|
|
11306
11471
|
console.log(`Generated marketplace.json at ${outPath}`);
|
|
11307
11472
|
}
|
|
11308
11473
|
} else if (subAction === "validate") {
|
|
11309
|
-
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ??
|
|
11310
|
-
const resolved =
|
|
11474
|
+
const targetPath = rest.filter((a) => !a.startsWith("--"))[0] ?? path14.join(process.cwd(), "marketplace.json");
|
|
11475
|
+
const resolved = path14.resolve(targetPath);
|
|
11311
11476
|
if (!fs11.existsSync(resolved)) {
|
|
11312
11477
|
console.error(`File not found: ${resolved}`);
|
|
11313
11478
|
process.exit(1);
|
|
@@ -11613,6 +11778,10 @@ async function cmdBench(rest) {
|
|
|
11613
11778
|
await compareBenchPackageResults(parsed);
|
|
11614
11779
|
return;
|
|
11615
11780
|
}
|
|
11781
|
+
if (parsed.action === "attribute" || parsed.action === "drift-gen") {
|
|
11782
|
+
await runBenchResearchCommand(parsed);
|
|
11783
|
+
return;
|
|
11784
|
+
}
|
|
11616
11785
|
if (parsed.action === "results") {
|
|
11617
11786
|
await showBenchPackageResults(parsed);
|
|
11618
11787
|
return;
|
|
@@ -11711,7 +11880,7 @@ async function cmdBench(rest) {
|
|
|
11711
11880
|
}
|
|
11712
11881
|
const completeCount = prevStatus.benchmarks.filter((b) => b.status === "complete").length;
|
|
11713
11882
|
const failedCount = prevStatus.benchmarks.filter((b) => b.status === "failed").length;
|
|
11714
|
-
printBenchStatusLine(parsed.json, `Resuming from: ${
|
|
11883
|
+
printBenchStatusLine(parsed.json, `Resuming from: ${path14.basename(latestStatusPath)}`);
|
|
11715
11884
|
printBenchStatusLine(parsed.json, ` Previous run: ${prevStatus.startedAt}`);
|
|
11716
11885
|
printBenchStatusLine(parsed.json, ` Benchmarks: ${prevStatus.benchmarks.length} total, ${completeCount} complete, ${failedCount} failed`);
|
|
11717
11886
|
const before = selectedBenchmarks.length;
|
|
@@ -11879,9 +12048,9 @@ Options:
|
|
|
11879
12048
|
);
|
|
11880
12049
|
process.exit(1);
|
|
11881
12050
|
} else {
|
|
11882
|
-
fixturePath =
|
|
12051
|
+
fixturePath = path14.resolve(expandTilde(fixturePathRaw));
|
|
11883
12052
|
}
|
|
11884
|
-
const outPath =
|
|
12053
|
+
const outPath = path14.resolve(expandTilde(outPathRaw));
|
|
11885
12054
|
const benchModule = await loadBenchModule();
|
|
11886
12055
|
const runner = benchModule.runProceduralAblationCli;
|
|
11887
12056
|
if (typeof runner !== "function") {
|
|
@@ -11900,7 +12069,7 @@ Options:
|
|
|
11900
12069
|
);
|
|
11901
12070
|
console.log(`wrote ${outPath}`);
|
|
11902
12071
|
}
|
|
11903
|
-
var LOGS_DIR =
|
|
12072
|
+
var LOGS_DIR = path14.join(PID_DIR, "logs");
|
|
11904
12073
|
var LAUNCHD_PLIST_PATHS = launchdPlistPaths(resolveHomeDir());
|
|
11905
12074
|
var [LAUNCHD_PLIST_PATH] = LAUNCHD_PLIST_PATHS;
|
|
11906
12075
|
var SYSTEMD_UNIT_PATHS = systemdUnitPaths(resolveHomeDir());
|
|
@@ -11977,7 +12146,7 @@ function selectLaunchdInspection(openclawPluginModeConfigured) {
|
|
|
11977
12146
|
for (const plistPath of LAUNCHD_PLIST_PATHS.slice(1)) {
|
|
11978
12147
|
const legacy = inspectLaunchdPlist(plistPath);
|
|
11979
12148
|
if (!legacy.installed) continue;
|
|
11980
|
-
const label =
|
|
12149
|
+
const label = path14.basename(plistPath, ".plist");
|
|
11981
12150
|
return legacy.ok ? {
|
|
11982
12151
|
...legacy,
|
|
11983
12152
|
warn: true,
|
|
@@ -12011,10 +12180,10 @@ function daemonInstall() {
|
|
|
12011
12180
|
const vars = { HOME: home, NODE_PATH: nodePath, REMNIC_SERVER_BIN: serverBin };
|
|
12012
12181
|
fs11.mkdirSync(LOGS_DIR, { recursive: true });
|
|
12013
12182
|
if (isMacOS()) {
|
|
12014
|
-
const templatePath =
|
|
12183
|
+
const templatePath = path14.resolve(import.meta.dirname, "../templates/launchd/ai.remnic.daemon.plist");
|
|
12015
12184
|
const template = fs11.readFileSync(templatePath, "utf8");
|
|
12016
12185
|
const plist = renderTemplate(template, vars);
|
|
12017
|
-
fs11.mkdirSync(
|
|
12186
|
+
fs11.mkdirSync(path14.dirname(LAUNCHD_PLIST_PATH), { recursive: true });
|
|
12018
12187
|
fs11.writeFileSync(LAUNCHD_PLIST_PATH, plist);
|
|
12019
12188
|
try {
|
|
12020
12189
|
launchdLoadPlist(LAUNCHD_PLIST_PATH);
|
|
@@ -12031,10 +12200,10 @@ function daemonInstall() {
|
|
|
12031
12200
|
console.log(` RunAtLoad: true, KeepAlive: true`);
|
|
12032
12201
|
console.log(` Logs: ${LOGS_DIR}/daemon.log`);
|
|
12033
12202
|
} else if (isLinux()) {
|
|
12034
|
-
const templatePath =
|
|
12203
|
+
const templatePath = path14.resolve(import.meta.dirname, "../templates/systemd/remnic.service");
|
|
12035
12204
|
const template = fs11.readFileSync(templatePath, "utf8");
|
|
12036
12205
|
const unit = renderTemplate(template, vars);
|
|
12037
|
-
fs11.mkdirSync(
|
|
12206
|
+
fs11.mkdirSync(path14.dirname(SYSTEMD_UNIT_PATH), { recursive: true });
|
|
12038
12207
|
fs11.writeFileSync(SYSTEMD_UNIT_PATH, unit);
|
|
12039
12208
|
try {
|
|
12040
12209
|
childProcess2.execSync("systemctl --user daemon-reload", { stdio: "pipe" });
|
|
@@ -12513,7 +12682,7 @@ Clean complete: cleaned=${result.cleaned}`
|
|
|
12513
12682
|
}
|
|
12514
12683
|
async function cmdOpenclawInstall(opts) {
|
|
12515
12684
|
const configPath = resolveOpenclawConfigPath(opts.configPath);
|
|
12516
|
-
const fallbackMemoryDir =
|
|
12685
|
+
const fallbackMemoryDir = path14.join(resolveHomeDir(), ".openclaw", "workspace", "memory", "local");
|
|
12517
12686
|
console.log(`OpenClaw config: ${configPath}`);
|
|
12518
12687
|
const existingConfig = readOpenclawConfig(configPath);
|
|
12519
12688
|
const { plugins, entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
@@ -12616,7 +12785,7 @@ Remove it first and re-run, or choose a different path with --memory-dir.`
|
|
|
12616
12785
|
fs11.mkdirSync(memoryDir, { recursive: true });
|
|
12617
12786
|
console.log(`Created memory directory: ${memoryDir}`);
|
|
12618
12787
|
}
|
|
12619
|
-
const configDir =
|
|
12788
|
+
const configDir = path14.dirname(configPath);
|
|
12620
12789
|
if (!fs11.existsSync(configDir)) {
|
|
12621
12790
|
fs11.mkdirSync(configDir, { recursive: true });
|
|
12622
12791
|
}
|
|
@@ -12644,11 +12813,11 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
12644
12813
|
const configPath = resolveOpenclawConfigPath(opts.configPath);
|
|
12645
12814
|
const pluginDir = resolveOpenclawPluginDir(opts.pluginDir);
|
|
12646
12815
|
const legacyPluginDirForBackup = opts.legacyPluginDirForBackup ? resolveOpenclawLegacyPluginDir(opts.legacyPluginDirForBackup) : void 0;
|
|
12647
|
-
const fallbackMemoryDir =
|
|
12816
|
+
const fallbackMemoryDir = path14.join(resolveHomeDir(), ".openclaw", "workspace", "memory", "local");
|
|
12648
12817
|
const packageSpec = `@remnic/plugin-openclaw@${opts.version ?? "latest"}`;
|
|
12649
12818
|
const existingConfig = readOpenclawConfig(configPath);
|
|
12650
12819
|
const { entries, slots } = parseOpenclawPluginState(existingConfig, configPath);
|
|
12651
|
-
const preservedMemoryDir = opts.memoryDir ?
|
|
12820
|
+
const preservedMemoryDir = opts.memoryDir ? path14.resolve(expandTilde(opts.memoryDir)) : resolveCurrentOpenclawMemoryDir(entries, slots, fallbackMemoryDir);
|
|
12652
12821
|
assertDirectoryPathOrMissing(pluginDir, "OpenClaw plugin dir");
|
|
12653
12822
|
if (legacyPluginDirForBackup) {
|
|
12654
12823
|
assertDirectoryPathOrMissing(legacyPluginDirForBackup, "Legacy OpenClaw plugin dir");
|
|
@@ -12660,7 +12829,7 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
12660
12829
|
}
|
|
12661
12830
|
console.log(`Memory dir: ${preservedMemoryDir}`);
|
|
12662
12831
|
console.log(`Package spec: ${packageSpec}`);
|
|
12663
|
-
console.log(`Backup root: ${
|
|
12832
|
+
console.log(`Backup root: ${path14.join(resolveHomeDir(), ".openclaw", "backups")}`);
|
|
12664
12833
|
const plannedActions = [
|
|
12665
12834
|
`backup openclaw.json and the existing ${REMNIC_OPENCLAW_PLUGIN_ID} extension`,
|
|
12666
12835
|
...legacyPluginDirForBackup ? [`backup the existing ${REMNIC_OPENCLAW_LEGACY_PLUGIN_ID} extension without modifying it`] : [],
|
|
@@ -12686,9 +12855,9 @@ async function cmdOpenclawUpgrade(opts) {
|
|
|
12686
12855
|
}
|
|
12687
12856
|
}
|
|
12688
12857
|
const backupDir = createOpenclawUpgradeBackupDir();
|
|
12689
|
-
const configBackupPath =
|
|
12690
|
-
const pluginBackupDir =
|
|
12691
|
-
const legacyPluginBackupDir = legacyPluginDirForBackup ?
|
|
12858
|
+
const configBackupPath = path14.join(backupDir, "openclaw.json");
|
|
12859
|
+
const pluginBackupDir = path14.join(backupDir, "extensions", REMNIC_OPENCLAW_PLUGIN_ID);
|
|
12860
|
+
const legacyPluginBackupDir = legacyPluginDirForBackup ? path14.join(backupDir, "extensions", REMNIC_OPENCLAW_LEGACY_PLUGIN_ID) : void 0;
|
|
12692
12861
|
const backupNotes = [];
|
|
12693
12862
|
if (backupPathIfPresent(configPath, configBackupPath)) {
|
|
12694
12863
|
backupNotes.push(`+ Backed up config to ${configBackupPath}`);
|
|
@@ -12789,9 +12958,9 @@ async function cmdOpenclawMigrateEngram(opts) {
|
|
|
12789
12958
|
console.log(" - Re-apply any local source patches to the new package only after verifying the published build.");
|
|
12790
12959
|
}
|
|
12791
12960
|
function createOpenclawUpgradeBackupDir() {
|
|
12792
|
-
const backupsRoot =
|
|
12961
|
+
const backupsRoot = path14.join(resolveHomeDir(), ".openclaw", "backups");
|
|
12793
12962
|
fs11.mkdirSync(backupsRoot, { recursive: true });
|
|
12794
|
-
return fs11.mkdtempSync(
|
|
12963
|
+
return fs11.mkdtempSync(path14.join(backupsRoot, `remnic-openclaw-upgrade-${formatOpenclawUpgradeStamp()}-`));
|
|
12795
12964
|
}
|
|
12796
12965
|
async function cmdTaxonomy(rest) {
|
|
12797
12966
|
initLogger2();
|
|
@@ -12833,8 +13002,8 @@ async function cmdTaxonomy(rest) {
|
|
|
12833
13002
|
const doc = generateResolverDocument(taxonomy);
|
|
12834
13003
|
console.log(doc);
|
|
12835
13004
|
if (config.taxonomyAutoGenResolver) {
|
|
12836
|
-
const resolverPath =
|
|
12837
|
-
fs11.mkdirSync(
|
|
13005
|
+
const resolverPath = path14.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
13006
|
+
fs11.mkdirSync(path14.dirname(resolverPath), { recursive: true });
|
|
12838
13007
|
fs11.writeFileSync(resolverPath, doc);
|
|
12839
13008
|
console.error(`Written: ${resolverPath}`);
|
|
12840
13009
|
}
|
|
@@ -12880,7 +13049,7 @@ async function cmdTaxonomy(rest) {
|
|
|
12880
13049
|
console.log(`Added category "${id}" (${name}).`);
|
|
12881
13050
|
if (config.taxonomyAutoGenResolver) {
|
|
12882
13051
|
const doc = generateResolverDocument(taxonomy);
|
|
12883
|
-
const resolverPath =
|
|
13052
|
+
const resolverPath = path14.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
12884
13053
|
fs11.writeFileSync(resolverPath, doc);
|
|
12885
13054
|
console.error(`Regenerated: ${resolverPath}`);
|
|
12886
13055
|
}
|
|
@@ -12911,7 +13080,7 @@ async function cmdTaxonomy(rest) {
|
|
|
12911
13080
|
console.log(`Removed category "${id}".`);
|
|
12912
13081
|
if (config.taxonomyAutoGenResolver) {
|
|
12913
13082
|
const doc = generateResolverDocument(taxonomy);
|
|
12914
|
-
const resolverPath =
|
|
13083
|
+
const resolverPath = path14.join(config.memoryDir, ".taxonomy", "RESOLVER.md");
|
|
12915
13084
|
fs11.writeFileSync(resolverPath, doc);
|
|
12916
13085
|
console.error(`Regenerated: ${resolverPath}`);
|
|
12917
13086
|
}
|
|
@@ -13193,7 +13362,7 @@ async function runTrainingExport(args, stdout = process.stdout) {
|
|
|
13193
13362
|
);
|
|
13194
13363
|
}
|
|
13195
13364
|
const formatted = adapter.formatRecords(records);
|
|
13196
|
-
const outDir =
|
|
13365
|
+
const outDir = path14.dirname(args.output);
|
|
13197
13366
|
fs11.mkdirSync(outDir, { recursive: true });
|
|
13198
13367
|
const tmpPath = `${args.output}.tmp-${process.pid}-${Date.now()}`;
|
|
13199
13368
|
fs11.writeFileSync(tmpPath, formatted, "utf-8");
|
|
@@ -13301,7 +13470,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13301
13470
|
case "tree": {
|
|
13302
13471
|
const subAction = rest[0];
|
|
13303
13472
|
const json = rest.includes("--json");
|
|
13304
|
-
const outputDir = resolveFlag(rest, "--output") ??
|
|
13473
|
+
const outputDir = resolveFlag(rest, "--output") ?? path14.join(process.cwd(), ".remnic", "context-tree");
|
|
13305
13474
|
const categoriesFlag = resolveFlag(rest, "--categories");
|
|
13306
13475
|
const categories = categoriesFlag ? categoriesFlag.split(",") : void 0;
|
|
13307
13476
|
const maxPerCategoryRaw = resolveFlag(rest, "--max-per-category");
|
|
@@ -13378,7 +13547,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
13378
13547
|
console.error(`Context tree not found at ${treeDir}. Run 'remnic tree generate' first.`);
|
|
13379
13548
|
process.exit(1);
|
|
13380
13549
|
}
|
|
13381
|
-
const indexPath =
|
|
13550
|
+
const indexPath = path14.join(treeDir, "INDEX.md");
|
|
13382
13551
|
if (!fs11.existsSync(indexPath)) {
|
|
13383
13552
|
console.error(`INDEX.md missing in ${treeDir}. Tree may be corrupt \u2014 regenerate.`);
|
|
13384
13553
|
process.exit(1);
|
|
@@ -13832,9 +14001,9 @@ Usage:
|
|
|
13832
14001
|
remnic extensions <list|show|validate|reload> Manage memory extensions
|
|
13833
14002
|
remnic space <list|switch|create|delete|push|pull|share|promote|audit> Manage spaces
|
|
13834
14003
|
create accepts --parent <id> to set parent-child relationship
|
|
13835
|
-
remnic bench <list|run|datasets|runs|compare|results|baseline|export|publish|ui|providers> [benchmark...] [--quick] [--all] [--dataset-dir <path>] [--results-dir <path>] [--baselines-dir <path>] [--threshold <value>] [--detail] [--format <json|csv|html>] [--output <path>] [--target remnic-ai] [--json]
|
|
14004
|
+
remnic bench <list|run|published|datasets|runs|compare|results|baseline|export|publish|ui|providers|judge-calibrate|attribute|drift-gen> [benchmark...] [--quick] [--all] [--dataset-dir <path>] [--results-dir <path>] [--baselines-dir <path>] [--threshold <value>] [--detail] [--format <json|csv|html>] [--output <path>] [--target remnic-ai] [--json]
|
|
13836
14005
|
benchmark is kept as a compatibility alias. check/report remain under that alias.
|
|
13837
|
-
remnic benchmark <list|run|datasets|runs|compare|results|baseline|export|publish|ui|providers|check|report> [queries...] [--explain] [--baseline=<path>] [--report=<path>]
|
|
14006
|
+
remnic benchmark <list|run|datasets|runs|compare|results|baseline|export|publish|ui|providers|check|report|attribute|drift-gen> [queries...] [--explain] [--baseline=<path>] [--report=<path>]
|
|
13838
14007
|
remnic briefing [--since <window>] [--focus <filter>] [--save] [--format markdown|json]
|
|
13839
14008
|
Daily context briefing. Windows: yesterday, today, NNh, NNd, NNw.
|
|
13840
14009
|
Focus: person:<name>, project:<name>, topic:<name>.
|
|
@@ -13962,7 +14131,6 @@ export {
|
|
|
13962
14131
|
fetchOfflineSnapshot,
|
|
13963
14132
|
formatOfflineLargeFilePushFailureMessage,
|
|
13964
14133
|
formatOfflineRequestForError,
|
|
13965
|
-
getBenchUsageText,
|
|
13966
14134
|
hasFlag,
|
|
13967
14135
|
hashCalibrationProviderConfig,
|
|
13968
14136
|
hydrateOfflineSnapshotContent,
|