@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
|
@@ -1675,9 +1675,79 @@ __export(database_exports, {
|
|
|
1675
1675
|
isInitialized: () => isInitialized,
|
|
1676
1676
|
setExternalClient: () => setExternalClient
|
|
1677
1677
|
});
|
|
1678
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
1678
|
+
import { chmodSync as chmodSync2, existsSync as existsSync6, statSync as statSync2, copyFileSync, unlinkSync as unlinkSync4, openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
1679
1679
|
import { createClient } from "@libsql/client";
|
|
1680
|
+
import { homedir } from "os";
|
|
1681
|
+
import { join } from "path";
|
|
1682
|
+
function logCatchDebug(context, err) {
|
|
1683
|
+
if (_debugDb) {
|
|
1684
|
+
process.stderr.write(
|
|
1685
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
1686
|
+
`
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
function acquireDbLock() {
|
|
1691
|
+
mkdirSync3(join(homedir(), ".exe-os"), { recursive: true });
|
|
1692
|
+
try {
|
|
1693
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1694
|
+
} catch (err) {
|
|
1695
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
1696
|
+
try {
|
|
1697
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
1698
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
1699
|
+
unlinkSync4(DB_LOCK_PATH);
|
|
1700
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1701
|
+
return;
|
|
1702
|
+
}
|
|
1703
|
+
} catch (e) {
|
|
1704
|
+
logCatchDebug("stale lock check", e);
|
|
1705
|
+
}
|
|
1706
|
+
process.stderr.write(
|
|
1707
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
1708
|
+
);
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
throw err;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
function releaseDbLock() {
|
|
1715
|
+
if (_lockFd !== null) {
|
|
1716
|
+
try {
|
|
1717
|
+
closeSync2(_lockFd);
|
|
1718
|
+
} catch (e) {
|
|
1719
|
+
logCatchDebug("lock close", e);
|
|
1720
|
+
}
|
|
1721
|
+
_lockFd = null;
|
|
1722
|
+
}
|
|
1723
|
+
try {
|
|
1724
|
+
unlinkSync4(DB_LOCK_PATH);
|
|
1725
|
+
} catch (e) {
|
|
1726
|
+
logCatchDebug("lock unlink", e);
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1680
1729
|
async function initDatabase(config) {
|
|
1730
|
+
acquireDbLock();
|
|
1731
|
+
if (existsSync6(config.dbPath)) {
|
|
1732
|
+
const dbStat = statSync2(config.dbPath);
|
|
1733
|
+
if (dbStat.size === 0) {
|
|
1734
|
+
const walPath = config.dbPath + "-wal";
|
|
1735
|
+
if (existsSync6(walPath) && statSync2(walPath).size > 0) {
|
|
1736
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
1737
|
+
copyFileSync(config.dbPath, backupPath);
|
|
1738
|
+
unlinkSync4(config.dbPath);
|
|
1739
|
+
process.stderr.write(
|
|
1740
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
1741
|
+
`
|
|
1742
|
+
);
|
|
1743
|
+
} else {
|
|
1744
|
+
process.stderr.write(
|
|
1745
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
1746
|
+
`
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1681
1751
|
if (_walCheckpointTimer) {
|
|
1682
1752
|
clearInterval(_walCheckpointTimer);
|
|
1683
1753
|
_walCheckpointTimer = null;
|
|
@@ -1704,10 +1774,8 @@ async function initDatabase(config) {
|
|
|
1704
1774
|
_client = createClient(opts);
|
|
1705
1775
|
_resilientClient = wrapWithRetry(_client);
|
|
1706
1776
|
_adapterClient = _resilientClient;
|
|
1707
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
1708
|
-
|
|
1709
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
1710
|
-
});
|
|
1777
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
1778
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
1711
1779
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
1712
1780
|
_walCheckpointTimer = setInterval(() => {
|
|
1713
1781
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -1722,11 +1790,16 @@ async function initDatabase(config) {
|
|
|
1722
1790
|
for (const suffix of ["-wal", "-shm"]) {
|
|
1723
1791
|
try {
|
|
1724
1792
|
chmodSync2(config.dbPath + suffix, 384);
|
|
1725
|
-
} catch {
|
|
1793
|
+
} catch (chmodErr) {
|
|
1794
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1795
|
+
`);
|
|
1726
1796
|
}
|
|
1727
1797
|
}
|
|
1728
|
-
} catch {
|
|
1798
|
+
} catch (chmodErr) {
|
|
1799
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1800
|
+
`);
|
|
1729
1801
|
}
|
|
1802
|
+
releaseDbLock();
|
|
1730
1803
|
}
|
|
1731
1804
|
function isInitialized() {
|
|
1732
1805
|
return _adapterClient !== null || _client !== null;
|
|
@@ -1781,7 +1854,8 @@ async function ensureSchema() {
|
|
|
1781
1854
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
1782
1855
|
try {
|
|
1783
1856
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1784
|
-
} catch {
|
|
1857
|
+
} catch (e) {
|
|
1858
|
+
logCatchDebug("migration", e);
|
|
1785
1859
|
}
|
|
1786
1860
|
await client.executeMultiple(`
|
|
1787
1861
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -1846,6 +1920,23 @@ async function ensureSchema() {
|
|
|
1846
1920
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
1847
1921
|
END;
|
|
1848
1922
|
`);
|
|
1923
|
+
try {
|
|
1924
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
1925
|
+
} catch (ftsErr) {
|
|
1926
|
+
process.stderr.write(
|
|
1927
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
1928
|
+
`
|
|
1929
|
+
);
|
|
1930
|
+
try {
|
|
1931
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
1932
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
1933
|
+
} catch (rebuildErr) {
|
|
1934
|
+
process.stderr.write(
|
|
1935
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
1936
|
+
`
|
|
1937
|
+
);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1849
1940
|
await client.executeMultiple(`
|
|
1850
1941
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
1851
1942
|
key TEXT PRIMARY KEY,
|
|
@@ -1904,35 +1995,40 @@ async function ensureSchema() {
|
|
|
1904
1995
|
});
|
|
1905
1996
|
}
|
|
1906
1997
|
}
|
|
1907
|
-
} catch {
|
|
1998
|
+
} catch (seedErr) {
|
|
1999
|
+
logCatchDebug("behavior seed", seedErr);
|
|
1908
2000
|
}
|
|
1909
2001
|
try {
|
|
1910
2002
|
await client.execute({
|
|
1911
2003
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
1912
2004
|
args: []
|
|
1913
2005
|
});
|
|
1914
|
-
} catch {
|
|
2006
|
+
} catch (e) {
|
|
2007
|
+
logCatchDebug("migration", e);
|
|
1915
2008
|
}
|
|
1916
2009
|
try {
|
|
1917
2010
|
await client.execute({
|
|
1918
2011
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
1919
2012
|
args: []
|
|
1920
2013
|
});
|
|
1921
|
-
} catch {
|
|
2014
|
+
} catch (e) {
|
|
2015
|
+
logCatchDebug("migration", e);
|
|
1922
2016
|
}
|
|
1923
2017
|
try {
|
|
1924
2018
|
await client.execute({
|
|
1925
2019
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
1926
2020
|
args: []
|
|
1927
2021
|
});
|
|
1928
|
-
} catch {
|
|
2022
|
+
} catch (e) {
|
|
2023
|
+
logCatchDebug("migration", e);
|
|
1929
2024
|
}
|
|
1930
2025
|
try {
|
|
1931
2026
|
await client.execute({
|
|
1932
2027
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
1933
2028
|
args: []
|
|
1934
2029
|
});
|
|
1935
|
-
} catch {
|
|
2030
|
+
} catch (e) {
|
|
2031
|
+
logCatchDebug("migration", e);
|
|
1936
2032
|
}
|
|
1937
2033
|
try {
|
|
1938
2034
|
await client.execute({
|
|
@@ -1941,98 +2037,112 @@ async function ensureSchema() {
|
|
|
1941
2037
|
WHERE parent_task_id IS NOT NULL`,
|
|
1942
2038
|
args: []
|
|
1943
2039
|
});
|
|
1944
|
-
} catch {
|
|
2040
|
+
} catch (e) {
|
|
2041
|
+
logCatchDebug("migration", e);
|
|
1945
2042
|
}
|
|
1946
2043
|
try {
|
|
1947
2044
|
await client.execute({
|
|
1948
2045
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
1949
2046
|
args: []
|
|
1950
2047
|
});
|
|
1951
|
-
} catch {
|
|
2048
|
+
} catch (e) {
|
|
2049
|
+
logCatchDebug("migration", e);
|
|
1952
2050
|
}
|
|
1953
2051
|
try {
|
|
1954
2052
|
await client.execute({
|
|
1955
2053
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
1956
2054
|
args: []
|
|
1957
2055
|
});
|
|
1958
|
-
} catch {
|
|
2056
|
+
} catch (e) {
|
|
2057
|
+
logCatchDebug("migration", e);
|
|
1959
2058
|
}
|
|
1960
2059
|
try {
|
|
1961
2060
|
await client.execute({
|
|
1962
2061
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
1963
2062
|
args: []
|
|
1964
2063
|
});
|
|
1965
|
-
} catch {
|
|
2064
|
+
} catch (e) {
|
|
2065
|
+
logCatchDebug("migration", e);
|
|
1966
2066
|
}
|
|
1967
2067
|
try {
|
|
1968
2068
|
await client.execute({
|
|
1969
2069
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
1970
2070
|
args: []
|
|
1971
2071
|
});
|
|
1972
|
-
} catch {
|
|
2072
|
+
} catch (e) {
|
|
2073
|
+
logCatchDebug("migration", e);
|
|
1973
2074
|
}
|
|
1974
2075
|
try {
|
|
1975
2076
|
await client.execute({
|
|
1976
2077
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
1977
2078
|
args: []
|
|
1978
2079
|
});
|
|
1979
|
-
} catch {
|
|
2080
|
+
} catch (e) {
|
|
2081
|
+
logCatchDebug("migration", e);
|
|
1980
2082
|
}
|
|
1981
2083
|
try {
|
|
1982
2084
|
await client.execute({
|
|
1983
2085
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
1984
2086
|
args: []
|
|
1985
2087
|
});
|
|
1986
|
-
} catch {
|
|
2088
|
+
} catch (e) {
|
|
2089
|
+
logCatchDebug("migration", e);
|
|
1987
2090
|
}
|
|
1988
2091
|
try {
|
|
1989
2092
|
await client.execute({
|
|
1990
2093
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
1991
2094
|
args: []
|
|
1992
2095
|
});
|
|
1993
|
-
} catch {
|
|
2096
|
+
} catch (e) {
|
|
2097
|
+
logCatchDebug("migration", e);
|
|
1994
2098
|
}
|
|
1995
2099
|
try {
|
|
1996
2100
|
await client.execute({
|
|
1997
2101
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
1998
2102
|
args: []
|
|
1999
2103
|
});
|
|
2000
|
-
} catch {
|
|
2104
|
+
} catch (e) {
|
|
2105
|
+
logCatchDebug("migration", e);
|
|
2001
2106
|
}
|
|
2002
2107
|
try {
|
|
2003
2108
|
await client.execute({
|
|
2004
2109
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
2005
2110
|
args: []
|
|
2006
2111
|
});
|
|
2007
|
-
} catch {
|
|
2112
|
+
} catch (e) {
|
|
2113
|
+
logCatchDebug("migration", e);
|
|
2008
2114
|
}
|
|
2009
2115
|
try {
|
|
2010
2116
|
await client.execute({
|
|
2011
2117
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
2012
2118
|
args: []
|
|
2013
2119
|
});
|
|
2014
|
-
} catch {
|
|
2120
|
+
} catch (e) {
|
|
2121
|
+
logCatchDebug("migration", e);
|
|
2015
2122
|
}
|
|
2016
2123
|
try {
|
|
2017
2124
|
await client.execute({
|
|
2018
2125
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2019
2126
|
args: []
|
|
2020
2127
|
});
|
|
2021
|
-
} catch {
|
|
2128
|
+
} catch (e) {
|
|
2129
|
+
logCatchDebug("migration", e);
|
|
2022
2130
|
}
|
|
2023
2131
|
try {
|
|
2024
2132
|
await client.execute({
|
|
2025
2133
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
2026
2134
|
args: []
|
|
2027
2135
|
});
|
|
2028
|
-
} catch {
|
|
2136
|
+
} catch (e) {
|
|
2137
|
+
logCatchDebug("migration", e);
|
|
2029
2138
|
}
|
|
2030
2139
|
try {
|
|
2031
2140
|
await client.execute({
|
|
2032
2141
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
2033
2142
|
args: []
|
|
2034
2143
|
});
|
|
2035
|
-
} catch {
|
|
2144
|
+
} catch (e) {
|
|
2145
|
+
logCatchDebug("migration", e);
|
|
2036
2146
|
}
|
|
2037
2147
|
await client.executeMultiple(`
|
|
2038
2148
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2137,14 +2247,16 @@ async function ensureSchema() {
|
|
|
2137
2247
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2138
2248
|
args: []
|
|
2139
2249
|
});
|
|
2140
|
-
} catch {
|
|
2250
|
+
} catch (e) {
|
|
2251
|
+
logCatchDebug("migration", e);
|
|
2141
2252
|
}
|
|
2142
2253
|
try {
|
|
2143
2254
|
await client.execute({
|
|
2144
2255
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2145
2256
|
args: []
|
|
2146
2257
|
});
|
|
2147
|
-
} catch {
|
|
2258
|
+
} catch (e) {
|
|
2259
|
+
logCatchDebug("migration", e);
|
|
2148
2260
|
}
|
|
2149
2261
|
await client.executeMultiple(`
|
|
2150
2262
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -2170,7 +2282,8 @@ async function ensureSchema() {
|
|
|
2170
2282
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
2171
2283
|
args: []
|
|
2172
2284
|
});
|
|
2173
|
-
} catch {
|
|
2285
|
+
} catch (e) {
|
|
2286
|
+
logCatchDebug("migration", e);
|
|
2174
2287
|
}
|
|
2175
2288
|
await client.executeMultiple(`
|
|
2176
2289
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -2194,7 +2307,8 @@ async function ensureSchema() {
|
|
|
2194
2307
|
`);
|
|
2195
2308
|
try {
|
|
2196
2309
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
2197
|
-
} catch {
|
|
2310
|
+
} catch (e) {
|
|
2311
|
+
logCatchDebug("migration", e);
|
|
2198
2312
|
}
|
|
2199
2313
|
await client.executeMultiple(`
|
|
2200
2314
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2231,63 +2345,72 @@ async function ensureSchema() {
|
|
|
2231
2345
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2232
2346
|
args: []
|
|
2233
2347
|
});
|
|
2234
|
-
} catch {
|
|
2348
|
+
} catch (e) {
|
|
2349
|
+
logCatchDebug("migration", e);
|
|
2235
2350
|
}
|
|
2236
2351
|
try {
|
|
2237
2352
|
await client.execute({
|
|
2238
2353
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2239
2354
|
args: []
|
|
2240
2355
|
});
|
|
2241
|
-
} catch {
|
|
2356
|
+
} catch (e) {
|
|
2357
|
+
logCatchDebug("migration", e);
|
|
2242
2358
|
}
|
|
2243
2359
|
try {
|
|
2244
2360
|
await client.execute({
|
|
2245
2361
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2246
2362
|
args: []
|
|
2247
2363
|
});
|
|
2248
|
-
} catch {
|
|
2364
|
+
} catch (e) {
|
|
2365
|
+
logCatchDebug("migration", e);
|
|
2249
2366
|
}
|
|
2250
2367
|
try {
|
|
2251
2368
|
await client.execute({
|
|
2252
2369
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2253
2370
|
args: []
|
|
2254
2371
|
});
|
|
2255
|
-
} catch {
|
|
2372
|
+
} catch (e) {
|
|
2373
|
+
logCatchDebug("migration", e);
|
|
2256
2374
|
}
|
|
2257
2375
|
try {
|
|
2258
2376
|
await client.execute({
|
|
2259
2377
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2260
2378
|
args: []
|
|
2261
2379
|
});
|
|
2262
|
-
} catch {
|
|
2380
|
+
} catch (e) {
|
|
2381
|
+
logCatchDebug("migration", e);
|
|
2263
2382
|
}
|
|
2264
2383
|
try {
|
|
2265
2384
|
await client.execute({
|
|
2266
2385
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2267
2386
|
args: []
|
|
2268
2387
|
});
|
|
2269
|
-
} catch {
|
|
2388
|
+
} catch (e) {
|
|
2389
|
+
logCatchDebug("migration", e);
|
|
2270
2390
|
}
|
|
2271
2391
|
try {
|
|
2272
2392
|
await client.execute({
|
|
2273
2393
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2274
2394
|
args: []
|
|
2275
2395
|
});
|
|
2276
|
-
} catch {
|
|
2396
|
+
} catch (e) {
|
|
2397
|
+
logCatchDebug("migration", e);
|
|
2277
2398
|
}
|
|
2278
2399
|
try {
|
|
2279
2400
|
await client.execute({
|
|
2280
2401
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2281
2402
|
args: []
|
|
2282
2403
|
});
|
|
2283
|
-
} catch {
|
|
2404
|
+
} catch (e) {
|
|
2405
|
+
logCatchDebug("migration", e);
|
|
2284
2406
|
}
|
|
2285
2407
|
try {
|
|
2286
2408
|
await client.execute({
|
|
2287
2409
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2288
2410
|
args: []
|
|
2289
2411
|
});
|
|
2290
|
-
} catch {
|
|
2412
|
+
} catch (e) {
|
|
2413
|
+
logCatchDebug("migration", e);
|
|
2291
2414
|
}
|
|
2292
2415
|
for (const col of [
|
|
2293
2416
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2295,14 +2418,16 @@ async function ensureSchema() {
|
|
|
2295
2418
|
]) {
|
|
2296
2419
|
try {
|
|
2297
2420
|
await client.execute(col);
|
|
2298
|
-
} catch {
|
|
2421
|
+
} catch (e) {
|
|
2422
|
+
logCatchDebug("migration", e);
|
|
2299
2423
|
}
|
|
2300
2424
|
}
|
|
2301
2425
|
try {
|
|
2302
2426
|
await client.execute(
|
|
2303
2427
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2304
2428
|
);
|
|
2305
|
-
} catch {
|
|
2429
|
+
} catch (e) {
|
|
2430
|
+
logCatchDebug("migration", e);
|
|
2306
2431
|
}
|
|
2307
2432
|
try {
|
|
2308
2433
|
await client.execute(
|
|
@@ -2310,7 +2435,8 @@ async function ensureSchema() {
|
|
|
2310
2435
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2311
2436
|
WHERE content_hash IS NOT NULL`
|
|
2312
2437
|
);
|
|
2313
|
-
} catch {
|
|
2438
|
+
} catch (e) {
|
|
2439
|
+
logCatchDebug("migration", e);
|
|
2314
2440
|
}
|
|
2315
2441
|
await client.executeMultiple(`
|
|
2316
2442
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2386,7 +2512,8 @@ async function ensureSchema() {
|
|
|
2386
2512
|
`);
|
|
2387
2513
|
try {
|
|
2388
2514
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2389
|
-
} catch {
|
|
2515
|
+
} catch (e) {
|
|
2516
|
+
logCatchDebug("migration", e);
|
|
2390
2517
|
}
|
|
2391
2518
|
await client.executeMultiple(`
|
|
2392
2519
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2401,14 +2528,16 @@ async function ensureSchema() {
|
|
|
2401
2528
|
]) {
|
|
2402
2529
|
try {
|
|
2403
2530
|
await client.execute(col);
|
|
2404
|
-
} catch {
|
|
2531
|
+
} catch (e) {
|
|
2532
|
+
logCatchDebug("migration", e);
|
|
2405
2533
|
}
|
|
2406
2534
|
}
|
|
2407
2535
|
try {
|
|
2408
2536
|
await client.execute(
|
|
2409
2537
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2410
2538
|
);
|
|
2411
|
-
} catch {
|
|
2539
|
+
} catch (e) {
|
|
2540
|
+
logCatchDebug("migration", e);
|
|
2412
2541
|
}
|
|
2413
2542
|
await client.executeMultiple(`
|
|
2414
2543
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2507,7 +2636,8 @@ async function ensureSchema() {
|
|
|
2507
2636
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2508
2637
|
args: []
|
|
2509
2638
|
});
|
|
2510
|
-
} catch {
|
|
2639
|
+
} catch (e) {
|
|
2640
|
+
logCatchDebug("migration", e);
|
|
2511
2641
|
}
|
|
2512
2642
|
}
|
|
2513
2643
|
for (const col of [
|
|
@@ -2516,7 +2646,8 @@ async function ensureSchema() {
|
|
|
2516
2646
|
]) {
|
|
2517
2647
|
try {
|
|
2518
2648
|
await client.execute(col);
|
|
2519
|
-
} catch {
|
|
2649
|
+
} catch (e) {
|
|
2650
|
+
logCatchDebug("migration", e);
|
|
2520
2651
|
}
|
|
2521
2652
|
}
|
|
2522
2653
|
await client.executeMultiple(`
|
|
@@ -2701,56 +2832,64 @@ async function ensureSchema() {
|
|
|
2701
2832
|
args: []
|
|
2702
2833
|
});
|
|
2703
2834
|
}
|
|
2704
|
-
} catch {
|
|
2835
|
+
} catch (e) {
|
|
2836
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
2705
2837
|
}
|
|
2706
2838
|
try {
|
|
2707
2839
|
await client.execute({
|
|
2708
2840
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
2709
2841
|
args: []
|
|
2710
2842
|
});
|
|
2711
|
-
} catch {
|
|
2843
|
+
} catch (e) {
|
|
2844
|
+
logCatchDebug("migration", e);
|
|
2712
2845
|
}
|
|
2713
2846
|
try {
|
|
2714
2847
|
await client.execute({
|
|
2715
2848
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
2716
2849
|
args: []
|
|
2717
2850
|
});
|
|
2718
|
-
} catch {
|
|
2851
|
+
} catch (e) {
|
|
2852
|
+
logCatchDebug("migration", e);
|
|
2719
2853
|
}
|
|
2720
2854
|
try {
|
|
2721
2855
|
await client.execute({
|
|
2722
2856
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
2723
2857
|
args: []
|
|
2724
2858
|
});
|
|
2725
|
-
} catch {
|
|
2859
|
+
} catch (e) {
|
|
2860
|
+
logCatchDebug("migration", e);
|
|
2726
2861
|
}
|
|
2727
2862
|
try {
|
|
2728
2863
|
await client.execute({
|
|
2729
2864
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
2730
2865
|
args: []
|
|
2731
2866
|
});
|
|
2732
|
-
} catch {
|
|
2867
|
+
} catch (e) {
|
|
2868
|
+
logCatchDebug("migration", e);
|
|
2733
2869
|
}
|
|
2734
2870
|
try {
|
|
2735
2871
|
await client.execute({
|
|
2736
2872
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
2737
2873
|
args: []
|
|
2738
2874
|
});
|
|
2739
|
-
} catch {
|
|
2875
|
+
} catch (e) {
|
|
2876
|
+
logCatchDebug("migration", e);
|
|
2740
2877
|
}
|
|
2741
2878
|
try {
|
|
2742
2879
|
await client.execute({
|
|
2743
2880
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2744
2881
|
args: []
|
|
2745
2882
|
});
|
|
2746
|
-
} catch {
|
|
2883
|
+
} catch (e) {
|
|
2884
|
+
logCatchDebug("migration", e);
|
|
2747
2885
|
}
|
|
2748
2886
|
try {
|
|
2749
2887
|
await client.execute({
|
|
2750
2888
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2751
2889
|
args: []
|
|
2752
2890
|
});
|
|
2753
|
-
} catch {
|
|
2891
|
+
} catch (e) {
|
|
2892
|
+
logCatchDebug("migration", e);
|
|
2754
2893
|
}
|
|
2755
2894
|
await client.executeMultiple(`
|
|
2756
2895
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -2949,13 +3088,15 @@ async function ensureSchema() {
|
|
|
2949
3088
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
2950
3089
|
args: []
|
|
2951
3090
|
});
|
|
2952
|
-
} catch {
|
|
3091
|
+
} catch (e) {
|
|
3092
|
+
logCatchDebug("migration", e);
|
|
2953
3093
|
}
|
|
2954
3094
|
try {
|
|
2955
3095
|
await client.execute(
|
|
2956
3096
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
2957
3097
|
);
|
|
2958
|
-
} catch {
|
|
3098
|
+
} catch (e) {
|
|
3099
|
+
logCatchDebug("migration", e);
|
|
2959
3100
|
}
|
|
2960
3101
|
try {
|
|
2961
3102
|
await client.execute({
|
|
@@ -2966,20 +3107,23 @@ async function ensureSchema() {
|
|
|
2966
3107
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
2967
3108
|
args: []
|
|
2968
3109
|
});
|
|
2969
|
-
} catch {
|
|
3110
|
+
} catch (e) {
|
|
3111
|
+
logCatchDebug("migration", e);
|
|
2970
3112
|
}
|
|
2971
3113
|
try {
|
|
2972
3114
|
await client.execute({
|
|
2973
3115
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
2974
3116
|
args: []
|
|
2975
3117
|
});
|
|
2976
|
-
} catch {
|
|
3118
|
+
} catch (e) {
|
|
3119
|
+
logCatchDebug("migration", e);
|
|
2977
3120
|
}
|
|
2978
3121
|
try {
|
|
2979
3122
|
await client.execute(
|
|
2980
3123
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
2981
3124
|
);
|
|
2982
|
-
} catch {
|
|
3125
|
+
} catch (e) {
|
|
3126
|
+
logCatchDebug("migration", e);
|
|
2983
3127
|
}
|
|
2984
3128
|
for (const col of [
|
|
2985
3129
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -2987,7 +3131,8 @@ async function ensureSchema() {
|
|
|
2987
3131
|
]) {
|
|
2988
3132
|
try {
|
|
2989
3133
|
await client.execute(col);
|
|
2990
|
-
} catch {
|
|
3134
|
+
} catch (e) {
|
|
3135
|
+
logCatchDebug("migration", e);
|
|
2991
3136
|
}
|
|
2992
3137
|
}
|
|
2993
3138
|
try {
|
|
@@ -2995,13 +3140,15 @@ async function ensureSchema() {
|
|
|
2995
3140
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
2996
3141
|
args: []
|
|
2997
3142
|
});
|
|
2998
|
-
} catch {
|
|
3143
|
+
} catch (e) {
|
|
3144
|
+
logCatchDebug("migration", e);
|
|
2999
3145
|
}
|
|
3000
3146
|
try {
|
|
3001
3147
|
await client.execute(
|
|
3002
3148
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
3003
3149
|
);
|
|
3004
|
-
} catch {
|
|
3150
|
+
} catch (e) {
|
|
3151
|
+
logCatchDebug("migration", e);
|
|
3005
3152
|
}
|
|
3006
3153
|
for (const col of [
|
|
3007
3154
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -3009,7 +3156,8 @@ async function ensureSchema() {
|
|
|
3009
3156
|
]) {
|
|
3010
3157
|
try {
|
|
3011
3158
|
await client.execute(col);
|
|
3012
|
-
} catch {
|
|
3159
|
+
} catch (e) {
|
|
3160
|
+
logCatchDebug("migration", e);
|
|
3013
3161
|
}
|
|
3014
3162
|
}
|
|
3015
3163
|
try {
|
|
@@ -3017,27 +3165,31 @@ async function ensureSchema() {
|
|
|
3017
3165
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3018
3166
|
args: []
|
|
3019
3167
|
});
|
|
3020
|
-
} catch {
|
|
3168
|
+
} catch (e) {
|
|
3169
|
+
logCatchDebug("migration", e);
|
|
3021
3170
|
}
|
|
3022
3171
|
try {
|
|
3023
3172
|
await client.execute({
|
|
3024
3173
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
3025
3174
|
args: []
|
|
3026
3175
|
});
|
|
3027
|
-
} catch {
|
|
3176
|
+
} catch (e) {
|
|
3177
|
+
logCatchDebug("migration", e);
|
|
3028
3178
|
}
|
|
3029
3179
|
try {
|
|
3030
3180
|
await client.execute(
|
|
3031
3181
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
3032
3182
|
);
|
|
3033
|
-
} catch {
|
|
3183
|
+
} catch (e) {
|
|
3184
|
+
logCatchDebug("migration", e);
|
|
3034
3185
|
}
|
|
3035
3186
|
try {
|
|
3036
3187
|
await client.execute({
|
|
3037
3188
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
3038
3189
|
args: []
|
|
3039
3190
|
});
|
|
3040
|
-
} catch {
|
|
3191
|
+
} catch (e) {
|
|
3192
|
+
logCatchDebug("migration", e);
|
|
3041
3193
|
}
|
|
3042
3194
|
for (const col of [
|
|
3043
3195
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -3058,7 +3210,8 @@ async function ensureSchema() {
|
|
|
3058
3210
|
]) {
|
|
3059
3211
|
try {
|
|
3060
3212
|
await client.execute(col);
|
|
3061
|
-
} catch {
|
|
3213
|
+
} catch (e) {
|
|
3214
|
+
logCatchDebug("migration", e);
|
|
3062
3215
|
}
|
|
3063
3216
|
}
|
|
3064
3217
|
try {
|
|
@@ -3066,14 +3219,16 @@ async function ensureSchema() {
|
|
|
3066
3219
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3067
3220
|
args: []
|
|
3068
3221
|
});
|
|
3069
|
-
} catch {
|
|
3222
|
+
} catch (e) {
|
|
3223
|
+
logCatchDebug("migration", e);
|
|
3070
3224
|
}
|
|
3071
3225
|
try {
|
|
3072
3226
|
await client.execute({
|
|
3073
3227
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
3074
3228
|
args: []
|
|
3075
3229
|
});
|
|
3076
|
-
} catch {
|
|
3230
|
+
} catch (e) {
|
|
3231
|
+
logCatchDebug("migration", e);
|
|
3077
3232
|
}
|
|
3078
3233
|
}
|
|
3079
3234
|
async function disposeDatabase() {
|
|
@@ -3084,7 +3239,8 @@ async function disposeDatabase() {
|
|
|
3084
3239
|
if (_client) {
|
|
3085
3240
|
try {
|
|
3086
3241
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3087
|
-
} catch {
|
|
3242
|
+
} catch (e) {
|
|
3243
|
+
logCatchDebug("WAL checkpoint", e);
|
|
3088
3244
|
}
|
|
3089
3245
|
}
|
|
3090
3246
|
if (_daemonClient) {
|
|
@@ -3100,8 +3256,9 @@ async function disposeDatabase() {
|
|
|
3100
3256
|
_client = null;
|
|
3101
3257
|
_resilientClient = null;
|
|
3102
3258
|
}
|
|
3259
|
+
releaseDbLock();
|
|
3103
3260
|
}
|
|
3104
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3261
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3105
3262
|
var init_database = __esm({
|
|
3106
3263
|
"src/lib/database.ts"() {
|
|
3107
3264
|
"use strict";
|
|
@@ -3109,11 +3266,14 @@ var init_database = __esm({
|
|
|
3109
3266
|
init_employees();
|
|
3110
3267
|
init_database_adapter();
|
|
3111
3268
|
init_memory();
|
|
3269
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
3112
3270
|
_client = null;
|
|
3113
3271
|
_resilientClient = null;
|
|
3114
3272
|
_walCheckpointTimer = null;
|
|
3115
3273
|
_daemonClient = null;
|
|
3116
3274
|
_adapterClient = null;
|
|
3275
|
+
_lockFd = null;
|
|
3276
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
3117
3277
|
initTurso = initDatabase;
|
|
3118
3278
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
3119
3279
|
disposeTurso = disposeDatabase;
|
|
@@ -3122,7 +3282,7 @@ var init_database = __esm({
|
|
|
3122
3282
|
|
|
3123
3283
|
// src/lib/keychain.ts
|
|
3124
3284
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3125
|
-
import { existsSync as
|
|
3285
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
3126
3286
|
import { execSync as execSync5 } from "child_process";
|
|
3127
3287
|
import path7 from "path";
|
|
3128
3288
|
import os5 from "os";
|
|
@@ -3157,7 +3317,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
3157
3317
|
if (process.platform !== "linux") return false;
|
|
3158
3318
|
try {
|
|
3159
3319
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3160
|
-
const st =
|
|
3320
|
+
const st = statSync3(keyPath);
|
|
3161
3321
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3162
3322
|
if (uid === 0) return true;
|
|
3163
3323
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -3358,7 +3518,7 @@ async function getMasterKey() {
|
|
|
3358
3518
|
}
|
|
3359
3519
|
}
|
|
3360
3520
|
const keyPath = getKeyPath();
|
|
3361
|
-
if (!
|
|
3521
|
+
if (!existsSync7(keyPath)) {
|
|
3362
3522
|
process.stderr.write(
|
|
3363
3523
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
3364
3524
|
`
|
|
@@ -3693,18 +3853,54 @@ __export(shard_manager_exports, {
|
|
|
3693
3853
|
shardExists: () => shardExists
|
|
3694
3854
|
});
|
|
3695
3855
|
import path8 from "path";
|
|
3696
|
-
import { existsSync as
|
|
3856
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readdirSync as readdirSync2, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
3697
3857
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3698
3858
|
function initShardManager(encryptionKey) {
|
|
3699
3859
|
_encryptionKey = encryptionKey;
|
|
3700
|
-
|
|
3701
|
-
|
|
3860
|
+
_keyValidated = false;
|
|
3861
|
+
_keyValidationPromise = null;
|
|
3862
|
+
if (!existsSync8(SHARDS_DIR)) {
|
|
3863
|
+
mkdirSync4(SHARDS_DIR, { recursive: true });
|
|
3864
|
+
}
|
|
3865
|
+
const existingShards = readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3866
|
+
if (existingShards.length === 0) {
|
|
3867
|
+
_keyValidated = true;
|
|
3702
3868
|
}
|
|
3703
3869
|
_shardingEnabled = true;
|
|
3704
3870
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
3705
3871
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
3706
3872
|
_evictionTimer.unref();
|
|
3707
3873
|
}
|
|
3874
|
+
async function validateEncryptionKey() {
|
|
3875
|
+
if (_keyValidated) return true;
|
|
3876
|
+
if (!_encryptionKey) return false;
|
|
3877
|
+
const existingShards = readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3878
|
+
if (existingShards.length === 0) {
|
|
3879
|
+
_keyValidated = true;
|
|
3880
|
+
return true;
|
|
3881
|
+
}
|
|
3882
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
3883
|
+
const dbPath = path8.join(SHARDS_DIR, shardFile);
|
|
3884
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
3885
|
+
try {
|
|
3886
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
3887
|
+
testClient.close();
|
|
3888
|
+
_keyValidated = true;
|
|
3889
|
+
return true;
|
|
3890
|
+
} catch {
|
|
3891
|
+
try {
|
|
3892
|
+
testClient.close();
|
|
3893
|
+
} catch {
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
}
|
|
3897
|
+
process.stderr.write(
|
|
3898
|
+
`[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.
|
|
3899
|
+
`
|
|
3900
|
+
);
|
|
3901
|
+
_shardingEnabled = false;
|
|
3902
|
+
return false;
|
|
3903
|
+
}
|
|
3708
3904
|
function isShardingEnabled() {
|
|
3709
3905
|
return _shardingEnabled;
|
|
3710
3906
|
}
|
|
@@ -3738,13 +3934,13 @@ function getShardClient(projectName) {
|
|
|
3738
3934
|
}
|
|
3739
3935
|
function shardExists(projectName) {
|
|
3740
3936
|
const safeName = safeShardName(projectName);
|
|
3741
|
-
return
|
|
3937
|
+
return existsSync8(path8.join(SHARDS_DIR, `${safeName}.db`));
|
|
3742
3938
|
}
|
|
3743
3939
|
function safeShardName(projectName) {
|
|
3744
3940
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3745
3941
|
}
|
|
3746
3942
|
function listShards() {
|
|
3747
|
-
if (!
|
|
3943
|
+
if (!existsSync8(SHARDS_DIR)) return [];
|
|
3748
3944
|
return readdirSync2(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
3749
3945
|
}
|
|
3750
3946
|
async function auditShardHealth(options = {}) {
|
|
@@ -3757,7 +3953,7 @@ async function auditShardHealth(options = {}) {
|
|
|
3757
3953
|
const shards = [];
|
|
3758
3954
|
for (const name of names) {
|
|
3759
3955
|
const dbPath = path8.join(SHARDS_DIR, `${name}.db`);
|
|
3760
|
-
const stat =
|
|
3956
|
+
const stat = statSync4(dbPath);
|
|
3761
3957
|
const item = {
|
|
3762
3958
|
name,
|
|
3763
3959
|
path: dbPath,
|
|
@@ -3997,6 +4193,17 @@ async function ensureShardSchema(client) {
|
|
|
3997
4193
|
}
|
|
3998
4194
|
}
|
|
3999
4195
|
async function getReadyShardClient(projectName) {
|
|
4196
|
+
if (!_keyValidated) {
|
|
4197
|
+
if (!_keyValidationPromise) {
|
|
4198
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
4199
|
+
}
|
|
4200
|
+
const valid = await _keyValidationPromise;
|
|
4201
|
+
if (!valid) {
|
|
4202
|
+
throw new Error(
|
|
4203
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
4204
|
+
);
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4000
4207
|
const safeName = safeShardName(projectName);
|
|
4001
4208
|
let client = getShardClient(projectName);
|
|
4002
4209
|
try {
|
|
@@ -4009,8 +4216,8 @@ async function getReadyShardClient(projectName) {
|
|
|
4009
4216
|
_shards.delete(safeName);
|
|
4010
4217
|
_shardLastAccess.delete(safeName);
|
|
4011
4218
|
const dbPath = path8.join(SHARDS_DIR, `${safeName}.db`);
|
|
4012
|
-
if (
|
|
4013
|
-
const stat =
|
|
4219
|
+
if (existsSync8(dbPath)) {
|
|
4220
|
+
const stat = statSync4(dbPath);
|
|
4014
4221
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4015
4222
|
const archivedPath = path8.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
4016
4223
|
renameSync3(dbPath, archivedPath);
|
|
@@ -4075,7 +4282,7 @@ function disposeShards() {
|
|
|
4075
4282
|
_shardingEnabled = false;
|
|
4076
4283
|
_encryptionKey = null;
|
|
4077
4284
|
}
|
|
4078
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
4285
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
4079
4286
|
var init_shard_manager = __esm({
|
|
4080
4287
|
"src/lib/shard-manager.ts"() {
|
|
4081
4288
|
"use strict";
|
|
@@ -4089,6 +4296,8 @@ var init_shard_manager = __esm({
|
|
|
4089
4296
|
_evictionTimer = null;
|
|
4090
4297
|
_encryptionKey = null;
|
|
4091
4298
|
_shardingEnabled = false;
|
|
4299
|
+
_keyValidated = false;
|
|
4300
|
+
_keyValidationPromise = null;
|
|
4092
4301
|
}
|
|
4093
4302
|
});
|
|
4094
4303
|
|
|
@@ -4284,6 +4493,18 @@ var init_platform_procedures = __esm({
|
|
|
4284
4493
|
priority: "p0",
|
|
4285
4494
|
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.'"
|
|
4286
4495
|
},
|
|
4496
|
+
{
|
|
4497
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
4498
|
+
domain: "workflow",
|
|
4499
|
+
priority: "p0",
|
|
4500
|
+
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."
|
|
4501
|
+
},
|
|
4502
|
+
{
|
|
4503
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
4504
|
+
domain: "workflow",
|
|
4505
|
+
priority: "p0",
|
|
4506
|
+
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."
|
|
4507
|
+
},
|
|
4287
4508
|
{
|
|
4288
4509
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
4289
4510
|
domain: "architecture",
|
|
@@ -4881,6 +5102,20 @@ __export(store_exports, {
|
|
|
4881
5102
|
vectorToBlob: () => vectorToBlob,
|
|
4882
5103
|
writeMemory: () => writeMemory
|
|
4883
5104
|
});
|
|
5105
|
+
function logStoreDebug(context, err) {
|
|
5106
|
+
if (_debugStore) {
|
|
5107
|
+
process.stderr.write(
|
|
5108
|
+
`[store] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5109
|
+
`
|
|
5110
|
+
);
|
|
5111
|
+
}
|
|
5112
|
+
}
|
|
5113
|
+
function logStoreWarn(context, err) {
|
|
5114
|
+
process.stderr.write(
|
|
5115
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5116
|
+
`
|
|
5117
|
+
);
|
|
5118
|
+
}
|
|
4884
5119
|
function isBusyError2(err) {
|
|
4885
5120
|
if (err instanceof Error) {
|
|
4886
5121
|
const msg = err.message.toLowerCase();
|
|
@@ -4935,13 +5170,15 @@ async function initStore(options) {
|
|
|
4935
5170
|
try {
|
|
4936
5171
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4937
5172
|
await initDaemonClient2();
|
|
4938
|
-
} catch {
|
|
5173
|
+
} catch (e) {
|
|
5174
|
+
logStoreWarn("catch", e);
|
|
4939
5175
|
}
|
|
4940
5176
|
if (!options?.lightweight) {
|
|
4941
5177
|
try {
|
|
4942
5178
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4943
5179
|
initShardManager2(hexKey);
|
|
4944
|
-
} catch {
|
|
5180
|
+
} catch (e) {
|
|
5181
|
+
logStoreWarn("catch", e);
|
|
4945
5182
|
}
|
|
4946
5183
|
const client = getClient();
|
|
4947
5184
|
const vResult = await retryOnBusy2(
|
|
@@ -4952,7 +5189,8 @@ async function initStore(options) {
|
|
|
4952
5189
|
try {
|
|
4953
5190
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4954
5191
|
await loadGlobalProcedures2();
|
|
4955
|
-
} catch {
|
|
5192
|
+
} catch (e) {
|
|
5193
|
+
logStoreWarn("catch", e);
|
|
4956
5194
|
}
|
|
4957
5195
|
}
|
|
4958
5196
|
}
|
|
@@ -5012,7 +5250,8 @@ async function writeMemory(record) {
|
|
|
5012
5250
|
memoryType
|
|
5013
5251
|
});
|
|
5014
5252
|
if (existing) return;
|
|
5015
|
-
} catch {
|
|
5253
|
+
} catch (e) {
|
|
5254
|
+
logStoreWarn("catch", e);
|
|
5016
5255
|
}
|
|
5017
5256
|
const dbRow = {
|
|
5018
5257
|
id: record.id,
|
|
@@ -5213,12 +5452,14 @@ async function flushBatch() {
|
|
|
5213
5452
|
try {
|
|
5214
5453
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
5215
5454
|
await insertMemoryCardsForBatch2(batch);
|
|
5216
|
-
} catch {
|
|
5455
|
+
} catch (e) {
|
|
5456
|
+
logStoreWarn("catch", e);
|
|
5217
5457
|
}
|
|
5218
5458
|
try {
|
|
5219
5459
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
5220
5460
|
await insertOntologyForBatch2(batch);
|
|
5221
|
-
} catch {
|
|
5461
|
+
} catch (e) {
|
|
5462
|
+
logStoreWarn("catch", e);
|
|
5222
5463
|
}
|
|
5223
5464
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
5224
5465
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -5257,7 +5498,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
5257
5498
|
}
|
|
5258
5499
|
}
|
|
5259
5500
|
}
|
|
5260
|
-
} catch {
|
|
5501
|
+
} catch (e) {
|
|
5502
|
+
logStoreWarn("catch", e);
|
|
5261
5503
|
}
|
|
5262
5504
|
return batch.length;
|
|
5263
5505
|
} finally {
|
|
@@ -5299,7 +5541,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
5299
5541
|
} else {
|
|
5300
5542
|
client = getClient();
|
|
5301
5543
|
}
|
|
5302
|
-
} catch {
|
|
5544
|
+
} catch (e) {
|
|
5545
|
+
logStoreDebug("shard routing fallback", e);
|
|
5303
5546
|
client = getClient();
|
|
5304
5547
|
}
|
|
5305
5548
|
const limit = options?.limit ?? 10;
|
|
@@ -5415,7 +5658,8 @@ async function attachDocumentMetadata(records) {
|
|
|
5415
5658
|
if (!record.document_id) continue;
|
|
5416
5659
|
record.document_metadata = byId.get(record.document_id) ?? null;
|
|
5417
5660
|
}
|
|
5418
|
-
} catch {
|
|
5661
|
+
} catch (e) {
|
|
5662
|
+
logStoreWarn("catch", e);
|
|
5419
5663
|
}
|
|
5420
5664
|
return records;
|
|
5421
5665
|
}
|
|
@@ -5476,11 +5720,12 @@ async function getMemoryCardinality(agentId) {
|
|
|
5476
5720
|
args: [agentId]
|
|
5477
5721
|
});
|
|
5478
5722
|
return Number(result.rows[0]?.cnt) || 0;
|
|
5479
|
-
} catch {
|
|
5723
|
+
} catch (e) {
|
|
5724
|
+
logStoreWarn("getMemoryCardinality", e);
|
|
5480
5725
|
return 0;
|
|
5481
5726
|
}
|
|
5482
5727
|
}
|
|
5483
|
-
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
5728
|
+
var _debugStore, INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
5484
5729
|
var init_store = __esm({
|
|
5485
5730
|
"src/lib/store.ts"() {
|
|
5486
5731
|
"use strict";
|
|
@@ -5490,6 +5735,7 @@ var init_store = __esm({
|
|
|
5490
5735
|
init_config();
|
|
5491
5736
|
init_state_bus();
|
|
5492
5737
|
init_memory_write_governor();
|
|
5738
|
+
_debugStore = process.env.EXE_DEBUG === "1";
|
|
5493
5739
|
INIT_MAX_RETRIES = 3;
|
|
5494
5740
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
5495
5741
|
_pendingRecords = [];
|