@askexenow/exe-os 0.9.101 → 0.9.104
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/agentic-ontology-backfill.js +334 -100
- package/dist/bin/agentic-reflection-backfill.js +328 -97
- package/dist/bin/agentic-semantic-label.js +328 -97
- package/dist/bin/backfill-conversations.js +332 -97
- package/dist/bin/backfill-responses.js +332 -97
- package/dist/bin/backfill-vectors.js +337 -106
- package/dist/bin/bulk-sync-postgres.js +335 -101
- package/dist/bin/cleanup-stale-review-tasks.js +356 -108
- package/dist/bin/cli.js +653 -405
- package/dist/bin/exe-agent.js +21 -3
- package/dist/bin/exe-assign.js +338 -94
- package/dist/bin/exe-boot.js +472 -239
- package/dist/bin/exe-call.js +22 -5
- package/dist/bin/exe-cloud.js +404 -158
- package/dist/bin/exe-dispatch.js +390 -142
- package/dist/bin/exe-doctor.js +349 -103
- package/dist/bin/exe-export-behaviors.js +351 -105
- package/dist/bin/exe-forget.js +352 -103
- package/dist/bin/exe-gateway.js +420 -172
- package/dist/bin/exe-heartbeat.js +361 -113
- package/dist/bin/exe-kill.js +344 -98
- package/dist/bin/exe-launch-agent.js +375 -129
- package/dist/bin/exe-new-employee.js +83 -67
- package/dist/bin/exe-pending-messages.js +356 -108
- package/dist/bin/exe-pending-notifications.js +358 -110
- package/dist/bin/exe-pending-reviews.js +359 -111
- package/dist/bin/exe-rename.js +354 -108
- package/dist/bin/exe-review.js +343 -97
- package/dist/bin/exe-search.js +363 -113
- package/dist/bin/exe-session-cleanup.js +403 -155
- package/dist/bin/exe-settings.js +14 -9
- package/dist/bin/exe-start-codex.js +365 -131
- package/dist/bin/exe-start-opencode.js +359 -125
- package/dist/bin/exe-status.js +356 -108
- package/dist/bin/exe-team.js +343 -97
- package/dist/bin/git-sweep.js +390 -142
- package/dist/bin/graph-backfill.js +334 -100
- package/dist/bin/graph-export.js +346 -100
- package/dist/bin/install.js +1 -0
- package/dist/bin/intercom-check.js +403 -155
- package/dist/bin/pre-publish.js +470 -0
- package/dist/bin/scan-tasks.js +393 -145
- package/dist/bin/setup.js +331 -159
- package/dist/bin/shard-migrate.js +328 -94
- package/dist/gateway/index.js +406 -158
- package/dist/hooks/bug-report-worker.js +396 -148
- package/dist/hooks/codex-stop-task-finalizer.js +374 -126
- package/dist/hooks/commit-complete.js +390 -142
- package/dist/hooks/error-recall.js +365 -115
- package/dist/hooks/ingest.js +357 -111
- package/dist/hooks/instructions-loaded.js +351 -105
- package/dist/hooks/notification.js +343 -97
- package/dist/hooks/post-compact.js +358 -110
- package/dist/hooks/post-tool-combined.js +384 -132
- package/dist/hooks/pre-compact.js +391 -143
- package/dist/hooks/pre-tool-use.js +362 -114
- package/dist/hooks/prompt-submit.js +422 -170
- package/dist/hooks/session-end.js +393 -145
- package/dist/hooks/session-start.js +390 -138
- package/dist/hooks/stop.js +361 -113
- package/dist/hooks/subagent-stop.js +354 -106
- package/dist/hooks/summary-worker.js +418 -185
- package/dist/index.js +400 -152
- package/dist/lib/cloud-sync.js +291 -131
- package/dist/lib/consolidation.js +8 -2
- package/dist/lib/database.js +233 -73
- package/dist/lib/db.js +233 -73
- package/dist/lib/device-registry.js +237 -77
- package/dist/lib/employee-templates.js +19 -1
- package/dist/lib/exe-daemon.js +705 -409
- package/dist/lib/hybrid-search.js +363 -113
- package/dist/lib/identity.js +9 -5
- package/dist/lib/messaging.js +26 -20
- package/dist/lib/reminders.js +5 -1
- package/dist/lib/schedules.js +320 -89
- package/dist/lib/skill-learning.js +28 -24
- package/dist/lib/store.js +342 -96
- package/dist/lib/tasks.js +82 -76
- package/dist/lib/tmux-routing.js +74 -68
- package/dist/lib/token-spend.js +5 -1
- package/dist/mcp/server.js +628 -355
- package/dist/mcp/tools/complete-reminder.js +5 -1
- package/dist/mcp/tools/create-reminder.js +5 -1
- package/dist/mcp/tools/create-task.js +89 -83
- package/dist/mcp/tools/deactivate-behavior.js +7 -3
- package/dist/mcp/tools/list-reminders.js +5 -1
- package/dist/mcp/tools/list-tasks.js +28 -21
- package/dist/mcp/tools/send-message.js +28 -22
- package/dist/mcp/tools/update-task.js +89 -83
- package/dist/runtime/index.js +390 -142
- package/dist/tui/App.js +437 -189
- package/package.json +2 -2
|
@@ -1458,9 +1458,79 @@ __export(database_exports, {
|
|
|
1458
1458
|
isInitialized: () => isInitialized,
|
|
1459
1459
|
setExternalClient: () => setExternalClient
|
|
1460
1460
|
});
|
|
1461
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
1461
|
+
import { chmodSync as chmodSync2, existsSync as existsSync6, statSync as statSync2, copyFileSync, unlinkSync as unlinkSync3, openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync2 } from "fs";
|
|
1462
1462
|
import { createClient } from "@libsql/client";
|
|
1463
|
+
import { homedir } from "os";
|
|
1464
|
+
import { join } from "path";
|
|
1465
|
+
function logCatchDebug(context, err) {
|
|
1466
|
+
if (_debugDb) {
|
|
1467
|
+
process.stderr.write(
|
|
1468
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
1469
|
+
`
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
function acquireDbLock() {
|
|
1474
|
+
mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
|
|
1475
|
+
try {
|
|
1476
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1477
|
+
} catch (err) {
|
|
1478
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
1479
|
+
try {
|
|
1480
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
1481
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
1482
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1483
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1484
|
+
return;
|
|
1485
|
+
}
|
|
1486
|
+
} catch (e) {
|
|
1487
|
+
logCatchDebug("stale lock check", e);
|
|
1488
|
+
}
|
|
1489
|
+
process.stderr.write(
|
|
1490
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
1491
|
+
);
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1494
|
+
throw err;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
function releaseDbLock() {
|
|
1498
|
+
if (_lockFd !== null) {
|
|
1499
|
+
try {
|
|
1500
|
+
closeSync2(_lockFd);
|
|
1501
|
+
} catch (e) {
|
|
1502
|
+
logCatchDebug("lock close", e);
|
|
1503
|
+
}
|
|
1504
|
+
_lockFd = null;
|
|
1505
|
+
}
|
|
1506
|
+
try {
|
|
1507
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1508
|
+
} catch (e) {
|
|
1509
|
+
logCatchDebug("lock unlink", e);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1463
1512
|
async function initDatabase(config) {
|
|
1513
|
+
acquireDbLock();
|
|
1514
|
+
if (existsSync6(config.dbPath)) {
|
|
1515
|
+
const dbStat = statSync2(config.dbPath);
|
|
1516
|
+
if (dbStat.size === 0) {
|
|
1517
|
+
const walPath = config.dbPath + "-wal";
|
|
1518
|
+
if (existsSync6(walPath) && statSync2(walPath).size > 0) {
|
|
1519
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
1520
|
+
copyFileSync(config.dbPath, backupPath);
|
|
1521
|
+
unlinkSync3(config.dbPath);
|
|
1522
|
+
process.stderr.write(
|
|
1523
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
1524
|
+
`
|
|
1525
|
+
);
|
|
1526
|
+
} else {
|
|
1527
|
+
process.stderr.write(
|
|
1528
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
1529
|
+
`
|
|
1530
|
+
);
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1464
1534
|
if (_walCheckpointTimer) {
|
|
1465
1535
|
clearInterval(_walCheckpointTimer);
|
|
1466
1536
|
_walCheckpointTimer = null;
|
|
@@ -1487,10 +1557,8 @@ async function initDatabase(config) {
|
|
|
1487
1557
|
_client = createClient(opts);
|
|
1488
1558
|
_resilientClient = wrapWithRetry(_client);
|
|
1489
1559
|
_adapterClient = _resilientClient;
|
|
1490
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
1491
|
-
|
|
1492
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
1493
|
-
});
|
|
1560
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
1561
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
1494
1562
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
1495
1563
|
_walCheckpointTimer = setInterval(() => {
|
|
1496
1564
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -1505,11 +1573,16 @@ async function initDatabase(config) {
|
|
|
1505
1573
|
for (const suffix of ["-wal", "-shm"]) {
|
|
1506
1574
|
try {
|
|
1507
1575
|
chmodSync2(config.dbPath + suffix, 384);
|
|
1508
|
-
} catch {
|
|
1576
|
+
} catch (chmodErr) {
|
|
1577
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1578
|
+
`);
|
|
1509
1579
|
}
|
|
1510
1580
|
}
|
|
1511
|
-
} catch {
|
|
1581
|
+
} catch (chmodErr) {
|
|
1582
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1583
|
+
`);
|
|
1512
1584
|
}
|
|
1585
|
+
releaseDbLock();
|
|
1513
1586
|
}
|
|
1514
1587
|
function isInitialized() {
|
|
1515
1588
|
return _adapterClient !== null || _client !== null;
|
|
@@ -1564,7 +1637,8 @@ async function ensureSchema() {
|
|
|
1564
1637
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
1565
1638
|
try {
|
|
1566
1639
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1567
|
-
} catch {
|
|
1640
|
+
} catch (e) {
|
|
1641
|
+
logCatchDebug("migration", e);
|
|
1568
1642
|
}
|
|
1569
1643
|
await client.executeMultiple(`
|
|
1570
1644
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -1629,6 +1703,23 @@ async function ensureSchema() {
|
|
|
1629
1703
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
1630
1704
|
END;
|
|
1631
1705
|
`);
|
|
1706
|
+
try {
|
|
1707
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
1708
|
+
} catch (ftsErr) {
|
|
1709
|
+
process.stderr.write(
|
|
1710
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
1711
|
+
`
|
|
1712
|
+
);
|
|
1713
|
+
try {
|
|
1714
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
1715
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
1716
|
+
} catch (rebuildErr) {
|
|
1717
|
+
process.stderr.write(
|
|
1718
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
1719
|
+
`
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1632
1723
|
await client.executeMultiple(`
|
|
1633
1724
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
1634
1725
|
key TEXT PRIMARY KEY,
|
|
@@ -1687,35 +1778,40 @@ async function ensureSchema() {
|
|
|
1687
1778
|
});
|
|
1688
1779
|
}
|
|
1689
1780
|
}
|
|
1690
|
-
} catch {
|
|
1781
|
+
} catch (seedErr) {
|
|
1782
|
+
logCatchDebug("behavior seed", seedErr);
|
|
1691
1783
|
}
|
|
1692
1784
|
try {
|
|
1693
1785
|
await client.execute({
|
|
1694
1786
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
1695
1787
|
args: []
|
|
1696
1788
|
});
|
|
1697
|
-
} catch {
|
|
1789
|
+
} catch (e) {
|
|
1790
|
+
logCatchDebug("migration", e);
|
|
1698
1791
|
}
|
|
1699
1792
|
try {
|
|
1700
1793
|
await client.execute({
|
|
1701
1794
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
1702
1795
|
args: []
|
|
1703
1796
|
});
|
|
1704
|
-
} catch {
|
|
1797
|
+
} catch (e) {
|
|
1798
|
+
logCatchDebug("migration", e);
|
|
1705
1799
|
}
|
|
1706
1800
|
try {
|
|
1707
1801
|
await client.execute({
|
|
1708
1802
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
1709
1803
|
args: []
|
|
1710
1804
|
});
|
|
1711
|
-
} catch {
|
|
1805
|
+
} catch (e) {
|
|
1806
|
+
logCatchDebug("migration", e);
|
|
1712
1807
|
}
|
|
1713
1808
|
try {
|
|
1714
1809
|
await client.execute({
|
|
1715
1810
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
1716
1811
|
args: []
|
|
1717
1812
|
});
|
|
1718
|
-
} catch {
|
|
1813
|
+
} catch (e) {
|
|
1814
|
+
logCatchDebug("migration", e);
|
|
1719
1815
|
}
|
|
1720
1816
|
try {
|
|
1721
1817
|
await client.execute({
|
|
@@ -1724,98 +1820,112 @@ async function ensureSchema() {
|
|
|
1724
1820
|
WHERE parent_task_id IS NOT NULL`,
|
|
1725
1821
|
args: []
|
|
1726
1822
|
});
|
|
1727
|
-
} catch {
|
|
1823
|
+
} catch (e) {
|
|
1824
|
+
logCatchDebug("migration", e);
|
|
1728
1825
|
}
|
|
1729
1826
|
try {
|
|
1730
1827
|
await client.execute({
|
|
1731
1828
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
1732
1829
|
args: []
|
|
1733
1830
|
});
|
|
1734
|
-
} catch {
|
|
1831
|
+
} catch (e) {
|
|
1832
|
+
logCatchDebug("migration", e);
|
|
1735
1833
|
}
|
|
1736
1834
|
try {
|
|
1737
1835
|
await client.execute({
|
|
1738
1836
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
1739
1837
|
args: []
|
|
1740
1838
|
});
|
|
1741
|
-
} catch {
|
|
1839
|
+
} catch (e) {
|
|
1840
|
+
logCatchDebug("migration", e);
|
|
1742
1841
|
}
|
|
1743
1842
|
try {
|
|
1744
1843
|
await client.execute({
|
|
1745
1844
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
1746
1845
|
args: []
|
|
1747
1846
|
});
|
|
1748
|
-
} catch {
|
|
1847
|
+
} catch (e) {
|
|
1848
|
+
logCatchDebug("migration", e);
|
|
1749
1849
|
}
|
|
1750
1850
|
try {
|
|
1751
1851
|
await client.execute({
|
|
1752
1852
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
1753
1853
|
args: []
|
|
1754
1854
|
});
|
|
1755
|
-
} catch {
|
|
1855
|
+
} catch (e) {
|
|
1856
|
+
logCatchDebug("migration", e);
|
|
1756
1857
|
}
|
|
1757
1858
|
try {
|
|
1758
1859
|
await client.execute({
|
|
1759
1860
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
1760
1861
|
args: []
|
|
1761
1862
|
});
|
|
1762
|
-
} catch {
|
|
1863
|
+
} catch (e) {
|
|
1864
|
+
logCatchDebug("migration", e);
|
|
1763
1865
|
}
|
|
1764
1866
|
try {
|
|
1765
1867
|
await client.execute({
|
|
1766
1868
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
1767
1869
|
args: []
|
|
1768
1870
|
});
|
|
1769
|
-
} catch {
|
|
1871
|
+
} catch (e) {
|
|
1872
|
+
logCatchDebug("migration", e);
|
|
1770
1873
|
}
|
|
1771
1874
|
try {
|
|
1772
1875
|
await client.execute({
|
|
1773
1876
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
1774
1877
|
args: []
|
|
1775
1878
|
});
|
|
1776
|
-
} catch {
|
|
1879
|
+
} catch (e) {
|
|
1880
|
+
logCatchDebug("migration", e);
|
|
1777
1881
|
}
|
|
1778
1882
|
try {
|
|
1779
1883
|
await client.execute({
|
|
1780
1884
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
1781
1885
|
args: []
|
|
1782
1886
|
});
|
|
1783
|
-
} catch {
|
|
1887
|
+
} catch (e) {
|
|
1888
|
+
logCatchDebug("migration", e);
|
|
1784
1889
|
}
|
|
1785
1890
|
try {
|
|
1786
1891
|
await client.execute({
|
|
1787
1892
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
1788
1893
|
args: []
|
|
1789
1894
|
});
|
|
1790
|
-
} catch {
|
|
1895
|
+
} catch (e) {
|
|
1896
|
+
logCatchDebug("migration", e);
|
|
1791
1897
|
}
|
|
1792
1898
|
try {
|
|
1793
1899
|
await client.execute({
|
|
1794
1900
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
1795
1901
|
args: []
|
|
1796
1902
|
});
|
|
1797
|
-
} catch {
|
|
1903
|
+
} catch (e) {
|
|
1904
|
+
logCatchDebug("migration", e);
|
|
1798
1905
|
}
|
|
1799
1906
|
try {
|
|
1800
1907
|
await client.execute({
|
|
1801
1908
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
1802
1909
|
args: []
|
|
1803
1910
|
});
|
|
1804
|
-
} catch {
|
|
1911
|
+
} catch (e) {
|
|
1912
|
+
logCatchDebug("migration", e);
|
|
1805
1913
|
}
|
|
1806
1914
|
try {
|
|
1807
1915
|
await client.execute({
|
|
1808
1916
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
1809
1917
|
args: []
|
|
1810
1918
|
});
|
|
1811
|
-
} catch {
|
|
1919
|
+
} catch (e) {
|
|
1920
|
+
logCatchDebug("migration", e);
|
|
1812
1921
|
}
|
|
1813
1922
|
try {
|
|
1814
1923
|
await client.execute({
|
|
1815
1924
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
1816
1925
|
args: []
|
|
1817
1926
|
});
|
|
1818
|
-
} catch {
|
|
1927
|
+
} catch (e) {
|
|
1928
|
+
logCatchDebug("migration", e);
|
|
1819
1929
|
}
|
|
1820
1930
|
await client.executeMultiple(`
|
|
1821
1931
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -1920,14 +2030,16 @@ async function ensureSchema() {
|
|
|
1920
2030
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
1921
2031
|
args: []
|
|
1922
2032
|
});
|
|
1923
|
-
} catch {
|
|
2033
|
+
} catch (e) {
|
|
2034
|
+
logCatchDebug("migration", e);
|
|
1924
2035
|
}
|
|
1925
2036
|
try {
|
|
1926
2037
|
await client.execute({
|
|
1927
2038
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
1928
2039
|
args: []
|
|
1929
2040
|
});
|
|
1930
|
-
} catch {
|
|
2041
|
+
} catch (e) {
|
|
2042
|
+
logCatchDebug("migration", e);
|
|
1931
2043
|
}
|
|
1932
2044
|
await client.executeMultiple(`
|
|
1933
2045
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -1953,7 +2065,8 @@ async function ensureSchema() {
|
|
|
1953
2065
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
1954
2066
|
args: []
|
|
1955
2067
|
});
|
|
1956
|
-
} catch {
|
|
2068
|
+
} catch (e) {
|
|
2069
|
+
logCatchDebug("migration", e);
|
|
1957
2070
|
}
|
|
1958
2071
|
await client.executeMultiple(`
|
|
1959
2072
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -1977,7 +2090,8 @@ async function ensureSchema() {
|
|
|
1977
2090
|
`);
|
|
1978
2091
|
try {
|
|
1979
2092
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
1980
|
-
} catch {
|
|
2093
|
+
} catch (e) {
|
|
2094
|
+
logCatchDebug("migration", e);
|
|
1981
2095
|
}
|
|
1982
2096
|
await client.executeMultiple(`
|
|
1983
2097
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2014,63 +2128,72 @@ async function ensureSchema() {
|
|
|
2014
2128
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2015
2129
|
args: []
|
|
2016
2130
|
});
|
|
2017
|
-
} catch {
|
|
2131
|
+
} catch (e) {
|
|
2132
|
+
logCatchDebug("migration", e);
|
|
2018
2133
|
}
|
|
2019
2134
|
try {
|
|
2020
2135
|
await client.execute({
|
|
2021
2136
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2022
2137
|
args: []
|
|
2023
2138
|
});
|
|
2024
|
-
} catch {
|
|
2139
|
+
} catch (e) {
|
|
2140
|
+
logCatchDebug("migration", e);
|
|
2025
2141
|
}
|
|
2026
2142
|
try {
|
|
2027
2143
|
await client.execute({
|
|
2028
2144
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2029
2145
|
args: []
|
|
2030
2146
|
});
|
|
2031
|
-
} catch {
|
|
2147
|
+
} catch (e) {
|
|
2148
|
+
logCatchDebug("migration", e);
|
|
2032
2149
|
}
|
|
2033
2150
|
try {
|
|
2034
2151
|
await client.execute({
|
|
2035
2152
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2036
2153
|
args: []
|
|
2037
2154
|
});
|
|
2038
|
-
} catch {
|
|
2155
|
+
} catch (e) {
|
|
2156
|
+
logCatchDebug("migration", e);
|
|
2039
2157
|
}
|
|
2040
2158
|
try {
|
|
2041
2159
|
await client.execute({
|
|
2042
2160
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2043
2161
|
args: []
|
|
2044
2162
|
});
|
|
2045
|
-
} catch {
|
|
2163
|
+
} catch (e) {
|
|
2164
|
+
logCatchDebug("migration", e);
|
|
2046
2165
|
}
|
|
2047
2166
|
try {
|
|
2048
2167
|
await client.execute({
|
|
2049
2168
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2050
2169
|
args: []
|
|
2051
2170
|
});
|
|
2052
|
-
} catch {
|
|
2171
|
+
} catch (e) {
|
|
2172
|
+
logCatchDebug("migration", e);
|
|
2053
2173
|
}
|
|
2054
2174
|
try {
|
|
2055
2175
|
await client.execute({
|
|
2056
2176
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2057
2177
|
args: []
|
|
2058
2178
|
});
|
|
2059
|
-
} catch {
|
|
2179
|
+
} catch (e) {
|
|
2180
|
+
logCatchDebug("migration", e);
|
|
2060
2181
|
}
|
|
2061
2182
|
try {
|
|
2062
2183
|
await client.execute({
|
|
2063
2184
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2064
2185
|
args: []
|
|
2065
2186
|
});
|
|
2066
|
-
} catch {
|
|
2187
|
+
} catch (e) {
|
|
2188
|
+
logCatchDebug("migration", e);
|
|
2067
2189
|
}
|
|
2068
2190
|
try {
|
|
2069
2191
|
await client.execute({
|
|
2070
2192
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2071
2193
|
args: []
|
|
2072
2194
|
});
|
|
2073
|
-
} catch {
|
|
2195
|
+
} catch (e) {
|
|
2196
|
+
logCatchDebug("migration", e);
|
|
2074
2197
|
}
|
|
2075
2198
|
for (const col of [
|
|
2076
2199
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2078,14 +2201,16 @@ async function ensureSchema() {
|
|
|
2078
2201
|
]) {
|
|
2079
2202
|
try {
|
|
2080
2203
|
await client.execute(col);
|
|
2081
|
-
} catch {
|
|
2204
|
+
} catch (e) {
|
|
2205
|
+
logCatchDebug("migration", e);
|
|
2082
2206
|
}
|
|
2083
2207
|
}
|
|
2084
2208
|
try {
|
|
2085
2209
|
await client.execute(
|
|
2086
2210
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2087
2211
|
);
|
|
2088
|
-
} catch {
|
|
2212
|
+
} catch (e) {
|
|
2213
|
+
logCatchDebug("migration", e);
|
|
2089
2214
|
}
|
|
2090
2215
|
try {
|
|
2091
2216
|
await client.execute(
|
|
@@ -2093,7 +2218,8 @@ async function ensureSchema() {
|
|
|
2093
2218
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2094
2219
|
WHERE content_hash IS NOT NULL`
|
|
2095
2220
|
);
|
|
2096
|
-
} catch {
|
|
2221
|
+
} catch (e) {
|
|
2222
|
+
logCatchDebug("migration", e);
|
|
2097
2223
|
}
|
|
2098
2224
|
await client.executeMultiple(`
|
|
2099
2225
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2169,7 +2295,8 @@ async function ensureSchema() {
|
|
|
2169
2295
|
`);
|
|
2170
2296
|
try {
|
|
2171
2297
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2172
|
-
} catch {
|
|
2298
|
+
} catch (e) {
|
|
2299
|
+
logCatchDebug("migration", e);
|
|
2173
2300
|
}
|
|
2174
2301
|
await client.executeMultiple(`
|
|
2175
2302
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2184,14 +2311,16 @@ async function ensureSchema() {
|
|
|
2184
2311
|
]) {
|
|
2185
2312
|
try {
|
|
2186
2313
|
await client.execute(col);
|
|
2187
|
-
} catch {
|
|
2314
|
+
} catch (e) {
|
|
2315
|
+
logCatchDebug("migration", e);
|
|
2188
2316
|
}
|
|
2189
2317
|
}
|
|
2190
2318
|
try {
|
|
2191
2319
|
await client.execute(
|
|
2192
2320
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2193
2321
|
);
|
|
2194
|
-
} catch {
|
|
2322
|
+
} catch (e) {
|
|
2323
|
+
logCatchDebug("migration", e);
|
|
2195
2324
|
}
|
|
2196
2325
|
await client.executeMultiple(`
|
|
2197
2326
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2290,7 +2419,8 @@ async function ensureSchema() {
|
|
|
2290
2419
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2291
2420
|
args: []
|
|
2292
2421
|
});
|
|
2293
|
-
} catch {
|
|
2422
|
+
} catch (e) {
|
|
2423
|
+
logCatchDebug("migration", e);
|
|
2294
2424
|
}
|
|
2295
2425
|
}
|
|
2296
2426
|
for (const col of [
|
|
@@ -2299,7 +2429,8 @@ async function ensureSchema() {
|
|
|
2299
2429
|
]) {
|
|
2300
2430
|
try {
|
|
2301
2431
|
await client.execute(col);
|
|
2302
|
-
} catch {
|
|
2432
|
+
} catch (e) {
|
|
2433
|
+
logCatchDebug("migration", e);
|
|
2303
2434
|
}
|
|
2304
2435
|
}
|
|
2305
2436
|
await client.executeMultiple(`
|
|
@@ -2484,56 +2615,64 @@ async function ensureSchema() {
|
|
|
2484
2615
|
args: []
|
|
2485
2616
|
});
|
|
2486
2617
|
}
|
|
2487
|
-
} catch {
|
|
2618
|
+
} catch (e) {
|
|
2619
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
2488
2620
|
}
|
|
2489
2621
|
try {
|
|
2490
2622
|
await client.execute({
|
|
2491
2623
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
2492
2624
|
args: []
|
|
2493
2625
|
});
|
|
2494
|
-
} catch {
|
|
2626
|
+
} catch (e) {
|
|
2627
|
+
logCatchDebug("migration", e);
|
|
2495
2628
|
}
|
|
2496
2629
|
try {
|
|
2497
2630
|
await client.execute({
|
|
2498
2631
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
2499
2632
|
args: []
|
|
2500
2633
|
});
|
|
2501
|
-
} catch {
|
|
2634
|
+
} catch (e) {
|
|
2635
|
+
logCatchDebug("migration", e);
|
|
2502
2636
|
}
|
|
2503
2637
|
try {
|
|
2504
2638
|
await client.execute({
|
|
2505
2639
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
2506
2640
|
args: []
|
|
2507
2641
|
});
|
|
2508
|
-
} catch {
|
|
2642
|
+
} catch (e) {
|
|
2643
|
+
logCatchDebug("migration", e);
|
|
2509
2644
|
}
|
|
2510
2645
|
try {
|
|
2511
2646
|
await client.execute({
|
|
2512
2647
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
2513
2648
|
args: []
|
|
2514
2649
|
});
|
|
2515
|
-
} catch {
|
|
2650
|
+
} catch (e) {
|
|
2651
|
+
logCatchDebug("migration", e);
|
|
2516
2652
|
}
|
|
2517
2653
|
try {
|
|
2518
2654
|
await client.execute({
|
|
2519
2655
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
2520
2656
|
args: []
|
|
2521
2657
|
});
|
|
2522
|
-
} catch {
|
|
2658
|
+
} catch (e) {
|
|
2659
|
+
logCatchDebug("migration", e);
|
|
2523
2660
|
}
|
|
2524
2661
|
try {
|
|
2525
2662
|
await client.execute({
|
|
2526
2663
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2527
2664
|
args: []
|
|
2528
2665
|
});
|
|
2529
|
-
} catch {
|
|
2666
|
+
} catch (e) {
|
|
2667
|
+
logCatchDebug("migration", e);
|
|
2530
2668
|
}
|
|
2531
2669
|
try {
|
|
2532
2670
|
await client.execute({
|
|
2533
2671
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2534
2672
|
args: []
|
|
2535
2673
|
});
|
|
2536
|
-
} catch {
|
|
2674
|
+
} catch (e) {
|
|
2675
|
+
logCatchDebug("migration", e);
|
|
2537
2676
|
}
|
|
2538
2677
|
await client.executeMultiple(`
|
|
2539
2678
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -2732,13 +2871,15 @@ async function ensureSchema() {
|
|
|
2732
2871
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
2733
2872
|
args: []
|
|
2734
2873
|
});
|
|
2735
|
-
} catch {
|
|
2874
|
+
} catch (e) {
|
|
2875
|
+
logCatchDebug("migration", e);
|
|
2736
2876
|
}
|
|
2737
2877
|
try {
|
|
2738
2878
|
await client.execute(
|
|
2739
2879
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
2740
2880
|
);
|
|
2741
|
-
} catch {
|
|
2881
|
+
} catch (e) {
|
|
2882
|
+
logCatchDebug("migration", e);
|
|
2742
2883
|
}
|
|
2743
2884
|
try {
|
|
2744
2885
|
await client.execute({
|
|
@@ -2749,20 +2890,23 @@ async function ensureSchema() {
|
|
|
2749
2890
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
2750
2891
|
args: []
|
|
2751
2892
|
});
|
|
2752
|
-
} catch {
|
|
2893
|
+
} catch (e) {
|
|
2894
|
+
logCatchDebug("migration", e);
|
|
2753
2895
|
}
|
|
2754
2896
|
try {
|
|
2755
2897
|
await client.execute({
|
|
2756
2898
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
2757
2899
|
args: []
|
|
2758
2900
|
});
|
|
2759
|
-
} catch {
|
|
2901
|
+
} catch (e) {
|
|
2902
|
+
logCatchDebug("migration", e);
|
|
2760
2903
|
}
|
|
2761
2904
|
try {
|
|
2762
2905
|
await client.execute(
|
|
2763
2906
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
2764
2907
|
);
|
|
2765
|
-
} catch {
|
|
2908
|
+
} catch (e) {
|
|
2909
|
+
logCatchDebug("migration", e);
|
|
2766
2910
|
}
|
|
2767
2911
|
for (const col of [
|
|
2768
2912
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -2770,7 +2914,8 @@ async function ensureSchema() {
|
|
|
2770
2914
|
]) {
|
|
2771
2915
|
try {
|
|
2772
2916
|
await client.execute(col);
|
|
2773
|
-
} catch {
|
|
2917
|
+
} catch (e) {
|
|
2918
|
+
logCatchDebug("migration", e);
|
|
2774
2919
|
}
|
|
2775
2920
|
}
|
|
2776
2921
|
try {
|
|
@@ -2778,13 +2923,15 @@ async function ensureSchema() {
|
|
|
2778
2923
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
2779
2924
|
args: []
|
|
2780
2925
|
});
|
|
2781
|
-
} catch {
|
|
2926
|
+
} catch (e) {
|
|
2927
|
+
logCatchDebug("migration", e);
|
|
2782
2928
|
}
|
|
2783
2929
|
try {
|
|
2784
2930
|
await client.execute(
|
|
2785
2931
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
2786
2932
|
);
|
|
2787
|
-
} catch {
|
|
2933
|
+
} catch (e) {
|
|
2934
|
+
logCatchDebug("migration", e);
|
|
2788
2935
|
}
|
|
2789
2936
|
for (const col of [
|
|
2790
2937
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -2792,7 +2939,8 @@ async function ensureSchema() {
|
|
|
2792
2939
|
]) {
|
|
2793
2940
|
try {
|
|
2794
2941
|
await client.execute(col);
|
|
2795
|
-
} catch {
|
|
2942
|
+
} catch (e) {
|
|
2943
|
+
logCatchDebug("migration", e);
|
|
2796
2944
|
}
|
|
2797
2945
|
}
|
|
2798
2946
|
try {
|
|
@@ -2800,27 +2948,31 @@ async function ensureSchema() {
|
|
|
2800
2948
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
2801
2949
|
args: []
|
|
2802
2950
|
});
|
|
2803
|
-
} catch {
|
|
2951
|
+
} catch (e) {
|
|
2952
|
+
logCatchDebug("migration", e);
|
|
2804
2953
|
}
|
|
2805
2954
|
try {
|
|
2806
2955
|
await client.execute({
|
|
2807
2956
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
2808
2957
|
args: []
|
|
2809
2958
|
});
|
|
2810
|
-
} catch {
|
|
2959
|
+
} catch (e) {
|
|
2960
|
+
logCatchDebug("migration", e);
|
|
2811
2961
|
}
|
|
2812
2962
|
try {
|
|
2813
2963
|
await client.execute(
|
|
2814
2964
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
2815
2965
|
);
|
|
2816
|
-
} catch {
|
|
2966
|
+
} catch (e) {
|
|
2967
|
+
logCatchDebug("migration", e);
|
|
2817
2968
|
}
|
|
2818
2969
|
try {
|
|
2819
2970
|
await client.execute({
|
|
2820
2971
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
2821
2972
|
args: []
|
|
2822
2973
|
});
|
|
2823
|
-
} catch {
|
|
2974
|
+
} catch (e) {
|
|
2975
|
+
logCatchDebug("migration", e);
|
|
2824
2976
|
}
|
|
2825
2977
|
for (const col of [
|
|
2826
2978
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -2841,7 +2993,8 @@ async function ensureSchema() {
|
|
|
2841
2993
|
]) {
|
|
2842
2994
|
try {
|
|
2843
2995
|
await client.execute(col);
|
|
2844
|
-
} catch {
|
|
2996
|
+
} catch (e) {
|
|
2997
|
+
logCatchDebug("migration", e);
|
|
2845
2998
|
}
|
|
2846
2999
|
}
|
|
2847
3000
|
try {
|
|
@@ -2849,14 +3002,16 @@ async function ensureSchema() {
|
|
|
2849
3002
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
2850
3003
|
args: []
|
|
2851
3004
|
});
|
|
2852
|
-
} catch {
|
|
3005
|
+
} catch (e) {
|
|
3006
|
+
logCatchDebug("migration", e);
|
|
2853
3007
|
}
|
|
2854
3008
|
try {
|
|
2855
3009
|
await client.execute({
|
|
2856
3010
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
2857
3011
|
args: []
|
|
2858
3012
|
});
|
|
2859
|
-
} catch {
|
|
3013
|
+
} catch (e) {
|
|
3014
|
+
logCatchDebug("migration", e);
|
|
2860
3015
|
}
|
|
2861
3016
|
}
|
|
2862
3017
|
async function disposeDatabase() {
|
|
@@ -2867,7 +3022,8 @@ async function disposeDatabase() {
|
|
|
2867
3022
|
if (_client) {
|
|
2868
3023
|
try {
|
|
2869
3024
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
2870
|
-
} catch {
|
|
3025
|
+
} catch (e) {
|
|
3026
|
+
logCatchDebug("WAL checkpoint", e);
|
|
2871
3027
|
}
|
|
2872
3028
|
}
|
|
2873
3029
|
if (_daemonClient) {
|
|
@@ -2883,8 +3039,9 @@ async function disposeDatabase() {
|
|
|
2883
3039
|
_client = null;
|
|
2884
3040
|
_resilientClient = null;
|
|
2885
3041
|
}
|
|
3042
|
+
releaseDbLock();
|
|
2886
3043
|
}
|
|
2887
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3044
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
2888
3045
|
var init_database = __esm({
|
|
2889
3046
|
"src/lib/database.ts"() {
|
|
2890
3047
|
"use strict";
|
|
@@ -2892,11 +3049,14 @@ var init_database = __esm({
|
|
|
2892
3049
|
init_employees();
|
|
2893
3050
|
init_database_adapter();
|
|
2894
3051
|
init_memory();
|
|
3052
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
2895
3053
|
_client = null;
|
|
2896
3054
|
_resilientClient = null;
|
|
2897
3055
|
_walCheckpointTimer = null;
|
|
2898
3056
|
_daemonClient = null;
|
|
2899
3057
|
_adapterClient = null;
|
|
3058
|
+
_lockFd = null;
|
|
3059
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
2900
3060
|
initTurso = initDatabase;
|
|
2901
3061
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
2902
3062
|
disposeTurso = disposeDatabase;
|
|
@@ -2919,18 +3079,54 @@ __export(shard_manager_exports, {
|
|
|
2919
3079
|
shardExists: () => shardExists
|
|
2920
3080
|
});
|
|
2921
3081
|
import path7 from "path";
|
|
2922
|
-
import { existsSync as
|
|
3082
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
2923
3083
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2924
3084
|
function initShardManager(encryptionKey) {
|
|
2925
3085
|
_encryptionKey = encryptionKey;
|
|
2926
|
-
|
|
2927
|
-
|
|
3086
|
+
_keyValidated = false;
|
|
3087
|
+
_keyValidationPromise = null;
|
|
3088
|
+
if (!existsSync8(SHARDS_DIR)) {
|
|
3089
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
3090
|
+
}
|
|
3091
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3092
|
+
if (existingShards.length === 0) {
|
|
3093
|
+
_keyValidated = true;
|
|
2928
3094
|
}
|
|
2929
3095
|
_shardingEnabled = true;
|
|
2930
3096
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
2931
3097
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
2932
3098
|
_evictionTimer.unref();
|
|
2933
3099
|
}
|
|
3100
|
+
async function validateEncryptionKey() {
|
|
3101
|
+
if (_keyValidated) return true;
|
|
3102
|
+
if (!_encryptionKey) return false;
|
|
3103
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3104
|
+
if (existingShards.length === 0) {
|
|
3105
|
+
_keyValidated = true;
|
|
3106
|
+
return true;
|
|
3107
|
+
}
|
|
3108
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
3109
|
+
const dbPath = path7.join(SHARDS_DIR, shardFile);
|
|
3110
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
3111
|
+
try {
|
|
3112
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
3113
|
+
testClient.close();
|
|
3114
|
+
_keyValidated = true;
|
|
3115
|
+
return true;
|
|
3116
|
+
} catch {
|
|
3117
|
+
try {
|
|
3118
|
+
testClient.close();
|
|
3119
|
+
} catch {
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
process.stderr.write(
|
|
3124
|
+
`[shard-manager] WARNING: encryption key cannot read any existing shards (${existingShards.length} found). New shard creation disabled to prevent stranded files. Run /exe-doctor to audit.
|
|
3125
|
+
`
|
|
3126
|
+
);
|
|
3127
|
+
_shardingEnabled = false;
|
|
3128
|
+
return false;
|
|
3129
|
+
}
|
|
2934
3130
|
function isShardingEnabled() {
|
|
2935
3131
|
return _shardingEnabled;
|
|
2936
3132
|
}
|
|
@@ -2964,13 +3160,13 @@ function getShardClient(projectName) {
|
|
|
2964
3160
|
}
|
|
2965
3161
|
function shardExists(projectName) {
|
|
2966
3162
|
const safeName = safeShardName(projectName);
|
|
2967
|
-
return
|
|
3163
|
+
return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
2968
3164
|
}
|
|
2969
3165
|
function safeShardName(projectName) {
|
|
2970
3166
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2971
3167
|
}
|
|
2972
3168
|
function listShards() {
|
|
2973
|
-
if (!
|
|
3169
|
+
if (!existsSync8(SHARDS_DIR)) return [];
|
|
2974
3170
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
2975
3171
|
}
|
|
2976
3172
|
async function auditShardHealth(options = {}) {
|
|
@@ -2983,7 +3179,7 @@ async function auditShardHealth(options = {}) {
|
|
|
2983
3179
|
const shards = [];
|
|
2984
3180
|
for (const name of names) {
|
|
2985
3181
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
2986
|
-
const stat =
|
|
3182
|
+
const stat = statSync4(dbPath);
|
|
2987
3183
|
const item = {
|
|
2988
3184
|
name,
|
|
2989
3185
|
path: dbPath,
|
|
@@ -3223,6 +3419,17 @@ async function ensureShardSchema(client) {
|
|
|
3223
3419
|
}
|
|
3224
3420
|
}
|
|
3225
3421
|
async function getReadyShardClient(projectName) {
|
|
3422
|
+
if (!_keyValidated) {
|
|
3423
|
+
if (!_keyValidationPromise) {
|
|
3424
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
3425
|
+
}
|
|
3426
|
+
const valid = await _keyValidationPromise;
|
|
3427
|
+
if (!valid) {
|
|
3428
|
+
throw new Error(
|
|
3429
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
3430
|
+
);
|
|
3431
|
+
}
|
|
3432
|
+
}
|
|
3226
3433
|
const safeName = safeShardName(projectName);
|
|
3227
3434
|
let client = getShardClient(projectName);
|
|
3228
3435
|
try {
|
|
@@ -3235,8 +3442,8 @@ async function getReadyShardClient(projectName) {
|
|
|
3235
3442
|
_shards.delete(safeName);
|
|
3236
3443
|
_shardLastAccess.delete(safeName);
|
|
3237
3444
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3238
|
-
if (
|
|
3239
|
-
const stat =
|
|
3445
|
+
if (existsSync8(dbPath)) {
|
|
3446
|
+
const stat = statSync4(dbPath);
|
|
3240
3447
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3241
3448
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3242
3449
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3301,7 +3508,7 @@ function disposeShards() {
|
|
|
3301
3508
|
_shardingEnabled = false;
|
|
3302
3509
|
_encryptionKey = null;
|
|
3303
3510
|
}
|
|
3304
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
3511
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
3305
3512
|
var init_shard_manager = __esm({
|
|
3306
3513
|
"src/lib/shard-manager.ts"() {
|
|
3307
3514
|
"use strict";
|
|
@@ -3315,6 +3522,8 @@ var init_shard_manager = __esm({
|
|
|
3315
3522
|
_evictionTimer = null;
|
|
3316
3523
|
_encryptionKey = null;
|
|
3317
3524
|
_shardingEnabled = false;
|
|
3525
|
+
_keyValidated = false;
|
|
3526
|
+
_keyValidationPromise = null;
|
|
3318
3527
|
}
|
|
3319
3528
|
});
|
|
3320
3529
|
|
|
@@ -3510,6 +3719,18 @@ var init_platform_procedures = __esm({
|
|
|
3510
3719
|
priority: "p0",
|
|
3511
3720
|
content: "create_task is dispatch + delivery. Task lifecycle: open \u2192 in_progress (you start) \u2192 done (update_task when finished) \u2192 needs_review (reviewer nudged) \u2192 closed (COO only via close_task). DB is the reliable delivery \u2014 intercom is just a speedup nudge. If you finish a task, self-chain: check for next task immediately (step 7). Never wait for a nudge. Never say 'standing by.'"
|
|
3512
3721
|
},
|
|
3722
|
+
{
|
|
3723
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
3724
|
+
domain: "workflow",
|
|
3725
|
+
priority: "p0",
|
|
3726
|
+
content: "When you dispatch work, you OWN the review. Check list_tasks(status='needs_review') on EVERY prompt \u2014 don't wait for intercom nudges (they're unreliable). When a task shows needs_review: (1) read the deliverable (git diff in worktree, exe/output/ files, or task result summary), (2) verify it works (tsc, build, run), (3) close_task if good or create a fix task if not. Reviews sitting >30 minutes is a pipeline stall. The whole chain: worker calls update_task(done) \u2192 system flags needs_review \u2192 manager pulls and verifies \u2192 close_task \u2192 COO reviews manager's work \u2192 merge to main. Every level actively pulls \u2014 nobody waits."
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
3730
|
+
domain: "workflow",
|
|
3731
|
+
priority: "p0",
|
|
3732
|
+
content: "When a bug from support(action='list_bugs') is fixed and verified, the reviewer MUST triage it upstream: support(action='triage_bug', id='<bug-id>', notes='<what was fixed>', fixed_version='<version>', linked_commit='<hash>'). This closes the bug in the customer's view \u2014 their COO checks list_my_bugs and sees status change from open \u2192 closed with the fix version. Without triage, customers see 'open' forever even after the fix ships. Same for feature requests: support(action='triage_feature', ..., shipped_version='<version>'). Triage is part of the review gate \u2014 a fix is not done until the upstream report is closed."
|
|
3733
|
+
},
|
|
3513
3734
|
{
|
|
3514
3735
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
3515
3736
|
domain: "architecture",
|
|
@@ -4095,7 +4316,7 @@ init_database();
|
|
|
4095
4316
|
|
|
4096
4317
|
// src/lib/keychain.ts
|
|
4097
4318
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4098
|
-
import { existsSync as
|
|
4319
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
4099
4320
|
import { execSync as execSync3 } from "child_process";
|
|
4100
4321
|
import path6 from "path";
|
|
4101
4322
|
import os5 from "os";
|
|
@@ -4134,7 +4355,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
4134
4355
|
if (process.platform !== "linux") return false;
|
|
4135
4356
|
try {
|
|
4136
4357
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4137
|
-
const st =
|
|
4358
|
+
const st = statSync3(keyPath);
|
|
4138
4359
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4139
4360
|
if (uid === 0) return true;
|
|
4140
4361
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -4336,7 +4557,7 @@ async function getMasterKey() {
|
|
|
4336
4557
|
}
|
|
4337
4558
|
}
|
|
4338
4559
|
const keyPath = getKeyPath();
|
|
4339
|
-
if (!
|
|
4560
|
+
if (!existsSync7(keyPath)) {
|
|
4340
4561
|
process.stderr.write(
|
|
4341
4562
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
4342
4563
|
`
|
|
@@ -4530,6 +4751,13 @@ function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
|
4530
4751
|
}
|
|
4531
4752
|
|
|
4532
4753
|
// src/lib/store.ts
|
|
4754
|
+
var _debugStore = process.env.EXE_DEBUG === "1";
|
|
4755
|
+
function logStoreWarn(context, err) {
|
|
4756
|
+
process.stderr.write(
|
|
4757
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
4758
|
+
`
|
|
4759
|
+
);
|
|
4760
|
+
}
|
|
4533
4761
|
var INIT_MAX_RETRIES = 3;
|
|
4534
4762
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
4535
4763
|
function isBusyError2(err) {
|
|
@@ -4592,13 +4820,15 @@ async function initStore(options) {
|
|
|
4592
4820
|
try {
|
|
4593
4821
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4594
4822
|
await initDaemonClient2();
|
|
4595
|
-
} catch {
|
|
4823
|
+
} catch (e) {
|
|
4824
|
+
logStoreWarn("catch", e);
|
|
4596
4825
|
}
|
|
4597
4826
|
if (!options?.lightweight) {
|
|
4598
4827
|
try {
|
|
4599
4828
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4600
4829
|
initShardManager2(hexKey);
|
|
4601
|
-
} catch {
|
|
4830
|
+
} catch (e) {
|
|
4831
|
+
logStoreWarn("catch", e);
|
|
4602
4832
|
}
|
|
4603
4833
|
const client = getClient();
|
|
4604
4834
|
const vResult = await retryOnBusy2(
|
|
@@ -4609,7 +4839,8 @@ async function initStore(options) {
|
|
|
4609
4839
|
try {
|
|
4610
4840
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4611
4841
|
await loadGlobalProcedures2();
|
|
4612
|
-
} catch {
|
|
4842
|
+
} catch (e) {
|
|
4843
|
+
logStoreWarn("catch", e);
|
|
4613
4844
|
}
|
|
4614
4845
|
}
|
|
4615
4846
|
}
|
|
@@ -4737,12 +4968,14 @@ async function flushBatch() {
|
|
|
4737
4968
|
try {
|
|
4738
4969
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
4739
4970
|
await insertMemoryCardsForBatch2(batch);
|
|
4740
|
-
} catch {
|
|
4971
|
+
} catch (e) {
|
|
4972
|
+
logStoreWarn("catch", e);
|
|
4741
4973
|
}
|
|
4742
4974
|
try {
|
|
4743
4975
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
4744
4976
|
await insertOntologyForBatch2(batch);
|
|
4745
|
-
} catch {
|
|
4977
|
+
} catch (e) {
|
|
4978
|
+
logStoreWarn("catch", e);
|
|
4746
4979
|
}
|
|
4747
4980
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4748
4981
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -4781,7 +5014,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
4781
5014
|
}
|
|
4782
5015
|
}
|
|
4783
5016
|
}
|
|
4784
|
-
} catch {
|
|
5017
|
+
} catch (e) {
|
|
5018
|
+
logStoreWarn("catch", e);
|
|
4785
5019
|
}
|
|
4786
5020
|
return batch.length;
|
|
4787
5021
|
} finally {
|
|
@@ -4811,7 +5045,7 @@ init_agentic_ontology();
|
|
|
4811
5045
|
|
|
4812
5046
|
// src/lib/background-jobs.ts
|
|
4813
5047
|
init_config();
|
|
4814
|
-
import { existsSync as
|
|
5048
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync3, unlinkSync as unlinkSync4 } from "fs";
|
|
4815
5049
|
import { execFileSync } from "child_process";
|
|
4816
5050
|
import os6 from "os";
|
|
4817
5051
|
import path8 from "path";
|
|
@@ -4821,7 +5055,7 @@ var LOCK_DIR = path8.join(JOB_DIR, "locks");
|
|
|
4821
5055
|
var DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
4822
5056
|
var MAX_HISTORY = 200;
|
|
4823
5057
|
function ensureDirs() {
|
|
4824
|
-
|
|
5058
|
+
mkdirSync4(LOCK_DIR, { recursive: true });
|
|
4825
5059
|
}
|
|
4826
5060
|
function now() {
|
|
4827
5061
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -4837,7 +5071,7 @@ function isAlive(pid) {
|
|
|
4837
5071
|
}
|
|
4838
5072
|
function readJobsRaw() {
|
|
4839
5073
|
ensureDirs();
|
|
4840
|
-
if (!
|
|
5074
|
+
if (!existsSync9(JOBS_FILE)) return [];
|
|
4841
5075
|
try {
|
|
4842
5076
|
const parsed = JSON.parse(readFileSync5(JOBS_FILE, "utf8"));
|
|
4843
5077
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -4857,7 +5091,7 @@ function lockPath(type) {
|
|
|
4857
5091
|
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
4858
5092
|
ensureDirs();
|
|
4859
5093
|
const file = lockPath(type);
|
|
4860
|
-
if (
|
|
5094
|
+
if (existsSync9(file)) {
|
|
4861
5095
|
try {
|
|
4862
5096
|
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4863
5097
|
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
@@ -4865,7 +5099,7 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
4865
5099
|
} catch {
|
|
4866
5100
|
}
|
|
4867
5101
|
try {
|
|
4868
|
-
|
|
5102
|
+
unlinkSync4(file);
|
|
4869
5103
|
} catch {
|
|
4870
5104
|
}
|
|
4871
5105
|
}
|
|
@@ -4879,12 +5113,12 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
4879
5113
|
function releaseJobLock(type) {
|
|
4880
5114
|
const file = lockPath(type);
|
|
4881
5115
|
try {
|
|
4882
|
-
if (!
|
|
5116
|
+
if (!existsSync9(file)) return;
|
|
4883
5117
|
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4884
|
-
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid))
|
|
5118
|
+
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync4(file);
|
|
4885
5119
|
} catch {
|
|
4886
5120
|
try {
|
|
4887
|
-
|
|
5121
|
+
unlinkSync4(file);
|
|
4888
5122
|
} catch {
|
|
4889
5123
|
}
|
|
4890
5124
|
}
|