@joshuaswarren/openclaw-engram 8.3.64 → 8.3.65
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 +106 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10919,6 +10919,92 @@ async function readAllEdges(memoryDir, config) {
|
|
|
10919
10919
|
]);
|
|
10920
10920
|
return parts.flat();
|
|
10921
10921
|
}
|
|
10922
|
+
function isValidGraphEdge(raw, expectedType) {
|
|
10923
|
+
if (!raw || typeof raw !== "object") return false;
|
|
10924
|
+
const edge = raw;
|
|
10925
|
+
return edge.type === expectedType && typeof edge.from === "string" && edge.from.length > 0 && typeof edge.to === "string" && edge.to.length > 0 && typeof edge.weight === "number" && Number.isFinite(edge.weight) && typeof edge.label === "string" && typeof edge.ts === "string";
|
|
10926
|
+
}
|
|
10927
|
+
async function analyzeGraphHealth(memoryDir, options) {
|
|
10928
|
+
const enabledTypes = [];
|
|
10929
|
+
if (options?.entityGraphEnabled !== false) enabledTypes.push("entity");
|
|
10930
|
+
if (options?.timeGraphEnabled !== false) enabledTypes.push("time");
|
|
10931
|
+
if (options?.causalGraphEnabled !== false) enabledTypes.push("causal");
|
|
10932
|
+
const files = [];
|
|
10933
|
+
const globalNodes = /* @__PURE__ */ new Set();
|
|
10934
|
+
for (const type of enabledTypes) {
|
|
10935
|
+
const filePath = graphFilePath(memoryDir, type);
|
|
10936
|
+
let exists3 = true;
|
|
10937
|
+
let totalLines = 0;
|
|
10938
|
+
let validEdges = 0;
|
|
10939
|
+
let corruptLines = 0;
|
|
10940
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
10941
|
+
try {
|
|
10942
|
+
const raw = await readFile14(filePath, "utf8");
|
|
10943
|
+
for (const line of raw.split("\n")) {
|
|
10944
|
+
const trimmed = line.trim();
|
|
10945
|
+
if (!trimmed) continue;
|
|
10946
|
+
totalLines += 1;
|
|
10947
|
+
try {
|
|
10948
|
+
const parsed = JSON.parse(trimmed);
|
|
10949
|
+
if (!isValidGraphEdge(parsed, type)) {
|
|
10950
|
+
corruptLines += 1;
|
|
10951
|
+
continue;
|
|
10952
|
+
}
|
|
10953
|
+
validEdges += 1;
|
|
10954
|
+
nodes.add(parsed.from);
|
|
10955
|
+
nodes.add(parsed.to);
|
|
10956
|
+
globalNodes.add(parsed.from);
|
|
10957
|
+
globalNodes.add(parsed.to);
|
|
10958
|
+
} catch {
|
|
10959
|
+
corruptLines += 1;
|
|
10960
|
+
}
|
|
10961
|
+
}
|
|
10962
|
+
} catch {
|
|
10963
|
+
exists3 = false;
|
|
10964
|
+
}
|
|
10965
|
+
files.push({
|
|
10966
|
+
type,
|
|
10967
|
+
filePath,
|
|
10968
|
+
exists: exists3,
|
|
10969
|
+
totalLines,
|
|
10970
|
+
validEdges,
|
|
10971
|
+
corruptLines,
|
|
10972
|
+
uniqueNodes: nodes.size
|
|
10973
|
+
});
|
|
10974
|
+
}
|
|
10975
|
+
const totals = files.reduce(
|
|
10976
|
+
(acc, item) => {
|
|
10977
|
+
acc.totalLines += item.totalLines;
|
|
10978
|
+
acc.validEdges += item.validEdges;
|
|
10979
|
+
acc.corruptLines += item.corruptLines;
|
|
10980
|
+
return acc;
|
|
10981
|
+
},
|
|
10982
|
+
{
|
|
10983
|
+
totalLines: 0,
|
|
10984
|
+
validEdges: 0,
|
|
10985
|
+
corruptLines: 0,
|
|
10986
|
+
uniqueNodes: globalNodes.size
|
|
10987
|
+
}
|
|
10988
|
+
);
|
|
10989
|
+
totals.uniqueNodes = globalNodes.size;
|
|
10990
|
+
const report = {
|
|
10991
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10992
|
+
enabledTypes,
|
|
10993
|
+
totals,
|
|
10994
|
+
files
|
|
10995
|
+
};
|
|
10996
|
+
if (options?.includeRepairGuidance === true) {
|
|
10997
|
+
const guidance = [];
|
|
10998
|
+
if (totals.corruptLines > 0) {
|
|
10999
|
+
guidance.push("Corrupt graph lines detected: back up memory/state/graphs, then rebuild graphs from clean memory replay/extraction runs.");
|
|
11000
|
+
}
|
|
11001
|
+
if (totals.validEdges === 0) {
|
|
11002
|
+
guidance.push("No valid edges detected yet: run normal extraction traffic (or replay ingestion) to seed graph files.");
|
|
11003
|
+
}
|
|
11004
|
+
if (guidance.length > 0) report.repairGuidance = guidance;
|
|
11005
|
+
}
|
|
11006
|
+
return report;
|
|
11007
|
+
}
|
|
10922
11008
|
function detectCausalPhrase(text) {
|
|
10923
11009
|
const lower = text.toLowerCase();
|
|
10924
11010
|
for (const phrase of CAUSAL_PHRASES) {
|
|
@@ -20823,6 +20909,14 @@ async function runMigrateObservationsCliCommand(options) {
|
|
|
20823
20909
|
async function runConversationIndexHealthCliCommand(orchestrator) {
|
|
20824
20910
|
return orchestrator.getConversationIndexHealth();
|
|
20825
20911
|
}
|
|
20912
|
+
async function runGraphHealthCliCommand(options) {
|
|
20913
|
+
return analyzeGraphHealth(options.memoryDir, {
|
|
20914
|
+
entityGraphEnabled: options.entityGraphEnabled,
|
|
20915
|
+
timeGraphEnabled: options.timeGraphEnabled,
|
|
20916
|
+
causalGraphEnabled: options.causalGraphEnabled,
|
|
20917
|
+
includeRepairGuidance: options.includeRepairGuidance
|
|
20918
|
+
});
|
|
20919
|
+
}
|
|
20826
20920
|
async function runTailscaleStatusCliCommand(options = {}) {
|
|
20827
20921
|
const helper = options.helper ?? new TailscaleHelper({ timeoutMs: options.timeoutMs });
|
|
20828
20922
|
return helper.status();
|
|
@@ -21454,6 +21548,18 @@ function registerCli(api, orchestrator) {
|
|
|
21454
21548
|
console.log(JSON.stringify(health, null, 2));
|
|
21455
21549
|
console.log("OK");
|
|
21456
21550
|
});
|
|
21551
|
+
cmd.command("graph-health").description("Show graph edge-file integrity, node coverage, and corruption counts").option("--repair-guidance", "Include non-destructive repair guidance").action(async (...args) => {
|
|
21552
|
+
const options = args[0] ?? {};
|
|
21553
|
+
const report = await runGraphHealthCliCommand({
|
|
21554
|
+
memoryDir: orchestrator.config.memoryDir,
|
|
21555
|
+
entityGraphEnabled: orchestrator.config.entityGraphEnabled,
|
|
21556
|
+
timeGraphEnabled: orchestrator.config.timeGraphEnabled,
|
|
21557
|
+
causalGraphEnabled: orchestrator.config.causalGraphEnabled,
|
|
21558
|
+
includeRepairGuidance: options.repairGuidance === true
|
|
21559
|
+
});
|
|
21560
|
+
console.log(JSON.stringify(report, null, 2));
|
|
21561
|
+
console.log("OK");
|
|
21562
|
+
});
|
|
21457
21563
|
cmd.command("tailscale-status").description("Show Tailscale availability and daemon status").option("--timeout-ms <n>", "Command timeout in milliseconds", "10000").action(async (...args) => {
|
|
21458
21564
|
const options = args[0] ?? {};
|
|
21459
21565
|
const timeoutMsRaw = parseInt(String(options.timeoutMs ?? "10000"), 10);
|