@gamaze/hicortex 0.2.1 → 0.3.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.
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ /**
3
+ * CC transcript reader — reads Claude Code .jsonl session files.
4
+ *
5
+ * CC stores transcripts at ~/.claude/projects/<project-hash>/<session-uuid>.jsonl.
6
+ * Each line is a JSON object with type, message, timestamp, etc.
7
+ *
8
+ * The reader scans for new sessions since the last nightly run
9
+ * and feeds them to the existing distiller pipeline.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.readCcTranscripts = readCcTranscripts;
13
+ const node_fs_1 = require("node:fs");
14
+ const node_path_1 = require("node:path");
15
+ const node_os_1 = require("node:os");
16
+ const CC_PROJECTS_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), ".claude", "projects");
17
+ /**
18
+ * Read all CC transcripts modified since `since`.
19
+ * Returns one batch per session file.
20
+ */
21
+ function readCcTranscripts(since, projectsDir = CC_PROJECTS_DIR) {
22
+ const batches = [];
23
+ let projectDirs;
24
+ try {
25
+ projectDirs = (0, node_fs_1.readdirSync)(projectsDir);
26
+ }
27
+ catch {
28
+ return []; // No CC projects directory
29
+ }
30
+ for (const projectDir of projectDirs) {
31
+ const projectPath = (0, node_path_1.join)(projectsDir, projectDir);
32
+ let stat;
33
+ try {
34
+ stat = (0, node_fs_1.statSync)(projectPath);
35
+ }
36
+ catch {
37
+ continue;
38
+ }
39
+ if (!stat.isDirectory())
40
+ continue;
41
+ const projectName = decodeProjectDirName(projectDir);
42
+ let files;
43
+ try {
44
+ files = (0, node_fs_1.readdirSync)(projectPath);
45
+ }
46
+ catch {
47
+ continue;
48
+ }
49
+ for (const file of files) {
50
+ if (!file.endsWith(".jsonl"))
51
+ continue;
52
+ const filePath = (0, node_path_1.join)(projectPath, file);
53
+ let fileStat;
54
+ try {
55
+ fileStat = (0, node_fs_1.statSync)(filePath);
56
+ }
57
+ catch {
58
+ continue;
59
+ }
60
+ // Skip files not modified since last run
61
+ if (fileStat.mtime <= since)
62
+ continue;
63
+ const batch = parseTranscriptFile(filePath, projectName);
64
+ if (batch) {
65
+ batches.push(batch);
66
+ }
67
+ }
68
+ }
69
+ return batches;
70
+ }
71
+ /**
72
+ * Parse a single .jsonl transcript file into a batch.
73
+ * Returns null if the file has too few meaningful entries.
74
+ */
75
+ function parseTranscriptFile(filePath, projectName) {
76
+ let raw;
77
+ try {
78
+ raw = (0, node_fs_1.readFileSync)(filePath, "utf-8");
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ const lines = raw.split("\n").filter((l) => l.trim());
84
+ if (lines.length < 4)
85
+ return null; // Too short to be meaningful
86
+ const entries = [];
87
+ let lastTimestamp = "";
88
+ for (const line of lines) {
89
+ try {
90
+ const entry = JSON.parse(line);
91
+ entries.push(entry);
92
+ if (entry.timestamp) {
93
+ lastTimestamp = entry.timestamp;
94
+ }
95
+ }
96
+ catch {
97
+ // Skip malformed lines
98
+ }
99
+ }
100
+ if (entries.length < 4)
101
+ return null;
102
+ // Extract session ID from filename (UUID.jsonl)
103
+ const sessionId = (0, node_path_1.basename)(filePath, ".jsonl");
104
+ return {
105
+ sessionId,
106
+ projectName,
107
+ date: lastTimestamp
108
+ ? lastTimestamp.slice(0, 10)
109
+ : new Date().toISOString().slice(0, 10),
110
+ entries,
111
+ };
112
+ }
113
+ /**
114
+ * Decode CC project directory name to a human-readable project name.
115
+ * CC uses path-based hashing: "-Users-mattias-Development-Tools-hicortex"
116
+ * becomes "hicortex" (last path component).
117
+ */
118
+ function decodeProjectDirName(dirName) {
119
+ // CC encodes paths by replacing / with -
120
+ // e.g. "-Users-mattias-Development-Tools-hicortex"
121
+ const parts = dirName.split("-").filter(Boolean);
122
+ if (parts.length === 0)
123
+ return dirName;
124
+ // Use the last meaningful path component as project name
125
+ return parts[parts.length - 1];
126
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Hicortex uninstall — clean removal of CC integration.
3
+ * Preserves the database (user data).
4
+ */
5
+ export declare function runUninstall(): Promise<void>;
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ /**
3
+ * Hicortex uninstall — clean removal of CC integration.
4
+ * Preserves the database (user data).
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.runUninstall = runUninstall;
8
+ const node_fs_1 = require("node:fs");
9
+ const node_path_1 = require("node:path");
10
+ const node_os_1 = require("node:os");
11
+ const node_child_process_1 = require("node:child_process");
12
+ const node_readline_1 = require("node:readline");
13
+ const claude_md_js_1 = require("./claude-md.js");
14
+ const HICORTEX_HOME = (0, node_path_1.join)((0, node_os_1.homedir)(), ".hicortex");
15
+ const CC_SETTINGS = (0, node_path_1.join)((0, node_os_1.homedir)(), ".claude", "settings.json");
16
+ const CC_COMMANDS_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), ".claude", "commands");
17
+ const CLAUDE_MD = (0, node_path_1.join)((0, node_os_1.homedir)(), ".claude", "CLAUDE.md");
18
+ async function ask(question) {
19
+ const rl = (0, node_readline_1.createInterface)({ input: process.stdin, output: process.stdout });
20
+ return new Promise((resolve) => {
21
+ rl.question(question, (answer) => {
22
+ rl.close();
23
+ resolve(answer.trim());
24
+ });
25
+ });
26
+ }
27
+ async function runUninstall() {
28
+ console.log("Hicortex — Uninstall CC Integration\n");
29
+ const answer = await ask("This will remove Hicortex from Claude Code. Your memory database is preserved. Continue? [y/N] ");
30
+ if (answer.toLowerCase() !== "y") {
31
+ console.log("Cancelled.");
32
+ return;
33
+ }
34
+ console.log();
35
+ // 1. Stop and remove daemon
36
+ const os = (0, node_os_1.platform)();
37
+ if (os === "darwin") {
38
+ const plistPath = (0, node_path_1.join)((0, node_os_1.homedir)(), "Library", "LaunchAgents", "com.gamaze.hicortex.plist");
39
+ if ((0, node_fs_1.existsSync)(plistPath)) {
40
+ try {
41
+ (0, node_child_process_1.execSync)(`launchctl unload ${plistPath} 2>/dev/null`);
42
+ }
43
+ catch { /* not loaded */ }
44
+ (0, node_fs_1.unlinkSync)(plistPath);
45
+ console.log(" ✓ Removed launchd daemon");
46
+ }
47
+ }
48
+ else if (os === "linux") {
49
+ try {
50
+ (0, node_child_process_1.execSync)("systemctl --user disable --now hicortex.service 2>/dev/null");
51
+ const servicePath = (0, node_path_1.join)((0, node_os_1.homedir)(), ".config", "systemd", "user", "hicortex.service");
52
+ if ((0, node_fs_1.existsSync)(servicePath))
53
+ (0, node_fs_1.unlinkSync)(servicePath);
54
+ (0, node_child_process_1.execSync)("systemctl --user daemon-reload 2>/dev/null");
55
+ console.log(" ✓ Removed systemd service");
56
+ }
57
+ catch { /* not installed */ }
58
+ }
59
+ // 2. Remove MCP from CC settings
60
+ try {
61
+ const raw = (0, node_fs_1.readFileSync)(CC_SETTINGS, "utf-8");
62
+ const settings = JSON.parse(raw);
63
+ if (settings?.mcpServers?.hicortex) {
64
+ delete settings.mcpServers.hicortex;
65
+ (0, node_fs_1.writeFileSync)(CC_SETTINGS, JSON.stringify(settings, null, 2));
66
+ console.log(" ✓ Removed MCP server from CC settings");
67
+ }
68
+ }
69
+ catch { /* no settings */ }
70
+ // 3. Remove CC custom commands
71
+ for (const cmd of ["learn.md", "hicortex-activate.md"]) {
72
+ const cmdPath = (0, node_path_1.join)(CC_COMMANDS_DIR, cmd);
73
+ if ((0, node_fs_1.existsSync)(cmdPath)) {
74
+ (0, node_fs_1.unlinkSync)(cmdPath);
75
+ }
76
+ }
77
+ console.log(" ✓ Removed /learn and /hicortex-activate commands");
78
+ // 4. Remove CLAUDE.md block
79
+ if ((0, claude_md_js_1.removeLessonsBlock)(CLAUDE_MD)) {
80
+ console.log(" ✓ Removed Hicortex Learnings block from CLAUDE.md");
81
+ }
82
+ console.log(`\n✓ Uninstalled. Database preserved at ${HICORTEX_HOME}/hicortex.db`);
83
+ console.log(" To remove all data: rm -rf ~/.hicortex");
84
+ }
@@ -2,7 +2,7 @@
2
2
  "id": "hicortex",
