@askexenow/exe-os 0.9.102 → 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 +12 -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 +1 -1
package/dist/lib/store.js
CHANGED
|
@@ -1457,9 +1457,79 @@ __export(database_exports, {
|
|
|
1457
1457
|
isInitialized: () => isInitialized,
|
|
1458
1458
|
setExternalClient: () => setExternalClient
|
|
1459
1459
|
});
|
|
1460
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
1460
|
+
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";
|
|
1461
1461
|
import { createClient } from "@libsql/client";
|
|
1462
|
+
import { homedir } from "os";
|
|
1463
|
+
import { join } from "path";
|
|
1464
|
+
function logCatchDebug(context, err) {
|
|
1465
|
+
if (_debugDb) {
|
|
1466
|
+
process.stderr.write(
|
|
1467
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
1468
|
+
`
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
function acquireDbLock() {
|
|
1473
|
+
mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
|
|
1474
|
+
try {
|
|
1475
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1476
|
+
} catch (err) {
|
|
1477
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
1478
|
+
try {
|
|
1479
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
1480
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
1481
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1482
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1483
|
+
return;
|
|
1484
|
+
}
|
|
1485
|
+
} catch (e) {
|
|
1486
|
+
logCatchDebug("stale lock check", e);
|
|
1487
|
+
}
|
|
1488
|
+
process.stderr.write(
|
|
1489
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
1490
|
+
);
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
throw err;
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
function releaseDbLock() {
|
|
1497
|
+
if (_lockFd !== null) {
|
|
1498
|
+
try {
|
|
1499
|
+
closeSync2(_lockFd);
|
|
1500
|
+
} catch (e) {
|
|
1501
|
+
logCatchDebug("lock close", e);
|
|
1502
|
+
}
|
|
1503
|
+
_lockFd = null;
|
|
1504
|
+
}
|
|
1505
|
+
try {
|
|
1506
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1507
|
+
} catch (e) {
|
|
1508
|
+
logCatchDebug("lock unlink", e);
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1462
1511
|
async function initDatabase(config) {
|
|
1512
|
+
acquireDbLock();
|
|
1513
|
+
if (existsSync6(config.dbPath)) {
|
|
1514
|
+
const dbStat = statSync2(config.dbPath);
|
|
1515
|
+
if (dbStat.size === 0) {
|
|
1516
|
+
const walPath = config.dbPath + "-wal";
|
|
1517
|
+
if (existsSync6(walPath) && statSync2(walPath).size > 0) {
|
|
1518
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
1519
|
+
copyFileSync(config.dbPath, backupPath);
|
|
1520
|
+
unlinkSync3(config.dbPath);
|
|
1521
|
+
process.stderr.write(
|
|
1522
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
1523
|
+
`
|
|
1524
|
+
);
|
|
1525
|
+
} else {
|
|
1526
|
+
process.stderr.write(
|
|
1527
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
1528
|
+
`
|
|
1529
|
+
);
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
}
|
|
1463
1533
|
if (_walCheckpointTimer) {
|
|
1464
1534
|
clearInterval(_walCheckpointTimer);
|
|
1465
1535
|
_walCheckpointTimer = null;
|
|
@@ -1486,10 +1556,8 @@ async function initDatabase(config) {
|
|
|
1486
1556
|
_client = createClient(opts);
|
|
1487
1557
|
_resilientClient = wrapWithRetry(_client);
|
|
1488
1558
|
_adapterClient = _resilientClient;
|
|
1489
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
1490
|
-
|
|
1491
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
1492
|
-
});
|
|
1559
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
1560
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
1493
1561
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
1494
1562
|
_walCheckpointTimer = setInterval(() => {
|
|
1495
1563
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -1504,11 +1572,16 @@ async function initDatabase(config) {
|
|
|
1504
1572
|
for (const suffix of ["-wal", "-shm"]) {
|
|
1505
1573
|
try {
|
|
1506
1574
|
chmodSync2(config.dbPath + suffix, 384);
|
|
1507
|
-
} catch {
|
|
1575
|
+
} catch (chmodErr) {
|
|
1576
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1577
|
+
`);
|
|
1508
1578
|
}
|
|
1509
1579
|
}
|
|
1510
|
-
} catch {
|
|
1580
|
+
} catch (chmodErr) {
|
|
1581
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1582
|
+
`);
|
|
1511
1583
|
}
|
|
1584
|
+
releaseDbLock();
|
|
1512
1585
|
}
|
|
1513
1586
|
function isInitialized() {
|
|
1514
1587
|
return _adapterClient !== null || _client !== null;
|
|
@@ -1563,7 +1636,8 @@ async function ensureSchema() {
|
|
|
1563
1636
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
1564
1637
|
try {
|
|
1565
1638
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1566
|
-
} catch {
|
|
1639
|
+
} catch (e) {
|
|
1640
|
+
logCatchDebug("migration", e);
|
|
1567
1641
|
}
|
|
1568
1642
|
await client.executeMultiple(`
|
|
1569
1643
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -1628,6 +1702,23 @@ async function ensureSchema() {
|
|
|
1628
1702
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
1629
1703
|
END;
|
|
1630
1704
|
`);
|
|
1705
|
+
try {
|
|
1706
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
1707
|
+
} catch (ftsErr) {
|
|
1708
|
+
process.stderr.write(
|
|
1709
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
1710
|
+
`
|
|
1711
|
+
);
|
|
1712
|
+
try {
|
|
1713
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
1714
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
1715
|
+
} catch (rebuildErr) {
|
|
1716
|
+
process.stderr.write(
|
|
1717
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
1718
|
+
`
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1631
1722
|
await client.executeMultiple(`
|
|
1632
1723
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
1633
1724
|
key TEXT PRIMARY KEY,
|
|
@@ -1686,35 +1777,40 @@ async function ensureSchema() {
|
|
|
1686
1777
|
});
|
|
1687
1778
|
}
|
|
1688
1779
|
}
|
|
1689
|
-
} catch {
|
|
1780
|
+
} catch (seedErr) {
|
|
1781
|
+
logCatchDebug("behavior seed", seedErr);
|
|
1690
1782
|
}
|
|
1691
1783
|
try {
|
|
1692
1784
|
await client.execute({
|
|
1693
1785
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
1694
1786
|
args: []
|
|
1695
1787
|
});
|
|
1696
|
-
} catch {
|
|
1788
|
+
} catch (e) {
|
|
1789
|
+
logCatchDebug("migration", e);
|
|
1697
1790
|
}
|
|
1698
1791
|
try {
|
|
1699
1792
|
await client.execute({
|
|
1700
1793
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
1701
1794
|
args: []
|
|
1702
1795
|
});
|
|
1703
|
-
} catch {
|
|
1796
|
+
} catch (e) {
|
|
1797
|
+
logCatchDebug("migration", e);
|
|
1704
1798
|
}
|
|
1705
1799
|
try {
|
|
1706
1800
|
await client.execute({
|
|
1707
1801
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
1708
1802
|
args: []
|
|
1709
1803
|
});
|
|
1710
|
-
} catch {
|
|
1804
|
+
} catch (e) {
|
|
1805
|
+
logCatchDebug("migration", e);
|
|
1711
1806
|
}
|
|
1712
1807
|
try {
|
|
1713
1808
|
await client.execute({
|
|
1714
1809
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
1715
1810
|
args: []
|
|
1716
1811
|
});
|
|
1717
|
-
} catch {
|
|
1812
|
+
} catch (e) {
|
|
1813
|
+
logCatchDebug("migration", e);
|
|
1718
1814
|
}
|
|
1719
1815
|
try {
|
|
1720
1816
|
await client.execute({
|
|
@@ -1723,98 +1819,112 @@ async function ensureSchema() {
|
|
|
1723
1819
|
WHERE parent_task_id IS NOT NULL`,
|
|
1724
1820
|
args: []
|
|
1725
1821
|
});
|
|
1726
|
-
} catch {
|
|
1822
|
+
} catch (e) {
|
|
1823
|
+
logCatchDebug("migration", e);
|
|
1727
1824
|
}
|
|
1728
1825
|
try {
|
|
1729
1826
|
await client.execute({
|
|
1730
1827
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
1731
1828
|
args: []
|
|
1732
1829
|
});
|
|
1733
|
-
} catch {
|
|
1830
|
+
} catch (e) {
|
|
1831
|
+
logCatchDebug("migration", e);
|
|
1734
1832
|
}
|
|
1735
1833
|
try {
|
|
1736
1834
|
await client.execute({
|
|
1737
1835
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
1738
1836
|
args: []
|
|
1739
1837
|
});
|
|
1740
|
-
} catch {
|
|
1838
|
+
} catch (e) {
|
|
1839
|
+
logCatchDebug("migration", e);
|
|
1741
1840
|
}
|
|
1742
1841
|
try {
|
|
1743
1842
|
await client.execute({
|
|
1744
1843
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
1745
1844
|
args: []
|
|
1746
1845
|
});
|
|
1747
|
-
} catch {
|
|
1846
|
+
} catch (e) {
|
|
1847
|
+
logCatchDebug("migration", e);
|
|
1748
1848
|
}
|
|
1749
1849
|
try {
|
|
1750
1850
|
await client.execute({
|
|
1751
1851
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
1752
1852
|
args: []
|
|
1753
1853
|
});
|
|
1754
|
-
} catch {
|
|
1854
|
+
} catch (e) {
|
|
1855
|
+
logCatchDebug("migration", e);
|
|
1755
1856
|
}
|
|
1756
1857
|
try {
|
|
1757
1858
|
await client.execute({
|
|
1758
1859
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
1759
1860
|
args: []
|
|
1760
1861
|
});
|
|
1761
|
-
} catch {
|
|
1862
|
+
} catch (e) {
|
|
1863
|
+
logCatchDebug("migration", e);
|
|
1762
1864
|
}
|
|
1763
1865
|
try {
|
|
1764
1866
|
await client.execute({
|
|
1765
1867
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
1766
1868
|
args: []
|
|
1767
1869
|
});
|
|
1768
|
-
} catch {
|
|
1870
|
+
} catch (e) {
|
|
1871
|
+
logCatchDebug("migration", e);
|
|
1769
1872
|
}
|
|
1770
1873
|
try {
|
|
1771
1874
|
await client.execute({
|
|
1772
1875
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
1773
1876
|
args: []
|
|
1774
1877
|
});
|
|
1775
|
-
} catch {
|
|
1878
|
+
} catch (e) {
|
|
1879
|
+
logCatchDebug("migration", e);
|
|
1776
1880
|
}
|
|
1777
1881
|
try {
|
|
1778
1882
|
await client.execute({
|
|
1779
1883
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
1780
1884
|
args: []
|
|
1781
1885
|
});
|
|
1782
|
-
} catch {
|
|
1886
|
+
} catch (e) {
|
|
1887
|
+
logCatchDebug("migration", e);
|
|
1783
1888
|
}
|
|
1784
1889
|
try {
|
|
1785
1890
|
await client.execute({
|
|
1786
1891
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
1787
1892
|
args: []
|
|
1788
1893
|
});
|
|
1789
|
-
} catch {
|
|
1894
|
+
} catch (e) {
|
|
1895
|
+
logCatchDebug("migration", e);
|
|
1790
1896
|
}
|
|
1791
1897
|
try {
|
|
1792
1898
|
await client.execute({
|
|
1793
1899
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
1794
1900
|
args: []
|
|
1795
1901
|
});
|
|
1796
|
-
} catch {
|
|
1902
|
+
} catch (e) {
|
|
1903
|
+
logCatchDebug("migration", e);
|
|
1797
1904
|
}
|
|
1798
1905
|
try {
|
|
1799
1906
|
await client.execute({
|
|
1800
1907
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
1801
1908
|
args: []
|
|
1802
1909
|
});
|
|
1803
|
-
} catch {
|
|
1910
|
+
} catch (e) {
|
|
1911
|
+
logCatchDebug("migration", e);
|
|
1804
1912
|
}
|
|
1805
1913
|
try {
|
|
1806
1914
|
await client.execute({
|
|
1807
1915
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
1808
1916
|
args: []
|
|
1809
1917
|
});
|
|
1810
|
-
} catch {
|
|
1918
|
+
} catch (e) {
|
|
1919
|
+
logCatchDebug("migration", e);
|
|
1811
1920
|
}
|
|
1812
1921
|
try {
|
|
1813
1922
|
await client.execute({
|
|
1814
1923
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
1815
1924
|
args: []
|
|
1816
1925
|
});
|
|
1817
|
-
} catch {
|
|
1926
|
+
} catch (e) {
|
|
1927
|
+
logCatchDebug("migration", e);
|
|
1818
1928
|
}
|
|
1819
1929
|
await client.executeMultiple(`
|
|
1820
1930
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -1919,14 +2029,16 @@ async function ensureSchema() {
|
|
|
1919
2029
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
1920
2030
|
args: []
|
|
1921
2031
|
});
|
|
1922
|
-
} catch {
|
|
2032
|
+
} catch (e) {
|
|
2033
|
+
logCatchDebug("migration", e);
|
|
1923
2034
|
}
|
|
1924
2035
|
try {
|
|
1925
2036
|
await client.execute({
|
|
1926
2037
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
1927
2038
|
args: []
|
|
1928
2039
|
});
|
|
1929
|
-
} catch {
|
|
2040
|
+
} catch (e) {
|
|
2041
|
+
logCatchDebug("migration", e);
|
|
1930
2042
|
}
|
|
1931
2043
|
await client.executeMultiple(`
|
|
1932
2044
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -1952,7 +2064,8 @@ async function ensureSchema() {
|
|
|
1952
2064
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
1953
2065
|
args: []
|
|
1954
2066
|
});
|
|
1955
|
-
} catch {
|
|
2067
|
+
} catch (e) {
|
|
2068
|
+
logCatchDebug("migration", e);
|
|
1956
2069
|
}
|
|
1957
2070
|
await client.executeMultiple(`
|
|
1958
2071
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -1976,7 +2089,8 @@ async function ensureSchema() {
|
|
|
1976
2089
|
`);
|
|
1977
2090
|
try {
|
|
1978
2091
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
1979
|
-
} catch {
|
|
2092
|
+
} catch (e) {
|
|
2093
|
+
logCatchDebug("migration", e);
|
|
1980
2094
|
}
|
|
1981
2095
|
await client.executeMultiple(`
|
|
1982
2096
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2013,63 +2127,72 @@ async function ensureSchema() {
|
|
|
2013
2127
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2014
2128
|
args: []
|
|
2015
2129
|
});
|
|
2016
|
-
} catch {
|
|
2130
|
+
} catch (e) {
|
|
2131
|
+
logCatchDebug("migration", e);
|
|
2017
2132
|
}
|
|
2018
2133
|
try {
|
|
2019
2134
|
await client.execute({
|
|
2020
2135
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2021
2136
|
args: []
|
|
2022
2137
|
});
|
|
2023
|
-
} catch {
|
|
2138
|
+
} catch (e) {
|
|
2139
|
+
logCatchDebug("migration", e);
|
|
2024
2140
|
}
|
|
2025
2141
|
try {
|
|
2026
2142
|
await client.execute({
|
|
2027
2143
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2028
2144
|
args: []
|
|
2029
2145
|
});
|
|
2030
|
-
} catch {
|
|
2146
|
+
} catch (e) {
|
|
2147
|
+
logCatchDebug("migration", e);
|
|
2031
2148
|
}
|
|
2032
2149
|
try {
|
|
2033
2150
|
await client.execute({
|
|
2034
2151
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2035
2152
|
args: []
|
|
2036
2153
|
});
|
|
2037
|
-
} catch {
|
|
2154
|
+
} catch (e) {
|
|
2155
|
+
logCatchDebug("migration", e);
|
|
2038
2156
|
}
|
|
2039
2157
|
try {
|
|
2040
2158
|
await client.execute({
|
|
2041
2159
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2042
2160
|
args: []
|
|
2043
2161
|
});
|
|
2044
|
-
} catch {
|
|
2162
|
+
} catch (e) {
|
|
2163
|
+
logCatchDebug("migration", e);
|
|
2045
2164
|
}
|
|
2046
2165
|
try {
|
|
2047
2166
|
await client.execute({
|
|
2048
2167
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2049
2168
|
args: []
|
|
2050
2169
|
});
|
|
2051
|
-
} catch {
|
|
2170
|
+
} catch (e) {
|
|
2171
|
+
logCatchDebug("migration", e);
|
|
2052
2172
|
}
|
|
2053
2173
|
try {
|
|
2054
2174
|
await client.execute({
|
|
2055
2175
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2056
2176
|
args: []
|
|
2057
2177
|
});
|
|
2058
|
-
} catch {
|
|
2178
|
+
} catch (e) {
|
|
2179
|
+
logCatchDebug("migration", e);
|
|
2059
2180
|
}
|
|
2060
2181
|
try {
|
|
2061
2182
|
await client.execute({
|
|
2062
2183
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2063
2184
|
args: []
|
|
2064
2185
|
});
|
|
2065
|
-
} catch {
|
|
2186
|
+
} catch (e) {
|
|
2187
|
+
logCatchDebug("migration", e);
|
|
2066
2188
|
}
|
|
2067
2189
|
try {
|
|
2068
2190
|
await client.execute({
|
|
2069
2191
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2070
2192
|
args: []
|
|
2071
2193
|
});
|
|
2072
|
-
} catch {
|
|
2194
|
+
} catch (e) {
|
|
2195
|
+
logCatchDebug("migration", e);
|
|
2073
2196
|
}
|
|
2074
2197
|
for (const col of [
|
|
2075
2198
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2077,14 +2200,16 @@ async function ensureSchema() {
|
|
|
2077
2200
|
]) {
|
|
2078
2201
|
try {
|
|
2079
2202
|
await client.execute(col);
|
|
2080
|
-
} catch {
|
|
2203
|
+
} catch (e) {
|
|
2204
|
+
logCatchDebug("migration", e);
|
|
2081
2205
|
}
|
|
2082
2206
|
}
|
|
2083
2207
|
try {
|
|
2084
2208
|
await client.execute(
|
|
2085
2209
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2086
2210
|
);
|
|
2087
|
-
} catch {
|
|
2211
|
+
} catch (e) {
|
|
2212
|
+
logCatchDebug("migration", e);
|
|
2088
2213
|
}
|
|
2089
2214
|
try {
|
|
2090
2215
|
await client.execute(
|
|
@@ -2092,7 +2217,8 @@ async function ensureSchema() {
|
|
|
2092
2217
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2093
2218
|
WHERE content_hash IS NOT NULL`
|
|
2094
2219
|
);
|
|
2095
|
-
} catch {
|
|
2220
|
+
} catch (e) {
|
|
2221
|
+
logCatchDebug("migration", e);
|
|
2096
2222
|
}
|
|
2097
2223
|
await client.executeMultiple(`
|
|
2098
2224
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2168,7 +2294,8 @@ async function ensureSchema() {
|
|
|
2168
2294
|
`);
|
|
2169
2295
|
try {
|
|
2170
2296
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2171
|
-
} catch {
|
|
2297
|
+
} catch (e) {
|
|
2298
|
+
logCatchDebug("migration", e);
|
|
2172
2299
|
}
|
|
2173
2300
|
await client.executeMultiple(`
|
|
2174
2301
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2183,14 +2310,16 @@ async function ensureSchema() {
|
|
|
2183
2310
|
]) {
|
|
2184
2311
|
try {
|
|
2185
2312
|
await client.execute(col);
|
|
2186
|
-
} catch {
|
|
2313
|
+
} catch (e) {
|
|
2314
|
+
logCatchDebug("migration", e);
|
|
2187
2315
|
}
|
|
2188
2316
|
}
|
|
2189
2317
|
try {
|
|
2190
2318
|
await client.execute(
|
|
2191
2319
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2192
2320
|
);
|
|
2193
|
-
} catch {
|
|
2321
|
+
} catch (e) {
|
|
2322
|
+
logCatchDebug("migration", e);
|
|
2194
2323
|
}
|
|
2195
2324
|
await client.executeMultiple(`
|
|
2196
2325
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2289,7 +2418,8 @@ async function ensureSchema() {
|
|
|
2289
2418
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2290
2419
|
args: []
|
|
2291
2420
|
});
|
|
2292
|
-
} catch {
|
|
2421
|
+
} catch (e) {
|
|
2422
|
+
logCatchDebug("migration", e);
|
|
2293
2423
|
}
|
|
2294
2424
|
}
|
|
2295
2425
|
for (const col of [
|
|
@@ -2298,7 +2428,8 @@ async function ensureSchema() {
|
|
|
2298
2428
|
]) {
|
|
2299
2429
|
try {
|
|
2300
2430
|
await client.execute(col);
|
|
2301
|
-
} catch {
|
|
2431
|
+
} catch (e) {
|
|
2432
|
+
logCatchDebug("migration", e);
|
|
2302
2433
|
}
|
|
2303
2434
|
}
|
|
2304
2435
|
await client.executeMultiple(`
|
|
@@ -2483,56 +2614,64 @@ async function ensureSchema() {
|
|
|
2483
2614
|
args: []
|
|
2484
2615
|
});
|
|
2485
2616
|
}
|
|
2486
|
-
} catch {
|
|
2617
|
+
} catch (e) {
|
|
2618
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
2487
2619
|
}
|
|
2488
2620
|
try {
|
|
2489
2621
|
await client.execute({
|
|
2490
2622
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
2491
2623
|
args: []
|
|
2492
2624
|
});
|
|
2493
|
-
} catch {
|
|
2625
|
+
} catch (e) {
|
|
2626
|
+
logCatchDebug("migration", e);
|
|
2494
2627
|
}
|
|
2495
2628
|
try {
|
|
2496
2629
|
await client.execute({
|
|
2497
2630
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
2498
2631
|
args: []
|
|
2499
2632
|
});
|
|
2500
|
-
} catch {
|
|
2633
|
+
} catch (e) {
|
|
2634
|
+
logCatchDebug("migration", e);
|
|
2501
2635
|
}
|
|
2502
2636
|
try {
|
|
2503
2637
|
await client.execute({
|
|
2504
2638
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
2505
2639
|
args: []
|
|
2506
2640
|
});
|
|
2507
|
-
} catch {
|
|
2641
|
+
} catch (e) {
|
|
2642
|
+
logCatchDebug("migration", e);
|
|
2508
2643
|
}
|
|
2509
2644
|
try {
|
|
2510
2645
|
await client.execute({
|
|
2511
2646
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
2512
2647
|
args: []
|
|
2513
2648
|
});
|
|
2514
|
-
} catch {
|
|
2649
|
+
} catch (e) {
|
|
2650
|
+
logCatchDebug("migration", e);
|
|
2515
2651
|
}
|
|
2516
2652
|
try {
|
|
2517
2653
|
await client.execute({
|
|
2518
2654
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
2519
2655
|
args: []
|
|
2520
2656
|
});
|
|
2521
|
-
} catch {
|
|
2657
|
+
} catch (e) {
|
|
2658
|
+
logCatchDebug("migration", e);
|
|
2522
2659
|
}
|
|
2523
2660
|
try {
|
|
2524
2661
|
await client.execute({
|
|
2525
2662
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2526
2663
|
args: []
|
|
2527
2664
|
});
|
|
2528
|
-
} catch {
|
|
2665
|
+
} catch (e) {
|
|
2666
|
+
logCatchDebug("migration", e);
|
|
2529
2667
|
}
|
|
2530
2668
|
try {
|
|
2531
2669
|
await client.execute({
|
|
2532
2670
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2533
2671
|
args: []
|
|
2534
2672
|
});
|
|
2535
|
-
} catch {
|
|
2673
|
+
} catch (e) {
|
|
2674
|
+
logCatchDebug("migration", e);
|
|
2536
2675
|
}
|
|
2537
2676
|
await client.executeMultiple(`
|
|
2538
2677
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -2731,13 +2870,15 @@ async function ensureSchema() {
|
|
|
2731
2870
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
2732
2871
|
args: []
|
|
2733
2872
|
});
|
|
2734
|
-
} catch {
|
|
2873
|
+
} catch (e) {
|
|
2874
|
+
logCatchDebug("migration", e);
|
|
2735
2875
|
}
|
|
2736
2876
|
try {
|
|
2737
2877
|
await client.execute(
|
|
2738
2878
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
2739
2879
|
);
|
|
2740
|
-
} catch {
|
|
2880
|
+
} catch (e) {
|
|
2881
|
+
logCatchDebug("migration", e);
|
|
2741
2882
|
}
|
|
2742
2883
|
try {
|
|
2743
2884
|
await client.execute({
|
|
@@ -2748,20 +2889,23 @@ async function ensureSchema() {
|
|
|
2748
2889
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
2749
2890
|
args: []
|
|
2750
2891
|
});
|
|
2751
|
-
} catch {
|
|
2892
|
+
} catch (e) {
|
|
2893
|
+
logCatchDebug("migration", e);
|
|
2752
2894
|
}
|
|
2753
2895
|
try {
|
|
2754
2896
|
await client.execute({
|
|
2755
2897
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
2756
2898
|
args: []
|
|
2757
2899
|
});
|
|
2758
|
-
} catch {
|
|
2900
|
+
} catch (e) {
|
|
2901
|
+
logCatchDebug("migration", e);
|
|
2759
2902
|
}
|
|
2760
2903
|
try {
|
|
2761
2904
|
await client.execute(
|
|
2762
2905
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
2763
2906
|
);
|
|
2764
|
-
} catch {
|
|
2907
|
+
} catch (e) {
|
|
2908
|
+
logCatchDebug("migration", e);
|
|
2765
2909
|
}
|
|
2766
2910
|
for (const col of [
|
|
2767
2911
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -2769,7 +2913,8 @@ async function ensureSchema() {
|
|
|
2769
2913
|
]) {
|
|
2770
2914
|
try {
|
|
2771
2915
|
await client.execute(col);
|
|
2772
|
-
} catch {
|
|
2916
|
+
} catch (e) {
|
|
2917
|
+
logCatchDebug("migration", e);
|
|
2773
2918
|
}
|
|
2774
2919
|
}
|
|
2775
2920
|
try {
|
|
@@ -2777,13 +2922,15 @@ async function ensureSchema() {
|
|
|
2777
2922
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
2778
2923
|
args: []
|
|
2779
2924
|
});
|
|
2780
|
-
} catch {
|
|
2925
|
+
} catch (e) {
|
|
2926
|
+
logCatchDebug("migration", e);
|
|
2781
2927
|
}
|
|
2782
2928
|
try {
|
|
2783
2929
|
await client.execute(
|
|
2784
2930
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
2785
2931
|
);
|
|
2786
|
-
} catch {
|
|
2932
|
+
} catch (e) {
|
|
2933
|
+
logCatchDebug("migration", e);
|
|
2787
2934
|
}
|
|
2788
2935
|
for (const col of [
|
|
2789
2936
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -2791,7 +2938,8 @@ async function ensureSchema() {
|
|
|
2791
2938
|
]) {
|
|
2792
2939
|
try {
|
|
2793
2940
|
await client.execute(col);
|
|
2794
|
-
} catch {
|
|
2941
|
+
} catch (e) {
|
|
2942
|
+
logCatchDebug("migration", e);
|
|
2795
2943
|
}
|
|
2796
2944
|
}
|
|
2797
2945
|
try {
|
|
@@ -2799,27 +2947,31 @@ async function ensureSchema() {
|
|
|
2799
2947
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
2800
2948
|
args: []
|
|
2801
2949
|
});
|
|
2802
|
-
} catch {
|
|
2950
|
+
} catch (e) {
|
|
2951
|
+
logCatchDebug("migration", e);
|
|
2803
2952
|
}
|
|
2804
2953
|
try {
|
|
2805
2954
|
await client.execute({
|
|
2806
2955
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
2807
2956
|
args: []
|
|
2808
2957
|
});
|
|
2809
|
-
} catch {
|
|
2958
|
+
} catch (e) {
|
|
2959
|
+
logCatchDebug("migration", e);
|
|
2810
2960
|
}
|
|
2811
2961
|
try {
|
|
2812
2962
|
await client.execute(
|
|
2813
2963
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
2814
2964
|
);
|
|
2815
|
-
} catch {
|
|
2965
|
+
} catch (e) {
|
|
2966
|
+
logCatchDebug("migration", e);
|
|
2816
2967
|
}
|
|
2817
2968
|
try {
|
|
2818
2969
|
await client.execute({
|
|
2819
2970
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
2820
2971
|
args: []
|
|
2821
2972
|
});
|
|
2822
|
-
} catch {
|
|
2973
|
+
} catch (e) {
|
|
2974
|
+
logCatchDebug("migration", e);
|
|
2823
2975
|
}
|
|
2824
2976
|
for (const col of [
|
|
2825
2977
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -2840,7 +2992,8 @@ async function ensureSchema() {
|
|
|
2840
2992
|
]) {
|
|
2841
2993
|
try {
|
|
2842
2994
|
await client.execute(col);
|
|
2843
|
-
} catch {
|
|
2995
|
+
} catch (e) {
|
|
2996
|
+
logCatchDebug("migration", e);
|
|
2844
2997
|
}
|
|
2845
2998
|
}
|
|
2846
2999
|
try {
|
|
@@ -2848,14 +3001,16 @@ async function ensureSchema() {
|
|
|
2848
3001
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
2849
3002
|
args: []
|
|
2850
3003
|
});
|
|
2851
|
-
} catch {
|
|
3004
|
+
} catch (e) {
|
|
3005
|
+
logCatchDebug("migration", e);
|
|
2852
3006
|
}
|
|
2853
3007
|
try {
|
|
2854
3008
|
await client.execute({
|
|
2855
3009
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
2856
3010
|
args: []
|
|
2857
3011
|
});
|
|
2858
|
-
} catch {
|
|
3012
|
+
} catch (e) {
|
|
3013
|
+
logCatchDebug("migration", e);
|
|
2859
3014
|
}
|
|
2860
3015
|
}
|
|
2861
3016
|
async function disposeDatabase() {
|
|
@@ -2866,7 +3021,8 @@ async function disposeDatabase() {
|
|
|
2866
3021
|
if (_client) {
|
|
2867
3022
|
try {
|
|
2868
3023
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
2869
|
-
} catch {
|
|
3024
|
+
} catch (e) {
|
|
3025
|
+
logCatchDebug("WAL checkpoint", e);
|
|
2870
3026
|
}
|
|
2871
3027
|
}
|
|
2872
3028
|
if (_daemonClient) {
|
|
@@ -2882,8 +3038,9 @@ async function disposeDatabase() {
|
|
|
2882
3038
|
_client = null;
|
|
2883
3039
|
_resilientClient = null;
|
|
2884
3040
|
}
|
|
3041
|
+
releaseDbLock();
|
|
2885
3042
|
}
|
|
2886
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3043
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
2887
3044
|
var init_database = __esm({
|
|
2888
3045
|
"src/lib/database.ts"() {
|
|
2889
3046
|
"use strict";
|
|
@@ -2891,11 +3048,14 @@ var init_database = __esm({
|
|
|
2891
3048
|
init_employees();
|
|
2892
3049
|
init_database_adapter();
|
|
2893
3050
|
init_memory();
|
|
3051
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
2894
3052
|
_client = null;
|
|
2895
3053
|
_resilientClient = null;
|
|
2896
3054
|
_walCheckpointTimer = null;
|
|
2897
3055
|
_daemonClient = null;
|
|
2898
3056
|
_adapterClient = null;
|
|
3057
|
+
_lockFd = null;
|
|
3058
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
2899
3059
|
initTurso = initDatabase;
|
|
2900
3060
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
2901
3061
|
disposeTurso = disposeDatabase;
|
|
@@ -2918,18 +3078,54 @@ __export(shard_manager_exports, {
|
|
|
2918
3078
|
shardExists: () => shardExists
|
|
2919
3079
|
});
|
|
2920
3080
|
import path7 from "path";
|
|
2921
|
-
import { existsSync as
|
|
3081
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
2922
3082
|
import { createClient as createClient2 } from "@libsql/client";
|
|
2923
3083
|
function initShardManager(encryptionKey) {
|
|
2924
3084
|
_encryptionKey = encryptionKey;
|
|
2925
|
-
|
|
2926
|
-
|
|
3085
|
+
_keyValidated = false;
|
|
3086
|
+
_keyValidationPromise = null;
|
|
3087
|
+
if (!existsSync8(SHARDS_DIR)) {
|
|
3088
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
3089
|
+
}
|
|
3090
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3091
|
+
if (existingShards.length === 0) {
|
|
3092
|
+
_keyValidated = true;
|
|
2927
3093
|
}
|
|
2928
3094
|
_shardingEnabled = true;
|
|
2929
3095
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
2930
3096
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
2931
3097
|
_evictionTimer.unref();
|
|
2932
3098
|
}
|
|
3099
|
+
async function validateEncryptionKey() {
|
|
3100
|
+
if (_keyValidated) return true;
|
|
3101
|
+
if (!_encryptionKey) return false;
|
|
3102
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3103
|
+
if (existingShards.length === 0) {
|
|
3104
|
+
_keyValidated = true;
|
|
3105
|
+
return true;
|
|
3106
|
+
}
|
|
3107
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
3108
|
+
const dbPath = path7.join(SHARDS_DIR, shardFile);
|
|
3109
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
3110
|
+
try {
|
|
3111
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
3112
|
+
testClient.close();
|
|
3113
|
+
_keyValidated = true;
|
|
3114
|
+
return true;
|
|
3115
|
+
} catch {
|
|
3116
|
+
try {
|
|
3117
|
+
testClient.close();
|
|
3118
|
+
} catch {
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
3122
|
+
process.stderr.write(
|
|
3123
|
+
`[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.
|
|
3124
|
+
`
|
|
3125
|
+
);
|
|
3126
|
+
_shardingEnabled = false;
|
|
3127
|
+
return false;
|
|
3128
|
+
}
|
|
2933
3129
|
function isShardingEnabled() {
|
|
2934
3130
|
return _shardingEnabled;
|
|
2935
3131
|
}
|
|
@@ -2963,13 +3159,13 @@ function getShardClient(projectName) {
|
|
|
2963
3159
|
}
|
|
2964
3160
|
function shardExists(projectName) {
|
|
2965
3161
|
const safeName = safeShardName(projectName);
|
|
2966
|
-
return
|
|
3162
|
+
return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
2967
3163
|
}
|
|
2968
3164
|
function safeShardName(projectName) {
|
|
2969
3165
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2970
3166
|
}
|
|
2971
3167
|
function listShards() {
|
|
2972
|
-
if (!
|
|
3168
|
+
if (!existsSync8(SHARDS_DIR)) return [];
|
|
2973
3169
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
2974
3170
|
}
|
|
2975
3171
|
async function auditShardHealth(options = {}) {
|
|
@@ -2982,7 +3178,7 @@ async function auditShardHealth(options = {}) {
|
|
|
2982
3178
|
const shards = [];
|
|
2983
3179
|
for (const name of names) {
|
|
2984
3180
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
2985
|
-
const stat =
|
|
3181
|
+
const stat = statSync4(dbPath);
|
|
2986
3182
|
const item = {
|
|
2987
3183
|
name,
|
|
2988
3184
|
path: dbPath,
|
|
@@ -3222,6 +3418,17 @@ async function ensureShardSchema(client) {
|
|
|
3222
3418
|
}
|
|
3223
3419
|
}
|
|
3224
3420
|
async function getReadyShardClient(projectName) {
|
|
3421
|
+
if (!_keyValidated) {
|
|
3422
|
+
if (!_keyValidationPromise) {
|
|
3423
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
3424
|
+
}
|
|
3425
|
+
const valid = await _keyValidationPromise;
|
|
3426
|
+
if (!valid) {
|
|
3427
|
+
throw new Error(
|
|
3428
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
3429
|
+
);
|
|
3430
|
+
}
|
|
3431
|
+
}
|
|
3225
3432
|
const safeName = safeShardName(projectName);
|
|
3226
3433
|
let client = getShardClient(projectName);
|
|
3227
3434
|
try {
|
|
@@ -3234,8 +3441,8 @@ async function getReadyShardClient(projectName) {
|
|
|
3234
3441
|
_shards.delete(safeName);
|
|
3235
3442
|
_shardLastAccess.delete(safeName);
|
|
3236
3443
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3237
|
-
if (
|
|
3238
|
-
const stat =
|
|
3444
|
+
if (existsSync8(dbPath)) {
|
|
3445
|
+
const stat = statSync4(dbPath);
|
|
3239
3446
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3240
3447
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3241
3448
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3300,7 +3507,7 @@ function disposeShards() {
|
|
|
3300
3507
|
_shardingEnabled = false;
|
|
3301
3508
|
_encryptionKey = null;
|
|
3302
3509
|
}
|
|
3303
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
3510
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
3304
3511
|
var init_shard_manager = __esm({
|
|
3305
3512
|
"src/lib/shard-manager.ts"() {
|
|
3306
3513
|
"use strict";
|
|
@@ -3314,6 +3521,8 @@ var init_shard_manager = __esm({
|
|
|
3314
3521
|
_evictionTimer = null;
|
|
3315
3522
|
_encryptionKey = null;
|
|
3316
3523
|
_shardingEnabled = false;
|
|
3524
|
+
_keyValidated = false;
|
|
3525
|
+
_keyValidationPromise = null;
|
|
3317
3526
|
}
|
|
3318
3527
|
});
|
|
3319
3528
|
|
|
@@ -3509,6 +3718,18 @@ var init_platform_procedures = __esm({
|
|
|
3509
3718
|
priority: "p0",
|
|
3510
3719
|
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.'"
|
|
3511
3720
|
},
|
|
3721
|
+
{
|
|
3722
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
3723
|
+
domain: "workflow",
|
|
3724
|
+
priority: "p0",
|
|
3725
|
+
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."
|
|
3726
|
+
},
|
|
3727
|
+
{
|
|
3728
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
3729
|
+
domain: "workflow",
|
|
3730
|
+
priority: "p0",
|
|
3731
|
+
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."
|
|
3732
|
+
},
|
|
3512
3733
|
{
|
|
3513
3734
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
3514
3735
|
domain: "architecture",
|
|
@@ -4094,7 +4315,7 @@ init_database();
|
|
|
4094
4315
|
|
|
4095
4316
|
// src/lib/keychain.ts
|
|
4096
4317
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4097
|
-
import { existsSync as
|
|
4318
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
4098
4319
|
import { execSync as execSync3 } from "child_process";
|
|
4099
4320
|
import path6 from "path";
|
|
4100
4321
|
import os5 from "os";
|
|
@@ -4133,7 +4354,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
4133
4354
|
if (process.platform !== "linux") return false;
|
|
4134
4355
|
try {
|
|
4135
4356
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4136
|
-
const st =
|
|
4357
|
+
const st = statSync3(keyPath);
|
|
4137
4358
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4138
4359
|
if (uid === 0) return true;
|
|
4139
4360
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -4335,7 +4556,7 @@ async function getMasterKey() {
|
|
|
4335
4556
|
}
|
|
4336
4557
|
}
|
|
4337
4558
|
const keyPath = getKeyPath();
|
|
4338
|
-
if (!
|
|
4559
|
+
if (!existsSync7(keyPath)) {
|
|
4339
4560
|
process.stderr.write(
|
|
4340
4561
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
4341
4562
|
`
|
|
@@ -4635,6 +4856,21 @@ function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
|
4635
4856
|
}
|
|
4636
4857
|
|
|
4637
4858
|
// src/lib/store.ts
|
|
4859
|
+
var _debugStore = process.env.EXE_DEBUG === "1";
|
|
4860
|
+
function logStoreDebug(context, err) {
|
|
4861
|
+
if (_debugStore) {
|
|
4862
|
+
process.stderr.write(
|
|
4863
|
+
`[store] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
4864
|
+
`
|
|
4865
|
+
);
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
function logStoreWarn(context, err) {
|
|
4869
|
+
process.stderr.write(
|
|
4870
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
4871
|
+
`
|
|
4872
|
+
);
|
|
4873
|
+
}
|
|
4638
4874
|
var INIT_MAX_RETRIES = 3;
|
|
4639
4875
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
4640
4876
|
function isBusyError2(err) {
|
|
@@ -4697,13 +4933,15 @@ async function initStore(options) {
|
|
|
4697
4933
|
try {
|
|
4698
4934
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4699
4935
|
await initDaemonClient2();
|
|
4700
|
-
} catch {
|
|
4936
|
+
} catch (e) {
|
|
4937
|
+
logStoreWarn("catch", e);
|
|
4701
4938
|
}
|
|
4702
4939
|
if (!options?.lightweight) {
|
|
4703
4940
|
try {
|
|
4704
4941
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4705
4942
|
initShardManager2(hexKey);
|
|
4706
|
-
} catch {
|
|
4943
|
+
} catch (e) {
|
|
4944
|
+
logStoreWarn("catch", e);
|
|
4707
4945
|
}
|
|
4708
4946
|
const client = getClient();
|
|
4709
4947
|
const vResult = await retryOnBusy2(
|
|
@@ -4714,7 +4952,8 @@ async function initStore(options) {
|
|
|
4714
4952
|
try {
|
|
4715
4953
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4716
4954
|
await loadGlobalProcedures2();
|
|
4717
|
-
} catch {
|
|
4955
|
+
} catch (e) {
|
|
4956
|
+
logStoreWarn("catch", e);
|
|
4718
4957
|
}
|
|
4719
4958
|
}
|
|
4720
4959
|
}
|
|
@@ -4774,7 +5013,8 @@ async function writeMemory(record) {
|
|
|
4774
5013
|
memoryType
|
|
4775
5014
|
});
|
|
4776
5015
|
if (existing) return;
|
|
4777
|
-
} catch {
|
|
5016
|
+
} catch (e) {
|
|
5017
|
+
logStoreWarn("catch", e);
|
|
4778
5018
|
}
|
|
4779
5019
|
const dbRow = {
|
|
4780
5020
|
id: record.id,
|
|
@@ -4975,12 +5215,14 @@ async function flushBatch() {
|
|
|
4975
5215
|
try {
|
|
4976
5216
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
4977
5217
|
await insertMemoryCardsForBatch2(batch);
|
|
4978
|
-
} catch {
|
|
5218
|
+
} catch (e) {
|
|
5219
|
+
logStoreWarn("catch", e);
|
|
4979
5220
|
}
|
|
4980
5221
|
try {
|
|
4981
5222
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
4982
5223
|
await insertOntologyForBatch2(batch);
|
|
4983
|
-
} catch {
|
|
5224
|
+
} catch (e) {
|
|
5225
|
+
logStoreWarn("catch", e);
|
|
4984
5226
|
}
|
|
4985
5227
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4986
5228
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -5019,7 +5261,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
5019
5261
|
}
|
|
5020
5262
|
}
|
|
5021
5263
|
}
|
|
5022
|
-
} catch {
|
|
5264
|
+
} catch (e) {
|
|
5265
|
+
logStoreWarn("catch", e);
|
|
5023
5266
|
}
|
|
5024
5267
|
return batch.length;
|
|
5025
5268
|
} finally {
|
|
@@ -5061,7 +5304,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
5061
5304
|
} else {
|
|
5062
5305
|
client = getClient();
|
|
5063
5306
|
}
|
|
5064
|
-
} catch {
|
|
5307
|
+
} catch (e) {
|
|
5308
|
+
logStoreDebug("shard routing fallback", e);
|
|
5065
5309
|
client = getClient();
|
|
5066
5310
|
}
|
|
5067
5311
|
const limit = options?.limit ?? 10;
|
|
@@ -5177,7 +5421,8 @@ async function attachDocumentMetadata(records) {
|
|
|
5177
5421
|
if (!record.document_id) continue;
|
|
5178
5422
|
record.document_metadata = byId.get(record.document_id) ?? null;
|
|
5179
5423
|
}
|
|
5180
|
-
} catch {
|
|
5424
|
+
} catch (e) {
|
|
5425
|
+
logStoreWarn("catch", e);
|
|
5181
5426
|
}
|
|
5182
5427
|
return records;
|
|
5183
5428
|
}
|
|
@@ -5238,7 +5483,8 @@ async function getMemoryCardinality(agentId) {
|
|
|
5238
5483
|
args: [agentId]
|
|
5239
5484
|
});
|
|
5240
5485
|
return Number(result.rows[0]?.cnt) || 0;
|
|
5241
|
-
} catch {
|
|
5486
|
+
} catch (e) {
|
|
5487
|
+
logStoreWarn("getMemoryCardinality", e);
|
|
5242
5488
|
return 0;
|
|
5243
5489
|
}
|
|
5244
5490
|
}
|