@askexenow/exe-os 0.9.93 → 0.9.94

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 (88) hide show
  1. package/deploy/compose/docker-compose.yml +1 -0
  2. package/dist/bin/agentic-ontology-backfill.js +65 -8
  3. package/dist/bin/agentic-reflection-backfill.js +54 -3
  4. package/dist/bin/agentic-semantic-label.js +54 -3
  5. package/dist/bin/backfill-conversations.js +69 -9
  6. package/dist/bin/backfill-responses.js +69 -9
  7. package/dist/bin/backfill-vectors.js +54 -3
  8. package/dist/bin/bulk-sync-postgres.js +66 -8
  9. package/dist/bin/cleanup-stale-review-tasks.js +118 -13
  10. package/dist/bin/cli.js +1558 -466
  11. package/dist/bin/customer-readiness.js +51 -0
  12. package/dist/bin/exe-agent.js +17 -3
  13. package/dist/bin/exe-assign.js +75 -9
  14. package/dist/bin/exe-boot.js +111 -12
  15. package/dist/bin/exe-call.js +17 -3
  16. package/dist/bin/exe-cloud.js +76 -10
  17. package/dist/bin/exe-dispatch.js +133 -18
  18. package/dist/bin/exe-doctor.js +75 -9
  19. package/dist/bin/exe-export-behaviors.js +75 -9
  20. package/dist/bin/exe-forget.js +94 -9
  21. package/dist/bin/exe-gateway.js +132 -18
  22. package/dist/bin/exe-heartbeat.js +118 -13
  23. package/dist/bin/exe-kill.js +75 -9
  24. package/dist/bin/exe-launch-agent.js +75 -9
  25. package/dist/bin/exe-new-employee.js +18 -4
  26. package/dist/bin/exe-pending-messages.js +118 -13
  27. package/dist/bin/exe-pending-notifications.js +118 -13
  28. package/dist/bin/exe-pending-reviews.js +118 -13
  29. package/dist/bin/exe-rename.js +75 -9
  30. package/dist/bin/exe-review.js +75 -9
  31. package/dist/bin/exe-search.js +100 -9
  32. package/dist/bin/exe-session-cleanup.js +133 -18
  33. package/dist/bin/exe-settings.js +1 -0
  34. package/dist/bin/exe-start-codex.js +65 -8
  35. package/dist/bin/exe-start-opencode.js +65 -8
  36. package/dist/bin/exe-status.js +118 -13
  37. package/dist/bin/exe-support.js +1 -0
  38. package/dist/bin/exe-team.js +75 -9
  39. package/dist/bin/git-sweep.js +133 -18
  40. package/dist/bin/graph-backfill.js +65 -8
  41. package/dist/bin/graph-export.js +75 -9
  42. package/dist/bin/intercom-check.js +133 -18
  43. package/dist/bin/scan-tasks.js +133 -18
  44. package/dist/bin/setup.js +55 -4
  45. package/dist/bin/shard-migrate.js +65 -8
  46. package/dist/bin/stack-update.js +5 -6
  47. package/dist/bin/update.js +1 -1
  48. package/dist/gateway/index.js +133 -18
  49. package/dist/hooks/bug-report-worker.js +133 -18
  50. package/dist/hooks/codex-stop-task-finalizer.js +123 -14
  51. package/dist/hooks/commit-complete.js +133 -18
  52. package/dist/hooks/error-recall.js +100 -9
  53. package/dist/hooks/ingest.js +75 -9
  54. package/dist/hooks/instructions-loaded.js +75 -9
  55. package/dist/hooks/notification.js +75 -9
  56. package/dist/hooks/post-compact.js +310 -50
  57. package/dist/hooks/post-tool-combined.js +433 -13
  58. package/dist/hooks/pre-compact.js +133 -18
  59. package/dist/hooks/pre-tool-use.js +118 -13
  60. package/dist/hooks/prompt-submit.js +191 -19
  61. package/dist/hooks/session-end.js +133 -18
  62. package/dist/hooks/session-start.js +143 -13
  63. package/dist/hooks/stop.js +118 -13
  64. package/dist/hooks/subagent-stop.js +118 -13
  65. package/dist/hooks/summary-worker.js +96 -7
  66. package/dist/index.js +133 -18
  67. package/dist/lib/cloud-sync.js +38 -0
  68. package/dist/lib/consolidation.js +3 -1
  69. package/dist/lib/database.js +37 -0
  70. package/dist/lib/db.js +37 -0
  71. package/dist/lib/device-registry.js +37 -0
  72. package/dist/lib/employee-templates.js +17 -3
  73. package/dist/lib/exe-daemon.js +913 -42
  74. package/dist/lib/hybrid-search.js +100 -9
  75. package/dist/lib/license.js +1 -1
  76. package/dist/lib/messaging.js +40 -4
  77. package/dist/lib/schedules.js +54 -3
  78. package/dist/lib/store.js +75 -9
  79. package/dist/lib/tasks.js +58 -9
  80. package/dist/lib/tmux-routing.js +58 -9
  81. package/dist/mcp/server.js +875 -42
  82. package/dist/mcp/tools/create-task.js +67 -12
  83. package/dist/mcp/tools/list-tasks.js +46 -5
  84. package/dist/mcp/tools/send-message.js +40 -4
  85. package/dist/mcp/tools/update-task.js +58 -9
  86. package/dist/runtime/index.js +133 -18
  87. package/dist/tui/App.js +132 -18
  88. package/package.json +1 -1