3
3
  "name": "Hicortex — Long-term Memory That Learns",
4
4
  "description": "Your agents remember past decisions, avoid repeated mistakes, and get smarter every day. Nightly reflection generates actionable lessons that automatically update agent behavior.",
5
- "version": "0.2.1",
5
+ "version": "0.3.1",
6
6
  "kind": "lifecycle",
7
7
  "skills": ["./skills/hicortex-memory", "./skills/hicortex-learn", "./skills/hicortex-activate"],
8
8
  "configSchema": {
package/package.json CHANGED
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "@gamaze/hicortex",
3
- "version": "0.2.1",
4
- "description": "Human-like memory for self-improving AI agents. Automatic capturing, nightly reflection, and cross-agent learning. OpenClaw plugin.",
3
+ "version": "0.3.1",
4
+ "description": "Human-like memory for self-improving AI agents. Automatic capturing, nightly reflection, and cross-agent learning. Works with Claude Code and OpenClaw.",
5
5
  "main": "dist/index.js",
6
+ "bin": {
7
+ "hicortex": "dist/cli.js"
8
+ },
6
9
  "openclaw": {
7
- "extensions": ["./dist/index.js"]
10
+ "extensions": [
11
+ "./dist/index.js"
12
+ ]
8
13
  },
9
14
  "types": "dist/index.d.ts",
10
15
  "files": [
@@ -20,10 +25,11 @@
20
25
  "prepublishOnly": "npm run build"
21
26
  },
22
27
  "devDependencies": {
23
- "typescript": "^5.4.0",
24
- "vitest": "^3.0.0",
28
+ "@types/better-sqlite3": "^7.6.0",
29
+ "@types/express": "^5.0.6",
25
30
  "@types/node": "^22.0.0",
26
- "@types/better-sqlite3": "^7.6.0"
31
+ "typescript": "^5.4.0",
32
+ "vitest": "^3.0.0"
27
33
  },
28
34
  "engines": {
29
35
  "node": ">=18"
@@ -35,8 +41,10 @@
35
41
  "directory": "packages/openclaw-plugin"
36
42
  },
37
43
  "dependencies": {
44
+ "@huggingface/transformers": "^3.0.0",
45
+ "@modelcontextprotocol/sdk": "^1.28.0",
38
46
  "better-sqlite3": "^11.0.0",
39
- "sqlite-vec": "^0.1.7",
40
- "@huggingface/transformers": "^3.0.0"
47
+ "express": "^4.21.0",
48
+ "sqlite-vec": "^0.1.7"
41
49
  }
42
- }
50
+ }