@askexenow/exe-os 0.8.82 → 0.8.85
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/bin/backfill-conversations.js +746 -595
- package/dist/bin/backfill-responses.js +745 -594
- package/dist/bin/backfill-vectors.js +312 -226
- package/dist/bin/cleanup-stale-review-tasks.js +97 -2
- package/dist/bin/cli.js +14360 -12525
- package/dist/bin/exe-agent.js +97 -88
- package/dist/bin/exe-assign.js +1003 -854
- package/dist/bin/exe-boot.js +1260 -323
- package/dist/bin/exe-call.js +10 -0
- package/dist/bin/exe-cloud.js +32 -9
- package/dist/bin/exe-dispatch.js +212 -36
- package/dist/bin/exe-doctor.js +403 -6
- package/dist/bin/exe-export-behaviors.js +175 -72
- package/dist/bin/exe-forget.js +97 -2
- package/dist/bin/exe-gateway.js +553 -174
- package/dist/bin/exe-healthcheck.js +1 -0
- package/dist/bin/exe-heartbeat.js +100 -5
- package/dist/bin/exe-kill.js +175 -72
- package/dist/bin/exe-launch-agent.js +189 -76
- package/dist/bin/exe-link.js +902 -80
- package/dist/bin/exe-new-employee.js +41 -11
- package/dist/bin/exe-pending-messages.js +96 -2
- package/dist/bin/exe-pending-notifications.js +97 -2
- package/dist/bin/exe-pending-reviews.js +98 -3
- package/dist/bin/exe-rename.js +577 -33
- package/dist/bin/exe-review.js +231 -73
- package/dist/bin/exe-search.js +989 -226
- package/dist/bin/exe-session-cleanup.js +4806 -1665
- package/dist/bin/exe-settings.js +20 -5
- package/dist/bin/exe-status.js +97 -2
- package/dist/bin/exe-team.js +97 -2
- package/dist/bin/git-sweep.js +901 -209
- package/dist/bin/graph-backfill.js +175 -72
- package/dist/bin/graph-export.js +175 -72
- package/dist/bin/install.js +38 -7
- package/dist/bin/list-providers.js +1 -0
- package/dist/bin/scan-tasks.js +906 -213
- package/dist/bin/setup.js +870 -271
- package/dist/bin/shard-migrate.js +175 -72
- package/dist/bin/update.js +4 -3
- package/dist/bin/wiki-sync.js +175 -72
- package/dist/gateway/index.js +550 -168
- package/dist/hooks/bug-report-worker.js +210 -25
- package/dist/hooks/commit-complete.js +899 -207
- package/dist/hooks/error-recall.js +988 -226
- package/dist/hooks/ingest-worker.js +1639 -1195
- package/dist/hooks/ingest.js +3 -0
- package/dist/hooks/instructions-loaded.js +707 -97
- package/dist/hooks/notification.js +699 -89
- package/dist/hooks/post-compact.js +714 -104
- package/dist/hooks/pre-compact.js +899 -207
- package/dist/hooks/pre-tool-use.js +742 -123
- package/dist/hooks/prompt-ingest-worker.js +245 -104
- package/dist/hooks/prompt-submit.js +995 -233
- package/dist/hooks/response-ingest-worker.js +245 -104
- package/dist/hooks/session-end.js +3941 -400
- package/dist/hooks/session-start.js +1001 -226
- package/dist/hooks/stop.js +725 -115
- package/dist/hooks/subagent-stop.js +714 -104
- package/dist/hooks/summary-worker.js +1970 -1336
- package/dist/index.js +1653 -1055
- package/dist/lib/cloud-sync.js +907 -86
- package/dist/lib/consolidation.js +2 -1
- package/dist/lib/database.js +642 -87
- package/dist/lib/db-daemon-client.js +503 -0
- package/dist/lib/device-registry.js +547 -7
- package/dist/lib/embedder.js +14 -28
- package/dist/lib/employee-templates.js +84 -74
- package/dist/lib/employees.js +9 -0
- package/dist/lib/exe-daemon-client.js +16 -29
- package/dist/lib/exe-daemon.js +1957 -924
- package/dist/lib/hybrid-search.js +988 -226
- package/dist/lib/identity.js +87 -67
- package/dist/lib/keychain.js +9 -1
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +8 -1
- package/dist/lib/reminders.js +91 -74
- package/dist/lib/schedules.js +96 -2
- package/dist/lib/skill-learning.js +103 -85
- package/dist/lib/store.js +234 -73
- package/dist/lib/tasks.js +113 -24
- package/dist/lib/tmux-routing.js +122 -33
- package/dist/lib/token-spend.js +273 -0
- package/dist/lib/ws-client.js +11 -0
- package/dist/mcp/server.js +10874 -5546
- package/dist/mcp/tools/complete-reminder.js +94 -77
- package/dist/mcp/tools/create-reminder.js +94 -77
- package/dist/mcp/tools/create-task.js +810 -27
- package/dist/mcp/tools/deactivate-behavior.js +95 -77
- package/dist/mcp/tools/list-reminders.js +94 -77
- package/dist/mcp/tools/list-tasks.js +31 -1
- package/dist/mcp/tools/send-message.js +8 -1
- package/dist/mcp/tools/update-task.js +39 -10
- package/dist/runtime/index.js +913 -221
- package/dist/tui/App.js +1000 -298
- package/package.json +6 -1
- package/src/commands/exe/build-adv.md +2 -2
|
@@ -211,15 +211,22 @@ function getClient() {
|
|
|
211
211
|
if (!_resilientClient) {
|
|
212
212
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
213
213
|
}
|
|
214
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
215
|
+
return _resilientClient;
|
|
216
|
+
}
|
|
217
|
+
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
218
|
+
return _daemonClient;
|
|
219
|
+
}
|
|
214
220
|
return _resilientClient;
|
|
215
221
|
}
|
|
216
|
-
var _resilientClient;
|
|
222
|
+
var _resilientClient, _daemonClient;
|
|
217
223
|
var init_database = __esm({
|
|
218
224
|
"src/lib/database.ts"() {
|
|
219
225
|
"use strict";
|
|
220
226
|
init_db_retry();
|
|
221
227
|
init_employees();
|
|
222
228
|
_resilientClient = null;
|
|
229
|
+
_daemonClient = null;
|
|
223
230
|
}
|
|
224
231
|
});
|
|
225
232
|
|
|
@@ -1084,19 +1091,41 @@ async function registerMcpServer(packageRoot, homeDir = os4.homedir()) {
|
|
|
1084
1091
|
args: [path8.join(packageRoot, "dist", "mcp", "server.js")],
|
|
1085
1092
|
env: {}
|
|
1086
1093
|
};
|
|
1087
|
-
const
|
|
1088
|
-
const
|
|
1089
|
-
const
|
|
1090
|
-
|
|
1094
|
+
const currentMem = claudeJson.mcpServers[MCP_LEGACY_KEY];
|
|
1095
|
+
const currentOs = claudeJson.mcpServers[MCP_PRIMARY_KEY];
|
|
1096
|
+
const memMatches = currentMem && JSON.stringify(currentMem) === JSON.stringify(newEntry);
|
|
1097
|
+
const osMatches = currentOs && JSON.stringify(currentOs) === JSON.stringify(newEntry);
|
|
1098
|
+
if (memMatches && osMatches) {
|
|
1099
|
+
await cleanSettingsJsonMcp(path8.join(homeDir, ".claude", "settings.json"));
|
|
1091
1100
|
return false;
|
|
1092
1101
|
}
|
|
1102
|
+
claudeJson.mcpServers[MCP_LEGACY_KEY] = newEntry;
|
|
1093
1103
|
claudeJson.mcpServers[MCP_PRIMARY_KEY] = newEntry;
|
|
1094
|
-
if (legacy) {
|
|
1095
|
-
delete claudeJson.mcpServers[MCP_LEGACY_KEY];
|
|
1096
|
-
}
|
|
1097
1104
|
await writeFile3(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + "\n");
|
|
1105
|
+
await cleanSettingsJsonMcp(path8.join(homeDir, ".claude", "settings.json"));
|
|
1098
1106
|
return true;
|
|
1099
1107
|
}
|
|
1108
|
+
async function cleanSettingsJsonMcp(settingsPath) {
|
|
1109
|
+
if (!existsSync8(settingsPath)) return;
|
|
1110
|
+
try {
|
|
1111
|
+
const settings = JSON.parse(await readFile3(settingsPath, "utf-8"));
|
|
1112
|
+
const servers = settings.mcpServers;
|
|
1113
|
+
if (!servers) return;
|
|
1114
|
+
let changed = false;
|
|
1115
|
+
if (servers[MCP_PRIMARY_KEY]) {
|
|
1116
|
+
delete servers[MCP_PRIMARY_KEY];
|
|
1117
|
+
changed = true;
|
|
1118
|
+
}
|
|
1119
|
+
if (servers[MCP_LEGACY_KEY]) {
|
|
1120
|
+
delete servers[MCP_LEGACY_KEY];
|
|
1121
|
+
changed = true;
|
|
1122
|
+
}
|
|
1123
|
+
if (changed) {
|
|
1124
|
+
await writeFile3(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1125
|
+
}
|
|
1126
|
+
} catch {
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1100
1129
|
async function mergeHooks(packageRoot, homeDir = os4.homedir()) {
|
|
1101
1130
|
const settingsPath = path8.join(homeDir, ".claude", "settings.json");
|
|
1102
1131
|
let settings = {};
|
|
@@ -2065,6 +2094,7 @@ import { realpathSync } from "fs";
|
|
|
2065
2094
|
import { fileURLToPath } from "url";
|
|
2066
2095
|
function isMainModule(importMetaUrl) {
|
|
2067
2096
|
if (process.argv[1] == null) return false;
|
|
2097
|
+
if (process.argv[1].includes("mcp/server")) return false;
|
|
2068
2098
|
try {
|
|
2069
2099
|
const scriptPath = realpathSync(process.argv[1]);
|
|
2070
2100
|
const modulePath = realpathSync(fileURLToPath(importMetaUrl));
|
|
@@ -2105,8 +2135,8 @@ MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
|
2105
2135
|
-----END PUBLIC KEY-----`;
|
|
2106
2136
|
var LICENSE_JWT_ALG = "ES256";
|
|
2107
2137
|
var PLAN_LIMITS = {
|
|
2108
|
-
free: { devices: 1, employees: 1, memories:
|
|
2109
|
-
pro: { devices:
|
|
2138
|
+
free: { devices: 1, employees: 1, memories: 5e3 },
|
|
2139
|
+
pro: { devices: 3, employees: 5, memories: 1e5 },
|
|
2110
2140
|
team: { devices: 10, employees: 20, memories: 1e6 },
|
|
2111
2141
|
agency: { devices: 50, employees: 100, memories: 1e7 },
|
|
2112
2142
|
enterprise: { devices: -1, employees: -1, memories: -1 }
|
|
@@ -2118,7 +2148,7 @@ var FREE_LICENSE = {
|
|
|
2118
2148
|
expiresAt: null,
|
|
2119
2149
|
deviceLimit: 1,
|
|
2120
2150
|
employeeLimit: 1,
|
|
2121
|
-
memoryLimit:
|
|
2151
|
+
memoryLimit: 5e3
|
|
2122
2152
|
};
|
|
2123
2153
|
function loadDeviceId() {
|
|
2124
2154
|
const deviceJsonPath = path4.join(EXE_AI_DIR, "device.json");
|
|
@@ -304,6 +304,12 @@ function getClient() {
|
|
|
304
304
|
if (!_resilientClient) {
|
|
305
305
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
306
306
|
}
|
|
307
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
308
|
+
return _resilientClient;
|
|
309
|
+
}
|
|
310
|
+
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
311
|
+
return _daemonClient;
|
|
312
|
+
}
|
|
307
313
|
return _resilientClient;
|
|
308
314
|
}
|
|
309
315
|
function getRawClient() {
|
|
@@ -792,6 +798,12 @@ async function ensureSchema() {
|
|
|
792
798
|
} catch {
|
|
793
799
|
}
|
|
794
800
|
}
|
|
801
|
+
try {
|
|
802
|
+
await client.execute(
|
|
803
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
804
|
+
);
|
|
805
|
+
} catch {
|
|
806
|
+
}
|
|
795
807
|
await client.executeMultiple(`
|
|
796
808
|
CREATE TABLE IF NOT EXISTS entities (
|
|
797
809
|
id TEXT PRIMARY KEY,
|
|
@@ -844,7 +856,30 @@ async function ensureSchema() {
|
|
|
844
856
|
entity_id TEXT NOT NULL,
|
|
845
857
|
PRIMARY KEY (hyperedge_id, entity_id)
|
|
846
858
|
);
|
|
859
|
+
|
|
860
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
|
|
861
|
+
name,
|
|
862
|
+
content=entities,
|
|
863
|
+
content_rowid=rowid
|
|
864
|
+
);
|
|
865
|
+
|
|
866
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
|
|
867
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
868
|
+
END;
|
|
869
|
+
|
|
870
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
|
|
871
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
872
|
+
END;
|
|
873
|
+
|
|
874
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
|
|
875
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
876
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
877
|
+
END;
|
|
847
878
|
`);
|
|
879
|
+
try {
|
|
880
|
+
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
881
|
+
} catch {
|
|
882
|
+
}
|
|
848
883
|
await client.executeMultiple(`
|
|
849
884
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
850
885
|
alias TEXT NOT NULL PRIMARY KEY,
|
|
@@ -1025,6 +1060,33 @@ async function ensureSchema() {
|
|
|
1025
1060
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
1026
1061
|
ON conversations(channel_id);
|
|
1027
1062
|
`);
|
|
1063
|
+
await client.executeMultiple(`
|
|
1064
|
+
CREATE TABLE IF NOT EXISTS session_agent_map (
|
|
1065
|
+
session_uuid TEXT PRIMARY KEY,
|
|
1066
|
+
agent_id TEXT NOT NULL,
|
|
1067
|
+
session_name TEXT,
|
|
1068
|
+
task_id TEXT,
|
|
1069
|
+
project_name TEXT,
|
|
1070
|
+
started_at TEXT NOT NULL
|
|
1071
|
+
);
|
|
1072
|
+
|
|
1073
|
+
CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
|
|
1074
|
+
ON session_agent_map(agent_id);
|
|
1075
|
+
`);
|
|
1076
|
+
try {
|
|
1077
|
+
const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
|
|
1078
|
+
if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
|
|
1079
|
+
await client.execute({
|
|
1080
|
+
sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
|
|
1081
|
+
SELECT session_id, agent_id, '', MIN(timestamp)
|
|
1082
|
+
FROM memories
|
|
1083
|
+
WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
|
|
1084
|
+
GROUP BY session_id, agent_id`,
|
|
1085
|
+
args: []
|
|
1086
|
+
});
|
|
1087
|
+
}
|
|
1088
|
+
} catch {
|
|
1089
|
+
}
|
|
1028
1090
|
try {
|
|
1029
1091
|
await client.execute({
|
|
1030
1092
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
@@ -1158,8 +1220,30 @@ async function ensureSchema() {
|
|
|
1158
1220
|
});
|
|
1159
1221
|
} catch {
|
|
1160
1222
|
}
|
|
1223
|
+
for (const col of [
|
|
1224
|
+
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
1225
|
+
"ALTER TABLE memories ADD COLUMN outcome TEXT",
|
|
1226
|
+
"ALTER TABLE memories ADD COLUMN domain TEXT",
|
|
1227
|
+
"ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
|
|
1228
|
+
"ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
|
|
1229
|
+
"ALTER TABLE memories ADD COLUMN chain_position TEXT",
|
|
1230
|
+
"ALTER TABLE memories ADD COLUMN review_status TEXT",
|
|
1231
|
+
"ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
|
|
1232
|
+
"ALTER TABLE memories ADD COLUMN file_paths TEXT",
|
|
1233
|
+
"ALTER TABLE memories ADD COLUMN commit_hash TEXT",
|
|
1234
|
+
"ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
|
|
1235
|
+
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
1236
|
+
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
1237
|
+
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
1238
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
1239
|
+
]) {
|
|
1240
|
+
try {
|
|
1241
|
+
await client.execute(col);
|
|
1242
|
+
} catch {
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1161
1245
|
}
|
|
1162
|
-
var _client, _resilientClient, initTurso;
|
|
1246
|
+
var _client, _resilientClient, _daemonClient, initTurso;
|
|
1163
1247
|
var init_database = __esm({
|
|
1164
1248
|
"src/lib/database.ts"() {
|
|
1165
1249
|
"use strict";
|
|
@@ -1167,6 +1251,7 @@ var init_database = __esm({
|
|
|
1167
1251
|
init_employees();
|
|
1168
1252
|
_client = null;
|
|
1169
1253
|
_resilientClient = null;
|
|
1254
|
+
_daemonClient = null;
|
|
1170
1255
|
initTurso = initDatabase;
|
|
1171
1256
|
}
|
|
1172
1257
|
});
|
|
@@ -1778,6 +1863,7 @@ var init_tmux_routing = __esm({
|
|
|
1778
1863
|
});
|
|
1779
1864
|
|
|
1780
1865
|
// src/lib/store.ts
|
|
1866
|
+
import { createHash } from "crypto";
|
|
1781
1867
|
init_database();
|
|
1782
1868
|
|
|
1783
1869
|
// src/lib/keychain.ts
|
|
@@ -1813,12 +1899,20 @@ async function getMasterKey() {
|
|
|
1813
1899
|
}
|
|
1814
1900
|
const keyPath = getKeyPath();
|
|
1815
1901
|
if (!existsSync3(keyPath)) {
|
|
1902
|
+
process.stderr.write(
|
|
1903
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
1904
|
+
`
|
|
1905
|
+
);
|
|
1816
1906
|
return null;
|
|
1817
1907
|
}
|
|
1818
1908
|
try {
|
|
1819
1909
|
const content = await readFile3(keyPath, "utf-8");
|
|
1820
1910
|
return Buffer.from(content.trim(), "base64");
|
|
1821
|
-
} catch {
|
|
1911
|
+
} catch (err) {
|
|
1912
|
+
process.stderr.write(
|
|
1913
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
1914
|
+
`
|
|
1915
|
+
);
|
|
1822
1916
|
return null;
|
|
1823
1917
|
}
|
|
1824
1918
|
}
|
|
@@ -305,6 +305,12 @@ function getClient() {
|
|
|
305
305
|
if (!_resilientClient) {
|
|
306
306
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
307
307
|
}
|
|
308
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
309
|
+
return _resilientClient;
|
|
310
|
+
}
|
|
311
|
+
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
312
|
+
return _daemonClient;
|
|
313
|
+
}
|
|
308
314
|
return _resilientClient;
|
|
309
315
|
}
|
|
310
316
|
function getRawClient() {
|
|
@@ -793,6 +799,12 @@ async function ensureSchema() {
|
|
|
793
799
|
} catch {
|
|
794
800
|
}
|
|
795
801
|
}
|
|
802
|
+
try {
|
|
803
|
+
await client.execute(
|
|
804
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
805
|
+
);
|
|
806
|
+
} catch {
|
|
807
|
+
}
|
|
796
808
|
await client.executeMultiple(`
|
|
797
809
|
CREATE TABLE IF NOT EXISTS entities (
|
|
798
810
|
id TEXT PRIMARY KEY,
|
|
@@ -845,7 +857,30 @@ async function ensureSchema() {
|
|
|
845
857
|
entity_id TEXT NOT NULL,
|
|
846
858
|
PRIMARY KEY (hyperedge_id, entity_id)
|
|
847
859
|
);
|
|
860
|
+
|
|
861
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
|
|
862
|
+
name,
|
|
863
|
+
content=entities,
|
|
864
|
+
content_rowid=rowid
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
|
|
868
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
869
|
+
END;
|
|
870
|
+
|
|
871
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
|
|
872
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
873
|
+
END;
|
|
874
|
+
|
|
875
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
|
|
876
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
877
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
878
|
+
END;
|
|
848
879
|
`);
|
|
880
|
+
try {
|
|
881
|
+
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
882
|
+
} catch {
|
|
883
|
+
}
|
|
849
884
|
await client.executeMultiple(`
|
|
850
885
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
851
886
|
alias TEXT NOT NULL PRIMARY KEY,
|
|
@@ -1026,6 +1061,33 @@ async function ensureSchema() {
|
|
|
1026
1061
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
1027
1062
|
ON conversations(channel_id);
|
|
1028
1063
|
`);
|
|
1064
|
+
await client.executeMultiple(`
|
|
1065
|
+
CREATE TABLE IF NOT EXISTS session_agent_map (
|
|
1066
|
+
session_uuid TEXT PRIMARY KEY,
|
|
1067
|
+
agent_id TEXT NOT NULL,
|
|
1068
|
+
session_name TEXT,
|
|
1069
|
+
task_id TEXT,
|
|
1070
|
+
project_name TEXT,
|
|
1071
|
+
started_at TEXT NOT NULL
|
|
1072
|
+
);
|
|
1073
|
+
|
|
1074
|
+
CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
|
|
1075
|
+
ON session_agent_map(agent_id);
|
|
1076
|
+
`);
|
|
1077
|
+
try {
|
|
1078
|
+
const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
|
|
1079
|
+
if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
|
|
1080
|
+
await client.execute({
|
|
1081
|
+
sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
|
|
1082
|
+
SELECT session_id, agent_id, '', MIN(timestamp)
|
|
1083
|
+
FROM memories
|
|
1084
|
+
WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
|
|
1085
|
+
GROUP BY session_id, agent_id`,
|
|
1086
|
+
args: []
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
} catch {
|
|
1090
|
+
}
|
|
1029
1091
|
try {
|
|
1030
1092
|
await client.execute({
|
|
1031
1093
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
@@ -1159,8 +1221,30 @@ async function ensureSchema() {
|
|
|
1159
1221
|
});
|
|
1160
1222
|
} catch {
|
|
1161
1223
|
}
|
|
1224
|
+
for (const col of [
|
|
1225
|
+
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
1226
|
+
"ALTER TABLE memories ADD COLUMN outcome TEXT",
|
|
1227
|
+
"ALTER TABLE memories ADD COLUMN domain TEXT",
|
|
1228
|
+
"ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
|
|
1229
|
+
"ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
|
|
1230
|
+
"ALTER TABLE memories ADD COLUMN chain_position TEXT",
|
|
1231
|
+
"ALTER TABLE memories ADD COLUMN review_status TEXT",
|
|
1232
|
+
"ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
|
|
1233
|
+
"ALTER TABLE memories ADD COLUMN file_paths TEXT",
|
|
1234
|
+
"ALTER TABLE memories ADD COLUMN commit_hash TEXT",
|
|
1235
|
+
"ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
|
|
1236
|
+
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
1237
|
+
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
1238
|
+
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
1239
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
1240
|
+
]) {
|
|
1241
|
+
try {
|
|
1242
|
+
await client.execute(col);
|
|
1243
|
+
} catch {
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1162
1246
|
}
|
|
1163
|
-
var _client, _resilientClient, initTurso;
|
|
1247
|
+
var _client, _resilientClient, _daemonClient, initTurso;
|
|
1164
1248
|
var init_database = __esm({
|
|
1165
1249
|
"src/lib/database.ts"() {
|
|
1166
1250
|
"use strict";
|
|
@@ -1168,6 +1252,7 @@ var init_database = __esm({
|
|
|
1168
1252
|
init_employees();
|
|
1169
1253
|
_client = null;
|
|
1170
1254
|
_resilientClient = null;
|
|
1255
|
+
_daemonClient = null;
|
|
1171
1256
|
initTurso = initDatabase;
|
|
1172
1257
|
}
|
|
1173
1258
|
});
|
|
@@ -1599,6 +1684,7 @@ ${p.content}`).join("\n\n");
|
|
|
1599
1684
|
});
|
|
1600
1685
|
|
|
1601
1686
|
// src/lib/store.ts
|
|
1687
|
+
import { createHash } from "crypto";
|
|
1602
1688
|
init_database();
|
|
1603
1689
|
|
|
1604
1690
|
// src/lib/keychain.ts
|
|
@@ -1634,12 +1720,20 @@ async function getMasterKey() {
|
|
|
1634
1720
|
}
|
|
1635
1721
|
const keyPath = getKeyPath();
|
|
1636
1722
|
if (!existsSync3(keyPath)) {
|
|
1723
|
+
process.stderr.write(
|
|
1724
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
1725
|
+
`
|
|
1726
|
+
);
|
|
1637
1727
|
return null;
|
|
1638
1728
|
}
|
|
1639
1729
|
try {
|
|
1640
1730
|
const content = await readFile3(keyPath, "utf-8");
|
|
1641
1731
|
return Buffer.from(content.trim(), "base64");
|
|
1642
|
-
} catch {
|
|
1732
|
+
} catch (err) {
|
|
1733
|
+
process.stderr.write(
|
|
1734
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
1735
|
+
`
|
|
1736
|
+
);
|
|
1643
1737
|
return null;
|
|
1644
1738
|
}
|
|
1645
1739
|
}
|
|
@@ -1782,6 +1876,7 @@ import { realpathSync } from "fs";
|
|
|
1782
1876
|
import { fileURLToPath } from "url";
|
|
1783
1877
|
function isMainModule(importMetaUrl) {
|
|
1784
1878
|
if (process.argv[1] == null) return false;
|
|
1879
|
+
if (process.argv[1].includes("mcp/server")) return false;
|
|
1785
1880
|
try {
|
|
1786
1881
|
const scriptPath = realpathSync(process.argv[1]);
|
|
1787
1882
|
const modulePath = realpathSync(fileURLToPath(importMetaUrl));
|
|
@@ -305,6 +305,12 @@ function getClient() {
|
|
|
305
305
|
if (!_resilientClient) {
|
|
306
306
|
throw new Error("Database client not initialized. Call initDatabase() first.");
|
|
307
307
|
}
|
|
308
|
+
if (process.env.EXE_IS_DAEMON === "1") {
|
|
309
|
+
return _resilientClient;
|
|
310
|
+
}
|
|
311
|
+
if (_daemonClient && _daemonClient._isDaemonActive()) {
|
|
312
|
+
return _daemonClient;
|
|
313
|
+
}
|
|
308
314
|
return _resilientClient;
|
|
309
315
|
}
|
|
310
316
|
function getRawClient() {
|
|
@@ -793,6 +799,12 @@ async function ensureSchema() {
|
|
|
793
799
|
} catch {
|
|
794
800
|
}
|
|
795
801
|
}
|
|
802
|
+
try {
|
|
803
|
+
await client.execute(
|
|
804
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
805
|
+
);
|
|
806
|
+
} catch {
|
|
807
|
+
}
|
|
796
808
|
await client.executeMultiple(`
|
|
797
809
|
CREATE TABLE IF NOT EXISTS entities (
|
|
798
810
|
id TEXT PRIMARY KEY,
|
|
@@ -845,7 +857,30 @@ async function ensureSchema() {
|
|
|
845
857
|
entity_id TEXT NOT NULL,
|
|
846
858
|
PRIMARY KEY (hyperedge_id, entity_id)
|
|
847
859
|
);
|
|
860
|
+
|
|
861
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
|
|
862
|
+
name,
|
|
863
|
+
content=entities,
|
|
864
|
+
content_rowid=rowid
|
|
865
|
+
);
|
|
866
|
+
|
|
867
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
|
|
868
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
869
|
+
END;
|
|
870
|
+
|
|
871
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
|
|
872
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
873
|
+
END;
|
|
874
|
+
|
|
875
|
+
CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
|
|
876
|
+
INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
|
|
877
|
+
INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
|
|
878
|
+
END;
|
|
848
879
|
`);
|
|
880
|
+
try {
|
|
881
|
+
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
882
|
+
} catch {
|
|
883
|
+
}
|
|
849
884
|
await client.executeMultiple(`
|
|
850
885
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
851
886
|
alias TEXT NOT NULL PRIMARY KEY,
|
|
@@ -1026,6 +1061,33 @@ async function ensureSchema() {
|
|
|
1026
1061
|
CREATE INDEX IF NOT EXISTS idx_conversations_channel
|
|
1027
1062
|
ON conversations(channel_id);
|
|
1028
1063
|
`);
|
|
1064
|
+
await client.executeMultiple(`
|
|
1065
|
+
CREATE TABLE IF NOT EXISTS session_agent_map (
|
|
1066
|
+
session_uuid TEXT PRIMARY KEY,
|
|
1067
|
+
agent_id TEXT NOT NULL,
|
|
1068
|
+
session_name TEXT,
|
|
1069
|
+
task_id TEXT,
|
|
1070
|
+
project_name TEXT,
|
|
1071
|
+
started_at TEXT NOT NULL
|
|
1072
|
+
);
|
|
1073
|
+
|
|
1074
|
+
CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
|
|
1075
|
+
ON session_agent_map(agent_id);
|
|
1076
|
+
`);
|
|
1077
|
+
try {
|
|
1078
|
+
const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
|
|
1079
|
+
if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
|
|
1080
|
+
await client.execute({
|
|
1081
|
+
sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
|
|
1082
|
+
SELECT session_id, agent_id, '', MIN(timestamp)
|
|
1083
|
+
FROM memories
|
|
1084
|
+
WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
|
|
1085
|
+
GROUP BY session_id, agent_id`,
|
|
1086
|
+
args: []
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
} catch {
|
|
1090
|
+
}
|
|
1029
1091
|
try {
|
|
1030
1092
|
await client.execute({
|
|
1031
1093
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
@@ -1159,8 +1221,30 @@ async function ensureSchema() {
|
|
|
1159
1221
|
});
|
|
1160
1222
|
} catch {
|
|
1161
1223
|
}
|
|
1224
|
+
for (const col of [
|
|
1225
|
+
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
1226
|
+
"ALTER TABLE memories ADD COLUMN outcome TEXT",
|
|
1227
|
+
"ALTER TABLE memories ADD COLUMN domain TEXT",
|
|
1228
|
+
"ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
|
|
1229
|
+
"ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
|
|
1230
|
+
"ALTER TABLE memories ADD COLUMN chain_position TEXT",
|
|
1231
|
+
"ALTER TABLE memories ADD COLUMN review_status TEXT",
|
|
1232
|
+
"ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
|
|
1233
|
+
"ALTER TABLE memories ADD COLUMN file_paths TEXT",
|
|
1234
|
+
"ALTER TABLE memories ADD COLUMN commit_hash TEXT",
|
|
1235
|
+
"ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
|
|
1236
|
+
"ALTER TABLE memories ADD COLUMN token_cost REAL",
|
|
1237
|
+
"ALTER TABLE memories ADD COLUMN audience TEXT",
|
|
1238
|
+
"ALTER TABLE memories ADD COLUMN language_type TEXT",
|
|
1239
|
+
"ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
|
|
1240
|
+
]) {
|
|
1241
|
+
try {
|
|
1242
|
+
await client.execute(col);
|
|
1243
|
+
} catch {
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1162
1246
|
}
|
|
1163
|
-
var _client, _resilientClient, initTurso;
|
|
1247
|
+
var _client, _resilientClient, _daemonClient, initTurso;
|
|
1164
1248
|
var init_database = __esm({
|
|
1165
1249
|
"src/lib/database.ts"() {
|
|
1166
1250
|
"use strict";
|
|
@@ -1168,6 +1252,7 @@ var init_database = __esm({
|
|
|
1168
1252
|
init_employees();
|
|
1169
1253
|
_client = null;
|
|
1170
1254
|
_resilientClient = null;
|
|
1255
|
+
_daemonClient = null;
|
|
1171
1256
|
initTurso = initDatabase;
|
|
1172
1257
|
}
|
|
1173
1258
|
});
|
|
@@ -1816,7 +1901,7 @@ async function listPendingReviews(limit, sessionScope) {
|
|
|
1816
1901
|
const result2 = await client.execute({
|
|
1817
1902
|
sql: `SELECT title, assigned_to, project_name FROM tasks
|
|
1818
1903
|
WHERE status = 'needs_review'
|
|
1819
|
-
AND
|
|
1904
|
+
AND session_scope = ?
|
|
1820
1905
|
ORDER BY priority ASC, created_at DESC LIMIT ?`,
|
|
1821
1906
|
args: [sessionScope, limit]
|
|
1822
1907
|
});
|
|
@@ -1879,6 +1964,7 @@ var init_tasks_review = __esm({
|
|
|
1879
1964
|
});
|
|
1880
1965
|
|
|
1881
1966
|
// src/lib/store.ts
|
|
1967
|
+
import { createHash } from "crypto";
|
|
1882
1968
|
init_database();
|
|
1883
1969
|
|
|
1884
1970
|
// src/lib/keychain.ts
|
|
@@ -1914,12 +2000,20 @@ async function getMasterKey() {
|
|
|
1914
2000
|
}
|
|
1915
2001
|
const keyPath = getKeyPath();
|
|
1916
2002
|
if (!existsSync3(keyPath)) {
|
|
2003
|
+
process.stderr.write(
|
|
2004
|
+
`[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
2005
|
+
`
|
|
2006
|
+
);
|
|
1917
2007
|
return null;
|
|
1918
2008
|
}
|
|
1919
2009
|
try {
|
|
1920
2010
|
const content = await readFile3(keyPath, "utf-8");
|
|
1921
2011
|
return Buffer.from(content.trim(), "base64");
|
|
1922
|
-
} catch {
|
|
2012
|
+
} catch (err) {
|
|
2013
|
+
process.stderr.write(
|
|
2014
|
+
`[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
|
|
2015
|
+
`
|
|
2016
|
+
);
|
|
1923
2017
|
return null;
|
|
1924
2018
|
}
|
|
1925
2019
|
}
|
|
@@ -2009,6 +2103,7 @@ import { realpathSync } from "fs";
|
|
|
2009
2103
|
import { fileURLToPath } from "url";
|
|
2010
2104
|
function isMainModule(importMetaUrl) {
|
|
2011
2105
|
if (process.argv[1] == null) return false;
|
|
2106
|
+
if (process.argv[1].includes("mcp/server")) return false;
|
|
2012
2107
|
try {
|
|
2013
2108
|
const scriptPath = realpathSync(process.argv[1]);
|
|
2014
2109
|
const modulePath = realpathSync(fileURLToPath(importMetaUrl));
|