package/dist/lib/tasks.js CHANGED
@@ -961,7 +961,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
961
961
  import os6 from "os";
962
962
  import path7 from "path";
963
963
  import { jwtVerify, importSPKI } from "jose";
964
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
964
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, PLAN_LIMITS;
965
965
  var init_license = __esm({
966
966
  "src/lib/license.ts"() {
967
967
  "use strict";
@@ -969,6 +969,7 @@ var init_license = __esm({
969
969
  LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
970
970
  CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
971
971
  DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
972
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
972
973
  PLAN_LIMITS = {
973
974
  free: { devices: 1, employees: 1, memories: 5e3 },
974
975
  pro: { devices: 3, employees: 5, memories: 1e5 },
@@ -1978,6 +1979,7 @@ function resolveExeSession() {
1978
1979
  const mySession = getMySession();
1979
1980
  if (!mySession) return null;
1980
1981
  const fromSessionName = extractRootExe(mySession);
1982
+ let candidate = null;
1981
1983
  try {
1982
1984
  const key = getSessionKey();
1983
1985
  const parentExe = getParentExe(key);
@@ -1988,13 +1990,47 @@ function resolveExeSession() {
1988
1990
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
1989
1991
  `
1990
1992
  );
1991
- return fromSessionName;
1993
+ candidate = fromSessionName;
1994
+ } else {
1995
+ candidate = fromCache;
1992
1996
  }
1993
- return fromCache;
1994
1997
  }
1995
1998
  } catch {
1996
1999
  }
1997
- return fromSessionName ?? mySession;
2000
+ if (!candidate) {
2001
+ candidate = fromSessionName ?? mySession;
2002
+ }
2003
+ if (candidate && isRootSession(candidate)) {
2004
+ try {
2005
+ const transport = getTransport();
2006
+ const liveSessions = transport.listSessions();
2007
+ if (!liveSessions.includes(candidate)) {
2008
+ const liveRoots = liveSessions.filter((s) => isRootSession(s));
2009
+ if (liveRoots.length === 1) {
2010
+ process.stderr.write(
2011
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
2012
+ `
2013
+ );
2014
+ return liveRoots[0];
2015
+ } else if (liveRoots.length > 1) {
2016
+ const base = candidate.replace(/\d+$/, "");
2017
+ const match = liveRoots.find((s) => s.startsWith(base));
2018
+ const chosen = match ?? liveRoots[0];
2019
+ process.stderr.write(
2020
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
2021
+ `
2022
+ );
2023
+ return chosen;
2024
+ }
2025
+ process.stderr.write(
2026
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
2027
+ `
2028
+ );
2029
+ }
2030
+ } catch {
2031
+ }
2032
+ }
2033
+ return candidate;
1998
2034
  }
1999
2035
  function isEmployeeAlive(sessionName) {
2000
2036
  return getTransport().isAlive(sessionName);
@@ -2396,7 +2432,12 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
2396
2432
  }
2397
2433
  const spawnCwd = opts?.cwd ?? projectDir;
2398
2434
  const useExeAgent = !!(opts?.model && opts?.provider);
2399
- const agentRtConfig = getAgentRuntime(employeeName);
2435
+ const baseRtConfig = getAgentRuntime(employeeName);
2436
+ const agentRtConfig = {
2437
+ ...baseRtConfig,
2438
+ ...opts?.runtimeOverride ? { runtime: opts.runtimeOverride } : {},
2439
+ ...opts?.modelOverride ? { model: opts.modelOverride } : {}
2440
+ };
2400
2441
  const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
2401
2442
  const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
2402
2443
  const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();
@@ -3034,8 +3075,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
3034
3075
  const complexity = input.complexity ?? "standard";
3035
3076
  const sessionScope = earlySessionScope;
3036
3077
  await client.execute({
3037
- sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, created_at, updated_at)
3038
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3078
+ sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, spawn_runtime, spawn_model, created_at, updated_at)
3079
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
3039
3080
  args: [
3040
3081
  id,
3041
3082
  input.title,
@@ -3055,6 +3096,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
3055
3096
  0,
3056
3097
  null,
3057
3098
  sessionScope,
3099
+ input.spawnRuntime ?? null,
3100
+ input.spawnModel ?? null,
3058
3101
  now,
3059
3102
  now
3060
3103
  ]
@@ -3111,7 +3154,9 @@ ${input.context}
3111
3154
  budgetTokens: input.budgetTokens ?? null,
3112
3155
  budgetFallbackModel: input.budgetFallbackModel ?? null,
3113
3156
  tokensUsed: 0,
3114
- tokensWarnedAt: null
3157
+ tokensWarnedAt: null,
3158
+ spawnRuntime: input.spawnRuntime ?? null,
3159
+ spawnModel: input.spawnModel ?? null
3115
3160
  };
3116
3161
  }
3117
3162
  async function listTasks(input) {
@@ -3161,7 +3206,9 @@ async function listTasks(input) {
3161
3206
  budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
3162
3207
  budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
3163
3208
  tokensUsed: Number(r.tokens_used ?? 0),
3164
- tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
3209
+ tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null,
3210
+ spawnRuntime: r.spawn_runtime !== null && r.spawn_runtime !== void 0 ? String(r.spawn_runtime) : null,
3211
+ spawnModel: r.spawn_model !== null && r.spawn_model !== void 0 ? String(r.spawn_model) : null
3165
3212
  }));
3166
3213
  }
