@askexenow/exe-os 0.8.0 → 0.8.1

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 (90) hide show
  1. package/README.md +178 -79
  2. package/dist/bin/backfill-responses.js +160 -8
  3. package/dist/bin/backfill-vectors.js +130 -1
  4. package/dist/bin/cleanup-stale-review-tasks.js +130 -1
  5. package/dist/bin/cli.js +10111 -7540
  6. package/dist/bin/exe-agent.js +159 -1
  7. package/dist/bin/exe-assign.js +235 -16
  8. package/dist/bin/exe-boot.js +344 -472
  9. package/dist/bin/exe-call.js +145 -1
  10. package/dist/bin/exe-cloud.js +11 -0
  11. package/dist/bin/exe-dispatch.js +37 -24
  12. package/dist/bin/exe-doctor.js +130 -1
  13. package/dist/bin/exe-export-behaviors.js +150 -7
  14. package/dist/bin/exe-forget.js +822 -665
  15. package/dist/bin/exe-gateway.js +470 -62
  16. package/dist/bin/exe-heartbeat.js +133 -2
  17. package/dist/bin/exe-kill.js +150 -7
  18. package/dist/bin/exe-launch-agent.js +150 -7
  19. package/dist/bin/exe-new-employee.js +756 -224
  20. package/dist/bin/exe-pending-messages.js +132 -2
  21. package/dist/bin/exe-pending-notifications.js +130 -1
  22. package/dist/bin/exe-pending-reviews.js +132 -2
  23. package/dist/bin/exe-review.js +160 -8
  24. package/dist/bin/exe-search.js +2473 -2008
  25. package/dist/bin/exe-session-cleanup.js +238 -51
  26. package/dist/bin/exe-settings.js +11 -0
  27. package/dist/bin/exe-status.js +130 -1
  28. package/dist/bin/exe-team.js +130 -1
  29. package/dist/bin/git-sweep.js +272 -16
  30. package/dist/bin/graph-backfill.js +150 -7
  31. package/dist/bin/graph-export.js +150 -7
  32. package/dist/bin/install.js +5 -0
  33. package/dist/bin/scan-tasks.js +238 -19
  34. package/dist/bin/setup.js +1776 -10
  35. package/dist/bin/shard-migrate.js +150 -7
  36. package/dist/bin/update.js +9 -6
  37. package/dist/bin/wiki-sync.js +150 -7
  38. package/dist/gateway/index.js +470 -62
  39. package/dist/hooks/bug-report-worker.js +195 -35
  40. package/dist/hooks/commit-complete.js +272 -16
  41. package/dist/hooks/error-recall.js +2313 -1847
  42. package/dist/hooks/exe-heartbeat-hook.js +5 -0
  43. package/dist/hooks/ingest-worker.js +330 -58
  44. package/dist/hooks/ingest.js +11 -0
  45. package/dist/hooks/instructions-loaded.js +199 -10
  46. package/dist/hooks/notification.js +199 -10
  47. package/dist/hooks/post-compact.js +199 -10
  48. package/dist/hooks/pre-compact.js +199 -10
  49. package/dist/hooks/pre-tool-use.js +199 -10
  50. package/dist/hooks/prompt-ingest-worker.js +179 -14
  51. package/dist/hooks/prompt-submit.js +781 -285
  52. package/dist/hooks/response-ingest-worker.js +1900 -1405
  53. package/dist/hooks/session-end.js +456 -12
  54. package/dist/hooks/session-start.js +2188 -1724
  55. package/dist/hooks/stop.js +200 -10
  56. package/dist/hooks/subagent-stop.js +199 -10
  57. package/dist/hooks/summary-worker.js +604 -334
  58. package/dist/index.js +554 -61
  59. package/dist/lib/cloud-sync.js +5 -0
  60. package/dist/lib/config.js +13 -0
  61. package/dist/lib/consolidation.js +5 -0
  62. package/dist/lib/database.js +104 -0
  63. package/dist/lib/device-registry.js +109 -0
  64. package/dist/lib/embedder.js +13 -0
  65. package/dist/lib/employee-templates.js +53 -26
  66. package/dist/lib/employees.js +5 -0
  67. package/dist/lib/exe-daemon-client.js +5 -0
  68. package/dist/lib/exe-daemon.js +493 -79
  69. package/dist/lib/file-grep.js +20 -4
  70. package/dist/lib/hybrid-search.js +1435 -190
  71. package/dist/lib/identity-templates.js +126 -5
  72. package/dist/lib/identity.js +5 -0
  73. package/dist/lib/license.js +5 -0
  74. package/dist/lib/messaging.js +37 -24
  75. package/dist/lib/schedules.js +130 -1
  76. package/dist/lib/skill-learning.js +11 -0
  77. package/dist/lib/status-brief.js +5 -0
  78. package/dist/lib/store.js +199 -10
  79. package/dist/lib/task-router.js +72 -6
  80. package/dist/lib/tasks.js +179 -50
  81. package/dist/lib/tmux-routing.js +179 -46
  82. package/dist/mcp/server.js +2129 -1855
  83. package/dist/mcp/tools/create-task.js +86 -36
  84. package/dist/mcp/tools/deactivate-behavior.js +5 -0
  85. package/dist/mcp/tools/list-tasks.js +39 -11
  86. package/dist/mcp/tools/send-message.js +37 -24
  87. package/dist/mcp/tools/update-task.js +153 -38
  88. package/dist/runtime/index.js +451 -59
  89. package/dist/tui/App.js +454 -59
  90. package/package.json +1 -1
