@askexenow/exe-os 0.9.102 → 0.9.104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agentic-ontology-backfill.js +334 -100
- package/dist/bin/agentic-reflection-backfill.js +328 -97
- package/dist/bin/agentic-semantic-label.js +328 -97
- package/dist/bin/backfill-conversations.js +332 -97
- package/dist/bin/backfill-responses.js +332 -97
- package/dist/bin/backfill-vectors.js +337 -106
- package/dist/bin/bulk-sync-postgres.js +335 -101
- package/dist/bin/cleanup-stale-review-tasks.js +356 -108
- package/dist/bin/cli.js +653 -405
- package/dist/bin/exe-agent.js +21 -3
- package/dist/bin/exe-assign.js +338 -94
- package/dist/bin/exe-boot.js +472 -239
- package/dist/bin/exe-call.js +22 -5
- package/dist/bin/exe-cloud.js +404 -158
- package/dist/bin/exe-dispatch.js +390 -142
- package/dist/bin/exe-doctor.js +349 -103
- package/dist/bin/exe-export-behaviors.js +351 -105
- package/dist/bin/exe-forget.js +352 -103
- package/dist/bin/exe-gateway.js +420 -172
- package/dist/bin/exe-heartbeat.js +361 -113
- package/dist/bin/exe-kill.js +344 -98
- package/dist/bin/exe-launch-agent.js +375 -129
- package/dist/bin/exe-new-employee.js +83 -67
- package/dist/bin/exe-pending-messages.js +356 -108
- package/dist/bin/exe-pending-notifications.js +358 -110
- package/dist/bin/exe-pending-reviews.js +359 -111
- package/dist/bin/exe-rename.js +354 -108
- package/dist/bin/exe-review.js +343 -97
- package/dist/bin/exe-search.js +363 -113
- package/dist/bin/exe-session-cleanup.js +403 -155
- package/dist/bin/exe-settings.js +14 -9
- package/dist/bin/exe-start-codex.js +365 -131
- package/dist/bin/exe-start-opencode.js +359 -125
- package/dist/bin/exe-status.js +356 -108
- package/dist/bin/exe-team.js +343 -97
- package/dist/bin/git-sweep.js +390 -142
- package/dist/bin/graph-backfill.js +334 -100
- package/dist/bin/graph-export.js +346 -100
- package/dist/bin/install.js +1 -0
- package/dist/bin/intercom-check.js +403 -155
- package/dist/bin/pre-publish.js +12 -0
- package/dist/bin/scan-tasks.js +393 -145
- package/dist/bin/setup.js +331 -159
- package/dist/bin/shard-migrate.js +328 -94
- package/dist/gateway/index.js +406 -158
- package/dist/hooks/bug-report-worker.js +396 -148
- package/dist/hooks/codex-stop-task-finalizer.js +374 -126
- package/dist/hooks/commit-complete.js +390 -142
- package/dist/hooks/error-recall.js +365 -115
- package/dist/hooks/ingest.js +357 -111
- package/dist/hooks/instructions-loaded.js +351 -105
- package/dist/hooks/notification.js +343 -97
- package/dist/hooks/post-compact.js +358 -110
- package/dist/hooks/post-tool-combined.js +384 -132
- package/dist/hooks/pre-compact.js +391 -143
- package/dist/hooks/pre-tool-use.js +362 -114
- package/dist/hooks/prompt-submit.js +422 -170
- package/dist/hooks/session-end.js +393 -145
- package/dist/hooks/session-start.js +390 -138
- package/dist/hooks/stop.js +361 -113
- package/dist/hooks/subagent-stop.js +354 -106
- package/dist/hooks/summary-worker.js +418 -185
- package/dist/index.js +400 -152
- package/dist/lib/cloud-sync.js +291 -131
- package/dist/lib/consolidation.js +8 -2
- package/dist/lib/database.js +233 -73
- package/dist/lib/db.js +233 -73
- package/dist/lib/device-registry.js +237 -77
- package/dist/lib/employee-templates.js +19 -1
- package/dist/lib/exe-daemon.js +705 -409
- package/dist/lib/hybrid-search.js +363 -113
- package/dist/lib/identity.js +9 -5
- package/dist/lib/messaging.js +26 -20
- package/dist/lib/reminders.js +5 -1
- package/dist/lib/schedules.js +320 -89
- package/dist/lib/skill-learning.js +28 -24
- package/dist/lib/store.js +342 -96
- package/dist/lib/tasks.js +82 -76
- package/dist/lib/tmux-routing.js +74 -68
- package/dist/lib/token-spend.js +5 -1
- package/dist/mcp/server.js +628 -355
- package/dist/mcp/tools/complete-reminder.js +5 -1
- package/dist/mcp/tools/create-reminder.js +5 -1
- package/dist/mcp/tools/create-task.js +89 -83
- package/dist/mcp/tools/deactivate-behavior.js +7 -3
- package/dist/mcp/tools/list-reminders.js +5 -1
- package/dist/mcp/tools/list-tasks.js +28 -21
- package/dist/mcp/tools/send-message.js +28 -22
- package/dist/mcp/tools/update-task.js +89 -83
- package/dist/runtime/index.js +390 -142
- package/dist/tui/App.js +437 -189
- package/package.json +1 -1
package/dist/bin/exe-review.js
CHANGED
|
@@ -1687,9 +1687,79 @@ __export(database_exports, {
|
|
|
1687
1687
|
isInitialized: () => isInitialized,
|
|
1688
1688
|
setExternalClient: () => setExternalClient
|
|
1689
1689
|
});
|
|
1690
|
-
import { chmodSync as chmodSync2 } from "fs";
|
|
1690
|
+
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";
|
|
1691
1691
|
import { createClient } from "@libsql/client";
|
|
1692
|
+
import { homedir } from "os";
|
|
1693
|
+
import { join } from "path";
|
|
1694
|
+
function logCatchDebug(context, err) {
|
|
1695
|
+
if (_debugDb) {
|
|
1696
|
+
process.stderr.write(
|
|
1697
|
+
`[database] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
1698
|
+
`
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
}
|
|
1702
|
+
function acquireDbLock() {
|
|
1703
|
+
mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
|
|
1704
|
+
try {
|
|
1705
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1706
|
+
} catch (err) {
|
|
1707
|
+
if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
|
|
1708
|
+
try {
|
|
1709
|
+
const lockStat = statSync2(DB_LOCK_PATH);
|
|
1710
|
+
if (Date.now() - lockStat.mtimeMs > 6e4) {
|
|
1711
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1712
|
+
_lockFd = openSync2(DB_LOCK_PATH, "wx");
|
|
1713
|
+
return;
|
|
1714
|
+
}
|
|
1715
|
+
} catch (e) {
|
|
1716
|
+
logCatchDebug("stale lock check", e);
|
|
1717
|
+
}
|
|
1718
|
+
process.stderr.write(
|
|
1719
|
+
"[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
|
|
1720
|
+
);
|
|
1721
|
+
return;
|
|
1722
|
+
}
|
|
1723
|
+
throw err;
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
function releaseDbLock() {
|
|
1727
|
+
if (_lockFd !== null) {
|
|
1728
|
+
try {
|
|
1729
|
+
closeSync2(_lockFd);
|
|
1730
|
+
} catch (e) {
|
|
1731
|
+
logCatchDebug("lock close", e);
|
|
1732
|
+
}
|
|
1733
|
+
_lockFd = null;
|
|
1734
|
+
}
|
|
1735
|
+
try {
|
|
1736
|
+
unlinkSync3(DB_LOCK_PATH);
|
|
1737
|
+
} catch (e) {
|
|
1738
|
+
logCatchDebug("lock unlink", e);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1692
1741
|
async function initDatabase(config) {
|
|
1742
|
+
acquireDbLock();
|
|
1743
|
+
if (existsSync6(config.dbPath)) {
|
|
1744
|
+
const dbStat = statSync2(config.dbPath);
|
|
1745
|
+
if (dbStat.size === 0) {
|
|
1746
|
+
const walPath = config.dbPath + "-wal";
|
|
1747
|
+
if (existsSync6(walPath) && statSync2(walPath).size > 0) {
|
|
1748
|
+
const backupPath = config.dbPath + ".zeroed-" + Date.now();
|
|
1749
|
+
copyFileSync(config.dbPath, backupPath);
|
|
1750
|
+
unlinkSync3(config.dbPath);
|
|
1751
|
+
process.stderr.write(
|
|
1752
|
+
`[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
|
|
1753
|
+
`
|
|
1754
|
+
);
|
|
1755
|
+
} else {
|
|
1756
|
+
process.stderr.write(
|
|
1757
|
+
`[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
|
|
1758
|
+
`
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1693
1763
|
if (_walCheckpointTimer) {
|
|
1694
1764
|
clearInterval(_walCheckpointTimer);
|
|
1695
1765
|
_walCheckpointTimer = null;
|
|
@@ -1716,10 +1786,8 @@ async function initDatabase(config) {
|
|
|
1716
1786
|
_client = createClient(opts);
|
|
1717
1787
|
_resilientClient = wrapWithRetry(_client);
|
|
1718
1788
|
_adapterClient = _resilientClient;
|
|
1719
|
-
_client.execute("PRAGMA busy_timeout = 30000")
|
|
1720
|
-
|
|
1721
|
-
_client.execute("PRAGMA journal_mode = WAL").catch(() => {
|
|
1722
|
-
});
|
|
1789
|
+
await _client.execute("PRAGMA busy_timeout = 30000");
|
|
1790
|
+
await _client.execute("PRAGMA journal_mode = WAL");
|
|
1723
1791
|
if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
|
|
1724
1792
|
_walCheckpointTimer = setInterval(() => {
|
|
1725
1793
|
_client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
|
|
@@ -1734,11 +1802,16 @@ async function initDatabase(config) {
|
|
|
1734
1802
|
for (const suffix of ["-wal", "-shm"]) {
|
|
1735
1803
|
try {
|
|
1736
1804
|
chmodSync2(config.dbPath + suffix, 384);
|
|
1737
|
-
} catch {
|
|
1805
|
+
} catch (chmodErr) {
|
|
1806
|
+
process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1807
|
+
`);
|
|
1738
1808
|
}
|
|
1739
1809
|
}
|
|
1740
|
-
} catch {
|
|
1810
|
+
} catch (chmodErr) {
|
|
1811
|
+
process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
|
|
1812
|
+
`);
|
|
1741
1813
|
}
|
|
1814
|
+
releaseDbLock();
|
|
1742
1815
|
}
|
|
1743
1816
|
function isInitialized() {
|
|
1744
1817
|
return _adapterClient !== null || _client !== null;
|
|
@@ -1793,7 +1866,8 @@ async function ensureSchema() {
|
|
|
1793
1866
|
await client.execute("PRAGMA wal_autocheckpoint = 1000");
|
|
1794
1867
|
try {
|
|
1795
1868
|
await client.execute("PRAGMA libsql_vector_search_ef = 128");
|
|
1796
|
-
} catch {
|
|
1869
|
+
} catch (e) {
|
|
1870
|
+
logCatchDebug("migration", e);
|
|
1797
1871
|
}
|
|
1798
1872
|
await client.executeMultiple(`
|
|
1799
1873
|
CREATE TABLE IF NOT EXISTS memories (
|
|
@@ -1858,6 +1932,23 @@ async function ensureSchema() {
|
|
|
1858
1932
|
INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
|
|
1859
1933
|
END;
|
|
1860
1934
|
`);
|
|
1935
|
+
try {
|
|
1936
|
+
await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
|
|
1937
|
+
} catch (ftsErr) {
|
|
1938
|
+
process.stderr.write(
|
|
1939
|
+
`[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
|
|
1940
|
+
`
|
|
1941
|
+
);
|
|
1942
|
+
try {
|
|
1943
|
+
await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
|
|
1944
|
+
process.stderr.write("[database] FTS index rebuilt successfully.\n");
|
|
1945
|
+
} catch (rebuildErr) {
|
|
1946
|
+
process.stderr.write(
|
|
1947
|
+
`[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
|
|
1948
|
+
`
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
}
|
|
1861
1952
|
await client.executeMultiple(`
|
|
1862
1953
|
CREATE TABLE IF NOT EXISTS sync_meta (
|
|
1863
1954
|
key TEXT PRIMARY KEY,
|
|
@@ -1916,35 +2007,40 @@ async function ensureSchema() {
|
|
|
1916
2007
|
});
|
|
1917
2008
|
}
|
|
1918
2009
|
}
|
|
1919
|
-
} catch {
|
|
2010
|
+
} catch (seedErr) {
|
|
2011
|
+
logCatchDebug("behavior seed", seedErr);
|
|
1920
2012
|
}
|
|
1921
2013
|
try {
|
|
1922
2014
|
await client.execute({
|
|
1923
2015
|
sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
|
|
1924
2016
|
args: []
|
|
1925
2017
|
});
|
|
1926
|
-
} catch {
|
|
2018
|
+
} catch (e) {
|
|
2019
|
+
logCatchDebug("migration", e);
|
|
1927
2020
|
}
|
|
1928
2021
|
try {
|
|
1929
2022
|
await client.execute({
|
|
1930
2023
|
sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
|
|
1931
2024
|
args: []
|
|
1932
2025
|
});
|
|
1933
|
-
} catch {
|
|
2026
|
+
} catch (e) {
|
|
2027
|
+
logCatchDebug("migration", e);
|
|
1934
2028
|
}
|
|
1935
2029
|
try {
|
|
1936
2030
|
await client.execute({
|
|
1937
2031
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
1938
2032
|
args: []
|
|
1939
2033
|
});
|
|
1940
|
-
} catch {
|
|
2034
|
+
} catch (e) {
|
|
2035
|
+
logCatchDebug("migration", e);
|
|
1941
2036
|
}
|
|
1942
2037
|
try {
|
|
1943
2038
|
await client.execute({
|
|
1944
2039
|
sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
|
|
1945
2040
|
args: []
|
|
1946
2041
|
});
|
|
1947
|
-
} catch {
|
|
2042
|
+
} catch (e) {
|
|
2043
|
+
logCatchDebug("migration", e);
|
|
1948
2044
|
}
|
|
1949
2045
|
try {
|
|
1950
2046
|
await client.execute({
|
|
@@ -1953,98 +2049,112 @@ async function ensureSchema() {
|
|
|
1953
2049
|
WHERE parent_task_id IS NOT NULL`,
|
|
1954
2050
|
args: []
|
|
1955
2051
|
});
|
|
1956
|
-
} catch {
|
|
2052
|
+
} catch (e) {
|
|
2053
|
+
logCatchDebug("migration", e);
|
|
1957
2054
|
}
|
|
1958
2055
|
try {
|
|
1959
2056
|
await client.execute({
|
|
1960
2057
|
sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
|
|
1961
2058
|
args: []
|
|
1962
2059
|
});
|
|
1963
|
-
} catch {
|
|
2060
|
+
} catch (e) {
|
|
2061
|
+
logCatchDebug("migration", e);
|
|
1964
2062
|
}
|
|
1965
2063
|
try {
|
|
1966
2064
|
await client.execute({
|
|
1967
2065
|
sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
|
|
1968
2066
|
args: []
|
|
1969
2067
|
});
|
|
1970
|
-
} catch {
|
|
2068
|
+
} catch (e) {
|
|
2069
|
+
logCatchDebug("migration", e);
|
|
1971
2070
|
}
|
|
1972
2071
|
try {
|
|
1973
2072
|
await client.execute({
|
|
1974
2073
|
sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
|
|
1975
2074
|
args: []
|
|
1976
2075
|
});
|
|
1977
|
-
} catch {
|
|
2076
|
+
} catch (e) {
|
|
2077
|
+
logCatchDebug("migration", e);
|
|
1978
2078
|
}
|
|
1979
2079
|
try {
|
|
1980
2080
|
await client.execute({
|
|
1981
2081
|
sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
|
|
1982
2082
|
args: []
|
|
1983
2083
|
});
|
|
1984
|
-
} catch {
|
|
2084
|
+
} catch (e) {
|
|
2085
|
+
logCatchDebug("migration", e);
|
|
1985
2086
|
}
|
|
1986
2087
|
try {
|
|
1987
2088
|
await client.execute({
|
|
1988
2089
|
sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
|
|
1989
2090
|
args: []
|
|
1990
2091
|
});
|
|
1991
|
-
} catch {
|
|
2092
|
+
} catch (e) {
|
|
2093
|
+
logCatchDebug("migration", e);
|
|
1992
2094
|
}
|
|
1993
2095
|
try {
|
|
1994
2096
|
await client.execute({
|
|
1995
2097
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
|
|
1996
2098
|
args: []
|
|
1997
2099
|
});
|
|
1998
|
-
} catch {
|
|
2100
|
+
} catch (e) {
|
|
2101
|
+
logCatchDebug("migration", e);
|
|
1999
2102
|
}
|
|
2000
2103
|
try {
|
|
2001
2104
|
await client.execute({
|
|
2002
2105
|
sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
|
|
2003
2106
|
args: []
|
|
2004
2107
|
});
|
|
2005
|
-
} catch {
|
|
2108
|
+
} catch (e) {
|
|
2109
|
+
logCatchDebug("migration", e);
|
|
2006
2110
|
}
|
|
2007
2111
|
try {
|
|
2008
2112
|
await client.execute({
|
|
2009
2113
|
sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
|
|
2010
2114
|
args: []
|
|
2011
2115
|
});
|
|
2012
|
-
} catch {
|
|
2116
|
+
} catch (e) {
|
|
2117
|
+
logCatchDebug("migration", e);
|
|
2013
2118
|
}
|
|
2014
2119
|
try {
|
|
2015
2120
|
await client.execute({
|
|
2016
2121
|
sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
|
|
2017
2122
|
args: []
|
|
2018
2123
|
});
|
|
2019
|
-
} catch {
|
|
2124
|
+
} catch (e) {
|
|
2125
|
+
logCatchDebug("migration", e);
|
|
2020
2126
|
}
|
|
2021
2127
|
try {
|
|
2022
2128
|
await client.execute({
|
|
2023
2129
|
sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
|
|
2024
2130
|
args: []
|
|
2025
2131
|
});
|
|
2026
|
-
} catch {
|
|
2132
|
+
} catch (e) {
|
|
2133
|
+
logCatchDebug("migration", e);
|
|
2027
2134
|
}
|
|
2028
2135
|
try {
|
|
2029
2136
|
await client.execute({
|
|
2030
2137
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2031
2138
|
args: []
|
|
2032
2139
|
});
|
|
2033
|
-
} catch {
|
|
2140
|
+
} catch (e) {
|
|
2141
|
+
logCatchDebug("migration", e);
|
|
2034
2142
|
}
|
|
2035
2143
|
try {
|
|
2036
2144
|
await client.execute({
|
|
2037
2145
|
sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
|
|
2038
2146
|
args: []
|
|
2039
2147
|
});
|
|
2040
|
-
} catch {
|
|
2148
|
+
} catch (e) {
|
|
2149
|
+
logCatchDebug("migration", e);
|
|
2041
2150
|
}
|
|
2042
2151
|
try {
|
|
2043
2152
|
await client.execute({
|
|
2044
2153
|
sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
|
|
2045
2154
|
args: []
|
|
2046
2155
|
});
|
|
2047
|
-
} catch {
|
|
2156
|
+
} catch (e) {
|
|
2157
|
+
logCatchDebug("migration", e);
|
|
2048
2158
|
}
|
|
2049
2159
|
await client.executeMultiple(`
|
|
2050
2160
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2149,14 +2259,16 @@ async function ensureSchema() {
|
|
|
2149
2259
|
sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
|
|
2150
2260
|
args: []
|
|
2151
2261
|
});
|
|
2152
|
-
} catch {
|
|
2262
|
+
} catch (e) {
|
|
2263
|
+
logCatchDebug("migration", e);
|
|
2153
2264
|
}
|
|
2154
2265
|
try {
|
|
2155
2266
|
await client.execute({
|
|
2156
2267
|
sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
|
|
2157
2268
|
args: []
|
|
2158
2269
|
});
|
|
2159
|
-
} catch {
|
|
2270
|
+
} catch (e) {
|
|
2271
|
+
logCatchDebug("migration", e);
|
|
2160
2272
|
}
|
|
2161
2273
|
await client.executeMultiple(`
|
|
2162
2274
|
CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
|
|
@@ -2182,7 +2294,8 @@ async function ensureSchema() {
|
|
|
2182
2294
|
sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
|
|
2183
2295
|
args: []
|
|
2184
2296
|
});
|
|
2185
|
-
} catch {
|
|
2297
|
+
} catch (e) {
|
|
2298
|
+
logCatchDebug("migration", e);
|
|
2186
2299
|
}
|
|
2187
2300
|
await client.executeMultiple(`
|
|
2188
2301
|
CREATE TABLE IF NOT EXISTS trajectories (
|
|
@@ -2206,7 +2319,8 @@ async function ensureSchema() {
|
|
|
2206
2319
|
`);
|
|
2207
2320
|
try {
|
|
2208
2321
|
await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
|
|
2209
|
-
} catch {
|
|
2322
|
+
} catch (e) {
|
|
2323
|
+
logCatchDebug("migration", e);
|
|
2210
2324
|
}
|
|
2211
2325
|
await client.executeMultiple(`
|
|
2212
2326
|
CREATE TABLE IF NOT EXISTS consolidations (
|
|
@@ -2243,63 +2357,72 @@ async function ensureSchema() {
|
|
|
2243
2357
|
sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
|
|
2244
2358
|
args: []
|
|
2245
2359
|
});
|
|
2246
|
-
} catch {
|
|
2360
|
+
} catch (e) {
|
|
2361
|
+
logCatchDebug("migration", e);
|
|
2247
2362
|
}
|
|
2248
2363
|
try {
|
|
2249
2364
|
await client.execute({
|
|
2250
2365
|
sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
|
|
2251
2366
|
args: []
|
|
2252
2367
|
});
|
|
2253
|
-
} catch {
|
|
2368
|
+
} catch (e) {
|
|
2369
|
+
logCatchDebug("migration", e);
|
|
2254
2370
|
}
|
|
2255
2371
|
try {
|
|
2256
2372
|
await client.execute({
|
|
2257
2373
|
sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
|
|
2258
2374
|
args: []
|
|
2259
2375
|
});
|
|
2260
|
-
} catch {
|
|
2376
|
+
} catch (e) {
|
|
2377
|
+
logCatchDebug("migration", e);
|
|
2261
2378
|
}
|
|
2262
2379
|
try {
|
|
2263
2380
|
await client.execute({
|
|
2264
2381
|
sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
|
|
2265
2382
|
args: []
|
|
2266
2383
|
});
|
|
2267
|
-
} catch {
|
|
2384
|
+
} catch (e) {
|
|
2385
|
+
logCatchDebug("migration", e);
|
|
2268
2386
|
}
|
|
2269
2387
|
try {
|
|
2270
2388
|
await client.execute({
|
|
2271
2389
|
sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
|
|
2272
2390
|
args: []
|
|
2273
2391
|
});
|
|
2274
|
-
} catch {
|
|
2392
|
+
} catch (e) {
|
|
2393
|
+
logCatchDebug("migration", e);
|
|
2275
2394
|
}
|
|
2276
2395
|
try {
|
|
2277
2396
|
await client.execute({
|
|
2278
2397
|
sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
|
|
2279
2398
|
args: []
|
|
2280
2399
|
});
|
|
2281
|
-
} catch {
|
|
2400
|
+
} catch (e) {
|
|
2401
|
+
logCatchDebug("migration", e);
|
|
2282
2402
|
}
|
|
2283
2403
|
try {
|
|
2284
2404
|
await client.execute({
|
|
2285
2405
|
sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
|
|
2286
2406
|
args: []
|
|
2287
2407
|
});
|
|
2288
|
-
} catch {
|
|
2408
|
+
} catch (e) {
|
|
2409
|
+
logCatchDebug("migration", e);
|
|
2289
2410
|
}
|
|
2290
2411
|
try {
|
|
2291
2412
|
await client.execute({
|
|
2292
2413
|
sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
|
|
2293
2414
|
args: []
|
|
2294
2415
|
});
|
|
2295
|
-
} catch {
|
|
2416
|
+
} catch (e) {
|
|
2417
|
+
logCatchDebug("migration", e);
|
|
2296
2418
|
}
|
|
2297
2419
|
try {
|
|
2298
2420
|
await client.execute({
|
|
2299
2421
|
sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
|
|
2300
2422
|
args: []
|
|
2301
2423
|
});
|
|
2302
|
-
} catch {
|
|
2424
|
+
} catch (e) {
|
|
2425
|
+
logCatchDebug("migration", e);
|
|
2303
2426
|
}
|
|
2304
2427
|
for (const col of [
|
|
2305
2428
|
"ALTER TABLE memories ADD COLUMN content_hash TEXT",
|
|
@@ -2307,14 +2430,16 @@ async function ensureSchema() {
|
|
|
2307
2430
|
]) {
|
|
2308
2431
|
try {
|
|
2309
2432
|
await client.execute(col);
|
|
2310
|
-
} catch {
|
|
2433
|
+
} catch (e) {
|
|
2434
|
+
logCatchDebug("migration", e);
|
|
2311
2435
|
}
|
|
2312
2436
|
}
|
|
2313
2437
|
try {
|
|
2314
2438
|
await client.execute(
|
|
2315
2439
|
`CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
|
|
2316
2440
|
);
|
|
2317
|
-
} catch {
|
|
2441
|
+
} catch (e) {
|
|
2442
|
+
logCatchDebug("migration", e);
|
|
2318
2443
|
}
|
|
2319
2444
|
try {
|
|
2320
2445
|
await client.execute(
|
|
@@ -2322,7 +2447,8 @@ async function ensureSchema() {
|
|
|
2322
2447
|
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2323
2448
|
WHERE content_hash IS NOT NULL`
|
|
2324
2449
|
);
|
|
2325
|
-
} catch {
|
|
2450
|
+
} catch (e) {
|
|
2451
|
+
logCatchDebug("migration", e);
|
|
2326
2452
|
}
|
|
2327
2453
|
await client.executeMultiple(`
|
|
2328
2454
|
CREATE TABLE IF NOT EXISTS entities (
|
|
@@ -2398,7 +2524,8 @@ async function ensureSchema() {
|
|
|
2398
2524
|
`);
|
|
2399
2525
|
try {
|
|
2400
2526
|
await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
|
|
2401
|
-
} catch {
|
|
2527
|
+
} catch (e) {
|
|
2528
|
+
logCatchDebug("migration", e);
|
|
2402
2529
|
}
|
|
2403
2530
|
await client.executeMultiple(`
|
|
2404
2531
|
CREATE TABLE IF NOT EXISTS entity_aliases (
|
|
@@ -2413,14 +2540,16 @@ async function ensureSchema() {
|
|
|
2413
2540
|
]) {
|
|
2414
2541
|
try {
|
|
2415
2542
|
await client.execute(col);
|
|
2416
|
-
} catch {
|
|
2543
|
+
} catch (e) {
|
|
2544
|
+
logCatchDebug("migration", e);
|
|
2417
2545
|
}
|
|
2418
2546
|
}
|
|
2419
2547
|
try {
|
|
2420
2548
|
await client.execute(
|
|
2421
2549
|
`CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
|
|
2422
2550
|
);
|
|
2423
|
-
} catch {
|
|
2551
|
+
} catch (e) {
|
|
2552
|
+
logCatchDebug("migration", e);
|
|
2424
2553
|
}
|
|
2425
2554
|
await client.executeMultiple(`
|
|
2426
2555
|
CREATE TABLE IF NOT EXISTS identity (
|
|
@@ -2519,7 +2648,8 @@ async function ensureSchema() {
|
|
|
2519
2648
|
sql: `ALTER TABLE memories ADD COLUMN ${column}`,
|
|
2520
2649
|
args: []
|
|
2521
2650
|
});
|
|
2522
|
-
} catch {
|
|
2651
|
+
} catch (e) {
|
|
2652
|
+
logCatchDebug("migration", e);
|
|
2523
2653
|
}
|
|
2524
2654
|
}
|
|
2525
2655
|
for (const col of [
|
|
@@ -2528,7 +2658,8 @@ async function ensureSchema() {
|
|
|
2528
2658
|
]) {
|
|
2529
2659
|
try {
|
|
2530
2660
|
await client.execute(col);
|
|
2531
|
-
} catch {
|
|
2661
|
+
} catch (e) {
|
|
2662
|
+
logCatchDebug("migration", e);
|
|
2532
2663
|
}
|
|
2533
2664
|
}
|
|
2534
2665
|
await client.executeMultiple(`
|
|
@@ -2713,56 +2844,64 @@ async function ensureSchema() {
|
|
|
2713
2844
|
args: []
|
|
2714
2845
|
});
|
|
2715
2846
|
}
|
|
2716
|
-
} catch {
|
|
2847
|
+
} catch (e) {
|
|
2848
|
+
logCatchDebug("session_agent_map backfill", e);
|
|
2717
2849
|
}
|
|
2718
2850
|
try {
|
|
2719
2851
|
await client.execute({
|
|
2720
2852
|
sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
|
|
2721
2853
|
args: []
|
|
2722
2854
|
});
|
|
2723
|
-
} catch {
|
|
2855
|
+
} catch (e) {
|
|
2856
|
+
logCatchDebug("migration", e);
|
|
2724
2857
|
}
|
|
2725
2858
|
try {
|
|
2726
2859
|
await client.execute({
|
|
2727
2860
|
sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
|
|
2728
2861
|
args: []
|
|
2729
2862
|
});
|
|
2730
|
-
} catch {
|
|
2863
|
+
} catch (e) {
|
|
2864
|
+
logCatchDebug("migration", e);
|
|
2731
2865
|
}
|
|
2732
2866
|
try {
|
|
2733
2867
|
await client.execute({
|
|
2734
2868
|
sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
|
|
2735
2869
|
args: []
|
|
2736
2870
|
});
|
|
2737
|
-
} catch {
|
|
2871
|
+
} catch (e) {
|
|
2872
|
+
logCatchDebug("migration", e);
|
|
2738
2873
|
}
|
|
2739
2874
|
try {
|
|
2740
2875
|
await client.execute({
|
|
2741
2876
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
|
|
2742
2877
|
args: []
|
|
2743
2878
|
});
|
|
2744
|
-
} catch {
|
|
2879
|
+
} catch (e) {
|
|
2880
|
+
logCatchDebug("migration", e);
|
|
2745
2881
|
}
|
|
2746
2882
|
try {
|
|
2747
2883
|
await client.execute({
|
|
2748
2884
|
sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
|
|
2749
2885
|
args: []
|
|
2750
2886
|
});
|
|
2751
|
-
} catch {
|
|
2887
|
+
} catch (e) {
|
|
2888
|
+
logCatchDebug("migration", e);
|
|
2752
2889
|
}
|
|
2753
2890
|
try {
|
|
2754
2891
|
await client.execute({
|
|
2755
2892
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
|
|
2756
2893
|
args: []
|
|
2757
2894
|
});
|
|
2758
|
-
} catch {
|
|
2895
|
+
} catch (e) {
|
|
2896
|
+
logCatchDebug("migration", e);
|
|
2759
2897
|
}
|
|
2760
2898
|
try {
|
|
2761
2899
|
await client.execute({
|
|
2762
2900
|
sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
|
|
2763
2901
|
args: []
|
|
2764
2902
|
});
|
|
2765
|
-
} catch {
|
|
2903
|
+
} catch (e) {
|
|
2904
|
+
logCatchDebug("migration", e);
|
|
2766
2905
|
}
|
|
2767
2906
|
await client.executeMultiple(`
|
|
2768
2907
|
CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
|
|
@@ -2961,13 +3100,15 @@ async function ensureSchema() {
|
|
|
2961
3100
|
sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
|
|
2962
3101
|
args: []
|
|
2963
3102
|
});
|
|
2964
|
-
} catch {
|
|
3103
|
+
} catch (e) {
|
|
3104
|
+
logCatchDebug("migration", e);
|
|
2965
3105
|
}
|
|
2966
3106
|
try {
|
|
2967
3107
|
await client.execute(
|
|
2968
3108
|
`CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
|
|
2969
3109
|
);
|
|
2970
|
-
} catch {
|
|
3110
|
+
} catch (e) {
|
|
3111
|
+
logCatchDebug("migration", e);
|
|
2971
3112
|
}
|
|
2972
3113
|
try {
|
|
2973
3114
|
await client.execute({
|
|
@@ -2978,20 +3119,23 @@ async function ensureSchema() {
|
|
|
2978
3119
|
sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
|
|
2979
3120
|
args: []
|
|
2980
3121
|
});
|
|
2981
|
-
} catch {
|
|
3122
|
+
} catch (e) {
|
|
3123
|
+
logCatchDebug("migration", e);
|
|
2982
3124
|
}
|
|
2983
3125
|
try {
|
|
2984
3126
|
await client.execute({
|
|
2985
3127
|
sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
|
|
2986
3128
|
args: []
|
|
2987
3129
|
});
|
|
2988
|
-
} catch {
|
|
3130
|
+
} catch (e) {
|
|
3131
|
+
logCatchDebug("migration", e);
|
|
2989
3132
|
}
|
|
2990
3133
|
try {
|
|
2991
3134
|
await client.execute(
|
|
2992
3135
|
`CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
|
|
2993
3136
|
);
|
|
2994
|
-
} catch {
|
|
3137
|
+
} catch (e) {
|
|
3138
|
+
logCatchDebug("migration", e);
|
|
2995
3139
|
}
|
|
2996
3140
|
for (const col of [
|
|
2997
3141
|
"ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
|
|
@@ -2999,7 +3143,8 @@ async function ensureSchema() {
|
|
|
2999
3143
|
]) {
|
|
3000
3144
|
try {
|
|
3001
3145
|
await client.execute(col);
|
|
3002
|
-
} catch {
|
|
3146
|
+
} catch (e) {
|
|
3147
|
+
logCatchDebug("migration", e);
|
|
3003
3148
|
}
|
|
3004
3149
|
}
|
|
3005
3150
|
try {
|
|
@@ -3007,13 +3152,15 @@ async function ensureSchema() {
|
|
|
3007
3152
|
sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
|
|
3008
3153
|
args: []
|
|
3009
3154
|
});
|
|
3010
|
-
} catch {
|
|
3155
|
+
} catch (e) {
|
|
3156
|
+
logCatchDebug("migration", e);
|
|
3011
3157
|
}
|
|
3012
3158
|
try {
|
|
3013
3159
|
await client.execute(
|
|
3014
3160
|
`CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
|
|
3015
3161
|
);
|
|
3016
|
-
} catch {
|
|
3162
|
+
} catch (e) {
|
|
3163
|
+
logCatchDebug("migration", e);
|
|
3017
3164
|
}
|
|
3018
3165
|
for (const col of [
|
|
3019
3166
|
"ALTER TABLE memories ADD COLUMN valid_from TEXT",
|
|
@@ -3021,7 +3168,8 @@ async function ensureSchema() {
|
|
|
3021
3168
|
]) {
|
|
3022
3169
|
try {
|
|
3023
3170
|
await client.execute(col);
|
|
3024
|
-
} catch {
|
|
3171
|
+
} catch (e) {
|
|
3172
|
+
logCatchDebug("migration", e);
|
|
3025
3173
|
}
|
|
3026
3174
|
}
|
|
3027
3175
|
try {
|
|
@@ -3029,27 +3177,31 @@ async function ensureSchema() {
|
|
|
3029
3177
|
sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
|
|
3030
3178
|
args: []
|
|
3031
3179
|
});
|
|
3032
|
-
} catch {
|
|
3180
|
+
} catch (e) {
|
|
3181
|
+
logCatchDebug("migration", e);
|
|
3033
3182
|
}
|
|
3034
3183
|
try {
|
|
3035
3184
|
await client.execute({
|
|
3036
3185
|
sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
|
|
3037
3186
|
args: []
|
|
3038
3187
|
});
|
|
3039
|
-
} catch {
|
|
3188
|
+
} catch (e) {
|
|
3189
|
+
logCatchDebug("migration", e);
|
|
3040
3190
|
}
|
|
3041
3191
|
try {
|
|
3042
3192
|
await client.execute(
|
|
3043
3193
|
`CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
|
|
3044
3194
|
);
|
|
3045
|
-
} catch {
|
|
3195
|
+
} catch (e) {
|
|
3196
|
+
logCatchDebug("migration", e);
|
|
3046
3197
|
}
|
|
3047
3198
|
try {
|
|
3048
3199
|
await client.execute({
|
|
3049
3200
|
sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
|
|
3050
3201
|
args: []
|
|
3051
3202
|
});
|
|
3052
|
-
} catch {
|
|
3203
|
+
} catch (e) {
|
|
3204
|
+
logCatchDebug("migration", e);
|
|
3053
3205
|
}
|
|
3054
3206
|
for (const col of [
|
|
3055
3207
|
"ALTER TABLE memories ADD COLUMN intent TEXT",
|
|
@@ -3070,7 +3222,8 @@ async function ensureSchema() {
|
|
|
3070
3222
|
]) {
|
|
3071
3223
|
try {
|
|
3072
3224
|
await client.execute(col);
|
|
3073
|
-
} catch {
|
|
3225
|
+
} catch (e) {
|
|
3226
|
+
logCatchDebug("migration", e);
|
|
3074
3227
|
}
|
|
3075
3228
|
}
|
|
3076
3229
|
try {
|
|
@@ -3078,14 +3231,16 @@ async function ensureSchema() {
|
|
|
3078
3231
|
sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
|
|
3079
3232
|
args: []
|
|
3080
3233
|
});
|
|
3081
|
-
} catch {
|
|
3234
|
+
} catch (e) {
|
|
3235
|
+
logCatchDebug("migration", e);
|
|
3082
3236
|
}
|
|
3083
3237
|
try {
|
|
3084
3238
|
await client.execute({
|
|
3085
3239
|
sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
|
|
3086
3240
|
args: []
|
|
3087
3241
|
});
|
|
3088
|
-
} catch {
|
|
3242
|
+
} catch (e) {
|
|
3243
|
+
logCatchDebug("migration", e);
|
|
3089
3244
|
}
|
|
3090
3245
|
}
|
|
3091
3246
|
async function disposeDatabase() {
|
|
@@ -3096,7 +3251,8 @@ async function disposeDatabase() {
|
|
|
3096
3251
|
if (_client) {
|
|
3097
3252
|
try {
|
|
3098
3253
|
await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
|
|
3099
|
-
} catch {
|
|
3254
|
+
} catch (e) {
|
|
3255
|
+
logCatchDebug("WAL checkpoint", e);
|
|
3100
3256
|
}
|
|
3101
3257
|
}
|
|
3102
3258
|
if (_daemonClient) {
|
|
@@ -3112,8 +3268,9 @@ async function disposeDatabase() {
|
|
|
3112
3268
|
_client = null;
|
|
3113
3269
|
_resilientClient = null;
|
|
3114
3270
|
}
|
|
3271
|
+
releaseDbLock();
|
|
3115
3272
|
}
|
|
3116
|
-
var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3273
|
+
var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
|
|
3117
3274
|
var init_database = __esm({
|
|
3118
3275
|
"src/lib/database.ts"() {
|
|
3119
3276
|
"use strict";
|
|
@@ -3121,11 +3278,14 @@ var init_database = __esm({
|
|
|
3121
3278
|
init_employees();
|
|
3122
3279
|
init_database_adapter();
|
|
3123
3280
|
init_memory();
|
|
3281
|
+
_debugDb = process.env.EXE_DEBUG === "1";
|
|
3124
3282
|
_client = null;
|
|
3125
3283
|
_resilientClient = null;
|
|
3126
3284
|
_walCheckpointTimer = null;
|
|
3127
3285
|
_daemonClient = null;
|
|
3128
3286
|
_adapterClient = null;
|
|
3287
|
+
_lockFd = null;
|
|
3288
|
+
DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
|
|
3129
3289
|
initTurso = initDatabase;
|
|
3130
3290
|
SOFT_DELETE_RETENTION_DAYS = 7;
|
|
3131
3291
|
disposeTurso = disposeDatabase;
|
|
@@ -3134,7 +3294,7 @@ var init_database = __esm({
|
|
|
3134
3294
|
|
|
3135
3295
|
// src/lib/keychain.ts
|
|
3136
3296
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
3137
|
-
import { existsSync as
|
|
3297
|
+
import { existsSync as existsSync7, statSync as statSync3 } from "fs";
|
|
3138
3298
|
import { execSync as execSync3 } from "child_process";
|
|
3139
3299
|
import path6 from "path";
|
|
3140
3300
|
import os5 from "os";
|
|
@@ -3169,7 +3329,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
|
|
|
3169
3329
|
if (process.platform !== "linux") return false;
|
|
3170
3330
|
try {
|
|
3171
3331
|
const uid = typeof os5.userInfo().uid === "number" ? os5.userInfo().uid : -1;
|
|
3172
|
-
const st =
|
|
3332
|
+
const st = statSync3(keyPath);
|
|
3173
3333
|
if (!st.isFile() || (st.mode & 63) !== 0) return false;
|
|
3174
3334
|
if (uid === 0) return true;
|
|
3175
3335
|
const exeOsDir = process.env.EXE_OS_DIR;
|
|
@@ -3370,7 +3530,7 @@ async function getMasterKey() {
|
|
|
3370
3530
|
}
|
|
3371
3531
|
}
|
|
3372
3532
|
const keyPath = getKeyPath();
|
|
3373
|
-
if (!
|
|
3533
|
+
if (!existsSync7(keyPath)) {
|
|
3374
3534
|
process.stderr.write(
|
|
3375
3535
|
`[keychain] Key not found at ${keyPath} (HOME=${os5.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
|
|
3376
3536
|
`
|
|
@@ -3705,18 +3865,54 @@ __export(shard_manager_exports, {
|
|
|
3705
3865
|
shardExists: () => shardExists
|
|
3706
3866
|
});
|
|
3707
3867
|
import path7 from "path";
|
|
3708
|
-
import { existsSync as
|
|
3868
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync3, readdirSync, renameSync as renameSync3, statSync as statSync4 } from "fs";
|
|
3709
3869
|
import { createClient as createClient2 } from "@libsql/client";
|
|
3710
3870
|
function initShardManager(encryptionKey) {
|
|
3711
3871
|
_encryptionKey = encryptionKey;
|
|
3712
|
-
|
|
3713
|
-
|
|
3872
|
+
_keyValidated = false;
|
|
3873
|
+
_keyValidationPromise = null;
|
|
3874
|
+
if (!existsSync8(SHARDS_DIR)) {
|
|
3875
|
+
mkdirSync3(SHARDS_DIR, { recursive: true });
|
|
3876
|
+
}
|
|
3877
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3878
|
+
if (existingShards.length === 0) {
|
|
3879
|
+
_keyValidated = true;
|
|
3714
3880
|
}
|
|
3715
3881
|
_shardingEnabled = true;
|
|
3716
3882
|
if (_evictionTimer) clearInterval(_evictionTimer);
|
|
3717
3883
|
_evictionTimer = setInterval(evictIdleShards, EVICTION_INTERVAL_MS);
|
|
3718
3884
|
_evictionTimer.unref();
|
|
3719
3885
|
}
|
|
3886
|
+
async function validateEncryptionKey() {
|
|
3887
|
+
if (_keyValidated) return true;
|
|
3888
|
+
if (!_encryptionKey) return false;
|
|
3889
|
+
const existingShards = readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db"));
|
|
3890
|
+
if (existingShards.length === 0) {
|
|
3891
|
+
_keyValidated = true;
|
|
3892
|
+
return true;
|
|
3893
|
+
}
|
|
3894
|
+
for (const shardFile of existingShards.slice(0, 3)) {
|
|
3895
|
+
const dbPath = path7.join(SHARDS_DIR, shardFile);
|
|
3896
|
+
const testClient = createClient2({ url: `file:${dbPath}`, encryptionKey: _encryptionKey });
|
|
3897
|
+
try {
|
|
3898
|
+
await testClient.execute("SELECT COUNT(*) FROM sqlite_schema");
|
|
3899
|
+
testClient.close();
|
|
3900
|
+
_keyValidated = true;
|
|
3901
|
+
return true;
|
|
3902
|
+
} catch {
|
|
3903
|
+
try {
|
|
3904
|
+
testClient.close();
|
|
3905
|
+
} catch {
|
|
3906
|
+
}
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3909
|
+
process.stderr.write(
|
|
3910
|
+
`[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.
|
|
3911
|
+
`
|
|
3912
|
+
);
|
|
3913
|
+
_shardingEnabled = false;
|
|
3914
|
+
return false;
|
|
3915
|
+
}
|
|
3720
3916
|
function isShardingEnabled() {
|
|
3721
3917
|
return _shardingEnabled;
|
|
3722
3918
|
}
|
|
@@ -3750,13 +3946,13 @@ function getShardClient(projectName) {
|
|
|
3750
3946
|
}
|
|
3751
3947
|
function shardExists(projectName) {
|
|
3752
3948
|
const safeName = safeShardName(projectName);
|
|
3753
|
-
return
|
|
3949
|
+
return existsSync8(path7.join(SHARDS_DIR, `${safeName}.db`));
|
|
3754
3950
|
}
|
|
3755
3951
|
function safeShardName(projectName) {
|
|
3756
3952
|
return projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
3757
3953
|
}
|
|
3758
3954
|
function listShards() {
|
|
3759
|
-
if (!
|
|
3955
|
+
if (!existsSync8(SHARDS_DIR)) return [];
|
|
3760
3956
|
return readdirSync(SHARDS_DIR).filter((f) => f.endsWith(".db")).map((f) => f.replace(".db", ""));
|
|
3761
3957
|
}
|
|
3762
3958
|
async function auditShardHealth(options = {}) {
|
|
@@ -3769,7 +3965,7 @@ async function auditShardHealth(options = {}) {
|
|
|
3769
3965
|
const shards = [];
|
|
3770
3966
|
for (const name of names) {
|
|
3771
3967
|
const dbPath = path7.join(SHARDS_DIR, `${name}.db`);
|
|
3772
|
-
const stat =
|
|
3968
|
+
const stat = statSync4(dbPath);
|
|
3773
3969
|
const item = {
|
|
3774
3970
|
name,
|
|
3775
3971
|
path: dbPath,
|
|
@@ -4009,6 +4205,17 @@ async function ensureShardSchema(client) {
|
|
|
4009
4205
|
}
|
|
4010
4206
|
}
|
|
4011
4207
|
async function getReadyShardClient(projectName) {
|
|
4208
|
+
if (!_keyValidated) {
|
|
4209
|
+
if (!_keyValidationPromise) {
|
|
4210
|
+
_keyValidationPromise = validateEncryptionKey();
|
|
4211
|
+
}
|
|
4212
|
+
const valid = await _keyValidationPromise;
|
|
4213
|
+
if (!valid) {
|
|
4214
|
+
throw new Error(
|
|
4215
|
+
`Shard creation blocked: encryption key mismatch with existing shards. Run /exe-doctor to audit.`
|
|
4216
|
+
);
|
|
4217
|
+
}
|
|
4218
|
+
}
|
|
4012
4219
|
const safeName = safeShardName(projectName);
|
|
4013
4220
|
let client = getShardClient(projectName);
|
|
4014
4221
|
try {
|
|
@@ -4021,8 +4228,8 @@ async function getReadyShardClient(projectName) {
|
|
|
4021
4228
|
_shards.delete(safeName);
|
|
4022
4229
|
_shardLastAccess.delete(safeName);
|
|
4023
4230
|
const dbPath = path7.join(SHARDS_DIR, `${safeName}.db`);
|
|
4024
|
-
if (
|
|
4025
|
-
const stat =
|
|
4231
|
+
if (existsSync8(dbPath)) {
|
|
4232
|
+
const stat = statSync4(dbPath);
|
|
4026
4233
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
4027
4234
|
const archivedPath = path7.join(SHARDS_DIR, `${safeName}.db.broken-${stamp}`);
|
|
4028
4235
|
renameSync3(dbPath, archivedPath);
|
|
@@ -4087,7 +4294,7 @@ function disposeShards() {
|
|
|
4087
4294
|
_shardingEnabled = false;
|
|
4088
4295
|
_encryptionKey = null;
|
|
4089
4296
|
}
|
|
4090
|
-
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled;
|
|
4297
|
+
var SHARDS_DIR, SHARD_IDLE_MS, MAX_OPEN_SHARDS, EVICTION_INTERVAL_MS, _shards, _shardLastAccess, _evictionTimer, _encryptionKey, _shardingEnabled, _keyValidated, _keyValidationPromise;
|
|
4091
4298
|
var init_shard_manager = __esm({
|
|
4092
4299
|
"src/lib/shard-manager.ts"() {
|
|
4093
4300
|
"use strict";
|
|
@@ -4101,6 +4308,8 @@ var init_shard_manager = __esm({
|
|
|
4101
4308
|
_evictionTimer = null;
|
|
4102
4309
|
_encryptionKey = null;
|
|
4103
4310
|
_shardingEnabled = false;
|
|
4311
|
+
_keyValidated = false;
|
|
4312
|
+
_keyValidationPromise = null;
|
|
4104
4313
|
}
|
|
4105
4314
|
});
|
|
4106
4315
|
|
|
@@ -4296,6 +4505,18 @@ var init_platform_procedures = __esm({
|
|
|
4296
4505
|
priority: "p0",
|
|
4297
4506
|
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.'"
|
|
4298
4507
|
},
|
|
4508
|
+
{
|
|
4509
|
+
title: "Review chain \u2014 managers must actively pull completed work, never wait for nudges",
|
|
4510
|
+
domain: "workflow",
|
|
4511
|
+
priority: "p0",
|
|
4512
|
+
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."
|
|
4513
|
+
},
|
|
4514
|
+
{
|
|
4515
|
+
title: "Bug fix lifecycle \u2014 triage upstream after every verified fix so customers see the status",
|
|
4516
|
+
domain: "workflow",
|
|
4517
|
+
priority: "p0",
|
|
4518
|
+
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."
|
|
4519
|
+
},
|
|
4299
4520
|
{
|
|
4300
4521
|
title: "Intercom is a speedup, not delivery \u2014 DB is the source of truth",
|
|
4301
4522
|
domain: "architecture",
|
|
@@ -4893,6 +5114,20 @@ __export(store_exports, {
|
|
|
4893
5114
|
vectorToBlob: () => vectorToBlob,
|
|
4894
5115
|
writeMemory: () => writeMemory
|
|
4895
5116
|
});
|
|
5117
|
+
function logStoreDebug(context, err) {
|
|
5118
|
+
if (_debugStore) {
|
|
5119
|
+
process.stderr.write(
|
|
5120
|
+
`[store] ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5121
|
+
`
|
|
5122
|
+
);
|
|
5123
|
+
}
|
|
5124
|
+
}
|
|
5125
|
+
function logStoreWarn(context, err) {
|
|
5126
|
+
process.stderr.write(
|
|
5127
|
+
`[store] WARN ${context}: ${err instanceof Error ? err.message : String(err)}
|
|
5128
|
+
`
|
|
5129
|
+
);
|
|
5130
|
+
}
|
|
4896
5131
|
function isBusyError2(err) {
|
|
4897
5132
|
if (err instanceof Error) {
|
|
4898
5133
|
const msg = err.message.toLowerCase();
|
|
@@ -4947,13 +5182,15 @@ async function initStore(options) {
|
|
|
4947
5182
|
try {
|
|
4948
5183
|
const { initDaemonClient: initDaemonClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4949
5184
|
await initDaemonClient2();
|
|
4950
|
-
} catch {
|
|
5185
|
+
} catch (e) {
|
|
5186
|
+
logStoreWarn("catch", e);
|
|
4951
5187
|
}
|
|
4952
5188
|
if (!options?.lightweight) {
|
|
4953
5189
|
try {
|
|
4954
5190
|
const { initShardManager: initShardManager2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4955
5191
|
initShardManager2(hexKey);
|
|
4956
|
-
} catch {
|
|
5192
|
+
} catch (e) {
|
|
5193
|
+
logStoreWarn("catch", e);
|
|
4957
5194
|
}
|
|
4958
5195
|
const client = getClient();
|
|
4959
5196
|
const vResult = await retryOnBusy2(
|
|
@@ -4964,7 +5201,8 @@ async function initStore(options) {
|
|
|
4964
5201
|
try {
|
|
4965
5202
|
const { loadGlobalProcedures: loadGlobalProcedures2 } = await Promise.resolve().then(() => (init_global_procedures(), global_procedures_exports));
|
|
4966
5203
|
await loadGlobalProcedures2();
|
|
4967
|
-
} catch {
|
|
5204
|
+
} catch (e) {
|
|
5205
|
+
logStoreWarn("catch", e);
|
|
4968
5206
|
}
|
|
4969
5207
|
}
|
|
4970
5208
|
}
|
|
@@ -5024,7 +5262,8 @@ async function writeMemory(record) {
|
|
|
5024
5262
|
memoryType
|
|
5025
5263
|
});
|
|
5026
5264
|
if (existing) return;
|
|
5027
|
-
} catch {
|
|
5265
|
+
} catch (e) {
|
|
5266
|
+
logStoreWarn("catch", e);
|
|
5028
5267
|
}
|
|
5029
5268
|
const dbRow = {
|
|
5030
5269
|
id: record.id,
|
|
@@ -5225,12 +5464,14 @@ async function flushBatch() {
|
|
|
5225
5464
|
try {
|
|
5226
5465
|
const { insertMemoryCardsForBatch: insertMemoryCardsForBatch2 } = await Promise.resolve().then(() => (init_memory_cards(), memory_cards_exports));
|
|
5227
5466
|
await insertMemoryCardsForBatch2(batch);
|
|
5228
|
-
} catch {
|
|
5467
|
+
} catch (e) {
|
|
5468
|
+
logStoreWarn("catch", e);
|
|
5229
5469
|
}
|
|
5230
5470
|
try {
|
|
5231
5471
|
const { insertOntologyForBatch: insertOntologyForBatch2 } = await Promise.resolve().then(() => (init_agentic_ontology(), agentic_ontology_exports));
|
|
5232
5472
|
await insertOntologyForBatch2(batch);
|
|
5233
|
-
} catch {
|
|
5473
|
+
} catch (e) {
|
|
5474
|
+
logStoreWarn("catch", e);
|
|
5234
5475
|
}
|
|
5235
5476
|
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
5236
5477
|
_pendingRecords.splice(0, batch.length);
|
|
@@ -5269,7 +5510,8 @@ ${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
|
5269
5510
|
}
|
|
5270
5511
|
}
|
|
5271
5512
|
}
|
|
5272
|
-
} catch {
|
|
5513
|
+
} catch (e) {
|
|
5514
|
+
logStoreWarn("catch", e);
|
|
5273
5515
|
}
|
|
5274
5516
|
return batch.length;
|
|
5275
5517
|
} finally {
|
|
@@ -5311,7 +5553,8 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
5311
5553
|
} else {
|
|
5312
5554
|
client = getClient();
|
|
5313
5555
|
}
|
|
5314
|
-
} catch {
|
|
5556
|
+
} catch (e) {
|
|
5557
|
+
logStoreDebug("shard routing fallback", e);
|
|
5315
5558
|
client = getClient();
|
|
5316
5559
|
}
|
|
5317
5560
|
const limit = options?.limit ?? 10;
|
|
@@ -5427,7 +5670,8 @@ async function attachDocumentMetadata(records) {
|
|
|
5427
5670
|
if (!record.document_id) continue;
|
|
5428
5671
|
record.document_metadata = byId.get(record.document_id) ?? null;
|
|
5429
5672
|
}
|
|
5430
|
-
} catch {
|
|
5673
|
+
} catch (e) {
|
|
5674
|
+
logStoreWarn("catch", e);
|
|
5431
5675
|
}
|
|
5432
5676
|
return records;
|
|
5433
5677
|
}
|
|
@@ -5488,11 +5732,12 @@ async function getMemoryCardinality(agentId) {
|
|
|
5488
5732
|
args: [agentId]
|
|
5489
5733
|
});
|
|
5490
5734
|
return Number(result.rows[0]?.cnt) || 0;
|
|
5491
|
-
} catch {
|
|
5735
|
+
} catch (e) {
|
|
5736
|
+
logStoreWarn("getMemoryCardinality", e);
|
|
5492
5737
|
return 0;
|
|
5493
5738
|
}
|
|
5494
5739
|
}
|
|
5495
|
-
var INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
5740
|
+
var _debugStore, INIT_MAX_RETRIES, INIT_RETRY_DELAY_MS, _pendingRecords, _batchSize, _flushIntervalMs, _flushTimer, _flushing, _nextVersion;
|
|
5496
5741
|
var init_store = __esm({
|
|
5497
5742
|
"src/lib/store.ts"() {
|
|
5498
5743
|
"use strict";
|
|
@@ -5502,6 +5747,7 @@ var init_store = __esm({
|
|
|
5502
5747
|
init_config();
|
|
5503
5748
|
init_state_bus();
|
|
5504
5749
|
init_memory_write_governor();
|
|
5750
|
+
_debugStore = process.env.EXE_DEBUG === "1";
|
|
5505
5751
|
INIT_MAX_RETRIES = 3;
|
|
5506
5752
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
5507
5753
|
_pendingRecords = [];
|