@gamaze/hicortex 0.2.1 → 0.3.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/README.md +77 -37
- package/dist/claude-md.d.ts +28 -0
- package/dist/claude-md.js +142 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.js +84 -0
- package/dist/consolidate.js +1 -1
- package/dist/db.d.ts +10 -0
- package/dist/db.js +74 -0
- package/dist/index.js +10 -14
- package/dist/init.d.ts +17 -0
- package/dist/init.js +397 -0
- package/dist/llm.d.ts +20 -2
- package/dist/llm.js +82 -2
- package/dist/mcp-server.d.ts +19 -0
- package/dist/mcp-server.js +266 -0
- package/dist/nightly.d.ts +15 -0
- package/dist/nightly.js +167 -0
- package/dist/status.d.ts +4 -0
- package/dist/status.js +120 -0
- package/dist/transcript-reader.d.ts +20 -0
- package/dist/transcript-reader.js +126 -0
- package/dist/uninstall.d.ts +5 -0
- package/dist/uninstall.js +84 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +17 -9
package/README.md
CHANGED
|
@@ -2,51 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
Upgrade your agents with Hicortex for automatic capturing of experiences, feedback, and decisions across all your connected agents. They start learning from every session, self-reflect, avoid past mistakes, and improve on their own — overnight, automatically. No configuration needed.
|
|
4
4
|
|
|
5
|
+
Works with **OpenClaw** (in-process plugin) and **Claude Code** (HTTP/SSE MCP server).
|
|
6
|
+
|
|
5
7
|
## Requirements
|
|
6
8
|
|
|
7
|
-
-
|
|
8
|
-
- LLM provider
|
|
9
|
+
- Node.js 18+
|
|
10
|
+
- LLM provider (auto-detected from OC config or `ANTHROPIC_API_KEY` for CC)
|
|
9
11
|
- ~500MB disk for database + embedding model
|
|
10
12
|
|
|
11
|
-
## Install
|
|
13
|
+
## Install — OpenClaw
|
|
12
14
|
|
|
13
15
|
```bash
|
|
14
16
|
openclaw plugins install @gamaze/hicortex
|
|
17
|
+
openclaw gateway restart
|
|
15
18
|
```
|
|
16
19
|
|
|
17
|
-
|
|
20
|
+
No configuration needed. The plugin auto-detects your LLM provider from OpenClaw settings on first startup.
|
|
21
|
+
|
|
22
|
+
## Install — Claude Code
|
|
18
23
|
|
|
19
|
-
|
|
24
|
+
```bash
|
|
25
|
+
npx @gamaze/hicortex init
|
|
26
|
+
```
|
|
20
27
|
|
|
21
|
-
|
|
28
|
+
This detects your environment, installs a persistent MCP server daemon, registers it with Claude Code, and adds `/learn` and `/hicortex-activate` commands. Restart CC after setup.
|
|
29
|
+
|
|
30
|
+
Or manually:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Start server
|
|
34
|
+
npx @gamaze/hicortex server
|
|
35
|
+
|
|
36
|
+
# Register with CC
|
|
37
|
+
claude mcp add hicortex --transport http http://localhost:8787/sse
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Configure
|
|
41
|
+
|
|
42
|
+
Optional config for OC (add to plugin entry in `~/.openclaw/openclaw.json`):
|
|
22
43
|
|
|
23
44
|
| Field | Default | Description |
|
|
24
45
|
|-------|---------|-------------|
|
|
25
46
|
| `licenseKey` | _(none)_ | License key. Free tier (250 memories) without key. |
|
|
26
|
-
| `llmBaseUrl` | _(auto)_ | Override LLM base URL
|
|
27
|
-
| `llmApiKey` | _(auto)_ | Override LLM API key
|
|
47
|
+
| `llmBaseUrl` | _(auto)_ | Override LLM base URL |
|
|
48
|
+
| `llmApiKey` | _(auto)_ | Override LLM API key |
|
|
28
49
|
| `llmModel` | _(auto)_ | Override model for scoring and distillation |
|
|
29
50
|
| `reflectModel` | _(auto)_ | Override model for nightly reflection |
|
|
30
51
|
| `consolidateHour` | `2` | Hour (0-23, local time) for nightly consolidation |
|
|
31
52
|
| `dbPath` | _(auto)_ | Custom database path |
|
|
32
53
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
openclaw gateway restart
|
|
37
|
-
```
|
|
54
|
+
For CC, set environment variables: `ANTHROPIC_API_KEY` (auto-detected), or `HICORTEX_LLM_BASE_URL` + `HICORTEX_LLM_API_KEY` + `HICORTEX_LLM_MODEL` for custom providers.
|
|
38
55
|
|
|
39
56
|
## What Happens Automatically
|
|
40
57
|
|
|
41
58
|
| When | What | How |
|
|
42
59
|
|------|------|-----|
|
|
43
|
-
| Agent start | Recent lessons injected into context | `before_agent_start` hook |
|
|
44
|
-
| Agent end | Conversation captured and distilled | `agent_end` hook
|
|
60
|
+
| Agent start | Recent lessons injected into context | OC: `before_agent_start` hook / CC: CLAUDE.md block |
|
|
61
|
+
| Agent end | Conversation captured and distilled | OC: `agent_end` hook / CC: nightly transcript scan |
|
|
45
62
|
| Nightly | Score importance, reflect, link, decay | In-process consolidation pipeline |
|
|
46
63
|
|
|
47
64
|
## Agent Tools
|
|
48
65
|
|
|
49
|
-
|
|
66
|
+
Available via MCP (both OC and CC):
|
|
50
67
|
|
|
51
68
|
- **hicortex_search** — Semantic search across all stored knowledge
|
|
52
69
|
- **hicortex_context** — Get recent decisions and project state
|
|
@@ -55,22 +72,41 @@ The plugin registers these tools for agents to use:
|
|
|
55
72
|
|
|
56
73
|
Skills: `/learn` to save explicit learnings.
|
|
57
74
|
|
|
75
|
+
## CLI Commands
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx @gamaze/hicortex server # Start MCP HTTP/SSE server (port 8787)
|
|
79
|
+
npx @gamaze/hicortex init # Set up for Claude Code
|
|
80
|
+
npx @gamaze/hicortex nightly # Run distill + consolidate + inject
|
|
81
|
+
npx @gamaze/hicortex status # Show config, DB stats, adapters
|
|
82
|
+
npx @gamaze/hicortex uninstall # Remove CC integration (keeps DB)
|
|
83
|
+
```
|
|
84
|
+
|
|
58
85
|
## Architecture
|
|
59
86
|
|
|
60
87
|
```
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
@gamaze/hicortex (single npm package, dual mode)
|
|
89
|
+
├── OpenClaw mode (in-process plugin)
|
|
90
|
+
│ ├── before_agent_start → inject lessons
|
|
91
|
+
│ ├── agent_end → capture + distill
|
|
92
|
+
│ └── registerService → DB, LLM, consolidation timer
|
|
93
|
+
│
|
|
94
|
+
└── Claude Code mode (persistent HTTP/SSE server)
|
|
95
|
+
├── MCP tools → hicortex_search, hicortex_context, hicortex_ingest, hicortex_lessons
|
|
96
|
+
├── /health endpoint → monitoring
|
|
97
|
+
├── Nightly → scan CC transcripts, distill, consolidate, inject CLAUDE.md
|
|
98
|
+
└── Shared DB at ~/.hicortex/hicortex.db
|
|
99
|
+
|
|
100
|
+
Shared core:
|
|
101
|
+
├── SQLite + sqlite-vec + FTS5 (single file)
|
|
102
|
+
├── bge-small-en-v1.5 embeddings (ONNX, local CPU)
|
|
103
|
+
├── BM25 + vector search with RRF fusion
|
|
104
|
+
└── Multi-provider LLM (20+ providers)
|
|
71
105
|
```
|
|
72
106
|
|
|
73
|
-
|
|
107
|
+
## Database
|
|
108
|
+
|
|
109
|
+
Canonical location: `~/.hicortex/hicortex.db`. Existing OC installations at `~/.openclaw/data/hicortex.db` are automatically migrated on upgrade.
|
|
74
110
|
|
|
75
111
|
## Pricing
|
|
76
112
|
|
|
@@ -85,33 +121,37 @@ Get a license key at [hicortex.gamaze.com](https://hicortex.gamaze.com).
|
|
|
85
121
|
|
|
86
122
|
## Uninstall
|
|
87
123
|
|
|
124
|
+
**OpenClaw:**
|
|
88
125
|
```bash
|
|
89
126
|
openclaw plugins uninstall hicortex
|
|
90
127
|
```
|
|
91
128
|
|
|
92
|
-
|
|
129
|
+
**Claude Code:**
|
|
130
|
+
```bash
|
|
131
|
+
npx @gamaze/hicortex uninstall
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Your memory database is preserved by default. To remove all data: `rm -rf ~/.hicortex`
|
|
93
135
|
|
|
94
136
|
## Development
|
|
95
137
|
|
|
96
138
|
```bash
|
|
97
|
-
# Local dev install
|
|
98
|
-
openclaw plugins install -l ./packages/openclaw-plugin
|
|
99
|
-
|
|
100
|
-
# Build
|
|
101
139
|
cd packages/openclaw-plugin
|
|
102
140
|
npm install
|
|
103
141
|
npm run build
|
|
104
|
-
|
|
105
|
-
# Test
|
|
106
142
|
npm test
|
|
107
143
|
```
|
|
108
144
|
|
|
109
145
|
## Troubleshooting
|
|
110
146
|
|
|
111
|
-
**Tools not visible to agent:** The plugin auto-adds tools to `tools.allow` on startup.
|
|
147
|
+
**Tools not visible to agent (OC):** The plugin auto-adds tools to `tools.allow` on startup. Restart the gateway after install.
|
|
112
148
|
|
|
113
|
-
**LLM auto-config failed:** Check
|
|
149
|
+
**LLM auto-config failed:** Check logs for `[hicortex] WARNING`. Add `llmBaseUrl` to plugin config or set `HICORTEX_LLM_BASE_URL` env var.
|
|
114
150
|
|
|
115
|
-
**No lessons generated:** Reflection requires an LLM. Check that your
|
|
151
|
+
**No lessons generated:** Reflection requires an LLM. Check that your provider is accessible and has sufficient quota.
|
|
116
152
|
|
|
117
153
|
**First startup slow:** The embedding model (~130MB) downloads on first run. Allow up to 2 minutes.
|
|
154
|
+
|
|
155
|
+
**Server won't start (CC):** Check `~/.hicortex/server.log` for errors. Verify port 8787 is free: `lsof -i :8787`.
|
|
156
|
+
|
|
157
|
+
**Multiple CC sessions:** The HTTP server handles multiple concurrent sessions. Do not use stdio transport — it spawns separate processes per session.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLAUDE.md lesson injection — manages the Hicortex Learnings block.
|
|
3
|
+
*
|
|
4
|
+
* Writes a delimited block into ~/.claude/CLAUDE.md containing:
|
|
5
|
+
* - Agent guidance for proactive tool use
|
|
6
|
+
* - Active lessons from the DB
|
|
7
|
+
*
|
|
8
|
+
* Idempotent: calling twice with the same lessons produces the same file.
|
|
9
|
+
*/
|
|
10
|
+
import type Database from "better-sqlite3";
|
|
11
|
+
/**
|
|
12
|
+
* Inject lessons from the DB into CLAUDE.md.
|
|
13
|
+
* Creates the file if it doesn't exist.
|
|
14
|
+
* Replaces existing block if present, appends if not.
|
|
15
|
+
*/
|
|
16
|
+
export declare function injectLessons(db: Database.Database, options?: {
|
|
17
|
+
claudeMdPath?: string;
|
|
18
|
+
stateDir?: string;
|
|
19
|
+
project?: string;
|
|
20
|
+
}): {
|
|
21
|
+
lessonsCount: number;
|
|
22
|
+
path: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Remove the Hicortex Learnings block from CLAUDE.md.
|
|
26
|
+
* Used by the uninstall command.
|
|
27
|
+
*/
|
|
28
|
+
export declare function removeLessonsBlock(claudeMdPath?: string): boolean;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLAUDE.md lesson injection — manages the Hicortex Learnings block.
|
|
4
|
+
*
|
|
5
|
+
* Writes a delimited block into ~/.claude/CLAUDE.md containing:
|
|
6
|
+
* - Agent guidance for proactive tool use
|
|
7
|
+
* - Active lessons from the DB
|
|
8
|
+
*
|
|
9
|
+
* Idempotent: calling twice with the same lessons produces the same file.
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.injectLessons = injectLessons;
|
|
46
|
+
exports.removeLessonsBlock = removeLessonsBlock;
|
|
47
|
+
const node_fs_1 = require("node:fs");
|
|
48
|
+
const node_path_1 = require("node:path");
|
|
49
|
+
const node_path_2 = require("node:path");
|
|
50
|
+
const node_os_1 = require("node:os");
|
|
51
|
+
const storage = __importStar(require("./storage.js"));
|
|
52
|
+
const license_js_1 = require("./license.js");
|
|
53
|
+
const START_MARKER = "<!-- HICORTEX-LEARNINGS:START -->";
|
|
54
|
+
const END_MARKER = "<!-- HICORTEX-LEARNINGS:END -->";
|
|
55
|
+
const DEFAULT_CLAUDE_MD = (0, node_path_2.join)((0, node_os_1.homedir)(), ".claude", "CLAUDE.md");
|
|
56
|
+
const AGENT_GUIDANCE = `You have access to long-term memory via Hicortex MCP tools. Use \`hicortex_search\` when you need context from past sessions, decisions, or prior work. Use \`hicortex_context\` at session start to recall recent project state. Use \`hicortex_ingest\` to save important decisions or learnings. Sessions are auto-captured nightly.`;
|
|
57
|
+
/**
|
|
58
|
+
* Inject lessons from the DB into CLAUDE.md.
|
|
59
|
+
* Creates the file if it doesn't exist.
|
|
60
|
+
* Replaces existing block if present, appends if not.
|
|
61
|
+
*/
|
|
62
|
+
function injectLessons(db, options = {}) {
|
|
63
|
+
const claudeMdPath = options.claudeMdPath ?? DEFAULT_CLAUDE_MD;
|
|
64
|
+
const stateDir = options.stateDir ?? (0, node_path_2.join)((0, node_os_1.homedir)(), ".hicortex");
|
|
65
|
+
// Determine lesson limit based on license
|
|
66
|
+
const features = (0, license_js_1.getFeatures)(stateDir);
|
|
67
|
+
const maxLessons = features.maxMemories === -1 ? 15 : 7;
|
|
68
|
+
// Load lessons
|
|
69
|
+
const lessons = storage.getLessons(db, 30, options.project);
|
|
70
|
+
const selected = lessons.slice(0, maxLessons);
|
|
71
|
+
// Format lesson lines
|
|
72
|
+
const lessonLines = selected.map((l) => {
|
|
73
|
+
const match = l.content.match(/## Lesson: (.+)/);
|
|
74
|
+
return match ? `- ${match[1]}` : `- ${l.content.slice(0, 200)}`;
|
|
75
|
+
});
|
|
76
|
+
// Build the block
|
|
77
|
+
const blockParts = [START_MARKER, "## Hicortex Learnings", "", AGENT_GUIDANCE];
|
|
78
|
+
if (lessonLines.length > 0) {
|
|
79
|
+
blockParts.push("", "### Active Lessons");
|
|
80
|
+
blockParts.push(...lessonLines);
|
|
81
|
+
}
|
|
82
|
+
blockParts.push(END_MARKER);
|
|
83
|
+
const block = blockParts.join("\n");
|
|
84
|
+
// Read existing file or start empty
|
|
85
|
+
let content = "";
|
|
86
|
+
try {
|
|
87
|
+
content = (0, node_fs_1.readFileSync)(claudeMdPath, "utf-8");
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// File doesn't exist — will create it
|
|
91
|
+
}
|
|
92
|
+
// Replace or append
|
|
93
|
+
const startIdx = content.indexOf(START_MARKER);
|
|
94
|
+
const endIdx = content.indexOf(END_MARKER);
|
|
95
|
+
if (startIdx !== -1 && endIdx !== -1) {
|
|
96
|
+
// Replace existing block
|
|
97
|
+
content =
|
|
98
|
+
content.slice(0, startIdx) +
|
|
99
|
+
block +
|
|
100
|
+
content.slice(endIdx + END_MARKER.length);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// Append with blank line separator
|
|
104
|
+
if (content.length > 0 && !content.endsWith("\n")) {
|
|
105
|
+
content += "\n";
|
|
106
|
+
}
|
|
107
|
+
if (content.length > 0) {
|
|
108
|
+
content += "\n";
|
|
109
|
+
}
|
|
110
|
+
content += block + "\n";
|
|
111
|
+
}
|
|
112
|
+
// Write
|
|
113
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(claudeMdPath), { recursive: true });
|
|
114
|
+
(0, node_fs_1.writeFileSync)(claudeMdPath, content);
|
|
115
|
+
return { lessonsCount: selected.length, path: claudeMdPath };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Remove the Hicortex Learnings block from CLAUDE.md.
|
|
119
|
+
* Used by the uninstall command.
|
|
120
|
+
*/
|
|
121
|
+
function removeLessonsBlock(claudeMdPath = DEFAULT_CLAUDE_MD) {
|
|
122
|
+
let content;
|
|
123
|
+
try {
|
|
124
|
+
content = (0, node_fs_1.readFileSync)(claudeMdPath, "utf-8");
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return false; // File doesn't exist
|
|
128
|
+
}
|
|
129
|
+
const startIdx = content.indexOf(START_MARKER);
|
|
130
|
+
const endIdx = content.indexOf(END_MARKER);
|
|
131
|
+
if (startIdx === -1 || endIdx === -1)
|
|
132
|
+
return false;
|
|
133
|
+
// Remove block and any trailing blank line
|
|
134
|
+
let newContent = content.slice(0, startIdx) +
|
|
135
|
+
content.slice(endIdx + END_MARKER.length);
|
|
136
|
+
// Clean up double blank lines left by removal
|
|
137
|
+
newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
138
|
+
if (newContent.length > 0)
|
|
139
|
+
newContent += "\n";
|
|
140
|
+
(0, node_fs_1.writeFileSync)(claudeMdPath, newContent);
|
|
141
|
+
return true;
|
|
142
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Hicortex CLI — entry point for `npx @gamaze/hicortex <command>`.
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* server Start the MCP HTTP/SSE server (persistent daemon)
|
|
7
|
+
* init Detect existing setup and configure for CC/OC
|
|
8
|
+
* nightly Run distill + consolidate + inject lessons (manual trigger)
|
|
9
|
+
* status Show config, DB stats, adapter status
|
|
10
|
+
* uninstall Clean removal of CC integration
|
|
11
|
+
*/
|
|
12
|
+
export {};
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* Hicortex CLI — entry point for `npx @gamaze/hicortex <command>`.
|
|
5
|
+
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* server Start the MCP HTTP/SSE server (persistent daemon)
|
|
8
|
+
* init Detect existing setup and configure for CC/OC
|
|
9
|
+
* nightly Run distill + consolidate + inject lessons (manual trigger)
|
|
10
|
+
* status Show config, DB stats, adapter status
|
|
11
|
+
* uninstall Clean removal of CC integration
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
const command = process.argv[2];
|
|
15
|
+
switch (command) {
|
|
16
|
+
case "server": {
|
|
17
|
+
const portArg = process.argv.indexOf("--port");
|
|
18
|
+
const port = portArg !== -1 ? parseInt(process.argv[portArg + 1], 10) : undefined;
|
|
19
|
+
const hostArg = process.argv.indexOf("--host");
|
|
20
|
+
const host = hostArg !== -1 ? process.argv[hostArg + 1] : undefined;
|
|
21
|
+
import("./mcp-server.js").then(({ startServer }) => {
|
|
22
|
+
startServer({ port, host }).catch((err) => {
|
|
23
|
+
console.error("[hicortex] Server failed to start:", err);
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
case "init":
|
|
30
|
+
import("./init.js").then(({ runInit }) => {
|
|
31
|
+
runInit().catch((err) => {
|
|
32
|
+
console.error("[hicortex] Init failed:", err);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
break;
|
|
37
|
+
case "nightly": {
|
|
38
|
+
const dryRun = process.argv.includes("--dry-run");
|
|
39
|
+
import("./nightly.js").then(({ runNightly }) => {
|
|
40
|
+
runNightly({ dryRun }).catch((err) => {
|
|
41
|
+
console.error("[hicortex] Nightly pipeline failed:", err);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case "status":
|
|
48
|
+
import("./status.js").then(({ runStatus }) => {
|
|
49
|
+
runStatus().catch((err) => {
|
|
50
|
+
console.error("[hicortex] Status failed:", err);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
break;
|
|
55
|
+
case "uninstall":
|
|
56
|
+
import("./uninstall.js").then(({ runUninstall }) => {
|
|
57
|
+
runUninstall().catch((err) => {
|
|
58
|
+
console.error("[hicortex] Uninstall failed:", err);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
default:
|
|
64
|
+
console.log(`Hicortex — Human-like memory for self-improving AI agents
|
|
65
|
+
|
|
66
|
+
Usage: hicortex <command> [options]
|
|
67
|
+
|
|
68
|
+
Commands:
|
|
69
|
+
server Start the MCP HTTP/SSE server
|
|
70
|
+
init Set up Hicortex for Claude Code
|
|
71
|
+
nightly Run nightly distill + consolidate + inject
|
|
72
|
+
status Show current configuration and stats
|
|
73
|
+
uninstall Remove CC integration (preserves DB)
|
|
74
|
+
|
|
75
|
+
Options:
|
|
76
|
+
server --port <n> Port (default: 8787)
|
|
77
|
+
server --host <h> Host (default: 127.0.0.1)
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
npx @gamaze/hicortex server
|
|
81
|
+
npx @gamaze/hicortex init
|
|
82
|
+
npx @gamaze/hicortex status`);
|
|
83
|
+
process.exit(command ? 1 : 0);
|
|
84
|
+
}
|
package/dist/consolidate.js
CHANGED
|
@@ -49,7 +49,7 @@ const node_os_1 = require("node:os");
|
|
|
49
49
|
const retrieval_js_1 = require("./retrieval.js");
|
|
50
50
|
const storage = __importStar(require("./storage.js"));
|
|
51
51
|
const prompts_js_1 = require("./prompts.js");
|
|
52
|
-
const LAST_CONSOLIDATED_PATH = (0, node_path_1.join)((0, node_os_1.homedir)(), ".
|
|
52
|
+
const LAST_CONSOLIDATED_PATH = (0, node_path_1.join)((0, node_os_1.homedir)(), ".hicortex", "last-consolidated.txt");
|
|
53
53
|
// Default config constants (matching Python config.py)
|
|
54
54
|
const CONSOLIDATE_MAX_LLM_CALLS = 200;
|
|
55
55
|
const CONSOLIDATE_PRUNE_MIN_AGE_DAYS = 90;
|
package/dist/db.d.ts
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
* Ported from hicortex/db.py — same schema for migration compatibility.
|
|
4
4
|
*/
|
|
5
5
|
import Database from "better-sqlite3";
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the database path. Handles migration from legacy OC location.
|
|
8
|
+
*
|
|
9
|
+
* Priority:
|
|
10
|
+
* 1. Explicit override (env var or config)
|
|
11
|
+
* 2. Canonical ~/.hicortex/hicortex.db (if exists)
|
|
12
|
+
* 3. Legacy ~/.openclaw/data/hicortex.db (migrate to canonical, leave symlink)
|
|
13
|
+
* 4. Default: create ~/.hicortex/hicortex.db
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveDbPath(override?: string): string;
|
|
6
16
|
/**
|
|
7
17
|
* Initialize the database: load sqlite-vec, enable WAL, create all tables.
|
|
8
18
|
* Returns the open Database instance (caller manages lifetime).
|
package/dist/db.js
CHANGED
|
@@ -7,11 +7,85 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
7
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
8
|
};
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.resolveDbPath = resolveDbPath;
|
|
10
11
|
exports.initDb = initDb;
|
|
11
12
|
exports.getStats = getStats;
|
|
12
13
|
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
13
14
|
const node_fs_1 = require("node:fs");
|
|
15
|
+
const node_path_1 = require("node:path");
|
|
16
|
+
const node_os_1 = require("node:os");
|
|
14
17
|
const EMBEDDING_DIMENSIONS = 384;
|
|
18
|
+
/** Canonical Hicortex home directory. */
|
|
19
|
+
const HICORTEX_HOME = (0, node_path_1.join)((0, node_os_1.homedir)(), ".hicortex");
|
|
20
|
+
/** Legacy OC plugin DB path (pre-v0.3 installations). */
|
|
21
|
+
const LEGACY_OC_DB = (0, node_path_1.join)((0, node_os_1.homedir)(), ".openclaw", "data", "hicortex.db");
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the database path. Handles migration from legacy OC location.
|
|
24
|
+
*
|
|
25
|
+
* Priority:
|
|
26
|
+
* 1. Explicit override (env var or config)
|
|
27
|
+
* 2. Canonical ~/.hicortex/hicortex.db (if exists)
|
|
28
|
+
* 3. Legacy ~/.openclaw/data/hicortex.db (migrate to canonical, leave symlink)
|
|
29
|
+
* 4. Default: create ~/.hicortex/hicortex.db
|
|
30
|
+
*/
|
|
31
|
+
function resolveDbPath(override) {
|
|
32
|
+
// 1. Explicit override
|
|
33
|
+
if (override)
|
|
34
|
+
return override;
|
|
35
|
+
const envOverride = process.env.HICORTEX_DB_PATH;
|
|
36
|
+
if (envOverride)
|
|
37
|
+
return envOverride;
|
|
38
|
+
const canonicalPath = (0, node_path_1.join)(HICORTEX_HOME, "hicortex.db");
|
|
39
|
+
// 2. Canonical path exists — use it
|
|
40
|
+
if ((0, node_fs_1.existsSync)(canonicalPath)) {
|
|
41
|
+
if ((0, node_fs_1.existsSync)(LEGACY_OC_DB) && !isSymlink(LEGACY_OC_DB)) {
|
|
42
|
+
console.warn(`[hicortex] WARNING: DB exists at both ${canonicalPath} and ${LEGACY_OC_DB}. ` +
|
|
43
|
+
`Using canonical path. Remove the legacy file if it is stale.`);
|
|
44
|
+
}
|
|
45
|
+
return canonicalPath;
|
|
46
|
+
}
|
|
47
|
+
// 3. Legacy OC path exists — migrate
|
|
48
|
+
if ((0, node_fs_1.existsSync)(LEGACY_OC_DB)) {
|
|
49
|
+
return migrateDb(LEGACY_OC_DB, canonicalPath);
|
|
50
|
+
}
|
|
51
|
+
// 4. Fresh install — ensure directory exists
|
|
52
|
+
(0, node_fs_1.mkdirSync)(HICORTEX_HOME, { recursive: true });
|
|
53
|
+
return canonicalPath;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Migrate DB from legacy path to canonical ~/.hicortex/.
|
|
57
|
+
* Moves the main DB file plus WAL/SHM if present.
|
|
58
|
+
* Leaves a symlink at the old path for backward compatibility.
|
|
59
|
+
*/
|
|
60
|
+
function migrateDb(legacyPath, canonicalPath) {
|
|
61
|
+
(0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(canonicalPath), { recursive: true });
|
|
62
|
+
// Move main DB file
|
|
63
|
+
(0, node_fs_1.renameSync)(legacyPath, canonicalPath);
|
|
64
|
+
// Move WAL and SHM files if present
|
|
65
|
+
for (const suffix of ["-wal", "-shm"]) {
|
|
66
|
+
const legacySuffix = legacyPath + suffix;
|
|
67
|
+
if ((0, node_fs_1.existsSync)(legacySuffix)) {
|
|
68
|
+
(0, node_fs_1.renameSync)(legacySuffix, canonicalPath + suffix);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Leave symlink at old path for backward compat
|
|
72
|
+
try {
|
|
73
|
+
(0, node_fs_1.symlinkSync)(canonicalPath, legacyPath);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Non-fatal — symlink may fail on some filesystems
|
|
77
|
+
}
|
|
78
|
+
console.log(`[hicortex] Migrated database to ${canonicalPath}`);
|
|
79
|
+
return canonicalPath;
|
|
80
|
+
}
|
|
81
|
+
function isSymlink(path) {
|
|
82
|
+
try {
|
|
83
|
+
return (0, node_fs_1.lstatSync)(path).isSymbolicLink();
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
15
89
|
const SCHEMA = `
|
|
16
90
|
CREATE TABLE IF NOT EXISTS memories (
|
|
17
91
|
id TEXT PRIMARY KEY,
|
package/dist/index.js
CHANGED
|
@@ -41,11 +41,10 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
41
41
|
})();
|
|
42
42
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
43
|
const node_path_1 = require("node:path");
|
|
44
|
-
const node_fs_1 = require("node:fs");
|
|
45
44
|
const db_js_1 = require("./db.js");
|
|
46
45
|
const license_js_1 = require("./license.js");
|
|
47
46
|
const llm_js_1 = require("./llm.js");
|
|
48
|
-
const
|
|
47
|
+
const node_fs_1 = require("node:fs");
|
|
49
48
|
const node_os_1 = require("node:os");
|
|
50
49
|
const embedder_js_1 = require("./embedder.js");
|
|
51
50
|
const storage = __importStar(require("./storage.js"));
|
|
@@ -78,11 +77,8 @@ exports.default = {
|
|
|
78
77
|
const log = ctx.logger
|
|
79
78
|
? (msg) => ctx.logger.info(msg)
|
|
80
79
|
: console.log;
|
|
81
|
-
//
|
|
82
|
-
const
|
|
83
|
-
(0, node_fs_1.mkdirSync)(dataDir, { recursive: true });
|
|
84
|
-
// Initialize database
|
|
85
|
-
const dbPath = config.dbPath ?? (0, node_path_1.join)(dataDir, "hicortex.db");
|
|
80
|
+
// Resolve database path (handles migration from legacy OC location)
|
|
81
|
+
const dbPath = (0, db_js_1.resolveDbPath)(config.dbPath);
|
|
86
82
|
log(`[hicortex] Initializing database at ${dbPath}`);
|
|
87
83
|
db = (0, db_js_1.initDb)(dbPath);
|
|
88
84
|
// Auto-configure LLM: resolve → test → persist
|
|
@@ -213,7 +209,7 @@ exports.default = {
|
|
|
213
209
|
const { readFileSync: readFs } = await import("node:fs");
|
|
214
210
|
const { join: joinPath } = await import("node:path");
|
|
215
211
|
const { homedir: homeDir } = await import("node:os");
|
|
216
|
-
const lastPath = joinPath(homeDir(), ".
|
|
212
|
+
const lastPath = joinPath(homeDir(), ".hicortex", "last-consolidated.txt");
|
|
217
213
|
const lastTs = readFs(lastPath, "utf-8").trim();
|
|
218
214
|
const lastDate = new Date(lastTs);
|
|
219
215
|
const hoursSince = (Date.now() - lastDate.getTime()) / (1000 * 60 * 60);
|
|
@@ -422,7 +418,7 @@ async function autoConfigureLlm(pluginConfig, log) {
|
|
|
422
418
|
function persistProviderConfig(llmConfig, log) {
|
|
423
419
|
try {
|
|
424
420
|
const configPath = (0, node_path_1.join)((0, node_os_1.homedir)(), ".openclaw", "openclaw.json");
|
|
425
|
-
const raw = (0,
|
|
421
|
+
const raw = (0, node_fs_1.readFileSync)(configPath, "utf-8");
|
|
426
422
|
const config = JSON.parse(raw);
|
|
427
423
|
// Check if baseUrl already stored for this provider
|
|
428
424
|
const existing = config?.models?.providers?.[llmConfig.provider]?.baseUrl;
|
|
@@ -448,7 +444,7 @@ function persistProviderConfig(llmConfig, log) {
|
|
|
448
444
|
maxTokens: 8192,
|
|
449
445
|
}];
|
|
450
446
|
}
|
|
451
|
-
(0,
|
|
447
|
+
(0, node_fs_1.writeFileSync)(configPath, JSON.stringify(config, null, 2));
|
|
452
448
|
log(`[hicortex] Persisted LLM config: ${llmConfig.provider} → ${llmConfig.baseUrl}`);
|
|
453
449
|
}
|
|
454
450
|
catch {
|
|
@@ -462,14 +458,14 @@ function persistProviderConfig(llmConfig, log) {
|
|
|
462
458
|
function getDaysSinceCapHit(dir) {
|
|
463
459
|
const capFile = (0, node_path_1.join)(dir, "cap-hit.txt");
|
|
464
460
|
try {
|
|
465
|
-
const ts = (0,
|
|
461
|
+
const ts = (0, node_fs_1.readFileSync)(capFile, "utf-8").trim();
|
|
466
462
|
const hitDate = new Date(ts);
|
|
467
463
|
return Math.floor((Date.now() - hitDate.getTime()) / (1000 * 60 * 60 * 24));
|
|
468
464
|
}
|
|
469
465
|
catch {
|
|
470
466
|
// First time hitting cap — record it
|
|
471
467
|
try {
|
|
472
|
-
(0,
|
|
468
|
+
(0, node_fs_1.writeFileSync)(capFile, new Date().toISOString());
|
|
473
469
|
}
|
|
474
470
|
catch { /* non-fatal */ }
|
|
475
471
|
return 0;
|
|
@@ -488,7 +484,7 @@ const HICORTEX_TOOLS = [
|
|
|
488
484
|
function ensureToolsAllowed(log) {
|
|
489
485
|
try {
|
|
490
486
|
const configPath = (0, node_path_1.join)((0, node_os_1.homedir)(), ".openclaw", "openclaw.json");
|
|
491
|
-
const raw = (0,
|
|
487
|
+
const raw = (0, node_fs_1.readFileSync)(configPath, "utf-8");
|
|
492
488
|
const config = JSON.parse(raw);
|
|
493
489
|
if (!config.tools)
|
|
494
490
|
config.tools = {};
|
|
@@ -498,7 +494,7 @@ function ensureToolsAllowed(log) {
|
|
|
498
494
|
if (missing.length === 0)
|
|
499
495
|
return;
|
|
500
496
|
config.tools.allow.push(...missing);
|
|
501
|
-
(0,
|
|
497
|
+
(0, node_fs_1.writeFileSync)(configPath, JSON.stringify(config, null, 2));
|
|
502
498
|
log(`[hicortex] Added tools to allow list: ${missing.join(", ")}`);
|
|
503
499
|
}
|
|
504
500
|
catch {
|
package/dist/init.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hicortex init — detect existing setup and configure for CC.
|
|
3
|
+
*
|
|
4
|
+
* Detection:
|
|
5
|
+
* 1. Local HC server running (localhost:8787)
|
|
6
|
+
* 2. Remote HC server (HICORTEX_SERVER_URL or bedrock:8787)
|
|
7
|
+
* 3. OC plugin installed (~/.openclaw/openclaw.json)
|
|
8
|
+
* 4. CC MCP already registered (~/.claude/settings.json)
|
|
9
|
+
* 5. Existing DB (~/.hicortex/ or ~/.openclaw/data/)
|
|
10
|
+
*
|
|
11
|
+
* Actions:
|
|
12
|
+
* - Install persistent daemon (launchd/systemd)
|
|
13
|
+
* - Register MCP server in CC settings
|
|
14
|
+
* - Inject CLAUDE.md learnings block
|
|
15
|
+
* - Install CC custom commands (/learn, /hicortex-activate)
|
|
16
|
+
*/
|
|
17
|
+
export declare function runInit(): Promise<void>;
|