@@ -104,6 +104,11 @@ function normalizeSessionLifecycle(raw) {
104
104
  const userSL = raw.sessionLifecycle ?? {};
105
105
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
106
106
  }
107
+ function normalizeAutoUpdate(raw) {
108
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
109
+ const userAU = raw.autoUpdate ?? {};
110
+ raw.autoUpdate = { ...defaultAU, ...userAU };
111
+ }
107
112
  async function loadConfig() {
108
113
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
109
114
  await mkdir2(dir, { recursive: true });
@@ -126,6 +131,7 @@ async function loadConfig() {
126
131
  }
127
132
  normalizeScalingRoadmap(migratedCfg);
128
133
  normalizeSessionLifecycle(migratedCfg);
134
+ normalizeAutoUpdate(migratedCfg);
129
135
  const config = { ...DEFAULT_CONFIG, dbPath: path3.join(dir, "memories.db"), ...migratedCfg };
130
136
  if (config.dbPath.startsWith("~")) {
131
137
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -148,6 +154,7 @@ function loadConfigSync() {
148
154
  const { config: migratedCfg } = migrateConfig(parsed);
149
155
  normalizeScalingRoadmap(migratedCfg);
150
156
  normalizeSessionLifecycle(migratedCfg);
157
+ normalizeAutoUpdate(migratedCfg);
151
158
  return { ...DEFAULT_CONFIG, dbPath: path3.join(dir, "memories.db"), ...migratedCfg };
152
159
  } catch {
153
160
  return { ...DEFAULT_CONFIG, dbPath: path3.join(dir, "memories.db") };
@@ -167,6 +174,7 @@ async function loadConfigFrom(configPath) {
167
174
  const { config: migratedCfg } = migrateConfig(parsed);
168
175
  normalizeScalingRoadmap(migratedCfg);
169
176
  normalizeSessionLifecycle(migratedCfg);
177
+ normalizeAutoUpdate(migratedCfg);
170
178
  return { ...DEFAULT_CONFIG, ...migratedCfg };
171
179
  } catch {
172
180
  return { ...DEFAULT_CONFIG };
@@ -238,6 +246,11 @@ var init_config = __esm({
238
246
  idleKillTicksRequired: 3,
239
247
  idleKillIntercomAckWindowMs: 1e4,
240
248
  maxAutoInstances: 10
249
+ },
250
+ autoUpdate: {
251
+ checkOnBoot: true,
252
+ autoInstall: false,
253
+ checkIntervalMs: 24 * 60 * 60 * 1e3
241
254
  }
242
255
  };
243
256
  CONFIG_MIGRATIONS = [
@@ -371,13 +384,27 @@ async function ensureShardSchema(client) {
371
384
  "ALTER TABLE memories ADD COLUMN document_id TEXT",
372
385
  "ALTER TABLE memories ADD COLUMN user_id TEXT",
373
386
  "ALTER TABLE memories ADD COLUMN char_offset INTEGER",
374
- "ALTER TABLE memories ADD COLUMN page_number INTEGER"
387
+ "ALTER TABLE memories ADD COLUMN page_number INTEGER",
388
+ // Source provenance columns (must match database.ts)
389
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
390
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
391
+ "ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
392
+ "ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
375
393
  ]) {
376
394
  try {
377
395
  await client.execute(col);
378
396
  } catch {
379
397
  }
380
398
  }
399
+ for (const idx of [
400
+ "CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
401
+ "CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
402
+ ]) {
403
+ try {
404
+ await client.execute(idx);
405
+ } catch {
406
+ }
407
+ }
381
408
  try {
382
409
  await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
383
410
  } catch {
@@ -899,12 +926,23 @@ function getProjectName(cwd) {
899
926
  const dir = cwd ?? process.cwd();
900
927
  if (_cached && _cachedCwd === dir) return _cached;
901
928
  try {
902
- const repoRoot = execSync("git rev-parse --show-toplevel", {
903
- cwd: dir,
904
- encoding: "utf8",
905
- timeout: 2e3,
906
- stdio: ["pipe", "pipe", "pipe"]
907
- }).trim();
929
+ let repoRoot;
930
+ try {
931
+ const gitCommonDir = execSync("git rev-parse --path-format=absolute --git-common-dir", {
932
+ cwd: dir,
933
+ encoding: "utf8",
934
+ timeout: 2e3,
935
+ stdio: ["pipe", "pipe", "pipe"]
936
+ }).trim();
937
+ repoRoot = path.dirname(gitCommonDir);
938
+ } catch {
939
+ repoRoot = execSync("git rev-parse --show-toplevel", {
940
+ cwd: dir,
941
+ encoding: "utf8",
942
+ timeout: 2e3,
943
+ stdio: ["pipe", "pipe", "pipe"]
944
+ }).trim();
945
+ }
908
946
  _cached = path.basename(repoRoot);
909
947
  _cachedCwd = dir;
910
948
  return _cached;
@@ -1131,6 +1169,27 @@ async function ensureSchema() {
1131
1169
  });
1132
1170
  } catch {
1133
1171
  }
1172
+ try {
1173
+ await client.execute({
1174
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
1175
+ args: []
1176
+ });
1177
+ } catch {
1178
+ }
1179
+ try {
1180
+ await client.execute({
1181
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
1182
+ args: []
1183
+ });
1184
+ } catch {
1185
+ }
1186
+ try {
1187
+ await client.execute({
1188
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
1189
+ args: []
1190
+ });
1191
+ } catch {
1192
+ }
1134
1193
  try {
1135
1194
  await client.execute({
1136
1195
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -1541,6 +1600,15 @@ async function ensureSchema() {
1541
1600
  } catch {
1542
1601
  }
1543
1602
  }
1603
+ for (const col of [
1604
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
1605
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
1606
+ ]) {
1607
+ try {
1608
+ await client.execute(col);
1609
+ } catch {
1610
+ }
1611
+ }
1544
1612
  await client.executeMultiple(`
1545
1613
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
1546
1614
  ON memories(workspace_id);
@@ -1605,6 +1673,34 @@ async function ensureSchema() {
1605
1673
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1606
1674
  ON conversations(channel_id);
1607
1675
  `);
1676
+ try {
1677
+ await client.execute({
1678
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
1679
+ args: []
1680
+ });
1681
+ } catch {
1682
+ }
1683
+ try {
1684
+ await client.execute({
1685
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
1686
+ args: []
1687
+ });
1688
+ } catch {
1689
+ }
1690
+ try {
1691
+ await client.execute({
1692
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
1693
+ args: []
1694
+ });
1695
+ } catch {
1696
+ }
1697
+ try {
1698
+ await client.execute({
1699
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
1700
+ args: []
1701
+ });
1702
+ } catch {
1703
+ }
1608
1704
  await client.executeMultiple(`
1609
1705
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
1610
1706
  content_text,
@@ -1631,6 +1727,52 @@ async function ensureSchema() {
1631
1727
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
1632
1728
  END;
1633
1729
  `);
1730
+ try {
1731
+ await client.execute({
1732
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
1733
+ args: []
1734
+ });
1735
+ } catch {
1736
+ }
1737
+ try {
1738
+ await client.execute(
1739
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
1740
+ );
1741
+ } catch {
1742
+ }
1743
+ try {
1744
+ await client.execute({
1745
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
1746
+ args: []
1747
+ });
1748
+ await client.execute({
1749
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
1750
+ args: []
1751
+ });
1752
+ } catch {
1753
+ }
1754
+ try {
1755
+ await client.execute({
1756
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
1757
+ args: []
1758
+ });
1759
+ } catch {
1760
+ }
1761
+ try {
1762
+ await client.execute(
1763
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
1764
+ );
1765
+ } catch {
1766
+ }
1767
+ for (const col of [
1768
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
1769
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
1770
+ ]) {
1771
+ try {
1772
+ await client.execute(col);
1773
+ } catch {
1774
+ }
1775
+ }
1634
1776
  }
1635
1777
 
1636
1778
  // src/lib/keychain.ts
@@ -1722,6 +1864,11 @@ async function initStore(options) {
1722
1864
  const vResult = await client.execute("SELECT MAX(version) as max_v FROM memories");
1723
1865
  _nextVersion = (Number(vResult.rows[0]?.max_v) || 0) + 1;
1724
1866
  }
1867
+ function classifyTier(record) {
1868
+ if (record.tool_name === "commit_to_long_term_memory" && (record.importance ?? 0) >= 8) return 1;
1869
+ if (["store_memory", "manual"].includes(record.tool_name ?? "") && (record.importance ?? 0) >= 5) return 2;
1870
+ return 3;
1871
+ }
1725
1872
  async function writeMemory(record) {
1726
1873
  if (record.vector !== null && record.vector.length !== EMBEDDING_DIM) {
1727
1874
  throw new Error(
@@ -1749,7 +1896,11 @@ async function writeMemory(record) {
1749
1896
  document_id: record.document_id ?? null,
1750
1897
  user_id: record.user_id ?? null,
1751
1898
  char_offset: record.char_offset ?? null,
1752
- page_number: record.page_number ?? null
1899
+ page_number: record.page_number ?? null,
1900
+ source_path: record.source_path ?? null,
1901
+ source_type: record.source_type ?? null,
1902
+ tier: record.tier ?? classifyTier(record),
1903
+ supersedes_id: record.supersedes_id ?? null
1753
1904
  };
1754
1905
  _pendingRecords.push(dbRow);
1755
1906
  if (_flushTimer === null) {
@@ -1781,20 +1932,26 @@ async function flushBatch() {
1781
1932
  const userId = row.user_id ?? null;
1782
1933
  const charOffset = row.char_offset ?? null;
1783
1934
  const pageNumber = row.page_number ?? null;
1935
+ const sourcePath = row.source_path ?? null;
1936
+ const sourceType = row.source_type ?? null;
1937
+ const tier = row.tier ?? 3;
1938
+ const supersedesId = row.supersedes_id ?? null;
1784
1939
  return {
1785
1940
  sql: hasVector ? `INSERT OR IGNORE INTO memories
1786
1941
  (id, agent_id, agent_role, session_id, timestamp,
1787
1942
  tool_name, project_name,
1788
1943
  has_error, raw_text, vector, version, task_id, importance, status,
1789
1944
  confidence, last_accessed,
1790
- workspace_id, document_id, user_id, char_offset, page_number)
1791
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1945
+ workspace_id, document_id, user_id, char_offset, page_number,
1946
+ source_path, source_type, tier, supersedes_id)
1947
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1792
1948
  (id, agent_id, agent_role, session_id, timestamp,
1793
1949
  tool_name, project_name,
1794
1950
  has_error, raw_text, vector, version, task_id, importance, status,
1795
1951
  confidence, last_accessed,
1796
- workspace_id, document_id, user_id, char_offset, page_number)
1797
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1952
+ workspace_id, document_id, user_id, char_offset, page_number,
1953
+ source_path, source_type, tier, supersedes_id)
1954
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1798
1955
  args: hasVector ? [
1799
1956
  row.id,
1800
1957
  row.agent_id,
@@ -1816,7 +1973,11 @@ async function flushBatch() {
1816
1973
  documentId,
1817
1974
  userId,
1818
1975
  charOffset,
1819
- pageNumber
1976
+ pageNumber,
1977
+ sourcePath,
1978
+ sourceType,
1979
+ tier,
1980
+ supersedesId
1820
1981
  ] : [
1821
1982
  row.id,
1822
1983
  row.agent_id,
@@ -1837,7 +1998,11 @@ async function flushBatch() {
1837
1998
  documentId,
1838
1999
  userId,
1839
2000
  charOffset,
1840
- pageNumber
2001
+ pageNumber,
2002
+ sourcePath,
2003
+ sourceType,
2004
+ tier,
2005
+ supersedesId
1841
2006
  ]
1842
2007
  };
1843
2008
  };