@askexenow/exe-os 0.9.112 → 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 +54 -11
  3. package/dist/bin/agentic-reflection-backfill.js +29 -1
  4. package/dist/bin/agentic-semantic-label.js +29 -1
  5. package/dist/bin/backfill-conversations.js +53 -10
  6. package/dist/bin/backfill-responses.js +54 -11
  7. package/dist/bin/backfill-vectors.js +29 -1
  8. package/dist/bin/bulk-sync-postgres.js +55 -12
  9. package/dist/bin/cleanup-stale-review-tasks.js +75 -15
  10. package/dist/bin/cli.js +293 -76
  11. package/dist/bin/exe-agent-config.js +7 -1
  12. package/dist/bin/exe-agent.js +28 -2
  13. package/dist/bin/exe-assign.js +54 -11
  14. package/dist/bin/exe-boot.js +481 -147
  15. package/dist/bin/exe-call.js +45 -4
  16. package/dist/bin/exe-cloud.js +93 -15
  17. package/dist/bin/exe-dispatch.js +369 -24
  18. package/dist/bin/exe-doctor.js +53 -10
  19. package/dist/bin/exe-export-behaviors.js +54 -11
  20. package/dist/bin/exe-forget.js +54 -11
  21. package/dist/bin/exe-gateway.js +128 -23
  22. package/dist/bin/exe-heartbeat.js +75 -15
  23. package/dist/bin/exe-kill.js +54 -11
  24. package/dist/bin/exe-launch-agent.js +70 -12
  25. package/dist/bin/exe-new-employee.js +175 -7
  26. package/dist/bin/exe-pending-messages.js +75 -15
  27. package/dist/bin/exe-pending-notifications.js +75 -15
  28. package/dist/bin/exe-pending-reviews.js +75 -15
  29. package/dist/bin/exe-rename.js +54 -11
  30. package/dist/bin/exe-review.js +54 -11
  31. package/dist/bin/exe-search.js +54 -11
  32. package/dist/bin/exe-session-cleanup.js +491 -146
  33. package/dist/bin/exe-settings.js +10 -4
  34. package/dist/bin/exe-start-codex.js +524 -245
  35. package/dist/bin/exe-start-opencode.js +534 -165
  36. package/dist/bin/exe-status.js +75 -15
  37. package/dist/bin/exe-support.js +1 -1
  38. package/dist/bin/exe-team.js +54 -11
  39. package/dist/bin/git-sweep.js +369 -24
  40. package/dist/bin/graph-backfill.js +54 -11
  41. package/dist/bin/graph-export.js +54 -11
  42. package/dist/bin/install.js +62 -4
  43. package/dist/bin/intercom-check.js +491 -146
  44. package/dist/bin/pre-publish.js +13 -1
  45. package/dist/bin/scan-tasks.js +369 -24
  46. package/dist/bin/setup.js +91 -13
  47. package/dist/bin/shard-migrate.js +54 -11
  48. package/dist/bin/stack-update.js +1 -1
  49. package/dist/bin/update.js +3 -3
  50. package/dist/gateway/index.js +128 -23
  51. package/dist/hooks/bug-report-worker.js +128 -23
  52. package/dist/hooks/codex-stop-task-finalizer.js +512 -140
  53. package/dist/hooks/commit-complete.js +369 -24
  54. package/dist/hooks/error-recall.js +54 -11
  55. package/dist/hooks/ingest.js +4575 -252
  56. package/dist/hooks/instructions-loaded.js +54 -11
  57. package/dist/hooks/notification.js +54 -11
  58. package/dist/hooks/post-compact.js +75 -15
  59. package/dist/hooks/post-tool-combined.js +75 -15
  60. package/dist/hooks/pre-compact.js +449 -104
  61. package/dist/hooks/pre-tool-use.js +90 -15
  62. package/dist/hooks/prompt-submit.js +129 -24
  63. package/dist/hooks/session-end.js +451 -109
  64. package/dist/hooks/session-start.js +104 -16
  65. package/dist/hooks/stop.js +74 -14
  66. package/dist/hooks/subagent-stop.js +75 -15
  67. package/dist/hooks/summary-worker.js +73 -7
  68. package/dist/index.js +128 -23
  69. package/dist/lib/agent-config.js +16 -1
  70. package/dist/lib/cloud-sync.js +38 -1
  71. package/dist/lib/consolidation.js +16 -1
  72. package/dist/lib/database.js +16 -0
  73. package/dist/lib/db.js +16 -0
  74. package/dist/lib/device-registry.js +16 -0
  75. package/dist/lib/employee-templates.js +29 -3
  76. package/dist/lib/employees.js +16 -1
  77. package/dist/lib/exe-daemon.js +268 -42
  78. package/dist/lib/hybrid-search.js +54 -11
  79. package/dist/lib/license.js +3 -3
  80. package/dist/lib/messaging.js +21 -4
  81. package/dist/lib/schedules.js +29 -1
  82. package/dist/lib/skill-learning.js +458 -70
  83. package/dist/lib/status-brief.js +14 -1
  84. package/dist/lib/store.js +54 -11
  85. package/dist/lib/tasks.js +393 -91
  86. package/dist/lib/tmux-routing.js +316 -14
  87. package/dist/mcp/server.js +169 -30
  88. package/dist/mcp/tools/create-task.js +75 -13
  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 +390 -91
  93. package/dist/runtime/index.js +446 -101
  94. package/dist/tui/App.js +208 -54
  95. package/package.json +1 -1
package/dist/bin/cli.js CHANGED
@@ -369,6 +369,7 @@ __export(agent_config_exports, {
369
369
  getAgentRuntime: () => getAgentRuntime,
370
370
  loadAgentConfig: () => loadAgentConfig,
371
371
  saveAgentConfig: () => saveAgentConfig,
372
+ setAgentMcps: () => setAgentMcps,
372
373
  setAgentRuntime: () => setAgentRuntime
373
374
  });
