@askexenow/exe-os 0.8.83 → 0.8.85

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 (95) hide show
  1. package/dist/bin/backfill-conversations.js +746 -595
  2. package/dist/bin/backfill-responses.js +745 -594
  3. package/dist/bin/backfill-vectors.js +312 -226
  4. package/dist/bin/cleanup-stale-review-tasks.js +97 -2
  5. package/dist/bin/cli.js +14350 -12518
  6. package/dist/bin/exe-agent.js +97 -88
  7. package/dist/bin/exe-assign.js +1003 -854
  8. package/dist/bin/exe-boot.js +1257 -320
  9. package/dist/bin/exe-call.js +10 -0
  10. package/dist/bin/exe-cloud.js +29 -6
  11. package/dist/bin/exe-dispatch.js +210 -34
  12. package/dist/bin/exe-doctor.js +403 -6
  13. package/dist/bin/exe-export-behaviors.js +175 -72
  14. package/dist/bin/exe-forget.js +97 -2
  15. package/dist/bin/exe-gateway.js +550 -171
  16. package/dist/bin/exe-healthcheck.js +1 -0
  17. package/dist/bin/exe-heartbeat.js +100 -5
  18. package/dist/bin/exe-kill.js +175 -72
  19. package/dist/bin/exe-launch-agent.js +189 -76
  20. package/dist/bin/exe-link.js +902 -80
  21. package/dist/bin/exe-new-employee.js +38 -8
  22. package/dist/bin/exe-pending-messages.js +96 -2
  23. package/dist/bin/exe-pending-notifications.js +97 -2
  24. package/dist/bin/exe-pending-reviews.js +98 -3
  25. package/dist/bin/exe-rename.js +564 -23
  26. package/dist/bin/exe-review.js +231 -73
  27. package/dist/bin/exe-search.js +989 -226
  28. package/dist/bin/exe-session-cleanup.js +4806 -1665
  29. package/dist/bin/exe-settings.js +20 -5
  30. package/dist/bin/exe-status.js +97 -2
  31. package/dist/bin/exe-team.js +97 -2
  32. package/dist/bin/git-sweep.js +899 -207
  33. package/dist/bin/graph-backfill.js +175 -72
  34. package/dist/bin/graph-export.js +175 -72
  35. package/dist/bin/install.js +38 -7
  36. package/dist/bin/list-providers.js +1 -0
  37. package/dist/bin/scan-tasks.js +904 -211
  38. package/dist/bin/setup.js +867 -268
  39. package/dist/bin/shard-migrate.js +175 -72
  40. package/dist/bin/update.js +1 -0
  41. package/dist/bin/wiki-sync.js +175 -72
  42. package/dist/gateway/index.js +548 -166
  43. package/dist/hooks/bug-report-worker.js +208 -23
  44. package/dist/hooks/commit-complete.js +897 -205
  45. package/dist/hooks/error-recall.js +988 -226
  46. package/dist/hooks/ingest-worker.js +1638 -1194
  47. package/dist/hooks/ingest.js +3 -0
  48. package/dist/hooks/instructions-loaded.js +707 -97
  49. package/dist/hooks/notification.js +699 -89
  50. package/dist/hooks/post-compact.js +714 -104
  51. package/dist/hooks/pre-compact.js +897 -205
  52. package/dist/hooks/pre-tool-use.js +742 -123
  53. package/dist/hooks/prompt-ingest-worker.js +242 -101
  54. package/dist/hooks/prompt-submit.js +995 -233
  55. package/dist/hooks/response-ingest-worker.js +242 -101
  56. package/dist/hooks/session-end.js +3941 -400
  57. package/dist/hooks/session-start.js +1001 -226
  58. package/dist/hooks/stop.js +725 -115
  59. package/dist/hooks/subagent-stop.js +714 -104
  60. package/dist/hooks/summary-worker.js +1964 -1330
  61. package/dist/index.js +1651 -1053
  62. package/dist/lib/cloud-sync.js +907 -86
  63. package/dist/lib/consolidation.js +2 -1
  64. package/dist/lib/database.js +642 -87
  65. package/dist/lib/db-daemon-client.js +503 -0
  66. package/dist/lib/device-registry.js +547 -7
  67. package/dist/lib/embedder.js +14 -28
  68. package/dist/lib/employee-templates.js +84 -74
  69. package/dist/lib/employees.js +9 -0
  70. package/dist/lib/exe-daemon-client.js +16 -29
  71. package/dist/lib/exe-daemon.js +1955 -922
  72. package/dist/lib/hybrid-search.js +988 -226
  73. package/dist/lib/identity.js +87 -67
  74. package/dist/lib/keychain.js +9 -1
  75. package/dist/lib/messaging.js +8 -1
  76. package/dist/lib/reminders.js +91 -74
  77. package/dist/lib/schedules.js +96 -2
  78. package/dist/lib/skill-learning.js +103 -85
  79. package/dist/lib/store.js +234 -73
  80. package/dist/lib/tasks.js +111 -22
  81. package/dist/lib/tmux-routing.js +120 -31
  82. package/dist/lib/token-spend.js +273 -0
  83. package/dist/lib/ws-client.js +11 -0
  84. package/dist/mcp/server.js +5222 -475
  85. package/dist/mcp/tools/complete-reminder.js +94 -77
  86. package/dist/mcp/tools/create-reminder.js +94 -77
  87. package/dist/mcp/tools/create-task.js +120 -22
  88. package/dist/mcp/tools/deactivate-behavior.js +95 -77
  89. package/dist/mcp/tools/list-reminders.js +94 -77
  90. package/dist/mcp/tools/list-tasks.js +31 -1
  91. package/dist/mcp/tools/send-message.js +8 -1
  92. package/dist/mcp/tools/update-task.js +39 -10
  93. package/dist/runtime/index.js +911 -219
  94. package/dist/tui/App.js +997 -295
  95. package/package.json +6 -1
