@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
@@ -2279,6 +2279,13 @@ async function ensureSchema() {
2279
2279
  } catch (e) {
2280
2280
  logCatchDebug("migration", e);
2281
2281
  }
2282
+ for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
2283
+ try {
2284
+ await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
2285
+ } catch (e) {
2286
+ logCatchDebug("migration", e);
2287
+ }
2288
+ }
2282
2289
  try {
2283
2290
  await client.execute({
2284
2291
  sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
@@ -3495,6 +3502,22 @@ async function ensureSchema() {
3495
3502
  } catch (e) {
3496
3503
  logCatchDebug("migration", e);
3497
3504
  }
3505
+ try {
3506
+ await client.execute({
3507
+ sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
3508
+ args: []
3509
+ });
3510
+ } catch (e) {
3511
+ logCatchDebug("migration", e);
3512
+ }
3513
+ try {
3514
+ await client.execute({
3515
+ sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
3516
+ args: []
3517
+ });
3518
+ } catch (e) {
3519
+ logCatchDebug("migration", e);
3520
+ }
3498
3521
  }
3499
3522
  async function disposeDatabase() {
3500
3523
  if (_walCheckpointTimer) {
@@ -4618,11 +4641,17 @@ var init_platform_procedures = __esm({
4618
4641
  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."
4619
4642
  },
4620
4643
  {
4621
- title: "Customer orchestration maturity \u2014 recommend, never trap",
4644
+ title: "Orchestration phase guidance \u2014 recommend, never trap",
4622
4645
  domain: "workflow",
4623
4646
  priority: "p1",
4624
4647
  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."
4625
4648
  },
4649
+ {
4650
+ title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
4651
+ domain: "identity",
4652
+ priority: "p0",
4653
+ 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."
4654
+ },
4626
4655
  {
4627
4656
  title: "Single dispatch path \u2014 create_task only",
4628
4657
  domain: "workflow",
@@ -4656,6 +4685,12 @@ var init_platform_procedures = __esm({
4656
4685
  priority: "p0",
4657
4686
  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."
4658
4687
  },
4688
+ {
4689
+ title: "Destructive operations \u2014 mandatory reviewer gate",
4690
+ domain: "security",
4691
+ priority: "p0",
4692
+ 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."
4693
+ },
4659
4694
  {
4660
4695
  title: "Customer patch triage \u2014 upstream bug vs customization",
4661
4696
  domain: "support",
@@ -4807,7 +4842,7 @@ var init_platform_procedures = __esm({
4807
4842
  title: "MCP tool dispatch \u2014 all tools use action parameter",
4808
4843
  domain: "tool-use",
4809
4844
  priority: "p0",
4810
- 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.'
4845
+ 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.'
4811
4846
  },
4812
4847
  {
4813
4848
  title: "MCP tools \u2014 memory, decision, and search",
@@ -4941,10 +4976,24 @@ function stableId(memoryId, type, content) {
4941
4976
  return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
4942
4977
  }
4943
4978
  function cleanText(text) {
4944
- return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
4979
+ let cleaned = text.replace(
4980
+ /```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
4981
+ (_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
4982
+ );
4983
+ cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
4984
+ return cleaned;
4945
4985
  }
4946
- function splitSentences(text) {
4947
- return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
4986
+ function splitSegments(text) {
4987
+ const cleaned = cleanText(text);
4988
+ const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
4989
+ if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
4990
+ const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
4991
+ if (lines.length > 0) return lines;
4992
+ if (cleaned.length >= MIN_SEGMENT_CHARS) {
4993
+ return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
4994
+ }
4995
+ }
4996
+ return segments;
4948
4997
  }
4949
4998
  function inferCardType(sentence, toolName) {
4950
4999
  const lower = sentence.toLowerCase();
@@ -4976,12 +5025,12 @@ function predicateFor(type) {
4976
5025
  }
4977
5026
  }
4978
5027
  function extractMemoryCards(row) {
4979
- const sentences = splitSentences(row.raw_text);
5028
+ const segments = splitSegments(row.raw_text);
4980
5029
  const cards = [];
4981
- for (const sentence of sentences) {
5030
+ for (const sentence of segments) {
4982
5031
  const type = inferCardType(sentence, row.tool_name);
4983
5032
  const subject = extractSubject(sentence, row.agent_id);
4984
- const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
5033
+ const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
4985
5034
  cards.push({
4986
5035
  id: stableId(row.id, type, content),
4987
5036
  memory_id: row.id,
@@ -5077,13 +5126,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
5077
5126
  last_accessed: String(row.timestamp)
5078
5127
  }));
5079
5128
  }
5080
- var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
5129
+ var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
5081
5130
  var init_memory_cards = __esm({
5082
5131
  "src/lib/memory-cards.ts"() {
5083
5132
  "use strict";
5084
5133
  init_database();
5085
- MAX_CARDS_PER_MEMORY = 6;
5086
- MAX_SENTENCE_CHARS = 360;
5134
+ MAX_CARDS_PER_MEMORY = 8;
5135
+ MAX_SEGMENT_CHARS = 500;
5136
+ MIN_SEGMENT_CHARS = 20;
5087
5137
  }
5088
5138
  });
5089
5139
 
@@ -7395,7 +7445,7 @@ async function hybridSearch(queryText, agentId, options) {
7395
7445
  try {
7396
7446
  const client = getClient();
7397
7447
  void client.execute({
7398
- sql: `UPDATE memories SET last_accessed = ?, retrieval_count = COALESCE(retrieval_count, 0) + 1 WHERE id IN (${placeholders})`,
7448
+ sql: `UPDATE memories SET last_accessed = ?, retrieval_count = COALESCE(retrieval_count, 0) + 1, strength = MIN(1.0, COALESCE(strength, 1.0) + 0.1) WHERE id IN (${placeholders})`,
7399
7449
  args: [now, ...ids]
7400
7450
  }).catch(() => {
7401
7451
  });
@@ -8644,7 +8694,7 @@ var init_license = __esm({
8644
8694
  LICENSE_PATH = path15.join(EXE_AI_DIR, "license.key");
8645
8695
  CACHE_PATH = path15.join(EXE_AI_DIR, "license-cache.json");
8646
8696
  DEVICE_ID_PATH = path15.join(EXE_AI_DIR, "device-id");
8647
- API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
8697
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
8648
8698
  }
8649
8699
  });
8650
8700
 
@@ -8697,6 +8747,18 @@ function extractRootExe(name) {
8697
8747
  const parts = name.split("-").filter(Boolean);
8698
8748
  return parts.length > 0 ? parts[parts.length - 1] : null;
8699
8749
  }
8750
+ function registerParentExe(sessionKey, parentExe, dispatchedBy) {
8751
+ if (!existsSync16(SESSION_CACHE)) {
8752
+ mkdirSync8(SESSION_CACHE, { recursive: true });
8753
+ }
8754
+ const rootExe = extractRootExe(parentExe) ?? parentExe;
8755
+ const filePath = path18.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
8756
+ writeFileSync7(filePath, JSON.stringify({
8757
+ parentExe: rootExe,
8758
+ dispatchedBy: dispatchedBy || rootExe,
8759
+ registeredAt: (/* @__PURE__ */ new Date()).toISOString()
8760
+ }));
8761
+ }
8700
8762
  function getParentExe(sessionKey) {
8701
8763
  try {
8702
8764
  const data = JSON.parse(readFileSync11(path18.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
@@ -8706,11 +8768,12 @@ function getParentExe(sessionKey) {
8706
8768
  }
8707
8769
  }
8708
8770
  function resolveExeSession() {
8771
+ if (process.env.EXE_SESSION_NAME) {
8772
+ const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
8773
+ if (fromEnv) return fromEnv;
8774
+ }
8709
8775
  const mySession = getMySession();
8710
8776
  if (!mySession) {
8711
- if (process.env.EXE_SESSION_NAME) {
8712
- return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
8713
- }
8714
8777
  return null;
8715
8778
  }
8716
8779
  const fromSessionName = extractRootExe(mySession);
@@ -8725,6 +8788,10 @@ function resolveExeSession() {
8725
8788
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
8726
8789
  `
8727
8790
  );
8791
+ try {
8792
+ registerParentExe(key, fromSessionName);
8793
+ } catch {
8794
+ }
8728
8795
  candidate = fromSessionName;
8729
8796
  } else {
8730
8797
  candidate = fromCache;