@askexenow/exe-os 0.9.32 → 0.9.34

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 (75) hide show
  1. package/dist/bin/backfill-conversations.js +18 -2
  2. package/dist/bin/backfill-responses.js +18 -2
  3. package/dist/bin/backfill-vectors.js +18 -2
  4. package/dist/bin/cleanup-stale-review-tasks.js +18 -2
  5. package/dist/bin/cli.js +43 -11
  6. package/dist/bin/exe-assign.js +18 -2
  7. package/dist/bin/exe-boot.js +32 -10
  8. package/dist/bin/exe-cloud.js +3 -3
  9. package/dist/bin/exe-dispatch.js +21 -4
  10. package/dist/bin/exe-doctor.js +45 -21
  11. package/dist/bin/exe-export-behaviors.js +18 -2
  12. package/dist/bin/exe-forget.js +27 -8
  13. package/dist/bin/exe-gateway.js +21 -4
  14. package/dist/bin/exe-heartbeat.js +18 -2
  15. package/dist/bin/exe-kill.js +18 -2
  16. package/dist/bin/exe-launch-agent.js +34 -2
  17. package/dist/bin/exe-link.js +20 -5
  18. package/dist/bin/exe-pending-messages.js +18 -2
  19. package/dist/bin/exe-pending-notifications.js +18 -2
  20. package/dist/bin/exe-pending-reviews.js +18 -2
  21. package/dist/bin/exe-rename.js +18 -2
  22. package/dist/bin/exe-review.js +18 -2
  23. package/dist/bin/exe-search.js +18 -2
  24. package/dist/bin/exe-session-cleanup.js +21 -4
  25. package/dist/bin/exe-settings.js +1 -1
  26. package/dist/bin/exe-start-codex.js +42 -7
  27. package/dist/bin/exe-start-opencode.js +34 -2
  28. package/dist/bin/exe-status.js +18 -2
  29. package/dist/bin/exe-team.js +18 -2
  30. package/dist/bin/git-sweep.js +21 -4
  31. package/dist/bin/graph-backfill.js +18 -2
  32. package/dist/bin/graph-export.js +18 -2
  33. package/dist/bin/intercom-check.js +21 -4
  34. package/dist/bin/scan-tasks.js +21 -4
  35. package/dist/bin/setup.js +24 -9
  36. package/dist/bin/shard-migrate.js +18 -2
  37. package/dist/gateway/index.js +21 -4
  38. package/dist/hooks/bug-report-worker.js +21 -4
  39. package/dist/hooks/codex-stop-task-finalizer.js +21 -4
  40. package/dist/hooks/commit-complete.js +21 -4
  41. package/dist/hooks/error-recall.js +27 -2
  42. package/dist/hooks/exe-heartbeat-hook.js +9 -0
  43. package/dist/hooks/ingest.js +27 -2
  44. package/dist/hooks/instructions-loaded.js +27 -2
  45. package/dist/hooks/notification.js +27 -2
  46. package/dist/hooks/post-compact.js +30 -3
  47. package/dist/hooks/post-tool-combined.js +34 -2
  48. package/dist/hooks/pre-compact.js +33 -5
  49. package/dist/hooks/pre-tool-use.js +30 -3
  50. package/dist/hooks/prompt-submit.js +33 -5
  51. package/dist/hooks/session-end.js +33 -5
  52. package/dist/hooks/session-start.js +34 -2
  53. package/dist/hooks/stop.js +30 -3
  54. package/dist/hooks/subagent-stop.js +30 -3
  55. package/dist/hooks/summary-worker.js +22 -7
  56. package/dist/index.js +21 -4
  57. package/dist/lib/cloud-sync.js +20 -5
  58. package/dist/lib/database.js +17 -1
  59. package/dist/lib/db.js +17 -1
  60. package/dist/lib/device-registry.js +18 -2
  61. package/dist/lib/exe-daemon.js +20243 -6717
  62. package/dist/lib/hybrid-search.js +18 -2
  63. package/dist/lib/schedules.js +18 -2
  64. package/dist/lib/store.js +18 -2
  65. package/dist/lib/tasks.js +3 -2
  66. package/dist/lib/tmux-routing.js +3 -2
  67. package/dist/mcp/server.js +213 -167
  68. package/dist/mcp/tools/create-task.js +15 -3
  69. package/dist/mcp/tools/deactivate-behavior.js +9 -0
  70. package/dist/mcp/tools/list-tasks.js +12 -1
  71. package/dist/mcp/tools/send-message.js +12 -1
  72. package/dist/mcp/tools/update-task.js +19 -2
  73. package/dist/runtime/index.js +21 -4
  74. package/dist/tui/App.js +21 -4
  75. package/package.json +1 -1
