@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.
Files changed (92) hide show
  1. package/dist/bin/agentic-ontology-backfill.js +334 -100
  2. package/dist/bin/agentic-reflection-backfill.js +328 -97
  3. package/dist/bin/agentic-semantic-label.js +328 -97
  4. package/dist/bin/backfill-conversations.js +332 -97
  5. package/dist/bin/backfill-responses.js +332 -97
  6. package/dist/bin/backfill-vectors.js +337 -106
  7. package/dist/bin/bulk-sync-postgres.js +335 -101
  8. package/dist/bin/cleanup-stale-review-tasks.js +356 -108
  9. package/dist/bin/cli.js +653 -405
  10. package/dist/bin/exe-agent.js +21 -3
  11. package/dist/bin/exe-assign.js +338 -94
  12. package/dist/bin/exe-boot.js +472 -239
  13. package/dist/bin/exe-call.js +22 -5
  14. package/dist/bin/exe-cloud.js +404 -158
  15. package/dist/bin/exe-dispatch.js +390 -142
  16. package/dist/bin/exe-doctor.js +349 -103
  17. package/dist/bin/exe-export-behaviors.js +351 -105
  18. package/dist/bin/exe-forget.js +352 -103
  19. package/dist/bin/exe-gateway.js +420 -172
  20. package/dist/bin/exe-heartbeat.js +361 -113
  21. package/dist/bin/exe-kill.js +344 -98
  22. package/dist/bin/exe-launch-agent.js +375 -129
  23. package/dist/bin/exe-new-employee.js +83 -67
  24. package/dist/bin/exe-pending-messages.js +356 -108
  25. package/dist/bin/exe-pending-notifications.js +358 -110
  26. package/dist/bin/exe-pending-reviews.js +359 -111
  27. package/dist/bin/exe-rename.js +354 -108
  28. package/dist/bin/exe-review.js +343 -97
  29. package/dist/bin/exe-search.js +363 -113
  30. package/dist/bin/exe-session-cleanup.js +403 -155
  31. package/dist/bin/exe-settings.js +14 -9
  32. package/dist/bin/exe-start-codex.js +365 -131
  33. package/dist/bin/exe-start-opencode.js +359 -125
  34. package/dist/bin/exe-status.js +356 -108
  35. package/dist/bin/exe-team.js +343 -97
  36. package/dist/bin/git-sweep.js +390 -142
  37. package/dist/bin/graph-backfill.js +334 -100
  38. package/dist/bin/graph-export.js +346 -100
  39. package/dist/bin/install.js +1 -0
  40. package/dist/bin/intercom-check.js +403 -155
  41. package/dist/bin/pre-publish.js +12 -0
  42. package/dist/bin/scan-tasks.js +393 -145
  43. package/dist/bin/setup.js +331 -159
  44. package/dist/bin/shard-migrate.js +328 -94
  45. package/dist/gateway/index.js +406 -158
  46. package/dist/hooks/bug-report-worker.js +396 -148
  47. package/dist/hooks/codex-stop-task-finalizer.js +374 -126
  48. package/dist/hooks/commit-complete.js +390 -142
  49. package/dist/hooks/error-recall.js +365 -115
  50. package/dist/hooks/ingest.js +357 -111
  51. package/dist/hooks/instructions-loaded.js +351 -105
  52. package/dist/hooks/notification.js +343 -97
  53. package/dist/hooks/post-compact.js +358 -110
  54. package/dist/hooks/post-tool-combined.js +384 -132
  55. package/dist/hooks/pre-compact.js +391 -143
  56. package/dist/hooks/pre-tool-use.js +362 -114
  57. package/dist/hooks/prompt-submit.js +422 -170
  58. package/dist/hooks/session-end.js +393 -145
  59. package/dist/hooks/session-start.js +390 -138
  60. package/dist/hooks/stop.js +361 -113
  61. package/dist/hooks/subagent-stop.js +354 -106
  62. package/dist/hooks/summary-worker.js +418 -185
  63. package/dist/index.js +400 -152
  64. package/dist/lib/cloud-sync.js +291 -131
  65. package/dist/lib/consolidation.js +8 -2
  66. package/dist/lib/database.js +233 -73
  67. package/dist/lib/db.js +233 -73
  68. package/dist/lib/device-registry.js +237 -77
  69. package/dist/lib/employee-templates.js +19 -1
  70. package/dist/lib/exe-daemon.js +705 -409
  71. package/dist/lib/hybrid-search.js +363 -113
  72. package/dist/lib/identity.js +9 -5
  73. package/dist/lib/messaging.js +26 -20
  74. package/dist/lib/reminders.js +5 -1
  75. package/dist/lib/schedules.js +320 -89
  76. package/dist/lib/skill-learning.js +28 -24
  77. package/dist/lib/store.js +342 -96
  78. package/dist/lib/tasks.js +82 -76
  79. package/dist/lib/tmux-routing.js +74 -68
  80. package/dist/lib/token-spend.js +5 -1
  81. package/dist/mcp/server.js +628 -355
  82. package/dist/mcp/tools/complete-reminder.js +5 -1
  83. package/dist/mcp/tools/create-reminder.js +5 -1
  84. package/dist/mcp/tools/create-task.js +89 -83
  85. package/dist/mcp/tools/deactivate-behavior.js +7 -3
  86. package/dist/mcp/tools/list-reminders.js +5 -1
  87. package/dist/mcp/tools/list-tasks.js +28 -21
  88. package/dist/mcp/tools/send-message.js +28 -22
  89. package/dist/mcp/tools/update-task.js +89 -83
  90. package/dist/runtime/index.js +390 -142
  91. package/dist/tui/App.js +437 -189
  92. package/package.json +1 -1
@@ -1396,9 +1396,79 @@ __export(database_exports, {
1396
1396
  isInitialized: () => isInitialized,
1397
1397
  setExternalClient: () => setExternalClient
1398
1398
  });
1399
- import { chmodSync as chmodSync2 } from "fs";
1399
+ 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";
1400
1400
  import { createClient } from "@libsql/client";
