@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
@@ -223,6 +223,27 @@ async function ensureSchema() {
223
223
  });
224
224
  } catch {
225
225
  }
226
+ try {
227
+ await client.execute({
228
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
229
+ args: []
230
+ });
231
+ } catch {
232
+ }
233
+ try {
234
+ await client.execute({
235
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
236
+ args: []
237
+ });
238
+ } catch {
239
+ }
240
+ try {
241
+ await client.execute({
242
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
243
+ args: []
244
+ });
245
+ } catch {
246
+ }
226
247
  try {
227
248
  await client.execute({
228
249
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -633,6 +654,15 @@ async function ensureSchema() {
633
654
  } catch {
634
655
  }
635
656
  }
657
+ for (const col of [
658
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
659
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
660
+ ]) {
661
+ try {
662
+ await client.execute(col);
663
+ } catch {
664
+ }
665
+ }
636
666
  await client.executeMultiple(`
637
667
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
638
668
  ON memories(workspace_id);
@@ -697,6 +727,34 @@ async function ensureSchema() {
697
727
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
698
728
  ON conversations(channel_id);
699
729
  `);
730
+ try {
731
+ await client.execute({
732
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
733
+ args: []
734
+ });
735
+ } catch {
736
+ }
737
+ try {
738
+ await client.execute({
739
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
740
+ args: []
741
+ });
742
+ } catch {
743
+ }
744
+ try {
745
+ await client.execute({
746
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
747
+ args: []
748
+ });
749
+ } catch {
750
+ }
751
+ try {
752
+ await client.execute({
753
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
754
+ args: []
755
+ });
756
+ } catch {
757
+ }
700
758
  await client.executeMultiple(`
701
759
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
702
760
  content_text,
@@ -723,6 +781,52 @@ async function ensureSchema() {
723
781
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
724
782
  END;
725
783
  `);
784
+ try {
785
+ await client.execute({
786
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
787
+ args: []
788
+ });
789
+ } catch {
790
+ }
791
+ try {
792
+ await client.execute(
793
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
794
+ );
795
+ } catch {
796
+ }
797
+ try {
798
+ await client.execute({
799
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
800
+ args: []
801
+ });
802
+ await client.execute({
803
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
804
+ args: []
805
+ });
806
+ } catch {
807
+ }
808
+ try {
809
+ await client.execute({
810
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
811
+ args: []
812
+ });
813
+ } catch {
814
+ }
815
+ try {
816
+ await client.execute(
817
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
818
+ );
819
+ } catch {
820
+ }
821
+ for (const col of [
822
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
823
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
824
+ ]) {
825
+ try {
826
+ await client.execute(col);
827
+ } catch {
828
+ }
829
+ }
726
830
  }
727
831
  var _client, initTurso;
728
832
  var init_database = __esm({
@@ -799,6 +903,11 @@ function normalizeSessionLifecycle(raw) {
799
903
  const userSL = raw.sessionLifecycle ?? {};
800
904
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
801
905
  }
906
+ function normalizeAutoUpdate(raw) {
907
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
908
+ const userAU = raw.autoUpdate ?? {};
909
+ raw.autoUpdate = { ...defaultAU, ...userAU };
910
+ }
802
911
  async function loadConfig() {
803
912
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
804
913
  await mkdir2(dir, { recursive: true });
@@ -821,6 +930,7 @@ async function loadConfig() {
821
930
  }
822
931
  normalizeScalingRoadmap(migratedCfg);
823
932
  normalizeSessionLifecycle(migratedCfg);
933
+ normalizeAutoUpdate(migratedCfg);
824
934
  const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
825
935
  if (config.dbPath.startsWith("~")) {
826
936
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -843,6 +953,7 @@ function loadConfigSync() {
843
953
  const { config: migratedCfg } = migrateConfig(parsed);
844
954
  normalizeScalingRoadmap(migratedCfg);
845
955
  normalizeSessionLifecycle(migratedCfg);
956
+ normalizeAutoUpdate(migratedCfg);
846
957
  return { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
847
958
  } catch {
848
959
  return { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db") };
@@ -914,6 +1025,11 @@ var init_config = __esm({
914
1025
  idleKillTicksRequired: 3,
915
1026
  idleKillIntercomAckWindowMs: 1e4,
916
1027
  maxAutoInstances: 10
1028
+ },
1029
+ autoUpdate: {
1030
+ checkOnBoot: true,
1031
+ autoInstall: false,
1032
+ checkIntervalMs: 24 * 60 * 60 * 1e3
917
1033
  }
918
1034
  };
919
1035
  CONFIG_MIGRATIONS = [
@@ -1047,13 +1163,27 @@ async function ensureShardSchema(client) {
1047
1163
  "ALTER TABLE memories ADD COLUMN document_id TEXT",
1048
1164
  "ALTER TABLE memories ADD COLUMN user_id TEXT",
1049
1165
  "ALTER TABLE memories ADD COLUMN char_offset INTEGER",
1050
- "ALTER TABLE memories ADD COLUMN page_number INTEGER"
1166
+ "ALTER TABLE memories ADD COLUMN page_number INTEGER",
1167
+ // Source provenance columns (must match database.ts)
1168
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
1169
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
1170
+ "ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
1171
+ "ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
1051
1172
  ]) {
1052
1173
  try {
1053
1174
  await client.execute(col);
1054
1175
  } catch {
1055
1176
  }
1056
1177
  }
1178
+ for (const idx of [
1179
+ "CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
1180
+ "CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
1181
+ ]) {
1182
+ try {
1183
+ await client.execute(idx);
1184
+ } catch {
1185
+ }
1186
+ }
1057
1187
  try {
1058
1188
  await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
1059
1189
  } catch {
@@ -1261,11 +1391,12 @@ var init_provider_table = __esm({
1261
1391
  import { readFileSync as readFileSync4, writeFileSync, renameSync as renameSync2, existsSync as existsSync7, mkdirSync as mkdirSync2 } from "fs";
1262
1392
  import path8 from "path";
1263
1393
  import os4 from "os";
1264
- var QUEUE_PATH, INTERCOM_LOG;
1394
+ var QUEUE_PATH, TTL_MS, INTERCOM_LOG;
1265
1395
  var init_intercom_queue = __esm({
1266
1396
  "src/lib/intercom-queue.ts"() {
1267
1397
  "use strict";
1268
1398
  QUEUE_PATH = path8.join(os4.homedir(), ".exe-os", "intercom-queue.json");
1399
+ TTL_MS = 60 * 60 * 1e3;
1269
1400
  INTERCOM_LOG = path8.join(os4.homedir(), ".exe-os", "intercom.log");
1270
1401
  }
1271
1402
  });
@@ -81,6 +81,11 @@ function normalizeSessionLifecycle(raw) {
81
81
  const userSL = raw.sessionLifecycle ?? {};
82
82
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
83
83
  }
84
+ function normalizeAutoUpdate(raw) {
85
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
86
+ const userAU = raw.autoUpdate ?? {};
87
+ raw.autoUpdate = { ...defaultAU, ...userAU };
88
+ }
84
89
  async function loadConfig() {
85
90
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
86
91
  await mkdir2(dir, { recursive: true });
@@ -103,6 +108,7 @@ async function loadConfig() {
103
108
  }
104
109
  normalizeScalingRoadmap(migratedCfg);
105
110
  normalizeSessionLifecycle(migratedCfg);
111
+ normalizeAutoUpdate(migratedCfg);
106
112
  const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
107
113
  if (config.dbPath.startsWith("~")) {
108
114
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -178,6 +184,11 @@ var init_config = __esm({
178
184
  idleKillTicksRequired: 3,
179
185
  idleKillIntercomAckWindowMs: 1e4,
180
186
  maxAutoInstances: 10
187
+ },
188
+ autoUpdate: {
189
+ checkOnBoot: true,
190
+ autoInstall: false,
191
+ checkIntervalMs: 24 * 60 * 60 * 1e3
181
192
  }
182
193
  };
183
194
  CONFIG_MIGRATIONS = [
@@ -311,13 +322,27 @@ async function ensureShardSchema(client) {
311
322
  "ALTER TABLE memories ADD COLUMN document_id TEXT",
312
323
  "ALTER TABLE memories ADD COLUMN user_id TEXT",
313
324
  "ALTER TABLE memories ADD COLUMN char_offset INTEGER",
314
- "ALTER TABLE memories ADD COLUMN page_number INTEGER"
325
+ "ALTER TABLE memories ADD COLUMN page_number INTEGER",
326
+ // Source provenance columns (must match database.ts)
327
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
328
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
329
+ "ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
330
+ "ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
315
331
  ]) {
316
332
  try {
317
333
  await client.execute(col);
318
334
  } catch {
319
335
  }
320
336
  }
337
+ for (const idx of [
338
+ "CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
339
+ "CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
340
+ ]) {
341
+ try {
342
+ await client.execute(idx);
343
+ } catch {
344
+ }
345
+ }
321
346
  try {
322
347
  await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
323
348
  } catch {
@@ -634,6 +659,27 @@ async function ensureSchema() {
634
659
  });
635
660
  } catch {
636
661
  }
662
+ try {
663
+ await client.execute({
664
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
665
+ args: []
666
+ });
667
+ } catch {
668
+ }
669
+ try {
670
+ await client.execute({
671
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
672
+ args: []
673
+ });
674
+ } catch {
675
+ }
676
+ try {
677
+ await client.execute({
678
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
679
+ args: []
680
+ });
681
+ } catch {
682
+ }
637
683
  try {
638
684
  await client.execute({
639
685
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -1044,6 +1090,15 @@ async function ensureSchema() {
1044
1090
  } catch {
1045
1091
  }
1046
1092
  }
1093
+ for (const col of [
1094
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
1095
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
1096
+ ]) {
1097
+ try {
1098
+ await client.execute(col);
1099
+ } catch {
1100
+ }
1101
+ }
1047
1102
  await client.executeMultiple(`
1048
1103
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
1049
1104
  ON memories(workspace_id);
@@ -1108,6 +1163,34 @@ async function ensureSchema() {
1108
1163
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1109
1164
  ON conversations(channel_id);
1110
1165
  `);
1166
+ try {
1167
+ await client.execute({
1168
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
1169
+ args: []
1170
+ });
1171
+ } catch {
1172
+ }
1173
+ try {
1174
+ await client.execute({
1175
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
1176
+ args: []
1177
+ });
1178
+ } catch {
1179
+ }
1180
+ try {
1181
+ await client.execute({
1182
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
1183
+ args: []
1184
+ });
1185
+ } catch {
1186
+ }
1187
+ try {
1188
+ await client.execute({
1189
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
1190
+ args: []
1191
+ });
1192
+ } catch {
1193
+ }
1111
1194
  await client.executeMultiple(`
1112
1195
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
1113
1196
  content_text,
@@ -1134,6 +1217,52 @@ async function ensureSchema() {
1134
1217
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
1135
1218
  END;
1136
1219
  `);
1220
+ try {
1221
+ await client.execute({
1222
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
1223
+ args: []
1224
+ });
1225
+ } catch {
1226
+ }
1227
+ try {
1228
+ await client.execute(
1229
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
1230
+ );
1231
+ } catch {
1232
+ }
1233
+ try {
1234
+ await client.execute({
1235
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
1236
+ args: []
1237
+ });
1238
+ await client.execute({
1239
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
1240
+ args: []
1241
+ });
1242
+ } catch {
1243
+ }
1244
+ try {
1245
+ await client.execute({
1246
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
1247
+ args: []
1248
+ });
1249
+ } catch {
1250
+ }
1251
+ try {
1252
+ await client.execute(
1253
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
1254
+ );
1255
+ } catch {
1256
+ }
1257
+ for (const col of [
1258
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
1259
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
1260
+ ]) {
1261
+ try {
1262
+ await client.execute(col);
1263
+ } catch {
1264
+ }
1265
+ }
1137
1266
  }
1138
1267
  var disposeTurso = disposeDatabase;
1139
1268
  async function disposeDatabase() {
@@ -1249,20 +1378,26 @@ async function flushBatch() {
1249
1378
  const userId = row.user_id ?? null;
1250
1379
  const charOffset = row.char_offset ?? null;
1251
1380
  const pageNumber = row.page_number ?? null;
1381
+ const sourcePath = row.source_path ?? null;
1382
+ const sourceType = row.source_type ?? null;
1383
+ const tier = row.tier ?? 3;
1384
+ const supersedesId = row.supersedes_id ?? null;
1252
1385
  return {
1253
1386
  sql: hasVector ? `INSERT OR IGNORE INTO memories
1254
1387
  (id, agent_id, agent_role, session_id, timestamp,
1255
1388
  tool_name, project_name,
1256
1389
  has_error, raw_text, vector, version, task_id, importance, status,
1257
1390
  confidence, last_accessed,
1258
- workspace_id, document_id, user_id, char_offset, page_number)
1259
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1391
+ workspace_id, document_id, user_id, char_offset, page_number,
1392
+ source_path, source_type, tier, supersedes_id)
1393
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1260
1394
  (id, agent_id, agent_role, session_id, timestamp,
1261
1395
  tool_name, project_name,
1262
1396
  has_error, raw_text, vector, version, task_id, importance, status,
1263
1397
  confidence, last_accessed,
1264
- workspace_id, document_id, user_id, char_offset, page_number)
1265
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1398
+ workspace_id, document_id, user_id, char_offset, page_number,
1399
+ source_path, source_type, tier, supersedes_id)
1400
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1266
1401
  args: hasVector ? [
1267
1402
  row.id,
1268
1403
  row.agent_id,
@@ -1284,7 +1419,11 @@ async function flushBatch() {
1284
1419
  documentId,
1285
1420
  userId,
1286
1421
  charOffset,
1287
- pageNumber
1422
+ pageNumber,
1423
+ sourcePath,
1424
+ sourceType,
1425
+ tier,
1426
+ supersedesId
1288
1427
  ] : [
1289
1428
  row.id,
1290
1429
  row.agent_id,
@@ -1305,7 +1444,11 @@ async function flushBatch() {
1305
1444
  documentId,
1306
1445
  userId,
1307
1446
  charOffset,
1308
- pageNumber
1447
+ pageNumber,
1448
+ sourcePath,
1449
+ sourceType,
1450
+ tier,
1451
+ supersedesId
1309
1452
  ]
1310
1453
  };
1311
1454
  };
@@ -81,6 +81,11 @@ function normalizeSessionLifecycle(raw) {
81
81
  const userSL = raw.sessionLifecycle ?? {};
82
82
  raw.sessionLifecycle = { ...defaultSL, ...userSL };
83
83
  }
84
+ function normalizeAutoUpdate(raw) {
85
+ const defaultAU = DEFAULT_CONFIG.autoUpdate;
86
+ const userAU = raw.autoUpdate ?? {};
87
+ raw.autoUpdate = { ...defaultAU, ...userAU };
88
+ }
84
89
  async function loadConfig() {
85
90
  const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
86
91
  await mkdir2(dir, { recursive: true });
@@ -103,6 +108,7 @@ async function loadConfig() {
103
108
  }
104
109
  normalizeScalingRoadmap(migratedCfg);
105
110
  normalizeSessionLifecycle(migratedCfg);
111
+ normalizeAutoUpdate(migratedCfg);
106
112
  const config = { ...DEFAULT_CONFIG, dbPath: path2.join(dir, "memories.db"), ...migratedCfg };
107
113
  if (config.dbPath.startsWith("~")) {
108
114
  config.dbPath = config.dbPath.replace(/^~/, os.homedir());
@@ -178,6 +184,11 @@ var init_config = __esm({
178
184
  idleKillTicksRequired: 3,
179
185
  idleKillIntercomAckWindowMs: 1e4,
180
186
  maxAutoInstances: 10
187
+ },
188
+ autoUpdate: {
189
+ checkOnBoot: true,
190
+ autoInstall: false,
191
+ checkIntervalMs: 24 * 60 * 60 * 1e3
181
192
  }
182
193
  };
183
194
  CONFIG_MIGRATIONS = [
@@ -311,13 +322,27 @@ async function ensureShardSchema(client) {
311
322
  "ALTER TABLE memories ADD COLUMN document_id TEXT",
312
323
  "ALTER TABLE memories ADD COLUMN user_id TEXT",
313
324
  "ALTER TABLE memories ADD COLUMN char_offset INTEGER",
314
- "ALTER TABLE memories ADD COLUMN page_number INTEGER"
325
+ "ALTER TABLE memories ADD COLUMN page_number INTEGER",
326
+ // Source provenance columns (must match database.ts)
327
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
328
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'",
329
+ "ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3",
330
+ "ALTER TABLE memories ADD COLUMN supersedes_id TEXT"
315
331
  ]) {
316
332
  try {
317
333
  await client.execute(col);
318
334
  } catch {
319
335
  }
320
336
  }
337
+ for (const idx of [
338
+ "CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
339
+ "CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
340
+ ]) {
341
+ try {
342
+ await client.execute(idx);
343
+ } catch {
344
+ }
345
+ }
321
346
  try {
322
347
  await client.execute("CREATE INDEX IF NOT EXISTS idx_memories_status ON memories(status)");
323
348
  } catch {
@@ -637,6 +662,27 @@ async function ensureSchema() {
637
662
  });
638
663
  } catch {
639
664
  }
665
+ try {
666
+ await client.execute({
667
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint TEXT`,
668
+ args: []
669
+ });
670
+ } catch {
671
+ }
672
+ try {
673
+ await client.execute({
674
+ sql: `ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER NOT NULL DEFAULT 0`,
675
+ args: []
676
+ });
677
+ } catch {
678
+ }
679
+ try {
680
+ await client.execute({
681
+ sql: `ALTER TABLE tasks ADD COLUMN complexity TEXT NOT NULL DEFAULT 'standard'`,
682
+ args: []
683
+ });
684
+ } catch {
685
+ }
640
686
  try {
641
687
  await client.execute({
642
688
  sql: `ALTER TABLE memories ADD COLUMN task_id TEXT`,
@@ -1047,6 +1093,15 @@ async function ensureSchema() {
1047
1093
  } catch {
1048
1094
  }
1049
1095
  }
1096
+ for (const col of [
1097
+ "ALTER TABLE memories ADD COLUMN source_path TEXT",
1098
+ "ALTER TABLE memories ADD COLUMN source_type TEXT DEFAULT 'text'"
1099
+ ]) {
1100
+ try {
1101
+ await client.execute(col);
1102
+ } catch {
1103
+ }
1104
+ }
1050
1105
  await client.executeMultiple(`
1051
1106
  CREATE INDEX IF NOT EXISTS idx_memories_workspace
1052
1107
  ON memories(workspace_id);
@@ -1111,6 +1166,34 @@ async function ensureSchema() {
1111
1166
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1112
1167
  ON conversations(channel_id);
1113
1168
  `);
1169
+ try {
1170
+ await client.execute({
1171
+ sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
1172
+ args: []
1173
+ });
1174
+ } catch {
1175
+ }
1176
+ try {
1177
+ await client.execute({
1178
+ sql: `ALTER TABLE tasks ADD COLUMN budget_fallback_model TEXT`,
1179
+ args: []
1180
+ });
1181
+ } catch {
1182
+ }
1183
+ try {
1184
+ await client.execute({
1185
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_used INTEGER DEFAULT 0`,
1186
+ args: []
1187
+ });
1188
+ } catch {
1189
+ }
1190
+ try {
1191
+ await client.execute({
1192
+ sql: `ALTER TABLE tasks ADD COLUMN tokens_warned_at INTEGER`,
1193
+ args: []
1194
+ });
1195
+ } catch {
1196
+ }
1114
1197
  await client.executeMultiple(`
1115
1198
  CREATE VIRTUAL TABLE IF NOT EXISTS conversations_fts USING fts5(
1116
1199
  content_text,
@@ -1137,6 +1220,52 @@ async function ensureSchema() {
1137
1220
  VALUES (new.rowid, new.content_text, new.sender_name, new.agent_response);
1138
1221
  END;
1139
1222
  `);
1223
+ try {
1224
+ await client.execute({
1225
+ sql: `ALTER TABLE memories ADD COLUMN tier INTEGER DEFAULT 3`,
1226
+ args: []
1227
+ });
1228
+ } catch {
1229
+ }
1230
+ try {
1231
+ await client.execute(
1232
+ `CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)`
1233
+ );
1234
+ } catch {
1235
+ }
1236
+ try {
1237
+ await client.execute({
1238
+ sql: `UPDATE memories SET tier = 1 WHERE tool_name = 'commit_to_long_term_memory' AND importance >= 8 AND tier = 3`,
1239
+ args: []
1240
+ });
1241
+ await client.execute({
1242
+ sql: `UPDATE memories SET tier = 2 WHERE tool_name IN ('store_memory', 'manual') AND importance >= 5 AND tier = 3`,
1243
+ args: []
1244
+ });
1245
+ } catch {
1246
+ }
1247
+ try {
1248
+ await client.execute({
1249
+ sql: `ALTER TABLE memories ADD COLUMN supersedes_id TEXT`,
1250
+ args: []
1251
+ });
1252
+ } catch {
1253
+ }
1254
+ try {
1255
+ await client.execute(
1256
+ `CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL`
1257
+ );
1258
+ } catch {
1259
+ }
1260
+ for (const col of [
1261
+ "ALTER TABLE tasks ADD COLUMN checkpoint TEXT",
1262
+ "ALTER TABLE tasks ADD COLUMN checkpoint_count INTEGER DEFAULT 0"
1263
+ ]) {
1264
+ try {
1265
+ await client.execute(col);
1266
+ } catch {
1267
+ }
1268
+ }
1140
1269
  }
1141
1270
  var disposeTurso = disposeDatabase;
1142
1271
  async function disposeDatabase() {
@@ -1252,20 +1381,26 @@ async function flushBatch() {
1252
1381
  const userId = row.user_id ?? null;
1253
1382
  const charOffset = row.char_offset ?? null;
1254
1383
  const pageNumber = row.page_number ?? null;
1384
+ const sourcePath = row.source_path ?? null;
1385
+ const sourceType = row.source_type ?? null;
1386
+ const tier = row.tier ?? 3;
1387
+ const supersedesId = row.supersedes_id ?? null;
1255
1388
  return {
1256
1389
  sql: hasVector ? `INSERT OR IGNORE INTO memories
1257
1390
  (id, agent_id, agent_role, session_id, timestamp,
1258
1391
  tool_name, project_name,
1259
1392
  has_error, raw_text, vector, version, task_id, importance, status,
1260
1393
  confidence, last_accessed,
1261
- workspace_id, document_id, user_id, char_offset, page_number)
1262
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1394
+ workspace_id, document_id, user_id, char_offset, page_number,
1395
+ source_path, source_type, tier, supersedes_id)
1396
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
1263
1397
  (id, agent_id, agent_role, session_id, timestamp,
1264
1398
  tool_name, project_name,
1265
1399
  has_error, raw_text, vector, version, task_id, importance, status,
1266
1400
  confidence, last_accessed,
1267
- workspace_id, document_id, user_id, char_offset, page_number)
1268
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1401
+ workspace_id, document_id, user_id, char_offset, page_number,
1402
+ source_path, source_type, tier, supersedes_id)
1403
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1269
1404
  args: hasVector ? [
1270
1405
  row.id,
1271
1406
  row.agent_id,
@@ -1287,7 +1422,11 @@ async function flushBatch() {
1287
1422
  documentId,
1288
1423
  userId,
1289
1424
  charOffset,
1290
- pageNumber
1425
+ pageNumber,
1426
+ sourcePath,
1427
+ sourceType,
1428
+ tier,
1429
+ supersedesId
1291
1430
  ] : [
1292
1431
  row.id,
1293
1432
  row.agent_id,
@@ -1308,7 +1447,11 @@ async function flushBatch() {
1308
1447
  documentId,
1309
1448
  userId,
1310
1449
  charOffset,
1311
- pageNumber
1450
+ pageNumber,
1451
+ sourcePath,
1452
+ sourceType,
1453
+ tier,
1454
+ supersedesId
1312
1455
  ]
1313
1456
  };
1314
1457
  };