shieldcortex 2.10.6 → 2.10.7
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.
|
@@ -540,6 +540,108 @@ async function onKeywordTrigger(event) {
|
|
|
540
540
|
await checkAndSaveKeywordTrigger(lastMessage, event);
|
|
541
541
|
}
|
|
542
542
|
|
|
543
|
+
// ==================== SELF-CHECK & SELF-HEAL ====================
|
|
544
|
+
|
|
545
|
+
/**
|
|
546
|
+
* One-shot self-check that runs on first bootstrap per process.
|
|
547
|
+
* Detects legacy hook paths and attempts self-heal by copying files.
|
|
548
|
+
*
|
|
549
|
+
* Safety:
|
|
550
|
+
* - _selfCheckDone flag prevents re-runs (no loops)
|
|
551
|
+
* - All fs ops are sync-safe copies (no recursive watchers, no intervals)
|
|
552
|
+
* - Fails silently on any error — never blocks bootstrap
|
|
553
|
+
*/
|
|
554
|
+
let _selfCheckDone = false;
|
|
555
|
+
|
|
556
|
+
async function selfCheckAndHeal(event) {
|
|
557
|
+
if (_selfCheckDone) return;
|
|
558
|
+
_selfCheckDone = true; // Set immediately to prevent re-entry
|
|
559
|
+
|
|
560
|
+
try {
|
|
561
|
+
const path = await import("node:path");
|
|
562
|
+
const { homedir } = await import("node:os");
|
|
563
|
+
const home = homedir();
|
|
564
|
+
|
|
565
|
+
// Where am I running from?
|
|
566
|
+
const myDir = path.dirname(new URL(import.meta.url).pathname);
|
|
567
|
+
|
|
568
|
+
// Expected locations (newest first)
|
|
569
|
+
const expectedDirs = [
|
|
570
|
+
path.join(home, ".openclaw", "hooks", "internal", "cortex-memory"),
|
|
571
|
+
path.join(home, ".openclaw", "hooks", "cortex-memory"),
|
|
572
|
+
];
|
|
573
|
+
|
|
574
|
+
const isInExpectedLocation = expectedDirs.some(d => myDir.startsWith(d));
|
|
575
|
+
|
|
576
|
+
if (isInExpectedLocation) {
|
|
577
|
+
// Check for stale legacy copies that could cause confusion
|
|
578
|
+
const legacyDirs = [
|
|
579
|
+
path.join(home, ".clawdbot", "hooks", "cortex-memory"),
|
|
580
|
+
path.join(home, ".clawdbot", "hooks", "internal", "cortex-memory"),
|
|
581
|
+
];
|
|
582
|
+
|
|
583
|
+
// Only check real directories, not symlinks pointing back to .openclaw
|
|
584
|
+
const clawdbotBase = path.join(home, ".clawdbot");
|
|
585
|
+
let isSymlink = false;
|
|
586
|
+
try {
|
|
587
|
+
const stat = await fs.lstat(clawdbotBase);
|
|
588
|
+
isSymlink = stat.isSymbolicLink();
|
|
589
|
+
} catch { /* doesn't exist */ }
|
|
590
|
+
|
|
591
|
+
if (!isSymlink) {
|
|
592
|
+
for (const legacyDir of legacyDirs) {
|
|
593
|
+
try {
|
|
594
|
+
await fs.access(legacyDir);
|
|
595
|
+
// Legacy dir exists and isn't a symlink — clean it up
|
|
596
|
+
await fs.rm(legacyDir, { recursive: true });
|
|
597
|
+
console.log(`[cortex-memory] Self-heal: removed stale legacy hook at ${legacyDir}`);
|
|
598
|
+
} catch { /* doesn't exist — good */ }
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return; // All good
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// We're running from an unexpected location — try to copy ourselves to the right place
|
|
606
|
+
const targetDir = expectedDirs[0]; // prefer hooks/internal/cortex-memory
|
|
607
|
+
const targetParent = path.dirname(targetDir);
|
|
608
|
+
|
|
609
|
+
// Ensure parent exists
|
|
610
|
+
await fs.mkdir(targetParent, { recursive: true });
|
|
611
|
+
await fs.mkdir(targetDir, { recursive: true });
|
|
612
|
+
|
|
613
|
+
// Copy our files to the expected location
|
|
614
|
+
const filesToCopy = ["HOOK.md", "handler.ts"];
|
|
615
|
+
let copiedCount = 0;
|
|
616
|
+
|
|
617
|
+
for (const file of filesToCopy) {
|
|
618
|
+
const src = path.join(myDir, file);
|
|
619
|
+
const dest = path.join(targetDir, file);
|
|
620
|
+
try {
|
|
621
|
+
await fs.access(src);
|
|
622
|
+
await fs.copyFile(src, dest);
|
|
623
|
+
copiedCount++;
|
|
624
|
+
} catch { /* source file missing — skip */ }
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
if (copiedCount > 0) {
|
|
628
|
+
console.log(`[cortex-memory] Self-heal: copied ${copiedCount} file(s) to ${targetDir}`);
|
|
629
|
+
console.log(`[cortex-memory] Hook will load from correct path on next restart`);
|
|
630
|
+
|
|
631
|
+
// Inject a warning into bootstrap context so the agent knows
|
|
632
|
+
if (event?.context?.bootstrapFiles && Array.isArray(event.context.bootstrapFiles)) {
|
|
633
|
+
event.context.bootstrapFiles.push({
|
|
634
|
+
name: "SHIELDCORTEX_HOOK_MIGRATED.md",
|
|
635
|
+
content: `# ShieldCortex Hook Self-Healed\n\nThe cortex-memory hook was running from an unexpected path (${myDir}).\nIt has been copied to ${targetDir}.\nA gateway restart will pick up the new location.\n\nNo action needed — this is informational.`,
|
|
636
|
+
});
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
} catch (err) {
|
|
640
|
+
// Self-check must NEVER break the hook — fail silently
|
|
641
|
+
console.warn("[cortex-memory] Self-check failed (non-fatal):", err instanceof Error ? err.message : String(err));
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
|
|
543
645
|
// ==================== MAIN HANDLER ====================
|
|
544
646
|
|
|
545
647
|
const cortexMemoryHandler = async (event) => {
|
|
@@ -552,6 +654,7 @@ const cortexMemoryHandler = async (event) => {
|
|
|
552
654
|
// Also save on clear/exit - these also end the session context
|
|
553
655
|
await onSessionStop(event);
|
|
554
656
|
} else if (event.type === "agent" && event.action === "bootstrap") {
|
|
657
|
+
await selfCheckAndHeal(event);
|
|
555
658
|
await onBootstrap(event);
|
|
556
659
|
} else if (event.type === "message") {
|
|
557
660
|
// FIX: Check for keyword triggers on message events (not just commands)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shieldcortex",
|
|
3
|
-
"version": "2.10.
|
|
3
|
+
"version": "2.10.7",
|
|
4
4
|
"description": "Persistent brain for AI agents. Knowledge graphs, memory decay, contradiction detection, consolidation — plus the only defence pipeline that stops memory poisoning. Works with Claude Code, OpenClaw, LangChain, and any MCP agent.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|