@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
|
@@ -1594,9 +1594,79 @@ __export(database_exports, {
|
|
|
1594
1594
|
isInitialized: () => isInitialized,
|
|
1595
1595
|
setExternalClient: () => setExternalClient
|
|
1596
1596
|
});
|
|
1597
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
1597
|
+
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";
|
|
1598
1598
|
import { createClient } from "@libsql/client";
|
|
1599
|
+
import { homedir } from "os";
|
|
1600
|
+
import { join } from "path";
|
|
1601
|
+
function logCatchDebug(context, err) {
|
|
1602
|
+
if (_debugDb) {
|
|
1603
|
+
process.stderr.write(
|
|
1604
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
1605
|
+
`
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
}
|
|
1609
|
+
function acquireDbLock() {
|
|
1610
|
+
mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
|
|
1611
|
+
try {
|
|
1612
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1613
|
+
} catch (err) {
|
|
1614
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
1615
|
+
try {
|
|
1616
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
1617
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
1618
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1619
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1620
|
+
return;
|
|
1621
|
+
}
|
|
1622
|
+
} catch (e) {
|
|
1623
|
+
logCatchDebug("stale lock check", e);
|
|
1624
|
+
}
|
|
1625
|
+
process.stderr.write(
|
|
1626
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
1627
|
+
);
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
throw err;
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
function releaseDbLock() {
|
|
1634
|
+
if (_lockFd !== null) {
|
|
1635
|
+
try {
|
|
1636
|
+
closeSync2(_lockFd);
|
|
1637
|
+
} catch (e) {
|
|
1638
|
+
logCatchDebug("lock close", e);
|
|
1639
|
+
}
|
|
1640
|
+
_lockFd = null;
|
|
1641
|
+
}
|
|
1642
|
+
try {
|
|
1643
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1644
|
+
} catch (e) {
|
|
1645
|
+
logCatchDebug("lock unlink", e);
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1599
1648
|
async function initDatabase(config) {
|
|
1649
|
+
acquireDbLock();
|
|
1650
|
+
if (existsSync6(config.dbPath)) {
|
|
1651
|
+
const dbStat = statSync2(config.dbPath);
|
|
1652
|
+
if (dbStat.size === 0) {
|
|
1653
|
+
const walPath = config.dbPath + "-wal";
|
|
1654
|
+
if (existsSync6(walPath) && statSync2(walPath).size > 0) {
|
|
1655
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
1656
|
+
copyFileSync(config.dbPath, backupPath);
|
|
1657
|
+
unlinkSync3(config.dbPath);
|
|
1658
|
+
process.stderr.write(
|
|
1659
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
1660
|
+
`
|
|
1661
|
+
);
|
|
1662
|
+
} else {
|
|
1663
|
+
process.stderr.write(
|
|
1664
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
1665
|
+
`
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1600
1670
|
if (_walCheckpointTimer) {
|
|
1601
1671
|
clearInterval(_walCheckpointTimer);
|
|
1602
1672
|
_walCheckpointTimer = null;
|
|
@@ -1623,10 +1693,8 @@ async function initDatabase(config) {
|
|
|
1623
1693
|
_client = createClient(opts);
|
|
1624
1694
|
_resilientClient = wrapWithRetry(_client);
|
|
1625
1695
|
_adapterClient = _resilientClient;
|
|
1626
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
1627
|
-
|
|
1628
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
1629
|
-
});
|
|
1696
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
1697
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
1630
1698
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
1631
1699
|
_walCheckpointTimer = setInterval(() => {
|
|
1632
1700
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -1641,11 +1709,16 @@ async function initDatabase(config) {
|
|
|
1641
1709
|
for (const suffix of ["-wal", "-shm"]) {
|
|
1642
1710
|
try {
|
|
1643
1711
|
chmodSync2(config.dbPath + suffix, 384);
|
|
1644
|
-
} catch {
|
|
1712
|
+
} catch (chmodErr) {
|
|
1713
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1714
|
+
`);
|
|
1645
1715
|
}
|
|
1646
1716
|
}
|
|
1647
|
-
} catch {
|
|
1717
|
+
} catch (chmodErr) {
|
|
1718
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1719
|
+
`);
|
|
1648
1720
|
}
|
|
1721
|
+
releaseDbLock();
|
|
1649
1722
|
}
|
|
1650
1723
|
function isInitialized() {
|
|
1651
1724
|
return _adapterClient !== null || _client !== null;
|
|
@@ -1700,7 +1773,8 @@ async function ensureSchema() {
|
|
|
1700
1773
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
1701
1774
|
try {
|
|
1702
1775
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1703
|
-
} catch {
|
|
1776
|
+
} catch (e) {
|
|
1777
|
+
logCatchDebug("migration", e);
|
|
1704
1778
|
}
|
|
1705
1779
|
await client.executeMultiple(`
|
|
1706
1780
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -1765,6 +1839,23 @@ async function ensureSchema() {
|
|
|
1765
1839
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
1766
1840
|
END;
|
|
1767
1841
|
`);
|
|
1842
|
+
try {
|
|
1843
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
1844
|
+
} catch (ftsErr) {
|
|
1845
|
+
process.stderr.write(
|
|
1846
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
1847
|
+
`
|
|
1848
|
+
);
|
|
1849
|
+
try {
|
|
1850
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
1851
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
1852
|
+
} catch (rebuildErr) {
|
|
1853
|
+
process.stderr.write(
|
|
1854
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
1855
|
+
`
|
|
1856
|
+
);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1768
1859
|
await client.executeMultiple(`
|
|
1769
1860
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
1770
1861
|
key TEXT PRIMARY KEY,
|
|
@@ -1823,35 +1914,40 @@ async function ensureSchema() {
|
|
|
1823
1914
|
});
|
|
1824
1915
|
}
|
|
1825
1916
|
}
|
|
1826
|
-
} catch {
|
|
1917
|
+
} catch (seedErr) {
|
|
1918
|
+
logCatchDebug("behavior seed", seedErr);
|
|
1827
1919
|
}
|
|
1828
1920
|
try {
|
|
1829
1921
|
await client.execute({
|
|
1830
1922
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
1831
1923
|
args: []
|
|
1832
1924
|
});
|
|
1833
|
-
} catch {
|
|
1925
|
+
} catch (e) {
|
|
1926
|
+
logCatchDebug("migration", e);
|
|
1834
1927
|
}
|
|
1835
1928
|
try {
|
|
1836
1929
|
await client.execute({
|
|
1837
1930
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
1838
1931
|
args: []
|
|
1839
1932
|
});
|
|
1840
|
-
} catch {
|
|
1933
|
+
} catch (e) {
|
|
1934
|
+
logCatchDebug("migration", e);
|
|
1841
1935
|
}
|
|
1842
1936
|
try {
|
|
1843
1937
|
await client.execute({
|
|
1844
1938
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
1845
1939
|
args: []
|
|
1846
1940
|
});
|
|
1847
|
-
} catch {
|
|
1941
|
+
} catch (e) {
|
|
1942
|
+
logCatchDebug("migration", e);
|
|
1848
1943
|
}
|
|
1849
1944
|
try {
|
|
1850
1945
|
await client.execute({
|
|
1851
1946
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
1852
1947
|
args: []
|
|
1853
1948
|
});
|
|
1854
|
-
} catch {
|
|
1949
|
+
} catch (e) {
|
|
1950
|
+
logCatchDebug("migration", e);
|
|
1855
1951
|
}
|
|
1856
1952
|
try {
|
|
1857
1953
|
await client.execute({
|
|
@@ -1860,98 +1956,112 @@ async function ensureSchema() {
|
|
|
1860
1956
|
WHERE parent_task_id IS NOT NULL`,
|
|
1861
1957
|
args: []
|
|
1862
1958
|
});
|
|
1863
|
-
} catch {
|
|
1959
|
+
} catch (e) {
|
|
1960
|
+
logCatchDebug("migration", e);
|
|
1864
1961
|
}
|
|
1865
1962
|
try {
|
|
1866
1963
|
await client.execute({
|
|
1867
1964
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
1868
1965
|
args: []
|
|
1869
1966
|
});
|
|
1870
|
-
} catch {
|
|
1967
|
+
} catch (e) {
|
|
1968
|
+
logCatchDebug("migration", e);
|
|
1871
1969
|
}
|
|
1872
1970
|
try {
|
|
1873
1971
|
await client.execute({
|
|
1874
1972
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
1875
1973
|
args: []
|
|
1876
1974
|
});
|
|
1877
|
-
} catch {
|
|
1975
|
+
} catch (e) {
|
|
1976
|
+
logCatchDebug("migration", e);
|
|
1878
1977
|
}
|
|
1879
1978
|
try {
|
|
1880
1979
|
await client.execute({
|
|
1881
1980
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
1882
1981
|
args: []
|
|
1883
1982
|
});
|
|
1884
|
-
} catch {
|
|
1983
|
+
} catch (e) {
|
|
1984
|
+
logCatchDebug("migration", e);
|
|
1885
1985
|
}
|
|
1886
1986
|
try {
|
|
1887
1987
|
await client.execute({
|
|
1888
1988
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
1889
1989
|
args: []
|
|
1890
1990
|
});
|
|
1891
|
-
} catch {
|
|
1991
|
+
} catch (e) {
|
|
1992
|
+
logCatchDebug("migration", e);
|
|
1892
1993
|
}
|
|
1893
1994
|
try {
|
|
1894
1995
|
await client.execute({
|
|
1895
1996
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
1896
1997
|
args: []
|
|
1897
1998
|
});
|
|
1898
|
-
} catch {
|
|
1999
|
+
} catch (e) {
|
|
2000
|
+
logCatchDebug("migration", e);
|
|
1899
2001
|
}
|
|
1900
2002
|
try {
|
|
1901
2003
|
await client.execute({
|
|
1902
2004
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
1903
2005
|
args: []
|
|
1904
2006
|
});
|
|
1905
|
-
} catch {
|
|
2007
|
+
} catch (e) {
|
|
2008
|
+
logCatchDebug("migration", e);
|
|
1906
2009
|
}
|
|
1907
2010
|
try {
|
|
1908
2011
|
await client.execute({
|
|
1909
2012
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
1910
2013
|
args: []
|
|
1911
2014
|
});
|
|
1912
|
-
} catch {
|
|
2015
|
+
} catch (e) {
|
|
2016
|
+
logCatchDebug("migration", e);
|
|
1913
2017
|
}
|
|
1914
2018
|
try {
|
|
1915
2019
|
await client.execute({
|
|
1916
2020
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
1917
2021
|
args: []
|
|
1918
2022
|
});
|
|
1919
|
-
} catch {
|
|
2023
|
+
} catch (e) {
|
|
2024
|
+
logCatchDebug("migration", e);
|
|
1920
2025
|
}
|
|
1921
2026
|
try {
|
|
1922
2027
|
await client.execute({
|
|
1923
2028
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
1924
2029
|
args: []
|
|
1925
2030
|
});
|
|
1926
|
-
} catch {
|
|
2031
|
+
} catch (e) {
|
|
2032
|
+
logCatchDebug("migration", e);
|
|
1927
2033
|
}
|
|
1928
2034
|
try {
|
|
1929
2035
|
await client.execute({
|
|
1930
2036
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
1931
2037
|
args: []
|
|
1932
2038
|
});
|
|
1933
|
-
} catch {
|
|
2039
|
+
} catch (e) {
|
|
2040
|
+
logCatchDebug("migration", e);
|
|
1934
2041
|
}
|
|
1935
2042
|
try {
|
|
1936
2043
|
await client.execute({
|
|
1937
2044
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
1938
2045
|
args: []
|
|
1939
2046
|
});
|
|
1940
|
-
} catch {
|
|
2047
|
+
} catch (e) {
|
|
2048
|
+
logCatchDebug("migration", e);
|
|
1941
2049
|
}
|
|
1942
2050
|
try {
|
|
1943
2051
|
await client.execute({
|
|
1944
2052
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
1945
2053
|
args: []
|
|
1946
2054
|
});
|
|
1947
|
-
} catch {
|
|
2055
|
+
} catch (e) {
|
|
2056
|
+
logCatchDebug("migration", e);
|
|
1948
2057
|
}
|
|
1949
2058
|
try {
|
|
1950
2059
|
await client.execute({
|
|
1951
2060
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
1952
2061
|
args: []
|
|
1953
2062
|
});
|
|
1954
|
-
} catch {
|
|
2063
|
+
} catch (e) {
|
|
2064
|
+
logCatchDebug("migration", e);
|
|
1955
2065
|
}
|
|
1956
2066
|
await client.executeMultiple(`
|
|
1957
2067
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2056,14 +2166,16 @@ async function ensureSchema() {
|
|
|
2056
2166
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2057
2167
|
args: []
|
|
2058
2168
|
});
|
|
2059
|
-
} catch {
|
|
2169
|
+
} catch (e) {
|
|
2170
|
+
logCatchDebug("migration", e);
|
|
2060
2171
|
}
|
|
2061
2172
|
try {
|
|
2062
2173
|
await client.execute({
|
|
2063
2174
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2064
2175
|
args: []
|
|
2065
2176
|
});
|
|
2066
|
-
} catch {
|
|
2177
|
+
} catch (e) {
|
|
2178
|
+
logCatchDebug("migration", e);
|
|
2067
2179
|
}
|
|
2068
2180
|
await client.executeMultiple(`
|
|
2069
2181
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -2089,7 +2201,8 @@ async function ensureSchema() {
|
|
|
2089
2201
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
2090
2202
|
args: []
|
|
2091
2203
|
});
|
|
2092
|
-
} catch {
|
|
2204
|
+
} catch (e) {
|
|
2205
|
+
logCatchDebug("migration", e);
|
|
2093
2206
|
}
|
|
2094
2207
|
await client.executeMultiple(`
|
|
2095
2208
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -2113,7 +2226,8 @@ async function ensureSchema() {
|
|
|
2113
2226
|
`);
|
|
2114
2227
|
try {
|
|
2115
2228
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
2116
|
-
} catch {
|
|
2229
|
+
} catch (e) {
|
|
2230
|
+
logCatchDebug("migration", e);
|
|
2117
2231
|
}
|
|
2118
2232
|
await client.executeMultiple(`
|
|
2119
2233
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2150,63 +2264,72 @@ async function ensureSchema() {
|
|
|
2150
2264
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2151
2265
|
args: []
|
|
2152
2266
|
});
|
|
2153
|
-
} catch {
|
|
2267
|
+
} catch (e) {
|
|
2268
|
+
logCatchDebug("migration", e);
|
|
2154
2269
|
}
|
|
2155
2270
|
try {
|
|
2156
2271
|
await client.execute({
|
|
2157
2272
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2158
2273
|
args: []
|
|
2159
2274
|
});
|
|
2160
|
-
} catch {
|
|
2275
|
+
} catch (e) {
|
|
2276
|
+
logCatchDebug("migration", e);
|
|
2161
2277
|
}
|
|
2162
2278
|
try {
|
|
2163
2279
|
await client.execute({
|
|
2164
2280
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2165
2281
|
args: []
|
|
2166
2282
|
});
|
|
2167
|
-
} catch {
|
|
2283
|
+
} catch (e) {
|
|
2284
|
+
logCatchDebug("migration", e);
|
|
2168
2285
|
}
|
|
2169
2286
|
try {
|
|
2170
2287
|
await client.execute({
|
|
2171
2288
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2172
2289
|
args: []
|
|
2173
2290
|
});
|
|
2174
|
-
} catch {
|
|
2291
|
+
} catch (e) {
|
|
2292
|
+
logCatchDebug("migration", e);
|
|
2175
2293
|
}
|
|
2176
2294
|
try {
|
|
2177
2295
|
await client.execute({
|
|
2178
2296
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2179
2297
|
args: []
|
|
2180
2298
|
});
|
|
2181
|
-
} catch {
|
|
2299
|
+
} catch (e) {
|
|
2300
|
+
logCatchDebug("migration", e);
|
|
2182
2301
|
}
|
|
2183
2302
|
try {
|
|
2184
2303
|
await client.execute({
|
|
2185
2304
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2186
2305
|
args: []
|
|
2187
2306
|
});
|
|
2188
|
-
} catch {
|
|
2307
|
+
} catch (e) {
|
|
2308
|
+
logCatchDebug("migration", e);
|
|
2189
2309
|
}
|
|
2190
2310
|
try {
|
|
2191
2311
|
await client.execute({
|
|
2192
2312
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2193
2313
|
args: []
|
|
2194
2314
|
});
|
|
2195
|
-
} catch {
|
|
2315
|
+
} catch (e) {
|
|
2316
|
+
logCatchDebug("migration", e);
|
|
2196
2317
|
}
|
|
2197
2318
|
try {
|
|
2198
2319
|
await client.execute({
|
|
2199
2320
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2200
2321
|
args: []
|
|
2201
2322
|
});
|
|
2202
|
-
} catch {
|
|
2323
|
+
} catch (e) {
|
|
2324
|
+
logCatchDebug("migration", e);
|
|
2203
2325
|
}
|
|
2204
2326
|
try {
|
|
2205
2327
|
await client.execute({
|
|
2206
2328
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2207
2329
|
args: []
|
|
2208
2330
|
});
|
|
2209
|
-
} catch {
|
|
2331
|
+
} catch (e) {
|
|
2332
|
+
logCatchDebug("migration", e);
|
|
2210
2333
|
}
|
|
2211
2334
|
for (const col of [
|
|
2212
2335
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2214,14 +2337,16 @@ async function ensureSchema() {
|
|
|
2214
2337
|
]) {
|
|
2215
2338
|
try {
|
|
2216
2339
|
await client.execute(col);
|
|
2217
|
-
} catch {
|
|
2340
|
+
} catch (e) {
|
|
2341
|
+
logCatchDebug("migration", e);
|
|
2218
2342
|
}
|
|
2219
2343
|
}
|
|
2220
2344
|
try {
|
|
2221
2345
|
await client.execute(
|
|
2222
2346
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2223
2347
|
);
|
|
2224
|
-
} catch {
|
|
2348
|
+
} catch (e) {
|
|
2349
|
+
logCatchDebug("migration", e);
|
|
2225
2350
|
}
|
|
2226
2351
|
try {
|
|
2227
2352
|
await client.execute(
|
|
@@ -2229,7 +2354,8 @@ async function ensureSchema() {
|
|
|
2229
2354
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2230
2355
|
WHERE content_hash IS NOT NULL`
|
|
2231
2356
|
);
|
|
2232
|
-
} catch {
|
|
2357
|
+
} catch (e) {
|
|
2358
|
+
logCatchDebug("migration", e);
|
|
2233
2359
|
}
|
|
2234
2360
|
await client.executeMultiple(`
|
|
2235
2361
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2305,7 +2431,8 @@ async function ensureSchema() {
|
|
|
2305
2431
|
`);
|
|
2306
2432
|
try {
|
|
2307
2433
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2308
|
-
} catch {
|
|
2434
|
+
} catch (e) {
|
|
2435
|
+
logCatchDebug("migration", e);
|
|
2309
2436
|
}
|
|
2310
2437
|
await client.executeMultiple(`
|
|
2311
2438
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2320,14 +2447,16 @@ async function ensureSchema() {
|
|
|
2320
2447
|
]) {
|
|
2321
2448
|
try {
|
|
2322
2449
|
await client.execute(col);
|
|
2323
|
-
} catch {
|
|
2450
|
+
} catch (e) {
|
|
2451
|
+
logCatchDebug("migration", e);
|
|
2324
2452
|
}
|
|
2325
2453
|
}
|
|
2326
2454
|
try {
|
|
2327
2455
|
await client.execute(
|
|
2328
2456
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2329
2457
|
);
|
|
2330
|
-
} catch {
|
|
2458
|
+
} catch (e) {
|
|
2459
|
+
logCatchDebug("migration", e);
|
|
2331
2460
|
}
|
|
2332
2461
|
await client.executeMultiple(`
|
|
2333
2462
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2426,7 +2555,8 @@ async function ensureSchema() {
|
|
|
2426
2555
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2427
2556
|
args: []
|
|
2428
2557
|
});
|
|
2429
|
-
} catch {
|
|
2558
|
+
} catch (e) {
|
|
2559
|
+
logCatchDebug("migration", e);
|
|
2430
2560
|
}
|
|
2431
2561
|
}
|
|
2432
2562
|
for (const col of [
|
|
@@ -2435,7 +2565,8 @@ async function ensureSchema() {
|
|
|
2435
2565
|
]) {
|
|
2436
2566
|
try {
|
|
2437
2567
|
await client.execute(col);
|
|
2438
|
-
} catch {
|
|
2568
|
+
} catch (e) {
|
|
2569
|
+
logCatchDebug("migration", e);
|
|
2439
2570
|
}
|
|
2440
2571
|
}
|
|
2441
2572
|
await client.executeMultiple(`
|
|
@@ -2620,56 +2751,64 @@ async function ensureSchema() {
|
|
|
2620
2751
|
args: []
|
|
2621
2752
|
});
|
|
2622
2753
|
}
|
|
2623
|
-
} catch {
|
|
2754
|
+
} catch (e) {
|
|
2755
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
2624
2756
|
}
|
|
2625
2757
|
try {
|
|
2626
2758
|
await client.execute({
|
|
2627
2759
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
2628
2760
|
args: []
|
|
2629
2761
|
});
|
|
2630
|
-
} catch {
|
|
2762
|
+
} catch (e) {
|
|
2763
|
+
logCatchDebug("migration", e);
|
|
2631
2764
|
}
|
|
2632
2765
|
try {
|
|
2633
2766
|
await client.execute({
|
|
2634
2767
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
2635
2768
|
args: []
|
|
2636
2769
|
});
|
|
2637
|
-
} catch {
|
|
2770
|
+
} catch (e) {
|
|
2771
|
+
logCatchDebug("migration", e);
|
|
2638
2772
|
}
|
|
2639
2773
|
try {
|
|
2640
2774
|
await client.execute({
|
|
2641
2775
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
2642
2776
|
args: []
|
|
2643
2777
|
});
|
|
2644
|
-
} catch {
|
|
2778
|
+
} catch (e) {
|
|
2779
|
+
logCatchDebug("migration", e);
|
|
2645
2780
|
}
|
|
2646
2781
|
try {
|
|
2647
2782
|
await client.execute({
|
|
2648
2783
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
2649
2784
|
args: []
|
|
2650
2785
|
});
|
|
2651
|
-
} catch {
|
|
2786
|
+
} catch (e) {
|
|
2787
|
+
logCatchDebug("migration", e);
|
|
2652
2788
|
}
|
|
2653
2789
|
try {
|
|
2654
2790
|
await client.execute({
|
|
2655
2791
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
2656
2792
|
args: []
|
|
2657
2793
|
});
|
|
2658
|
-
} catch {
|
|
2794
|
+
} catch (e) {
|
|
2795
|
+
logCatchDebug("migration", e);
|
|
2659
2796
|
}
|
|
2660
2797
|
try {
|
|
2661
2798
|
await client.execute({
|
|
2662
2799
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2663
2800
|
args: []
|
|
2664
2801
|
});
|
|
2665
|
-
} catch {
|
|
2802
|
+
} catch (e) {
|
|
2803
|
+
logCatchDebug("migration", e);
|
|
2666
2804
|
}
|
|
2667
2805
|
try {
|
|
2668
2806
|
await client.execute({
|
|
2669
2807
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2670
2808
|
args: []
|
|
2671
2809
|
});
|
|
2672
|
-
} catch {
|
|
2810
|
+
} catch (e) {
|
|
2811
|
+
logCatchDebug("migration", e);
|
|
2673
2812
|
}
|
|
2674
2813
|
await client.executeMultiple(`
|
|
2675
2814
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -2868,13 +3007,15 @@ async function ensureSchema() {
|
|
|
2868
3007
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
2869
3008
|
args: []
|
|
2870
3009
|
});
|
|
2871
|
-
} catch {
|
|
3010
|
+
} catch (e) {
|
|
3011
|
+
logCatchDebug("migration", e);
|
|
2872
3012
|
}
|
|
2873
3013
|
try {
|
|
2874
3014
|
await client.execute(
|
|
2875
3015
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
2876
3016
|
);
|
|
2877
|
-
} catch {
|
|
3017
|
+
} catch (e) {
|
|
3018
|
+
logCatchDebug("migration", e);
|
|
2878
3019
|
}
|
|
2879
3020
|
try {
|
|
2880
3021
|
await client.execute({
|
|
@@ -2885,20 +3026,23 @@ async function ensureSchema() {
|
|
|
2885
3026
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
2886
3027
|
args: []
|
|
2887
3028
|
});
|
|
2888
|
-
} catch {
|
|
3029
|
+
} catch (e) {
|
|
3030
|
+
logCatchDebug("migration", e);
|
|
2889
3031
|
}
|
|
2890
3032
|
try {
|
|
2891
3033
|
await client.execute({
|
|
2892
3034
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
2893
3035
|
args: []
|
|
2894
3036
|
});
|
|
2895
|
-
} catch {
|
|
3037
|
+
} catch (e) {
|
|
3038
|
+
logCatchDebug("migration", e);
|
|
2896
3039
|
}
|
|
2897
3040
|
try {
|
|
2898
3041
|
await client.execute(
|
|
2899
3042
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
2900
3043
|
);
|
|
2901
|
-
} catch {
|
|
3044
|
+
} catch (e) {
|
|
3045
|
+
logCatchDebug("migration", e);
|
|
2902
3046
|
}
|
|
2903
3047
|
for (const col of [
|
|
2904
3048
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -2906,7 +3050,8 @@ async function ensureSchema() {
|
|
|
2906
3050
|
]) {
|
|
2907
3051
|
try {
|
|
2908
3052
|
await client.execute(col);
|
|
2909
|
-
} catch {
|
|
3053
|
+
} catch (e) {
|
|
3054
|
+
logCatchDebug("migration", e);
|
|
2910
3055
|
}
|
|
2911
3056
|
}
|
|
2912
3057
|
try {
|
|
@@ -2914,13 +3059,15 @@ async function ensureSchema() {
|
|
|
2914
3059
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
2915
3060
|
args: []
|
|
2916
3061
|
});
|
|
2917
|
-
} catch {
|
|
3062
|
+
} catch (e) {
|
|
3063
|
+
logCatchDebug("migration", e);
|
|
2918
3064
|
}
|
|
2919
3065
|
try {
|
|
2920
3066
|
await client.execute(
|
|
2921
3067
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
2922
3068
|
);
|
|
2923
|
-
} catch {
|
|
3069
|
+
} catch (e) {
|
|
3070
|
+
logCatchDebug("migration", e);
|
|
2924
3071
|
}
|
|
2925
3072
|
for (const col of [
|
|
2926
3073
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -2928,7 +3075,8 @@ async function ensureSchema() {
|
|
|
2928
3075
|
]) {
|
|
2929
3076
|
try {
|
|
2930
3077
|
await client.execute(col);
|
|
2931
|
-
} catch {
|
|
3078
|
+
} catch (e) {
|
|
3079
|
+
logCatchDebug("migration", e);
|
|
2932
3080
|
}
|
|
2933
3081
|
}
|
|
2934
3082
|
try {
|
|
@@ -2936,27 +3084,31 @@ async function ensureSchema() {
|
|
|
2936
3084
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
2937
3085
|
args: []
|
|
2938
3086
|
});
|
|
2939
|
-
} catch {
|
|
3087
|
+
} catch (e) {
|
|
3088
|
+
logCatchDebug("migration", e);
|
|
2940
3089
|
}
|
|
2941
3090
|
try {
|
|
2942
3091
|
await client.execute({
|
|
2943
3092
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
2944
3093
|
args: []
|
|
2945
3094
|
});
|
|
2946
|
-
} catch {
|
|
3095
|
+
} catch (e) {
|
|
3096
|
+
logCatchDebug("migration", e);
|
|
2947
3097
|
}
|
|
2948
3098
|
try {
|
|
2949
3099
|
await client.execute(
|
|
2950
3100
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
2951
3101
|
);
|
|
2952
|
-
} catch {
|
|
3102
|
+
} catch (e) {
|
|
3103
|
+
logCatchDebug("migration", e);
|
|
2953
3104
|
}
|
|
2954
3105
|
try {
|
|
2955
3106
|
await client.execute({
|
|
2956
3107
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
2957
3108
|
args: []
|
|
2958
3109
|
});
|
|
2959
|
-
} catch {
|
|
3110
|
+
} catch (e) {
|
|
3111
|
+
logCatchDebug("migration", e);
|
|
2960
3112
|
}
|
|
2961
3113
|
for (const col of [
|
|
2962
3114
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -2977,7 +3129,8 @@ async function ensureSchema() {
|
|
|
2977
3129
|
]) {
|
|
2978
3130
|
try {
|
|
2979
3131
|
await client.execute(col);
|
|
2980
|
-
} catch {
|
|
3132
|
+
} catch (e) {
|
|
3133
|
+
logCatchDebug("migration", e);
|
|
2981
3134
|
}
|
|
2982
3135
|
}
|
|
2983
3136
|
try {
|
|
@@ -2985,14 +3138,16 @@ async function ensureSchema() {
|
|
|
2985
3138
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
2986
3139
|
args: []
|
|
2987
3140
|
});
|
|
2988
|
-
} catch {
|
|
3141
|
+
} catch (e) {
|
|
3142
|
+
logCatchDebug("migration", e);
|
|
2989
3143
|
}
|
|
2990
3144
|
try {
|
|
2991
3145
|
await client.execute({
|
|
2992
3146
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
2993
3147
|
args: []
|
|
2994
3148
|
});
|
|
2995
|
-
} catch {
|
|
3149
|
+
} catch (e) {
|
|
3150
|
+
logCatchDebug("migration", e);
|
|
2996
3151
|
}
|
|
2997
3152
|
}
|
|
2998
3153
|
async function disposeDatabase() {
|
|
@@ -3003,7 +3158,8 @@ async function disposeDatabase() {
|
|
|
3003
3158
|
if (_client) {
|
|
3004
3159
|
try {
|
|
3005
3160
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3006
|
-
} catch {
|
|
3161
|
+
} catch (e) {
|
|
3162
|
+
logCatchDebug("WAL checkpoint", e);
|
|
3007
3163
|
}
|
|
3008
3164
|
}
|
|
3009
3165
|
if (_daemonClient) {
|
|
@@ -3019,8 +3175,9 @@ async function disposeDatabase() {
|
|
|
3019
3175
|
_client = null;
|
|
3020
3176
|
_resilientClient = null;
|
|
3021
3177
|
}
|
|
3178
|
+
releaseDbLock();
|
|
3022
3179
|
}
|
|
3023
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3180
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3024
3181
|
var init_database = __esm({
|
|
3025
3182
|
"src/lib/database.ts"() {
|
|
3026
3183
|
"use strict";
|
|
@@ -3028,11 +3185,14 @@ var init_database = __esm({
|
|
|
3028
3185
|
init_employees();
|
|
3029
3186
|
init_database_adapter();
|
|
3030
3187
|
init_memory();
|
|
3188
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
3031
3189
|
_client = null;
|
|
3032
3190
|
_resilientClient = null;
|
|
3033
3191
|
_walCheckpointTimer = null;
|
|
3034
3192
|
_daemonClient = null;
|
|
3035
3193
|
_adapterClient = null;
|
|
3194
|
+
_lockFd = null;
|
|
3195
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
3036
3196
|
initTurso = initDatabase;
|
|
3037
3197
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
3038
3198
|
disposeTurso = disposeDatabase;
|
|
@@ -3055,18 +3215,54 @@ __export(shard_manager_exports, {
|
|
|
3055
3215
|
shardExists: () => shardExists
|
|
3056
3216
|
});
|
|
3057
3217
|
import path7 from "path";
|
|
3058
|
-
import { existsSync as
|
|
3218
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
3059
3219
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3060
3220
|
function initShardManager(encryptionKey) {
|
|
3061
3221
|
_encryptionKey = encryptionKey;
|
|
3062
|
-
|
|
3063
|
-
|
|
3222
|
+
_keyValidated = false;
|
|
3223
|
+
_keyValidationPromise = null;
|
|
3224
|
+
if (!existsSync8(SHARDS_DIR)) {
|
|
3225
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
3226
|
+
}
|
|
3227
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3228
|
+
if (existingShards.length === 0) {
|
|
3229
|
+
_keyValidated = true;
|
|
3064
3230
|
}
|
|
3065
3231
|
_shardingEnabled = true;
|
|
3066
3232
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
3067
3233
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
3068
3234
|
_evictionTimer.unref();
|
|
3069
3235
|
}
|
|
3236
|
+
async function validateEncryptionKey() {
|
|
3237
|
+
if (_keyValidated) return true;
|
|
3238
|
+
if (!_encryptionKey) return false;
|
|
3239
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3240
|
+
if (existingShards.length === 0) {
|
|
3241
|
+
_keyValidated = true;
|
|
3242
|
+
return true;
|
|
3243
|
+
}
|
|
3244
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
3245
|
+
const dbPath = path7.join(SHARDS_DIR, shardFile);
|
|
3246
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
3247
|
+
try {
|
|
3248
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
3249
|
+
testClient.close();
|
|
3250
|
+
_keyValidated = true;
|
|
3251
|
+
return true;
|
|
3252
|
+
} catch {
|
|
3253
|
+
try {
|
|
3254
|
+
testClient.close();
|
|
3255
|
+
} catch {
|
|
3256
|
+
}
|
|
3257
|
+
}
|
|
3258
|
+
}
|
|
3259
|
+
process.stderr.write(
|
|
3260
|
+
`[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.
|
|
3261
|
+
`
|
|
3262
|
+
);
|
|
3263
|
+
_shardingEnabled = false;
|
|
3264
|
+
return false;
|
|
3265
|
+
}
|
|
3070
3266
|
function isShardingEnabled() {
|
|
3071
3267
|
return _shardingEnabled;
|
|
3072
3268
|
}
|
|
@@ -3100,13 +3296,13 @@ function getShardClient(projectName) {
|
|
|
3100
3296
|
}
|
|
3101
3297
|
function shardExists(projectName) {
|
|
3102
3298
|
const safeName = safeShardName(projectName);
|
|
3103
|
-
return
|
|
3299
|
+
return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
3104
3300
|
}
|
|
3105
3301
|
function safeShardName(projectName) {
|
|
3106
3302
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3107
3303
|
}
|
|
3108
3304
|
function listShards() {
|
|
3109
|
-
if (!
|
|
3305
|
+
if (!existsSync8(SHARDS_DIR)) return [];
|
|
3110
3306
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
3111
3307
|
}
|
|
3112
3308
|
async function auditShardHealth(options = {}) {
|
|
@@ -3119,7 +3315,7 @@ async function auditShardHealth(options = {}) {
|
|
|
3119
3315
|
const shards = [];
|
|
3120
3316
|
for (const name of names) {
|
|
3121
3317
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
3122
|
-
const stat =
|
|
3318
|
+
const stat = statSync4(dbPath);
|
|
3123
3319
|
const item = {
|
|
3124
3320
|
name,
|
|
3125
3321
|
path: dbPath,
|
|
@@ -3359,6 +3555,17 @@ async function ensureShardSchema(client) {
|
|
|
3359
3555
|
}
|
|
3360
3556
|
}
|
|
3361
3557
|
async function getReadyShardClient(projectName) {
|
|
3558
|
+
if (!_keyValidated) {
|
|
3559
|
+
if (!_keyValidationPromise) {
|
|
3560
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
3561
|
+
}
|
|
3562
|
+
const valid = await _keyValidationPromise;
|
|
3563
|
+
if (!valid) {
|
|
3564
|
+
throw new Error(
|
|
3565
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
3566
|
+
);
|
|
3567
|
+
}
|
|
3568
|
+
}
|
|
3362
3569
|
const safeName = safeShardName(projectName);
|
|
3363
3570
|
let client = getShardClient(projectName);
|
|
3364
3571
|
try {
|
|
@@ -3371,8 +3578,8 @@ async function getReadyShardClient(projectName) {
|
|
|
3371
3578
|
_shards.delete(safeName);
|
|
3372
3579
|
_shardLastAccess.delete(safeName);
|
|
3373
3580
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
3374
|
-
if (
|
|
3375
|
-
const stat =
|
|
3581
|
+
if (existsSync8(dbPath)) {
|
|
3582
|
+
const stat = statSync4(dbPath);
|
|
3376
3583
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3377
3584
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
3378
3585
|
renameSync3(dbPath, archivedPath);
|
|
@@ -3437,7 +3644,7 @@ function disposeShards() {
|
|
|
3437
3644
|
_shardingEnabled = false;
|
|
3438
3645
|
_encryptionKey = null;
|
|
3439
3646
|
}
|
|
3440
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
3647
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
3441
3648
|
var init_shard_manager = __esm({
|
|
3442
3649
|
"src/lib/shard-manager.ts"() {
|
|
3443
3650
|
"use strict";
|
|
@@ -3451,6 +3658,8 @@ var init_shard_manager = __esm({
|
|
|
3451
3658
|
_evictionTimer = null;
|
|
3452
3659
|
_encryptionKey = null;
|
|
3453
3660
|
_shardingEnabled = false;
|
|
3661
|
+
_keyValidated = false;
|
|
3662
|
+
_keyValidationPromise = null;
|
|
3454
3663
|
}
|
|
3455
3664
|
});
|
|
3456
3665
|
|
|
@@ -3646,6 +3855,18 @@ var init_platform_procedures = __esm({
|
|
|
3646
3855
|
priority: "p0",
|
|
3647
3856
|
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.'"
|
|
3648
3857
|
},
|
|
3858
|
+
{
|
|
3859
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
3860
|
+
domain: "workflow",
|
|
3861
|
+
priority: "p0",
|
|
3862
|
+
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."
|
|
3863
|
+
},
|
|
3864
|
+
{
|
|
3865
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
3866
|
+
domain: "workflow",
|
|
3867
|
+
priority: "p0",
|
|
3868
|
+
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."
|
|
3869
|
+
},
|
|
3649
3870
|
{
|
|
3650
3871
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
3651
3872
|
domain: "architecture",
|
|
@@ -3805,7 +4026,7 @@ init_database();
|
|
|
3805
4026
|
|
|
3806
4027
|
// src/lib/keychain.ts
|
|
3807
4028
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3808
|
-
import { existsSync as
|
|
4029
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
3809
4030
|
import { execSync as execSync3 } from "child_process";
|
|
3810
4031
|
import path6 from "path";
|
|
3811
4032
|
import os5 from "os";
|
|
@@ -3844,7 +4065,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
3844
4065
|
if (process.platform !== "linux") return false;
|
|
3845
4066
|
try {
|
|
3846
4067
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3847
|
-
const st =
|
|
4068
|
+
const st = statSync3(keyPath);
|
|
3848
4069
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3849
4070
|
if (uid === 0) return true;
|
|
3850
4071
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -4046,7 +4267,7 @@ async function getMasterKey() {
|
|
|
4046
4267
|
}
|
|
4047
4268
|
}
|
|
4048
4269
|
const keyPath = getKeyPath();
|
|
4049
|
-
if (!
|
|
4270
|
+
if (!existsSync7(keyPath)) {
|
|
4050
4271
|
process.stderr.write(
|
|
4051
4272
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
4052
4273
|
`
|
|
@@ -4161,6 +4382,13 @@ var orgBus = new StateBus();
|
|
|
4161
4382
|
import { createHash } from "crypto";
|
|
4162
4383
|
|
|
4163
4384
|
// src/lib/store.ts
|
|
4385
|
+
var _debugStore = process.env.EXE_DEBUG === "1";
|
|
4386
|
+
function logStoreWarn(context, err) {
|
|
4387
|
+
process.stderr.write(
|
|
4388
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
4389
|
+
`
|
|
4390
|
+
);
|
|
4391
|
+
}
|
|
4164
4392
|
var INIT_MAX_RETRIES = 3;
|
|
4165
4393
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
4166
4394
|
function isBusyError2(err) {
|
|
@@ -4223,13 +4451,15 @@ async function initStore(options) {
|
|
|
4223
4451
|
try {
|
|
4224
4452
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4225
4453
|
await initDaemonClient2();
|
|
4226
|
-
} catch {
|
|
4454
|
+
} catch (e) {
|
|
4455
|
+
logStoreWarn("catch", e);
|
|
4227
4456
|
}
|
|
4228
4457
|
if (!options?.lightweight) {
|
|
4229
4458
|
try {
|
|
4230
4459
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4231
4460
|
initShardManager2(hexKey);
|
|
4232
|
-
} catch {
|
|
4461
|
+
} catch (e) {
|
|
4462
|
+
logStoreWarn("catch", e);
|
|
4233
4463
|
}
|
|
4234
4464
|
const client = getClient();
|
|
4235
4465
|
const vResult = await retryOnBusy2(
|
|
@@ -4240,7 +4470,8 @@ async function initStore(options) {
|
|
|
4240
4470
|
try {
|
|
4241
4471
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4242
4472
|
await loadGlobalProcedures2();
|
|
4243
|
-
} catch {
|
|
4473
|
+
} catch (e) {
|
|
4474
|
+
logStoreWarn("catch", e);
|
|
4244
4475
|
}
|
|
4245
4476
|
}
|
|
4246
4477
|
}
|
|
@@ -4271,32 +4502,32 @@ function isMainModule(importMetaUrl) {
|
|
|
4271
4502
|
}
|
|
4272
4503
|
|
|
4273
4504
|
// src/bin/backfill-vectors.ts
|
|
4274
|
-
import { existsSync as
|
|
4505
|
+
import { existsSync as existsSync11, unlinkSync as unlinkSync6 } from "fs";
|
|
4275
4506
|
import path10 from "path";
|
|
4276
4507
|
|
|
4277
4508
|
// src/lib/worker-gate.ts
|
|
4278
4509
|
init_config();
|
|
4279
|
-
import { readdirSync as readdirSync2, writeFileSync as writeFileSync3, unlinkSync as
|
|
4510
|
+
import { readdirSync as readdirSync2, writeFileSync as writeFileSync3, unlinkSync as unlinkSync4, mkdirSync as mkdirSync4, existsSync as existsSync9 } from "fs";
|
|
4280
4511
|
import path8 from "path";
|
|
4281
4512
|
var WORKER_PID_DIR = path8.join(EXE_AI_DIR, "worker-pids");
|
|
4282
4513
|
function registerWorkerPid(pid) {
|
|
4283
4514
|
try {
|
|
4284
|
-
|
|
4515
|
+
mkdirSync4(WORKER_PID_DIR, { recursive: true });
|
|
4285
4516
|
writeFileSync3(path8.join(WORKER_PID_DIR, `worker-${pid}.pid`), String(pid));
|
|
4286
4517
|
} catch {
|
|
4287
4518
|
}
|
|
4288
4519
|
}
|
|
4289
4520
|
function cleanupWorkerPid() {
|
|
4290
4521
|
try {
|
|
4291
|
-
|
|
4522
|
+
unlinkSync4(path8.join(WORKER_PID_DIR, `worker-${process.pid}.pid`));
|
|
4292
4523
|
} catch {
|
|
4293
4524
|
}
|
|
4294
4525
|
}
|
|
4295
4526
|
var BACKFILL_LOCK = path8.join(WORKER_PID_DIR, "backfill.lock");
|
|
4296
4527
|
function tryAcquireBackfillLock() {
|
|
4297
4528
|
try {
|
|
4298
|
-
|
|
4299
|
-
if (
|
|
4529
|
+
mkdirSync4(WORKER_PID_DIR, { recursive: true });
|
|
4530
|
+
if (existsSync9(BACKFILL_LOCK)) {
|
|
4300
4531
|
try {
|
|
4301
4532
|
const pid = parseInt(
|
|
4302
4533
|
__require("fs").readFileSync(BACKFILL_LOCK, "utf8").trim(),
|
|
@@ -4320,14 +4551,14 @@ function tryAcquireBackfillLock() {
|
|
|
4320
4551
|
}
|
|
4321
4552
|
function releaseBackfillLock() {
|
|
4322
4553
|
try {
|
|
4323
|
-
|
|
4554
|
+
unlinkSync4(BACKFILL_LOCK);
|
|
4324
4555
|
} catch {
|
|
4325
4556
|
}
|
|
4326
4557
|
}
|
|
4327
4558
|
|
|
4328
4559
|
// src/lib/background-jobs.ts
|
|
4329
4560
|
init_config();
|
|
4330
|
-
import { existsSync as
|
|
4561
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync4, unlinkSync as unlinkSync5 } from "fs";
|
|
4331
4562
|
import { execFileSync } from "child_process";
|
|
4332
4563
|
import os6 from "os";
|
|
4333
4564
|
import path9 from "path";
|
|
@@ -4337,7 +4568,7 @@ var LOCK_DIR = path9.join(JOB_DIR, "locks");
|
|
|
4337
4568
|
var DEFAULT_LOCK_TTL_MS = 6 * 60 * 60 * 1e3;
|
|
4338
4569
|
var MAX_HISTORY = 200;
|
|
4339
4570
|
function ensureDirs() {
|
|
4340
|
-
|
|
4571
|
+
mkdirSync5(LOCK_DIR, { recursive: true });
|
|
4341
4572
|
}
|
|
4342
4573
|
function now() {
|
|
4343
4574
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -4353,7 +4584,7 @@ function isAlive(pid) {
|
|
|
4353
4584
|
}
|
|
4354
4585
|
function readJobsRaw() {
|
|
4355
4586
|
ensureDirs();
|
|
4356
|
-
if (!
|
|
4587
|
+
if (!existsSync10(JOBS_FILE)) return [];
|
|
4357
4588
|
try {
|
|
4358
4589
|
const parsed = JSON.parse(readFileSync5(JOBS_FILE, "utf8"));
|
|
4359
4590
|
return Array.isArray(parsed) ? parsed : [];
|
|
@@ -4373,7 +4604,7 @@ function lockPath(type) {
|
|
|
4373
4604
|
function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
4374
4605
|
ensureDirs();
|
|
4375
4606
|
const file = lockPath(type);
|
|
4376
|
-
if (
|
|
4607
|
+
if (existsSync10(file)) {
|
|
4377
4608
|
try {
|
|
4378
4609
|
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4379
4610
|
const age = Date.now() - Date.parse(lock.updatedAt ?? "");
|
|
@@ -4381,7 +4612,7 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
4381
4612
|
} catch {
|
|
4382
4613
|
}
|
|
4383
4614
|
try {
|
|
4384
|
-
|
|
4615
|
+
unlinkSync5(file);
|
|
4385
4616
|
} catch {
|
|
4386
4617
|
}
|
|
4387
4618
|
}
|
|
@@ -4395,12 +4626,12 @@ function acquireJobLock(type, ttlMs = DEFAULT_LOCK_TTL_MS) {
|
|
|
4395
4626
|
function releaseJobLock(type) {
|
|
4396
4627
|
const file = lockPath(type);
|
|
4397
4628
|
try {
|
|
4398
|
-
if (!
|
|
4629
|
+
if (!existsSync10(file)) return;
|
|
4399
4630
|
const lock = JSON.parse(readFileSync5(file, "utf8"));
|
|
4400
|
-
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid))
|
|
4631
|
+
if (lock.pid === process.pid || !lock.pid || !isAlive(lock.pid)) unlinkSync5(file);
|
|
4401
4632
|
} catch {
|
|
4402
4633
|
try {
|
|
4403
|
-
|
|
4634
|
+
unlinkSync5(file);
|
|
4404
4635
|
} catch {
|
|
4405
4636
|
}
|
|
4406
4637
|
}
|
|
@@ -4557,7 +4788,7 @@ async function backfillVectors() {
|
|
|
4557
4788
|
const remainingCount = Number(remaining.rows[0]?.cnt) || 0;
|
|
4558
4789
|
if (remainingCount === 0) {
|
|
4559
4790
|
try {
|
|
4560
|
-
|
|
4791
|
+
unlinkSync6(BACKFILL_FLAG);
|
|
4561
4792
|
} catch {
|
|
4562
4793
|
}
|
|
4563
4794
|
}
|
|
@@ -4568,7 +4799,7 @@ async function backfillVectors() {
|
|
|
4568
4799
|
return { processed: totalProcessed, failed: totalFailed, remaining: remainingCount };
|
|
4569
4800
|
}
|
|
4570
4801
|
function isBackfillNeeded() {
|
|
4571
|
-
return
|
|
4802
|
+
return existsSync11(BACKFILL_FLAG);
|
|
4572
4803
|
}
|
|
4573
4804
|
if (isMainModule(import.meta.url)) {
|
|
4574
4805
|
backfillVectors().then((result) => {
|