374
375
  import { readFileSync as readFileSync2, writeFileSync, existsSync as existsSync3 } from "fs";
@@ -395,7 +396,7 @@ function getAgentRuntime(agentId) {
395
396
  if (orgDefault) return orgDefault;
396
397
  return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
397
398
  }
398
- function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
399
+ function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
399
400
  const knownModels = KNOWN_RUNTIMES[runtime];
400
401
  if (!knownModels) {
401
402
  return {
@@ -410,12 +411,26 @@ function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
410
411
  };
411
412
  }
412
413
  const config = loadAgentConfig();
414
+ const existing = config[agentId];
413
415
  const entry = { runtime, model };
414
416
  if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
417
+ if (mcps !== void 0) {
418
+ entry.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
419
+ } else if (existing?.mcps) {
420
+ entry.mcps = existing.mcps;
421
+ }
415
422
  config[agentId] = entry;
416
423
  saveAgentConfig(config);
417
424
  return { ok: true };
418
425
  }
426
+ function setAgentMcps(agentId, mcps) {
427
+ const config = loadAgentConfig();
428
+ const existing = config[agentId] ?? getAgentRuntime(agentId);
429
+ existing.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
430
+ config[agentId] = existing;
431
+ saveAgentConfig(config);
432
+ return { ok: true };
433
+ }
419
434
  function clearAgentRuntime(agentId) {
420
435
  const config = loadAgentConfig();
421
436
  delete config[agentId];
@@ -842,6 +857,16 @@ import { chmodSync as chmodSync2, existsSync as existsSync7, mkdirSync as mkdirS
842
857
  import { randomBytes } from "crypto";
843
858
  import path6 from "path";
844
859
  import os5 from "os";
860
+ function resolveDefaultAgentId() {
861
+ if (process.env.AGENT_ID && process.env.AGENT_ID !== "default") return process.env.AGENT_ID;
862
+ try {
863
+ const { loadEmployeesSync: loadEmployeesSync2 } = (init_employees(), __toCommonJS(employees_exports));
864
+ const coo = loadEmployeesSync2().find((e) => e.role === "COO");
865
+ if (coo) return coo.name;
866
+ } catch {
867
+ }
868
+ return "exe";
869
+ }
845
870
  function mcpHttpPort() {
846
871
  return process.env.EXE_MCP_PORT || DEFAULT_MCP_HTTP_PORT;
847
872
  }
@@ -871,11 +896,14 @@ function readOrCreateDaemonToken(homeDir = os5.homedir()) {
871
896
  function buildMcpHttpHeaders(homeDir = os5.homedir(), opts = {}) {
872
897
  const agentId = opts.useShellPlaceholders ? "${AGENT_ID:-exe}" : opts.agentId ?? DEFAULT_MCP_HTTP_AGENT_ID;
873
898
  const agentRole = opts.useShellPlaceholders ? "${AGENT_ROLE:-COO}" : opts.agentRole ?? DEFAULT_MCP_HTTP_AGENT_ROLE;
874
- return {
899
+ const sessionName = opts.useShellPlaceholders ? "$(tmux display-message -p '#{session_name}' 2>/dev/null || echo '')" : process.env.EXE_SESSION_NAME ?? "";
900
+ const headers = {
875
901
  Authorization: `Bearer ${readOrCreateDaemonToken(homeDir)}`,
876
902
  "X-Agent-Id": agentId,
877
903
  "X-Agent-Role": agentRole
878
904
  };
905
+ if (sessionName) headers["X-Exe-Session"] = sessionName;
906
+ return headers;
879
907
  }
880
908
  function buildClaudeHttpMcpEntry(homeDir = os5.homedir()) {
881
909
  return {
@@ -889,12 +917,15 @@ var init_mcp_http_config = __esm({
889
917
  "src/adapters/mcp-http-config.ts"() {
890
918
  "use strict";
891
919
  DEFAULT_MCP_HTTP_PORT = "48739";
892
- DEFAULT_MCP_HTTP_AGENT_ID = "exe";
920
+ DEFAULT_MCP_HTTP_AGENT_ID = resolveDefaultAgentId();
893
921
  DEFAULT_MCP_HTTP_AGENT_ROLE = "COO";
894
922
  }
895
923
  });
896
924
 
897
925
  // src/adapters/runtime-hook-manifest.ts
926
+ function isLegacyHomeDirHookCommand(command) {
927
+ return LEGACY_HOME_DIR_HOOK_PATTERNS.some((pattern) => command.includes(pattern));
928
+ }
898
929
  function commandHasAnyMarker(command, markers) {
899
930
  return markers.some((marker) => command.includes(marker));
900
931
  }
@@ -904,7 +935,7 @@ function isLegacySplitPostToolCommand(command) {
904
935
  function textHasLegacySplitPostToolHook(text) {
905
936
  return [EXE_HOOK_FILES.ingest, EXE_HOOK_FILES.errorRecall, EXE_HOOK_FILES.ingestWorker].some((file) => text.includes(file));
906
937
  }
907
- var EXE_HOOK_FILES, EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS;
938
+ var EXE_HOOK_FILES, EXE_HOOKS, EXE_HOOK_MANIFEST, LEGACY_SPLIT_POST_TOOL_HOOK_MARKERS, LEGACY_HOME_DIR_HOOK_PATTERNS;
908
939
  var init_runtime_hook_manifest = __esm({
909
940
  "src/adapters/runtime-hook-manifest.ts"() {
910
941
  "use strict";
@@ -1043,6 +1074,14 @@ var init_runtime_hook_manifest = __esm({
1043
1074
  "dist/hooks/error-recall.js",
1044
1075
  "dist/hooks/ingest-worker.js"
1045
1076
  ];
1077
+ LEGACY_HOME_DIR_HOOK_PATTERNS = [
1078
+ ".exe-os/hooks/",
1079
+ // Old hook storage path (pre-npm-package era)
1080
+ "log-prefix.js",
1081
+ // Removed hook from early versions
1082
+ "approval-bridge.log"
1083
+ // Removed log redirect from early versions
1084
+ ];
1046
1085
  }
1047
1086
  });
1048
1087
 
@@ -1522,6 +1561,14 @@ async function mergeHooks(packageRoot, homeDir = os6.homedir()) {
1522
1561
  ];
1523
1562
  let added = 0;
1524
1563
  let skipped = 0;
1564
+ for (const eventKey of Object.keys(settings.hooks)) {
1565
+ const groups = settings.hooks[eventKey];
1566
+ if (!Array.isArray(groups)) continue;
1567
+ settings.hooks[eventKey] = groups.map((g) => ({
1568
+ ...g,
1569
+ hooks: g.hooks.filter((h) => !isLegacyHomeDirHookCommand(h.command))
1570
+ })).filter((g) => g.hooks.length > 0);
1571
+ }
1525
1572
  const postToolGroups = settings.hooks["PostToolUse"];
1526
1573
  if (Array.isArray(postToolGroups)) {
1527
1574
  settings.hooks["PostToolUse"] = postToolGroups.map((g) => ({
@@ -5915,6 +5962,22 @@ async function ensureSchema() {
5915
5962
  } catch (e) {
5916
5963
  logCatchDebug("migration", e);
5917
5964
  }
5965
+ try {
5966
+ await client.execute({
5967
+ sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
5968
+ args: []
5969
+ });
5970
+ } catch (e) {
5971
+ logCatchDebug("migration", e);
5972
+ }
5973
+ try {
5974
+ await client.execute({
5975
+ sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
5976
+ args: []
5977
+ });
5978
+ } catch (e) {
5979
+ logCatchDebug("migration", e);
5980
+ }
5918
5981
  }
5919
5982
  async function disposeDatabase() {
5920
5983
  if (_walCheckpointTimer) {
@@ -6460,7 +6523,7 @@ async function assertVpsLicense(opts) {
6460
6523
  }
6461
6524
  if (!transientFailure) {
6462
6525
  throw new Error(
6463
- "License validation failed: unknown backend state. Restore network connectivity to https://askexe.com/cloud and retry."
6526
+ "License validation failed: unknown backend state. Restore network connectivity to https://cloud.askexe.com and retry."
6464
6527
  );
6465
6528
  }
6466
6529
  const fresh = await getCachedLicense();
@@ -6497,7 +6560,7 @@ async function assertVpsLicense(opts) {
6497
6560
  } catch {
6498
6561
  }
6499
6562
  throw new Error(
6500
- `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.`
6563
+ `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.`
6501
6564
  );
6502
6565
  }
6503
6566
  function startLicenseRevalidation(intervalMs = 36e5) {
@@ -6529,7 +6592,7 @@ var init_license = __esm({
6529
6592
  LICENSE_PATH = path13.join(EXE_AI_DIR, "license.key");
6530
6593
  CACHE_PATH = path13.join(EXE_AI_DIR, "license-cache.json");
6531
6594
  DEVICE_ID_PATH = path13.join(EXE_AI_DIR, "device-id");
6532
- API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com/cloud";
6595
+ API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
6533
6596
  RETRY_DELAY_MS = 500;
6534
6597
  LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
6535
6598
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
@@ -7332,6 +7395,27 @@ async function cloudSync(config) {
7332
7395
  if (stmts.length > 0) await client.batch(stmts, "write");
7333
7396
  pulled = pullResult.records.length;
7334
7397
  } else {
7398
+ try {
7399
+ const incomingIds = pullResult.records.map((r) => sqlSafe(r.id));
7400
+ if (incomingIds.length > 0) {
7401
+ const ph = incomingIds.map(() => "?").join(",");
7402
+ const existing = await client.execute({
7403
+ sql: `SELECT id, version, timestamp FROM memories WHERE id IN (${ph})`,
7404
+ args: incomingIds
7405
+ });
7406
+ const localMap = new Map(existing.rows.map((r) => [String(r.id), r]));
7407
+ for (const rec of pullResult.records) {
7408
+ const local = localMap.get(String(rec.id));
7409
+ if (local && Number(local.version) > 0 && Number(local.version) !== Number(rec.version ?? 0)) {
7410
+ process.stderr.write(
7411
+ `[cloud-sync] CONFLICT: memory ${String(rec.id).slice(0, 8)} \u2014 local v${local.version} vs remote v${rec.version ?? 0}. Remote wins (LWW).
7412
+ `
7413
+ );
7414
+ }
7415
+ }
7416
+ }
7417
+ } catch {
7418
+ }
7335
7419
  const stmts = pullResult.records.map((rec) => ({
7336
7420
  sql: `INSERT OR REPLACE INTO memories
7337
7421
  (id, agent_id, agent_role, session_id, timestamp,
@@ -9089,11 +9173,17 @@ var init_platform_procedures = __esm({
9089
9173
  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."
9090
9174
  },
9091
9175
  {
9092
- title: "Customer orchestration maturity \u2014 recommend, never trap",
9176
+ title: "Orchestration phase guidance \u2014 recommend, never trap",
9093
9177
  domain: "workflow",
9094
9178
  priority: "p1",
9095
9179
  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."
9096
9180
  },
9181
+ {
9182
+ title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
9183
+ domain: "identity",
9184
+ priority: "p0",
9185
+ 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."
9186
+ },
9097
9187
  {
9098
9188
  title: "Single dispatch path \u2014 create_task only",
9099
9189
  domain: "workflow",
@@ -9127,6 +9217,12 @@ var init_platform_procedures = __esm({
9127
9217
  priority: "p0",
9128
9218
  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."
9129
9219
  },
9220
+ {
9221
+ title: "Destructive operations \u2014 mandatory reviewer gate",
9222
+ domain: "security",
9223
+ priority: "p0",
9224
+ 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."
9225
+ },
9130
9226
  {
9131
9227
  title: "Customer patch triage \u2014 upstream bug vs customization",
9132
9228
  domain: "support",
@@ -9412,10 +9508,24 @@ function stableId(memoryId, type, content) {
9412
9508
  return createHash3("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
9413
9509
  }
9414
9510
  function cleanText(text) {
9415
- return text.replace(/```[\s\S]*?```/g, " ").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
9511
+ let cleaned = text.replace(
9512
+ /```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
9513
+ (_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
9514
+ );
9515
+ cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
9516
+ return cleaned;
9416
9517
  }
9417
- function splitSentences(text) {
9418
- return cleanText(text).split(/(?<=[.!?])\s+|\n+/).map((s) => s.trim()).filter((s) => s.length >= 24 && s.length <= MAX_SENTENCE_CHARS);
9518
+ function splitSegments(text) {
9519
+ const cleaned = cleanText(text);
9520
+ 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);
9521
+ if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
9522
+ const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
9523
+ if (lines.length > 0) return lines;
9524
+ if (cleaned.length >= MIN_SEGMENT_CHARS) {
9525
+ return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
9526
+ }
9527
+ }
9528
+ return segments;
9419
9529
  }
9420
9530
  function inferCardType(sentence, toolName) {
9421
9531
  const lower = sentence.toLowerCase();
@@ -9447,12 +9557,12 @@ function predicateFor(type) {
9447
9557
  }
9448
9558
  }
9449
9559
  function extractMemoryCards(row) {
9450
- const sentences = splitSentences(row.raw_text);
9560
+ const segments = splitSegments(row.raw_text);
9451
9561
  const cards = [];
9452
- for (const sentence of sentences) {
9562
+ for (const sentence of segments) {
9453
9563
  const type = inferCardType(sentence, row.tool_name);
9454
9564
  const subject = extractSubject(sentence, row.agent_id);
9455
- const content = sentence.length > MAX_SENTENCE_CHARS ? `${sentence.slice(0, MAX_SENTENCE_CHARS - 1)}\u2026` : sentence;
9565
+ const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
9456
9566
  cards.push({
9457
9567
  id: stableId(row.id, type, content),
9458
9568
  memory_id: row.id,
@@ -9548,13 +9658,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
9548
9658
  last_accessed: String(row.timestamp)
9549
9659
  }));
9550
9660
  }
9551
- var MAX_CARDS_PER_MEMORY, MAX_SENTENCE_CHARS;
9661
+ var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
9552
9662
  var init_memory_cards = __esm({
9553
9663
  "src/lib/memory-cards.ts"() {
9554
9664
  "use strict";
9555
9665
  init_database();
9556
- MAX_CARDS_PER_MEMORY = 6;
9557
- MAX_SENTENCE_CHARS = 360;
9666
+ MAX_CARDS_PER_MEMORY = 8;
9667
+ MAX_SEGMENT_CHARS = 500;
9668
+ MIN_SEGMENT_CHARS = 20;
9558
9669
  }
9559
9670
  });
9560
9671
 
@@ -10645,7 +10756,7 @@ async function setupMode() {
10645
10756
  rl.close();
10646
10757
  return;
10647
10758
  }
10648
- const endpoint = await ask(rl, " Endpoint [https://askexe.com/cloud]: ") || "https://askexe.com/cloud";
10759
+ const endpoint = await ask(rl, " Endpoint [https://cloud.askexe.com]: ") || "https://cloud.askexe.com";
10649
10760
  console.log(" Validating...");
10650
10761
  try {
10651
10762
  assertSecureEndpoint(endpoint);
@@ -10711,6 +10822,14 @@ async function setupMode() {
10711
10822
  }
10712
10823
  console.log("");
10713
10824
  }
10825
+ try {
10826
+ const keyInfo = await getKeyStorageInfo();
10827
+ if (keyInfo.kind !== "missing") {
10828
+ console.log(` \u2713 Encryption key: ${keyInfo.note}`);
10829
+ }
10830
+ } catch {
10831
+ }
10832
+ console.log("");
10714
10833
  console.log(BAR);
10715
10834
  console.log(latestConfig.cloud?.apiKey ? " Setup complete. Cloud sync is connected." : " Setup complete. Cloud sync is not configured yet.");
10716
10835
  console.log(BAR);
@@ -10802,7 +10921,13 @@ async function statusMode() {
10802
10921
  console.log("");
10803
10922
  if (key) {
10804
10923
  const fingerprint = key.toString("hex").slice(0, 8);
10805
- console.log(` Encryption key: \u2713 present (${fingerprint}...)`);
10924
+ let storageNote = "";
10925
+ try {
10926
+ const keyInfo = await getKeyStorageInfo();
10927
+ if (keyInfo.kind !== "missing") storageNote = ` [${keyInfo.note}]`;
10928
+ } catch {
10929
+ }
10930
+ console.log(` Encryption key: \u2713 present (${fingerprint}...)${storageNote}`);
10806
10931
  } else {
10807
10932
  console.log(" Encryption key: \u2717 not found \u2014 run /exe-setup");
10808
10933
  }
@@ -12291,17 +12416,14 @@ var backfill_metadata_exports = {};
12291
12416
  __export(backfill_metadata_exports, {
12292
12417
  backfillMetadata: () => backfillMetadata
12293
12418
  });
12294
- function roleAgentMarkers(role, fallbackName) {
12419
+ function roleAgentMarkers(role) {
12295
12420
  try {
12296
12421
  const employees = loadEmployeesSync();
12297
- const employee = getEmployeeByRole(employees, role);
12298
- const configuredName = employee?.name?.toLowerCase().trim();
12299
- if (configuredName) {
12300
- return [configuredName];
12301
- }
12422
+ const names = getEmployeeNamesByRole(employees, role).map((n) => n.toLowerCase().trim()).filter(Boolean);
12423
+ if (names.length > 0) return names;
12302
12424
  } catch {
12303
12425
  }
12304
- return [fallbackName];
12426
+ return [];
12305
12427
  }
12306
12428
  function mentionsAgentMarker(text, markers) {
12307
12429
  return markers.some(
@@ -12860,8 +12982,8 @@ var init_backfill_metadata = __esm({
12860
12982
  VALID_LANGUAGE_TYPES = /* @__PURE__ */ new Set(["code", "prose", "mixed", "json", "sql"]);
12861
12983
  MAX_TEXT_LENGTH = 2e3;
12862
12984
  BATCH_SLEEP_MS = 1e3;
12863
- MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO", "mari");
12864
- RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead", "gen");
12985
+ MARKETING_AGENT_MARKERS = roleAgentMarkers("CMO");
12986
+ RESEARCH_AGENT_MARKERS = roleAgentMarkers("AI Product Lead");
12865
12987
  if (isMainModule(import.meta.url)) {
12866
12988
  const options = parseArgs2(process.argv.slice(2));
12867
12989
  backfillMetadata(options).then((result) => {
@@ -14341,6 +14463,19 @@ async function resolveTask(client, identifier, scopeSession) {
14341
14463
  args: [identifier, ...scope.args]
14342
14464
  });
14343
14465
  if (result.rows.length === 1) return result.rows[0];
14466
+ if (/^[a-f0-9]{7,12}$/i.test(identifier)) {
14467
+ result = await client.execute({
14468
+ sql: `SELECT * FROM tasks WHERE id LIKE ?`,
14469
+ args: [`${identifier}%`]
14470
+ });
14471
+ if (result.rows.length === 1) return result.rows[0];
14472
+ if (result.rows.length > 1) {
14473
+ const matches = result.rows.map((r) => `${String(r.id)} "${String(r.title)}" (${String(r.status)})`).join(", ");
14474
+ throw new Error(
14475
+ `Multiple tasks match short-ID "${identifier}": ${matches}. Use a longer prefix to disambiguate.`
14476
+ );
14477
+ }
14478
+ }
14344
14479
  result = await client.execute({
14345
14480
  sql: `SELECT * FROM tasks WHERE task_file LIKE ?${scope.sql}`,
14346
14481
  args: [`%${identifier}%`, ...scope.args]
@@ -15195,12 +15330,13 @@ async function cascadeUnblock(taskId, baseDir, now2) {
15195
15330
  WHERE blocked_by = ? AND status = 'blocked'`,
15196
15331
  args: [now2, taskId]
15197
15332
  });
15198
- if (baseDir && unblocked.rowsAffected > 0) {
15199
- const ubScope = sessionScopeFilter();
15200
- const unblockedRows = await client.execute({
15201
- sql: `SELECT task_file FROM tasks WHERE blocked_by IS NULL AND updated_at = ?${ubScope.sql}`,
15202
- args: [now2, ...ubScope.args]
15203
- });
15333
+ if (unblocked.rowsAffected === 0) return;
15334
+ const ubScope = sessionScopeFilter();
15335
+ const unblockedRows = await client.execute({
15336
+ sql: `SELECT id, title, assigned_to, priority, task_file FROM tasks WHERE blocked_by IS NULL AND updated_at = ?${ubScope.sql}`,
15337
+ args: [now2, ...ubScope.args]
15338
+ });
15339
+ if (baseDir) {
15204
15340
  for (const ur of unblockedRows.rows) {
15205
15341
  try {
15206
15342
  const ubFile = path32.join(baseDir, String(ur.task_file));
@@ -15212,6 +15348,19 @@ async function cascadeUnblock(taskId, baseDir, now2) {
15212
15348
  }
15213
15349
  }
15214
15350
  }
15351
+ if (unblockedRows.rows.length > 0 && !process.env.VITEST) {
15352
+ try {
15353
+ const { queueIntercom: queueIntercom2 } = await Promise.resolve().then(() => (init_intercom_queue(), intercom_queue_exports));
15354
+ const dispatched = /* @__PURE__ */ new Set();
15355
+ for (const ur of unblockedRows.rows) {
15356
+ const assignee = String(ur.assigned_to);
15357
+ if (dispatched.has(assignee)) continue;
15358
+ dispatched.add(assignee);
15359
+ queueIntercom2(`${assignee}`, `unblocked: "${String(ur.title)}" is now ready`);
15360
+ }
15361
+ } catch {
15362
+ }
15363
+ }
15215
15364
  }
15216
15365
  async function findNextTask(assignedTo) {
15217
15366
  const client = getClient();
@@ -15421,6 +15570,15 @@ var init_embedder = __esm({
15421
15570
  // src/lib/behaviors.ts
15422
15571
  import crypto10 from "crypto";
15423
15572
  async function storeBehavior(opts) {
15573
+ try {
15574
+ const { loadEmployeesSync: loadEmployeesSync2 } = await Promise.resolve().then(() => (init_employees(), employees_exports));
15575
+ const roster = loadEmployeesSync2();
15576
+ if (roster.length > 0 && !roster.some((e) => e.name === opts.agentId)) {
15577
+ throw new Error(`Agent "${opts.agentId}" not found in roster. Cannot store behavior for unregistered agent.`);
15578
+ }
15579
+ } catch (e) {
15580
+ if (e instanceof Error && e.message.includes("not found in roster")) throw e;
15581
+ }
15424
15582
  const client = getClient();
15425
15583
  const id = crypto10.randomUUID();
15426
15584
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
@@ -15874,6 +16032,12 @@ async function updateTask(input) {
15874
16032
  }
15875
16033
  }
15876
16034
  }
16035
+ if (input.status === "cancelled") {
16036
+ try {
16037
+ await cascadeUnblock(taskId, input.baseDir, now2);
16038
+ } catch {
16039
+ }
16040
+ }
15877
16041
  if ((input.status === "done" || input.status === "closed") && !isCoordinatorName(String(row.assigned_to)) && !process.env.VITEST) {
15878
16042
  Promise.resolve().then(() => (init_skill_learning(), skill_learning_exports)).then(
15879
16043
  ({ captureAndLearn: captureAndLearn2 }) => captureAndLearn2({
@@ -16405,11 +16569,12 @@ function getDispatchedBy(sessionKey) {
16405
16569
  }
16406
16570
  }
16407
16571
  function resolveExeSession() {
16572
+ if (process.env.EXE_SESSION_NAME) {
16573
+ const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
16574
+ if (fromEnv) return fromEnv;
16575
+ }
16408
16576
  const mySession = getMySession();
16409
16577
  if (!mySession) {
16410
- if (process.env.EXE_SESSION_NAME) {
16411
- return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
16412
- }
16413
16578
  return null;
16414
16579
  }
16415
16580
  const fromSessionName = extractRootExe(mySession);
@@ -16424,6 +16589,10 @@ function resolveExeSession() {
16424
16589
  `[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
16425
16590
  `
16426
16591
  );
16592
+ try {
16593
+ registerParentExe(key, fromSessionName);
16594
+ } catch {
16595
+ }
16427
16596
  candidate = fromSessionName;
16428
16597
  } else {
16429
16598
  candidate = fromCache;
@@ -17582,9 +17751,23 @@ __export(employee_templates_exports, {
17582
17751
  function getSessionPrompt(storedPrompt) {
17583
17752
  const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
17584
17753
  const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
17754
+ let titlePrefix = "";
17755
+ const frontmatterMatch = withoutProcedures.match(/^---\r?\n([\s\S]*?)\r?\n---/);
17756
+ if (frontmatterMatch) {
17757
+ const titleMatch = frontmatterMatch[1].match(/^title:\s*(.+)$/m);
17758
+ const roleMatch = frontmatterMatch[1].match(/^role:\s*(.+)$/m);
17759
+ if (titleMatch) {
17760
+ const title = titleMatch[1].trim();
17761
+ const role = roleMatch ? roleMatch[1].trim() : "";
17762
+ if (title && role && title.toLowerCase() !== role.toLowerCase()) {
17763
+ titlePrefix = `## Your Identity
17764
+ You are **${title}** (specialist). `;
17765
+ }
17766
+ }
17767
+ }
17585
17768
  const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
17586
17769
  const globalBlock = getGlobalProceduresBlock();
17587
- return `${globalBlock}${rolePrompt}
17770
+ return `${globalBlock}${titlePrefix}${rolePrompt}
17588
17771
  ${BASE_OPERATING_PROCEDURES}`;
17589
17772
  }
17590
17773
  function buildCustomEmployeePrompt(name, role) {
@@ -17603,7 +17786,7 @@ function personalizePrompt(prompt, templateName, actualName) {
17603
17786
  return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
17604
17787
  }
17605
17788
  function renderClientCOOTemplate(vars) {
17606
- const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
17789
+ const resolved = { ...vars, title: vars.title || "Chief of Staff" };
17607
17790
  for (const key of CLIENT_COO_PLACEHOLDERS) {
17608
17791
  const value = resolved[key];
17609
17792
  if (typeof value !== "string" || value.length === 0) {
@@ -20327,7 +20510,7 @@ async function runSetupWizard(opts = {}) {
20327
20510
  log("");
20328
20511
  const apiKey = await ask3(rl, "Cloud API key (starts with exe_sk_): ");
20329
20512
  if (apiKey && apiKey.startsWith("exe_sk_")) {
20330
- const cloudEndpoint = "https://askexe.com/cloud";
20513
+ const cloudEndpoint = "https://cloud.askexe.com";
20331
20514
  const cloudCfg = { apiKey, endpoint: cloudEndpoint };
20332
20515
  const earlyConfig = await loadConfig();
20333
20516
  earlyConfig.cloud = cloudCfg;
@@ -20427,7 +20610,7 @@ async function runSetupWizard(opts = {}) {
20427
20610
  log("");
20428
20611
  const existingKey = await ask3(rl, "Paste your Exe OS license key, or press Enter to start as a free user: ");
20429
20612
  if (existingKey && existingKey.startsWith("exe_sk_")) {
20430
- const cloudEndpoint = "https://askexe.com/cloud";
20613
+ const cloudEndpoint = "https://cloud.askexe.com";
20431
20614
  try {
20432
20615
  const { loadDeviceId: loadDeviceId2 } = await Promise.resolve().then(() => (init_license(), license_exports));
20433
20616
  const deviceId = loadDeviceId2();
@@ -20452,7 +20635,7 @@ async function runSetupWizard(opts = {}) {
20452
20635
  }
20453
20636
  } catch {
20454
20637
  log("Could not validate key \u2014 saving it and proceeding.");
20455
- cloudConfig = { apiKey: existingKey, endpoint: "https://askexe.com/cloud" };
20638
+ cloudConfig = { apiKey: existingKey, endpoint: "https://cloud.askexe.com" };
20456
20639
  const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
20457
20640
  saveLicense3(existingKey);
20458
20641
  mirrorLicenseKey3(existingKey);
@@ -20464,7 +20647,7 @@ async function runSetupWizard(opts = {}) {
20464
20647
  const deviceId = loadDeviceId2();
20465
20648
  let res;
20466
20649
  try {
20467
- res = await fetch("https://askexe.com/cloud/auth/auto-provision", {
20650
+ res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
20468
20651
  method: "POST",
20469
20652
  headers: { "Content-Type": "application/json" },
20470
20653
  body: JSON.stringify({ deviceId }),
@@ -20472,7 +20655,7 @@ async function runSetupWizard(opts = {}) {
20472
20655
  });
20473
20656
  } catch {
20474
20657
  await new Promise((r) => setTimeout(r, 500));
20475
- res = await fetch("https://askexe.com/cloud/auth/auto-provision", {
20658
+ res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
20476
20659
  method: "POST",
20477
20660
  headers: { "Content-Type": "application/json" },
20478
20661
  body: JSON.stringify({ deviceId }),
@@ -20482,7 +20665,7 @@ async function runSetupWizard(opts = {}) {
20482
20665
  if (res.ok) {
20483
20666
  const data = await res.json();
20484
20667
  if (data.apiKey) {
20485
- cloudConfig = { apiKey: data.apiKey, endpoint: "https://askexe.com/cloud" };
20668
+ cloudConfig = { apiKey: data.apiKey, endpoint: "https://cloud.askexe.com" };
20486
20669
  const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
20487
20670
  saveLicense3(data.apiKey);
20488
20671
  mirrorLicenseKey3(data.apiKey);
@@ -33142,7 +33325,7 @@ function useOrchestrator(enabled = true) {
33142
33325
  const [pendingReviews, setPendingReviews] = useState8(0);
33143
33326
  const [isLoading, setIsLoading] = useState8(true);
33144
33327
  const orchestratorRef = useRef5(null);
33145
- const exeSessionRef = useRef5("exe1");
33328
+ const exeSessionRef = useRef5("");
33146
33329
  const coordinatorNameRef = useRef5(DEFAULT_COORDINATOR_TEMPLATE_NAME);
33147
33330
  useEffect10(() => {
33148
33331
  if (!enabled) return;
@@ -33739,6 +33922,8 @@ var tui_data_exports = {};
33739
33922
  __export(tui_data_exports, {
33740
33923
  loadMemoryDashboard: () => loadMemoryDashboard,
33741
33924
  loadTaskList: () => loadTaskList,
33925
+ loadTeamBadgeCounts: () => loadTeamBadgeCounts,
33926
+ loadTeamDetailMetrics: () => loadTeamDetailMetrics,
33742
33927
  loadTeamMetrics: () => loadTeamMetrics,
33743
33928
  searchWikiMemoryRows: () => searchWikiMemoryRows
33744
33929
  });
@@ -33767,16 +33952,20 @@ async function loadMemoryDashboard(limit) {
33767
33952
  }))
33768
33953
  };
33769
33954
  }
33770
- async function loadTeamMetrics(employeeNames) {
33955
+ async function loadTeamBadgeCounts() {
33771
33956
  const client = getClient();
33772
33957
  const memoryCounts = /* @__PURE__ */ new Map();
33773
- const projectsByEmployee = /* @__PURE__ */ new Map();
33774
- const currentTaskByEmployee = /* @__PURE__ */ new Map();
33775
- const scope = sessionScopeFilter();
33776
33958
  const memResult = await client.execute("SELECT agent_id, COUNT(*) as cnt FROM memories GROUP BY agent_id");
33777
33959
  for (const row of memResult.rows) {
33778
33960
  memoryCounts.set(String(row.agent_id), Number(row.cnt));
33779
33961
  }
33962
+ return memoryCounts;
33963
+ }
33964
+ async function loadTeamDetailMetrics(employeeNames) {
33965
+ const client = getClient();
33966
+ const projectsByEmployee = /* @__PURE__ */ new Map();
33967
+ const currentTaskByEmployee = /* @__PURE__ */ new Map();
33968
+ const scope = sessionScopeFilter();
33780
33969
  for (const employeeName of employeeNames) {
33781
33970
  const [projectResult, taskResult] = await Promise.all([
33782
33971
  client.execute({
@@ -33809,6 +33998,13 @@ async function loadTeamMetrics(employeeNames) {
33809
33998
  currentTaskByEmployee.set(employeeName, String(taskResult.rows[0].title));
33810
33999
  }
33811
34000
  }
34001
+ return { projectsByEmployee, currentTaskByEmployee };
34002
+ }
34003
+ async function loadTeamMetrics(employeeNames) {
34004
+ const [memoryCounts, { projectsByEmployee, currentTaskByEmployee }] = await Promise.all([
34005
+ loadTeamBadgeCounts(),
34006
+ loadTeamDetailMetrics(employeeNames)
34007
+ ]);
33812
34008
  return { memoryCounts, projectsByEmployee, currentTaskByEmployee };
33813
34009
  }
33814
34010
  async function loadTaskList() {
@@ -35064,6 +35260,8 @@ function TeamView({ onBack, onViewSessions }) {
35064
35260
  const [members, setMembers] = useState12([]);
35065
35261
  const [externals, setExternals] = useState12([]);
35066
35262
  const [loading, setLoading] = useState12(!demo);
35263
+ const [badgeInFlight, setBadgeInFlight] = useState12(!demo);
35264
+ const [detailInFlight, setDetailInFlight] = useState12(!demo);
35067
35265
  const [dbError, setDbError] = useState12(null);
35068
35266
  const [selectedIdx, setSelectedIdx] = useState12(0);
35069
35267
  const [showDetail, setShowDetail] = useState12(false);
@@ -35076,6 +35274,8 @@ function TeamView({ onBack, onViewSessions }) {
35076
35274
  setMembers(DEMO_EMPLOYEES.map((e) => ({ ...e })));
35077
35275
  setExternals(DEMO_EXTERNAL_AGENTS);
35078
35276
  setLoading(false);
35277
+ setBadgeInFlight(false);
35278
+ setDetailInFlight(false);
35079
35279
  return;
35080
35280
  }
35081
35281
  loadTeam();
@@ -35114,33 +35314,48 @@ function TeamView({ onBack, onViewSessions }) {
35114
35314
  let projectsByEmployee = /* @__PURE__ */ new Map();
35115
35315
  let currentTaskByEmployee = /* @__PURE__ */ new Map();
35116
35316
  try {
35117
- const { loadTeamMetrics: loadTeamMetrics2 } = await Promise.resolve().then(() => (init_tui_data(), tui_data_exports));
35118
- const teamMetrics = await loadTeamMetrics2(roster.map((emp) => emp.name));
35119
- memoryCounts = teamMetrics.memoryCounts;
35120
- projectsByEmployee = new Map(
35121
- Array.from(teamMetrics.projectsByEmployee.entries()).map(([name, projects]) => [
35122
- name,
35123
- projects.filter((project) => !DEPRECATED_PROJECTS.has(project.name))
35124
- ])
35125
- );
35317
+ const { loadTeamBadgeCounts: loadTeamBadgeCounts2, loadTeamDetailMetrics: loadTeamDetailMetrics2 } = await Promise.resolve().then(() => (init_tui_data(), tui_data_exports));
35318
+ setBadgeInFlight(true);
35319
+ const badgeCountsPromise = loadTeamBadgeCounts2();
35320
+ const detailsPromise = loadTeamDetailMetrics2(roster.map((emp) => emp.name));
35321
+ memoryCounts = await badgeCountsPromise;
35322
+ setBadgeInFlight(false);
35323
+ const initialMembers = roster.map((emp) => {
35324
+ const agentSt = getAgentStatus(emp.name);
35325
+ return {
35326
+ name: emp.name,
35327
+ role: emp.role,
35328
+ status: agentSt.label,
35329
+ activity: agentSt.label === "active" ? "Processing..." : "",
35330
+ memoryCount: memoryCounts.get(emp.name) ?? 0,
35331
+ projects: void 0,
35332
+ currentTask: void 0,
35333
+ sessionName: agentSt.session
35334
+ };
35335
+ });
35336
+ setMembers(initialMembers);
35337
+ setDetailInFlight(true);
35338
+ const teamMetrics = await detailsPromise;
35339
+ projectsByEmployee = teamMetrics.projectsByEmployee;
35126
35340
  currentTaskByEmployee = teamMetrics.currentTaskByEmployee;
35341
+ setDetailInFlight(false);
35342
+ const finalMembers = roster.map((emp) => {
35343
+ const agentSt = getAgentStatus(emp.name);
35344
+ return {
35345
+ name: emp.name,
35346
+ role: emp.role,
35347
+ status: agentSt.label,
35348
+ activity: agentSt.label === "active" ? "Processing..." : "",
35349
+ memoryCount: memoryCounts.get(emp.name) ?? 0,
35350
+ projects: projectsByEmployee.get(emp.name),
35351
+ currentTask: currentTaskByEmployee.get(emp.name),
35352
+ sessionName: agentSt.session
35353
+ };
35354
+ });
35355
+ setMembers(finalMembers);
35356
+ setDbError(null);
35127
35357
  } catch {
35128
35358
  }
35129
- const teamData = roster.map((emp) => {
35130
- const agentSt = getAgentStatus(emp.name);
35131
- return {
35132
- name: emp.name,
35133
- role: emp.role,
35134
- status: agentSt.label,
35135
- activity: agentSt.label === "active" ? "Processing..." : "",
35136
- memoryCount: memoryCounts.get(emp.name) ?? 0,
35137
- projects: projectsByEmployee.get(emp.name),
35138
- currentTask: currentTaskByEmployee.get(emp.name),
35139
- sessionName: agentSt.session
35140
- };
35141
- });
35142
- setMembers(teamData);
35143
- setDbError(null);
35144
35359
  try {
35145
35360
  const { existsSync: existsSync44, readFileSync: readFileSync39 } = await import("fs");
35146
35361
  const { join: join2 } = await import("path");
@@ -35162,6 +35377,8 @@ function TeamView({ onBack, onViewSessions }) {
35162
35377
  setDbError(err instanceof Error ? err.message : "Unknown error");
35163
35378
  } finally {
35164
35379
  setLoading(false);
35380
+ setBadgeInFlight(false);
35381
+ setDetailInFlight(false);
35165
35382
  }
35166
35383
  });
35167
35384
  }
@@ -35216,6 +35433,8 @@ function TeamView({ onBack, onViewSessions }) {
35216
35433
  orch.pendingReviews,
35217
35434
  " review(s) pending coordinator attention"
35218
35435
  ] }),
35436
+ badgeInFlight && /* @__PURE__ */ jsx12(Text, { color: "#F5D76E", children: " Loading memory counts..." }),
35437
+ detailInFlight && /* @__PURE__ */ jsx12(Text, { color: "#6B4C9A", children: " Loading employee details..." }),
35219
35438
  /* @__PURE__ */ jsx12(Text, { children: " " }),
35220
35439
  /* @__PURE__ */ jsx12(Text, { bold: true, children: "INTERNAL" }),
35221
35440
  /* @__PURE__ */ jsx12(Text, { children: " " }),
@@ -35304,7 +35523,6 @@ function TeamView({ onBack, onViewSessions }) {
35304
35523
  }) })
35305
35524
  ] });
35306
35525
  }
35307
- var DEPRECATED_PROJECTS;
35308
35526
  var init_Team = __esm({
35309
35527
  async "src/tui/views/Team.tsx"() {
35310
35528
  "use strict";
@@ -35314,7 +35532,6 @@ var init_Team = __esm({
35314
35532
  init_demo_data();
35315
35533
  init_useOrchestrator();
35316
35534
  init_agent_status();
35317
- DEPRECATED_PROJECTS = /* @__PURE__ */ new Set(["exe-ai-employees"]);
35318
35535
  }
35319
35536
  });
35320
35537