3167
3214
  function isTmuxSessionAlive(identifier) {
@@ -4628,6 +4675,8 @@ async function updateTask(input) {
4628
4675
  budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
4629
4676
  tokensUsed: Number(row.tokens_used ?? 0),
4630
4677
  tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
4678
+ spawnRuntime: row.spawn_runtime !== void 0 && row.spawn_runtime !== null ? String(row.spawn_runtime) : null,
4679
+ spawnModel: row.spawn_model !== void 0 && row.spawn_model !== null ? String(row.spawn_model) : null,
4631
4680
  nextTask
4632
4681
  };
4633
4682
  }
@@ -961,7 +961,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
961
961
  import os6 from "os";
962
962
  import path7 from "path";
963
963
  import { jwtVerify, importSPKI } from "jose";
964
- var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, PLAN_LIMITS;
964
+ var LICENSE_PATH, CACHE_PATH, DEVICE_ID_PATH, API_BASE, PLAN_LIMITS;
965
965
  var init_license = __esm({
966
966
  "src/lib/license.ts"() {
967
967
  "use strict";
@@ -969,6 +969,7 @@ var init_license = __esm({
969
969
  LICENSE_PATH = path7.join(EXE_AI_DIR, "license.key");
970
970
  CACHE_PATH = path7.join(EXE_AI_DIR, "license-cache.json");
971
971
  DEVICE_ID_PATH = path7.join(EXE_AI_DIR, "device-id");
972
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
972
973
  PLAN_LIMITS = {
973
974
  free: { devices: 1, employees: 1, memories: 5e3 },
974
975
  pro: { devices: 3, employees: 5, memories: 1e5 },
@@ -1619,8 +1620,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
1619
1620
  const complexity = input.complexity ?? "standard";
1620
1621
  const sessionScope = earlySessionScope;
1621
1622
  await client.execute({
1622
- sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, created_at, updated_at)
1623
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1623
+ sql: `INSERT INTO tasks (id, title, assigned_to, assigned_by, project_name, priority, status, task_file, blocked_by, parent_task_id, reviewer, context, complexity, budget_tokens, budget_fallback_model, tokens_used, tokens_warned_at, session_scope, spawn_runtime, spawn_model, created_at, updated_at)
1624
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
1624
1625
  args: [
1625
1626
  id,
1626
1627
  input.title,
@@ -1640,6 +1641,8 @@ ${scopeMismatchWarning}` : scopeMismatchWarning;
1640
1641
  0,
1641
1642
  null,
1642
1643
  sessionScope,
1644
+ input.spawnRuntime ?? null,
1645
+ input.spawnModel ?? null,
1643
1646
  now,
1644
1647
  now
1645
1648
  ]
@@ -1696,7 +1699,9 @@ ${input.context}
1696
1699
  budgetTokens: input.budgetTokens ?? null,
1697
1700
  budgetFallbackModel: input.budgetFallbackModel ?? null,
1698
1701
  tokensUsed: 0,
1699
- tokensWarnedAt: null
1702
+ tokensWarnedAt: null,
1703
+ spawnRuntime: input.spawnRuntime ?? null,
1704
+ spawnModel: input.spawnModel ?? null
1700
1705
  };
1701
1706
  }
1702
1707
  async function listTasks(input) {
@@ -1746,7 +1751,9 @@ async function listTasks(input) {
1746
1751
  budgetTokens: r.budget_tokens !== null ? Number(r.budget_tokens) : null,
1747
1752
  budgetFallbackModel: r.budget_fallback_model !== null ? String(r.budget_fallback_model) : null,
1748
1753
  tokensUsed: Number(r.tokens_used ?? 0),
1749
- tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null
1754
+ tokensWarnedAt: r.tokens_warned_at !== null ? Number(r.tokens_warned_at) : null,
1755
+ spawnRuntime: r.spawn_runtime !== null && r.spawn_runtime !== void 0 ? String(r.spawn_runtime) : null,
1756
+ spawnModel: r.spawn_model !== null && r.spawn_model !== void 0 ? String(r.spawn_model) : null
1750
1757
  }));
1751
1758
  }
1752
1759
  function isTmuxSessionAlive(identifier) {
@@ -3521,6 +3528,8 @@ async function updateTask(input) {
3521
3528
  budgetFallbackModel: row.budget_fallback_model !== void 0 && row.budget_fallback_model !== null ? String(row.budget_fallback_model) : null,
3522
3529
  tokensUsed: Number(row.tokens_used ?? 0),
3523
3530
  tokensWarnedAt: row.tokens_warned_at !== void 0 && row.tokens_warned_at !== null ? Number(row.tokens_warned_at) : null,
3531
+ spawnRuntime: row.spawn_runtime !== void 0 && row.spawn_runtime !== null ? String(row.spawn_runtime) : null,
3532
+ spawnModel: row.spawn_model !== void 0 && row.spawn_model !== null ? String(row.spawn_model) : null,
3524
3533
  nextTask
3525
3534
  };
3526
3535
  }
@@ -4016,6 +4025,7 @@ function resolveExeSession() {
4016
4025
  const mySession = getMySession();
4017
4026
  if (!mySession) return null;
4018
4027
  const fromSessionName = extractRootExe(mySession);
4028
+ let candidate = null;
4019
4029
  try {
4020
4030
  const key = getSessionKey();
4021
4031
  const parentExe = getParentExe(key);
@@ -4026,13 +4036,47 @@ function resolveExeSession() {
4026
4036
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
4027
4037
  `
4028
4038
  );
4029
- return fromSessionName;
4039
+ candidate = fromSessionName;
4040
+ } else {
4041
+ candidate = fromCache;
4030
4042
  }
4031
- return fromCache;
4032
4043
  }
4033
4044
  } catch {
4034
4045
  }
4035
- return fromSessionName ?? mySession;
4046
+ if (!candidate) {
4047
+ candidate = fromSessionName ?? mySession;
4048
+ }
4049
+ if (candidate && isRootSession(candidate)) {
4050
+ try {
4051
+ const transport = getTransport();
4052
+ const liveSessions = transport.listSessions();
4053
+ if (!liveSessions.includes(candidate)) {
4054
+ const liveRoots = liveSessions.filter((s) => isRootSession(s));
4055
+ if (liveRoots.length === 1) {
4056
+ process.stderr.write(
4057
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. Using live coordinator "${liveRoots[0]}".
4058
+ `
4059
+ );
4060
+ return liveRoots[0];
4061
+ } else if (liveRoots.length > 1) {
4062
+ const base = candidate.replace(/\d+$/, "");
4063
+ const match = liveRoots.find((s) => s.startsWith(base));
4064
+ const chosen = match ?? liveRoots[0];
4065
+ process.stderr.write(
4066
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead. ${liveRoots.length} live roots found, using "${chosen}".
4067
+ `
4068
+ );
4069
+ return chosen;
4070
+ }
4071
+ process.stderr.write(
4072
+ `[tmux-routing] WARN: resolved session "${candidate}" is dead and no live coordinator found.
4073
+ `
4074
+ );
4075
+ }
4076
+ } catch {
4077
+ }
4078
+ }
4079
+ return candidate;
4036
4080
  }
4037
4081
  function isEmployeeAlive(sessionName) {
4038
4082
  return getTransport().isAlive(sessionName);
@@ -4434,7 +4478,12 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
4434
4478
  }
4435
4479
  const spawnCwd = opts?.cwd ?? projectDir;
4436
4480
  const useExeAgent = !!(opts?.model && opts?.provider);
4437
- const agentRtConfig = getAgentRuntime(employeeName);
4481
+ const baseRtConfig = getAgentRuntime(employeeName);
4482
+ const agentRtConfig = {
4483
+ ...baseRtConfig,
4484
+ ...opts?.runtimeOverride ? { runtime: opts.runtimeOverride } : {},
4485
+ ...opts?.modelOverride ? { model: opts.modelOverride } : {}
4486
+ };
4438
4487
  const useCodex = !useExeAgent && agentRtConfig.runtime === "codex";
4439
4488
  const useOpencode = !useExeAgent && !useCodex && agentRtConfig.runtime === "opencode";
4440
4489
  const ccProvider = useExeAgent || useCodex || useOpencode ? DEFAULT_PROVIDER : detectActiveProvider();