@@ -1446,6 +1446,7 @@ var init_db_daemon_client = __esm({
1446
1446
  // src/lib/database.ts
1447
1447
  var database_exports = {};
1448
1448
  __export(database_exports, {
1449
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1449
1450
  disposeDatabase: () => disposeDatabase,
1450
1451
  disposeTurso: () => disposeTurso,
1451
1452
  ensureSchema: () => ensureSchema,
@@ -1602,10 +1603,17 @@ async function ensureSchema() {
1602
1603
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1603
1604
  END;
1604
1605
 
1605
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
1606
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
1607
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
1606
1608
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1607
1609
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
1608
1610
  END;
1611
+
1612
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
1613
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
1614
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
1615
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1616
+ END;
1609
1617
  `);
1610
1618
  await client.executeMultiple(`
1611
1619
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2008,6 +2016,13 @@ async function ensureSchema() {
2008
2016
  });
2009
2017
  } catch {
2010
2018
  }
2019
+ try {
2020
+ await client.execute({
2021
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2022
+ args: []
2023
+ });
2024
+ } catch {
2025
+ }
2011
2026
  try {
2012
2027
  await client.execute({
2013
2028
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -2544,7 +2559,7 @@ async function disposeDatabase() {
2544
2559
  _resilientClient = null;
2545
2560
  }
2546
2561
  }
2547
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2562
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2548
2563
  var init_database = __esm({
2549
2564
  "src/lib/database.ts"() {
2550
2565
  "use strict";
@@ -2558,6 +2573,7 @@ var init_database = __esm({
2558
2573
  _daemonClient = null;
2559
2574
  _adapterClient = null;
2560
2575
  initTurso = initDatabase;
2576
+ SOFT_DELETE_RETENTION_DAYS = 7;
2561
2577
  disposeTurso = disposeDatabase;
2562
2578
  }
2563
2579
  });
@@ -4028,9 +4044,9 @@ async function auditDuplicates(client, flags) {
4028
4044
  const { clause, args } = agentFilter(flags);
4029
4045
  const backfillExclude = clause ? " AND tool_name != 'ConversationBackfill'" : " WHERE tool_name != 'ConversationBackfill'";
4030
4046
  const groups = await client.execute({
4031
- sql: `SELECT raw_text, COUNT(*) as cnt
4047
+ sql: `SELECT SUBSTR(raw_text, 1, 200) as text_head, LENGTH(raw_text) as text_len, COUNT(*) as cnt
4032
4048
  FROM memories${clause}${backfillExclude}
4033
- GROUP BY raw_text
4049
+ GROUP BY text_head, text_len
4034
4050
  HAVING cnt > 1
4035
4051
  ORDER BY cnt DESC
4036
4052
  LIMIT 500`,
@@ -4038,23 +4054,33 @@ async function auditDuplicates(client, flags) {
4038
4054
  });
4039
4055
  const duplicates = [];
4040
4056
  for (const g of groups.rows) {
4041
- const text = g.raw_text;
4042
- const cnt = Number(g.cnt);
4043
- const filterArgs = [text, ...args];
4044
- let filterClause = " WHERE raw_text = ?";
4057
+ const textHead = g.text_head;
4058
+ const textLen = Number(g.text_len);
4059
+ const filterArgs = [textHead, textLen, ...args];
4060
+ let filterClause = " WHERE SUBSTR(raw_text, 1, 200) = ? AND LENGTH(raw_text) = ?";
4045
4061
  if (flags.agent) filterClause += " AND agent_id = ?";
4046
4062
  if (flags.project) filterClause += " AND project_name = ?";
4047
4063
  const ids = await client.execute({
4048
- sql: `SELECT id FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
4064
+ sql: `SELECT id, raw_text FROM memories${filterClause} ORDER BY timestamp DESC LIMIT 10000`,
4049
4065
  args: filterArgs
4050
4066
  });
4051
- const allIds = ids.rows.map((r) => r.id);
4052
- duplicates.push({
4053
- raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
4054
- count: cnt,
4055
- keep_id: allIds[0],
4056
- delete_ids: allIds.slice(1)
4057
- });
4067
+ const byText = /* @__PURE__ */ new Map();
4068
+ for (const r of ids.rows) {
4069
+ const text = r.raw_text;
4070
+ const id = r.id;
4071
+ const existing = byText.get(text);
4072
+ if (existing) existing.push(id);
4073
+ else byText.set(text, [id]);
4074
+ }
4075
+ for (const [text, allIds] of byText) {
4076
+ if (allIds.length <= 1) continue;
4077
+ duplicates.push({
4078
+ raw_text: text.length > 100 ? text.slice(0, 100) + "..." : text,
4079
+ count: allIds.length,
4080
+ keep_id: allIds[0],
4081
+ delete_ids: allIds.slice(1)
4082
+ });
4083
+ }
4058
4084
  }
4059
4085
  return duplicates;
4060
4086
  }
@@ -4348,15 +4374,13 @@ async function fixDuplicates(client, duplicates, dryRun) {
4348
4374
  continue;
4349
4375
  }
4350
4376
  const placeholders = dup.delete_ids.map(() => "?").join(",");
4377
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4351
4378
  await client.execute({
4352
- sql: `DELETE FROM memories WHERE id IN (${placeholders})`,
4353
- args: dup.delete_ids
4379
+ sql: `UPDATE memories SET status = 'deleted', deleted_at = ? WHERE id IN (${placeholders})`,
4380
+ args: [now, ...dup.delete_ids]
4354
4381
  });
4355
4382
  deleted += dup.delete_ids.length;
4356
4383
  }
4357
- if (!dryRun && deleted > 0) {
4358
- await client.execute("INSERT INTO memories_fts(memories_fts) VALUES('rebuild')");
4359
- }
4360
4384
  return deleted;
4361
4385
  }
4362
4386
  async function fixBloated(client, bloated, dryRun) {
@@ -1661,6 +1661,7 @@ var init_db_daemon_client = __esm({
1661
1661
  // src/lib/database.ts
1662
1662
  var database_exports = {};
1663
1663
  __export(database_exports, {
1664
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1664
1665
  disposeDatabase: () => disposeDatabase,
1665
1666
  disposeTurso: () => disposeTurso,
1666
1667
  ensureSchema: () => ensureSchema,
@@ -1817,10 +1818,17 @@ async function ensureSchema() {
1817
1818
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1818
1819
  END;
1819
1820
 
1820
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
1821
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
1822
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
1821
1823
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1822
1824
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
1823
1825
  END;
1826
+
1827
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
1828
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
1829
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
1830
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1831
+ END;
1824
1832
  `);
1825
1833
  await client.executeMultiple(`
1826
1834
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2223,6 +2231,13 @@ async function ensureSchema() {
2223
2231
  });
2224
2232
  } catch {
2225
2233
  }
2234
+ try {
2235
+ await client.execute({
2236
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2237
+ args: []
2238
+ });
2239
+ } catch {
2240
+ }
2226
2241
  try {
2227
2242
  await client.execute({
2228
2243
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -2759,7 +2774,7 @@ async function disposeDatabase() {
2759
2774
  _resilientClient = null;
2760
2775
  }
2761
2776
  }
2762
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2777
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2763
2778
  var init_database = __esm({
2764
2779
  "src/lib/database.ts"() {
2765
2780
  "use strict";
@@ -2773,6 +2788,7 @@ var init_database = __esm({
2773
2788
  _daemonClient = null;
2774
2789
  _adapterClient = null;
2775
2790
  initTurso = initDatabase;
2791
+ SOFT_DELETE_RETENTION_DAYS = 7;
2776
2792
  disposeTurso = disposeDatabase;
2777
2793
  }
2778
2794
  });
@@ -1661,6 +1661,7 @@ var init_db_daemon_client = __esm({
1661
1661
  // src/lib/database.ts
1662
1662
  var database_exports = {};
1663
1663
  __export(database_exports, {
1664
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1664
1665
  disposeDatabase: () => disposeDatabase,
1665
1666
  disposeTurso: () => disposeTurso,
1666
1667
  ensureSchema: () => ensureSchema,
@@ -1817,10 +1818,17 @@ async function ensureSchema() {
1817
1818
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1818
1819
  END;
1819
1820
 
1820
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
1821
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
1822
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
1821
1823
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1822
1824
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
1823
1825
  END;
1826
+
1827
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
1828
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
1829
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
1830
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1831
+ END;
1824
1832
  `);
1825
1833
  await client.executeMultiple(`
1826
1834
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2223,6 +2231,13 @@ async function ensureSchema() {
2223
2231
  });
2224
2232
  } catch {
2225
2233
  }
2234
+ try {
2235
+ await client.execute({
2236
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2237
+ args: []
2238
+ });
2239
+ } catch {
2240
+ }
2226
2241
  try {
2227
2242
  await client.execute({
2228
2243
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -2759,7 +2774,7 @@ async function disposeDatabase() {
2759
2774
  _resilientClient = null;
2760
2775
  }
2761
2776
  }
2762
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2777
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2763
2778
  var init_database = __esm({
2764
2779
  "src/lib/database.ts"() {
2765
2780
  "use strict";
@@ -2773,6 +2788,7 @@ var init_database = __esm({
2773
2788
  _daemonClient = null;
2774
2789
  _adapterClient = null;
2775
2790
  initTurso = initDatabase;
2791
+ SOFT_DELETE_RETENTION_DAYS = 7;
2776
2792
  disposeTurso = disposeDatabase;
2777
2793
  }
2778
2794
  });
@@ -4566,8 +4582,9 @@ async function main() {
4566
4582
  const row = check.rows[0];
4567
4583
  console.log(`Memory: [${row.timestamp}] ${row.tool_name} (agent: ${row.agent_id})`);
4568
4584
  if (await confirm(rl, "Delete this memory?")) {
4569
- await client.execute({ sql: "DELETE FROM memories WHERE id = ?", args: [value] });
4570
- console.log("Deleted.");
4585
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4586
+ await client.execute({ sql: "UPDATE memories SET status = 'deleted', deleted_at = ? WHERE id = ?", args: [now, value] });
4587
+ console.log("Deleted (recoverable for 7 days).");
4571
4588
  } else {
4572
4589
  console.log("Cancelled.");
4573
4590
  }
@@ -4593,8 +4610,9 @@ This will permanently delete ALL memories for this employee.`);
4593
4610
  if (typed !== value) {
4594
4611
  console.log("Name didn't match. Cancelled.");
4595
4612
  } else {
4596
- await client.execute({ sql: "DELETE FROM memories WHERE agent_id = ?", args: [value] });
4597
- console.log(`Deleted ${total} memories for "${value}".`);
4613
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4614
+ await client.execute({ sql: "UPDATE memories SET status = 'deleted', deleted_at = ? WHERE agent_id = ?", args: [now, value] });
4615
+ console.log(`Deleted ${total} memories for "${value}" (recoverable for 7 days).`);
4598
4616
  }
4599
4617
  } else if (flag === "--query") {
4600
4618
  const agentId = process.env.AGENT_ID;
@@ -4644,9 +4662,10 @@ This will permanently delete ALL memories for this employee.`);
4644
4662
  if (matches.length > 0) {
4645
4663
  const ids = matches.map((m) => m.id);
4646
4664
  const placeholders = ids.map(() => "?").join(",");
4665
+ const now = (/* @__PURE__ */ new Date()).toISOString();
4647
4666
  await client.execute({
4648
- sql: `DELETE FROM memories WHERE id IN (${placeholders})`,
4649
- args: ids
4667
+ sql: `UPDATE memories SET status = 'deleted', deleted_at = ? WHERE id IN (${placeholders})`,
4668
+ args: [now, ...ids]
4650
4669
  });
4651
4670
  }
4652
4671
  if (behaviorMatches.length > 0) {
@@ -2306,6 +2306,7 @@ var init_db_daemon_client = __esm({
2306
2306
  // src/lib/database.ts
2307
2307
  var database_exports = {};
2308
2308
  __export(database_exports, {
2309
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
2309
2310
  disposeDatabase: () => disposeDatabase,
2310
2311
  disposeTurso: () => disposeTurso,
2311
2312
  ensureSchema: () => ensureSchema,
@@ -2462,10 +2463,17 @@ async function ensureSchema() {
2462
2463
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2463
2464
  END;
2464
2465
 
2465
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
2466
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
2467
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
2466
2468
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2467
2469
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
2468
2470
  END;
2471
+
2472
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
2473
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
2474
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
2475
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2476
+ END;
2469
2477
  `);
2470
2478
  await client.executeMultiple(`
2471
2479
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2868,6 +2876,13 @@ async function ensureSchema() {
2868
2876
  });
2869
2877
  } catch {
2870
2878
  }
2879
+ try {
2880
+ await client.execute({
2881
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2882
+ args: []
2883
+ });
2884
+ } catch {
2885
+ }
2871
2886
  try {
2872
2887
  await client.execute({
2873
2888
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -3404,7 +3419,7 @@ async function disposeDatabase() {
3404
3419
  _resilientClient = null;
3405
3420
  }
3406
3421
  }
3407
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
3422
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3408
3423
  var init_database = __esm({
3409
3424
  "src/lib/database.ts"() {
3410
3425
  "use strict";
@@ -3418,6 +3433,7 @@ var init_database = __esm({
3418
3433
  _daemonClient = null;
3419
3434
  _adapterClient = null;
3420
3435
  initTurso = initDatabase;
3436
+ SOFT_DELETE_RETENTION_DAYS = 7;
3421
3437
  disposeTurso = disposeDatabase;
3422
3438
  }
3423
3439
  });
@@ -10271,9 +10287,10 @@ async function updateTask(input) {
10271
10287
  args: [assignedAgent]
10272
10288
  });
10273
10289
  } else if (input.status === "cancelled") {
10290
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
10274
10291
  await draftClient.execute({
10275
- sql: `DELETE FROM memories WHERE agent_id = ? AND draft = 1`,
10276
- args: [assignedAgent]
10292
+ sql: `UPDATE memories SET status = 'deleted', deleted_at = ? WHERE agent_id = ? AND draft = 1`,
10293
+ args: [now2, assignedAgent]
10277
10294
  });
10278
10295
  }
10279
10296
  } catch {
@@ -1691,6 +1691,7 @@ var init_db_daemon_client = __esm({
1691
1691
  // src/lib/database.ts
1692
1692
  var database_exports = {};
1693
1693
  __export(database_exports, {
1694
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1694
1695
  disposeDatabase: () => disposeDatabase,
1695
1696
  disposeTurso: () => disposeTurso,
1696
1697
  ensureSchema: () => ensureSchema,
@@ -1847,10 +1848,17 @@ async function ensureSchema() {
1847
1848
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1848
1849
  END;
1849
1850
 
1850
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
1851
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
1852
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
1851
1853
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1852
1854
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
1853
1855
  END;
1856
+
1857
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
1858
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
1859
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
1860
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1861
+ END;
1854
1862
  `);
1855
1863
  await client.executeMultiple(`
1856
1864
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2253,6 +2261,13 @@ async function ensureSchema() {
2253
2261
  });
2254
2262
  } catch {
2255
2263
  }
2264
+ try {
2265
+ await client.execute({
2266
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2267
+ args: []
2268
+ });
2269
+ } catch {
2270
+ }
2256
2271
  try {
2257
2272
  await client.execute({
2258
2273
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -2789,7 +2804,7 @@ async function disposeDatabase() {
2789
2804
  _resilientClient = null;
2790
2805
  }
2791
2806
  }
2792
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2807
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2793
2808
  var init_database = __esm({
2794
2809
  "src/lib/database.ts"() {
2795
2810
  "use strict";
@@ -2803,6 +2818,7 @@ var init_database = __esm({
2803
2818
  _daemonClient = null;
2804
2819
  _adapterClient = null;
2805
2820
  initTurso = initDatabase;
2821
+ SOFT_DELETE_RETENTION_DAYS = 7;
2806
2822
  disposeTurso = disposeDatabase;
2807
2823
  }
2808
2824
  });
@@ -1661,6 +1661,7 @@ var init_db_daemon_client = __esm({
1661
1661
  // src/lib/database.ts
1662
1662
  var database_exports = {};
1663
1663
  __export(database_exports, {
1664
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1664
1665
  disposeDatabase: () => disposeDatabase,
1665
1666
  disposeTurso: () => disposeTurso,
1666
1667
  ensureSchema: () => ensureSchema,
@@ -1817,10 +1818,17 @@ async function ensureSchema() {
1817
1818
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1818
1819
  END;
1819
1820
 
1820
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
1821
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
1822
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
1821
1823
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1822
1824
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
1823
1825
  END;
1826
+
1827
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
1828
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
1829
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
1830
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1831
+ END;
1824
1832
  `);
1825
1833
  await client.executeMultiple(`
1826
1834
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2223,6 +2231,13 @@ async function ensureSchema() {
2223
2231
  });
2224
2232
  } catch {
2225
2233
  }
2234
+ try {
2235
+ await client.execute({
2236
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2237
+ args: []
2238
+ });
2239
+ } catch {
2240
+ }
2226
2241
  try {
2227
2242
  await client.execute({
2228
2243
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -2759,7 +2774,7 @@ async function disposeDatabase() {
2759
2774
  _resilientClient = null;
2760
2775
  }
2761
2776
  }
2762
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2777
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2763
2778
  var init_database = __esm({
2764
2779
  "src/lib/database.ts"() {
2765
2780
  "use strict";
@@ -2773,6 +2788,7 @@ var init_database = __esm({
2773
2788
  _daemonClient = null;
2774
2789
  _adapterClient = null;
2775
2790
  initTurso = initDatabase;
2791
+ SOFT_DELETE_RETENTION_DAYS = 7;
2776
2792
  disposeTurso = disposeDatabase;
2777
2793
  }
2778
2794
  });
@@ -1780,6 +1780,7 @@ var init_db_daemon_client = __esm({
1780
1780
  // src/lib/database.ts
1781
1781
  var database_exports = {};
1782
1782
  __export(database_exports, {
1783
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1783
1784
  disposeDatabase: () => disposeDatabase,
1784
1785
  disposeTurso: () => disposeTurso,
1785
1786
  ensureSchema: () => ensureSchema,
@@ -1936,10 +1937,17 @@ async function ensureSchema() {
1936
1937
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1937
1938
  END;
1938
1939
 
1939
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
1940
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
1941
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
1940
1942
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1941
1943
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
1942
1944
  END;
1945
+
1946
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
1947
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
1948
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
1949
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
1950
+ END;
1943
1951
  `);
1944
1952
  await client.executeMultiple(`
1945
1953
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2342,6 +2350,13 @@ async function ensureSchema() {
2342
2350
  });
2343
2351
  } catch {
2344
2352
  }
2353
+ try {
2354
+ await client.execute({
2355
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2356
+ args: []
2357
+ });
2358
+ } catch {
2359
+ }
2345
2360
  try {
2346
2361
  await client.execute({
2347
2362
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -2878,7 +2893,7 @@ async function disposeDatabase() {
2878
2893
  _resilientClient = null;
2879
2894
  }
2880
2895
  }
2881
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
2896
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
2882
2897
  var init_database = __esm({
2883
2898
  "src/lib/database.ts"() {
2884
2899
  "use strict";
@@ -2892,6 +2907,7 @@ var init_database = __esm({
2892
2907
  _daemonClient = null;
2893
2908
  _adapterClient = null;
2894
2909
  initTurso = initDatabase;
2910
+ SOFT_DELETE_RETENTION_DAYS = 7;
2895
2911
  disposeTurso = disposeDatabase;
2896
2912
  }
2897
2913
  });
@@ -4152,6 +4168,19 @@ var init_session_key = __esm({
4152
4168
  }
4153
4169
  });
4154
4170
 
4171
+ // src/mcp/agent-context.ts
4172
+ import { AsyncLocalStorage } from "async_hooks";
4173
+ function getAgentContext() {
4174
+ return agentStore.getStore();
4175
+ }
4176
+ var agentStore;
4177
+ var init_agent_context = __esm({
4178
+ "src/mcp/agent-context.ts"() {
4179
+ "use strict";
4180
+ agentStore = new AsyncLocalStorage();
4181
+ }
4182
+ });
4183
+
4155
4184
  // src/lib/active-agent.ts
4156
4185
  var active_agent_exports = {};
4157
4186
  __export(active_agent_exports, {
@@ -4227,6 +4256,8 @@ function clearActiveAgent() {
4227
4256
  }
4228
4257
  }
4229
4258
  function getActiveAgent() {
4259
+ const httpCtx = getAgentContext();
4260
+ if (httpCtx) return httpCtx;
4230
4261
  try {
4231
4262
  const markerPath = getMarkerPath();
4232
4263
  const raw = readFileSync6(markerPath, "utf8");
@@ -4321,6 +4352,7 @@ var init_active_agent = __esm({
4321
4352
  "use strict";
4322
4353
  init_config();
4323
4354
  init_session_key();
4355
+ init_agent_context();
4324
4356
  init_employees();
4325
4357
  CACHE_DIR = path10.join(EXE_AI_DIR, "session-cache");
4326
4358
  STALE_MS = 24 * 60 * 60 * 1e3;
@@ -1915,6 +1915,7 @@ var init_db_daemon_client = __esm({
1915
1915
  // src/lib/database.ts
1916
1916
  var database_exports = {};
1917
1917
  __export(database_exports, {
1918
+ SOFT_DELETE_RETENTION_DAYS: () => SOFT_DELETE_RETENTION_DAYS,
1918
1919
  disposeDatabase: () => disposeDatabase,
1919
1920
  disposeTurso: () => disposeTurso,
1920
1921
  ensureSchema: () => ensureSchema,
@@ -2071,10 +2072,17 @@ async function ensureSchema() {
2071
2072
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2072
2073
  END;
2073
2074
 
2074
- CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories BEGIN
2075
+ CREATE TRIGGER IF NOT EXISTS memories_fts_au AFTER UPDATE ON memories
2076
+ WHEN new.status IS NULL OR new.status != 'deleted' BEGIN
2075
2077
  INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2076
2078
  INSERT INTO memories_fts(rowid, raw_text) VALUES (new.rowid, new.raw_text);
2077
2079
  END;
2080
+
2081
+ -- Soft-delete trigger: remove from FTS when status changes to 'deleted'
2082
+ CREATE TRIGGER IF NOT EXISTS memories_fts_soft_delete AFTER UPDATE ON memories
2083
+ WHEN new.status = 'deleted' AND (old.status IS NULL OR old.status != 'deleted') BEGIN
2084
+ INSERT INTO memories_fts(memories_fts, rowid, raw_text) VALUES('delete', old.rowid, old.raw_text);
2085
+ END;
2078
2086
  `);
2079
2087
  await client.executeMultiple(`
2080
2088
  CREATE TABLE IF NOT EXISTS sync_meta (
@@ -2477,6 +2485,13 @@ async function ensureSchema() {
2477
2485
  });
2478
2486
  } catch {
2479
2487
  }
2488
+ try {
2489
+ await client.execute({
2490
+ sql: `ALTER TABLE memories ADD COLUMN deleted_at TEXT`,
2491
+ args: []
2492
+ });
2493
+ } catch {
2494
+ }
2480
2495
  try {
2481
2496
  await client.execute({
2482
2497
  sql: `ALTER TABLE memories ADD COLUMN confidence REAL DEFAULT 0.7`,
@@ -3013,7 +3028,7 @@ async function disposeDatabase() {
3013
3028
  _resilientClient = null;
3014
3029
  }
3015
3030
  }
3016
- var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, disposeTurso;
3031
+ var _client, _resilientClient, _walCheckpointTimer, _daemonClient, _adapterClient, initTurso, SOFT_DELETE_RETENTION_DAYS, disposeTurso;
3017
3032
  var init_database = __esm({
3018
3033
  "src/lib/database.ts"() {
3019
3034
  "use strict";
@@ -3027,6 +3042,7 @@ var init_database = __esm({
3027
3042
  _daemonClient = null;
3028
3043
  _adapterClient = null;
3029
3044
  initTurso = initDatabase;
3045
+ SOFT_DELETE_RETENTION_DAYS = 7;
3030
3046
  disposeTurso = disposeDatabase;
3031
3047
  }
3032
3048
  });
@@ -3449,7 +3465,7 @@ __export(cloud_sync_exports, {
3449
3465
  pushToPostgres: () => pushToPostgres,
3450
3466
  recordRosterDeletion: () => recordRosterDeletion
3451
3467
  });
3452
- 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 } from "fs";
3468
+ 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 statSync3 } from "fs";
3453
3469
  import crypto3 from "crypto";
3454
3470
  import path10 from "path";
3455
3471
  import { homedir as homedir2 } from "os";
@@ -3939,10 +3955,9 @@ async function cloudSync(config) {
3939
3955
  const totalMemories = await countRows("SELECT COUNT(*) as cnt FROM memories WHERE status = 'active' OR status IS NULL");
3940
3956
  try {
3941
3957
  const { getLatestBackup: getLatestBackup2 } = await Promise.resolve().then(() => (init_db_backup(), db_backup_exports));
3942
- const { statSync: statFile } = await import("fs");
3943
3958
  const latestBackup = getLatestBackup2();
3944
3959
  if (latestBackup) {
3945
- const backupSize = statFile(latestBackup).size;
3960
+ const backupSize = statSync3(latestBackup).size;
3946
3961
  const MAX_CLOUD_BACKUP_BYTES = 50 * 1024 * 1024;
3947
3962
  if (backupSize <= MAX_CLOUD_BACKUP_BYTES) {
3948
3963
  const backupData = readFileSync7(latestBackup);