apsolut-cortex 0.2.0 → 0.2.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/cli.js +121 -19
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
4
|
import {
|
|
5
|
-
existsSync as
|
|
6
|
-
mkdirSync as
|
|
5
|
+
existsSync as existsSync3,
|
|
6
|
+
mkdirSync as mkdirSync3,
|
|
7
7
|
readFileSync as readFileSync2,
|
|
8
8
|
writeFileSync as writeFileSync2
|
|
9
9
|
} from "fs";
|
|
@@ -12,21 +12,124 @@ import { homedir as homedir2 } from "os";
|
|
|
12
12
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
13
13
|
|
|
14
14
|
// src/registry.ts
|
|
15
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
15
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync, writeFileSync } from "fs";
|
|
16
16
|
import { dirname } from "path";
|
|
17
17
|
|
|
18
18
|
// src/db.ts
|
|
19
19
|
import Database from "better-sqlite3";
|
|
20
|
+
import { existsSync, mkdirSync } from "fs";
|
|
20
21
|
import { homedir } from "os";
|
|
21
22
|
import { join } from "path";
|
|
22
23
|
var CORTEX_DIR = join(homedir(), ".apsolut");
|
|
23
24
|
var DB_PATH = join(CORTEX_DIR, "memory.db");
|
|
24
25
|
var REGISTRY_PATH = join(CORTEX_DIR, "registry.json");
|
|
25
26
|
var MODELS_DIR = join(CORTEX_DIR, "models");
|
|
27
|
+
var _db = null;
|
|
28
|
+
function getDb() {
|
|
29
|
+
if (_db)
|
|
30
|
+
return _db;
|
|
31
|
+
if (!existsSync(CORTEX_DIR))
|
|
32
|
+
mkdirSync(CORTEX_DIR, { recursive: true });
|
|
33
|
+
if (!existsSync(MODELS_DIR))
|
|
34
|
+
mkdirSync(MODELS_DIR, { recursive: true });
|
|
35
|
+
_db = new Database(DB_PATH);
|
|
36
|
+
_db.pragma("journal_mode = WAL");
|
|
37
|
+
_db.pragma("synchronous = NORMAL");
|
|
38
|
+
_db.pragma("foreign_keys = ON");
|
|
39
|
+
_db.pragma("cache_size = -32000");
|
|
40
|
+
_db.exec(`
|
|
41
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
42
|
+
id TEXT PRIMARY KEY,
|
|
43
|
+
name TEXT NOT NULL,
|
|
44
|
+
path TEXT,
|
|
45
|
+
created_at INTEGER NOT NULL,
|
|
46
|
+
last_session INTEGER
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
50
|
+
id TEXT PRIMARY KEY,
|
|
51
|
+
project_id TEXT NOT NULL REFERENCES projects(id),
|
|
52
|
+
started_at INTEGER NOT NULL,
|
|
53
|
+
ended_at INTEGER,
|
|
54
|
+
summary TEXT,
|
|
55
|
+
memories_injected INTEGER NOT NULL DEFAULT 0,
|
|
56
|
+
memories_stored INTEGER NOT NULL DEFAULT 0,
|
|
57
|
+
tool_failures INTEGER NOT NULL DEFAULT 0
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_project
|
|
61
|
+
ON sessions(project_id, started_at DESC);
|
|
62
|
+
|
|
63
|
+
CREATE TABLE IF NOT EXISTS observations (
|
|
64
|
+
id TEXT PRIMARY KEY,
|
|
65
|
+
session_id TEXT NOT NULL REFERENCES sessions(id),
|
|
66
|
+
project_id TEXT NOT NULL,
|
|
67
|
+
tool_name TEXT,
|
|
68
|
+
content TEXT NOT NULL,
|
|
69
|
+
category TEXT,
|
|
70
|
+
created_at INTEGER NOT NULL,
|
|
71
|
+
promoted INTEGER NOT NULL DEFAULT 0
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
CREATE INDEX IF NOT EXISTS idx_obs_session ON observations(session_id);
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_obs_project ON observations(project_id, created_at DESC);
|
|
76
|
+
|
|
77
|
+
CREATE TABLE IF NOT EXISTS memories (
|
|
78
|
+
id TEXT PRIMARY KEY,
|
|
79
|
+
project_id TEXT NOT NULL,
|
|
80
|
+
tier TEXT NOT NULL DEFAULT 'semantic',
|
|
81
|
+
category TEXT NOT NULL DEFAULT 'insight',
|
|
82
|
+
trust TEXT NOT NULL DEFAULT 'observed',
|
|
83
|
+
content TEXT NOT NULL,
|
|
84
|
+
context TEXT,
|
|
85
|
+
source TEXT NOT NULL DEFAULT 'manual',
|
|
86
|
+
embedding BLOB,
|
|
87
|
+
weight REAL NOT NULL DEFAULT 1.0,
|
|
88
|
+
used_count INTEGER NOT NULL DEFAULT 0,
|
|
89
|
+
last_used INTEGER,
|
|
90
|
+
created_at INTEGER NOT NULL,
|
|
91
|
+
session_id TEXT REFERENCES sessions(id),
|
|
92
|
+
flagged INTEGER NOT NULL DEFAULT 0,
|
|
93
|
+
flag_reason TEXT
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
CREATE INDEX IF NOT EXISTS idx_mem_project ON memories(project_id);
|
|
97
|
+
CREATE INDEX IF NOT EXISTS idx_mem_weight ON memories(project_id, weight DESC);
|
|
98
|
+
CREATE INDEX IF NOT EXISTS idx_mem_tier ON memories(project_id, tier);
|
|
99
|
+
CREATE INDEX IF NOT EXISTS idx_mem_trust ON memories(project_id, trust);
|
|
100
|
+
CREATE INDEX IF NOT EXISTS idx_mem_flagged ON memories(project_id, flagged)
|
|
101
|
+
WHERE flagged = 1;
|
|
102
|
+
|
|
103
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS memories_fts USING fts5(
|
|
104
|
+
content, context,
|
|
105
|
+
content='memories',
|
|
106
|
+
content_rowid='rowid',
|
|
107
|
+
tokenize='porter ascii'
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
CREATE TRIGGER IF NOT EXISTS memories_ai AFTER INSERT ON memories BEGIN
|
|
111
|
+
INSERT INTO memories_fts(rowid, content, context)
|
|
112
|
+
VALUES (new.rowid, new.content, COALESCE(new.context, ''));
|
|
113
|
+
END;
|
|
114
|
+
|
|
115
|
+
CREATE TRIGGER IF NOT EXISTS memories_au AFTER UPDATE ON memories BEGIN
|
|
116
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, context)
|
|
117
|
+
VALUES ('delete', old.rowid, old.content, COALESCE(old.context, ''));
|
|
118
|
+
INSERT INTO memories_fts(rowid, content, context)
|
|
119
|
+
VALUES (new.rowid, new.content, COALESCE(new.context, ''));
|
|
120
|
+
END;
|
|
121
|
+
|
|
122
|
+
CREATE TRIGGER IF NOT EXISTS memories_ad AFTER DELETE ON memories BEGIN
|
|
123
|
+
INSERT INTO memories_fts(memories_fts, rowid, content, context)
|
|
124
|
+
VALUES ('delete', old.rowid, old.content, COALESCE(old.context, ''));
|
|
125
|
+
END;
|
|
126
|
+
`);
|
|
127
|
+
return _db;
|
|
128
|
+
}
|
|
26
129
|
|
|
27
130
|
// src/registry.ts
|
|
28
131
|
function readRegistry() {
|
|
29
|
-
if (!
|
|
132
|
+
if (!existsSync2(REGISTRY_PATH))
|
|
30
133
|
return { projects: {} };
|
|
31
134
|
try {
|
|
32
135
|
return JSON.parse(readFileSync(REGISTRY_PATH, "utf-8"));
|
|
@@ -36,8 +139,8 @@ function readRegistry() {
|
|
|
36
139
|
}
|
|
37
140
|
function writeRegistry(reg) {
|
|
38
141
|
const dir = dirname(REGISTRY_PATH);
|
|
39
|
-
if (!
|
|
40
|
-
|
|
142
|
+
if (!existsSync2(dir))
|
|
143
|
+
mkdirSync2(dir, { recursive: true });
|
|
41
144
|
writeFileSync(REGISTRY_PATH, JSON.stringify(reg, null, 2));
|
|
42
145
|
}
|
|
43
146
|
function registerProject(id, name, path) {
|
|
@@ -95,7 +198,7 @@ Models: ~/.apsolut/models/
|
|
|
95
198
|
}
|
|
96
199
|
async function runHook(name) {
|
|
97
200
|
const hookPath = IS_DIST ? join2(__dirname2, "hooks", `${name}.js`) : join2(__dirname2, "hooks", `${name}.ts`);
|
|
98
|
-
if (!
|
|
201
|
+
if (!existsSync3(hookPath)) {
|
|
99
202
|
process.stderr.write(`[apsolut-cortex] hook not found: ${hookPath}
|
|
100
203
|
`);
|
|
101
204
|
process.exit(0);
|
|
@@ -106,12 +209,12 @@ async function init() {
|
|
|
106
209
|
console.log(`
|
|
107
210
|
apsolut-cortex init
|
|
108
211
|
`);
|
|
109
|
-
if (!
|
|
110
|
-
|
|
212
|
+
if (!existsSync3(PROJECT_APSOLUT)) {
|
|
213
|
+
mkdirSync3(PROJECT_APSOLUT, { recursive: true });
|
|
111
214
|
}
|
|
112
215
|
let projectId;
|
|
113
216
|
let projectName;
|
|
114
|
-
if (
|
|
217
|
+
if (existsSync3(PROJECT_CONFIG)) {
|
|
115
218
|
const existing = JSON.parse(readFileSync2(PROJECT_CONFIG, "utf-8"));
|
|
116
219
|
projectId = existing.id;
|
|
117
220
|
projectName = existing.name;
|
|
@@ -134,7 +237,7 @@ apsolut-cortex init
|
|
|
134
237
|
const mcpCommand = IS_DIST ? "node" : "bun";
|
|
135
238
|
const mcpArgs = [mcpServerPath];
|
|
136
239
|
let mcp = {};
|
|
137
|
-
if (
|
|
240
|
+
if (existsSync3(MCP_JSON)) {
|
|
138
241
|
try {
|
|
139
242
|
mcp = JSON.parse(readFileSync2(MCP_JSON, "utf-8"));
|
|
140
243
|
} catch {}
|
|
@@ -157,9 +260,9 @@ apsolut-cortex init
|
|
|
157
260
|
};
|
|
158
261
|
let settings = {};
|
|
159
262
|
const settingsDir = dirname2(CLAUDE_SETTINGS);
|
|
160
|
-
if (!
|
|
161
|
-
|
|
162
|
-
if (
|
|
263
|
+
if (!existsSync3(settingsDir))
|
|
264
|
+
mkdirSync3(settingsDir, { recursive: true });
|
|
265
|
+
if (existsSync3(CLAUDE_SETTINGS)) {
|
|
163
266
|
try {
|
|
164
267
|
settings = JSON.parse(readFileSync2(CLAUDE_SETTINGS, "utf-8"));
|
|
165
268
|
} catch {}
|
|
@@ -178,7 +281,7 @@ apsolut-cortex init
|
|
|
178
281
|
writeFileSync2(CLAUDE_SETTINGS, JSON.stringify(settings, null, 2));
|
|
179
282
|
console.log(added > 0 ? `✓ Registered ${added} hooks in ~/.claude/settings.json` : `✓ Hooks already registered`);
|
|
180
283
|
const gitignore = join2(PROJECT_ROOT, ".gitignore");
|
|
181
|
-
if (
|
|
284
|
+
if (existsSync3(gitignore)) {
|
|
182
285
|
const content = readFileSync2(gitignore, "utf-8");
|
|
183
286
|
if (!content.includes(".apsolut/")) {
|
|
184
287
|
writeFileSync2(gitignore, content + `
|
|
@@ -216,8 +319,7 @@ apsolut-cortex init
|
|
|
216
319
|
console.log(BANNER);
|
|
217
320
|
}
|
|
218
321
|
async function status() {
|
|
219
|
-
|
|
220
|
-
if (!existsSync2(PROJECT_CONFIG)) {
|
|
322
|
+
if (!existsSync3(PROJECT_CONFIG)) {
|
|
221
323
|
console.log("No project found. Run: apsolut-cortex init");
|
|
222
324
|
process.exit(1);
|
|
223
325
|
}
|
|
@@ -252,7 +354,7 @@ DB: ~/.apsolut/memory.db
|
|
|
252
354
|
`);
|
|
253
355
|
}
|
|
254
356
|
function uninstall() {
|
|
255
|
-
if (
|
|
357
|
+
if (existsSync3(MCP_JSON)) {
|
|
256
358
|
try {
|
|
257
359
|
const mcp = JSON.parse(readFileSync2(MCP_JSON, "utf-8"));
|
|
258
360
|
if (mcp.mcpServers?.["apsolut-cortex"]) {
|
|
@@ -262,7 +364,7 @@ function uninstall() {
|
|
|
262
364
|
}
|
|
263
365
|
} catch {}
|
|
264
366
|
}
|
|
265
|
-
if (
|
|
367
|
+
if (existsSync3(CLAUDE_SETTINGS)) {
|
|
266
368
|
try {
|
|
267
369
|
const settings = JSON.parse(readFileSync2(CLAUDE_SETTINGS, "utf-8"));
|
|
268
370
|
const hooks = settings.hooks;
|