@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
|
@@ -1598,9 +1598,79 @@ __export(database_exports, {
|
|
|
1598
1598
|
isInitialized: () => isInitialized,
|
|
1599
1599
|
setExternalClient: () => setExternalClient
|
|
1600
1600
|
});
|
|
1601
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
1601
|
+
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";
|
|
1602
1602
|
import { createClient } from "@libsql/client";
|
|
1603
|
+
import { homedir } from "os";
|
|
1604
|
+
import { join } from "path";
|
|
1605
|
+
function logCatchDebug(context, err) {
|
|
1606
|
+
if (_debugDb) {
|
|
1607
|
+
process.stderr.write(
|
|
1608
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
1609
|
+
`
|
|
1610
|
+
);
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
function acquireDbLock() {
|
|
1614
|
+
mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
|
|
1615
|
+
try {
|
|
1616
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1617
|
+
} catch (err) {
|
|
1618
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
1619
|
+
try {
|
|
1620
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
1621
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
1622
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1623
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
} catch (e) {
|
|
1627
|
+
logCatchDebug("stale lock check", e);
|
|
1628
|
+
}
|
|
1629
|
+
process.stderr.write(
|
|
1630
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
1631
|
+
);
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
throw err;
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
function releaseDbLock() {
|
|
1638
|
+
if (_lockFd !== null) {
|
|
1639
|
+
try {
|
|
1640
|
+
closeSync2(_lockFd);
|
|
1641
|
+
} catch (e) {
|
|
1642
|
+
logCatchDebug("lock close", e);
|
|
1643
|
+
}
|
|
1644
|
+
_lockFd = null;
|
|
1645
|
+
}
|
|
1646
|
+
try {
|
|
1647
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1648
|
+
} catch (e) {
|
|
1649
|
+
logCatchDebug("lock unlink", e);
|
|
1650
|
+
}
|
|
1651
|
+
}
|
|
1603
1652
|
async function initDatabase(config) {
|
|
1653
|
+
acquireDbLock();
|
|
1654
|
+
if (existsSync6(config.dbPath)) {
|
|
1655
|
+
const dbStat = statSync2(config.dbPath);
|
|
1656
|
+
if (dbStat.size === 0) {
|
|
1657
|
+
const walPath = config.dbPath + "-wal";
|
|
1658
|
+
if (existsSync6(walPath) && statSync2(walPath).size > 0) {
|
|
1659
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
1660
|
+
copyFileSync(config.dbPath, backupPath);
|
|
1661
|
+
unlinkSync3(config.dbPath);
|
|
1662
|
+
process.stderr.write(
|
|
1663
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
1664
|
+
`
|
|
1665
|
+
);
|
|
1666
|
+
} else {
|
|
1667
|
+
process.stderr.write(
|
|
1668
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
1669
|
+
`
|
|
1670
|
+
);
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1604
1674
|
if (_walCheckpointTimer) {
|
|
1605
1675
|
clearInterval(_walCheckpointTimer);
|
|
1606
1676
|
_walCheckpointTimer = null;
|
|
@@ -1627,10 +1697,8 @@ async function initDatabase(config) {
|
|
|
1627
1697
|
_client = createClient(opts);
|
|
1628
1698
|
_resilientClient = wrapWithRetry(_client);
|
|
1629
1699
|
_adapterClient = _resilientClient;
|
|
1630
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
1631
|
-
|
|
1632
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
1633
|
-
});
|
|
1700
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
1701
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
1634
1702
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
1635
1703
|
_walCheckpointTimer = setInterval(() => {
|
|
1636
1704
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -1645,11 +1713,16 @@ async function initDatabase(config) {
|
|
|
1645
1713
|
for (const suffix of ["-wal", "-shm"]) {
|
|
1646
1714
|
try {
|
|
1647
1715
|
chmodSync2(config.dbPath + suffix, 384);
|
|
1648
|
-
} catch {
|
|
1716
|
+
} catch (chmodErr) {
|
|
1717
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1718
|
+
`);
|
|
1649
1719
|
}
|
|
1650
1720
|
}
|
|
1651
|
-
} catch {
|
|
1721
|
+
} catch (chmodErr) {
|
|
1722
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1723
|
+
`);
|
|
1652
1724
|
}
|
|
1725
|
+
releaseDbLock();
|
|
1653
1726
|
}
|
|
1654
1727
|
function isInitialized() {
|
|
1655
1728
|
return _adapterClient !== null || _client !== null;
|
|
@@ -1704,7 +1777,8 @@ async function ensureSchema() {
|
|
|
1704
1777
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
1705
1778
|
try {
|
|
1706
1779
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1707
|
-
} catch {
|
|
1780
|
+
} catch (e) {
|
|
1781
|
+
logCatchDebug("migration", e);
|
|
1708
1782
|
}
|
|
1709
1783
|
await client.executeMultiple(`
|
|
1710
1784
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -1769,6 +1843,23 @@ async function ensureSchema() {
|
|
|
1769
1843
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
1770
1844
|
END;
|
|
1771
1845
|
`);
|
|
1846
|
+
try {
|
|
1847
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
1848
|
+
} catch (ftsErr) {
|
|
1849
|
+
process.stderr.write(
|
|
1850
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
1851
|
+
`
|
|
1852
|
+
);
|
|
1853
|
+
try {
|
|
1854
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
1855
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
1856
|
+
} catch (rebuildErr) {
|
|
1857
|
+
process.stderr.write(
|
|
1858
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
1859
|
+
`
|
|
1860
|
+
);
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1772
1863
|
await client.executeMultiple(`
|
|
1773
1864
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
1774
1865
|
key TEXT PRIMARY KEY,
|
|
@@ -1827,35 +1918,40 @@ async function ensureSchema() {
|
|
|
1827
1918
|
});
|
|
1828
1919
|
}
|
|
1829
1920
|
}
|
|
1830
|
-
} catch {
|
|
1921
|
+
} catch (seedErr) {
|
|
1922
|
+
logCatchDebug("behavior seed", seedErr);
|
|
1831
1923
|
}
|
|
1832
1924
|
try {
|
|
1833
1925
|
await client.execute({
|
|
1834
1926
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
1835
1927
|
args: []
|
|
1836
1928
|
});
|
|
1837
|
-
} catch {
|
|
1929
|
+
} catch (e) {
|
|
1930
|
+
logCatchDebug("migration", e);
|
|
1838
1931
|
}
|
|
1839
1932
|
try {
|
|
1840
1933
|
await client.execute({
|
|
1841
1934
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
1842
1935
|
args: []
|
|
1843
1936
|
});
|
|
1844
|
-
} catch {
|
|
1937
|
+
} catch (e) {
|
|
1938
|
+
logCatchDebug("migration", e);
|
|
1845
1939
|
}
|
|
1846
1940
|
try {
|
|
1847
1941
|
await client.execute({
|
|
1848
1942
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
1849
1943
|
args: []
|
|
1850
1944
|
});
|
|
1851
|
-
} catch {
|
|
1945
|
+
} catch (e) {
|
|
1946
|
+
logCatchDebug("migration", e);
|
|
1852
1947
|
}
|
|
1853
1948
|
try {
|
|
1854
1949
|
await client.execute({
|
|
1855
1950
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
1856
1951
|
args: []
|
|
1857
1952
|
});
|
|
1858
|
-
} catch {
|
|
1953
|
+
} catch (e) {
|
|
1954
|
+
logCatchDebug("migration", e);
|
|
1859
1955
|
}
|
|
1860
1956
|
try {
|
|
1861
1957
|
await client.execute({
|
|
@@ -1864,98 +1960,112 @@ async function ensureSchema() {
|
|
|
1864
1960
|
WHERE parent_task_id IS NOT NULL`,
|
|
1865
1961
|
args: []
|
|
1866
1962
|
});
|
|
1867
|
-
} catch {
|
|
1963
|
+
} catch (e) {
|
|
1964
|
+
logCatchDebug("migration", e);
|
|
1868
1965
|
}
|
|
1869
1966
|
try {
|
|
1870
1967
|
await client.execute({
|
|
1871
1968
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
1872
1969
|
args: []
|
|
1873
1970
|
});
|
|
1874
|
-
} catch {
|
|
1971
|
+
} catch (e) {
|
|
1972
|
+
logCatchDebug("migration", e);
|
|
1875
1973
|
}
|
|
1876
1974
|
try {
|
|
1877
1975
|
await client.execute({
|
|
1878
1976
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
1879
1977
|
args: []
|
|
1880
1978
|
});
|
|
1881
|
-
} catch {
|
|
1979
|
+
} catch (e) {
|
|
1980
|
+
logCatchDebug("migration", e);
|
|
1882
1981
|
}
|
|
1883
1982
|
try {
|
|
1884
1983
|
await client.execute({
|
|
1885
1984
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
1886
1985
|
args: []
|
|
1887
1986
|
});
|
|
1888
|
-
} catch {
|
|
1987
|
+
} catch (e) {
|
|
1988
|
+
logCatchDebug("migration", e);
|
|
1889
1989
|
}
|
|
1890
1990
|
try {
|
|
1891
1991
|
await client.execute({
|
|
1892
1992
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
1893
1993
|
args: []
|
|
1894
1994
|
});
|
|
1895
|
-
} catch {
|
|
1995
|
+
} catch (e) {
|
|
1996
|
+
logCatchDebug("migration", e);
|
|
1896
1997
|
}
|
|
1897
1998
|
try {
|
|
1898
1999
|
await client.execute({
|
|
1899
2000
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
1900
2001
|
args: []
|
|
1901
2002
|
});
|
|
1902
|
-
} catch {
|
|
2003
|
+
} catch (e) {
|
|
2004
|
+
logCatchDebug("migration", e);
|
|
1903
2005
|
}
|
|
1904
2006
|
try {
|
|
1905
2007
|
await client.execute({
|
|
1906
2008
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
1907
2009
|
args: []
|
|
1908
2010
|
});
|
|
1909
|
-
} catch {
|
|
2011
|
+
} catch (e) {
|
|
2012
|
+
logCatchDebug("migration", e);
|
|
1910
2013
|
}
|
|
1911
2014
|
try {
|
|
1912
2015
|
await client.execute({
|
|
1913
2016
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
1914
2017
|
args: []
|
|
1915
2018
|
});
|
|
1916
|
-
} catch {
|
|
2019
|
+
} catch (e) {
|
|
2020
|
+
logCatchDebug("migration", e);
|
|
1917
2021
|
}
|
|
1918
2022
|
try {
|
|
1919
2023
|
await client.execute({
|
|
1920
2024
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
1921
2025
|
args: []
|
|
1922
2026
|
});
|
|
1923
|
-
} catch {
|
|
2027
|
+
} catch (e) {
|
|
2028
|
+
logCatchDebug("migration", e);
|
|
1924
2029
|
}
|
|
1925
2030
|
try {
|
|
1926
2031
|
await client.execute({
|
|
1927
2032
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
1928
2033
|
args: []
|
|
1929
2034
|
});
|
|
1930
|
-
} catch {
|
|
2035
|
+
} catch (e) {
|
|
2036
|
+
logCatchDebug("migration", e);
|
|
1931
2037
|
}
|
|
1932
2038
|
try {
|
|
1933
2039
|
await client.execute({
|
|
1934
2040
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
1935
2041
|
args: []
|
|
1936
2042
|
});
|
|
1937
|
-
} catch {
|
|
2043
|
+
} catch (e) {
|
|
2044
|
+
logCatchDebug("migration", e);
|
|
1938
2045
|
}
|
|
1939
2046
|
try {
|
|
1940
2047
|
await client.execute({
|
|
1941
2048
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
1942
2049
|
args: []
|
|
1943
2050
|
});
|
|
1944
|
-
} catch {
|
|
2051
|
+
} catch (e) {
|
|
2052
|
+
logCatchDebug("migration", e);
|
|
1945
2053
|
}
|
|
1946
2054
|
try {
|
|
1947
2055
|
await client.execute({
|
|
1948
2056
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
1949
2057
|
args: []
|
|
1950
2058
|
});
|
|
1951
|
-
} catch {
|
|
2059
|
+
} catch (e) {
|
|
2060
|
+
logCatchDebug("migration", e);
|
|
1952
2061
|
}
|
|
1953
2062
|
try {
|
|
1954
2063
|
await client.execute({
|
|
1955
2064
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
1956
2065
|
args: []
|
|
1957
2066
|
});
|
|
1958
|
-
} catch {
|
|
2067
|
+
} catch (e) {
|
|
2068
|
+
logCatchDebug("migration", e);
|
|
1959
2069
|
}
|
|
1960
2070
|
await client.executeMultiple(`
|
|
1961
2071
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2060,14 +2170,16 @@ async function ensureSchema() {
|
|
|
2060
2170
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2061
2171
|
args: []
|
|
2062
2172
|
});
|
|
2063
|
-
} catch {
|
|
2173
|
+
} catch (e) {
|
|
2174
|
+
logCatchDebug("migration", e);
|
|
2064
2175
|
}
|
|
2065
2176
|
try {
|
|
2066
2177
|
await client.execute({
|
|
2067
2178
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2068
2179
|
args: []
|
|
2069
2180
|
});
|
|
2070
|
-
} catch {
|
|
2181
|
+
} catch (e) {
|
|
2182
|
+
logCatchDebug("migration", e);
|
|
2071
2183
|
}
|
|
2072
2184
|
await client.executeMultiple(`
|
|
2073
2185
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -2093,7 +2205,8 @@ async function ensureSchema() {
|
|
|
2093
2205
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
2094
2206
|
args: []
|
|
2095
2207
|
});
|
|
2096
|
-
} catch {
|
|
2208
|
+
} catch (e) {
|
|
2209
|
+
logCatchDebug("migration", e);
|
|
2097
2210
|
}
|
|
2098
2211
|
await client.executeMultiple(`
|
|
2099
2212
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -2117,7 +2230,8 @@ async function ensureSchema() {
|
|
|
2117
2230
|
`);
|
|
2118
2231
|
try {
|
|
2119
2232
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
2120
|
-
} catch {
|
|
2233
|
+
} catch (e) {
|
|
2234
|
+
logCatchDebug("migration", e);
|
|
2121
2235
|
}
|
|
2122
2236
|
await client.executeMultiple(`
|
|
2123
2237
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2154,63 +2268,72 @@ async function ensureSchema() {
|
|
|
2154
2268
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2155
2269
|
args: []
|
|
2156
2270
|
});
|
|
2157
|
-
} catch {
|
|
2271
|
+
} catch (e) {
|
|
2272
|
+
logCatchDebug("migration", e);
|
|
2158
2273
|
}
|
|
2159
2274
|
try {
|
|
2160
2275
|
await client.execute({
|
|
2161
2276
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2162
2277
|
args: []
|
|
2163
2278
|
});
|
|
2164
|
-
} catch {
|
|
2279
|
+
} catch (e) {
|
|
2280
|
+
logCatchDebug("migration", e);
|
|
2165
2281
|
}
|
|
2166
2282
|
try {
|
|
2167
2283
|
await client.execute({
|
|
2168
2284
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2169
2285
|
args: []
|
|
2170
2286
|
});
|
|
2171
|
-
} catch {
|
|
2287
|
+
} catch (e) {
|
|
2288
|
+
logCatchDebug("migration", e);
|
|
2172
2289
|
}
|
|
2173
2290
|
try {
|
|
2174
2291
|
await client.execute({
|
|
2175
2292
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2176
2293
|
args: []
|
|
2177
2294
|
});
|
|
2178
|
-
} catch {
|
|
2295
|
+
} catch (e) {
|
|
2296
|
+
logCatchDebug("migration", e);
|
|
2179
2297
|
}
|
|
2180
2298
|
try {
|
|
2181
2299
|
await client.execute({
|
|
2182
2300
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2183
2301
|
args: []
|
|
2184
2302
|
});
|
|
2185
|
-
} catch {
|
|
2303
|
+
} catch (e) {
|
|
2304
|
+
logCatchDebug("migration", e);
|
|
2186
2305
|
}
|
|
2187
2306
|
try {
|
|
2188
2307
|
await client.execute({
|
|
2189
2308
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2190
2309
|
args: []
|
|
2191
2310
|
});
|
|
2192
|
-
} catch {
|
|
2311
|
+
} catch (e) {
|
|
2312
|
+
logCatchDebug("migration", e);
|
|
2193
2313
|
}
|
|
2194
2314
|
try {
|
|
2195
2315
|
await client.execute({
|
|
2196
2316
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2197
2317
|
args: []
|
|
2198
2318
|
});
|
|
2199
|
-
} catch {
|
|
2319
|
+
} catch (e) {
|
|
2320
|
+
logCatchDebug("migration", e);
|
|
2200
2321
|
}
|
|
2201
2322
|
try {
|
|
2202
2323
|
await client.execute({
|
|
2203
2324
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2204
2325
|
args: []
|
|
2205
2326
|
});
|
|
2206
|
-
} catch {
|
|
2327
|
+
} catch (e) {
|
|
2328
|
+
logCatchDebug("migration", e);
|
|
2207
2329
|
}
|
|
2208
2330
|
try {
|
|
2209
2331
|
await client.execute({
|
|
2210
2332
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2211
2333
|
args: []
|
|
2212
2334
|
});
|
|
2213
|
-
} catch {
|
|
2335
|
+
} catch (e) {
|
|
2336
|
+
logCatchDebug("migration", e);
|
|
2214
2337
|
}
|
|
2215
2338
|
for (const col of [
|
|
2216
2339
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2218,14 +2341,16 @@ async function ensureSchema() {
|
|
|
2218
2341
|
]) {
|
|
2219
2342
|
try {
|
|
2220
2343
|
await client.execute(col);
|
|
2221
|
-
} catch {
|
|
2344
|
+
} catch (e) {
|
|
2345
|
+
logCatchDebug("migration", e);
|
|
2222
2346
|
}
|
|
2223
2347
|
}
|
|
2224
2348
|
try {
|
|
2225
2349
|
await client.execute(
|
|
2226
2350
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2227
2351
|
);
|
|
2228
|
-
} catch {
|
|
2352
|
+
} catch (e) {
|
|
2353
|
+
logCatchDebug("migration", e);
|
|
2229
2354
|
}
|
|
2230
2355
|
try {
|
|
2231
2356
|
await client.execute(
|
|
@@ -2233,7 +2358,8 @@ async function ensureSchema() {
|
|
|
2233
2358
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2234
2359
|
WHERE content_hash IS NOT NULL`
|
|
2235
2360
|
);
|
|
2236
|
-
} catch {
|
|
2361
|
+
} catch (e) {
|
|
2362
|
+
logCatchDebug("migration", e);
|
|
2237
2363
|
}
|
|
2238
2364
|
await client.executeMultiple(`
|
|
2239
2365
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2309,7 +2435,8 @@ async function ensureSchema() {
|
|
|
2309
2435
|
`);
|
|
2310
2436
|
try {
|
|
2311
2437
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2312
|
-
} catch {
|
|
2438
|
+
} catch (e) {
|
|
2439
|
+
logCatchDebug("migration", e);
|
|
2313
2440
|
}
|
|
2314
2441
|
await client.executeMultiple(`
|
|
2315
2442
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2324,14 +2451,16 @@ async function ensureSchema() {
|
|
|
2324
2451
|
]) {
|
|
2325
2452
|
try {
|
|
2326
2453
|
await client.execute(col);
|
|
2327
|
-
} catch {
|
|
2454
|
+
} catch (e) {
|
|
2455
|
+
logCatchDebug("migration", e);
|
|
2328
2456
|
}
|
|
2329
2457
|
}
|
|
2330
2458
|
try {
|
|
2331
2459
|
await client.execute(
|
|
2332
2460
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2333
2461
|
);
|
|
2334
|
-
} catch {
|
|
2462
|
+
} catch (e) {
|
|
2463
|
+
logCatchDebug("migration", e);
|
|
2335
2464
|
}
|
|
2336
2465
|
await client.executeMultiple(`
|
|
2337
2466
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2430,7 +2559,8 @@ async function ensureSchema() {
|
|
|
2430
2559
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2431
2560
|
args: []
|
|
2432
2561
|
});
|
|
2433
|
-
} catch {
|
|
2562
|
+
} catch (e) {
|
|
2563
|
+
logCatchDebug("migration", e);
|
|
2434
2564
|
}
|
|
2435
2565
|
}
|
|
2436
2566
|
for (const col of [
|
|
@@ -2439,7 +2569,8 @@ async function ensureSchema() {
|
|
|
2439
2569
|
]) {
|
|
2440
2570
|
try {
|
|
2441
2571
|
await client.execute(col);
|
|
2442
|
-
} catch {
|
|
2572
|
+
} catch (e) {
|
|
2573
|
+
logCatchDebug("migration", e);
|
|
2443
2574
|
}
|
|
2444
2575
|
}
|
|
2445
2576
|
await client.executeMultiple(`
|
|
@@ -2624,56 +2755,64 @@ async function ensureSchema() {
|
|
|
2624
2755
|
args: []
|
|
2625
2756
|
});
|
|
2626
2757
|
}
|
|
2627
|
-
} catch {
|
|
2758
|
+
} catch (e) {
|
|
2759
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
2628
2760
|
}
|
|
2629
2761
|
try {
|
|
2630
2762
|
await client.execute({
|
|
2631
2763
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
2632
2764
|
args: []
|
|
2633
2765
|
});
|
|
2634
|
-
} catch {
|
|
2766
|
+
} catch (e) {
|
|
2767
|
+
logCatchDebug("migration", e);
|
|
2635
2768
|
}
|
|
2636
2769
|
try {
|
|
2637
2770
|
await client.execute({
|
|
2638
2771
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
2639
2772
|
args: []
|
|
2640
2773
|
});
|
|
2641
|
-
} catch {
|
|
2774
|
+
} catch (e) {
|
|
2775
|
+
logCatchDebug("migration", e);
|
|
2642
2776
|
}
|
|
2643
2777
|
try {
|
|
2644
2778
|
await client.execute({
|
|
2645
2779
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
2646
2780
|
args: []
|
|
2647
2781
|
});
|
|
2648
|
-
} catch {
|
|
2782
|
+
} catch (e) {
|
|
2783
|
+
logCatchDebug("migration", e);
|
|
2649
2784
|
}
|
|
2650
2785
|
try {
|
|
2651
2786
|
await client.execute({
|
|
2652
2787
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
2653
2788
|
args: []
|
|
2654
2789
|
});
|
|
2655
|
-
} catch {
|
|
2790
|
+
} catch (e) {
|
|
2791
|
+
logCatchDebug("migration", e);
|
|
2656
2792
|
}
|
|
2657
2793
|
try {
|
|
2658
2794
|
await client.execute({
|
|
2659
2795
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
2660
2796
|
args: []
|
|
2661
2797
|
});
|
|
2662
|
-
} catch {
|
|
2798
|
+
} catch (e) {
|
|
2799
|
+
logCatchDebug("migration", e);
|
|
2663
2800
|
}
|
|
2664
2801
|
try {
|
|
2665
2802
|
await client.execute({
|
|
2666
2803
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2667
2804
|
args: []
|
|
2668
2805
|
});
|
|
2669
|
-
} catch {
|
|
2806
|
+
} catch (e) {
|
|
2807
|
+
logCatchDebug("migration", e);
|
|
2670
2808
|
}
|
|
2671
2809
|
try {
|
|
2672
2810
|
await client.execute({
|
|
2673
2811
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2674
2812
|
args: []
|
|
2675
2813
|
});
|
|
2676
|
-
} catch {
|
|
2814
|
+
} catch (e) {
|
|
2815
|
+
logCatchDebug("migration", e);
|
|
2677
2816
|
}
|
|
2678
2817
|
await client.executeMultiple(`
|
|
2679
2818
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -2872,13 +3011,15 @@ async function ensureSchema() {
|
|
|
2872
3011
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
2873
3012
|
args: []
|
|
2874
3013
|
});
|
|
2875
|
-
} catch {
|
|
3014
|
+
} catch (e) {
|
|
3015
|
+
logCatchDebug("migration", e);
|
|
2876
3016
|
}
|
|
2877
3017
|
try {
|
|
2878
3018
|
await client.execute(
|
|
2879
3019
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
2880
3020
|
);
|
|
2881
|
-
} catch {
|
|
3021
|
+
} catch (e) {
|
|
3022
|
+
logCatchDebug("migration", e);
|
|
2882
3023
|
}
|
|
2883
3024
|
try {
|
|
2884
3025
|
await client.execute({
|
|
@@ -2889,20 +3030,23 @@ async function ensureSchema() {
|
|
|
2889
3030
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
2890
3031
|
args: []
|
|
2891
3032
|
});
|
|
2892
|
-
} catch {
|
|
3033
|
+
} catch (e) {
|
|
3034
|
+
logCatchDebug("migration", e);
|
|
2893
3035
|
}
|
|
2894
3036
|
try {
|
|
2895
3037
|
await client.execute({
|
|
2896
3038
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
2897
3039
|
args: []
|
|
2898
3040
|
});
|
|
2899
|
-
} catch {
|
|
3041
|
+
} catch (e) {
|
|
3042
|
+
logCatchDebug("migration", e);
|
|
2900
3043
|
}
|
|
2901
3044
|
try {
|
|
2902
3045
|
await client.execute(
|
|
2903
3046
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
2904
3047
|
);
|
|
2905
|
-
} catch {
|
|
3048
|
+
} catch (e) {
|
|
3049
|
+
logCatchDebug("migration", e);
|
|
2906
3050
|
}
|
|
2907
3051
|
for (const col of [
|
|
2908
3052
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -2910,7 +3054,8 @@ async function ensureSchema() {
|
|
|
2910
3054
|
]) {
|
|
2911
3055
|
try {
|
|
2912
3056
|
await client.execute(col);
|
|
2913
|
-
} catch {
|
|
3057
|
+
} catch (e) {
|
|
3058
|
+
logCatchDebug("migration", e);
|
|
2914
3059
|
}
|
|
2915
3060
|
}
|
|
2916
3061
|
try {
|
|
@@ -2918,13 +3063,15 @@ async function ensureSchema() {
|
|
|
2918
3063
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
2919
3064
|
args: []
|
|
2920
3065
|
});
|
|
2921
|
-
} catch {
|
|
3066
|
+
} catch (e) {
|
|
3067
|
+
logCatchDebug("migration", e);
|
|
2922
3068
|
}
|
|
2923
3069
|
try {
|
|
2924
3070
|
await client.execute(
|
|
2925
3071
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
2926
3072
|
);
|
|
2927
|
-
} catch {
|
|
3073
|
+
} catch (e) {
|
|
3074
|
+
logCatchDebug("migration", e);
|
|
2928
3075
|
}
|
|
2929
3076
|
for (const col of [
|
|
2930
3077
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -2932,7 +3079,8 @@ async function ensureSchema() {
|
|
|
2932
3079
|
]) {
|
|
2933
3080
|
try {
|
|
2934
3081
|
await client.execute(col);
|
|
2935
|
-
} catch {
|
|
3082
|
+
} catch (e) {
|
|
3083
|
+
logCatchDebug("migration", e);
|
|
2936
3084
|
}
|
|
2937
3085
|
}
|
|
2938
3086
|
try {
|
|
@@ -2940,27 +3088,31 @@ async function ensureSchema() {
|
|
|
2940
3088
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
2941
3089
|
args: []
|
|
2942
3090
|
});
|
|
2943
|
-
} catch {
|
|
3091
|
+
} catch (e) {
|
|
3092
|
+
logCatchDebug("migration", e);
|
|
2944
3093
|
}
|
|
2945
3094
|
try {
|
|
2946
3095
|
await client.execute({
|
|
2947
3096
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
2948
3097
|
args: []
|
|
2949
3098
|
});
|
|
2950
|
-
} catch {
|
|
3099
|
+
} catch (e) {
|
|
3100
|
+
logCatchDebug("migration", e);
|
|
2951
3101
|
}
|
|
2952
3102
|
try {
|
|
2953
3103
|
await client.execute(
|
|
2954
3104
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
2955
3105
|
);
|
|
2956
|
-
} catch {
|
|
3106
|
+
} catch (e) {
|
|
3107
|
+
logCatchDebug("migration", e);
|
|
2957
3108
|
}
|
|
2958
3109
|
try {
|
|
2959
3110
|
await client.execute({
|
|
2960
3111
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
2961
3112
|
args: []
|
|
2962
3113
|
});
|
|
2963
|
-
} catch {
|
|
3114
|
+
} catch (e) {
|
|
3115
|
+
logCatchDebug("migration", e);
|
|
2964
3116
|
}
|
|
2965
3117
|
for (const col of [
|
|
2966
3118
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -2981,7 +3133,8 @@ async function ensureSchema() {
|
|
|
2981
3133
|
]) {
|
|
2982
3134
|
try {
|
|
2983
3135
|
await client.execute(col);
|
|
2984
|
-
} catch {
|
|
3136
|
+
} catch (e) {
|
|
3137
|
+
logCatchDebug("migration", e);
|
|
2985
3138
|
}
|
|
2986
3139
|
}
|
|
2987
3140
|
try {
|
|
@@ -2989,14 +3142,16 @@ async function ensureSchema() {
|
|
|
2989
3142
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
2990
3143
|
args: []
|
|
2991
3144
|
});
|
|
2992
|
-
} catch {
|
|
3145
|
+
} catch (e) {
|
|
3146
|
+
logCatchDebug("migration", e);
|
|
2993
3147
|
}
|
|
2994
3148
|
try {
|
|
2995
3149
|
await client.execute({
|
|
2996
3150
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
2997
3151
|
args: []
|
|
2998
3152
|
});
|
|
2999
|
-
} catch {
|
|
3153
|
+
} catch (e) {
|
|
3154
|
+
logCatchDebug("migration", e);
|
|
3000
3155
|
}
|
|
3001
3156
|
}
|
|
3002
3157
|
async function disposeDatabase() {
|
|
@@ -3007,7 +3162,8 @@ async function disposeDatabase() {
|
|
|
3007
3162
|
if (_client) {
|
|
3008
3163
|
try {
|
|
3009
3164
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3010
|
-
} catch {
|
|
3165
|
+
} catch (e) {
|
|
3166
|
+
logCatchDebug("WAL checkpoint", e);
|
|
3011
3167
|
}
|
|
3012
3168
|
}
|
|
3013
3169
|
if (_daemonClient) {
|
|
@@ -3023,8 +3179,9 @@ async function disposeDatabase() {
|
|
|
3023
3179
|
_client = null;
|
|
3024
3180
|
_resilientClient = null;
|
|
3025
3181
|
}
|
|
3182
|
+
releaseDbLock();
|
|
3026
3183
|
}
|
|
3027
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3184
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3028
3185
|
var init_database = __esm({
|
|
3029
3186
|
"src/lib/database.ts"() {
|
|
3030
3187
|
"use strict";
|
|
@@ -3032,11 +3189,14 @@ var init_database = __esm({
|
|
|
3032
3189
|
init_employees();
|
|
3033
3190
|
init_database_adapter();
|
|
3034
3191
|
init_memory();
|
|
3192
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
3035
3193
|
_client = null;
|
|
3036
3194
|
_resilientClient = null;
|
|
3037
3195
|
_walCheckpointTimer = null;
|
|
3038
3196
|
_daemonClient = null;
|
|
3039
3197
|
_adapterClient = null;
|
|
3198
|
+
_lockFd = null;
|
|
3199
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
3040
3200
|
initTurso = initDatabase;
|
|
3041
3201
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
3042
3202
|
disposeTurso = disposeDatabase;
|
|
@@ -3059,18 +3219,54 @@ __export(shard_manager_exports, {
|
|
|
3059
3219
|
shardExists: () => shardExists
|
|
3060
3220
|
});
|
|
3061
3221
|
import path7 from "path";
|
|
3062
|
-
import { existsSync as
|
|
3222
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
3063
3223
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3064
3224
|
function initShardManager(encryptionKey) {
|
|
3065
3225
|
_encryptionKey = encryptionKey;
|
|
3066
|
-
|
|
3067
|
-
|
|
3226
|
+
_keyValidated = false;
|
|
3227
|
+
_keyValidationPromise = null;
|
|
3228
|
+
if (!existsSync8(SHARDS_DIR)) {
|
|
3229
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
3230
|
+
}
|
|
3231
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3232
|
+
if (existingShards.length === 0) {
|
|
3233
|
+
_keyValidated = true;
|
|
3068
3234
|
}
|
|
3069
3235
|
_shardingEnabled = true;
|
|
3070
3236
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
3071
3237
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
3072
3238
|
_evictionTimer.unref();
|
|
3073
3239
|
}
|
|
3240
|
+
async function validateEncryptionKey() {
|
|
3241
|
+
if (_keyValidated) return true;
|
|
3242
|
+
if (!_encryptionKey) return false;
|
|
3243
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3244
|
+
if (existingShards.length === 0) {
|
|
3245
|
+
_keyValidated = true;
|
|
3246
|
+
return true;
|
|
3247
|
+
}
|
|
3248
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
3249
|
+
const dbPath = path7.join(SHARDS_DIR, shardFile);
|
|
3250
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
3251
|
+
try {
|
|
3252
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
3253
|
+
testClient.close();
|
|
3254
|
+
_keyValidated = true;
|
|
3255
|
+
return true;
|
|
3256
|
+
} catch {
|
|
3257
|
+
try {
|
|
3258
|
+
testClient.close();
|
|
3259
|
+
} catch {
|
|
3260
|
+
}
|
|
3261
|
+
}
|
|
3262
|
+
}
|
|
3263
|
+
process.stderr.write(
|
|
3264
|
+
`[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.
|
|
3265
|
+
`
|
|
3266
|
+
);
|
|
3267
|
+
_shardingEnabled = false;
|
|
3268
|
+
return false;
|
|
3269
|
+
}
|
|
3074
3270
|
function isShardingEnabled() {
|
|
3075
3271
|
return _shardingEnabled;
|
|
3076
3272
|
}
|
|
@@ -3104,13 +3300,13 @@ function getShardClient(projectName) {
|
|
|
3104
3300
|
}
|
|
3105
3301
|
function shardExists(projectName) {
|
|
3106
3302
|
const safeName = safeShardName(projectName);
|
|
3107
|
-
return
|
|
3303
|
+
return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
3108
3304
|
}
|
|
3109
3305
|
function safeShardName(projectName) {
|
|
3110
3306
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3111
3307
|
}
|
|
3112
3308
|
function listShards() {
|
|
3113
|
-
if (!
|
|
3309
|
+
if (!existsSync8(SHARDS_DIR)) return [];
|
|
3114
3310
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
3115
3311
|
}
|
|
3116
3312
|
async function auditShardHealth(options = {}) {
|
|
@@ -3123,7 +3319,7 @@ async function auditShardHealth(options = {}) {
|
|
|
3123
3319
|
const shards = [];
|
|
3124
3320
|
for (const name of names) {
|
|
3125
3321
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
3126
|
-
const stat2 =
|
|
3322
|
+
const stat2 = statSync4(dbPath);
|
|
3127
3323
|
const item = {
|
|
3128
3324
|
name,
|
|
3129
3325
|
path: dbPath,
|
|
@@ -3363,6 +3559,17 @@ async function ensureShardSchema(client) {
|
|
|
3363
3559
|
}
|
|
3364
3560
|
}
|
|
3365
3561
|
async function getReadyShardClient(projectName) {
|
|
3562
|
+
if (!_keyValidated) {
|
|
3563
|
+
if (!_keyValidationPromise) {
|
|
3564
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
3565
|
+
}
|
|
3566
|
+
const valid = await _keyValidationPromise;
|
|
3567
|
+
if (!valid) {
|
|
3568
|
+
throw new Error(
|
|
3569
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
3570
|
+
);
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3366
3573
|
const safeName = safeShardName(projectName);
|
|
3367
3574
|
let client = getShardClient(projectName);
|
|
3368
3575
|
try {
|
|
@@ -3375,8 +3582,8 @@ async function getReadyShardClient(projectName) {
|
|
|
3375
3582
|
_shards.delete(safeName);
|
|
3376
3583
|
_shardLastAccess.delete(safeName);
|
|
3377
3584
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3378
|
-
if (
|
|
3379
|
-
const stat2 =
|
|
3585
|
+
if (existsSync8(dbPath)) {
|
|
3586
|
+
const stat2 = statSync4(dbPath);
|
|
3380
3587
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3381
3588
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3382
3589
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3441,7 +3648,7 @@ function disposeShards() {
|
|
|
3441
3648
|
_shardingEnabled = false;
|
|
3442
3649
|
_encryptionKey = null;
|
|
3443
3650
|
}
|
|
3444
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
3651
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
3445
3652
|
var init_shard_manager = __esm({
|
|
3446
3653
|
"src/lib/shard-manager.ts"() {
|
|
3447
3654
|
"use strict";
|
|
@@ -3455,6 +3662,8 @@ var init_shard_manager = __esm({
|
|
|
3455
3662
|
_evictionTimer = null;
|
|
3456
3663
|
_encryptionKey = null;
|
|
3457
3664
|
_shardingEnabled = false;
|
|
3665
|
+
_keyValidated = false;
|
|
3666
|
+
_keyValidationPromise = null;
|
|
3458
3667
|
}
|
|
3459
3668
|
});
|
|
3460
3669
|
|
|
@@ -3650,6 +3859,18 @@ var init_platform_procedures = __esm({
|
|
|
3650
3859
|
priority: "p0",
|
|
3651
3860
|
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.'"
|
|
3652
3861
|
},
|
|
3862
|
+
{
|
|
3863
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
3864
|
+
domain: "workflow",
|
|
3865
|
+
priority: "p0",
|
|
3866
|
+
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."
|
|
3867
|
+
},
|
|
3868
|
+
{
|
|
3869
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
3870
|
+
domain: "workflow",
|
|
3871
|
+
priority: "p0",
|
|
3872
|
+
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."
|
|
3873
|
+
},
|
|
3653
3874
|
{
|
|
3654
3875
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
3655
3876
|
domain: "architecture",
|
|
@@ -4235,7 +4456,7 @@ import { createReadStream } from "fs";
|
|
|
4235
4456
|
import { readdir, stat } from "fs/promises";
|
|
4236
4457
|
import path8 from "path";
|
|
4237
4458
|
import { createInterface } from "readline";
|
|
4238
|
-
import { homedir } from "os";
|
|
4459
|
+
import { homedir as homedir2 } from "os";
|
|
4239
4460
|
import { parseArgs } from "util";
|
|
4240
4461
|
|
|
4241
4462
|
// src/lib/store.ts
|
|
@@ -4244,7 +4465,7 @@ init_database();
|
|
|
4244
4465
|
|
|
4245
4466
|
// src/lib/keychain.ts
|
|
4246
4467
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
4247
|
-
import { existsSync as
|
|
4468
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
4248
4469
|
import { execSync as execSync3 } from "child_process";
|
|
4249
4470
|
import path6 from "path";
|
|
4250
4471
|
import os5 from "os";
|
|
@@ -4283,7 +4504,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
4283
4504
|
if (process.platform !== "linux") return false;
|
|
4284
4505
|
try {
|
|
4285
4506
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
4286
|
-
const st =
|
|
4507
|
+
const st = statSync3(keyPath);
|
|
4287
4508
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
4288
4509
|
if (uid === 0) return true;
|
|
4289
4510
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -4485,7 +4706,7 @@ async function getMasterKey() {
|
|
|
4485
4706
|
}
|
|
4486
4707
|
}
|
|
4487
4708
|
const keyPath = getKeyPath();
|
|
4488
|
-
if (!
|
|
4709
|
+
if (!existsSync7(keyPath)) {
|
|
4489
4710
|
process.stderr.write(
|
|
4490
4711
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
4491
4712
|
`
|
|
@@ -4785,6 +5006,13 @@ function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
|
4785
5006
|
}
|
|
4786
5007
|
|
|
4787
5008
|
// src/lib/store.ts
|
|
5009
|
+
var _debugStore = process.env.EXE_DEBUG === "1";
|
|
5010
|
+
function logStoreWarn(context, err) {
|
|
5011
|
+
process.stderr.write(
|
|
5012
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5013
|
+
`
|
|
5014
|
+
);
|
|
5015
|
+
}
|
|
4788
5016
|
var INIT_MAX_RETRIES = 3;
|
|
4789
5017
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
4790
5018
|
function isBusyError2(err) {
|
|
@@ -4847,13 +5075,15 @@ async function initStore(options) {
|
|
|
4847
5075
|
try {
|
|
4848
5076
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4849
5077
|
await initDaemonClient2();
|
|
4850
|
-
} catch {
|
|
5078
|
+
} catch (e) {
|
|
5079
|
+
logStoreWarn("catch", e);
|
|
4851
5080
|
}
|
|
4852
5081
|
if (!options?.lightweight) {
|
|
4853
5082
|
try {
|
|
4854
5083
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4855
5084
|
initShardManager2(hexKey);
|
|
4856
|
-
} catch {
|
|
5085
|
+
} catch (e) {
|
|
5086
|
+
logStoreWarn("catch", e);
|
|
4857
5087
|
}
|
|
4858
5088
|
const client = getClient();
|
|
4859
5089
|
const vResult = await retryOnBusy2(
|
|
@@ -4864,7 +5094,8 @@ async function initStore(options) {
|
|
|
4864
5094
|
try {
|
|
4865
5095
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4866
5096
|
await loadGlobalProcedures2();
|
|
4867
|
-
} catch {
|
|
5097
|
+
} catch (e) {
|
|
5098
|
+
logStoreWarn("catch", e);
|
|
4868
5099
|
}
|
|
4869
5100
|
}
|
|
4870
5101
|
}
|
|
@@ -4924,7 +5155,8 @@ async function writeMemory(record) {
|
|
|
4924
5155
|
memoryType
|
|
4925
5156
|
});
|
|
4926
5157
|
if (existing) return;
|
|
4927
|
-
} catch {
|
|
5158
|
+
} catch (e) {
|
|
5159
|
+
logStoreWarn("catch", e);
|
|
4928
5160
|
}
|
|
4929
5161
|
const dbRow = {
|
|
4930
5162
|
id: record.id,
|
|
@@ -5125,12 +5357,14 @@ async function flushBatch() {
|
|
|
5125
5357
|
try {
|
|
5126
5358
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
5127
5359
|
await insertMemoryCardsForBatch2(batch);
|
|
5128
|
-
} catch {
|
|
5360
|
+
} catch (e) {
|
|
5361
|
+
logStoreWarn("catch", e);
|
|
5129
5362
|
}
|
|
5130
5363
|
try {
|
|
5131
5364
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
5132
5365
|
await insertOntologyForBatch2(batch);
|
|
5133
|
-
} catch {
|
|
5366
|
+
} catch (e) {
|
|
5367
|
+
logStoreWarn("catch", e);
|
|
5134
5368
|
}
|
|
5135
5369
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
5136
5370
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -5169,7 +5403,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
5169
5403
|
}
|
|
5170
5404
|
}
|
|
5171
5405
|
}
|
|
5172
|
-
} catch {
|
|
5406
|
+
} catch (e) {
|
|
5407
|
+
logStoreWarn("catch", e);
|
|
5173
5408
|
}
|
|
5174
5409
|
return batch.length;
|
|
5175
5410
|
} finally {
|
|
@@ -5208,7 +5443,7 @@ var MIN_MESSAGES = 3;
|
|
|
5208
5443
|
var MAX_SUMMARY_LENGTH = 4e3;
|
|
5209
5444
|
var MAX_WALK_DEPTH = 10;
|
|
5210
5445
|
async function findJsonlFiles(sinceDate, projectFilter) {
|
|
5211
|
-
const projectsDir = path8.join(
|
|
5446
|
+
const projectsDir = path8.join(homedir2(), ".claude", "projects");
|
|
5212
5447
|
const files = [];
|
|
5213
5448
|
async function walk(dir, depth = 0) {
|
|
5214
5449
|
if (depth > MAX_WALK_DEPTH) return;
|
|
@@ -5253,7 +5488,7 @@ async function findJsonlFiles(sinceDate, projectFilter) {
|
|
|
5253
5488
|
return files;
|
|
5254
5489
|
}
|
|
5255
5490
|
function decodeProjectDir(dirName) {
|
|
5256
|
-
const homeEncoded =
|
|
5491
|
+
const homeEncoded = homedir2().replaceAll("/", "-");
|
|
5257
5492
|
if (dirName.startsWith(homeEncoded + "-")) {
|
|
5258
5493
|
return dirName.slice(homeEncoded.length + 1);
|
|
5259
5494
|
}
|
|
@@ -5261,7 +5496,7 @@ function decodeProjectDir(dirName) {
|
|
|
5261
5496
|
return dirName;
|
|
5262
5497
|
}
|
|
5263
5498
|
function projectNameFromPath(filePath) {
|
|
5264
|
-
const projectsDir = path8.join(
|
|
5499
|
+
const projectsDir = path8.join(homedir2(), ".claude", "projects");
|
|
5265
5500
|
const relative = path8.relative(projectsDir, filePath);
|
|
5266
5501
|
const projectDir = relative.split(path8.sep)[0] ?? "unknown";
|
|
5267
5502
|
return decodeProjectDir(projectDir);
|