@askexenow/exe-os 0.9.111 → 0.9.113

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/README.md +9 -7
  2. package/dist/bin/agentic-ontology-backfill.js +62 -12
  3. package/dist/bin/agentic-reflection-backfill.js +37 -2
  4. package/dist/bin/agentic-semantic-label.js +37 -2
  5. package/dist/bin/backfill-conversations.js +61 -11
  6. package/dist/bin/backfill-responses.js +62 -12
  7. package/dist/bin/backfill-vectors.js +37 -2
  8. package/dist/bin/bulk-sync-postgres.js +63 -13
  9. package/dist/bin/cleanup-stale-review-tasks.js +83 -16
  10. package/dist/bin/cli.js +312 -80
  11. package/dist/bin/exe-agent-config.js +7 -1
  12. package/dist/bin/exe-agent.js +29 -3
  13. package/dist/bin/exe-assign.js +62 -12
  14. package/dist/bin/exe-boot.js +500 -151
  15. package/dist/bin/exe-call.js +46 -5
  16. package/dist/bin/exe-cloud.js +101 -16
  17. package/dist/bin/exe-dispatch.js +827 -27
  18. package/dist/bin/exe-doctor.js +61 -11
  19. package/dist/bin/exe-export-behaviors.js +67 -14
  20. package/dist/bin/exe-forget.js +62 -12
  21. package/dist/bin/exe-gateway.js +147 -27
  22. package/dist/bin/exe-heartbeat.js +83 -16
  23. package/dist/bin/exe-kill.js +62 -12
  24. package/dist/bin/exe-launch-agent.js +83 -15
  25. package/dist/bin/exe-new-employee.js +176 -8
  26. package/dist/bin/exe-pending-messages.js +83 -16
  27. package/dist/bin/exe-pending-notifications.js +83 -16
  28. package/dist/bin/exe-pending-reviews.js +83 -16
  29. package/dist/bin/exe-rename.js +62 -12
  30. package/dist/bin/exe-review.js +62 -12
  31. package/dist/bin/exe-search.js +62 -12
  32. package/dist/bin/exe-session-cleanup.js +949 -149
  33. package/dist/bin/exe-settings.js +10 -4
  34. package/dist/bin/exe-start-codex.js +537 -248
  35. package/dist/bin/exe-start-opencode.js +547 -168
  36. package/dist/bin/exe-status.js +83 -16
  37. package/dist/bin/exe-support.js +1 -1
  38. package/dist/bin/exe-team.js +62 -12
  39. package/dist/bin/git-sweep.js +827 -27
  40. package/dist/bin/graph-backfill.js +62 -12
  41. package/dist/bin/graph-export.js +62 -12
  42. package/dist/bin/install.js +62 -4
  43. package/dist/bin/intercom-check.js +949 -149
  44. package/dist/bin/pre-publish.js +14 -2
  45. package/dist/bin/scan-tasks.js +827 -27
  46. package/dist/bin/setup.js +99 -14
  47. package/dist/bin/shard-migrate.js +62 -12
  48. package/dist/bin/stack-update.js +1 -1
  49. package/dist/bin/update.js +3 -3
  50. package/dist/gateway/index.js +586 -26
  51. package/dist/hooks/bug-report-worker.js +586 -26
  52. package/dist/hooks/codex-stop-task-finalizer.js +977 -143
  53. package/dist/hooks/commit-complete.js +827 -27
  54. package/dist/hooks/error-recall.js +62 -12
  55. package/dist/hooks/ingest.js +4579 -249
  56. package/dist/hooks/instructions-loaded.js +62 -12
  57. package/dist/hooks/notification.js +62 -12
  58. package/dist/hooks/post-compact.js +83 -16
  59. package/dist/hooks/post-tool-combined.js +83 -16
  60. package/dist/hooks/pre-compact.js +907 -107
  61. package/dist/hooks/pre-tool-use.js +98 -16
  62. package/dist/hooks/prompt-submit.js +596 -30
  63. package/dist/hooks/session-end.js +909 -112
  64. package/dist/hooks/session-start.js +112 -17
  65. package/dist/hooks/stop.js +82 -15
  66. package/dist/hooks/subagent-stop.js +83 -16
  67. package/dist/hooks/summary-worker.js +81 -8
  68. package/dist/index.js +595 -29
  69. package/dist/lib/agent-config.js +16 -1
  70. package/dist/lib/cloud-sync.js +45 -1
  71. package/dist/lib/consolidation.js +16 -1
  72. package/dist/lib/database.js +23 -0
  73. package/dist/lib/db.js +23 -0
  74. package/dist/lib/device-registry.js +23 -0
  75. package/dist/lib/employee-templates.js +30 -4
  76. package/dist/lib/employees.js +16 -1
  77. package/dist/lib/exe-daemon.js +482 -52
  78. package/dist/lib/hybrid-search.js +62 -12
  79. package/dist/lib/license.js +3 -3
  80. package/dist/lib/messaging.js +21 -4
  81. package/dist/lib/schedules.js +37 -2
  82. package/dist/lib/skill-learning.js +910 -41
  83. package/dist/lib/status-brief.js +14 -1
  84. package/dist/lib/store.js +62 -12
  85. package/dist/lib/tasks.js +843 -93
  86. package/dist/lib/tmux-routing.js +766 -16
  87. package/dist/mcp/server.js +238 -41
  88. package/dist/mcp/tools/create-task.js +525 -15
  89. package/dist/mcp/tools/deactivate-behavior.js +33 -24
  90. package/dist/mcp/tools/list-tasks.js +21 -4
  91. package/dist/mcp/tools/send-message.js +21 -4
  92. package/dist/mcp/tools/update-task.js +840 -93
  93. package/dist/runtime/index.js +913 -107
  94. package/dist/tui/App.js +227 -58
  95. package/package.json +1 -1