1401
+ import { homedir } from "os";
1402
+ import { join } from "path";
1403
+ function logCatchDebug(context, err) {
1404
+ if (_debugDb) {
1405
+ process.stderr.write(
1406
+ `[database] ${context}: ${err instanceof Error ? err.message : String(err)}
1407
+ `
1408
+ );
1409
+ }
1410
+ }
1411
+ function acquireDbLock() {
1412
+ mkdirSync2(join(homedir(), ".exe-os"), { recursive: true });
1413
+ try {
1414
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
1415
+ } catch (err) {
1416
+ if (err && typeof err === "object" && "code" in err && err.code === "EEXIST") {
1417
+ try {
1418
+ const lockStat = statSync2(DB_LOCK_PATH);
1419
+ if (Date.now() - lockStat.mtimeMs > 6e4) {
1420
+ unlinkSync3(DB_LOCK_PATH);
1421
+ _lockFd = openSync2(DB_LOCK_PATH, "wx");
1422
+ return;
1423
+ }
1424
+ } catch (e) {
1425
+ logCatchDebug("stale lock check", e);
1426
+ }
1427
+ process.stderr.write(
1428
+ "[database] WARN: Another process holds db.lock \u2014 waiting briefly then proceeding.\n"
1429
+ );
1430
+ return;
1431
+ }
1432
+ throw err;
1433
+ }
1434
+ }
1435
+ function releaseDbLock() {
1436
+ if (_lockFd !== null) {
1437
+ try {
1438
+ closeSync2(_lockFd);
1439
+ } catch (e) {
1440
+ logCatchDebug("lock close", e);
1441
+ }
1442
+ _lockFd = null;
1443
+ }
1444
+ try {
1445
+ unlinkSync3(DB_LOCK_PATH);
1446
+ } catch (e) {
1447
+ logCatchDebug("lock unlink", e);
1448
+ }
1449
+ }
1401
1450
  async function initDatabase(config) {
1451
+ acquireDbLock();
1452
+ if (existsSync6(config.dbPath)) {
1453
+ const dbStat = statSync2(config.dbPath);
1454
+ if (dbStat.size === 0) {
1455
+ const walPath = config.dbPath + "-wal";
1456
+ if (existsSync6(walPath) && statSync2(walPath).size > 0) {
1457
+ const backupPath = config.dbPath + ".zeroed-" + Date.now();
1458
+ copyFileSync(config.dbPath, backupPath);
1459
+ unlinkSync3(config.dbPath);
1460
+ process.stderr.write(
1461
+ `[database] CRITICAL: DB was 0 bytes. Moved to ${backupPath}, attempting WAL recovery.
1462
+ `
1463
+ );
1464
+ } else {
1465
+ process.stderr.write(
1466
+ `[database] CRITICAL: DB is 0 bytes and no WAL available for recovery. Data may be lost. Check backups at ${config.dbPath}.bak
1467
+ `
1468
+ );
1469
+ }
1470
+ }
1471
+ }
1402
1472
  if (_walCheckpointTimer) {
1403
1473
  clearInterval(_walCheckpointTimer);
1404
1474
  _walCheckpointTimer = null;
@@ -1425,10 +1495,8 @@ async function initDatabase(config) {
1425
1495
  _client = createClient(opts);
1426
1496
  _resilientClient = wrapWithRetry(_client);
1427
1497
  _adapterClient = _resilientClient;
1428
- _client.execute("PRAGMA busy_timeout = 30000").catch(() => {
1429
- });
1430
- _client.execute("PRAGMA journal_mode = WAL").catch(() => {
1431
- });
1498
+ await _client.execute("PRAGMA busy_timeout = 30000");
1499
+ await _client.execute("PRAGMA journal_mode = WAL");
1432
1500
  if (_walCheckpointTimer) clearInterval(_walCheckpointTimer);
1433
1501
  _walCheckpointTimer = setInterval(() => {
1434
1502
  _client?.execute("PRAGMA wal_checkpoint(PASSIVE)").catch(() => {
@@ -1443,11 +1511,16 @@ async function initDatabase(config) {
1443
1511
  for (const suffix of ["-wal", "-shm"]) {
1444
1512
  try {
1445
1513
  chmodSync2(config.dbPath + suffix, 384);
1446
- } catch {
1514
+ } catch (chmodErr) {
1515
+ process.stderr.write(`[database] chmod ${suffix} failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
1516
+ `);
1447
1517
  }
1448
1518
  }
1449
- } catch {
1519
+ } catch (chmodErr) {
1520
+ process.stderr.write(`[database] chmod db failed: ${chmodErr instanceof Error ? chmodErr.message : String(chmodErr)}
1521
+ `);
1450
1522
  }
1523
+ releaseDbLock();
1451
1524
  }
1452
1525
  function isInitialized() {
1453
1526
  return _adapterClient !== null || _client !== null;
@@ -1502,7 +1575,8 @@ async function ensureSchema() {
1502
1575
  await client.execute("PRAGMA wal_autocheckpoint = 1000");
1503
1576
  try {
1504
1577
  await client.execute("PRAGMA libsql_vector_search_ef = 128");
1505
- } catch {
1578
+ } catch (e) {
1579
+ logCatchDebug("migration", e);
1506
1580
  }
1507
1581
  await client.executeMultiple(`
1508
1582
  CREATE TABLE IF NOT EXISTS memories (
@@ -1567,6 +1641,23 @@ async function ensureSchema() {
1567
1641
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1568
1642
  END;
1569
1643
  `);
1644
+ try {
1645
+ await client.execute("SELECT COUNT(*) FROM memories_fts LIMIT 1");
1646
+ } catch (ftsErr) {
1647
+ process.stderr.write(
1648
+ `[database] WARN: memories_fts corrupted (${ftsErr instanceof Error ? ftsErr.message : String(ftsErr)}) \u2014 rebuilding FTS index.
1649
+ `
1650
+ );
1651
+ try {
1652
+ await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
1653
+ process.stderr.write("[database] FTS index rebuilt successfully.\n");
1654
+ } catch (rebuildErr) {
1655
+ process.stderr.write(
1656
+ `[database] ERROR: FTS rebuild failed: ${rebuildErr instanceof Error ? rebuildErr.message : String(rebuildErr)}
1657
+ `
1658
+ );
1659
+ }
1660
+ }
1570
1661
  await client.executeMultiple(`
1571
1662
  CREATE TABLE IF NOT EXISTS sync_meta (
1572
1663
  key TEXT PRIMARY KEY,
@@ -1625,35 +1716,40 @@ async function ensureSchema() {
1625
1716
  });
1626
1717
  }
1627
1718
  }
1628
- } catch {
1719
+ } catch (seedErr) {
1720
+ logCatchDebug("behavior seed", seedErr);
1629
1721
  }
1630
1722
  try {
1631
1723
  await client.execute({
1632
1724
  sql: `ALTER TABLE behaviors ADD COLUMN priority TEXT DEFAULT 'p1'`,
1633
1725
  args: []
1634
1726
  });
1635
- } catch {
1727
+ } catch (e) {
1728
+ logCatchDebug("migration", e);
1636
1729
  }
1637
1730
  try {
1638
1731
  await client.execute({
1639
1732
  sql: `ALTER TABLE behaviors ADD COLUMN vector F32_BLOB(${EMBEDDING_DIM})`,
1640
1733
  args: []
1641
1734
  });
1642
- } catch {
1735
+ } catch (e) {
1736
+ logCatchDebug("migration", e);
1643
1737
  }
1644
1738
  try {
1645
1739
  await client.execute({
1646
1740
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
1647
1741
  args: []
1648
1742
  });
1649
- } catch {
1743
+ } catch (e) {
1744
+ logCatchDebug("migration", e);
1650
1745
  }
1651
1746
  try {
1652
1747
  await client.execute({
1653
1748
  sql: `ALTER TABLE tasks ADD COLUMN parent_task_id TEXT`,
1654
1749
  args: []
1655
1750
  });
1656
- } catch {
1751
+ } catch (e) {
1752
+ logCatchDebug("migration", e);
1657
1753
  }
1658
1754
  try {
1659
1755
  await client.execute({
@@ -1662,98 +1758,112 @@ async function ensureSchema() {
1662
1758
  WHERE parent_task_id IS NOT NULL`,
1663
1759
  args: []
1664
1760
  });
1665
- } catch {
1761
+ } catch (e) {
1762
+ logCatchDebug("migration", e);
1666
1763
  }
1667
1764
  try {
1668
1765
  await client.execute({
1669
1766
  sql: `UPDATE tasks SET status = 'done' WHERE status = 'completed'`,
1670
1767
  args: []
1671
1768
  });
1672
- } catch {
1769
+ } catch (e) {
1770
+ logCatchDebug("migration", e);
1673
1771
  }
1674
1772
  try {
1675
1773
  await client.execute({
1676
1774
  sql: `ALTER TABLE tasks ADD COLUMN reviewer TEXT`,
1677
1775
  args: []
1678
1776
  });
1679
- } catch {
1777
+ } catch (e) {
1778
+ logCatchDebug("migration", e);
1680
1779
  }
1681
1780
  try {
1682
1781
  await client.execute({
1683
1782
  sql: `ALTER TABLE tasks ADD COLUMN context TEXT`,
1684
1783
  args: []
1685
1784
  });
1686
- } catch {
1785
+ } catch (e) {
1786
+ logCatchDebug("migration", e);
1687
1787
  }
1688
1788
  try {
1689
1789
  await client.execute({
1690
1790
  sql: `ALTER TABLE tasks ADD COLUMN result TEXT`,
1691
1791
  args: []
1692
1792
  });
1693
- } catch {
1793
+ } catch (e) {
1794
+ logCatchDebug("migration", e);
1694
1795
  }
1695
1796
  try {
1696
1797
  await client.execute({
1697
1798
  sql: `ALTER TABLE tasks ADD COLUMN assigned_tmux TEXT`,
1698
1799
  args: []
1699
1800
  });
1700
- } catch {
1801
+ } catch (e) {
1802
+ logCatchDebug("migration", e);
1701
1803
  }
1702
1804
  try {
1703
1805
  await client.execute({
1704
1806
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
1705
1807
  args: []
1706
1808
  });
1707
- } catch {
1809
+ } catch (e) {
1810
+ logCatchDebug("migration", e);
1708
1811
  }
1709
1812
  try {
1710
1813
  await client.execute({
1711
1814
  sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
1712
1815
  args: []
1713
1816
  });
1714
- } catch {
1817
+ } catch (e) {
1818
+ logCatchDebug("migration", e);
1715
1819
  }
1716
1820
  try {
1717
1821
  await client.execute({
1718
1822
  sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
1719
1823
  args: []
1720
1824
  });
1721
- } catch {
1825
+ } catch (e) {
1826
+ logCatchDebug("migration", e);
1722
1827
  }
1723
1828
  try {
1724
1829
  await client.execute({
1725
1830
  sql: `ALTER TABLE tasks ADD COLUMN session_scope TEXT`,
1726
1831
  args: []
1727
1832
  });
1728
- } catch {
1833
+ } catch (e) {
1834
+ logCatchDebug("migration", e);
1729
1835
  }
1730
1836
  try {
1731
1837
  await client.execute({
1732
1838
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
1733
1839
  args: []
1734
1840
  });
1735
- } catch {
1841
+ } catch (e) {
1842
+ logCatchDebug("migration", e);
1736
1843
  }
1737
1844
  try {
1738
1845
  await client.execute({
1739
1846
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
1740
1847
  args: []
1741
1848
  });
1742
- } catch {
1849
+ } catch (e) {
1850
+ logCatchDebug("migration", e);
1743
1851
  }
1744
1852
  try {
1745
1853
  await client.execute({
1746
1854
  sql: `ALTER TABLE memories ADD COLUMN author_device_id TEXT`,
1747
1855
  args: []
1748
1856
  });
1749
- } catch {
1857
+ } catch (e) {
1858
+ logCatchDebug("migration", e);
1750
1859
  }
1751
1860
  try {
1752
1861
  await client.execute({
1753
1862
  sql: `ALTER TABLE memories ADD COLUMN scope TEXT NOT NULL DEFAULT 'business'`,
1754
1863
  args: []
1755
1864
  });
1756
- } catch {
1865
+ } catch (e) {
1866
+ logCatchDebug("migration", e);
1757
1867
  }
1758
1868
  await client.executeMultiple(`
1759
1869
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -1858,14 +1968,16 @@ async function ensureSchema() {
1858
1968
  sql: `ALTER TABLE notifications ADD COLUMN session_scope TEXT`,
1859
1969
  args: []
1860
1970
  });
1861
- } catch {
1971
+ } catch (e) {
1972
+ logCatchDebug("migration", e);
1862
1973
  }
1863
1974
  try {
1864
1975
  await client.execute({
1865
1976
  sql: `ALTER TABLE messages ADD COLUMN session_scope TEXT`,
1866
1977
  args: []
1867
1978
  });
1868
- } catch {
1979
+ } catch (e) {
1980
+ logCatchDebug("migration", e);
1869
1981
  }
1870
1982
  await client.executeMultiple(`
1871
1983
  CREATE INDEX IF NOT EXISTS idx_notifications_agent_scope_read
@@ -1891,7 +2003,8 @@ async function ensureSchema() {
1891
2003
  sql: `UPDATE tasks SET project_name = 'exe-os' WHERE project_name = 'worker'`,
1892
2004
  args: []
1893
2005
  });
1894
- } catch {
2006
+ } catch (e) {
2007
+ logCatchDebug("migration", e);
1895
2008
  }
1896
2009
  await client.executeMultiple(`
1897
2010
  CREATE TABLE IF NOT EXISTS trajectories (
@@ -1915,7 +2028,8 @@ async function ensureSchema() {
1915
2028
  `);
1916
2029
  try {
1917
2030
  await client.execute("ALTER TABLE trajectories ADD COLUMN skill_id TEXT");
1918
- } catch {
2031
+ } catch (e) {
2032
+ logCatchDebug("migration", e);
1919
2033
  }
1920
2034
  await client.executeMultiple(`
1921
2035
  CREATE TABLE IF NOT EXISTS consolidations (
@@ -1952,63 +2066,72 @@ async function ensureSchema() {
1952
2066
  sql: `ALTER TABLE memories ADD COLUMN consolidated INTEGER NOT NULL DEFAULT 0`,
1953
2067
  args: []
1954
2068
  });
1955
- } catch {
2069
+ } catch (e) {
2070
+ logCatchDebug("migration", e);
1956
2071
  }
1957
2072
  try {
1958
2073
  await client.execute({
1959
2074
  sql: `ALTER TABLE memories ADD COLUMN importance INTEGER DEFAULT 5`,
1960
2075
  args: []
1961
2076
  });
1962
- } catch {
2077
+ } catch (e) {
2078
+ logCatchDebug("migration", e);
1963
2079
  }
1964
2080
  try {
1965
2081
  await client.execute({
1966
2082
  sql: `ALTER TABLE memories ADD COLUMN status TEXT DEFAULT 'active'`,
1967
2083
  args: []
1968
2084
  });
1969
- } catch {
2085
+ } catch (e) {
2086
+ logCatchDebug("migration", e);
1970
2087
  }
1971
2088
  try {
1972
2089
  await client.execute({
1973
2090
  sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
1974
2091
  args: []
1975
2092
  });
1976
- } catch {
2093
+ } catch (e) {
2094
+ logCatchDebug("migration", e);
1977
2095
  }
1978
2096
  try {
1979
2097
  await client.execute({
1980
2098
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
1981
2099
  args: []
1982
2100
  });
1983
- } catch {
2101
+ } catch (e) {
2102
+ logCatchDebug("migration", e);
1984
2103
  }
1985
2104
  try {
1986
2105
  await client.execute({
1987
2106
  sql: `ALTER TABLE memories ADD COLUMN last_accessed TEXT`,
1988
2107
  args: []
1989
2108
  });
1990
- } catch {
2109
+ } catch (e) {
2110
+ logCatchDebug("migration", e);
1991
2111
  }
1992
2112
  try {
1993
2113
  await client.execute({
1994
2114
  sql: `UPDATE memories SET last_accessed = timestamp WHERE last_accessed IS NULL`,
1995
2115
  args: []
1996
2116
  });
1997
- } catch {
2117
+ } catch (e) {
2118
+ logCatchDebug("migration", e);
1998
2119
  }
1999
2120
  try {
2000
2121
  await client.execute({
2001
2122
  sql: `ALTER TABLE memories ADD COLUMN wiki_synced INTEGER DEFAULT 0`,
2002
2123
  args: []
2003
2124
  });
2004
- } catch {
2125
+ } catch (e) {
2126
+ logCatchDebug("migration", e);
2005
2127
  }
2006
2128
  try {
2007
2129
  await client.execute({
2008
2130
  sql: `ALTER TABLE memories ADD COLUMN graph_extracted INTEGER DEFAULT 0`,
2009
2131
  args: []
2010
2132
  });
2011
- } catch {
2133
+ } catch (e) {
2134
+ logCatchDebug("migration", e);
2012
2135
  }
2013
2136
  for (const col of [
2014
2137
  "ALTER TABLE memories ADD COLUMN content_hash TEXT",
@@ -2016,14 +2139,16 @@ async function ensureSchema() {
2016
2139
  ]) {
2017
2140
  try {
2018
2141
  await client.execute(col);
2019
- } catch {
2142
+ } catch (e) {
2143
+ logCatchDebug("migration", e);
2020
2144
  }
2021
2145
  }
2022
2146
  try {
2023
2147
  await client.execute(
2024
2148
  `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
2025
2149
  );
2026
- } catch {
2150
+ } catch (e) {
2151
+ logCatchDebug("migration", e);
2027
2152
  }
2028
2153
  try {
2029
2154
  await client.execute(
@@ -2031,7 +2156,8 @@ async function ensureSchema() {
2031
2156
  ON memories(content_hash, agent_id, project_name, memory_type)
2032
2157
  WHERE content_hash IS NOT NULL`
2033
2158
  );
2034
- } catch {
2159
+ } catch (e) {
2160
+ logCatchDebug("migration", e);
2035
2161
  }
2036
2162
  await client.executeMultiple(`
2037
2163
  CREATE TABLE IF NOT EXISTS entities (
@@ -2107,7 +2233,8 @@ async function ensureSchema() {
2107
2233
  `);
2108
2234
  try {
2109
2235
  await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
2110
- } catch {
2236
+ } catch (e) {
2237
+ logCatchDebug("migration", e);
2111
2238
  }
2112
2239
  await client.executeMultiple(`
2113
2240
  CREATE TABLE IF NOT EXISTS entity_aliases (
@@ -2122,14 +2249,16 @@ async function ensureSchema() {
2122
2249
  ]) {
2123
2250
  try {
2124
2251
  await client.execute(col);
2125
- } catch {
2252
+ } catch (e) {
2253
+ logCatchDebug("migration", e);
2126
2254
  }
2127
2255
  }
2128
2256
  try {
2129
2257
  await client.execute(
2130
2258
  `CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)`
2131
2259
  );
2132
- } catch {
2260
+ } catch (e) {
2261
+ logCatchDebug("migration", e);
2133
2262
  }
2134
2263
  await client.executeMultiple(`
2135
2264
  CREATE TABLE IF NOT EXISTS identity (
@@ -2228,7 +2357,8 @@ async function ensureSchema() {
2228
2357
  sql: `ALTER TABLE memories ADD COLUMN ${column}`,
2229
2358
  args: []
2230
2359
  });
2231
- } catch {
2360
+ } catch (e) {
2361
+ logCatchDebug("migration", e);
2232
2362
  }
2233
2363
  }
2234
2364
  for (const col of [
@@ -2237,7 +2367,8 @@ async function ensureSchema() {
2237
2367
  ]) {
2238
2368
  try {
2239
2369
  await client.execute(col);
2240
- } catch {
2370
+ } catch (e) {
2371
+ logCatchDebug("migration", e);
2241
2372
  }
2242
2373
  }
2243
2374
  await client.executeMultiple(`
@@ -2422,56 +2553,64 @@ async function ensureSchema() {
2422
2553
  args: []
2423
2554
  });
2424
2555
  }
2425
- } catch {
2556
+ } catch (e) {
2557
+ logCatchDebug("session_agent_map backfill", e);
2426
2558
  }
2427
2559
  try {
2428
2560
  await client.execute({
2429
2561
  sql: `ALTER TABLE session_agent_map ADD COLUMN cache_cold_count INTEGER NOT NULL DEFAULT 0`,
2430
2562
  args: []
2431
2563
  });
2432
- } catch {
2564
+ } catch (e) {
2565
+ logCatchDebug("migration", e);
2433
2566
  }
2434
2567
  try {
2435
2568
  await client.execute({
2436
2569
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
2437
2570
  args: []
2438
2571
  });
2439
- } catch {
2572
+ } catch (e) {
2573
+ logCatchDebug("migration", e);
2440
2574
  }
2441
2575
  try {
2442
2576
  await client.execute({
2443
2577
  sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
2444
2578
  args: []
2445
2579
  });
2446
- } catch {
2580
+ } catch (e) {
2581
+ logCatchDebug("migration", e);
2447
2582
  }
2448
2583
  try {
2449
2584
  await client.execute({
2450
2585
  sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
2451
2586
  args: []
2452
2587
  });
2453
- } catch {
2588
+ } catch (e) {
2589
+ logCatchDebug("migration", e);
2454
2590
  }
2455
2591
  try {
2456
2592
  await client.execute({
2457
2593
  sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
2458
2594
  args: []
2459
2595
  });
2460
- } catch {
2596
+ } catch (e) {
2597
+ logCatchDebug("migration", e);
2461
2598
  }
2462
2599
  try {
2463
2600
  await client.execute({
2464
2601
  sql: `ALTER TABLE tasks ADD COLUMN spawn_runtime TEXT`,
2465
2602
  args: []
2466
2603
  });
2467
- } catch {
2604
+ } catch (e) {
2605
+ logCatchDebug("migration", e);
2468
2606
  }
2469
2607
  try {
2470
2608
  await client.execute({
2471
2609
  sql: `ALTER TABLE tasks ADD COLUMN spawn_model TEXT`,
2472
2610
  args: []
2473
2611
  });
2474
- } catch {
2612
+ } catch (e) {
2613
+ logCatchDebug("migration", e);
2475
2614
  }
2476
2615
  await client.executeMultiple(`
2477
2616
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
@@ -2670,13 +2809,15 @@ async function ensureSchema() {
2670
2809
  sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
2671
2810
  args: []
2672
2811
  });
2673
- } catch {
2812
+ } catch (e) {
2813
+ logCatchDebug("migration", e);
2674
2814
  }
2675
2815
  try {
2676
2816
  await client.execute(
2677
2817
  `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
2678
2818
  );
2679
- } catch {
2819
+ } catch (e) {
2820
+ logCatchDebug("migration", e);
2680
2821
  }
2681
2822
  try {
2682
2823
  await client.execute({
@@ -2687,20 +2828,23 @@ async function ensureSchema() {
2687
2828
  sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
2688
2829
  args: []
2689
2830
  });
2690
- } catch {
2831
+ } catch (e) {
2832
+ logCatchDebug("migration", e);
2691
2833
  }
2692
2834
  try {
2693
2835
  await client.execute({
2694
2836
  sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
2695
2837
  args: []
2696
2838
  });
2697
- } catch {
2839
+ } catch (e) {
2840
+ logCatchDebug("migration", e);
2698
2841
  }
2699
2842
  try {
2700
2843
  await client.execute(
2701
2844
  `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
2702
2845
  );
2703
- } catch {
2846
+ } catch (e) {
2847
+ logCatchDebug("migration", e);
2704
2848
  }
2705
2849
  for (const col of [
2706
2850
  "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
@@ -2708,7 +2852,8 @@ async function ensureSchema() {
2708
2852
  ]) {
2709
2853
  try {
2710
2854
  await client.execute(col);
2711
- } catch {
2855
+ } catch (e) {
2856
+ logCatchDebug("migration", e);
2712
2857
  }
2713
2858
  }
2714
2859
  try {
@@ -2716,13 +2861,15 @@ async function ensureSchema() {
2716
2861
  sql: `ALTER TABLE memories ADD COLUMN draft INTEGER DEFAULT 0`,
2717
2862
  args: []
2718
2863
  });
2719
- } catch {
2864
+ } catch (e) {
2865
+ logCatchDebug("migration", e);
2720
2866
  }
2721
2867
  try {
2722
2868
  await client.execute(
2723
2869
  `CREATE INDEX IF NOT EXISTS idx_memories_draft ON memories(draft) WHERE draft = 1`
2724
2870
  );
2725
- } catch {
2871
+ } catch (e) {
2872
+ logCatchDebug("migration", e);
2726
2873
  }
2727
2874
  for (const col of [
2728
2875
  "ALTER TABLE memories ADD COLUMN valid_from TEXT",
@@ -2730,7 +2877,8 @@ async function ensureSchema() {
2730
2877
  ]) {
2731
2878
  try {
2732
2879
  await client.execute(col);
2733
- } catch {
2880
+ } catch (e) {
2881
+ logCatchDebug("migration", e);
2734
2882
  }
2735
2883
  }
2736
2884
  try {
@@ -2738,27 +2886,31 @@ async function ensureSchema() {
2738
2886
  sql: `UPDATE memories SET valid_from = timestamp WHERE valid_from IS NULL`,
2739
2887
  args: []
2740
2888
  });
2741
- } catch {
2889
+ } catch (e) {
2890
+ logCatchDebug("migration", e);
2742
2891
  }
2743
2892
  try {
2744
2893
  await client.execute({
2745
2894
  sql: `ALTER TABLE memories ADD COLUMN memory_type TEXT DEFAULT 'raw'`,
2746
2895
  args: []
2747
2896
  });
2748
- } catch {
2897
+ } catch (e) {
2898
+ logCatchDebug("migration", e);
2749
2899
  }
2750
2900
  try {
2751
2901
  await client.execute(
2752
2902
  `CREATE INDEX IF NOT EXISTS idx_memories_type ON memories(memory_type)`
2753
2903
  );
2754
- } catch {
2904
+ } catch (e) {
2905
+ logCatchDebug("migration", e);
2755
2906
  }
2756
2907
  try {
2757
2908
  await client.execute({
2758
2909
  sql: `ALTER TABLE memories ADD COLUMN trajectory TEXT`,
2759
2910
  args: []
2760
2911
  });
2761
- } catch {
2912
+ } catch (e) {
2913
+ logCatchDebug("migration", e);
2762
2914
  }
2763
2915
  for (const col of [
2764
2916
  "ALTER TABLE memories ADD COLUMN intent TEXT",
@@ -2779,7 +2931,8 @@ async function ensureSchema() {
2779
2931
  ]) {
2780
2932
  try {
2781
2933
  await client.execute(col);
2782
- } catch {
2934
+ } catch (e) {
2935
+ logCatchDebug("migration", e);
2783
2936
  }
2784
2937
  }
2785
2938
  try {
@@ -2787,14 +2940,16 @@ async function ensureSchema() {
2787
2940
  sql: `ALTER TABLE memories ADD COLUMN procedure_for TEXT`,
2788
2941
  args: []
2789
2942
  });
2790
- } catch {
2943
+ } catch (e) {
2944
+ logCatchDebug("migration", e);
2791
2945
  }
2792
2946
  try {
2793
2947
  await client.execute({
2794
2948
  sql: `UPDATE tasks SET status = 'closed' WHERE status = 'done' AND result IS NOT NULL`,
2795
2949
  args: []
2796
2950
  });
2797
- } catch {
2951
+ } catch (e) {
2952
+ logCatchDebug("migration", e);
2798
2953
  }
2799
2954
  }
2800
2955
  async function disposeDatabase() {
@@ -2805,7 +2960,8 @@ async function disposeDatabase() {
2805
2960
  if (_client) {
2806
2961
  try {
2807
2962
  await _client.execute("PRAGMA wal_checkpoint(PASSIVE)");
2808
- } catch {
2963
+ } catch (e) {
2964
+ logCatchDebug("WAL checkpoint", e);
2809
2965
  }
2810
2966
  }
2811
2967
  if (_daemonClient) {
@@ -2821,8 +2977,9 @@ async function disposeDatabase() {
2821
2977
  _client = null;
2822
2978
  _resilientClient = null;
2823
2979
  }
2980
+ releaseDbLock();
2824
2981
  }
2825
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2982
+ var _debugDb, _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, _lockFd, DB_LOCK_PATH, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2826
2983
  var init_database = __esm({
2827
2984
  "src/lib/database.ts"() {
2828
2985
  "use strict";
@@ -2830,11 +2987,14 @@ var init_database = __esm({
2830
2987
  init_employees();
2831
2988
  init_database_adapter();
2832
2989
  init_memory();
2990
+ _debugDb = process.env.EXE_DEBUG === "1";
2833
2991
  _client = null;
2834
2992
  _resilientClient = null;
2835
2993
  _walCheckpointTimer = null;
2836
2994
  _daemonClient = null;
2837
2995
  _adapterClient = null;
2996
+ _lockFd = null;
2997
+ DB_LOCK_PATH = join(homedir(), ".exe-os", "db.lock");
2838
2998
  initTurso = initDatabase;
2839
2999
  SOFT_DELETE_RETENTION_DAYS = 7;
2840
3000
  disposeTurso = disposeDatabase;
@@ -2860,9 +3020,9 @@ __export(crdt_sync_exports, {
2860
3020
  rebuildFromDb: () => rebuildFromDb
2861
3021
  });
2862
3022
  import * as Y from "yjs";
2863
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync7, mkdirSync as mkdirSync3, unlinkSync as unlinkSync3 } from "fs";
3023
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync4, existsSync as existsSync8, mkdirSync as mkdirSync4, unlinkSync as unlinkSync4 } from "fs";
2864
3024
  import path7 from "path";
2865
- import { homedir } from "os";
3025
+ import { homedir as homedir2 } from "os";
2866
3026
  function getStatePath() {
2867
3027
  return _statePathOverride ?? DEFAULT_STATE_PATH;
2868
3028
  }
@@ -2873,14 +3033,14 @@ function initCrdtDoc() {
2873
3033
  if (doc) return doc;
2874
3034
  doc = new Y.Doc();
2875
3035
  const sp = getStatePath();
2876
- if (existsSync7(sp)) {
3036
+ if (existsSync8(sp)) {
2877
3037
  try {
2878
3038
  const state = readFileSync6(sp);
2879
3039
  Y.applyUpdate(doc, new Uint8Array(state));
2880
3040
  } catch {
2881
3041
  console.warn("[crdt-sync] WARN: corrupted state file, rebuilding from DB");
2882
3042
  try {
2883
- unlinkSync3(sp);
3043
+ unlinkSync4(sp);
2884
3044
  } catch {
2885
3045
  }
2886
3046
  rebuildFromDb().catch((err) => {
@@ -3018,7 +3178,7 @@ function persistState() {
3018
3178
  try {
3019
3179
  const sp = getStatePath();
3020
3180
  const dir = path7.dirname(sp);
3021
- if (!existsSync7(dir)) mkdirSync3(dir, { recursive: true });
3181
+ if (!existsSync8(dir)) mkdirSync4(dir, { recursive: true });
3022
3182
  const state = Y.encodeStateAsUpdate(doc);
3023
3183
  writeFileSync4(sp, Buffer.from(state));
3024
3184
  } catch {
@@ -3061,7 +3221,7 @@ var DEFAULT_STATE_PATH, _statePathOverride, doc;
3061
3221
  var init_crdt_sync = __esm({
3062
3222
  "src/lib/crdt-sync.ts"() {
3063
3223
  "use strict";
3064
- DEFAULT_STATE_PATH = path7.join(homedir(), ".exe-os", "crdt-state.bin");
3224
+ DEFAULT_STATE_PATH = path7.join(homedir2(), ".exe-os", "crdt-state.bin");
3065
3225
  _statePathOverride = null;
3066
3226
  doc = null;
3067
3227
  }
@@ -3093,7 +3253,7 @@ __export(keychain_exports, {
3093
3253
  setMasterKey: () => setMasterKey
3094
3254
  });
3095
3255
  import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
3096
- import { existsSync as existsSync8, statSync as statSync2 } from "fs";
3256
+ import { existsSync as existsSync9, statSync as statSync3 } from "fs";
3097
3257
  import { execSync as execSync3 } from "child_process";
3098
3258
  import path8 from "path";
3099
3259
  import os6 from "os";
@@ -3128,7 +3288,7 @@ function isRootOnlyTrustedServerKeyFile(keyPath) {
3128
3288
  if (process.platform !== "linux") return false;
3129
3289
  try {
3130
3290
  const uid = typeof os6.userInfo().uid === "number" ? os6.userInfo().uid : -1;
3131
- const st = statSync2(keyPath);
3291
+ const st = statSync3(keyPath);
3132
3292
  if (!st.isFile() || (st.mode & 63) !== 0) return false;
3133
3293
  if (uid === 0) return true;
3134
3294
  const exeOsDir = process.env.EXE_OS_DIR;
@@ -3329,7 +3489,7 @@ async function getMasterKey() {
3329
3489
  }
3330
3490
  }
3331
3491
  const keyPath = getKeyPath();
3332
- if (!existsSync8(keyPath)) {
3492
+ if (!existsSync9(keyPath)) {
3333
3493
  process.stderr.write(
3334
3494
  `[keychain] Key not found at ${keyPath} (HOME=${os6.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
3335
3495
  `
@@ -3437,7 +3597,7 @@ async function getKeyStorageInfo() {
3437
3597
  }
3438
3598
  }
3439
3599
  const keyPath = getKeyPath();
3440
- if (!existsSync8(keyPath)) {
3600
+ if (!existsSync9(keyPath)) {
3441
3601
  return {
3442
3602
  kind: "missing",
3443
3603
  secure: false,
@@ -3533,7 +3693,7 @@ async function deleteMasterKey() {
3533
3693
  }
3534
3694
  }
3535
3695
  const keyPath = getKeyPath();
3536
- if (existsSync8(keyPath)) {
3696
+ if (existsSync9(keyPath)) {
3537
3697
  await unlink(keyPath);
3538
3698
  }
3539
3699
  }
@@ -3589,42 +3749,42 @@ __export(db_backup_exports, {
3589
3749
  listBackups: () => listBackups,
3590
3750
  rotateBackups: () => rotateBackups
3591
3751
  });
3592
- import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync, unlinkSync as unlinkSync4, statSync as statSync3 } from "fs";
3752
+ import { copyFileSync as copyFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync5, readdirSync, unlinkSync as unlinkSync5, statSync as statSync4 } from "fs";
3593
3753
  import path9 from "path";
3594
3754
  function findActiveDb() {
3595
3755
  for (const name of DB_NAMES) {
3596
3756
  const p = path9.join(EXE_AI_DIR, name);
3597
- if (existsSync9(p)) return p;
3757
+ if (existsSync10(p)) return p;
3598
3758
  }
3599
3759
  return null;
3600
3760
  }
3601
3761
  function createBackup(reason = "manual") {
3602
3762
  const dbPath = findActiveDb();
3603
3763
  if (!dbPath) return null;
3604
- mkdirSync4(BACKUP_DIR, { recursive: true });
3764
+ mkdirSync5(BACKUP_DIR, { recursive: true });
3605
3765
  const dbName = path9.basename(dbPath, ".db");
3606
3766
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
3607
3767
  const backupName = `${dbName}-${reason}-${timestamp}.db`;
3608
3768
  const backupPath = path9.join(BACKUP_DIR, backupName);
3609
- copyFileSync(dbPath, backupPath);
3769
+ copyFileSync2(dbPath, backupPath);
3610
3770
  const walPath = dbPath + "-wal";
3611
- if (existsSync9(walPath)) {
3771
+ if (existsSync10(walPath)) {
3612
3772
  try {
3613
- copyFileSync(walPath, backupPath + "-wal");
3773
+ copyFileSync2(walPath, backupPath + "-wal");
3614
3774
  } catch {
3615
3775
  }
3616
3776
  }
3617
3777
  const shmPath = dbPath + "-shm";
3618
- if (existsSync9(shmPath)) {
3778
+ if (existsSync10(shmPath)) {
3619
3779
  try {
3620
- copyFileSync(shmPath, backupPath + "-shm");
3780
+ copyFileSync2(shmPath, backupPath + "-shm");
3621
3781
  } catch {
3622
3782
  }
3623
3783
  }
3624
3784
  return backupPath;
3625
3785
  }
3626
3786
  function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
3627
- if (!existsSync9(BACKUP_DIR)) return 0;
3787
+ if (!existsSync10(BACKUP_DIR)) return 0;
3628
3788
  const cutoff = Date.now() - keepDays * 24 * 60 * 60 * 1e3;
3629
3789
  let deleted = 0;
3630
3790
  try {
@@ -3633,9 +3793,9 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
3633
3793
  if (!file.endsWith(".db") && !file.endsWith(".db-wal") && !file.endsWith(".db-shm")) continue;
3634
3794
  const filePath = path9.join(BACKUP_DIR, file);
3635
3795
  try {
3636
- const stat = statSync3(filePath);
3796
+ const stat = statSync4(filePath);
3637
3797
  if (stat.mtimeMs < cutoff) {
3638
- unlinkSync4(filePath);
3798
+ unlinkSync5(filePath);
3639
3799
  deleted++;
3640
3800
  }
3641
3801
  } catch {
@@ -3646,12 +3806,12 @@ function rotateBackups(keepDays = DEFAULT_KEEP_DAYS) {
3646
3806
  return deleted;
3647
3807
  }
3648
3808
  function listBackups() {
3649
- if (!existsSync9(BACKUP_DIR)) return [];
3809
+ if (!existsSync10(BACKUP_DIR)) return [];
3650
3810
  try {
3651
3811
  const files = readdirSync(BACKUP_DIR).filter((f) => f.endsWith(".db") && !f.endsWith("-wal") && !f.endsWith("-shm"));
3652
3812
  return files.map((name) => {
3653
3813
  const p = path9.join(BACKUP_DIR, name);
3654
- const stat = statSync3(p);
3814
+ const stat = statSync4(p);
3655
3815
  return { path: p, name, size: stat.size, date: stat.mtime };
3656
3816
  }).sort((a, b) => b.date.getTime() - a.date.getTime());
3657
3817
  } catch {
@@ -3683,10 +3843,10 @@ var init_db_backup = __esm({
3683
3843
 
3684
3844
  // src/lib/cloud-sync.ts
3685
3845
  init_database();
3686
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync10, readdirSync as readdirSync2, mkdirSync as mkdirSync5, appendFileSync, unlinkSync as unlinkSync5, openSync as openSync2, closeSync as closeSync2, statSync as statSync4 } from "fs";
3846
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync11, readdirSync as readdirSync2, mkdirSync as mkdirSync6, appendFileSync, unlinkSync as unlinkSync6, openSync as openSync3, closeSync as closeSync3, statSync as statSync5 } from "fs";
3687
3847
  import crypto3 from "crypto";
3688
3848
  import path10 from "path";
3689
- import { homedir as homedir2 } from "os";
3849
+ import { homedir as homedir3 } from "os";
3690
3850
 
3691
3851
  // src/lib/crypto.ts
3692
3852
  import crypto2 from "crypto";
@@ -3751,7 +3911,7 @@ function decompress(input) {
3751
3911
 
3752
3912
  // src/lib/license.ts
3753
3913
  init_config();
3754
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
3914
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
3755
3915
  import { randomUUID as randomUUID2 } from "crypto";
3756
3916
  import { createRequire as createRequire2 } from "module";
3757
3917
  import { pathToFileURL as pathToFileURL2 } from "url";
@@ -3765,21 +3925,21 @@ var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
3765
3925
  function loadDeviceId() {
3766
3926
  const deviceJsonPath = path6.join(EXE_AI_DIR, "device.json");
3767
3927
  try {
3768
- if (existsSync6(deviceJsonPath)) {
3928
+ if (existsSync7(deviceJsonPath)) {
3769
3929
  const data = JSON.parse(readFileSync5(deviceJsonPath, "utf8"));
3770
3930
  if (data.deviceId) return data.deviceId;
3771
3931
  }
3772
3932
  } catch {
3773
3933
  }
3774
3934
  try {
3775
- if (existsSync6(DEVICE_ID_PATH)) {
3935
+ if (existsSync7(DEVICE_ID_PATH)) {
3776
3936
  const id2 = readFileSync5(DEVICE_ID_PATH, "utf8").trim();
3777
3937
  if (id2) return id2;
3778
3938
  }
3779
3939
  } catch {
3780
3940
  }
3781
3941
  const id = randomUUID2();
3782
- mkdirSync2(EXE_AI_DIR, { recursive: true });
3942
+ mkdirSync3(EXE_AI_DIR, { recursive: true });
3783
3943
  writeFileSync3(DEVICE_ID_PATH, id, "utf8");
3784
3944
  return id;
3785
3945
  }
@@ -3794,7 +3954,7 @@ function sqlSafe(v) {
3794
3954
  }
3795
3955
  function logError(msg) {
3796
3956
  try {
3797
- const logPath = path10.join(homedir2(), ".exe-os", "workers.log");
3957
+ const logPath = path10.join(homedir3(), ".exe-os", "workers.log");
3798
3958
  appendFileSync(logPath, `${(/* @__PURE__ */ new Date()).toISOString()} ${msg}
3799
3959
  `);
3800
3960
  } catch {
@@ -3816,7 +3976,7 @@ function loadPgClient() {
3816
3976
  let cloudPostgresUrl;
3817
3977
  let configEnabled = false;
3818
3978
  try {
3819
- if (existsSync10(configPath)) {
3979
+ if (existsSync11(configPath)) {
3820
3980
  const cfg = JSON.parse(readFileSync7(configPath, "utf8"));
3821
3981
  cloudPostgresUrl = cfg.cloud?.postgresUrl;
3822
3982
  configEnabled = cfg.cloud?.syncToPostgres === true;
@@ -3844,9 +4004,9 @@ function loadPgClient() {
3844
4004
  if (!Ctor) throw new Error(`No PrismaClient at ${explicitPath}`);
3845
4005
  return new Ctor();
3846
4006
  }
3847
- const exeDbRoot = process.env.EXE_DB_ROOT ?? path10.join(homedir2(), "exe-db");
4007
+ const exeDbRoot = process.env.EXE_DB_ROOT ?? path10.join(homedir3(), "exe-db");
3848
4008
  const packagePath = path10.join(exeDbRoot, "package.json");
3849
- if (existsSync10(packagePath)) {
4009
+ if (existsSync11(packagePath)) {
3850
4010
  const req = createRequire3(packagePath);
3851
4011
  const entry = req.resolve("@prisma/client");
3852
4012
  const mod = await import(pathToFileURL3(entry).href);
@@ -3907,8 +4067,8 @@ async function pushToPostgres(records) {
3907
4067
  }
3908
4068
  async function withRosterLock(fn) {
3909
4069
  try {
3910
- const fd = openSync2(ROSTER_LOCK_PATH, "wx");
3911
- closeSync2(fd);
4070
+ const fd = openSync3(ROSTER_LOCK_PATH, "wx");
4071
+ closeSync3(fd);
3912
4072
  writeFileSync5(ROSTER_LOCK_PATH, String(Date.now()));
3913
4073
  } catch (err) {
3914
4074
  if (err.code === "EEXIST") {
@@ -3917,9 +4077,9 @@ async function withRosterLock(fn) {
3917
4077
  if (Date.now() - ts < LOCK_STALE_MS) {
3918
4078
  throw new Error("Roster merge already in progress \u2014 another sync is running");
3919
4079
  }
3920
- unlinkSync5(ROSTER_LOCK_PATH);
3921
- const fd = openSync2(ROSTER_LOCK_PATH, "wx");
3922
- closeSync2(fd);
4080
+ unlinkSync6(ROSTER_LOCK_PATH);
4081
+ const fd = openSync3(ROSTER_LOCK_PATH, "wx");
4082
+ closeSync3(fd);
3923
4083
  writeFileSync5(ROSTER_LOCK_PATH, String(Date.now()));
3924
4084
  } catch (retryErr) {
3925
4085
  if (retryErr instanceof Error && retryErr.message.includes("already in progress")) throw retryErr;
@@ -3933,7 +4093,7 @@ async function withRosterLock(fn) {
3933
4093
  return await fn();
3934
4094
  } finally {
3935
4095
  try {
3936
- unlinkSync5(ROSTER_LOCK_PATH);
4096
+ unlinkSync6(ROSTER_LOCK_PATH);
3937
4097
  } catch {
3938
4098
  }
3939
4099
  }
@@ -4368,7 +4528,7 @@ async function cloudSync(config) {
4368
4528
  const employees = await loadEmployees();
4369
4529
  rosterResult.employees = employees.length;
4370
4530
  const idDir = path10.join(EXE_AI_DIR, "identity");
4371
- if (existsSync10(idDir)) {
4531
+ if (existsSync11(idDir)) {
4372
4532
  rosterResult.identities = readdirSync2(idDir).filter((f) => f.endsWith(".md")).length;
4373
4533
  }
4374
4534
  } catch {
@@ -4378,7 +4538,7 @@ async function cloudSync(config) {
4378
4538
  const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
4379
4539
  const latestBackup = getLatestBackup2();
4380
4540
  if (latestBackup) {
4381
- const backupSize = statSync4(latestBackup).size;
4541
+ const backupSize = statSync5(latestBackup).size;
4382
4542
  const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
4383
4543
  if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
4384
4544
  const backupData = readFileSync7(latestBackup);
@@ -4430,7 +4590,7 @@ var ROSTER_DELETIONS_PATH = path10.join(EXE_AI_DIR, "roster-deletions.json");
4430
4590
  function recordRosterDeletion(name) {
4431
4591
  let deletions = [];
4432
4592
  try {
4433
- if (existsSync10(ROSTER_DELETIONS_PATH)) {
4593
+ if (existsSync11(ROSTER_DELETIONS_PATH)) {
4434
4594
  deletions = JSON.parse(readFileSync7(ROSTER_DELETIONS_PATH, "utf-8"));
4435
4595
  }
4436
4596
  } catch {
@@ -4440,7 +4600,7 @@ function recordRosterDeletion(name) {
4440
4600
  }
4441
4601
  function consumeRosterDeletions() {
4442
4602
  try {
4443
- if (!existsSync10(ROSTER_DELETIONS_PATH)) return [];
4603
+ if (!existsSync11(ROSTER_DELETIONS_PATH)) return [];
4444
4604
  const deletions = JSON.parse(readFileSync7(ROSTER_DELETIONS_PATH, "utf-8"));
4445
4605
  writeFileSync5(ROSTER_DELETIONS_PATH, "[]");
4446
4606
  return deletions;
@@ -4453,14 +4613,14 @@ function buildRosterBlob(paths) {
4453
4613
  const identityDir = paths?.identityDir ?? path10.join(EXE_AI_DIR, "identity");
4454
4614
  const configPath = paths?.configPath ?? path10.join(EXE_AI_DIR, "config.json");
4455
4615
  let roster = [];
4456
- if (existsSync10(rosterPath)) {
4616
+ if (existsSync11(rosterPath)) {
4457
4617
  try {
4458
4618
  roster = JSON.parse(readFileSync7(rosterPath, "utf-8"));
4459
4619
  } catch {
4460
4620
  }
4461
4621
  }
4462
4622
  const identities = {};
4463
- if (existsSync10(identityDir)) {
4623
+ if (existsSync11(identityDir)) {
4464
4624
  for (const file of readdirSync2(identityDir).filter((f) => f.endsWith(".md"))) {
4465
4625
  try {
4466
4626
  identities[file] = readFileSync7(path10.join(identityDir, file), "utf-8");
@@ -4469,7 +4629,7 @@ function buildRosterBlob(paths) {
4469
4629
  }
4470
4630
  }
4471
4631
  let config;
4472
- if (existsSync10(configPath)) {
4632
+ if (existsSync11(configPath)) {
4473
4633
  try {
4474
4634
  config = JSON.parse(readFileSync7(configPath, "utf-8"));
4475
4635
  } catch {
@@ -4477,7 +4637,7 @@ function buildRosterBlob(paths) {
4477
4637
  }
4478
4638
  let agentConfig;
4479
4639
  const agentConfigPath = path10.join(EXE_AI_DIR, "agent-config.json");
4480
- if (existsSync10(agentConfigPath)) {
4640
+ if (existsSync11(agentConfigPath)) {
4481
4641
  try {
4482
4642
  agentConfig = JSON.parse(readFileSync7(agentConfigPath, "utf-8"));
4483
4643
  } catch {
@@ -4557,7 +4717,7 @@ async function cloudPullRoster(config) {
4557
4717
  function mergeConfig(remoteConfig, configPath) {
4558
4718
  const cfgPath = configPath ?? path10.join(EXE_AI_DIR, "config.json");
4559
4719
  let local = {};
4560
- if (existsSync10(cfgPath)) {
4720
+ if (existsSync11(cfgPath)) {
4561
4721
  try {
4562
4722
  local = JSON.parse(readFileSync7(cfgPath, "utf-8"));
4563
4723
  } catch {
@@ -4593,11 +4753,11 @@ async function mergeRosterFromRemote(remote, paths) {
4593
4753
  ) ?? lookupKey;
4594
4754
  const remoteIdentity = remote.identities[matchedKey];
4595
4755
  if (remoteIdentity) {
4596
- if (!existsSync10(identityDir)) mkdirSync5(identityDir, { recursive: true });
4756
+ if (!existsSync11(identityDir)) mkdirSync6(identityDir, { recursive: true });
4597
4757
  const idPath = path10.join(identityDir, `${remoteEmp.name}.md`);
4598
4758
  let localIdentity = null;
4599
4759
  try {
4600
- localIdentity = existsSync10(idPath) ? readFileSync7(idPath, "utf-8") : null;
4760
+ localIdentity = existsSync11(idPath) ? readFileSync7(idPath, "utf-8") : null;
4601
4761
  } catch {
4602
4762
  }
4603
4763
  if (localIdentity !== remoteIdentity) {
@@ -4629,7 +4789,7 @@ async function mergeRosterFromRemote(remote, paths) {
4629
4789
  try {
4630
4790
  const agentConfigPath = path10.join(EXE_AI_DIR, "agent-config.json");
4631
4791
  let local = {};
4632
- if (existsSync10(agentConfigPath)) {
4792
+ if (existsSync11(agentConfigPath)) {
4633
4793
  try {
4634
4794
  local = JSON.parse(readFileSync7(agentConfigPath, "utf-8"));
4635
4795
  } catch {
@@ -5065,14 +5225,14 @@ async function cloudPullDocuments(config) {
5065
5225
  var CODE_CONTEXT_DIR = path10.join(EXE_AI_DIR, "code-context");
5066
5226
  async function cloudPushCodeContext(config) {
5067
5227
  assertSecureEndpoint(config.endpoint);
5068
- if (!existsSync10(CODE_CONTEXT_DIR)) return 0;
5228
+ if (!existsSync11(CODE_CONTEXT_DIR)) return 0;
5069
5229
  const files = readdirSync2(CODE_CONTEXT_DIR).filter(
5070
5230
  (f) => f.endsWith(".json") && !f.endsWith(".vectors.json") && !f.startsWith(".")
5071
5231
  );
5072
5232
  if (files.length === 0) return 0;
5073
5233
  const metaPath = path10.join(CODE_CONTEXT_DIR, ".sync-meta.json");
5074
5234
  let syncMeta = {};
5075
- if (existsSync10(metaPath)) {
5235
+ if (existsSync11(metaPath)) {
5076
5236
  try {
5077
5237
  syncMeta = JSON.parse(readFileSync7(metaPath, "utf-8"));
5078
5238
  } catch {
@@ -5082,7 +5242,7 @@ async function cloudPushCodeContext(config) {
5082
5242
  for (const file of files) {
5083
5243
  const filePath = path10.join(CODE_CONTEXT_DIR, file);
5084
5244
  try {
5085
- const stat = statSync4(filePath);
5245
+ const stat = statSync5(filePath);
5086
5246
  const lastPushed = syncMeta[file] ?? 0;
5087
5247
  if (stat.mtimeMs <= lastPushed) continue;
5088
5248
  const content = readFileSync7(filePath, "utf-8");
@@ -5127,7 +5287,7 @@ async function cloudPullCodeContext(config) {
5127
5287
  if (!resp.ok) return 0;
5128
5288
  const data = await resp.json();
5129
5289
  if (!data.indexes || data.indexes.length === 0) return 0;
5130
- mkdirSync5(CODE_CONTEXT_DIR, { recursive: true });
5290
+ mkdirSync6(CODE_CONTEXT_DIR, { recursive: true });
5131
5291
  let pulled = 0;
5132
5292
  for (const { key, blob } of data.indexes) {
5133
5293
  try {
@@ -5135,7 +5295,7 @@ async function cloudPullCodeContext(config) {
5135
5295
  const localPath = path10.join(CODE_CONTEXT_DIR, key);
5136
5296
  const compressed = decryptSyncBlob(blob);
5137
5297
  const content = decompress(compressed).toString("utf8");
5138
- if (!existsSync10(localPath)) {
5298
+ if (!existsSync11(localPath)) {
5139
5299
  writeFileSync5(localPath, content, "utf-8");
5140
5300
  pulled++;
5141
5301
  } else {