@@ -260,6 +260,7 @@ __export(employees_exports, {
260
260
  DEFAULT_COORDINATOR_TEMPLATE_NAME: () => DEFAULT_COORDINATOR_TEMPLATE_NAME,
261
261
  EMPLOYEES_PATH: () => EMPLOYEES_PATH,
262
262
  addEmployee: () => addEmployee,
263
+ baseAgentName: () => baseAgentName,
263
264
  canCoordinate: () => canCoordinate,
264
265
  getCoordinatorEmployee: () => getCoordinatorEmployee,
265
266
  getCoordinatorName: () => getCoordinatorName,
@@ -356,6 +357,14 @@ function hasRole(agentName, role) {
356
357
  const emp = getEmployee(employees, agentName);
357
358
  return emp ? emp.role.toLowerCase() === role.toLowerCase() : false;
358
359
  }
360
+ function baseAgentName(name, employees) {
361
+ const match = name.match(/^([a-zA-Z]+)\d+$/);
362
+ if (!match) return name;
363
+ const base = match[1];
364
+ const roster = employees ?? loadEmployeesSync();
365
+ if (getEmployee(roster, base)) return base;
366
+ return name;
367
+ }
359
368
  function isMultiInstance(agentName, employees) {
360
369
  const roster = employees ?? loadEmployeesSync();
361
370
  const emp = getEmployee(roster, agentName);
@@ -472,6 +481,12 @@ function getClient() {
472
481
  if (!_resilientClient) {
473
482
  throw new Error("Database client not initialized. Call initDatabase() first.");
474
483
  }
484
+ if (process.env.EXE_IS_DAEMON === "1") {
485
+ return _resilientClient;
486
+ }
487
+ if (_daemonClient && _daemonClient._isDaemonActive()) {
488
+ return _daemonClient;
489
+ }
475
490
  return _resilientClient;
476
491
  }
477
492
  function getRawClient() {
@@ -960,6 +975,12 @@ async function ensureSchema() {
960
975
  } catch {
961
976
  }
962
977
  }
978
+ try {
979
+ await client.execute(
980
+ `CREATE INDEX IF NOT EXISTS idx_memories_content_hash ON memories(content_hash, agent_id)`
981
+ );
982
+ } catch {
983
+ }
963
984
  await client.executeMultiple(`
964
985
  CREATE TABLE IF NOT EXISTS entities (
965
986
  id TEXT PRIMARY KEY,
@@ -1012,7 +1033,30 @@ async function ensureSchema() {
1012
1033
  entity_id TEXT NOT NULL,
1013
1034
  PRIMARY KEY (hyperedge_id, entity_id)
1014
1035
  );
1036
+
1037
+ CREATE VIRTUAL TABLE IF NOT EXISTS entities_fts USING fts5(
1038
+ name,
1039
+ content=entities,
1040
+ content_rowid=rowid
1041
+ );
1042
+
1043
+ CREATE TRIGGER IF NOT EXISTS entities_fts_ai AFTER INSERT ON entities BEGIN
1044
+ INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
1045
+ END;
1046
+
1047
+ CREATE TRIGGER IF NOT EXISTS entities_fts_ad AFTER DELETE ON entities BEGIN
1048
+ INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
1049
+ END;
1050
+
1051
+ CREATE TRIGGER IF NOT EXISTS entities_fts_au AFTER UPDATE ON entities BEGIN
1052
+ INSERT INTO entities_fts(entities_fts, rowid, name) VALUES('delete', old.rowid, old.name);
1053
+ INSERT INTO entities_fts(rowid, name) VALUES (new.rowid, new.name);
1054
+ END;
1015
1055
  `);
1056
+ try {
1057
+ await client.execute("INSERT INTO entities_fts(entities_fts) VALUES('rebuild')");
1058
+ } catch {
1059
+ }
1016
1060
  await client.executeMultiple(`
1017
1061
  CREATE TABLE IF NOT EXISTS entity_aliases (
1018
1062
  alias TEXT NOT NULL PRIMARY KEY,
@@ -1193,6 +1237,33 @@ async function ensureSchema() {
1193
1237
  CREATE INDEX IF NOT EXISTS idx_conversations_channel
1194
1238
  ON conversations(channel_id);
1195
1239
  `);
1240
+ await client.executeMultiple(`
1241
+ CREATE TABLE IF NOT EXISTS session_agent_map (
1242
+ session_uuid TEXT PRIMARY KEY,
1243
+ agent_id TEXT NOT NULL,
1244
+ session_name TEXT,
1245
+ task_id TEXT,
1246
+ project_name TEXT,
1247
+ started_at TEXT NOT NULL
1248
+ );
1249
+
1250
+ CREATE INDEX IF NOT EXISTS idx_session_agent_map_agent
1251
+ ON session_agent_map(agent_id);
1252
+ `);
1253
+ try {
1254
+ const mapCount = await client.execute({ sql: `SELECT COUNT(*) as cnt FROM session_agent_map`, args: [] });
1255
+ if (Number(mapCount.rows[0]?.cnt ?? 0) === 0) {
1256
+ await client.execute({
1257
+ sql: `INSERT OR IGNORE INTO session_agent_map (session_uuid, agent_id, session_name, started_at)
1258
+ SELECT session_id, agent_id, '', MIN(timestamp)
1259
+ FROM memories
1260
+ WHERE session_id IS NOT NULL AND session_id != '' AND agent_id IS NOT NULL AND agent_id != ''
1261
+ GROUP BY session_id, agent_id`,
1262
+ args: []
1263
+ });
1264
+ }
1265
+ } catch {
1266
+ }
1196
1267
  try {
1197
1268
  await client.execute({
1198
1269
  sql: `ALTER TABLE tasks ADD COLUMN budget_tokens INTEGER`,
@@ -1326,15 +1397,41 @@ async function ensureSchema() {
1326
1397
  });
1327
1398
  } catch {
1328
1399
  }
1400
+ for (const col of [
1401
+ "ALTER TABLE memories ADD COLUMN intent TEXT",
1402
+ "ALTER TABLE memories ADD COLUMN outcome TEXT",
1403
+ "ALTER TABLE memories ADD COLUMN domain TEXT",
1404
+ "ALTER TABLE memories ADD COLUMN referenced_entities TEXT",
1405
+ "ALTER TABLE memories ADD COLUMN retrieval_count INTEGER DEFAULT 0",
1406
+ "ALTER TABLE memories ADD COLUMN chain_position TEXT",
1407
+ "ALTER TABLE memories ADD COLUMN review_status TEXT",
1408
+ "ALTER TABLE memories ADD COLUMN context_window_pct INTEGER",
1409
+ "ALTER TABLE memories ADD COLUMN file_paths TEXT",
1410
+ "ALTER TABLE memories ADD COLUMN commit_hash TEXT",
1411
+ "ALTER TABLE memories ADD COLUMN duration_ms INTEGER",
1412
+ "ALTER TABLE memories ADD COLUMN token_cost REAL",
1413
+ "ALTER TABLE memories ADD COLUMN audience TEXT",
1414
+ "ALTER TABLE memories ADD COLUMN language_type TEXT",
1415
+ "ALTER TABLE memories ADD COLUMN parent_memory_id TEXT"
1416
+ ]) {
1417
+ try {
1418
+ await client.execute(col);
1419
+ } catch {
1420
+ }
1421
+ }
1329
1422
  }
1330
1423
  async function disposeDatabase() {
1424
+ if (_daemonClient) {
1425
+ _daemonClient.close();
1426
+ _daemonClient = null;
1427
+ }
1331
1428
  if (_client) {
1332
1429
  _client.close();
1333
1430
  _client = null;
1334
1431
  _resilientClient = null;
1335
1432
  }
1336
1433
  }
1337
- var _client, _resilientClient, initTurso, disposeTurso;
1434
+ var _client, _resilientClient, _daemonClient, initTurso, disposeTurso;
1338
1435
  var init_database = __esm({
1339
1436
  "src/lib/database.ts"() {
1340
1437
  "use strict";
@@ -1342,6 +1439,7 @@ var init_database = __esm({
1342
1439
  init_employees();
1343
1440
  _client = null;
1344
1441
  _resilientClient = null;
1442
+ _daemonClient = null;
1345
1443
  initTurso = initDatabase;
1346
1444
  disposeTurso = disposeDatabase;
1347
1445
  }
@@ -2615,6 +2713,7 @@ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync
2615
2713
  import { spawnSync } from "child_process";
2616
2714
 
2617
2715
  // src/lib/store.ts
2716
+ import { createHash } from "crypto";
2618
2717
  init_database();
2619
2718
 
2620
2719
  // src/lib/keychain.ts
@@ -2650,12 +2749,20 @@ async function getMasterKey() {
2650
2749
  }
2651
2750
  const keyPath = getKeyPath();
2652
2751
  if (!existsSync3(keyPath)) {
2752
+ process.stderr.write(
2753
+ `[keychain] Key not found at ${keyPath} (HOME=${os3.homedir()}, EXE_OS_DIR=${process.env.EXE_OS_DIR ?? "unset"})
2754
+ `
2755
+ );
2653
2756
  return null;
2654
2757
  }
2655
2758
  try {
2656
2759
  const content = await readFile3(keyPath, "utf-8");
2657
2760
  return Buffer.from(content.trim(), "base64");
2658
- } catch {
2761
+ } catch (err) {
2762
+ process.stderr.write(
2763
+ `[keychain] Key read failed at ${keyPath}: ${err instanceof Error ? err.message : String(err)}
2764
+ `
2765
+ );
2659
2766
  return null;
2660
2767
  }
2661
2768
  }
@@ -2820,80 +2927,85 @@ async function flushBatch() {
2820
2927
  const draft = row.draft ? 1 : 0;
2821
2928
  const memoryType = row.memory_type ?? "raw";
2822
2929
  const trajectory = row.trajectory ?? null;
2823
- return {
2824
- sql: hasVector ? `INSERT OR IGNORE INTO memories
2825
- (id, agent_id, agent_role, session_id, timestamp,
2826
- tool_name, project_name,
2827
- has_error, raw_text, vector, version, task_id, importance, status,
2828
- confidence, last_accessed,
2829
- workspace_id, document_id, user_id, char_offset, page_number,
2830
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory)
2831
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories
2832
- (id, agent_id, agent_role, session_id, timestamp,
2930
+ const contentHash = row.content_hash ?? null;
2931
+ const intent = row.intent ?? null;
2932
+ const outcome = row.outcome ?? null;
2933
+ const domain = row.domain ?? null;
2934
+ const referencedEntities = row.referenced_entities ?? null;
2935
+ const retrievalCount = row.retrieval_count ?? 0;
2936
+ const chainPosition = row.chain_position ?? null;
2937
+ const reviewStatus = row.review_status ?? null;
2938
+ const contextWindowPct = row.context_window_pct ?? null;
2939
+ const filePaths = row.file_paths ?? null;
2940
+ const commitHash = row.commit_hash ?? null;
2941
+ const durationMs = row.duration_ms ?? null;
2942
+ const tokenCost = row.token_cost ?? null;
2943
+ const audience = row.audience ?? null;
2944
+ const languageType = row.language_type ?? null;
2945
+ const parentMemoryId = row.parent_memory_id ?? null;
2946
+ const cols = `id, agent_id, agent_role, session_id, timestamp,
2833
2947
  tool_name, project_name,
2834
2948
  has_error, raw_text, vector, version, task_id, importance, status,
2835
2949
  confidence, last_accessed,
2836
2950
  workspace_id, document_id, user_id, char_offset, page_number,
2837
- source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory)
2838
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
2839
- args: hasVector ? [
2840
- row.id,
2841
- row.agent_id,
2842
- row.agent_role,
2843
- row.session_id,
2844
- row.timestamp,
2845
- row.tool_name,
2846
- row.project_name,
2847
- row.has_error,
2848
- row.raw_text,
2849
- vectorToBlob(row.vector),
2850
- row.version,
2851
- taskId,
2852
- importance,
2853
- status,
2854
- confidence,
2855
- lastAccessed,
2856
- workspaceId,
2857
- documentId,
2858
- userId,
2859
- charOffset,
2860
- pageNumber,
2861
- sourcePath,
2862
- sourceType,
2863
- tier,
2864
- supersedesId,
2865
- draft,
2866
- memoryType,
2867
- trajectory
2868
- ] : [
2869
- row.id,
2870
- row.agent_id,
2871
- row.agent_role,
2872
- row.session_id,
2873
- row.timestamp,
2874
- row.tool_name,
2875
- row.project_name,
2876
- row.has_error,
2877
- row.raw_text,
2878
- row.version,
2879
- taskId,
2880
- importance,
2881
- status,
2882
- confidence,
2883
- lastAccessed,
2884
- workspaceId,
2885
- documentId,
2886
- userId,
2887
- charOffset,
2888
- pageNumber,
2889
- sourcePath,
2890
- sourceType,
2891
- tier,
2892
- supersedesId,
2893
- draft,
2894
- memoryType,
2895
- trajectory
2896
- ]
2951
+ source_path, source_type, tier, supersedes_id, draft, memory_type, trajectory, content_hash,
2952
+ intent, outcome, domain, referenced_entities, retrieval_count,
2953
+ chain_position, review_status, context_window_pct, file_paths, commit_hash,
2954
+ duration_ms, token_cost, audience, language_type, parent_memory_id`;
2955
+ const metaArgs = [
2956
+ intent,
2957
+ outcome,
2958
+ domain,
2959
+ referencedEntities,
2960
+ retrievalCount,
2961
+ chainPosition,
2962
+ reviewStatus,
2963
+ contextWindowPct,
2964
+ filePaths,
2965
+ commitHash,
2966
+ durationMs,
2967
+ tokenCost,
2968
+ audience,
2969
+ languageType,
2970
+ parentMemoryId
2971
+ ];
2972
+ const baseArgs = [
2973
+ row.id,
2974
+ row.agent_id,
2975
+ row.agent_role,
2976
+ row.session_id,
2977
+ row.timestamp,
2978
+ row.tool_name,
2979
+ row.project_name,
2980
+ row.has_error,
2981
+ row.raw_text
2982
+ ];
2983
+ const sharedArgs = [
2984
+ row.version,
2985
+ taskId,
2986
+ importance,
2987
+ status,
2988
+ confidence,
2989
+ lastAccessed,
2990
+ workspaceId,
2991
+ documentId,
2992
+ userId,
2993
+ charOffset,
2994
+ pageNumber,
2995
+ sourcePath,
2996
+ sourceType,
2997
+ tier,
2998
+ supersedesId,
2999
+ draft,
3000
+ memoryType,
3001
+ trajectory,
3002
+ contentHash
3003
+ ];
3004
+ return {
3005
+ sql: hasVector ? `INSERT OR IGNORE INTO memories (${cols})
3006
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, vector32(?), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` : `INSERT OR IGNORE INTO memories (${cols})
3007
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3008
+ args: hasVector ? [...baseArgs, vectorToBlob(row.vector), ...sharedArgs, ...metaArgs] : [...baseArgs, ...sharedArgs, ...metaArgs]
2897
3009
  };
2898
3010
  };
2899
3011
  const globalClient = getClient();
@@ -3395,7 +3507,7 @@ async function main() {
3395
3507
  try {
3396
3508
  mkdirSync4(ccAgentDir, { recursive: true });
3397
3509
  let content = readFileSync4(sourceFile, "utf-8");
3398
- content = content.replace(/\$\{agent_id\}/g, agent);
3510
+ content = content.replace(/\$\{agent_id\}/g, baseAgentName(agent));
3399
3511
  writeFileSync4(ccAgentFile, content, "utf-8");
3400
3512
  process.stderr.write(
3401
3513
  `[exe-launch-agent] auto-provisioned ${ccAgentFile} from ${sourceFile}
@@ -3407,7 +3519,8 @@ async function main() {
3407
3519
  }
3408
3520
  }
3409
3521
  const plan = buildLaunchPlan(agent, behaviorsPath, passthrough, hasAgentFlag, provider);
3410
- process.env.AGENT_ID = agent;
3522
+ const memoryAgent = baseAgentName(agent);
3523
+ process.env.AGENT_ID = memoryAgent;
3411
3524
  const empRole = (() => {
3412
3525
  try {
3413
3526
  const emps = __require("fs").readFileSync(
@@ -3415,7 +3528,7 @@ async function main() {
3415
3528
  "utf-8"
3416
3529
  );
3417
3530
  const found = JSON.parse(emps).find(
3418
- (e) => e.name.toLowerCase() === agent.toLowerCase()
3531
+ (e) => e.name.toLowerCase() === memoryAgent.toLowerCase()
3419
3532
  );
3420
3533
  return found?.role ?? "employee";
3421
3534
  } catch {
@@ -3425,7 +3538,7 @@ async function main() {
3425
3538
  process.env.AGENT_ROLE = empRole;
3426
3539
  try {
3427
3540
  const { writeActiveAgent: writeActiveAgent2 } = await Promise.resolve().then(() => (init_active_agent(), active_agent_exports));
3428
- writeActiveAgent2(agent, empRole);
3541
+ writeActiveAgent2(memoryAgent, empRole);
3429
3542
  } catch {
3430
3543
  }
3431
3544
  if (!process.env.CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING) {