claude-cortex 1.7.2 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/setup/claude-md.d.ts +6 -2
- package/dist/setup/claude-md.d.ts.map +1 -1
- package/dist/setup/claude-md.js +34 -13
- package/dist/setup/claude-md.js.map +1 -1
- package/dist/setup/clawdbot.d.ts +15 -0
- package/dist/setup/clawdbot.d.ts.map +1 -0
- package/dist/setup/clawdbot.js +118 -0
- package/dist/setup/clawdbot.js.map +1 -0
- package/hooks/clawdbot/cortex-memory/HOOK.md +71 -0
- package/hooks/clawdbot/cortex-memory/handler.js +280 -0
- package/package.json +4 -2
- package/scripts/pre-compact-hook.mjs +671 -0
- package/scripts/pre-compact-hook.sh +29 -0
- package/scripts/session-start-hook.mjs +219 -0
- package/scripts/start-dashboard.sh +41 -0
- package/scripts/stop-dashboard.sh +21 -0
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
* npx claude-cortex service install # Auto-start dashboard on login
|
|
19
19
|
* npx claude-cortex service uninstall # Remove auto-start
|
|
20
20
|
* npx claude-cortex service status # Check service status
|
|
21
|
+
* npx claude-cortex clawdbot install # Install Clawdbot/Moltbot hook
|
|
22
|
+
* npx claude-cortex clawdbot uninstall # Remove Clawdbot/Moltbot hook
|
|
23
|
+
* npx claude-cortex clawdbot status # Check Clawdbot hook status
|
|
21
24
|
*/
|
|
22
25
|
export {};
|
|
23
26
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
* npx claude-cortex service install # Auto-start dashboard on login
|
|
19
19
|
* npx claude-cortex service uninstall # Remove auto-start
|
|
20
20
|
* npx claude-cortex service status # Check service status
|
|
21
|
+
* npx claude-cortex clawdbot install # Install Clawdbot/Moltbot hook
|
|
22
|
+
* npx claude-cortex clawdbot uninstall # Remove Clawdbot/Moltbot hook
|
|
23
|
+
* npx claude-cortex clawdbot status # Check Clawdbot hook status
|
|
21
24
|
*/
|
|
22
25
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
23
26
|
import { spawn } from 'child_process';
|
|
@@ -28,6 +31,7 @@ import { startVisualizationServer } from './api/visualization-server.js';
|
|
|
28
31
|
import { handleServiceCommand } from './service/install.js';
|
|
29
32
|
import { setupClaudeMd } from './setup/claude-md.js';
|
|
30
33
|
import { handleHookCommand } from './setup/hooks.js';
|
|
34
|
+
import { handleClawdbotCommand } from './setup/clawdbot.js';
|
|
31
35
|
// Get the directory of this file for relative paths
|
|
32
36
|
const __filename = fileURLToPath(import.meta.url);
|
|
33
37
|
const __dirname = path.dirname(__filename);
|
|
@@ -135,6 +139,11 @@ async function main() {
|
|
|
135
139
|
await handleHookCommand(process.argv[3] || '');
|
|
136
140
|
return;
|
|
137
141
|
}
|
|
142
|
+
// Handle "clawdbot" subcommand
|
|
143
|
+
if (process.argv[2] === 'clawdbot') {
|
|
144
|
+
await handleClawdbotCommand(process.argv[3] || '');
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
138
147
|
// Handle "service" subcommand before normal mode parsing
|
|
139
148
|
if (process.argv[2] === 'service') {
|
|
140
149
|
await handleServiceCommand(process.argv[3] || '');
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,KAAK,EAAgB,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAS5D,oDAAoD;AACpD,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,+BAA+B;AAC/B,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,MAAM,GAAS,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAErC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACtC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5B,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,aAAa,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,GAAG,WAAW,CAAC;QAC5B,CAAC;aAAM,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;YACvC,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;gBAChF,MAAM,CAAC,IAAI,GAAG,IAAkB,CAAC;YACnC,CAAC;YACD,CAAC,EAAE,CAAC;QACN,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,MAAe;IAC3C,wBAAwB;IACxB,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEpC,8BAA8B;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,2BAA2B;IAC3B,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;GAEG;AACH,SAAS,cAAc;IACrB,uEAAuE;IACvE,2DAA2D;IAC3D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;IAEhE,OAAO,CAAC,GAAG,CAAC;;;;;;;;GAQX,CAAC,CAAC;IAEH,gEAAgE;IAChE,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;QAC/C,GAAG,EAAE,YAAY;QACjB,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;QACjC,KAAK,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,oCAAoC;IACpC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9B,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC7D,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;IAClG,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE;QACpC,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,EAAE,CAAC,CAAC;QACxD,CAAC;aAAM,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,KAAK,CAAC,gCAAgC,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,4BAA4B;IAC5B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;QAChC,MAAM,aAAa,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,2BAA2B;IAC3B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,iBAAiB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO;IACT,CAAC;IAED,+BAA+B;IAC/B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;QACnC,MAAM,qBAAqB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,yDAAyD;IACzD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAED,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,SAAS,EAAE,CAAC;IAErC,IAAI,gBAAgB,GAAwB,IAAI,CAAC;IAEjD,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,8CAA8C;QAC9C,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;QACrD,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;SAAM,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,2CAA2C;QAC3C,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACjC,gBAAgB,GAAG,cAAc,EAAE,CAAC;QAEpC,uCAAuC;QACvC,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;YAClC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,oBAAoB,CAAC,CAAC;YACtD,IAAI,gBAAgB,EAAE,CAAC;gBACrB,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACnC,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC/C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;IACnD,CAAC;SAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QAC3B,oDAAoD;QACpD,OAAO,CAAC,GAAG,CAAC,yCAAyC,CAAC,CAAC;QACvD,wBAAwB,CAAC,MAAM,CAAC,CAAC;QACjC,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;SAAM,CAAC;QACN,mDAAmD;QACnD,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;AACH,CAAC;AAED,MAAM;AACN,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,iDAAiD;IACjD,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;IAC9D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Full setup for Claude Cortex.
|
|
3
|
+
*
|
|
4
|
+
* 1. Injects proactive memory instructions into ~/.claude/CLAUDE.md (Claude Code)
|
|
5
|
+
* 2. Installs cortex-memory hook into Clawdbot/Moltbot if detected
|
|
6
|
+
*
|
|
7
|
+
* Both steps are idempotent.
|
|
4
8
|
*/
|
|
5
9
|
export declare function setupClaudeMd(): Promise<void>;
|
|
6
10
|
//# sourceMappingURL=claude-md.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/setup/claude-md.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-md.d.ts","sourceRoot":"","sources":["../../src/setup/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA4CH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAoBnD"}
|
package/dist/setup/claude-md.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Full setup for Claude Cortex.
|
|
3
|
+
*
|
|
4
|
+
* 1. Injects proactive memory instructions into ~/.claude/CLAUDE.md (Claude Code)
|
|
5
|
+
* 2. Installs cortex-memory hook into Clawdbot/Moltbot if detected
|
|
6
|
+
*
|
|
7
|
+
* Both steps are idempotent.
|
|
4
8
|
*/
|
|
5
9
|
import fs from 'fs';
|
|
6
10
|
import path from 'path';
|
|
7
11
|
import os from 'os';
|
|
12
|
+
import { installClawdbotHook, findClawdbotHooksDir } from './clawdbot.js';
|
|
8
13
|
const MARKER = '# Claude Cortex — Memory System';
|
|
9
14
|
const INSTRUCTIONS = `
|
|
10
15
|
${MARKER}
|
|
@@ -20,25 +25,41 @@ You have access to a persistent memory system via MCP tools (\`remember\`, \`rec
|
|
|
20
25
|
|
|
21
26
|
Do not wait until the end of the session. Call \`remember\` right after the event happens.
|
|
22
27
|
`;
|
|
23
|
-
|
|
28
|
+
function setupClaudeCode() {
|
|
24
29
|
const claudeDir = path.join(os.homedir(), '.claude');
|
|
25
30
|
const claudeMdPath = path.join(claudeDir, 'CLAUDE.md');
|
|
26
|
-
// Ensure ~/.claude/ exists
|
|
27
31
|
fs.mkdirSync(claudeDir, { recursive: true });
|
|
28
|
-
// Read existing content
|
|
29
32
|
let existing = '';
|
|
30
33
|
if (fs.existsSync(claudeMdPath)) {
|
|
31
34
|
existing = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
32
35
|
}
|
|
33
|
-
// Check if already configured
|
|
34
36
|
if (existing.includes(MARKER)) {
|
|
35
|
-
console.log('✓ Claude
|
|
36
|
-
|
|
37
|
+
console.log('✓ Claude Code: instructions already present in ~/.claude/CLAUDE.md');
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
const newContent = existing.trimEnd() + '\n' + INSTRUCTIONS;
|
|
41
|
+
fs.writeFileSync(claudeMdPath, newContent, 'utf-8');
|
|
42
|
+
console.log('✓ Claude Code: added memory instructions to ~/.claude/CLAUDE.md');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export async function setupClaudeMd() {
|
|
46
|
+
console.log('Setting up Claude Cortex...\n');
|
|
47
|
+
// 1. Claude Code — always
|
|
48
|
+
setupClaudeCode();
|
|
49
|
+
// 2. Clawdbot/Moltbot — if detected
|
|
50
|
+
const hooksDir = findClawdbotHooksDir();
|
|
51
|
+
if (hooksDir) {
|
|
52
|
+
const hookExists = fs.existsSync(path.join(hooksDir, 'cortex-memory'));
|
|
53
|
+
if (hookExists) {
|
|
54
|
+
console.log('✓ Clawdbot: cortex-memory hook already installed');
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
await installClawdbotHook();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log('- Clawdbot/Moltbot: not detected (skipped)');
|
|
37
62
|
}
|
|
38
|
-
|
|
39
|
-
const newContent = existing.trimEnd() + '\n' + INSTRUCTIONS;
|
|
40
|
-
fs.writeFileSync(claudeMdPath, newContent, 'utf-8');
|
|
41
|
-
console.log('✓ Added Claude Cortex memory instructions to ~/.claude/CLAUDE.md');
|
|
42
|
-
console.log(' Claude will now proactively use memory tools in all projects.');
|
|
63
|
+
console.log('\nSetup complete.');
|
|
43
64
|
}
|
|
44
65
|
//# sourceMappingURL=claude-md.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/setup/claude-md.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-md.js","sourceRoot":"","sources":["../../src/setup/claude-md.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAE1E,MAAM,MAAM,GAAG,iCAAiC,CAAC;AAEjD,MAAM,YAAY,GAAG;EACnB,MAAM;;;;;;;;;;;;CAYP,CAAC;AAEF,SAAS,eAAe;IACtB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IAEvD,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE7C,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;IACpF,CAAC;SAAM,CAAC;QACN,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,EAAE,GAAG,IAAI,GAAG,YAAY,CAAC;QAC5D,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;IAE7C,0BAA0B;IAC1B,eAAe,EAAE,CAAC;IAElB,oCAAoC;IACpC,MAAM,QAAQ,GAAG,oBAAoB,EAAE,CAAC;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC;QACvE,IAAI,UAAU,EAAE,CAAC;YACf,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAClE,CAAC;aAAM,CAAC;YACN,MAAM,mBAAmB,EAAE,CAAC;QAC9B,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clawdbot/Moltbot hook installer.
|
|
3
|
+
*
|
|
4
|
+
* Copies the cortex-memory hook into Clawdbot's bundled hooks directory.
|
|
5
|
+
* Only works if Clawdbot is installed on the system.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Find Clawdbot's bundled hooks directory by locating the binary
|
|
9
|
+
*/
|
|
10
|
+
export declare function findClawdbotHooksDir(): string | null;
|
|
11
|
+
export declare function installClawdbotHook(): Promise<void>;
|
|
12
|
+
export declare function uninstallClawdbotHook(): Promise<void>;
|
|
13
|
+
export declare function clawdbotHookStatus(): Promise<void>;
|
|
14
|
+
export declare function handleClawdbotCommand(subcommand: string): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=clawdbot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clawdbot.d.ts","sourceRoot":"","sources":["../../src/setup/clawdbot.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,IAAI,CA8BpD;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAgCzD;AAED,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB3D;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAcxD;AAED,wBAAsB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe7E"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clawdbot/Moltbot hook installer.
|
|
3
|
+
*
|
|
4
|
+
* Copies the cortex-memory hook into Clawdbot's bundled hooks directory.
|
|
5
|
+
* Only works if Clawdbot is installed on the system.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
13
|
+
const HOOK_NAME = 'cortex-memory';
|
|
14
|
+
// Hook source is in hooks/clawdbot/cortex-memory/ relative to project root
|
|
15
|
+
// From dist/setup/, go up two levels to project root
|
|
16
|
+
const HOOK_SOURCE = path.resolve(__dirname, '..', '..', 'hooks', 'clawdbot', HOOK_NAME);
|
|
17
|
+
/**
|
|
18
|
+
* Find Clawdbot's bundled hooks directory by locating the binary
|
|
19
|
+
*/
|
|
20
|
+
export function findClawdbotHooksDir() {
|
|
21
|
+
try {
|
|
22
|
+
const binPath = execSync('which clawdbot 2>/dev/null || which moltbot 2>/dev/null', {
|
|
23
|
+
encoding: 'utf-8',
|
|
24
|
+
}).trim();
|
|
25
|
+
if (!binPath)
|
|
26
|
+
return null;
|
|
27
|
+
// Resolve symlink — lands in e.g. <prefix>/lib/node_modules/clawdbot/dist/entry.js
|
|
28
|
+
const realBin = fs.realpathSync(binPath);
|
|
29
|
+
// Walk up from resolved path to find dist/hooks/bundled/
|
|
30
|
+
let dir = path.dirname(realBin);
|
|
31
|
+
for (let i = 0; i < 5; i++) {
|
|
32
|
+
const candidate = path.join(dir, 'hooks', 'bundled');
|
|
33
|
+
if (fs.existsSync(candidate)) {
|
|
34
|
+
return candidate;
|
|
35
|
+
}
|
|
36
|
+
// Also check dist/hooks/bundled from current dir
|
|
37
|
+
const distCandidate = path.join(dir, 'dist', 'hooks', 'bundled');
|
|
38
|
+
if (fs.existsSync(distCandidate)) {
|
|
39
|
+
return distCandidate;
|
|
40
|
+
}
|
|
41
|
+
dir = path.dirname(dir);
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export async function installClawdbotHook() {
|
|
50
|
+
const hooksDir = findClawdbotHooksDir();
|
|
51
|
+
if (!hooksDir) {
|
|
52
|
+
console.error('Clawdbot/Moltbot is not installed on this system.');
|
|
53
|
+
console.log('Install it first: npm install -g clawdbot');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
if (!fs.existsSync(HOOK_SOURCE)) {
|
|
57
|
+
console.error('Hook source files not found. Package may be corrupted.');
|
|
58
|
+
process.exit(1);
|
|
59
|
+
}
|
|
60
|
+
const destDir = path.join(hooksDir, HOOK_NAME);
|
|
61
|
+
// Copy hook files
|
|
62
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
63
|
+
for (const file of ['HOOK.md', 'handler.js']) {
|
|
64
|
+
const src = path.join(HOOK_SOURCE, file);
|
|
65
|
+
const dest = path.join(destDir, file);
|
|
66
|
+
fs.copyFileSync(src, dest);
|
|
67
|
+
}
|
|
68
|
+
console.log(`✓ Installed cortex-memory hook to ${destDir}`);
|
|
69
|
+
console.log(' The hook will activate on next Clawdbot restart.');
|
|
70
|
+
console.log('');
|
|
71
|
+
console.log(' What it does:');
|
|
72
|
+
console.log(' • Auto-saves important session context on /new');
|
|
73
|
+
console.log(' • Injects past memories on session start');
|
|
74
|
+
console.log(' • "remember this: ..." keyword trigger');
|
|
75
|
+
}
|
|
76
|
+
export async function uninstallClawdbotHook() {
|
|
77
|
+
const hooksDir = findClawdbotHooksDir();
|
|
78
|
+
if (!hooksDir) {
|
|
79
|
+
console.log('Clawdbot/Moltbot is not installed on this system.');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const destDir = path.join(hooksDir, HOOK_NAME);
|
|
83
|
+
if (!fs.existsSync(destDir)) {
|
|
84
|
+
console.log('cortex-memory hook is not installed.');
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
fs.rmSync(destDir, { recursive: true });
|
|
88
|
+
console.log(`✓ Removed cortex-memory hook from ${destDir}`);
|
|
89
|
+
}
|
|
90
|
+
export async function clawdbotHookStatus() {
|
|
91
|
+
const hooksDir = findClawdbotHooksDir();
|
|
92
|
+
if (!hooksDir) {
|
|
93
|
+
console.log('Clawdbot/Moltbot: not installed');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const destDir = path.join(hooksDir, HOOK_NAME);
|
|
97
|
+
const installed = fs.existsSync(destDir);
|
|
98
|
+
console.log(`Clawdbot/Moltbot: installed`);
|
|
99
|
+
console.log(`Hooks directory: ${hooksDir}`);
|
|
100
|
+
console.log(`cortex-memory: ${installed ? 'installed' : 'not installed'}`);
|
|
101
|
+
}
|
|
102
|
+
export async function handleClawdbotCommand(subcommand) {
|
|
103
|
+
switch (subcommand) {
|
|
104
|
+
case 'install':
|
|
105
|
+
await installClawdbotHook();
|
|
106
|
+
break;
|
|
107
|
+
case 'uninstall':
|
|
108
|
+
await uninstallClawdbotHook();
|
|
109
|
+
break;
|
|
110
|
+
case 'status':
|
|
111
|
+
await clawdbotHookStatus();
|
|
112
|
+
break;
|
|
113
|
+
default:
|
|
114
|
+
console.log('Usage: claude-cortex clawdbot <install|uninstall|status>');
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=clawdbot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clawdbot.js","sourceRoot":"","sources":["../../src/setup/clawdbot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cortex-memory
|
|
3
|
+
description: "Persistent brain-like memory via Claude Cortex — auto-saves session context and recalls past knowledge"
|
|
4
|
+
homepage: https://github.com/mkdelta221/claude-cortex
|
|
5
|
+
metadata:
|
|
6
|
+
{
|
|
7
|
+
"clawdbot":
|
|
8
|
+
{
|
|
9
|
+
"emoji": "🧠",
|
|
10
|
+
"events": ["command:new", "agent:bootstrap", "command"],
|
|
11
|
+
"requires": { "anyBins": ["npx"] },
|
|
12
|
+
"install": [{ "id": "community", "kind": "community", "label": "Claude Cortex" }],
|
|
13
|
+
},
|
|
14
|
+
}
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Cortex Memory Hook
|
|
18
|
+
|
|
19
|
+
Integrates [Claude Cortex](https://github.com/mkdelta221/claude-cortex) persistent memory. Automatically saves important session context and recalls past knowledge at session start.
|
|
20
|
+
|
|
21
|
+
## What It Does
|
|
22
|
+
|
|
23
|
+
### On `/new` (Session End)
|
|
24
|
+
1. Reads the ending session transcript
|
|
25
|
+
2. Pattern-matches for decisions, bug fixes, learnings, architecture changes, and preferences
|
|
26
|
+
3. Saves up to 5 high-salience memories to Claude Cortex via mcporter
|
|
27
|
+
|
|
28
|
+
### On Session Start (Agent Bootstrap)
|
|
29
|
+
1. Calls Cortex `get_context` to retrieve relevant memories
|
|
30
|
+
2. Injects them into the agent's bootstrap context
|
|
31
|
+
3. Agent starts with knowledge of past sessions
|
|
32
|
+
|
|
33
|
+
### Keyword Triggers
|
|
34
|
+
- Say **"remember this"** or **"don't forget"** followed by content
|
|
35
|
+
- Auto-saves to Cortex with critical importance
|
|
36
|
+
|
|
37
|
+
## Requirements
|
|
38
|
+
|
|
39
|
+
- **npx** must be available (Node.js installed)
|
|
40
|
+
- Claude Cortex installs automatically on first use via `npx -y claude-cortex`
|
|
41
|
+
- mcporter must be available for MCP tool calls
|
|
42
|
+
|
|
43
|
+
## Database
|
|
44
|
+
|
|
45
|
+
Memories stored in `~/.claude-cortex/memories.db` (SQLite). Shared with Claude Code sessions — memories created here are available everywhere.
|
|
46
|
+
|
|
47
|
+
## Install
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx claude-cortex clawdbot install
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Uninstall
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx claude-cortex clawdbot uninstall
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or disable without removing:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"hooks": {
|
|
64
|
+
"internal": {
|
|
65
|
+
"entries": {
|
|
66
|
+
"cortex-memory": { "enabled": false }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cortex Memory Hook — Persistent brain-like memory for Clawdbot/Moltbot
|
|
3
|
+
*
|
|
4
|
+
* Integrates Claude Cortex MCP server via mcporter to provide:
|
|
5
|
+
* - Auto-extraction of important session content on /new
|
|
6
|
+
* - Context injection on agent bootstrap
|
|
7
|
+
* - Keyword-triggered memory saves
|
|
8
|
+
*/
|
|
9
|
+
import { execFile } from "node:child_process";
|
|
10
|
+
import fs from "node:fs/promises";
|
|
11
|
+
|
|
12
|
+
// ==================== CORTEX MCP HELPER ====================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Call a Claude Cortex MCP tool via mcporter
|
|
16
|
+
* @param {string} tool - Tool name (e.g., "remember", "recall", "get_context")
|
|
17
|
+
* @param {Record<string, string>} args - Tool arguments as key:value pairs
|
|
18
|
+
* @returns {Promise<string|null>} Raw stdout or null on error
|
|
19
|
+
*/
|
|
20
|
+
function callCortex(tool, args = {}) {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
const cmdArgs = [
|
|
23
|
+
"mcporter", "call", "--stdio",
|
|
24
|
+
"npx -y claude-cortex",
|
|
25
|
+
tool,
|
|
26
|
+
];
|
|
27
|
+
for (const [key, value] of Object.entries(args)) {
|
|
28
|
+
// Escape single quotes in values to avoid FTS5 issues
|
|
29
|
+
const safe = String(value).replace(/'/g, "");
|
|
30
|
+
cmdArgs.push(`${key}:${safe}`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
execFile("npx", cmdArgs, {
|
|
34
|
+
timeout: 15000,
|
|
35
|
+
maxBuffer: 1024 * 256,
|
|
36
|
+
shell: true,
|
|
37
|
+
}, (err, stdout) => {
|
|
38
|
+
if (err) {
|
|
39
|
+
console.error(`[cortex-memory] mcporter error (${tool}):`, err.message);
|
|
40
|
+
resolve(null);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
resolve(stdout?.trim() || null);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// ==================== CONTENT EXTRACTION ====================
|
|
49
|
+
|
|
50
|
+
const PATTERNS = {
|
|
51
|
+
architecture: [
|
|
52
|
+
/\b(?:architecture|designed|structured|pattern|approach)\b.*?(?:uses?|is|with)\b/i,
|
|
53
|
+
/\b(?:created|implemented|refactored|built|set up)\b/i,
|
|
54
|
+
/\b(?:decided?\s+to|going\s+with|chose|opted?\s+for|using)\b/i,
|
|
55
|
+
],
|
|
56
|
+
error: [
|
|
57
|
+
/\b(?:fixed|resolved|solved)\s+(?:by|with|using)\b/i,
|
|
58
|
+
/\b(?:the\s+)?(?:solution|fix|root\s*cause|bug)\s+(?:was|is)\b/i,
|
|
59
|
+
],
|
|
60
|
+
learning: [
|
|
61
|
+
/\b(?:learned|discovered|turns?\s+out|figured\s+out|realized)\b/i,
|
|
62
|
+
/\b(?:TIL|today\s+I\s+learned)\b/i,
|
|
63
|
+
],
|
|
64
|
+
preference: [
|
|
65
|
+
/\b(?:always|never|prefer|don't\s+like|should\s+always)\b/i,
|
|
66
|
+
],
|
|
67
|
+
note: [
|
|
68
|
+
/\b(?:important|remember|key\s+point|crucial|note)\s*:/i,
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Extract high-salience content from session messages
|
|
74
|
+
* @param {string[]} messages - Array of "role: content" strings
|
|
75
|
+
* @returns {Array<{title: string, content: string, category: string}>}
|
|
76
|
+
*/
|
|
77
|
+
function extractMemories(messages) {
|
|
78
|
+
const extracted = [];
|
|
79
|
+
const seen = new Set();
|
|
80
|
+
|
|
81
|
+
for (const msg of messages) {
|
|
82
|
+
if (!msg.startsWith("assistant:")) continue;
|
|
83
|
+
const text = msg.slice("assistant:".length).trim();
|
|
84
|
+
if (text.length < 20) continue;
|
|
85
|
+
|
|
86
|
+
for (const [category, patterns] of Object.entries(PATTERNS)) {
|
|
87
|
+
for (const pattern of patterns) {
|
|
88
|
+
if (pattern.test(text)) {
|
|
89
|
+
const title = text.slice(0, 80).replace(/["\n]/g, " ").trim();
|
|
90
|
+
if (seen.has(title)) break;
|
|
91
|
+
seen.add(title);
|
|
92
|
+
|
|
93
|
+
extracted.push({
|
|
94
|
+
title,
|
|
95
|
+
content: text.slice(0, 500),
|
|
96
|
+
category,
|
|
97
|
+
});
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (extracted.length >= 5) break;
|
|
102
|
+
}
|
|
103
|
+
if (extracted.length >= 5) break;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return extracted;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// ==================== SESSION FILE READER ====================
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Read recent messages from a session JSONL file
|
|
113
|
+
* @param {string} sessionFilePath
|
|
114
|
+
* @returns {Promise<string[]>} Array of "role: content" strings
|
|
115
|
+
*/
|
|
116
|
+
async function getRecentMessages(sessionFilePath) {
|
|
117
|
+
try {
|
|
118
|
+
const content = await fs.readFile(sessionFilePath, "utf-8");
|
|
119
|
+
const lines = content.trim().split("\n");
|
|
120
|
+
const recentLines = lines.slice(-30);
|
|
121
|
+
|
|
122
|
+
const messages = [];
|
|
123
|
+
for (const line of recentLines) {
|
|
124
|
+
try {
|
|
125
|
+
const entry = JSON.parse(line);
|
|
126
|
+
if (entry.type === "message" && entry.message) {
|
|
127
|
+
const msg = entry.message;
|
|
128
|
+
if ((msg.role === "user" || msg.role === "assistant") && msg.content) {
|
|
129
|
+
const text = Array.isArray(msg.content)
|
|
130
|
+
? msg.content.find((c) => c.type === "text")?.text
|
|
131
|
+
: msg.content;
|
|
132
|
+
if (text && !text.startsWith("/")) {
|
|
133
|
+
messages.push(`${msg.role}: ${text}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch {
|
|
138
|
+
// Skip invalid lines
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return messages;
|
|
142
|
+
} catch {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// ==================== EVENT HANDLERS ====================
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Handle command:new — extract memories from ending session
|
|
151
|
+
*/
|
|
152
|
+
async function onSessionEnd(event) {
|
|
153
|
+
const context = event.context || {};
|
|
154
|
+
const sessionEntry = context.previousSessionEntry || context.sessionEntry || {};
|
|
155
|
+
const sessionFile = sessionEntry.sessionFile;
|
|
156
|
+
|
|
157
|
+
if (!sessionFile) {
|
|
158
|
+
console.log("[cortex-memory] No session file found, skipping extraction");
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const messages = await getRecentMessages(sessionFile);
|
|
163
|
+
if (messages.length === 0) {
|
|
164
|
+
console.log("[cortex-memory] No messages to extract");
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const memories = extractMemories(messages);
|
|
169
|
+
if (memories.length === 0) {
|
|
170
|
+
console.log("[cortex-memory] No high-salience content found");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
let saved = 0;
|
|
175
|
+
for (const mem of memories) {
|
|
176
|
+
const result = await callCortex("remember", {
|
|
177
|
+
title: mem.title,
|
|
178
|
+
content: mem.content,
|
|
179
|
+
category: mem.category,
|
|
180
|
+
project: "clawdbot",
|
|
181
|
+
scope: "global",
|
|
182
|
+
importance: "high",
|
|
183
|
+
tags: "auto-extracted,clawdbot-hook",
|
|
184
|
+
});
|
|
185
|
+
if (result) saved++;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log(`[cortex-memory] Saved ${saved}/${memories.length} memories from session`);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Handle agent:bootstrap — inject past context into agent
|
|
193
|
+
*/
|
|
194
|
+
async function onBootstrap(event) {
|
|
195
|
+
const context = event.context || {};
|
|
196
|
+
if (!Array.isArray(context.bootstrapFiles)) return;
|
|
197
|
+
|
|
198
|
+
const result = await callCortex("get_context", {
|
|
199
|
+
query: "clawdbot session context",
|
|
200
|
+
format: "summary",
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
if (!result || result.length < 20) {
|
|
204
|
+
console.log("[cortex-memory] No context to inject");
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
context.bootstrapFiles.push({
|
|
209
|
+
name: "CORTEX_MEMORY.md",
|
|
210
|
+
content: `# Past Session Context (from Claude Cortex)\n\n${result}`,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
console.log("[cortex-memory] Injected past context into bootstrap");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Handle command events — check for keyword triggers
|
|
218
|
+
*/
|
|
219
|
+
async function onKeywordTrigger(event) {
|
|
220
|
+
if (event.action === "new" || event.action === "stop") return;
|
|
221
|
+
|
|
222
|
+
const context = event.context || {};
|
|
223
|
+
const sessionEntry = context.sessionEntry || {};
|
|
224
|
+
const lastMessage = context.lastUserMessage || sessionEntry.lastUserMessage;
|
|
225
|
+
if (!lastMessage || typeof lastMessage !== "string") return;
|
|
226
|
+
|
|
227
|
+
const lower = lastMessage.toLowerCase();
|
|
228
|
+
const triggers = ["remember this", "don't forget", "dont forget"];
|
|
229
|
+
const triggered = triggers.some((t) => lower.includes(t));
|
|
230
|
+
if (!triggered) return;
|
|
231
|
+
|
|
232
|
+
let content = lastMessage;
|
|
233
|
+
for (const t of triggers) {
|
|
234
|
+
const idx = lower.indexOf(t);
|
|
235
|
+
if (idx !== -1) {
|
|
236
|
+
content = lastMessage.slice(idx + t.length).replace(/^[:\s]+/, "").trim();
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (content.length < 5) return;
|
|
242
|
+
|
|
243
|
+
const title = content.slice(0, 80).replace(/["\n]/g, " ").trim();
|
|
244
|
+
|
|
245
|
+
const result = await callCortex("remember", {
|
|
246
|
+
title,
|
|
247
|
+
content: content.slice(0, 500),
|
|
248
|
+
category: "note",
|
|
249
|
+
project: "clawdbot",
|
|
250
|
+
scope: "global",
|
|
251
|
+
importance: "critical",
|
|
252
|
+
tags: "keyword-trigger,clawdbot-hook",
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
if (result) {
|
|
256
|
+
event.messages.push(`Saved to Cortex memory: "${title}"`);
|
|
257
|
+
console.log(`[cortex-memory] Keyword trigger saved: ${title}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ==================== MAIN HANDLER ====================
|
|
262
|
+
|
|
263
|
+
const cortexMemoryHandler = async (event) => {
|
|
264
|
+
try {
|
|
265
|
+
if (event.type === "command" && event.action === "new") {
|
|
266
|
+
await onSessionEnd(event);
|
|
267
|
+
} else if (event.type === "agent" && event.action === "bootstrap") {
|
|
268
|
+
await onBootstrap(event);
|
|
269
|
+
} else if (event.type === "command") {
|
|
270
|
+
await onKeywordTrigger(event);
|
|
271
|
+
}
|
|
272
|
+
} catch (err) {
|
|
273
|
+
console.error(
|
|
274
|
+
"[cortex-memory] Error:",
|
|
275
|
+
err instanceof Error ? err.message : String(err)
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
export default cortexMemoryHandler;
|