@@ -2097,6 +2097,13 @@ async function ensureSchema() {
2097
2097
  } catch (e) {
2098
2098
  logCatchDebug("migration", e);
2099
2099
  }
2100
+ for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
2101
+ try {
2102
+ await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
2103
+ } catch (e) {
2104
+ logCatchDebug("migration", e);
2105
+ }
2106
+ }
2100
2107
  try {
2101
2108
  await client.execute({
2102
2109
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
@@ -3313,6 +3320,22 @@ async function ensureSchema() {
3313
3320
  } catch (e) {
3314
3321
  logCatchDebug("migration", e);
3315
3322
  }
3323
+ try {
3324
+ await client.execute({
3325
+ sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
3326
+ args: []
3327
+ });
3328
+ } catch (e) {
3329
+ logCatchDebug("migration", e);
3330
+ }
3331
+ try {
3332
+ await client.execute({
3333
+ sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
3334
+ args: []
3335
+ });
3336
+ } catch (e) {
3337
+ logCatchDebug("migration", e);
3338
+ }
3316
3339
  }
3317
3340
  async function disposeDatabase() {
3318
3341
  if (_walCheckpointTimer) {
@@ -4430,11 +4453,17 @@ var init_platform_procedures = __esm({
4430
4453
  content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
4431
4454
  },
4432
4455
  {
4433
- title: "Customer orchestration maturity \u2014 recommend, never trap",
4456
+ title: "Orchestration phase guidance \u2014 recommend, never trap",
4434
4457
  domain: "workflow",
4435
4458
  priority: "p1",
4436
4459
  content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
4437
4460
  },
4461
+ {
4462
+ title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
4463
+ domain: "identity",
4464
+ priority: "p0",
4465
+ content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
4466
+ },
4438
4467
  {
4439
4468
  title: "Single dispatch path \u2014 create_task only",
4440
4469
  domain: "workflow",
@@ -4468,6 +4497,12 @@ var init_platform_procedures = __esm({
4468
4497
  priority: "p0",
4469
4498
  content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
4470
4499
  },
4500
+ {
4501
+ title: "Destructive operations \u2014 mandatory reviewer gate",
4502
+ domain: "security",
4503
+ priority: "p0",
4504
+ content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
4505
+ },
4471
4506
  {
4472
4507
  title: "Customer patch triage \u2014 upstream bug vs customization",
4473
4508
  domain: "support",
@@ -4619,7 +4654,7 @@ var init_platform_procedures = __esm({
4619
4654
  title: "MCP tool dispatch \u2014 all tools use action parameter",
4620
4655
  domain: "tool-use",
4621
4656
  priority: "p0",
4622
- content: 'exe-os MCP tools come in two surfaces depending on EXE_MCP_TOOL_SURFACE config. Consolidated (19 tools): action-based dispatch \u2014 memory(action="recall"), task(action="create"), etc. Legacy (108 tools): one tool per operation \u2014 recall_my_memory, create_task, etc. Both surfaces have identical functionality. Use whichever tool names are available in your session. If you see domain tools (memory, task, config, etc.), use the action parameter. If you see specific tools (recall_my_memory, create_task, etc.), call them directly.'
4657
+ content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
4623
4658
  },
4624
4659
  {
4625
4660
  title: "MCP tools \u2014 memory, decision, and search",
@@ -5393,7 +5428,7 @@ async function assertVpsLicense(opts) {
5393
5428
  }
5394
5429
  if (!transientFailure) {
5395
5430
  throw new Error(
5396
- "License validation failed: unknown backend state. Restore network connectivity to https://askexe.com/cloud and retry."
5431
+ "License validation failed: unknown backend state. Restore network connectivity to https://cloud.askexe.com and retry."
5397
5432
  );
5398
5433
  }
5399
5434
  const fresh = await getCachedLicense();
@@ -5430,7 +5465,7 @@ async function assertVpsLicense(opts) {
5430
5465
  } catch {
5431
5466
  }
5432
5467
  throw new Error(
5433
- `License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com/cloud and retry. This VPS image refuses to boot after the offline grace window.`
5468
+ `License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://cloud.askexe.com and retry. This VPS image refuses to boot after the offline grace window.`
5434
5469
  );
5435
5470
  }
5436
5471
  function startLicenseRevalidation(intervalMs = 36e5) {
@@ -5462,7 +5497,7 @@ var init_license = __esm({
5462
5497
  LICENSE_PATH = path11.join(EXE_AI_DIR, "license.key");
5463
5498
  CACHE_PATH = path11.join(EXE_AI_DIR, "license-cache.json");
5464
5499
  DEVICE_ID_PATH = path11.join(EXE_AI_DIR, "device-id");
5465
- API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
5500
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
5466
5501
  RETRY_DELAY_MS = 500;
5467
5502
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
5468
5503
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
@@ -5651,6 +5686,18 @@ function extractRootExe(name) {
5651
5686
  const parts = name.split("-").filter(Boolean);
5652
5687
  return parts.length > 0 ? parts[parts.length - 1] : null;
5653
5688
  }
5689
+ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
5690
+ if (!existsSync14(SESSION_CACHE)) {
5691
+ mkdirSync7(SESSION_CACHE, { recursive: true });
5692
+ }
5693
+ const rootExe = extractRootExe(parentExe) ?? parentExe;
5694
+ const filePath = path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
5695
+ writeFileSync6(filePath, JSON.stringify({
5696
+ parentExe: rootExe,
5697
+ dispatchedBy: dispatchedBy || rootExe,
5698
+ registeredAt: (/* @__PURE__ */ new Date()).toISOString()
5699
+ }));
5700
+ }
5654
5701
  function getParentExe(sessionKey) {
5655
5702
  try {
5656
5703
  const data = JSON.parse(readFileSync9(path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
@@ -5660,11 +5707,12 @@ function getParentExe(sessionKey) {
5660
5707
  }
5661
5708
  }
5662
5709
  function resolveExeSession() {
5710
+ if (process.env.EXE_SESSION_NAME) {
5711
+ const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
5712
+ if (fromEnv) return fromEnv;
5713
+ }
5663
5714
  const mySession = getMySession();
5664
5715
  if (!mySession) {
5665
- if (process.env.EXE_SESSION_NAME) {
5666
- return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
5667
- }
5668
5716
  return null;
5669
5717
  }
5670
5718
  const fromSessionName = extractRootExe(mySession);
@@ -5679,6 +5727,10 @@ function resolveExeSession() {
5679
5727
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
5680
5728
  `
5681
5729
  );
5730
+ try {
5731
+ registerParentExe(key, fromSessionName);
5732
+ } catch {
5733
+ }
5682
5734
  candidate = fromSessionName;
5683
5735
  } else {
5684
5736
  candidate = fromCache;
@@ -6844,6 +6896,27 @@ async function cloudSync(config) {
6844
6896
  if (stmts.length > 0) await client.batch(stmts, "write");
6845
6897
  pulled = pullResult.records.length;
6846
6898
  } else {
6899
+ try {
6900
+ const incomingIds = pullResult.records.map((r) => sqlSafe(r.id));
6901
+ if (incomingIds.length > 0) {
6902
+ const ph = incomingIds.map(() => "?").join(",");
6903
+ const existing = await client.execute({
6904
+ sql: `SELECT id, version, timestamp FROM memories WHERE id IN (${ph})`,
6905
+ args: incomingIds
6906
+ });
6907
+ const localMap = new Map(existing.rows.map((r) => [String(r.id), r]));
6908
+ for (const rec of pullResult.records) {
6909
+ const local = localMap.get(String(rec.id));
6910
+ if (local && Number(local.version) > 0 && Number(local.version) !== Number(rec.version ?? 0)) {
6911
+ process.stderr.write(
6912
+ `[cloud-sync] CONFLICT: memory ${String(rec.id).slice(0, 8)} \u2014 local v${local.version} vs remote v${rec.version ?? 0}. Remote wins (LWW).
6913
+ `
6914
+ );
6915
+ }
6916
+ }
6917
+ }
6918
+ } catch {
6919
+ }
6847
6920
  const stmts = pullResult.records.map((rec) => ({
6848
6921
  sql: `INSERT OR REPLACE INTO memories
6849
6922
  (id, agent_id, agent_role, session_id, timestamp,