@askexenow/exe-os 0.8.38 → 0.8.39
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 +17 -8
- package/dist/bin/backfill-conversations.js +46 -10
- package/dist/bin/backfill-responses.js +46 -10
- package/dist/bin/backfill-vectors.js +42 -8
- package/dist/bin/cleanup-stale-review-tasks.js +37 -8
- package/dist/bin/cli.js +281 -154
- package/dist/bin/exe-agent.js +19 -4
- package/dist/bin/exe-assign.js +39 -5
- package/dist/bin/exe-boot.js +237 -111
- package/dist/bin/exe-call.js +11 -6
- package/dist/bin/exe-cloud.js +99 -28
- package/dist/bin/exe-dispatch.js +1 -1
- package/dist/bin/exe-doctor.js +37 -8
- package/dist/bin/exe-export-behaviors.js +39 -10
- package/dist/bin/exe-forget.js +38 -9
- package/dist/bin/exe-gateway.js +109 -42
- package/dist/bin/exe-heartbeat.js +49 -20
- package/dist/bin/exe-kill.js +39 -10
- package/dist/bin/exe-launch-agent.js +58 -22
- package/dist/bin/exe-link.js +184 -85
- package/dist/bin/exe-new-employee.js +21 -7
- package/dist/bin/exe-pending-messages.js +46 -17
- package/dist/bin/exe-pending-notifications.js +37 -8
- package/dist/bin/exe-pending-reviews.js +47 -18
- package/dist/bin/exe-rename.js +21 -7
- package/dist/bin/exe-review.js +34 -5
- package/dist/bin/exe-search.js +47 -10
- package/dist/bin/exe-session-cleanup.js +56 -19
- package/dist/bin/exe-settings.js +63 -2
- package/dist/bin/exe-status.js +34 -5
- package/dist/bin/exe-team.js +34 -5
- package/dist/bin/git-sweep.js +38 -9
- package/dist/bin/graph-backfill.js +37 -8
- package/dist/bin/graph-export.js +37 -8
- package/dist/bin/install.js +1 -1
- package/dist/bin/scan-tasks.js +40 -11
- package/dist/bin/setup.js +58 -24
- package/dist/bin/shard-migrate.js +37 -8
- package/dist/bin/wiki-sync.js +39 -9
- package/dist/gateway/index.js +102 -37
- package/dist/hooks/bug-report-worker.js +62 -28
- package/dist/hooks/commit-complete.js +38 -9
- package/dist/hooks/error-recall.js +49 -8
- package/dist/hooks/exe-heartbeat-hook.js +3 -2
- package/dist/hooks/ingest-worker.js +151 -37
- package/dist/hooks/ingest.js +74 -28
- package/dist/hooks/instructions-loaded.js +39 -9
- package/dist/hooks/notification.js +37 -7
- package/dist/hooks/post-compact.js +37 -7
- package/dist/hooks/pre-compact.js +35 -6
- package/dist/hooks/pre-tool-use.js +52 -14
- package/dist/hooks/prompt-ingest-worker.js +56 -10
- package/dist/hooks/prompt-submit.js +61 -23
- package/dist/hooks/response-ingest-worker.js +57 -11
- package/dist/hooks/session-end.js +43 -10
- package/dist/hooks/session-start.js +46 -8
- package/dist/hooks/stop.js +37 -7
- package/dist/hooks/subagent-stop.js +37 -7
- package/dist/hooks/summary-worker.js +317 -99
- package/dist/index.js +87 -22
- package/dist/lib/cloud-sync.js +172 -78
- package/dist/lib/config.js +4 -1
- package/dist/lib/consolidation.js +5 -4
- package/dist/lib/database.js +1 -0
- package/dist/lib/device-registry.js +2 -1
- package/dist/lib/embedder.js +9 -1
- package/dist/lib/employees.js +11 -6
- package/dist/lib/exe-daemon-client.js +6 -1
- package/dist/lib/exe-daemon.js +71 -28
- package/dist/lib/hybrid-search.js +47 -10
- package/dist/lib/identity.js +1 -1
- package/dist/lib/keychain.js +2 -1
- package/dist/lib/license.js +13 -4
- package/dist/lib/messaging.js +1 -1
- package/dist/lib/reminders.js +2 -2
- package/dist/lib/schedules.js +37 -8
- package/dist/lib/skill-learning.js +1 -1
- package/dist/lib/store.js +37 -8
- package/dist/lib/tasks.js +1 -1
- package/dist/lib/tmux-routing.js +1 -1
- package/dist/mcp/server.js +97 -43
- package/dist/mcp/tools/complete-reminder.js +1 -1
- package/dist/mcp/tools/create-task.js +14 -6
- package/dist/mcp/tools/deactivate-behavior.js +2 -2
- package/dist/mcp/tools/list-reminders.js +1 -1
- package/dist/mcp/tools/list-tasks.js +1 -1
- package/dist/mcp/tools/send-message.js +1 -1
- package/dist/mcp/tools/update-task.js +1 -1
- package/dist/runtime/index.js +35 -6
- package/dist/tui/App.js +177 -95
- package/package.json +3 -3
|
@@ -96,6 +96,7 @@ async function ensureSchema() {
|
|
|
96
96
|
const client = getRawClient();
|
|
97
97
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
98
98
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
99
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
99
100
|
try {
|
|
100
101
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
101
102
|
} catch {
|
|
@@ -896,15 +897,15 @@ var init_database = __esm({
|
|
|
896
897
|
});
|
|
897
898
|
|
|
898
899
|
// src/lib/config.ts
|
|
899
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
900
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
|
|
900
901
|
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
901
902
|
import path2 from "path";
|
|
902
|
-
import
|
|
903
|
+
import os2 from "os";
|
|
903
904
|
function resolveDataDir() {
|
|
904
905
|
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
905
906
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
906
|
-
const newDir = path2.join(
|
|
907
|
-
const legacyDir = path2.join(
|
|
907
|
+
const newDir = path2.join(os2.homedir(), ".exe-os");
|
|
908
|
+
const legacyDir = path2.join(os2.homedir(), ".exe-mem");
|
|
908
909
|
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
909
910
|
try {
|
|
910
911
|
renameSync(legacyDir, newDir);
|
|
@@ -991,7 +992,7 @@ async function loadConfig() {
|
|
|
991
992
|
normalizeAutoUpdate(migratedCfg);
|
|
992
993
|
const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
|
|
993
994
|
if (config.dbPath.startsWith("~")) {
|
|
994
|
-
config.dbPath = config.dbPath.replace(/^~/,
|
|
995
|
+
config.dbPath = config.dbPath.replace(/^~/, os2.homedir());
|
|
995
996
|
}
|
|
996
997
|
return config;
|
|
997
998
|
} catch {
|
|
@@ -1327,12 +1328,12 @@ var init_shard_manager = __esm({
|
|
|
1327
1328
|
|
|
1328
1329
|
// src/lib/session-registry.ts
|
|
1329
1330
|
import path4 from "path";
|
|
1330
|
-
import
|
|
1331
|
+
import os3 from "os";
|
|
1331
1332
|
var REGISTRY_PATH;
|
|
1332
1333
|
var init_session_registry = __esm({
|
|
1333
1334
|
"src/lib/session-registry.ts"() {
|
|
1334
1335
|
"use strict";
|
|
1335
|
-
REGISTRY_PATH = path4.join(
|
|
1336
|
+
REGISTRY_PATH = path4.join(os3.homedir(), ".exe-os", "session-registry.json");
|
|
1336
1337
|
}
|
|
1337
1338
|
});
|
|
1338
1339
|
|
|
@@ -1383,14 +1384,14 @@ var init_provider_table = __esm({
|
|
|
1383
1384
|
// src/lib/intercom-queue.ts
|
|
1384
1385
|
import { readFileSync as readFileSync2, writeFileSync, renameSync as renameSync2, existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
|
|
1385
1386
|
import path5 from "path";
|
|
1386
|
-
import
|
|
1387
|
+
import os4 from "os";
|
|
1387
1388
|
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
1388
1389
|
var init_intercom_queue = __esm({
|
|
1389
1390
|
"src/lib/intercom-queue.ts"() {
|
|
1390
1391
|
"use strict";
|
|
1391
|
-
QUEUE_PATH = path5.join(
|
|
1392
|
+
QUEUE_PATH = path5.join(os4.homedir(), ".exe-os", "intercom-queue.json");
|
|
1392
1393
|
TTL_MS = 60 * 60 * 1e3;
|
|
1393
|
-
INTERCOM_LOG = path5.join(
|
|
1394
|
+
INTERCOM_LOG = path5.join(os4.homedir(), ".exe-os", "intercom.log");
|
|
1394
1395
|
}
|
|
1395
1396
|
});
|
|
1396
1397
|
|
|
@@ -1441,7 +1442,7 @@ var init_plan_limits = __esm({
|
|
|
1441
1442
|
|
|
1442
1443
|
// src/lib/tmux-routing.ts
|
|
1443
1444
|
import path9 from "path";
|
|
1444
|
-
import
|
|
1445
|
+
import os5 from "os";
|
|
1445
1446
|
import { fileURLToPath } from "url";
|
|
1446
1447
|
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
1447
1448
|
var init_tmux_routing = __esm({
|
|
@@ -1455,9 +1456,9 @@ var init_tmux_routing = __esm({
|
|
|
1455
1456
|
init_provider_table();
|
|
1456
1457
|
init_intercom_queue();
|
|
1457
1458
|
init_plan_limits();
|
|
1458
|
-
SPAWN_LOCK_DIR = path9.join(
|
|
1459
|
-
SESSION_CACHE = path9.join(
|
|
1460
|
-
INTERCOM_LOG2 = path9.join(
|
|
1459
|
+
SPAWN_LOCK_DIR = path9.join(os5.homedir(), ".exe-os", "spawn-locks");
|
|
1460
|
+
SESSION_CACHE = path9.join(os5.homedir(), ".exe-os", "session-cache");
|
|
1461
|
+
INTERCOM_LOG2 = path9.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
1461
1462
|
DEBOUNCE_FILE = path9.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1462
1463
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1463
1464
|
}
|
|
@@ -1470,11 +1471,12 @@ init_database();
|
|
|
1470
1471
|
import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
1471
1472
|
import { existsSync } from "fs";
|
|
1472
1473
|
import path from "path";
|
|
1474
|
+
import os from "os";
|
|
1473
1475
|
import crypto from "crypto";
|
|
1474
1476
|
var SERVICE = "exe-mem";
|
|
1475
1477
|
var ACCOUNT = "master-key";
|
|
1476
1478
|
function getKeyDir() {
|
|
1477
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(
|
|
1479
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
1478
1480
|
}
|
|
1479
1481
|
function getKeyPath() {
|
|
1480
1482
|
return path.join(getKeyDir(), "master.key");
|
|
@@ -1511,6 +1513,30 @@ async function getMasterKey() {
|
|
|
1511
1513
|
|
|
1512
1514
|
// src/lib/store.ts
|
|
1513
1515
|
init_config();
|
|
1516
|
+
var INIT_MAX_RETRIES = 3;
|
|
1517
|
+
var INIT_RETRY_DELAY_MS = 1e3;
|
|
1518
|
+
function isBusyError2(err) {
|
|
1519
|
+
if (err instanceof Error) {
|
|
1520
|
+
const msg = err.message.toLowerCase();
|
|
1521
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1522
|
+
}
|
|
1523
|
+
return false;
|
|
1524
|
+
}
|
|
1525
|
+
async function retryOnBusy2(fn, label) {
|
|
1526
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1527
|
+
try {
|
|
1528
|
+
return await fn();
|
|
1529
|
+
} catch (err) {
|
|
1530
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1531
|
+
process.stderr.write(
|
|
1532
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1533
|
+
`
|
|
1534
|
+
);
|
|
1535
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
throw new Error("unreachable");
|
|
1539
|
+
}
|
|
1514
1540
|
var _pendingRecords = [];
|
|
1515
1541
|
var _batchSize = 20;
|
|
1516
1542
|
var _flushIntervalMs = 1e4;
|
|
@@ -1545,14 +1571,17 @@ async function initStore(options) {
|
|
|
1545
1571
|
dbPath,
|
|
1546
1572
|
encryptionKey: hexKey
|
|
1547
1573
|
});
|
|
1548
|
-
await ensureSchema();
|
|
1574
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1549
1575
|
try {
|
|
1550
1576
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1551
1577
|
initShardManager2(hexKey);
|
|
1552
1578
|
} catch {
|
|
1553
1579
|
}
|
|
1554
1580
|
const client = getClient();
|
|
1555
|
-
const vResult = await
|
|
1581
|
+
const vResult = await retryOnBusy2(
|
|
1582
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1583
|
+
"version-query"
|
|
1584
|
+
);
|
|
1556
1585
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1557
1586
|
}
|
|
1558
1587
|
|
|
@@ -10,15 +10,15 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/lib/config.ts
|
|
13
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
13
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
|
|
14
14
|
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
15
15
|
import path2 from "path";
|
|
16
|
-
import
|
|
16
|
+
import os2 from "os";
|
|
17
17
|
function resolveDataDir() {
|
|
18
18
|
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
19
19
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
20
|
-
const newDir = path2.join(
|
|
21
|
-
const legacyDir = path2.join(
|
|
20
|
+
const newDir = path2.join(os2.homedir(), ".exe-os");
|
|
21
|
+
const legacyDir = path2.join(os2.homedir(), ".exe-mem");
|
|
22
22
|
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
23
23
|
try {
|
|
24
24
|
renameSync(legacyDir, newDir);
|
|
@@ -105,7 +105,7 @@ async function loadConfig() {
|
|
|
105
105
|
normalizeAutoUpdate(migratedCfg);
|
|
106
106
|
const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
|
|
107
107
|
if (config.dbPath.startsWith("~")) {
|
|
108
|
-
config.dbPath = config.dbPath.replace(/^~/,
|
|
108
|
+
config.dbPath = config.dbPath.replace(/^~/, os2.homedir());
|
|
109
109
|
}
|
|
110
110
|
return config;
|
|
111
111
|
} catch {
|
|
@@ -526,6 +526,7 @@ async function ensureSchema() {
|
|
|
526
526
|
const client = getRawClient();
|
|
527
527
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
528
528
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
529
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
529
530
|
try {
|
|
530
531
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
531
532
|
} catch {
|
|
@@ -1319,11 +1320,12 @@ async function ensureSchema() {
|
|
|
1319
1320
|
import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
1320
1321
|
import { existsSync } from "fs";
|
|
1321
1322
|
import path from "path";
|
|
1323
|
+
import os from "os";
|
|
1322
1324
|
import crypto from "crypto";
|
|
1323
1325
|
var SERVICE = "exe-mem";
|
|
1324
1326
|
var ACCOUNT = "master-key";
|
|
1325
1327
|
function getKeyDir() {
|
|
1326
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(
|
|
1328
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
1327
1329
|
}
|
|
1328
1330
|
function getKeyPath() {
|
|
1329
1331
|
return path.join(getKeyDir(), "master.key");
|
|
@@ -1360,6 +1362,30 @@ async function getMasterKey() {
|
|
|
1360
1362
|
|
|
1361
1363
|
// src/lib/store.ts
|
|
1362
1364
|
init_config();
|
|
1365
|
+
var INIT_MAX_RETRIES = 3;
|
|
1366
|
+
var INIT_RETRY_DELAY_MS = 1e3;
|
|
1367
|
+
function isBusyError2(err) {
|
|
1368
|
+
if (err instanceof Error) {
|
|
1369
|
+
const msg = err.message.toLowerCase();
|
|
1370
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1371
|
+
}
|
|
1372
|
+
return false;
|
|
1373
|
+
}
|
|
1374
|
+
async function retryOnBusy2(fn, label) {
|
|
1375
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1376
|
+
try {
|
|
1377
|
+
return await fn();
|
|
1378
|
+
} catch (err) {
|
|
1379
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1380
|
+
process.stderr.write(
|
|
1381
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1382
|
+
`
|
|
1383
|
+
);
|
|
1384
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1387
|
+
throw new Error("unreachable");
|
|
1388
|
+
}
|
|
1363
1389
|
var _pendingRecords = [];
|
|
1364
1390
|
var _batchSize = 20;
|
|
1365
1391
|
var _flushIntervalMs = 1e4;
|
|
@@ -1394,14 +1420,17 @@ async function initStore(options) {
|
|
|
1394
1420
|
dbPath,
|
|
1395
1421
|
encryptionKey: hexKey
|
|
1396
1422
|
});
|
|
1397
|
-
await ensureSchema();
|
|
1423
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1398
1424
|
try {
|
|
1399
1425
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1400
1426
|
initShardManager2(hexKey);
|
|
1401
1427
|
} catch {
|
|
1402
1428
|
}
|
|
1403
1429
|
const client = getClient();
|
|
1404
|
-
const vResult = await
|
|
1430
|
+
const vResult = await retryOnBusy2(
|
|
1431
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1432
|
+
"version-query"
|
|
1433
|
+
);
|
|
1405
1434
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1406
1435
|
}
|
|
1407
1436
|
|
|
@@ -97,6 +97,7 @@ async function ensureSchema() {
|
|
|
97
97
|
const client = getRawClient();
|
|
98
98
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
99
99
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
100
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
100
101
|
try {
|
|
101
102
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
102
103
|
} catch {
|
|
@@ -897,15 +898,15 @@ var init_database = __esm({
|
|
|
897
898
|
});
|
|
898
899
|
|
|
899
900
|
// src/lib/config.ts
|
|
900
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
901
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, chmod as chmod2 } from "fs/promises";
|
|
901
902
|
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
902
903
|
import path2 from "path";
|
|
903
|
-
import
|
|
904
|
+
import os2 from "os";
|
|
904
905
|
function resolveDataDir() {
|
|
905
906
|
if (process.env.EXE_OS_DIR) return process.env.EXE_OS_DIR;
|
|
906
907
|
if (process.env.EXE_MEM_DIR) return process.env.EXE_MEM_DIR;
|
|
907
|
-
const newDir = path2.join(
|
|
908
|
-
const legacyDir = path2.join(
|
|
908
|
+
const newDir = path2.join(os2.homedir(), ".exe-os");
|
|
909
|
+
const legacyDir = path2.join(os2.homedir(), ".exe-mem");
|
|
909
910
|
if (!existsSync2(newDir) && existsSync2(legacyDir)) {
|
|
910
911
|
try {
|
|
911
912
|
renameSync(legacyDir, newDir);
|
|
@@ -992,7 +993,7 @@ async function loadConfig() {
|
|
|
992
993
|
normalizeAutoUpdate(migratedCfg);
|
|
993
994
|
const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
|
|
994
995
|
if (config.dbPath.startsWith("~")) {
|
|
995
|
-
config.dbPath = config.dbPath.replace(/^~/,
|
|
996
|
+
config.dbPath = config.dbPath.replace(/^~/, os2.homedir());
|
|
996
997
|
}
|
|
997
998
|
return config;
|
|
998
999
|
} catch {
|
|
@@ -1343,7 +1344,7 @@ var init_employees = __esm({
|
|
|
1343
1344
|
// src/lib/notifications.ts
|
|
1344
1345
|
import crypto2 from "crypto";
|
|
1345
1346
|
import path5 from "path";
|
|
1346
|
-
import
|
|
1347
|
+
import os3 from "os";
|
|
1347
1348
|
import {
|
|
1348
1349
|
readFileSync as readFileSync3,
|
|
1349
1350
|
readdirSync as readdirSync2,
|
|
@@ -1373,12 +1374,12 @@ var init_tasks_crud = __esm({
|
|
|
1373
1374
|
|
|
1374
1375
|
// src/lib/session-registry.ts
|
|
1375
1376
|
import path7 from "path";
|
|
1376
|
-
import
|
|
1377
|
+
import os4 from "os";
|
|
1377
1378
|
var REGISTRY_PATH;
|
|
1378
1379
|
var init_session_registry = __esm({
|
|
1379
1380
|
"src/lib/session-registry.ts"() {
|
|
1380
1381
|
"use strict";
|
|
1381
|
-
REGISTRY_PATH = path7.join(
|
|
1382
|
+
REGISTRY_PATH = path7.join(os4.homedir(), ".exe-os", "session-registry.json");
|
|
1382
1383
|
}
|
|
1383
1384
|
});
|
|
1384
1385
|
|
|
@@ -1429,14 +1430,14 @@ var init_provider_table = __esm({
|
|
|
1429
1430
|
// src/lib/intercom-queue.ts
|
|
1430
1431
|
import { readFileSync as readFileSync5, writeFileSync, renameSync as renameSync2, existsSync as existsSync7, mkdirSync as mkdirSync2 } from "fs";
|
|
1431
1432
|
import path8 from "path";
|
|
1432
|
-
import
|
|
1433
|
+
import os5 from "os";
|
|
1433
1434
|
var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
|
|
1434
1435
|
var init_intercom_queue = __esm({
|
|
1435
1436
|
"src/lib/intercom-queue.ts"() {
|
|
1436
1437
|
"use strict";
|
|
1437
|
-
QUEUE_PATH = path8.join(
|
|
1438
|
+
QUEUE_PATH = path8.join(os5.homedir(), ".exe-os", "intercom-queue.json");
|
|
1438
1439
|
TTL_MS = 60 * 60 * 1e3;
|
|
1439
|
-
INTERCOM_LOG = path8.join(
|
|
1440
|
+
INTERCOM_LOG = path8.join(os5.homedir(), ".exe-os", "intercom.log");
|
|
1440
1441
|
}
|
|
1441
1442
|
});
|
|
1442
1443
|
|
|
@@ -1473,7 +1474,7 @@ var init_plan_limits = __esm({
|
|
|
1473
1474
|
|
|
1474
1475
|
// src/lib/tmux-routing.ts
|
|
1475
1476
|
import path11 from "path";
|
|
1476
|
-
import
|
|
1477
|
+
import os6 from "os";
|
|
1477
1478
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1478
1479
|
var SPAWN_LOCK_DIR, SESSION_CACHE, INTERCOM_LOG2, DEBOUNCE_FILE, DEBOUNCE_CLEANUP_AGE_MS;
|
|
1479
1480
|
var init_tmux_routing = __esm({
|
|
@@ -1487,9 +1488,9 @@ var init_tmux_routing = __esm({
|
|
|
1487
1488
|
init_provider_table();
|
|
1488
1489
|
init_intercom_queue();
|
|
1489
1490
|
init_plan_limits();
|
|
1490
|
-
SPAWN_LOCK_DIR = path11.join(
|
|
1491
|
-
SESSION_CACHE = path11.join(
|
|
1492
|
-
INTERCOM_LOG2 = path11.join(
|
|
1491
|
+
SPAWN_LOCK_DIR = path11.join(os6.homedir(), ".exe-os", "spawn-locks");
|
|
1492
|
+
SESSION_CACHE = path11.join(os6.homedir(), ".exe-os", "session-cache");
|
|
1493
|
+
INTERCOM_LOG2 = path11.join(os6.homedir(), ".exe-os", "intercom.log");
|
|
1493
1494
|
DEBOUNCE_FILE = path11.join(SESSION_CACHE, "intercom-debounce.json");
|
|
1494
1495
|
DEBOUNCE_CLEANUP_AGE_MS = 5 * 60 * 1e3;
|
|
1495
1496
|
}
|
|
@@ -1528,11 +1529,12 @@ init_database();
|
|
|
1528
1529
|
import { readFile, writeFile, unlink, mkdir, chmod } from "fs/promises";
|
|
1529
1530
|
import { existsSync } from "fs";
|
|
1530
1531
|
import path from "path";
|
|
1532
|
+
import os from "os";
|
|
1531
1533
|
import crypto from "crypto";
|
|
1532
1534
|
var SERVICE = "exe-mem";
|
|
1533
1535
|
var ACCOUNT = "master-key";
|
|
1534
1536
|
function getKeyDir() {
|
|
1535
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(
|
|
1537
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path.join(os.homedir(), ".exe-os");
|
|
1536
1538
|
}
|
|
1537
1539
|
function getKeyPath() {
|
|
1538
1540
|
return path.join(getKeyDir(), "master.key");
|
|
@@ -1569,6 +1571,30 @@ async function getMasterKey() {
|
|
|
1569
1571
|
|
|
1570
1572
|
// src/lib/store.ts
|
|
1571
1573
|
init_config();
|
|
1574
|
+
var INIT_MAX_RETRIES = 3;
|
|
1575
|
+
var INIT_RETRY_DELAY_MS = 1e3;
|
|
1576
|
+
function isBusyError2(err) {
|
|
1577
|
+
if (err instanceof Error) {
|
|
1578
|
+
const msg = err.message.toLowerCase();
|
|
1579
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1580
|
+
}
|
|
1581
|
+
return false;
|
|
1582
|
+
}
|
|
1583
|
+
async function retryOnBusy2(fn, label) {
|
|
1584
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1585
|
+
try {
|
|
1586
|
+
return await fn();
|
|
1587
|
+
} catch (err) {
|
|
1588
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1589
|
+
process.stderr.write(
|
|
1590
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1591
|
+
`
|
|
1592
|
+
);
|
|
1593
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
throw new Error("unreachable");
|
|
1597
|
+
}
|
|
1572
1598
|
var _pendingRecords = [];
|
|
1573
1599
|
var _batchSize = 20;
|
|
1574
1600
|
var _flushIntervalMs = 1e4;
|
|
@@ -1603,14 +1629,17 @@ async function initStore(options) {
|
|
|
1603
1629
|
dbPath,
|
|
1604
1630
|
encryptionKey: hexKey
|
|
1605
1631
|
});
|
|
1606
|
-
await ensureSchema();
|
|
1632
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1607
1633
|
try {
|
|
1608
1634
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1609
1635
|
initShardManager2(hexKey);
|
|
1610
1636
|
} catch {
|
|
1611
1637
|
}
|
|
1612
1638
|
const client = getClient();
|
|
1613
|
-
const vResult = await
|
|
1639
|
+
const vResult = await retryOnBusy2(
|
|
1640
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1641
|
+
"version-query"
|
|
1642
|
+
);
|
|
1614
1643
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1615
1644
|
}
|
|
1616
1645
|
|
package/dist/bin/exe-rename.js
CHANGED
|
@@ -111,6 +111,7 @@ async function ensureSchema() {
|
|
|
111
111
|
const client = getRawClient();
|
|
112
112
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
113
113
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
114
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
114
115
|
try {
|
|
115
116
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
116
117
|
} catch {
|
|
@@ -931,7 +932,7 @@ import { execSync } from "child_process";
|
|
|
931
932
|
import path2 from "path";
|
|
932
933
|
|
|
933
934
|
// src/lib/config.ts
|
|
934
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
935
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
935
936
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
936
937
|
import path from "path";
|
|
937
938
|
import os from "os";
|
|
@@ -1053,15 +1054,20 @@ async function saveEmployees(employees, employeesPath = EMPLOYEES_PATH) {
|
|
|
1053
1054
|
await mkdir2(path2.dirname(employeesPath), { recursive: true });
|
|
1054
1055
|
await writeFile2(employeesPath, JSON.stringify(employees, null, 2) + "\n", "utf-8");
|
|
1055
1056
|
}
|
|
1057
|
+
function findExeBin() {
|
|
1058
|
+
try {
|
|
1059
|
+
return execSync(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
1060
|
+
} catch {
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1056
1064
|
function registerBinSymlinks(name) {
|
|
1057
1065
|
const created = [];
|
|
1058
1066
|
const skipped = [];
|
|
1059
1067
|
const errors = [];
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
} catch {
|
|
1064
|
-
errors.push("Could not find 'exe' in PATH");
|
|
1068
|
+
const exeBinPath = findExeBin();
|
|
1069
|
+
if (!exeBinPath) {
|
|
1070
|
+
errors.push("Could not find 'exe-os' in PATH");
|
|
1065
1071
|
return { created, skipped, errors };
|
|
1066
1072
|
}
|
|
1067
1073
|
const binDir = path2.dirname(exeBinPath);
|
|
@@ -1240,9 +1246,17 @@ async function renameEmployee(oldName, newName, opts = {}) {
|
|
|
1240
1246
|
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
1241
1247
|
}
|
|
1242
1248
|
}
|
|
1249
|
+
function findExeBin2() {
|
|
1250
|
+
try {
|
|
1251
|
+
return execSync2(process.platform === "win32" ? "where exe-os" : "which exe-os", { encoding: "utf8" }).trim();
|
|
1252
|
+
} catch {
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1243
1256
|
function removeOldSymlinks(name) {
|
|
1244
1257
|
try {
|
|
1245
|
-
const exeBinPath =
|
|
1258
|
+
const exeBinPath = findExeBin2();
|
|
1259
|
+
if (!exeBinPath) return;
|
|
1246
1260
|
const binDir = path3.dirname(exeBinPath);
|
|
1247
1261
|
for (const suffix of ["", "-opencode"]) {
|
|
1248
1262
|
const linkPath = path3.join(binDir, `${name}${suffix}`);
|
package/dist/bin/exe-review.js
CHANGED
|
@@ -10,7 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/lib/config.ts
|
|
13
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
13
|
+
import { readFile, writeFile, mkdir, chmod } from "fs/promises";
|
|
14
14
|
import { readFileSync, existsSync, renameSync } from "fs";
|
|
15
15
|
import path from "path";
|
|
16
16
|
import os from "os";
|
|
@@ -554,6 +554,7 @@ async function ensureSchema() {
|
|
|
554
554
|
const client = getRawClient();
|
|
555
555
|
await client.execute("PRAGMA journal_mode = WAL");
|
|
556
556
|
await client.execute("PRAGMA busy_timeout = 30000");
|
|
557
|
+
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
557
558
|
try {
|
|
558
559
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
559
560
|
} catch {
|
|
@@ -1344,14 +1345,15 @@ async function ensureSchema() {
|
|
|
1344
1345
|
}
|
|
1345
1346
|
|
|
1346
1347
|
// src/lib/keychain.ts
|
|
1347
|
-
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod } from "fs/promises";
|
|
1348
|
+
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
1348
1349
|
import { existsSync as existsSync3 } from "fs";
|
|
1349
1350
|
import path3 from "path";
|
|
1351
|
+
import os2 from "os";
|
|
1350
1352
|
import crypto from "crypto";
|
|
1351
1353
|
var SERVICE = "exe-mem";
|
|
1352
1354
|
var ACCOUNT = "master-key";
|
|
1353
1355
|
function getKeyDir() {
|
|
1354
|
-
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(
|
|
1356
|
+
return process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? path3.join(os2.homedir(), ".exe-os");
|
|
1355
1357
|
}
|
|
1356
1358
|
function getKeyPath() {
|
|
1357
1359
|
return path3.join(getKeyDir(), "master.key");
|
|
@@ -1388,6 +1390,30 @@ async function getMasterKey() {
|
|
|
1388
1390
|
|
|
1389
1391
|
// src/lib/store.ts
|
|
1390
1392
|
init_config();
|
|
1393
|
+
var INIT_MAX_RETRIES = 3;
|
|
1394
|
+
var INIT_RETRY_DELAY_MS = 1e3;
|
|
1395
|
+
function isBusyError2(err) {
|
|
1396
|
+
if (err instanceof Error) {
|
|
1397
|
+
const msg = err.message.toLowerCase();
|
|
1398
|
+
return msg.includes("sqlite_busy") || msg.includes("database is locked");
|
|
1399
|
+
}
|
|
1400
|
+
return false;
|
|
1401
|
+
}
|
|
1402
|
+
async function retryOnBusy2(fn, label) {
|
|
1403
|
+
for (let attempt = 0; attempt <= INIT_MAX_RETRIES; attempt++) {
|
|
1404
|
+
try {
|
|
1405
|
+
return await fn();
|
|
1406
|
+
} catch (err) {
|
|
1407
|
+
if (!isBusyError2(err) || attempt === INIT_MAX_RETRIES) throw err;
|
|
1408
|
+
process.stderr.write(
|
|
1409
|
+
`[store] SQLITE_BUSY during ${label}, retry ${attempt + 1}/${INIT_MAX_RETRIES}
|
|
1410
|
+
`
|
|
1411
|
+
);
|
|
1412
|
+
await new Promise((r) => setTimeout(r, INIT_RETRY_DELAY_MS * (attempt + 1)));
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1415
|
+
throw new Error("unreachable");
|
|
1416
|
+
}
|
|
1391
1417
|
var _pendingRecords = [];
|
|
1392
1418
|
var _batchSize = 20;
|
|
1393
1419
|
var _flushIntervalMs = 1e4;
|
|
@@ -1422,14 +1448,17 @@ async function initStore(options) {
|
|
|
1422
1448
|
dbPath,
|
|
1423
1449
|
encryptionKey: hexKey
|
|
1424
1450
|
});
|
|
1425
|
-
await ensureSchema();
|
|
1451
|
+
await retryOnBusy2(() => ensureSchema(), "ensureSchema");
|
|
1426
1452
|
try {
|
|
1427
1453
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
1428
1454
|
initShardManager2(hexKey);
|
|
1429
1455
|
} catch {
|
|
1430
1456
|
}
|
|
1431
1457
|
const client = getClient();
|
|
1432
|
-
const vResult = await
|
|
1458
|
+
const vResult = await retryOnBusy2(
|
|
1459
|
+
() => client.execute("SELECT MAX(version) as max_v FROM memories"),
|
|
1460
|
+
"version-query"
|
|
1461
|
+
);
|
|
1433
1462
|
_nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
|
|
1434
1463
|
}
|
|
1435
1464
|
function classifyTier(record) {
|