@adhdev/daemon-core 0.9.76-rc.6 → 0.9.76-rc.61

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 (54) hide show
  1. package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -1
  2. package/dist/cli-adapters/provider-cli-runtime.d.ts +1 -0
  3. package/dist/commands/cli-manager.d.ts +17 -4
  4. package/dist/commands/mesh-coordinator.d.ts +2 -0
  5. package/dist/commands/router.d.ts +11 -0
  6. package/dist/config/mesh-config.d.ts +3 -0
  7. package/dist/git/git-types.d.ts +1 -1
  8. package/dist/git/git-worktree.d.ts +64 -0
  9. package/dist/git/index.d.ts +2 -0
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.js +1690 -447
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +1703 -478
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/mesh/coordinator-prompt.d.ts +1 -0
  16. package/dist/mesh/mesh-events.d.ts +9 -0
  17. package/dist/providers/chat-message-normalization.d.ts +40 -0
  18. package/dist/providers/cli-provider-instance.d.ts +3 -0
  19. package/dist/providers/provider-instance-manager.d.ts +1 -0
  20. package/dist/providers/provider-instance.d.ts +2 -0
  21. package/dist/repo-mesh-types.d.ts +27 -0
  22. package/dist/session-host/runtime-support.d.ts +2 -1
  23. package/dist/shared-types.d.ts +4 -0
  24. package/dist/types.d.ts +9 -0
  25. package/package.json +4 -5
  26. package/src/chat/subscription-updates.ts +3 -1
  27. package/src/cli-adapters/provider-cli-adapter.ts +28 -7
  28. package/src/cli-adapters/provider-cli-runtime.ts +3 -2
  29. package/src/commands/chat-commands.ts +126 -11
  30. package/src/commands/cli-manager.ts +78 -5
  31. package/src/commands/handler.ts +13 -4
  32. package/src/commands/mesh-coordinator.ts +148 -5
  33. package/src/commands/router.d.ts +1 -0
  34. package/src/commands/router.ts +553 -34
  35. package/src/config/mesh-config.ts +23 -2
  36. package/src/git/git-commands.ts +5 -1
  37. package/src/git/git-types.ts +1 -0
  38. package/src/git/git-worktree.ts +214 -0
  39. package/src/git/index.ts +14 -0
  40. package/src/index.ts +16 -1
  41. package/src/mesh/coordinator-prompt.ts +29 -14
  42. package/src/mesh/mesh-events.ts +109 -43
  43. package/src/providers/chat-message-normalization.ts +241 -0
  44. package/src/providers/cli-provider-instance.d.ts +2 -0
  45. package/src/providers/cli-provider-instance.ts +93 -8
  46. package/src/providers/provider-instance-manager.ts +20 -1
  47. package/src/providers/provider-instance.ts +2 -0
  48. package/src/providers/read-chat-contract.ts +8 -0
  49. package/src/repo-mesh-types.ts +30 -0
  50. package/src/session-host/runtime-support.ts +55 -7
  51. package/src/shared-types.ts +4 -0
  52. package/src/status/builders.ts +17 -12
  53. package/src/status/reporter.ts +6 -0
  54. package/src/types.ts +9 -0
package/dist/index.js CHANGED
@@ -41,11 +41,140 @@ var init_repo_mesh_types = __esm({
41
41
  requireApprovalForPush: true,
42
42
  requireApprovalForDestructiveGit: true,
43
43
  dirtyWorkspaceBehavior: "warn",
44
- maxParallelTasks: 2
44
+ maxParallelTasks: 2,
45
+ sessionCleanupOnNodeRemove: "preserve"
45
46
  };
46
47
  }
47
48
  });
48
49
 
50
+ // src/git/git-worktree.ts
51
+ var git_worktree_exports = {};
52
+ __export(git_worktree_exports, {
53
+ createWorktree: () => createWorktree,
54
+ listWorktrees: () => listWorktrees,
55
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
56
+ removeWorktree: () => removeWorktree,
57
+ resolveWorktreePath: () => resolveWorktreePath
58
+ });
59
+ function resolveWorktreePath(repoRoot, meshName, branch) {
60
+ const safeBranch = branch.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
61
+ const safeMeshName = meshName.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
62
+ const parentDir = path4.dirname(repoRoot);
63
+ return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
64
+ }
65
+ async function createWorktree(opts) {
66
+ const { repoRoot, branch, baseBranch, meshName } = opts;
67
+ const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
68
+ if ((0, import_node_fs2.existsSync)(targetDir)) {
69
+ throw new Error(`Worktree target directory already exists: ${targetDir}`);
70
+ }
71
+ await (0, import_promises3.mkdir)(path4.dirname(targetDir), { recursive: true });
72
+ const args = ["worktree", "add", targetDir, "-b", branch];
73
+ if (baseBranch) {
74
+ args.push(baseBranch);
75
+ }
76
+ try {
77
+ await execFileAsync2("git", args, {
78
+ cwd: repoRoot,
79
+ encoding: "utf8",
80
+ timeout: GIT_TIMEOUT_MS,
81
+ maxBuffer: GIT_MAX_BUFFER,
82
+ windowsHide: true
83
+ });
84
+ } catch (error) {
85
+ const stderr = typeof error.stderr === "string" ? error.stderr : "";
86
+ if (/already exists/i.test(stderr)) {
87
+ throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
88
+ }
89
+ throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
90
+ }
91
+ return {
92
+ success: true,
93
+ worktreePath: targetDir,
94
+ branch
95
+ };
96
+ }
97
+ async function removeWorktree(repoRoot, worktreePath) {
98
+ if (!(0, import_node_fs2.existsSync)(worktreePath)) {
99
+ await pruneWorktrees(repoRoot);
100
+ return { success: true, removedPath: worktreePath };
101
+ }
102
+ try {
103
+ await execFileAsync2("git", ["worktree", "remove", worktreePath, "--force"], {
104
+ cwd: repoRoot,
105
+ encoding: "utf8",
106
+ timeout: GIT_TIMEOUT_MS,
107
+ maxBuffer: GIT_MAX_BUFFER,
108
+ windowsHide: true
109
+ });
110
+ } catch (error) {
111
+ const stderr = typeof error.stderr === "string" ? error.stderr : "";
112
+ throw new Error(`git worktree remove failed: ${stderr.trim() || error.message}`);
113
+ }
114
+ return { success: true, removedPath: worktreePath };
115
+ }
116
+ async function listWorktrees(repoRoot) {
117
+ const { stdout } = await execFileAsync2("git", ["worktree", "list", "--porcelain"], {
118
+ cwd: repoRoot,
119
+ encoding: "utf8",
120
+ timeout: GIT_TIMEOUT_MS,
121
+ maxBuffer: GIT_MAX_BUFFER,
122
+ windowsHide: true
123
+ });
124
+ return parseWorktreeListOutput(stdout);
125
+ }
126
+ function parseWorktreeListOutput(output) {
127
+ const entries = [];
128
+ const blocks = output.trim().split(/\n\n+/);
129
+ for (const block of blocks) {
130
+ if (!block.trim()) continue;
131
+ const lines = block.trim().split("\n");
132
+ const entry = { path: "", head: "", branch: null, bare: false };
133
+ for (const line of lines) {
134
+ if (line.startsWith("worktree ")) {
135
+ entry.path = line.slice("worktree ".length).trim();
136
+ } else if (line.startsWith("HEAD ")) {
137
+ entry.head = line.slice("HEAD ".length).trim();
138
+ } else if (line.startsWith("branch ")) {
139
+ const ref = line.slice("branch ".length).trim();
140
+ entry.branch = ref.replace(/^refs\/heads\//, "");
141
+ } else if (line === "bare") {
142
+ entry.bare = true;
143
+ }
144
+ }
145
+ if (entry.path) {
146
+ entries.push(entry);
147
+ }
148
+ }
149
+ return entries;
150
+ }
151
+ async function pruneWorktrees(repoRoot) {
152
+ try {
153
+ await execFileAsync2("git", ["worktree", "prune"], {
154
+ cwd: repoRoot,
155
+ encoding: "utf8",
156
+ timeout: GIT_TIMEOUT_MS,
157
+ windowsHide: true
158
+ });
159
+ } catch {
160
+ }
161
+ }
162
+ var path4, import_promises3, import_node_fs2, import_node_child_process2, import_node_util2, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER;
163
+ var init_git_worktree = __esm({
164
+ "src/git/git-worktree.ts"() {
165
+ "use strict";
166
+ path4 = __toESM(require("path"));
167
+ import_promises3 = require("fs/promises");
168
+ import_node_fs2 = require("fs");
169
+ import_node_child_process2 = require("child_process");
170
+ import_node_util2 = require("util");
171
+ execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
172
+ WORKTREE_DIR_NAME = ".adhdev-worktrees";
173
+ GIT_TIMEOUT_MS = 3e4;
174
+ GIT_MAX_BUFFER = 4 * 1024 * 1024;
175
+ }
176
+ });
177
+
49
178
  // src/config/config.ts
50
179
  var config_exports = {};
51
180
  __export(config_exports, {
@@ -304,10 +433,10 @@ function getMeshConfigPath() {
304
433
  return (0, import_path2.join)(getConfigDir(), "meshes.json");
305
434
  }
306
435
  function loadMeshConfig() {
307
- const path26 = getMeshConfigPath();
308
- if (!(0, import_fs2.existsSync)(path26)) return { meshes: [] };
436
+ const path27 = getMeshConfigPath();
437
+ if (!(0, import_fs2.existsSync)(path27)) return { meshes: [] };
309
438
  try {
310
- const raw = JSON.parse((0, import_fs2.readFileSync)(path26, "utf-8"));
439
+ const raw = JSON.parse((0, import_fs2.readFileSync)(path27, "utf-8"));
311
440
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
312
441
  return raw;
313
442
  } catch {
@@ -315,16 +444,16 @@ function loadMeshConfig() {
315
444
  }
316
445
  }
317
446
  function saveMeshConfig(config) {
318
- const path26 = getMeshConfigPath();
319
- (0, import_fs2.writeFileSync)(path26, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
447
+ const path27 = getMeshConfigPath();
448
+ (0, import_fs2.writeFileSync)(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
320
449
  }
321
450
  function normalizeRepoIdentity(remoteUrl) {
322
451
  let identity = remoteUrl.trim();
323
452
  if (identity.startsWith("http://") || identity.startsWith("https://")) {
324
453
  try {
325
454
  const url = new URL(identity);
326
- const path26 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
327
- return `${url.hostname}/${path26}`;
455
+ const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
456
+ return `${url.hostname}/${path27}`;
328
457
  } catch {
329
458
  }
330
459
  }
@@ -332,6 +461,18 @@ function normalizeRepoIdentity(remoteUrl) {
332
461
  if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
333
462
  return identity;
334
463
  }
464
+ function mergeMeshPolicy(base, patch) {
465
+ const policy = { ...DEFAULT_MESH_POLICY, ...base || {}, ...patch || {} };
466
+ if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
467
+ policy.dirtyWorkspaceBehavior = "warn";
468
+ }
469
+ const maxParallelTasks = Number(policy.maxParallelTasks);
470
+ policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
471
+ if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
472
+ policy.sessionCleanupOnNodeRemove = "preserve";
473
+ }
474
+ return policy;
475
+ }
335
476
  function listMeshes() {
336
477
  return loadMeshConfig().meshes;
337
478
  }
@@ -355,7 +496,7 @@ function createMesh(opts) {
355
496
  repoIdentity,
356
497
  repoRemoteUrl: opts.repoRemoteUrl,
357
498
  defaultBranch: opts.defaultBranch,
358
- policy: { ...DEFAULT_MESH_POLICY, ...opts.policy },
499
+ policy: mergeMeshPolicy(void 0, opts.policy),
359
500
  coordinator: opts.coordinator || {},
360
501
  nodes: [],
361
502
  createdAt: now,
@@ -371,7 +512,7 @@ function updateMesh(meshId, opts) {
371
512
  if (!mesh) return void 0;
372
513
  if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
373
514
  if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
374
- if (opts.policy) mesh.policy = { ...mesh.policy, ...opts.policy };
515
+ if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
375
516
  if (opts.coordinator) mesh.coordinator = opts.coordinator;
376
517
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
377
518
  saveMeshConfig(config);
@@ -399,9 +540,12 @@ function addNode(meshId, opts) {
399
540
  id: `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
400
541
  workspace: opts.workspace.trim(),
401
542
  repoRoot: opts.repoRoot,
543
+ daemonId: opts.daemonId,
402
544
  userOverrides: opts.userOverrides || {},
403
545
  policy: opts.policy || {},
404
- isLocalWorktree: opts.isLocalWorktree
546
+ isLocalWorktree: opts.isLocalWorktree,
547
+ worktreeBranch: opts.worktreeBranch,
548
+ clonedFromNodeId: opts.clonedFromNodeId
405
549
  };
406
550
  mesh.nodes.push(node);
407
551
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -431,7 +575,7 @@ function updateNode(meshId, nodeId, opts) {
431
575
  saveMeshConfig(config);
432
576
  return node;
433
577
  }
434
- var import_fs2, import_path2, import_crypto3;
578
+ var import_fs2, import_path2, import_crypto3, SESSION_CLEANUP_MODES;
435
579
  var init_mesh_config = __esm({
436
580
  "src/config/mesh-config.ts"() {
437
581
  "use strict";
@@ -440,6 +584,7 @@ var init_mesh_config = __esm({
440
584
  import_crypto3 = require("crypto");
441
585
  init_config();
442
586
  init_repo_mesh_types();
587
+ SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
443
588
  }
444
589
  });
445
590
 
@@ -449,7 +594,7 @@ __export(coordinator_prompt_exports, {
449
594
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
450
595
  });
451
596
  function buildCoordinatorSystemPrompt(ctx) {
452
- const { mesh, status, userInstruction } = ctx;
597
+ const { mesh, status, userInstruction, coordinatorCliType } = ctx;
453
598
  const sections = [];
454
599
  sections.push(`You are a **Repo Mesh Coordinator** \u2014 a technical team lead who orchestrates work across multiple agent sessions on a shared Git repository.
455
600
 
@@ -463,15 +608,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
463
608
  } else {
464
609
  sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
465
610
  }
466
- sections.push(buildPolicySection(mesh.policy));
611
+ sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
467
612
  sections.push(TOOLS_SECTION);
468
613
  sections.push(WORKFLOW_SECTION);
469
- sections.push(RULES_SECTION);
614
+ sections.push(buildRulesSection(coordinatorCliType));
470
615
  if (userInstruction) {
471
616
  sections.push(`## Additional Context
472
617
  ${userInstruction}`);
473
618
  }
474
- if (mesh.coordinator.systemPromptSuffix) {
619
+ if (mesh.coordinator?.systemPromptSuffix) {
475
620
  sections.push(mesh.coordinator.systemPromptSuffix);
476
621
  }
477
622
  return sections.join("\n\n");
@@ -516,10 +661,29 @@ function buildPolicySection(policy) {
516
661
  return `## Policy
517
662
  ${rules.join("\n")}`;
518
663
  }
519
- var TOOLS_SECTION, WORKFLOW_SECTION, RULES_SECTION;
664
+ function buildRulesSection(coordinatorCliType) {
665
+ const coordinatorNote = coordinatorCliType ? `
666
+ - **Coordinator runtime is not a delegation default.** This coordinator is running as \`${coordinatorCliType}\`, but delegated node sessions must follow the user's requested provider, not the coordinator's own runtime.` : "";
667
+ return `## Rules
668
+
669
+ - **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
670
+ - **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
671
+ - **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
672
+ - **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
673
+ - **Don't inspect code.** Treat delegated agent summaries as self-reports, not verification. Verify side effects via \`mesh_git_status\` (including related repo freshness when configured), not by reading source files.
674
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed. Never launch a duplicate session or second worker solely because \`mesh_read_chat\` has no final assistant message while the delegated session is still showing tool/terminal activity.
675
+ - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
676
+ - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
677
+ - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
678
+ - **Never fabricate tool results.** Always call the actual tool; never pretend you did.
679
+ - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
680
+ - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
681
+ }
682
+ var TOOLS_SECTION, WORKFLOW_SECTION;
520
683
  var init_coordinator_prompt = __esm({
521
684
  "src/mesh/coordinator-prompt.ts"() {
522
685
  "use strict";
686
+ init_repo_mesh_types();
523
687
  TOOLS_SECTION = `## Available Tools
524
688
 
525
689
  | Tool | Purpose |
@@ -531,30 +695,23 @@ var init_coordinator_prompt = __esm({
531
695
  | \`mesh_read_chat\` | Read an agent's recent messages to check progress |
532
696
  | \`mesh_git_status\` | Check git status on a specific node |
533
697
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
534
- | \`mesh_approve\` | Approve/reject a pending agent action |`;
698
+ | \`mesh_approve\` | Approve/reject a pending agent action |
699
+ | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
700
+ | \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
535
701
  WORKFLOW_SECTION = `## Orchestration Workflow
536
702
 
537
703
  1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
538
704
  2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
539
705
  3. **Delegate** \u2014 For each task:
540
706
  a. Pick the best node (consider: health, dirty state, current workload).
541
- b. If no session exists, call \`mesh_launch_session\` to start one.
542
- c. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
543
- 4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
544
- 5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
707
+ b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
708
+ c. If no session exists, call \`mesh_launch_session\` to start one.
709
+ d. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
710
+ 4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly just because the delegated session has not produced a final assistant message yet; tool/terminal activity means work may still be in progress. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session; wait for the completion callback/status event instead unless you are debugging a real stall. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal, an explicit user status request, or a real timeout/stall. Handle approvals via \`mesh_approve\`.
711
+ 5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
545
712
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
546
- 7. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
547
- RULES_SECTION = `## Rules
548
-
549
- - **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
550
- - **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
551
- - **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
552
- - **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
553
- - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
554
- - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
555
- - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
556
- - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
557
- - **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
713
+ 7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
714
+ 8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
558
715
  }
559
716
  });
560
717
 
@@ -573,13 +730,13 @@ function getDaemonLogDir() {
573
730
  return LOG_DIR;
574
731
  }
575
732
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
576
- return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
733
+ return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
577
734
  }
578
735
  function checkDateRotation() {
579
736
  const today = getDateStr();
580
737
  if (today !== currentDate) {
581
738
  currentDate = today;
582
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
739
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
583
740
  cleanOldLogs();
584
741
  }
585
742
  }
@@ -593,7 +750,7 @@ function cleanOldLogs() {
593
750
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
594
751
  if (dateMatch && dateMatch[1] < cutoffStr) {
595
752
  try {
596
- fs2.unlinkSync(path9.join(LOG_DIR, file));
753
+ fs2.unlinkSync(path10.join(LOG_DIR, file));
597
754
  } catch {
598
755
  }
599
756
  }
@@ -709,17 +866,17 @@ function installGlobalInterceptor() {
709
866
  writeToFile(`Log file: ${currentLogFile}`);
710
867
  writeToFile(`Log level: ${currentLevel}`);
711
868
  }
712
- var fs2, path9, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
869
+ var fs2, path10, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
713
870
  var init_logger = __esm({
714
871
  "src/logging/logger.ts"() {
715
872
  "use strict";
716
873
  fs2 = __toESM(require("fs"));
717
- path9 = __toESM(require("path"));
874
+ path10 = __toESM(require("path"));
718
875
  os4 = __toESM(require("os"));
719
876
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
720
877
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
721
878
  currentLevel = "info";
722
- LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os4.homedir(), "Library", "Logs", "adhdev") : path9.join(os4.homedir(), ".local", "share", "adhdev", "logs");
879
+ LOG_DIR = process.platform === "win32" ? path10.join(process.env.LOCALAPPDATA || process.env.APPDATA || path10.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path10.join(os4.homedir(), "Library", "Logs", "adhdev") : path10.join(os4.homedir(), ".local", "share", "adhdev", "logs");
723
880
  MAX_LOG_SIZE = 5 * 1024 * 1024;
724
881
  MAX_LOG_DAYS = 7;
725
882
  try {
@@ -727,16 +884,16 @@ var init_logger = __esm({
727
884
  } catch {
728
885
  }
729
886
  currentDate = getDateStr();
730
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
887
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
731
888
  cleanOldLogs();
732
889
  try {
733
- const oldLog = path9.join(LOG_DIR, "daemon.log");
890
+ const oldLog = path10.join(LOG_DIR, "daemon.log");
734
891
  if (fs2.existsSync(oldLog)) {
735
892
  const stat2 = fs2.statSync(oldLog);
736
893
  const oldDate = stat2.mtime.toISOString().slice(0, 10);
737
- fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
894
+ fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
738
895
  }
739
- const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
896
+ const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
740
897
  if (fs2.existsSync(oldLogBackup)) {
741
898
  fs2.unlinkSync(oldLogBackup);
742
899
  }
@@ -768,7 +925,7 @@ var init_logger = __esm({
768
925
  }
769
926
  };
770
927
  interceptorInstalled = false;
771
- LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
928
+ LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
772
929
  }
773
930
  });
774
931
 
@@ -1236,9 +1393,9 @@ function buildCliScreenSnapshot(text) {
1236
1393
  function findBinary(name) {
1237
1394
  const trimmed = String(name || "").trim();
1238
1395
  if (!trimmed) return trimmed;
1239
- const expanded = trimmed.startsWith("~") ? path13.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1240
- if (path13.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1241
- return path13.isAbsolute(expanded) ? expanded : path13.resolve(expanded);
1396
+ const expanded = trimmed.startsWith("~") ? path14.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1397
+ if (path14.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1398
+ return path14.isAbsolute(expanded) ? expanded : path14.resolve(expanded);
1242
1399
  }
1243
1400
  const isWin = os9.platform() === "win32";
1244
1401
  try {
@@ -1254,7 +1411,7 @@ function findBinary(name) {
1254
1411
  }
1255
1412
  }
1256
1413
  function isScriptBinary(binaryPath) {
1257
- if (!path13.isAbsolute(binaryPath)) return false;
1414
+ if (!path14.isAbsolute(binaryPath)) return false;
1258
1415
  try {
1259
1416
  const fs16 = require("fs");
1260
1417
  const resolved = fs16.realpathSync(binaryPath);
@@ -1270,7 +1427,7 @@ function isScriptBinary(binaryPath) {
1270
1427
  }
1271
1428
  }
1272
1429
  function looksLikeMachOOrElf(filePath) {
1273
- if (!path13.isAbsolute(filePath)) return false;
1430
+ if (!path14.isAbsolute(filePath)) return false;
1274
1431
  try {
1275
1432
  const fs16 = require("fs");
1276
1433
  const resolved = fs16.realpathSync(filePath);
@@ -1359,12 +1516,12 @@ function normalizeCliProviderForRuntime(raw) {
1359
1516
  }
1360
1517
  };
1361
1518
  }
1362
- var os9, path13, import_child_process4, buildCliSpawnEnv;
1519
+ var os9, path14, import_child_process4, buildCliSpawnEnv;
1363
1520
  var init_provider_cli_shared = __esm({
1364
1521
  "src/cli-adapters/provider-cli-shared.ts"() {
1365
1522
  "use strict";
1366
1523
  os9 = __toESM(require("os"));
1367
- path13 = __toESM(require("path"));
1524
+ path14 = __toESM(require("path"));
1368
1525
  import_child_process4 = require("child_process");
1369
1526
  init_spawn_env();
1370
1527
  buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
@@ -1487,7 +1644,7 @@ var init_provider_cli_config = __esm({
1487
1644
 
1488
1645
  // src/cli-adapters/provider-cli-runtime.ts
1489
1646
  function resolveCliSpawnPlan(options) {
1490
- const { provider, runtimeSettings, workingDir, extraArgs } = options;
1647
+ const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
1491
1648
  const { spawn: spawnConfig } = provider;
1492
1649
  const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
1493
1650
  const binaryPath = findBinary(configuredCommand);
@@ -1495,9 +1652,9 @@ function resolveCliSpawnPlan(options) {
1495
1652
  const allArgs = [...spawnConfig.args, ...extraArgs];
1496
1653
  let shellCmd;
1497
1654
  let shellArgs;
1498
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1655
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1499
1656
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1500
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1657
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1501
1658
  const useShell = isWin ? useShellWin : useShellUnix;
1502
1659
  if (useShell) {
1503
1660
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -1511,7 +1668,7 @@ function resolveCliSpawnPlan(options) {
1511
1668
  shellCmd = binaryPath;
1512
1669
  shellArgs = allArgs;
1513
1670
  }
1514
- const env = buildCliSpawnEnv(process.env, spawnConfig.env);
1671
+ const env = buildCliSpawnEnv(process.env, { ...spawnConfig.env || {}, ...extraEnv || {} });
1515
1672
  env.TERMINAL_CWD = workingDir;
1516
1673
  return {
1517
1674
  binaryPath,
@@ -1573,12 +1730,12 @@ function respondToCliTerminalQueries(options) {
1573
1730
  }
1574
1731
  return "";
1575
1732
  }
1576
- var os10, path14, import_session_host_core2;
1733
+ var os10, path15, import_session_host_core2;
1577
1734
  var init_provider_cli_runtime = __esm({
1578
1735
  "src/cli-adapters/provider-cli-runtime.ts"() {
1579
1736
  "use strict";
1580
1737
  os10 = __toESM(require("os"));
1581
- path14 = __toESM(require("path"));
1738
+ path15 = __toESM(require("path"));
1582
1739
  import_session_host_core2 = require("@adhdev/session-host-core");
1583
1740
  init_provider_cli_shared();
1584
1741
  }
@@ -1614,8 +1771,9 @@ var init_provider_cli_adapter = __esm({
1614
1771
  init_provider_cli_runtime();
1615
1772
  init_provider_cli_shared();
1616
1773
  ProviderCliAdapter = class _ProviderCliAdapter {
1617
- constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
1774
+ constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
1618
1775
  this.extraArgs = extraArgs;
1776
+ this.extraEnv = extraEnv;
1619
1777
  this.provider = provider;
1620
1778
  this.transportFactory = transportFactory;
1621
1779
  this.cliType = provider.type;
@@ -1766,8 +1924,9 @@ var init_provider_cli_adapter = __esm({
1766
1924
  const currentSnapshot = normalizeScreenSnapshot(screenText);
1767
1925
  const lastSnapshot = this.lastScreenSnapshot;
1768
1926
  if (!lastSnapshot || lastSnapshot === currentSnapshot) return screenText;
1769
- const staleSnapshotLooksActive = /\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel/i.test(lastSnapshot);
1770
- const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:\n|\r|$)/.test(screenText) && !/\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel/i.test(screenText);
1927
+ const activeScreenPattern = /\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel|Enter to confirm\s*[·•-]\s*Esc to cancel|\b(?:MCP servers?|tool calls?)\b[^\n\r]{0,160}\brequire approval\b/i;
1928
+ const staleSnapshotLooksActive = activeScreenPattern.test(lastSnapshot);
1929
+ const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:Try\s+["“][^\n\r"”]+["”])?\s*(?:\n|\r|$)/.test(screenText) && !activeScreenPattern.test(screenText);
1771
1930
  if (staleSnapshotLooksActive && currentScreenLooksIdle) return screenText;
1772
1931
  if (currentSnapshot.length >= lastSnapshot.length) return screenText;
1773
1932
  return `${screenText}
@@ -1930,7 +2089,8 @@ ${lastSnapshot}`;
1930
2089
  provider: this.provider,
1931
2090
  runtimeSettings: this.runtimeSettings,
1932
2091
  workingDir: this.workingDir,
1933
- extraArgs: this.extraArgs
2092
+ extraArgs: this.extraArgs,
2093
+ extraEnv: this.extraEnv
1934
2094
  });
1935
2095
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1936
2096
  this.resetTraceSession();
@@ -3128,9 +3288,8 @@ ${lastSnapshot}`;
3128
3288
  };
3129
3289
  this.recordTrace("submit_echo_missing", diagnostic);
3130
3290
  if (this.requirePromptEchoBeforeSubmit) {
3131
- const message = `${this.cliName} prompt echo was not observed on the PTY screen before submit`;
3132
- LOG.warn("CLI", `[${this.cliType}] ${message} elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
3133
- completion.rejectOnce(new Error(message));
3291
+ LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending guarded submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
3292
+ this.submitSendKey(state, completion);
3134
3293
  return;
3135
3294
  }
3136
3295
  LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
@@ -3177,7 +3336,14 @@ ${lastSnapshot}`;
3177
3336
  })() : null;
3178
3337
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
3179
3338
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
3180
- throw new Error(`${this.cliName} is still processing the previous prompt`);
3339
+ const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
3340
+ const parsedHasActionableModal = Boolean(
3341
+ parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
3342
+ );
3343
+ const terminalLooksIdle = this.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && !this.hasActionableApproval() && !parsedHasActionableModal;
3344
+ if (!terminalLooksIdle) {
3345
+ throw new Error(`${this.cliName} is still processing the previous prompt`);
3346
+ }
3181
3347
  }
3182
3348
  if (this.isWaitingForResponse && !allowInputDuringGeneration) {
3183
3349
  if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
@@ -3653,6 +3819,12 @@ __export(index_exports, {
3653
3819
  AcpProviderInstance: () => AcpProviderInstance,
3654
3820
  AgentStreamPoller: () => AgentStreamPoller,
3655
3821
  BUILTIN_CHAT_MESSAGE_KINDS: () => BUILTIN_CHAT_MESSAGE_KINDS,
3822
+ CHAT_MESSAGE_ACTIVITY_SOURCES: () => CHAT_MESSAGE_ACTIVITY_SOURCES,
3823
+ CHAT_MESSAGE_AUDIENCES: () => CHAT_MESSAGE_AUDIENCES,
3824
+ CHAT_MESSAGE_INTERNAL_SOURCES: () => CHAT_MESSAGE_INTERNAL_SOURCES,
3825
+ CHAT_MESSAGE_SOURCES: () => CHAT_MESSAGE_SOURCES,
3826
+ CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES: () => CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES,
3827
+ CHAT_MESSAGE_VISIBILITIES: () => CHAT_MESSAGE_VISIBILITIES,
3656
3828
  CdpDomHandlers: () => CdpDomHandlers,
3657
3829
  CliProviderInstance: () => CliProviderInstance,
3658
3830
  DAEMON_WS_PATH: () => DAEMON_WS_PATH,
@@ -3715,6 +3887,7 @@ __export(index_exports, {
3715
3887
  buildThoughtChatMessage: () => buildThoughtChatMessage,
3716
3888
  buildToolChatMessage: () => buildToolChatMessage,
3717
3889
  buildUserChatMessage: () => buildUserChatMessage,
3890
+ classifyChatMessageVisibility: () => classifyChatMessageVisibility,
3718
3891
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
3719
3892
  clearDebugTrace: () => clearDebugTrace,
3720
3893
  compareGitSnapshots: () => compareGitSnapshots,
@@ -3727,12 +3900,17 @@ __export(index_exports, {
3727
3900
  createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
3728
3901
  createInteractionId: () => createInteractionId,
3729
3902
  createMesh: () => createMesh,
3903
+ createWorktree: () => createWorktree,
3730
3904
  deleteMesh: () => deleteMesh,
3731
3905
  detectAllVersions: () => detectAllVersions,
3732
3906
  detectCLIs: () => detectCLIs,
3733
3907
  detectIDEs: () => detectIDEs,
3734
3908
  ensureSessionHostReady: () => ensureSessionHostReady,
3735
3909
  execNpmCommandSync: () => execNpmCommandSync,
3910
+ filterActivityChatMessages: () => filterActivityChatMessages,
3911
+ filterChatMessagesByVisibility: () => filterChatMessagesByVisibility,
3912
+ filterInternalChatMessages: () => filterInternalChatMessages,
3913
+ filterUserFacingChatMessages: () => filterUserFacingChatMessages,
3736
3914
  findCdpManager: () => findCdpManager,
3737
3915
  flattenMessageParts: () => flattenMessageParts,
3738
3916
  forwardAgentStreamsToIdeInstance: () => forwardAgentStreamsToIdeInstance,
@@ -3763,22 +3941,26 @@ __export(index_exports, {
3763
3941
  initDaemonComponents: () => initDaemonComponents,
3764
3942
  installExtensions: () => installExtensions,
3765
3943
  installGlobalInterceptor: () => installGlobalInterceptor,
3944
+ isActivityChatMessage: () => isActivityChatMessage,
3766
3945
  isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
3767
3946
  isCdpConnected: () => isCdpConnected,
3768
3947
  isExtensionInstalled: () => isExtensionInstalled,
3769
3948
  isGitCommandName: () => isGitCommandName,
3770
3949
  isIdeRunning: () => isIdeRunning,
3950
+ isInternalChatMessage: () => isInternalChatMessage,
3771
3951
  isManagedStatusWaiting: () => isManagedStatusWaiting,
3772
3952
  isManagedStatusWorking: () => isManagedStatusWorking,
3773
3953
  isPathInside: () => isPathInside,
3774
3954
  isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
3775
3955
  isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
3776
3956
  isSetupComplete: () => isSetupComplete,
3957
+ isUserFacingChatMessage: () => isUserFacingChatMessage,
3777
3958
  killIdeProcess: () => killIdeProcess,
3778
3959
  launchIDE: () => launchIDE,
3779
3960
  launchWithCdp: () => launchWithCdp,
3780
3961
  listHostedCliRuntimes: () => listHostedCliRuntimes,
3781
3962
  listMeshes: () => listMeshes,
3963
+ listWorktrees: () => listWorktrees,
3782
3964
  loadConfig: () => loadConfig,
3783
3965
  loadState: () => loadState,
3784
3966
  logCommand: () => logCommand,
@@ -3798,6 +3980,7 @@ __export(index_exports, {
3798
3980
  normalizeSessionModalFields: () => normalizeSessionModalFields,
3799
3981
  parsePorcelainV2Status: () => parsePorcelainV2Status,
3800
3982
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
3983
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
3801
3984
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
3802
3985
  partitionSessionHostRecords: () => partitionSessionHostRecords,
3803
3986
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
@@ -3807,6 +3990,7 @@ __export(index_exports, {
3807
3990
  recordDebugTrace: () => recordDebugTrace,
3808
3991
  registerExtensionProviders: () => registerExtensionProviders,
3809
3992
  removeNode: () => removeNode,
3993
+ removeWorktree: () => removeWorktree,
3810
3994
  resetConfig: () => resetConfig,
3811
3995
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
3812
3996
  resetState: () => resetState,
@@ -3816,6 +4000,7 @@ __export(index_exports, {
3816
4000
  resolveGitRepository: () => resolveGitRepository,
3817
4001
  resolveSessionHostAppName: () => resolveSessionHostAppName,
3818
4002
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
4003
+ resolveWorktreePath: () => resolveWorktreePath,
3819
4004
  runAsyncBatch: () => runAsyncBatch,
3820
4005
  runGit: () => runGit,
3821
4006
  saveConfig: () => saveConfig,
@@ -4739,6 +4924,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
4739
4924
  "dirty_index_required",
4740
4925
  "conflict",
4741
4926
  "invalid_args",
4927
+ "nothing_to_commit",
4742
4928
  "git_command_failed"
4743
4929
  ]);
4744
4930
  function failure(reason, error) {
@@ -4983,7 +5169,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
4983
5169
  } catch (err) {
4984
5170
  const output = (err?.stdout || "") + (err?.stderr || "");
4985
5171
  if (/nothing to commit/i.test(output)) {
4986
- throw new GitCommandError("git_command_failed", "Nothing to commit");
5172
+ throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
5173
+ stdout: err?.stdout,
5174
+ stderr: err?.stderr
5175
+ });
4987
5176
  }
4988
5177
  throw err;
4989
5178
  }
@@ -5175,20 +5364,23 @@ var TurnSnapshotTracker = class {
5175
5364
  }
5176
5365
  };
5177
5366
 
5367
+ // src/git/index.ts
5368
+ init_git_worktree();
5369
+
5178
5370
  // src/index.ts
5179
5371
  init_config();
5180
5372
 
5181
5373
  // src/config/workspaces.ts
5182
5374
  var fs = __toESM(require("fs"));
5183
5375
  var os = __toESM(require("os"));
5184
- var path4 = __toESM(require("path"));
5376
+ var path5 = __toESM(require("path"));
5185
5377
  var import_crypto2 = require("crypto");
5186
5378
  var MAX_WORKSPACES = 50;
5187
5379
  function expandPath(p) {
5188
5380
  const t = (p || "").trim();
5189
5381
  if (!t) return "";
5190
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5191
- return path4.resolve(t);
5382
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5383
+ return path5.resolve(t);
5192
5384
  }
5193
5385
  function validateWorkspacePath(absPath) {
5194
5386
  try {
@@ -5202,7 +5394,7 @@ function validateWorkspacePath(absPath) {
5202
5394
  }
5203
5395
  }
5204
5396
  function defaultWorkspaceLabel(absPath) {
5205
- const base = path4.basename(absPath) || absPath;
5397
+ const base = path5.basename(absPath) || absPath;
5206
5398
  return base;
5207
5399
  }
5208
5400
  function getDefaultWorkspacePath(config) {
@@ -5293,9 +5485,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5293
5485
  return getDefaultWorkspacePath(config) || void 0;
5294
5486
  }
5295
5487
  function findWorkspaceByPath(config, rawPath) {
5296
- const abs = path4.resolve(expandPath(rawPath));
5488
+ const abs = path5.resolve(expandPath(rawPath));
5297
5489
  if (!abs) return void 0;
5298
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5490
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5299
5491
  }
5300
5492
  function addWorkspaceEntry(config, rawPath, label, options) {
5301
5493
  const abs = expandPath(rawPath);
@@ -5311,7 +5503,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5311
5503
  const v = validateWorkspacePath(abs);
5312
5504
  if (!v.ok) return { error: v.error };
5313
5505
  const list = [...config.workspaces || []];
5314
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5506
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5315
5507
  return { error: "Workspace already in list" };
5316
5508
  }
5317
5509
  if (list.length >= MAX_WORKSPACES) {
@@ -5345,7 +5537,7 @@ function setDefaultWorkspaceId(config, id) {
5345
5537
  }
5346
5538
 
5347
5539
  // src/config/recent-activity.ts
5348
- var path5 = __toESM(require("path"));
5540
+ var path6 = __toESM(require("path"));
5349
5541
 
5350
5542
  // src/providers/summary-metadata.ts
5351
5543
  function normalizeSummaryItem(item) {
@@ -5414,9 +5606,9 @@ var MAX_ACTIVITY = 30;
5414
5606
  function normalizeWorkspace(workspace) {
5415
5607
  if (!workspace) return "";
5416
5608
  try {
5417
- return path5.resolve(expandPath(workspace));
5609
+ return path6.resolve(expandPath(workspace));
5418
5610
  } catch {
5419
- return path5.resolve(workspace);
5611
+ return path6.resolve(workspace);
5420
5612
  }
5421
5613
  }
5422
5614
  function buildRecentActivityKey(entry) {
@@ -5584,14 +5776,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5584
5776
  }
5585
5777
 
5586
5778
  // src/config/saved-sessions.ts
5587
- var path6 = __toESM(require("path"));
5779
+ var path7 = __toESM(require("path"));
5588
5780
  var MAX_SAVED_SESSIONS = 500;
5589
5781
  function normalizeWorkspace2(workspace) {
5590
5782
  if (!workspace) return "";
5591
5783
  try {
5592
- return path6.resolve(expandPath(workspace));
5784
+ return path7.resolve(expandPath(workspace));
5593
5785
  } catch {
5594
- return path6.resolve(workspace);
5786
+ return path7.resolve(workspace);
5595
5787
  }
5596
5788
  }
5597
5789
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5770,7 +5962,7 @@ function resetState() {
5770
5962
  var import_child_process = require("child_process");
5771
5963
  var import_fs4 = require("fs");
5772
5964
  var import_os2 = require("os");
5773
- var path7 = __toESM(require("path"));
5965
+ var path8 = __toESM(require("path"));
5774
5966
  var BUILTIN_IDE_DEFINITIONS = [];
5775
5967
  var registeredIDEs = /* @__PURE__ */ new Map();
5776
5968
  function registerIDEDefinition(def) {
@@ -5789,9 +5981,9 @@ function getMergedDefinitions() {
5789
5981
  function findCliCommand(command) {
5790
5982
  const trimmed = String(command || "").trim();
5791
5983
  if (!trimmed) return null;
5792
- if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5793
- const candidate = trimmed.startsWith("~") ? path7.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5794
- const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
5984
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5985
+ const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5986
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5795
5987
  return (0, import_fs4.existsSync)(resolved) ? resolved : null;
5796
5988
  }
5797
5989
  try {
@@ -5819,7 +6011,7 @@ function getIdeVersion(cliCommand) {
5819
6011
  function checkPathExists(paths) {
5820
6012
  const home = (0, import_os2.homedir)();
5821
6013
  for (const p of paths) {
5822
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
6014
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5823
6015
  if (normalized.includes("*")) {
5824
6016
  const username = home.split(/[\\/]/).pop() || "";
5825
6017
  const resolved = normalized.replace("*", username);
@@ -5831,19 +6023,19 @@ function checkPathExists(paths) {
5831
6023
  return null;
5832
6024
  }
5833
6025
  async function detectIDEs(providerLoader) {
5834
- const os21 = (0, import_os2.platform)();
6026
+ const os22 = (0, import_os2.platform)();
5835
6027
  const results = [];
5836
6028
  for (const def of getMergedDefinitions()) {
5837
6029
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5838
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
6030
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5839
6031
  let resolvedCli = cliPath;
5840
- if (!resolvedCli && appPath && os21 === "darwin") {
6032
+ if (!resolvedCli && appPath && os22 === "darwin") {
5841
6033
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5842
6034
  if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
5843
6035
  }
5844
- if (!resolvedCli && appPath && os21 === "win32") {
5845
- const { dirname: dirname8 } = await import("path");
5846
- const appDir = dirname8(appPath);
6036
+ if (!resolvedCli && appPath && os22 === "win32") {
6037
+ const { dirname: dirname9 } = await import("path");
6038
+ const appDir = dirname9(appPath);
5847
6039
  const candidates = [
5848
6040
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5849
6041
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5858,7 +6050,7 @@ async function detectIDEs(providerLoader) {
5858
6050
  }
5859
6051
  }
5860
6052
  }
5861
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
6053
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5862
6054
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5863
6055
  results.push({
5864
6056
  id: def.id,
@@ -5877,7 +6069,7 @@ async function detectIDEs(providerLoader) {
5877
6069
  // src/detection/cli-detector.ts
5878
6070
  var import_child_process2 = require("child_process");
5879
6071
  var os2 = __toESM(require("os"));
5880
- var path8 = __toESM(require("path"));
6072
+ var path9 = __toESM(require("path"));
5881
6073
  var import_fs5 = require("fs");
5882
6074
  function parseVersion(raw) {
5883
6075
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -5890,18 +6082,18 @@ function shellQuote(value) {
5890
6082
  function expandHome(value) {
5891
6083
  const trimmed = value.trim();
5892
6084
  if (!trimmed.startsWith("~")) return trimmed;
5893
- return path8.join(os2.homedir(), trimmed.slice(1));
6085
+ return path9.join(os2.homedir(), trimmed.slice(1));
5894
6086
  }
5895
6087
  function isExplicitCommandPath(command) {
5896
6088
  const trimmed = command.trim();
5897
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
6089
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5898
6090
  }
5899
6091
  function resolveCommandPath(command) {
5900
6092
  const trimmed = command.trim();
5901
6093
  if (!trimmed) return null;
5902
6094
  if (isExplicitCommandPath(trimmed)) {
5903
6095
  const expanded = expandHome(trimmed);
5904
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
6096
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5905
6097
  return (0, import_fs5.existsSync)(candidate) ? candidate : null;
5906
6098
  }
5907
6099
  return null;
@@ -7833,6 +8025,20 @@ var StatusMonitor = class {
7833
8025
 
7834
8026
  // src/providers/chat-message-normalization.ts
7835
8027
  var BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
8028
+ var CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
8029
+ var CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
8030
+ var CHAT_MESSAGE_AUDIENCES = ["chat", "debug", "trace", "internal"];
8031
+ var CHAT_MESSAGE_SOURCES = [
8032
+ "assistant_text",
8033
+ "tool_call",
8034
+ "terminal_command",
8035
+ "runtime_activity",
8036
+ "runtime_status",
8037
+ "provider_chrome",
8038
+ "control"
8039
+ ];
8040
+ var CHAT_MESSAGE_ACTIVITY_SOURCES = ["tool_call", "terminal_command", "runtime_activity"];
8041
+ var CHAT_MESSAGE_INTERNAL_SOURCES = ["runtime_status", "provider_chrome", "control"];
7836
8042
  var KNOWN_CHAT_MESSAGE_KINDS = new Set(BUILTIN_CHAT_MESSAGE_KINDS);
7837
8043
  var CHAT_MESSAGE_KIND_ALIASES = {
7838
8044
  text: "standard",
@@ -7974,6 +8180,169 @@ function normalizeChatMessage(message) {
7974
8180
  function normalizeChatMessages(messages) {
7975
8181
  return (Array.isArray(messages) ? messages : []).map((message) => normalizeChatMessage(message));
7976
8182
  }
8183
+ function readMessageMeta(message) {
8184
+ const meta = message?.meta;
8185
+ return meta && typeof meta === "object" && !Array.isArray(meta) ? meta : null;
8186
+ }
8187
+ function readStringField(value) {
8188
+ return typeof value === "string" ? value.trim().toLowerCase() : "";
8189
+ }
8190
+ function readRecordField(message, meta, key) {
8191
+ const record = message;
8192
+ return record[key] ?? meta?.[key];
8193
+ }
8194
+ function readVisibilityField(message, meta) {
8195
+ return readStringField(readRecordField(message, meta, "visibility"));
8196
+ }
8197
+ function readTranscriptVisibilityField(message, meta) {
8198
+ const record = message;
8199
+ return readStringField(record.transcriptVisibility ?? meta?.transcriptVisibility ?? record.visibility ?? meta?.visibility);
8200
+ }
8201
+ var EXPLICIT_HIDDEN_VISIBILITIES = /* @__PURE__ */ new Set(["hidden", "debug", "internal"]);
8202
+ var EXPLICIT_VISIBLE_VISIBILITIES = /* @__PURE__ */ new Set(["visible", "user", "chat"]);
8203
+ var HIDDEN_AUDIENCES = /* @__PURE__ */ new Set(["debug", "trace", "internal"]);
8204
+ var ACTIVITY_SOURCE_SET = new Set(CHAT_MESSAGE_ACTIVITY_SOURCES);
8205
+ var INTERNAL_SOURCE_SET = new Set(CHAT_MESSAGE_INTERNAL_SOURCES);
8206
+ function hasBooleanMarker(message, meta, keys) {
8207
+ const record = message;
8208
+ return keys.some((key) => record[key] === true || meta?.[key] === true);
8209
+ }
8210
+ function isActivityKind(kind) {
8211
+ return kind === "thought" || kind === "tool" || kind === "terminal";
8212
+ }
8213
+ function isOrdinaryVisibleTurn(message, role, kind) {
8214
+ if (role === "user" || role === "human") return kind === "standard" || kind === "";
8215
+ if (role === "assistant") return kind === "standard" || kind === "";
8216
+ return false;
8217
+ }
8218
+ function classifyChatMessageVisibility(message) {
8219
+ if (!message) {
8220
+ return {
8221
+ surface: "internal",
8222
+ isUserFacing: false,
8223
+ isActivityFacing: false,
8224
+ isInternal: true,
8225
+ explicitUserFacing: false,
8226
+ explicitHidden: true,
8227
+ role: "",
8228
+ kind: "standard",
8229
+ visibility: "",
8230
+ transcriptVisibility: "",
8231
+ audience: "",
8232
+ source: ""
8233
+ };
8234
+ }
8235
+ const meta = readMessageMeta(message);
8236
+ const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
8237
+ const kind = resolveChatMessageKind(message);
8238
+ const visibility = readVisibilityField(message, meta);
8239
+ const transcriptVisibility = readTranscriptVisibilityField(message, meta);
8240
+ const audience = readStringField(readRecordField(message, meta, "audience"));
8241
+ const source = readStringField(readRecordField(message, meta, "source"));
8242
+ const explicitHidden = EXPLICIT_HIDDEN_VISIBILITIES.has(visibility) || EXPLICIT_HIDDEN_VISIBILITIES.has(transcriptVisibility) || HIDDEN_AUDIENCES.has(audience) || hasBooleanMarker(message, meta, ["internal", "isInternal", "debug", "statusOnly", "controlOnly"]);
8243
+ const explicitUserFacing = EXPLICIT_VISIBLE_VISIBILITIES.has(visibility) || EXPLICIT_VISIBLE_VISIBILITIES.has(transcriptVisibility) || audience === "chat" || hasBooleanMarker(message, meta, ["userFacing"]);
8244
+ if (explicitHidden) {
8245
+ const activityLike = isActivityKind(kind) || ACTIVITY_SOURCE_SET.has(source);
8246
+ return {
8247
+ surface: activityLike ? "activity" : "internal",
8248
+ isUserFacing: false,
8249
+ isActivityFacing: activityLike,
8250
+ isInternal: !activityLike,
8251
+ explicitUserFacing,
8252
+ explicitHidden,
8253
+ role,
8254
+ kind,
8255
+ visibility,
8256
+ transcriptVisibility,
8257
+ audience,
8258
+ source
8259
+ };
8260
+ }
8261
+ if (explicitUserFacing) {
8262
+ return {
8263
+ surface: "chat",
8264
+ isUserFacing: true,
8265
+ isActivityFacing: false,
8266
+ isInternal: false,
8267
+ explicitUserFacing,
8268
+ explicitHidden,
8269
+ role,
8270
+ kind,
8271
+ visibility,
8272
+ transcriptVisibility,
8273
+ audience,
8274
+ source
8275
+ };
8276
+ }
8277
+ if (INTERNAL_SOURCE_SET.has(source) || role === "system" || kind === "system") {
8278
+ return {
8279
+ surface: "internal",
8280
+ isUserFacing: false,
8281
+ isActivityFacing: false,
8282
+ isInternal: true,
8283
+ explicitUserFacing,
8284
+ explicitHidden,
8285
+ role,
8286
+ kind,
8287
+ visibility,
8288
+ transcriptVisibility,
8289
+ audience,
8290
+ source
8291
+ };
8292
+ }
8293
+ if (ACTIVITY_SOURCE_SET.has(source) || isActivityKind(kind)) {
8294
+ return {
8295
+ surface: "activity",
8296
+ isUserFacing: false,
8297
+ isActivityFacing: true,
8298
+ isInternal: false,
8299
+ explicitUserFacing,
8300
+ explicitHidden,
8301
+ role,
8302
+ kind,
8303
+ visibility,
8304
+ transcriptVisibility,
8305
+ audience,
8306
+ source
8307
+ };
8308
+ }
8309
+ const isUserFacing = isOrdinaryVisibleTurn(message, role, kind);
8310
+ return {
8311
+ surface: isUserFacing ? "chat" : "internal",
8312
+ isUserFacing,
8313
+ isActivityFacing: false,
8314
+ isInternal: !isUserFacing,
8315
+ explicitUserFacing,
8316
+ explicitHidden,
8317
+ role,
8318
+ kind,
8319
+ visibility,
8320
+ transcriptVisibility,
8321
+ audience,
8322
+ source
8323
+ };
8324
+ }
8325
+ function isUserFacingChatMessage(message) {
8326
+ return classifyChatMessageVisibility(message).isUserFacing;
8327
+ }
8328
+ function isActivityChatMessage(message) {
8329
+ return classifyChatMessageVisibility(message).isActivityFacing;
8330
+ }
8331
+ function isInternalChatMessage(message) {
8332
+ return classifyChatMessageVisibility(message).isInternal;
8333
+ }
8334
+ function filterUserFacingChatMessages(messages) {
8335
+ return (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
8336
+ }
8337
+ function filterActivityChatMessages(messages) {
8338
+ return (Array.isArray(messages) ? messages : []).filter((message) => isActivityChatMessage(message));
8339
+ }
8340
+ function filterInternalChatMessages(messages) {
8341
+ return (Array.isArray(messages) ? messages : []).filter((message) => isInternalChatMessage(message));
8342
+ }
8343
+ function filterChatMessagesByVisibility(messages, surface) {
8344
+ return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
8345
+ }
7977
8346
 
7978
8347
  // src/providers/control-effects.ts
7979
8348
  function extractProviderControlValues(controls, data) {
@@ -8170,9 +8539,9 @@ ${cleanBody}`;
8170
8539
 
8171
8540
  // src/config/chat-history.ts
8172
8541
  var fs3 = __toESM(require("fs"));
8173
- var path10 = __toESM(require("path"));
8542
+ var path11 = __toESM(require("path"));
8174
8543
  var os5 = __toESM(require("os"));
8175
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8544
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
8176
8545
  var RETAIN_DAYS = 30;
8177
8546
  var SAVED_HISTORY_INDEX_VERSION = 1;
8178
8547
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8335,7 +8704,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8335
8704
  function buildSavedHistoryFileSignatureMap(dir, files) {
8336
8705
  return new Map(files.map((file) => {
8337
8706
  try {
8338
- const stat2 = fs3.statSync(path10.join(dir, file));
8707
+ const stat2 = fs3.statSync(path11.join(dir, file));
8339
8708
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8340
8709
  } catch {
8341
8710
  return [file, `${file}:missing`];
@@ -8346,7 +8715,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8346
8715
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8347
8716
  }
8348
8717
  function getSavedHistoryIndexFilePath(dir) {
8349
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8718
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8350
8719
  }
8351
8720
  function getSavedHistoryIndexLockPath(dir) {
8352
8721
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8448,7 +8817,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8448
8817
  }
8449
8818
  for (const file of Array.from(currentEntries.keys())) {
8450
8819
  if (incomingFiles.has(file)) continue;
8451
- if (!fs3.existsSync(path10.join(dir, file))) {
8820
+ if (!fs3.existsSync(path11.join(dir, file))) {
8452
8821
  currentEntries.delete(file);
8453
8822
  }
8454
8823
  }
@@ -8474,7 +8843,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8474
8843
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8475
8844
  const files = listHistoryFiles(dir);
8476
8845
  for (const file of files) {
8477
- const stat2 = fs3.statSync(path10.join(dir, file));
8846
+ const stat2 = fs3.statSync(path11.join(dir, file));
8478
8847
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8479
8848
  }
8480
8849
  return false;
@@ -8484,14 +8853,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8484
8853
  }
8485
8854
  function buildSavedHistoryFileSignature(dir, file) {
8486
8855
  try {
8487
- const stat2 = fs3.statSync(path10.join(dir, file));
8856
+ const stat2 = fs3.statSync(path11.join(dir, file));
8488
8857
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8489
8858
  } catch {
8490
8859
  return `${file}:missing`;
8491
8860
  }
8492
8861
  }
8493
8862
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8494
- const filePath = path10.join(dir, file);
8863
+ const filePath = path11.join(dir, file);
8495
8864
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8496
8865
  const currentEntry = entries.get(file) || null;
8497
8866
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8564,7 +8933,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8564
8933
  function computeSavedHistoryFileSummary(dir, file) {
8565
8934
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8566
8935
  if (!historySessionId) return null;
8567
- const filePath = path10.join(dir, file);
8936
+ const filePath = path11.join(dir, file);
8568
8937
  const content = fs3.readFileSync(filePath, "utf-8");
8569
8938
  const lines = content.split("\n").filter(Boolean);
8570
8939
  let messageCount = 0;
@@ -8651,7 +9020,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8651
9020
  const summaryBySessionId = /* @__PURE__ */ new Map();
8652
9021
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8653
9022
  for (const file of files.slice().sort()) {
8654
- const filePath = path10.join(dir, file);
9023
+ const filePath = path11.join(dir, file);
8655
9024
  const signature = fileSignatures.get(file) || `${file}:missing`;
8656
9025
  const cached = savedHistoryFileSummaryCache.get(filePath);
8657
9026
  const persisted = persistedEntries.get(file);
@@ -8771,12 +9140,12 @@ var ChatHistoryWriter = class {
8771
9140
  });
8772
9141
  }
8773
9142
  if (newMessages.length === 0) return;
8774
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9143
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8775
9144
  fs3.mkdirSync(dir, { recursive: true });
8776
9145
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8777
9146
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8778
9147
  const fileName = `${filePrefix}${date}.jsonl`;
8779
- const filePath = path10.join(dir, fileName);
9148
+ const filePath = path11.join(dir, fileName);
8780
9149
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8781
9150
  fs3.appendFileSync(filePath, lines, "utf-8");
8782
9151
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8867,11 +9236,11 @@ var ChatHistoryWriter = class {
8867
9236
  const ws = String(workspace || "").trim();
8868
9237
  if (!id || !ws) return;
8869
9238
  try {
8870
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9239
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8871
9240
  fs3.mkdirSync(dir, { recursive: true });
8872
9241
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8873
9242
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8874
- const filePath = path10.join(dir, fileName);
9243
+ const filePath = path11.join(dir, fileName);
8875
9244
  const record = {
8876
9245
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8877
9246
  receivedAt: Date.now(),
@@ -8917,14 +9286,14 @@ var ChatHistoryWriter = class {
8917
9286
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8918
9287
  this.lastSeenCounts.delete(fromDedupKey);
8919
9288
  }
8920
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9289
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8921
9290
  if (!fs3.existsSync(dir)) return;
8922
9291
  const fromPrefix = `${this.sanitize(fromId)}_`;
8923
9292
  const toPrefix = `${this.sanitize(toId)}_`;
8924
9293
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8925
9294
  for (const file of files) {
8926
- const sourcePath = path10.join(dir, file);
8927
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
9295
+ const sourcePath = path11.join(dir, file);
9296
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8928
9297
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8929
9298
  const rewritten = sourceLines.map((line) => {
8930
9299
  try {
@@ -8958,13 +9327,13 @@ var ChatHistoryWriter = class {
8958
9327
  const sessionId = String(historySessionId || "").trim();
8959
9328
  if (!sessionId) return;
8960
9329
  try {
8961
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9330
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8962
9331
  if (!fs3.existsSync(dir)) return;
8963
9332
  const prefix = `${this.sanitize(sessionId)}_`;
8964
9333
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8965
9334
  const seen = /* @__PURE__ */ new Set();
8966
9335
  for (const file of files) {
8967
- const filePath = path10.join(dir, file);
9336
+ const filePath = path11.join(dir, file);
8968
9337
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8969
9338
  const next = [];
8970
9339
  for (const line of lines) {
@@ -9018,11 +9387,11 @@ var ChatHistoryWriter = class {
9018
9387
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
9019
9388
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
9020
9389
  for (const dir of agentDirs) {
9021
- const dirPath = path10.join(HISTORY_DIR, dir.name);
9390
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
9022
9391
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
9023
9392
  let removedAny = false;
9024
9393
  for (const file of files) {
9025
- const filePath = path10.join(dirPath, file);
9394
+ const filePath = path11.join(dirPath, file);
9026
9395
  const stat2 = fs3.statSync(filePath);
9027
9396
  if (stat2.mtimeMs < cutoff) {
9028
9397
  fs3.unlinkSync(filePath);
@@ -9072,13 +9441,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
9072
9441
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
9073
9442
  try {
9074
9443
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9075
- const dir = path10.join(HISTORY_DIR, sanitized);
9444
+ const dir = path11.join(HISTORY_DIR, sanitized);
9076
9445
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
9077
9446
  const files = listHistoryFiles(dir, historySessionId);
9078
9447
  const allMessages = [];
9079
9448
  const seen = /* @__PURE__ */ new Set();
9080
9449
  for (const file of files) {
9081
- const filePath = path10.join(dir, file);
9450
+ const filePath = path11.join(dir, file);
9082
9451
  const content = fs3.readFileSync(filePath, "utf-8");
9083
9452
  const lines = content.trim().split("\n").filter(Boolean);
9084
9453
  for (let i = 0; i < lines.length; i++) {
@@ -9102,7 +9471,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
9102
9471
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9103
9472
  try {
9104
9473
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9105
- const dir = path10.join(HISTORY_DIR, sanitized);
9474
+ const dir = path11.join(HISTORY_DIR, sanitized);
9106
9475
  if (!fs3.existsSync(dir)) {
9107
9476
  savedHistorySessionCache.delete(sanitized);
9108
9477
  return { sessions: [], hasMore: false };
@@ -9163,11 +9532,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9163
9532
  }
9164
9533
  function readExistingSessionStartRecord(agentType, historySessionId) {
9165
9534
  try {
9166
- const dir = path10.join(HISTORY_DIR, agentType);
9535
+ const dir = path11.join(HISTORY_DIR, agentType);
9167
9536
  if (!fs3.existsSync(dir)) return null;
9168
9537
  const files = listHistoryFiles(dir, historySessionId).sort();
9169
9538
  for (const file of files) {
9170
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9539
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
9171
9540
  for (const line of lines) {
9172
9541
  try {
9173
9542
  const parsed = JSON.parse(line);
@@ -9187,16 +9556,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
9187
9556
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
9188
9557
  if (records.length === 0) return false;
9189
9558
  try {
9190
- const dir = path10.join(HISTORY_DIR, agentType);
9559
+ const dir = path11.join(HISTORY_DIR, agentType);
9191
9560
  fs3.mkdirSync(dir, { recursive: true });
9192
9561
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9193
9562
  for (const file of fs3.readdirSync(dir)) {
9194
9563
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9195
- fs3.unlinkSync(path10.join(dir, file));
9564
+ fs3.unlinkSync(path11.join(dir, file));
9196
9565
  }
9197
9566
  }
9198
9567
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9199
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9568
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9200
9569
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9201
9570
  `, "utf-8");
9202
9571
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -9946,6 +10315,14 @@ function validateMessage(message, source, index) {
9946
10315
  if (typeof message.senderName === "string") normalized.senderName = message.senderName;
9947
10316
  if (typeof message._type === "string") normalized._type = message._type;
9948
10317
  if (typeof message._sub === "string") normalized._sub = message._sub;
10318
+ if (typeof message.visibility === "string") normalized.visibility = message.visibility;
10319
+ if (typeof message.transcriptVisibility === "string") normalized.transcriptVisibility = message.transcriptVisibility;
10320
+ if (typeof message.audience === "string") normalized.audience = message.audience;
10321
+ if (typeof message.source === "string") normalized.source = message.source;
10322
+ if (typeof message.userFacing === "boolean") normalized.userFacing = message.userFacing;
10323
+ if (typeof message.internal === "boolean") normalized.internal = message.internal;
10324
+ if (typeof message.isInternal === "boolean") normalized.isInternal = message.isInternal;
10325
+ if (typeof message.debug === "boolean") normalized.debug = message.debug;
9949
10326
  return normalized;
9950
10327
  }
9951
10328
  function validateModal(activeModal, status, source) {
@@ -11191,6 +11568,14 @@ function getActiveChatOptions(profile) {
11191
11568
  if (profile === "full") return {};
11192
11569
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11193
11570
  }
11571
+ function resolveSessionStatus(activeChat, providerStatus) {
11572
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11573
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11574
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11575
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11576
+ if (topLevelStatus !== "idle") return topLevelStatus;
11577
+ return chatStatus;
11578
+ }
11194
11579
  function shouldIncludeSessionControls(profile) {
11195
11580
  return profile !== "live";
11196
11581
  }
@@ -11269,9 +11654,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11269
11654
  providerName: state.name,
11270
11655
  kind: "workspace",
11271
11656
  transport: "cdp-page",
11272
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11273
- activeModal: activeChat?.activeModal || null
11274
- }),
11657
+ status: resolveSessionStatus(activeChat, state.status),
11275
11658
  title,
11276
11659
  workspace,
11277
11660
  ...git && { git },
@@ -11306,9 +11689,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11306
11689
  providerSessionId: ext.providerSessionId,
11307
11690
  kind: "agent",
11308
11691
  transport: "cdp-webview",
11309
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11310
- activeModal: activeChat?.activeModal || null
11311
- }),
11692
+ status: resolveSessionStatus(activeChat, ext.status),
11312
11693
  title: activeChat?.title || ext.name,
11313
11694
  workspace,
11314
11695
  ...git && { git },
@@ -11358,9 +11739,7 @@ function buildCliSession(state, options) {
11358
11739
  providerSessionId: state.providerSessionId,
11359
11740
  kind: "agent",
11360
11741
  transport: "pty",
11361
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11362
- activeModal: activeChat?.activeModal || null
11363
- }),
11742
+ status: resolveSessionStatus(activeChat, state.status),
11364
11743
  title: activeChat?.title || state.name,
11365
11744
  workspace,
11366
11745
  ...git && { git },
@@ -11408,9 +11787,7 @@ function buildAcpSession(state, options) {
11408
11787
  providerName: state.name,
11409
11788
  kind: "agent",
11410
11789
  transport: "acp",
11411
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11412
- activeModal: activeChat?.activeModal || null
11413
- }),
11790
+ status: resolveSessionStatus(activeChat, state.status),
11414
11791
  title: activeChat?.title || state.name,
11415
11792
  workspace,
11416
11793
  ...git && { git },
@@ -11533,7 +11910,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11533
11910
  // src/commands/chat-commands.ts
11534
11911
  var fs4 = __toESM(require("fs"));
11535
11912
  var os6 = __toESM(require("os"));
11536
- var path11 = __toESM(require("path"));
11913
+ var path12 = __toESM(require("path"));
11537
11914
  var import_node_crypto = require("crypto");
11538
11915
 
11539
11916
  // src/providers/provider-input-support.ts
@@ -11736,6 +12113,7 @@ function buildSessionModalDeliverySignature(payload) {
11736
12113
  // src/commands/chat-commands.ts
11737
12114
  var RECENT_SEND_WINDOW_MS = 1200;
11738
12115
  var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
12116
+ var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
11739
12117
  var recentSendByTarget = /* @__PURE__ */ new Map();
11740
12118
  function getCurrentProviderType(h, fallback = "") {
11741
12119
  return h.currentSession?.providerType || h.currentProviderType || fallback;
@@ -11788,6 +12166,16 @@ function buildSendInputSignature(input) {
11788
12166
  function getSendChatInputEnvelope(args) {
11789
12167
  return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
11790
12168
  }
12169
+ function sleep(ms) {
12170
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
12171
+ }
12172
+ async function waitOnceForFreshHermesCliStart(adapter, log) {
12173
+ if (adapter.cliType !== "hermes-cli") return;
12174
+ const status = typeof adapter.getStatus === "function" ? adapter.getStatus()?.status : void 0;
12175
+ if (status !== "starting") return;
12176
+ log(`Hermes CLI is still starting; waiting ${HERMES_CLI_STARTING_SEND_SETTLE_MS}ms before first send`);
12177
+ await sleep(HERMES_CLI_STARTING_SEND_SETTLE_MS);
12178
+ }
11791
12179
  function getHistorySessionId(h, args) {
11792
12180
  const explicit = typeof args?.historySessionId === "string" ? args.historySessionId.trim() : "";
11793
12181
  if (explicit) return explicit;
@@ -11842,7 +12230,7 @@ function normalizeReadChatTailLimit(args) {
11842
12230
  }
11843
12231
  function normalizeReadChatMessages(payload) {
11844
12232
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
11845
- return messages;
12233
+ return normalizeChatMessages(messages);
11846
12234
  }
11847
12235
  function deriveHistoryDedupKey(message) {
11848
12236
  const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
@@ -11896,6 +12284,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11896
12284
  return raw;
11897
12285
  }
11898
12286
  }
12287
+ function isGeneratingLikeStatus(status) {
12288
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
12289
+ }
12290
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12291
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
12292
+ if (hasNonEmptyModalButtons(activeModal)) return false;
12293
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
12294
+ if (adapterRawStatus !== "idle") return false;
12295
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
12296
+ return true;
12297
+ }
12298
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12299
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
12300
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
12301
+ }
12302
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
12303
+ if (status !== "idle") return messages;
12304
+ return messages.map((message) => {
12305
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
12306
+ const hasStreamingMeta = meta?.streaming === true;
12307
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
12308
+ return {
12309
+ ...message,
12310
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
12311
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
12312
+ };
12313
+ });
12314
+ }
11899
12315
  function buildReadChatCommandResult(payload, args) {
11900
12316
  let validatedPayload;
11901
12317
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -11908,13 +12324,22 @@ function buildReadChatCommandResult(payload, args) {
11908
12324
  return { success: false, error: error?.message || String(error) };
11909
12325
  }
11910
12326
  const messages = normalizeReadChatMessages(validatedPayload);
11911
- const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
12327
+ const visibleMessages = filterUserFacingChatMessages(messages);
12328
+ const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
12329
+ const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
12330
+ const returnedDebugReadChat = debugReadChat ? {
12331
+ ...debugReadChat,
12332
+ fullMsgCount: typeof debugReadChat.fullMsgCount === "number" ? debugReadChat.fullMsgCount : messages.length,
12333
+ visibleMsgCount: visibleMessages.length,
12334
+ hiddenMsgCount,
12335
+ returnedMsgCount: sync.messages.length
12336
+ } : void 0;
11912
12337
  return {
11913
12338
  success: true,
11914
12339
  ...validatedPayload,
11915
12340
  messages: sync.messages,
11916
12341
  totalMessages: sync.totalMessages,
11917
- ...debugReadChat ? { debugReadChat } : {}
12342
+ ...returnedDebugReadChat ? { debugReadChat: returnedDebugReadChat } : {}
11918
12343
  };
11919
12344
  }
11920
12345
  var DEFAULT_DEBUG_SANITIZE_OPTIONS = {
@@ -12044,7 +12469,7 @@ function buildDebugBundleText(bundle) {
12044
12469
  }
12045
12470
  function getChatDebugBundleDir() {
12046
12471
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
12047
- return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12472
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12048
12473
  }
12049
12474
  function safeBundleIdSegment(value, fallback) {
12050
12475
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -12060,6 +12485,14 @@ function buildChatDebugBundleSummary(bundle) {
12060
12485
  const readChat = bundle.readChat && typeof bundle.readChat === "object" ? bundle.readChat : {};
12061
12486
  const cli = bundle.cli && typeof bundle.cli === "object" ? bundle.cli : null;
12062
12487
  const frontend = bundle.frontend && typeof bundle.frontend === "object" ? bundle.frontend : null;
12488
+ const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === "object" ? readChat.debugReadChat : {};
12489
+ const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === "object" ? cli.parsedStatus : null;
12490
+ const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : void 0;
12491
+ const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : void 0;
12492
+ const cliPartialResponse = typeof cli?.partialResponse === "string" ? cli.partialResponse : "";
12493
+ const readChatStatus = typeof readChat.status === "string" ? readChat.status : "";
12494
+ const cliStatus = typeof cli?.status === "string" ? cli.status : "";
12495
+ const cliParsedStatus = typeof parsedStatus?.status === "string" ? parsedStatus.status : "";
12063
12496
  return {
12064
12497
  createdAt: bundle.createdAt,
12065
12498
  targetSessionId: target.targetSessionId,
@@ -12068,8 +12501,22 @@ function buildChatDebugBundleSummary(bundle) {
12068
12501
  readChatSuccess: readChat.success,
12069
12502
  readChatStatus: readChat.status,
12070
12503
  readChatTotalMessages: readChat.totalMessages,
12504
+ readChatReturnedMessages,
12071
12505
  cliStatus: cli?.status,
12506
+ cliParsedStatus: cliParsedStatus || void 0,
12072
12507
  cliMessageCount: cli?.messageCount,
12508
+ cliParsedMessageCount,
12509
+ cliPartialResponseChars: cliPartialResponse.length,
12510
+ parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
12511
+ parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
12512
+ readChatDebug: Object.keys(debugReadChat).length ? {
12513
+ adapterStatus: debugReadChat.adapterStatus,
12514
+ parsedStatus: debugReadChat.parsedStatus,
12515
+ returnedStatus: debugReadChat.returnedStatus,
12516
+ parsedMsgCount: debugReadChat.parsedMsgCount,
12517
+ returnedMsgCount: debugReadChat.returnedMsgCount,
12518
+ shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages
12519
+ } : void 0,
12073
12520
  hasFrontendSnapshot: !!frontend
12074
12521
  };
12075
12522
  }
@@ -12077,7 +12524,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
12077
12524
  const bundleId = createChatDebugBundleId(targetSessionId);
12078
12525
  const dir = getChatDebugBundleDir();
12079
12526
  fs4.mkdirSync(dir, { recursive: true });
12080
- const savedPath = path11.join(dir, `${bundleId}.json`);
12527
+ const savedPath = path12.join(dir, `${bundleId}.json`);
12081
12528
  const json = `${JSON.stringify(bundle, null, 2)}
12082
12529
  `;
12083
12530
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12307,7 +12754,7 @@ async function handleChatHistory(h, args) {
12307
12754
  }
12308
12755
  }
12309
12756
  async function handleReadChat(h, args) {
12310
- const provider = h.getProvider(args?.agentType);
12757
+ const provider = h.getProvider(args?.agentType || args?.providerType);
12311
12758
  const transport = getTargetTransport(h, provider);
12312
12759
  const historySessionId = getHistorySessionId(h, args);
12313
12760
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
@@ -12334,10 +12781,13 @@ async function handleReadChat(h, args) {
12334
12781
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12335
12782
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12336
12783
  const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
12337
- const returnedStatus = parsedRecord.status || "idle";
12338
- LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length}`);
12784
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12785
+ const runtimeMessageMerger = getTargetInstance(h, args);
12786
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12787
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12788
+ LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length} returnedMsgCount=${returnedMessages.length}`);
12339
12789
  return buildReadChatCommandResult({
12340
- messages: parsedRecord.messages,
12790
+ messages: returnedMessages,
12341
12791
  status: returnedStatus,
12342
12792
  activeModal,
12343
12793
  debugReadChat: {
@@ -12348,7 +12798,7 @@ async function handleReadChat(h, args) {
12348
12798
  returnedStatus: String(returnedStatus || ""),
12349
12799
  shouldPreferAdapterMessages: false,
12350
12800
  parsedMsgCount: parsedRecord.messages.length,
12351
- returnedMsgCount: parsedRecord.messages.length
12801
+ returnedMsgCount: returnedMessages.length
12352
12802
  },
12353
12803
  ...title ? { title } : {},
12354
12804
  ...providerSessionId ? { providerSessionId } : {},
@@ -12594,6 +13044,7 @@ async function handleSendChat(h, args) {
12594
13044
  try {
12595
13045
  assertTextOnlyInput(provider, input);
12596
13046
  if (!text) return { success: false, error: "text required for PTY send" };
13047
+ await waitOnceForFreshHermesCliStart(adapter, _log);
12597
13048
  await adapter.sendMessage(text);
12598
13049
  return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
12599
13050
  } catch (e) {
@@ -13093,9 +13544,17 @@ async function handleResolveAction(h, args) {
13093
13544
  const targetState = targetInstance?.getState?.();
13094
13545
  const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons) && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? targetState.activeChat.activeModal : null;
13095
13546
  const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons) && status.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? status.activeModal : null;
13096
- const effectiveModal = statusModal || surfacedModal;
13097
- const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
13098
- LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
13547
+ const parsedStatus = !statusModal && !surfacedModal && typeof adapter.getScriptParsedStatus === "function" ? (() => {
13548
+ try {
13549
+ return parseMaybeJson(adapter.getScriptParsedStatus());
13550
+ } catch {
13551
+ return null;
13552
+ }
13553
+ })() : null;
13554
+ const parsedModal = parsedStatus?.status === "waiting_approval" && parsedStatus?.activeModal && Array.isArray(parsedStatus.activeModal.buttons) && parsedStatus.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? parsedStatus.activeModal : null;
13555
+ const effectiveModal = statusModal || surfacedModal || parsedModal;
13556
+ const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" || parsedStatus?.status === "waiting_approval" ? "waiting_approval" : status?.status;
13557
+ LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} parsedModal=${parsedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
13099
13558
  if (!effectiveModal) {
13100
13559
  return { success: false, error: "Not in approval state" };
13101
13560
  }
@@ -13221,7 +13680,7 @@ async function handleResolveAction(h, args) {
13221
13680
 
13222
13681
  // src/commands/cdp-commands.ts
13223
13682
  var fs5 = __toESM(require("fs"));
13224
- var path12 = __toESM(require("path"));
13683
+ var path13 = __toESM(require("path"));
13225
13684
  var os7 = __toESM(require("os"));
13226
13685
  var KEY_TO_VK = {
13227
13686
  Backspace: 8,
@@ -13478,25 +13937,25 @@ function resolveSafePath(requestedPath) {
13478
13937
  const inputPath = rawPath || ".";
13479
13938
  const home = os7.homedir();
13480
13939
  if (inputPath.startsWith("~")) {
13481
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13940
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13482
13941
  }
13483
13942
  if (process.platform === "win32") {
13484
13943
  const normalized = normalizeWindowsRequestedPath(inputPath);
13485
- if (path12.win32.isAbsolute(normalized)) {
13486
- return path12.win32.normalize(normalized);
13944
+ if (path13.win32.isAbsolute(normalized)) {
13945
+ return path13.win32.normalize(normalized);
13487
13946
  }
13488
- return path12.win32.resolve(normalized);
13947
+ return path13.win32.resolve(normalized);
13489
13948
  }
13490
- if (path12.isAbsolute(inputPath)) {
13491
- return path12.normalize(inputPath);
13949
+ if (path13.isAbsolute(inputPath)) {
13950
+ return path13.normalize(inputPath);
13492
13951
  }
13493
- return path12.resolve(inputPath);
13952
+ return path13.resolve(inputPath);
13494
13953
  }
13495
13954
  function listDirectoryEntriesSafe(dirPath) {
13496
13955
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13497
13956
  const files = [];
13498
13957
  for (const entry of entries) {
13499
- const entryPath = path12.join(dirPath, entry.name);
13958
+ const entryPath = path13.join(dirPath, entry.name);
13500
13959
  try {
13501
13960
  if (entry.isDirectory()) {
13502
13961
  files.push({ name: entry.name, type: "directory" });
@@ -13550,7 +14009,7 @@ async function handleFileRead(h, args) {
13550
14009
  async function handleFileWrite(h, args) {
13551
14010
  try {
13552
14011
  const filePath = resolveSafePath(args?.path);
13553
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
14012
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13554
14013
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13555
14014
  return { success: true, path: filePath };
13556
14015
  } catch (e) {
@@ -14334,9 +14793,11 @@ var DaemonCommandHandler = class {
14334
14793
  }
14335
14794
  const sessionLookupFailed = !!targetSessionId && !session;
14336
14795
  const managerKey = this.extractIdeType(args, sessionLookupFailed);
14337
- let providerType;
14796
+ let providerType = args?.agentType || args?.providerType;
14338
14797
  if (!sessionLookupFailed) {
14339
- providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
14798
+ providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
14799
+ } else if (!providerType) {
14800
+ providerType = this.inferProviderType(managerKey);
14340
14801
  }
14341
14802
  return { session, managerKey, providerType, sessionLookupFailed };
14342
14803
  }
@@ -14416,7 +14877,8 @@ var DaemonCommandHandler = class {
14416
14877
  "pty_resize",
14417
14878
  "invoke_provider_script"
14418
14879
  ]);
14419
- if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
14880
+ const allowsInactiveReadChatFallback = cmd === "read_chat" && !!this._currentRoute.providerType && (typeof args?.providerSessionId === "string" && args.providerSessionId.trim().length > 0 || typeof args?.historySessionId === "string" && args.historySessionId.trim().length > 0);
14881
+ if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
14420
14882
  const result2 = {
14421
14883
  success: false,
14422
14884
  error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
@@ -14669,7 +15131,7 @@ var DaemonCommandHandler = class {
14669
15131
 
14670
15132
  // src/commands/cli-manager.ts
14671
15133
  var os13 = __toESM(require("os"));
14672
- var path16 = __toESM(require("path"));
15134
+ var path17 = __toESM(require("path"));
14673
15135
  var crypto4 = __toESM(require("crypto"));
14674
15136
  var import_fs6 = require("fs");
14675
15137
  var import_child_process6 = require("child_process");
@@ -14679,7 +15141,7 @@ init_config();
14679
15141
 
14680
15142
  // src/providers/cli-provider-instance.ts
14681
15143
  var os12 = __toESM(require("os"));
14682
- var path15 = __toESM(require("path"));
15144
+ var path16 = __toESM(require("path"));
14683
15145
  var crypto3 = __toESM(require("crypto"));
14684
15146
  var fs6 = __toESM(require("fs"));
14685
15147
  var import_node_module = require("module");
@@ -14738,7 +15200,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14738
15200
  var CachedDatabaseSync = null;
14739
15201
  function getDatabaseSync() {
14740
15202
  if (CachedDatabaseSync) return CachedDatabaseSync;
14741
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
15203
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14742
15204
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14743
15205
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14744
15206
  if (!CachedDatabaseSync) {
@@ -14791,7 +15253,7 @@ var CliProviderInstance = class {
14791
15253
  this.providerSessionId = options?.providerSessionId;
14792
15254
  this.launchMode = options?.launchMode || "new";
14793
15255
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14794
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
15256
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14795
15257
  this.monitor = new StatusMonitor();
14796
15258
  this.historyWriter = new ChatHistoryWriter();
14797
15259
  }
@@ -15268,7 +15730,19 @@ var CliProviderInstance = class {
15268
15730
  }
15269
15731
  }
15270
15732
  pushEvent(event) {
15271
- this.events.push(event);
15733
+ const enrichedEvent = {
15734
+ ...event,
15735
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
15736
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
15737
+ providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
15738
+ workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
15739
+ providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
15740
+ };
15741
+ if (this.context?.emitProviderEvent) {
15742
+ this.context.emitProviderEvent(enrichedEvent);
15743
+ return;
15744
+ }
15745
+ this.events.push(enrichedEvent);
15272
15746
  }
15273
15747
  flushEvents() {
15274
15748
  const events = [...this.events];
@@ -15475,12 +15949,59 @@ ${effect.notification.body || ""}`.trim();
15475
15949
  );
15476
15950
  }
15477
15951
  }
15952
+ mergeRuntimeChatMessages(parsedMessages) {
15953
+ return this.mergeConversationMessages(parsedMessages);
15954
+ }
15478
15955
  mergeConversationMessages(parsedMessages) {
15479
15956
  if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
15480
- return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
15481
- const aTime = a.message.receivedAt || a.message.timestamp || 0;
15482
- const bTime = b.message.receivedAt || b.message.timestamp || 0;
15483
- if (aTime !== bTime) return aTime - bTime;
15957
+ const parsedEntries = parsedMessages.map((message, index) => ({
15958
+ message,
15959
+ index,
15960
+ source: "parsed"
15961
+ }));
15962
+ const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
15963
+ message: entry.message,
15964
+ index: parsedMessages.length + index,
15965
+ source: "runtime",
15966
+ runtimeKey: entry.key
15967
+ }));
15968
+ const getTime = (message) => {
15969
+ const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
15970
+ return Number.isFinite(value) && value > 0 ? value : 0;
15971
+ };
15972
+ const getRole = (message) => typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
15973
+ const isRuntimeOverlay = (entry) => {
15974
+ if (entry.source !== "runtime") return false;
15975
+ const key = typeof entry.runtimeKey === "string" ? entry.runtimeKey.trim().toLowerCase() : "";
15976
+ if (key.startsWith("auto_approval:")) return true;
15977
+ return !isUserFacingChatMessage(entry.message);
15978
+ };
15979
+ const shouldKeepParsedBeforeUntimedRuntime = (message) => {
15980
+ const role = getRole(message);
15981
+ return role === "user" || role === "human";
15982
+ };
15983
+ const shouldKeepParsedAfterUntimedRuntime = (message) => {
15984
+ const role = getRole(message);
15985
+ if (role !== "assistant") return false;
15986
+ const kind = resolveChatMessageKind(message);
15987
+ return kind === "standard" || kind === "terminal";
15988
+ };
15989
+ return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
15990
+ const aTime = getTime(a.message);
15991
+ const bTime = getTime(b.message);
15992
+ if (aTime && bTime && aTime !== bTime) return aTime - bTime;
15993
+ if (a.source !== b.source && aTime !== bTime) {
15994
+ const parsedEntry = a.source === "parsed" ? a : b.source === "parsed" ? b : null;
15995
+ const runtimeEntry = a.source === "runtime" ? a : b.source === "runtime" ? b : null;
15996
+ if (parsedEntry && runtimeEntry && isRuntimeOverlay(runtimeEntry) && getTime(parsedEntry.message) === 0 && getTime(runtimeEntry.message) > 0) {
15997
+ if (shouldKeepParsedBeforeUntimedRuntime(parsedEntry.message)) {
15998
+ return a.source === "parsed" ? -1 : 1;
15999
+ }
16000
+ if (shouldKeepParsedAfterUntimedRuntime(parsedEntry.message)) {
16001
+ return a.source === "parsed" ? 1 : -1;
16002
+ }
16003
+ }
16004
+ }
15484
16005
  return a.index - b.index;
15485
16006
  }).map((entry) => entry.message));
15486
16007
  }
@@ -16804,11 +17325,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16804
17325
  // src/commands/cli-manager.ts
16805
17326
  function isExplicitCommand(command) {
16806
17327
  const trimmed = command.trim();
16807
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17328
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16808
17329
  }
16809
17330
  function expandExecutable(command) {
16810
17331
  const trimmed = command.trim();
16811
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17332
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16812
17333
  }
16813
17334
  function commandExists(command) {
16814
17335
  const trimmed = command.trim();
@@ -16832,6 +17353,35 @@ function colorize(color, text) {
16832
17353
  const fn = chalkApi?.[color];
16833
17354
  return typeof fn === "function" ? fn(text) : text;
16834
17355
  }
17356
+ var COORDINATOR_DELEGATED_ENV_UNSETS = {
17357
+ ADHDEV_INLINE_MESH: "",
17358
+ ADHDEV_MCP_TRANSPORT: "",
17359
+ ADHDEV_MESH_ID: "",
17360
+ HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
17361
+ };
17362
+ function hasCliArg(args, flag) {
17363
+ return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
17364
+ }
17365
+ function ensureEmptyDelegatedMcpConfig(workspace) {
17366
+ const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
17367
+ (0, import_fs6.mkdirSync)(baseDir, { recursive: true });
17368
+ const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
17369
+ const filePath = path17.join(baseDir, `${workspaceHash}.json`);
17370
+ (0, import_fs6.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
17371
+ return filePath;
17372
+ }
17373
+ function buildCoordinatorDelegatedCliLaunchOptions(input) {
17374
+ const cliType = String(input.cliType || "").trim();
17375
+ const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
17376
+ const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
17377
+ if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
17378
+ cliArgs.unshift("--ignore-user-config");
17379
+ }
17380
+ if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
17381
+ cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
17382
+ }
17383
+ return { cliArgs, env };
17384
+ }
16835
17385
  function isUuid(value) {
16836
17386
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
16837
17387
  }
@@ -17002,7 +17552,7 @@ var DaemonCliManager = class {
17002
17552
  attachExisting
17003
17553
  }) || void 0;
17004
17554
  }
17005
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17555
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
17006
17556
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17007
17557
  const provider = this.providerLoader.getMeta(normalizedType);
17008
17558
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -17016,7 +17566,7 @@ var DaemonCliManager = class {
17016
17566
  providerSessionId,
17017
17567
  attachExisting
17018
17568
  );
17019
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17569
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
17020
17570
  }
17021
17571
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
17022
17572
  }
@@ -17089,7 +17639,7 @@ var DaemonCliManager = class {
17089
17639
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
17090
17640
  const trimmed = (workingDir || "").trim();
17091
17641
  if (!trimmed) throw new Error("working directory required");
17092
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17642
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
17093
17643
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17094
17644
  const rawProvider = this.providerLoader.getByAlias(cliType);
17095
17645
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17219,6 +17769,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17219
17769
  {
17220
17770
  providerSessionId: sessionBinding.providerSessionId,
17221
17771
  launchMode: sessionBinding.launchMode,
17772
+ extraEnv: options?.extraEnv,
17222
17773
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17223
17774
  this.persistRecentActivity({
17224
17775
  kind: "cli",
@@ -17239,7 +17790,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17239
17790
  resolvedCliArgs,
17240
17791
  key,
17241
17792
  sessionBinding.providerSessionId,
17242
- false
17793
+ false,
17794
+ options?.extraEnv
17243
17795
  );
17244
17796
  try {
17245
17797
  await adapter.spawn();
@@ -17463,12 +18015,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
17463
18015
  const dir = resolved.path;
17464
18016
  const launchSource = resolved.source;
17465
18017
  if (!cliType) throw new Error("cliType required");
18018
+ const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
18019
+ const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
18020
+ cliType,
18021
+ workspace: dir,
18022
+ cliArgs: args?.cliArgs,
18023
+ env: args?.env
18024
+ }) : null;
17466
18025
  const started = await this.startSession(
17467
18026
  cliType,
17468
18027
  dir,
17469
- args?.cliArgs,
18028
+ delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
17470
18029
  args?.initialModel,
17471
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
18030
+ {
18031
+ resumeSessionId: args?.resumeSessionId,
18032
+ settingsOverride,
18033
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
18034
+ }
17472
18035
  );
17473
18036
  return {
17474
18037
  success: true,
@@ -17590,11 +18153,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17590
18153
  var import_child_process7 = require("child_process");
17591
18154
  var net = __toESM(require("net"));
17592
18155
  var os15 = __toESM(require("os"));
17593
- var path18 = __toESM(require("path"));
18156
+ var path19 = __toESM(require("path"));
17594
18157
 
17595
18158
  // src/providers/provider-loader.ts
17596
18159
  var fs7 = __toESM(require("fs"));
17597
- var path17 = __toESM(require("path"));
18160
+ var path18 = __toESM(require("path"));
17598
18161
  var os14 = __toESM(require("os"));
17599
18162
  var chokidar = __toESM(require("chokidar"));
17600
18163
  init_logger();
@@ -17918,7 +18481,7 @@ var ProviderLoader = class _ProviderLoader {
17918
18481
  try {
17919
18482
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17920
18483
  return ["ide", "extension", "cli", "acp"].some(
17921
- (category) => fs7.existsSync(path17.join(candidate, category))
18484
+ (category) => fs7.existsSync(path18.join(candidate, category))
17922
18485
  );
17923
18486
  } catch {
17924
18487
  return false;
@@ -17926,20 +18489,20 @@ var ProviderLoader = class _ProviderLoader {
17926
18489
  }
17927
18490
  static hasProviderRootMarker(candidate) {
17928
18491
  try {
17929
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18492
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17930
18493
  } catch {
17931
18494
  return false;
17932
18495
  }
17933
18496
  }
17934
18497
  detectDefaultUserDir() {
17935
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
18498
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17936
18499
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17937
18500
  const visited = /* @__PURE__ */ new Set();
17938
18501
  for (const start of this.probeStarts) {
17939
- let current = path17.resolve(start);
18502
+ let current = path18.resolve(start);
17940
18503
  while (!visited.has(current)) {
17941
18504
  visited.add(current);
17942
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18505
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17943
18506
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17944
18507
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17945
18508
  if (envOptIn || hasMarker) {
@@ -17961,7 +18524,7 @@ var ProviderLoader = class _ProviderLoader {
17961
18524
  return { path: siblingCandidate, source };
17962
18525
  }
17963
18526
  }
17964
- const parent = path17.dirname(current);
18527
+ const parent = path18.dirname(current);
17965
18528
  if (parent === current) break;
17966
18529
  current = parent;
17967
18530
  }
@@ -17971,11 +18534,11 @@ var ProviderLoader = class _ProviderLoader {
17971
18534
  constructor(options) {
17972
18535
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17973
18536
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17974
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
18537
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17975
18538
  const detected = this.detectDefaultUserDir();
17976
18539
  this.userDir = detected.path;
17977
18540
  this.userDirSource = detected.source;
17978
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18541
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17979
18542
  this.disableUpstream = false;
17980
18543
  this.applySourceConfig({
17981
18544
  userDir: options?.userDir,
@@ -18034,7 +18597,7 @@ var ProviderLoader = class _ProviderLoader {
18034
18597
  this.userDir = detected.path;
18035
18598
  this.userDirSource = detected.source;
18036
18599
  }
18037
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18600
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
18038
18601
  this.disableUpstream = this.sourceMode === "no-upstream";
18039
18602
  if (this.explicitProviderDir) {
18040
18603
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -18048,7 +18611,7 @@ var ProviderLoader = class _ProviderLoader {
18048
18611
  * Canonical provider directory shape for a given root.
18049
18612
  */
18050
18613
  getProviderDir(root, category, type) {
18051
- return path17.join(root, category, type);
18614
+ return path18.join(root, category, type);
18052
18615
  }
18053
18616
  /**
18054
18617
  * Canonical user override directory for a provider.
@@ -18075,7 +18638,7 @@ var ProviderLoader = class _ProviderLoader {
18075
18638
  resolveProviderFile(type, ...segments) {
18076
18639
  const dir = this.findProviderDirInternal(type);
18077
18640
  if (!dir) return null;
18078
- return path17.join(dir, ...segments);
18641
+ return path18.join(dir, ...segments);
18079
18642
  }
18080
18643
  /**
18081
18644
  * Load all providers (3-tier priority)
@@ -18114,7 +18677,7 @@ var ProviderLoader = class _ProviderLoader {
18114
18677
  if (!fs7.existsSync(this.upstreamDir)) return false;
18115
18678
  try {
18116
18679
  return fs7.readdirSync(this.upstreamDir).some(
18117
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18680
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
18118
18681
  );
18119
18682
  } catch {
18120
18683
  return false;
@@ -18611,8 +19174,8 @@ var ProviderLoader = class _ProviderLoader {
18611
19174
  resolved._resolvedScriptDir = entry.scriptDir;
18612
19175
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18613
19176
  if (providerDir) {
18614
- const fullDir = path17.join(providerDir, entry.scriptDir);
18615
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
19177
+ const fullDir = path18.join(providerDir, entry.scriptDir);
19178
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18616
19179
  }
18617
19180
  matched = true;
18618
19181
  }
@@ -18627,8 +19190,8 @@ var ProviderLoader = class _ProviderLoader {
18627
19190
  resolved._resolvedScriptDir = base.defaultScriptDir;
18628
19191
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18629
19192
  if (providerDir) {
18630
- const fullDir = path17.join(providerDir, base.defaultScriptDir);
18631
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
19193
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
19194
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18632
19195
  }
18633
19196
  }
18634
19197
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18645,8 +19208,8 @@ var ProviderLoader = class _ProviderLoader {
18645
19208
  resolved._resolvedScriptDir = dirOverride;
18646
19209
  resolved._resolvedScriptsSource = `versions:${range}`;
18647
19210
  if (providerDir) {
18648
- const fullDir = path17.join(providerDir, dirOverride);
18649
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
19211
+ const fullDir = path18.join(providerDir, dirOverride);
19212
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18650
19213
  }
18651
19214
  }
18652
19215
  } else if (override.scripts) {
@@ -18662,8 +19225,8 @@ var ProviderLoader = class _ProviderLoader {
18662
19225
  resolved._resolvedScriptDir = base.defaultScriptDir;
18663
19226
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18664
19227
  if (providerDir) {
18665
- const fullDir = path17.join(providerDir, base.defaultScriptDir);
18666
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
19228
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
19229
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18667
19230
  }
18668
19231
  }
18669
19232
  }
@@ -18695,14 +19258,14 @@ var ProviderLoader = class _ProviderLoader {
18695
19258
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18696
19259
  return null;
18697
19260
  }
18698
- const dir = path17.join(providerDir, scriptDir);
19261
+ const dir = path18.join(providerDir, scriptDir);
18699
19262
  if (!fs7.existsSync(dir)) {
18700
19263
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18701
19264
  return null;
18702
19265
  }
18703
19266
  const cached = this.scriptsCache.get(dir);
18704
19267
  if (cached) return cached;
18705
- const scriptsJs = path17.join(dir, "scripts.js");
19268
+ const scriptsJs = path18.join(dir, "scripts.js");
18706
19269
  if (fs7.existsSync(scriptsJs)) {
18707
19270
  try {
18708
19271
  delete require.cache[require.resolve(scriptsJs)];
@@ -18744,7 +19307,7 @@ var ProviderLoader = class _ProviderLoader {
18744
19307
  return;
18745
19308
  }
18746
19309
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18747
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
19310
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18748
19311
  this.reload();
18749
19312
  }
18750
19313
  };
@@ -18799,7 +19362,7 @@ var ProviderLoader = class _ProviderLoader {
18799
19362
  }
18800
19363
  const https = require("https");
18801
19364
  const { execSync: execSync7 } = require("child_process");
18802
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
19365
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18803
19366
  let prevEtag = "";
18804
19367
  let prevTimestamp = 0;
18805
19368
  try {
@@ -18859,17 +19422,17 @@ var ProviderLoader = class _ProviderLoader {
18859
19422
  return { updated: false };
18860
19423
  }
18861
19424
  this.log("Downloading latest providers from GitHub...");
18862
- const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18863
- const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
19425
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19426
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18864
19427
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18865
19428
  fs7.mkdirSync(tmpExtract, { recursive: true });
18866
19429
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18867
19430
  const extracted = fs7.readdirSync(tmpExtract);
18868
19431
  const rootDir = extracted.find(
18869
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19432
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18870
19433
  );
18871
19434
  if (!rootDir) throw new Error("Unexpected tarball structure");
18872
- const sourceDir = path17.join(tmpExtract, rootDir);
19435
+ const sourceDir = path18.join(tmpExtract, rootDir);
18873
19436
  const backupDir = this.upstreamDir + ".bak";
18874
19437
  if (fs7.existsSync(this.upstreamDir)) {
18875
19438
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18944,8 +19507,8 @@ var ProviderLoader = class _ProviderLoader {
18944
19507
  copyDirRecursive(src, dest) {
18945
19508
  fs7.mkdirSync(dest, { recursive: true });
18946
19509
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
18947
- const srcPath = path17.join(src, entry.name);
18948
- const destPath = path17.join(dest, entry.name);
19510
+ const srcPath = path18.join(src, entry.name);
19511
+ const destPath = path18.join(dest, entry.name);
18949
19512
  if (entry.isDirectory()) {
18950
19513
  this.copyDirRecursive(srcPath, destPath);
18951
19514
  } else {
@@ -18956,7 +19519,7 @@ var ProviderLoader = class _ProviderLoader {
18956
19519
  /** .meta.json save */
18957
19520
  writeMeta(metaPath, etag, timestamp) {
18958
19521
  try {
18959
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
19522
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18960
19523
  fs7.writeFileSync(metaPath, JSON.stringify({
18961
19524
  etag,
18962
19525
  timestamp,
@@ -18973,7 +19536,7 @@ var ProviderLoader = class _ProviderLoader {
18973
19536
  const scan = (d) => {
18974
19537
  try {
18975
19538
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18976
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
19539
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18977
19540
  else if (entry.name === "provider.json") count++;
18978
19541
  }
18979
19542
  } catch {
@@ -19201,17 +19764,17 @@ var ProviderLoader = class _ProviderLoader {
19201
19764
  for (const root of searchRoots) {
19202
19765
  if (!fs7.existsSync(root)) continue;
19203
19766
  const candidate = this.getProviderDir(root, cat, type);
19204
- if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19205
- const catDir = path17.join(root, cat);
19767
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19768
+ const catDir = path18.join(root, cat);
19206
19769
  if (fs7.existsSync(catDir)) {
19207
19770
  try {
19208
19771
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19209
19772
  if (!entry.isDirectory()) continue;
19210
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19773
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19211
19774
  if (fs7.existsSync(jsonPath)) {
19212
19775
  try {
19213
19776
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19214
- if (data.type === type) return path17.join(catDir, entry.name);
19777
+ if (data.type === type) return path18.join(catDir, entry.name);
19215
19778
  } catch {
19216
19779
  }
19217
19780
  }
@@ -19228,7 +19791,7 @@ var ProviderLoader = class _ProviderLoader {
19228
19791
  * (template substitution is NOT applied here — scripts.js handles that)
19229
19792
  */
19230
19793
  buildScriptWrappersFromDir(dir) {
19231
- const scriptsJs = path17.join(dir, "scripts.js");
19794
+ const scriptsJs = path18.join(dir, "scripts.js");
19232
19795
  if (fs7.existsSync(scriptsJs)) {
19233
19796
  try {
19234
19797
  delete require.cache[require.resolve(scriptsJs)];
@@ -19242,7 +19805,7 @@ var ProviderLoader = class _ProviderLoader {
19242
19805
  for (const file of fs7.readdirSync(dir)) {
19243
19806
  if (!file.endsWith(".js")) continue;
19244
19807
  const scriptName = toCamel(file.replace(".js", ""));
19245
- const filePath = path17.join(dir, file);
19808
+ const filePath = path18.join(dir, file);
19246
19809
  result[scriptName] = (...args) => {
19247
19810
  try {
19248
19811
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19302,7 +19865,7 @@ var ProviderLoader = class _ProviderLoader {
19302
19865
  }
19303
19866
  const hasJson = entries.some((e) => e.name === "provider.json");
19304
19867
  if (hasJson) {
19305
- const jsonPath = path17.join(d, "provider.json");
19868
+ const jsonPath = path18.join(d, "provider.json");
19306
19869
  try {
19307
19870
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19308
19871
  const mod = JSON.parse(raw);
@@ -19323,7 +19886,7 @@ var ProviderLoader = class _ProviderLoader {
19323
19886
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19324
19887
  } else {
19325
19888
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19326
- const scriptsPath = path17.join(d, "scripts.js");
19889
+ const scriptsPath = path18.join(d, "scripts.js");
19327
19890
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19328
19891
  try {
19329
19892
  delete require.cache[require.resolve(scriptsPath)];
@@ -19349,7 +19912,7 @@ var ProviderLoader = class _ProviderLoader {
19349
19912
  if (!entry.isDirectory()) continue;
19350
19913
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19351
19914
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19352
- scan(path17.join(d, entry.name));
19915
+ scan(path18.join(d, entry.name));
19353
19916
  }
19354
19917
  }
19355
19918
  };
@@ -19674,8 +20237,8 @@ function detectCurrentWorkspace(ideId) {
19674
20237
  const appNameMap = getMacAppIdentifiers();
19675
20238
  const appName = appNameMap[ideId];
19676
20239
  if (appName) {
19677
- const storagePath = path18.join(
19678
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
20240
+ const storagePath = path19.join(
20241
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19679
20242
  appName,
19680
20243
  "storage.json"
19681
20244
  );
@@ -19864,9 +20427,9 @@ init_logger();
19864
20427
 
19865
20428
  // src/logging/command-log.ts
19866
20429
  var fs8 = __toESM(require("fs"));
19867
- var path19 = __toESM(require("path"));
20430
+ var path20 = __toESM(require("path"));
19868
20431
  var os16 = __toESM(require("os"));
19869
- var LOG_DIR2 = process.platform === "win32" ? path19.join(process.env.LOCALAPPDATA || process.env.APPDATA || path19.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path19.join(os16.homedir(), "Library", "Logs", "adhdev") : path19.join(os16.homedir(), ".local", "share", "adhdev", "logs");
20432
+ var LOG_DIR2 = process.platform === "win32" ? path20.join(process.env.LOCALAPPDATA || process.env.APPDATA || path20.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path20.join(os16.homedir(), "Library", "Logs", "adhdev") : path20.join(os16.homedir(), ".local", "share", "adhdev", "logs");
19870
20433
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19871
20434
  var MAX_DAYS = 7;
19872
20435
  try {
@@ -19904,13 +20467,13 @@ function getDateStr2() {
19904
20467
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19905
20468
  }
19906
20469
  var currentDate2 = getDateStr2();
19907
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20470
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19908
20471
  var writeCount2 = 0;
19909
20472
  function checkRotation() {
19910
20473
  const today = getDateStr2();
19911
20474
  if (today !== currentDate2) {
19912
20475
  currentDate2 = today;
19913
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20476
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19914
20477
  cleanOldFiles();
19915
20478
  }
19916
20479
  }
@@ -19924,7 +20487,7 @@ function cleanOldFiles() {
19924
20487
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19925
20488
  if (dateMatch && dateMatch[1] < cutoffStr) {
19926
20489
  try {
19927
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
20490
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19928
20491
  } catch {
19929
20492
  }
19930
20493
  }
@@ -20007,14 +20570,66 @@ function getRecentCommands(count = 50) {
20007
20570
  cleanOldFiles();
20008
20571
 
20009
20572
  // src/commands/router.ts
20573
+ var yaml = __toESM(require("js-yaml"));
20010
20574
  init_logger();
20011
20575
 
20012
20576
  // src/commands/mesh-coordinator.ts
20013
- var import_node_fs2 = require("fs");
20577
+ var import_node_child_process3 = require("child_process");
20578
+ var import_node_fs3 = require("fs");
20014
20579
  var import_node_module2 = require("module");
20580
+ var os17 = __toESM(require("os"));
20015
20581
  var import_node_path = require("path");
20016
20582
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
20017
20583
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20584
+ var HERMES_CLI_TYPE = "hermes-cli";
20585
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20586
+ function isHermesProvider(provider, cliType) {
20587
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20588
+ return type === HERMES_CLI_TYPE;
20589
+ }
20590
+ function resolveHermesMeshCoordinatorSetup(options) {
20591
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20592
+ meshId: options.meshId,
20593
+ nodeExecutable: options.nodeExecutable,
20594
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20595
+ });
20596
+ if (!mcpServer) {
20597
+ return {
20598
+ kind: "unsupported",
20599
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20600
+ };
20601
+ }
20602
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20603
+ if (!configPath.trim()) {
20604
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20605
+ }
20606
+ return {
20607
+ kind: "auto_import",
20608
+ serverName: DEFAULT_SERVER_NAME,
20609
+ configPath,
20610
+ configFormat: "hermes_config_yaml",
20611
+ mcpServer
20612
+ };
20613
+ }
20614
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20615
+ return {
20616
+ kind: "manual",
20617
+ serverName: DEFAULT_SERVER_NAME,
20618
+ configFormat: "hermes_config_yaml",
20619
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20620
+ requiresRestart: true,
20621
+ instructions: "Hermes CLI does not auto-import repo-local .mcp.json. Add this MCP server to Hermes config under mcp_servers, then start a fresh Hermes session.",
20622
+ template: renderMeshCoordinatorTemplate(
20623
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20624
+ {
20625
+ meshId,
20626
+ workspace,
20627
+ serverName: DEFAULT_SERVER_NAME,
20628
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20629
+ }
20630
+ )
20631
+ };
20632
+ }
20018
20633
  function resolveMeshCoordinatorSetup(options) {
20019
20634
  const { provider, meshId, workspace } = options;
20020
20635
  const config = provider?.meshCoordinator;
@@ -20024,6 +20639,9 @@ function resolveMeshCoordinatorSetup(options) {
20024
20639
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
20025
20640
  };
20026
20641
  }
20642
+ if (isHermesProvider(provider, options.cliType)) {
20643
+ return resolveHermesMeshCoordinatorSetup(options);
20644
+ }
20027
20645
  const mcpConfig = config.mcpConfig;
20028
20646
  if (!mcpConfig || mcpConfig.mode === "none") {
20029
20647
  return {
@@ -20033,8 +20651,8 @@ function resolveMeshCoordinatorSetup(options) {
20033
20651
  }
20034
20652
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
20035
20653
  if (mcpConfig.mode === "auto_import") {
20036
- const path26 = mcpConfig.path?.trim();
20037
- if (!path26) {
20654
+ const path27 = mcpConfig.path?.trim();
20655
+ if (!path27) {
20038
20656
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
20039
20657
  }
20040
20658
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -20045,13 +20663,13 @@ function resolveMeshCoordinatorSetup(options) {
20045
20663
  if (!mcpServer) {
20046
20664
  return {
20047
20665
  kind: "unsupported",
20048
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20666
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20049
20667
  };
20050
20668
  }
20051
20669
  return {
20052
20670
  kind: "auto_import",
20053
20671
  serverName,
20054
- configPath: (0, import_node_path.join)(workspace, path26),
20672
+ configPath: resolveMcpConfigPath(path27, workspace),
20055
20673
  configFormat: mcpConfig.format,
20056
20674
  mcpServer
20057
20675
  };
@@ -20085,14 +20703,85 @@ function resolveMeshCoordinatorSetup(options) {
20085
20703
  function renderMeshCoordinatorTemplate(template, values) {
20086
20704
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
20087
20705
  }
20706
+ function resolveMcpConfigPath(configPath, workspace) {
20707
+ const trimmed = configPath.trim();
20708
+ if (trimmed === "~") return os17.homedir();
20709
+ if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
20710
+ if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
20711
+ return (0, import_node_path.join)(workspace, trimmed);
20712
+ }
20088
20713
  function resolveAdhdevMcpServerLaunch(options) {
20089
20714
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
20090
20715
  if (!entryPath) return null;
20716
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20717
+ if (!nodeExecutable) return null;
20091
20718
  return {
20092
- command: options.nodeExecutable?.trim() || process.execPath,
20719
+ command: nodeExecutable,
20093
20720
  args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
20094
20721
  };
20095
20722
  }
20723
+ function resolveMcpNodeExecutable(explicitExecutable) {
20724
+ const explicit = explicitExecutable?.trim();
20725
+ if (explicit) return explicit;
20726
+ const candidates = [];
20727
+ const addCandidate = (candidate) => {
20728
+ const trimmed = candidate?.trim();
20729
+ if (!trimmed) return;
20730
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20731
+ if (!candidates.includes(normalized)) candidates.push(normalized);
20732
+ };
20733
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20734
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20735
+ addCandidate(process.env.npm_node_execpath);
20736
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20737
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20738
+ addCandidate("/opt/homebrew/bin/node");
20739
+ addCandidate("/usr/local/bin/node");
20740
+ addCandidate("/usr/bin/node");
20741
+ addCandidate(process.execPath);
20742
+ for (const candidate of candidates) {
20743
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20744
+ }
20745
+ return null;
20746
+ }
20747
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20748
+ for (const entry of (pathValue || "").split(":")) {
20749
+ const dir = entry.trim();
20750
+ if (!dir) continue;
20751
+ addCandidate((0, import_node_path.join)(dir, "node"));
20752
+ }
20753
+ }
20754
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20755
+ const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
20756
+ try {
20757
+ const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20758
+ for (const versionDir of versionDirs) {
20759
+ addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
20760
+ }
20761
+ } catch {
20762
+ }
20763
+ }
20764
+ function compareNodeVersionNamesDescending(a, b) {
20765
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20766
+ const left = parse(a);
20767
+ const right = parse(b);
20768
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20769
+ const diff = (right[i] || 0) - (left[i] || 0);
20770
+ if (diff !== 0) return diff;
20771
+ }
20772
+ return b.localeCompare(a);
20773
+ }
20774
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20775
+ try {
20776
+ (0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20777
+ stdio: "ignore",
20778
+ timeout: 3e3
20779
+ });
20780
+ return true;
20781
+ } catch {
20782
+ return false;
20783
+ }
20784
+ }
20096
20785
  function resolveAdhdevMcpEntryPath(explicitPath) {
20097
20786
  const explicit = explicitPath?.trim();
20098
20787
  if (explicit) return normalizeExistingPath(explicit) || explicit;
@@ -20128,15 +20817,109 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
20128
20817
  }
20129
20818
  function normalizeExistingPath(filePath) {
20130
20819
  try {
20131
- if (!(0, import_node_fs2.existsSync)(filePath)) return null;
20132
- return import_node_fs2.realpathSync.native(filePath);
20820
+ if (!(0, import_node_fs3.existsSync)(filePath)) return null;
20821
+ return import_node_fs3.realpathSync.native(filePath);
20133
20822
  } catch {
20134
20823
  return null;
20135
20824
  }
20136
20825
  }
20137
20826
 
20827
+ // src/mesh/mesh-events.ts
20828
+ init_mesh_config();
20829
+ init_logger();
20830
+ function readNonEmptyString(value) {
20831
+ return typeof value === "string" && value.trim() ? value.trim() : "";
20832
+ }
20833
+ function formatCompletionMetadata(event) {
20834
+ const parts = [
20835
+ readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
20836
+ readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
20837
+ readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
20838
+ ].filter(Boolean);
20839
+ return parts.length > 0 ? ` (${parts.join("; ")})` : "";
20840
+ }
20841
+ function buildMeshSystemMessage(args) {
20842
+ const metadata = formatCompletionMetadata(args.metadataEvent);
20843
+ if (args.event === "agent:generating_completed") {
20844
+ return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path; use mesh_read_chat once to review its final progress, but do not poll repeatedly.`;
20845
+ }
20846
+ if (args.event === "agent:waiting_approval") {
20847
+ return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
20848
+ }
20849
+ return "";
20850
+ }
20851
+ function injectMeshSystemMessage(components, args) {
20852
+ const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
20853
+ const instState = inst.getState();
20854
+ if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
20855
+ if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
20856
+ return true;
20857
+ });
20858
+ if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
20859
+ const messageText = buildMeshSystemMessage({
20860
+ event: args.event,
20861
+ nodeLabel: args.nodeLabel,
20862
+ metadataEvent: args.metadataEvent
20863
+ });
20864
+ if (!messageText) return { success: false, error: "unsupported mesh event" };
20865
+ for (const coord of coordinatorInstances) {
20866
+ const coordState = coord.getState();
20867
+ LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
20868
+ coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
20869
+ }
20870
+ return { success: true, forwarded: coordinatorInstances.length };
20871
+ }
20872
+ function handleMeshForwardEvent(components, payload) {
20873
+ const eventName = readNonEmptyString(payload.event);
20874
+ if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
20875
+ return { success: false, error: "unsupported mesh event" };
20876
+ }
20877
+ const meshId = readNonEmptyString(payload.meshId);
20878
+ if (!meshId) return { success: false, error: "meshId required" };
20879
+ const nodeId = readNonEmptyString(payload.nodeId);
20880
+ const workspace = readNonEmptyString(payload.workspace);
20881
+ const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
20882
+ return injectMeshSystemMessage(components, {
20883
+ meshId,
20884
+ nodeLabel,
20885
+ event: eventName,
20886
+ metadataEvent: {
20887
+ targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
20888
+ providerType: readNonEmptyString(payload.providerType),
20889
+ providerSessionId: readNonEmptyString(payload.providerSessionId)
20890
+ }
20891
+ });
20892
+ }
20893
+ function setupMeshEventForwarding(components) {
20894
+ components.instanceManager.onEvent((event) => {
20895
+ if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
20896
+ const instanceId = readNonEmptyString(event.instanceId);
20897
+ if (!instanceId) return;
20898
+ const sourceInstance = components.instanceManager.getInstance(instanceId);
20899
+ if (!sourceInstance || sourceInstance.category !== "cli") return;
20900
+ const state = sourceInstance.getState();
20901
+ const workspace = readNonEmptyString(state.workspace);
20902
+ if (!workspace) return;
20903
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
20904
+ const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
20905
+ const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
20906
+ const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
20907
+ if (!meshId) return;
20908
+ const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
20909
+ const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
20910
+ const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
20911
+ injectMeshSystemMessage(components, {
20912
+ meshId,
20913
+ sourceInstanceId: instanceId,
20914
+ nodeLabel,
20915
+ event: event.event,
20916
+ metadataEvent: event
20917
+ });
20918
+ });
20919
+ }
20920
+
20138
20921
  // src/status/snapshot.ts
20139
- var os17 = __toESM(require("os"));
20922
+ var os18 = __toESM(require("os"));
20140
20923
  init_config();
20141
20924
  init_terminal_screen();
20142
20925
  init_logger();
@@ -20192,8 +20975,8 @@ function buildAvailableProviders(providerLoader) {
20192
20975
  }
20193
20976
  function buildMachineInfo(profile = "full") {
20194
20977
  const base = {
20195
- hostname: os17.hostname(),
20196
- platform: os17.platform()
20978
+ hostname: os18.hostname(),
20979
+ platform: os18.platform()
20197
20980
  };
20198
20981
  if (profile === "live") {
20199
20982
  return base;
@@ -20202,23 +20985,23 @@ function buildMachineInfo(profile = "full") {
20202
20985
  const memSnap2 = getHostMemorySnapshot();
20203
20986
  return {
20204
20987
  ...base,
20205
- arch: os17.arch(),
20206
- cpus: os17.cpus().length,
20988
+ arch: os18.arch(),
20989
+ cpus: os18.cpus().length,
20207
20990
  totalMem: memSnap2.totalMem,
20208
- release: os17.release()
20991
+ release: os18.release()
20209
20992
  };
20210
20993
  }
20211
20994
  const memSnap = getHostMemorySnapshot();
20212
20995
  return {
20213
20996
  ...base,
20214
- arch: os17.arch(),
20215
- cpus: os17.cpus().length,
20997
+ arch: os18.arch(),
20998
+ cpus: os18.cpus().length,
20216
20999
  totalMem: memSnap.totalMem,
20217
21000
  freeMem: memSnap.freeMem,
20218
21001
  availableMem: memSnap.availableMem,
20219
- loadavg: os17.loadavg(),
20220
- uptime: os17.uptime(),
20221
- release: os17.release()
21002
+ loadavg: os18.loadavg(),
21003
+ uptime: os18.uptime(),
21004
+ release: os18.release()
20222
21005
  };
20223
21006
  }
20224
21007
  function parseMessageTime(value) {
@@ -20452,14 +21235,14 @@ function buildStatusSnapshot(options) {
20452
21235
  var import_child_process8 = require("child_process");
20453
21236
  var import_child_process9 = require("child_process");
20454
21237
  var fs9 = __toESM(require("fs"));
20455
- var os18 = __toESM(require("os"));
20456
- var path20 = __toESM(require("path"));
21238
+ var os19 = __toESM(require("os"));
21239
+ var path21 = __toESM(require("path"));
20457
21240
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20458
21241
  function getUpgradeLogPath() {
20459
- const home = os18.homedir();
20460
- const dir = path20.join(home, ".adhdev");
21242
+ const home = os19.homedir();
21243
+ const dir = path21.join(home, ".adhdev");
20461
21244
  fs9.mkdirSync(dir, { recursive: true });
20462
- return path20.join(dir, "daemon-upgrade.log");
21245
+ return path21.join(dir, "daemon-upgrade.log");
20463
21246
  }
20464
21247
  function appendUpgradeLog(message) {
20465
21248
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20470,14 +21253,14 @@ function appendUpgradeLog(message) {
20470
21253
  }
20471
21254
  }
20472
21255
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20473
- const binDir = path20.dirname(nodeExecutable);
21256
+ const binDir = path21.dirname(nodeExecutable);
20474
21257
  if (platform10 === "win32") {
20475
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
21258
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20476
21259
  if (fs9.existsSync(npmCliPath)) {
20477
21260
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20478
21261
  }
20479
21262
  for (const candidate of ["npm.exe", "npm"]) {
20480
- const candidatePath = path20.join(binDir, candidate);
21263
+ const candidatePath = path21.join(binDir, candidate);
20481
21264
  if (fs9.existsSync(candidatePath)) {
20482
21265
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20483
21266
  }
@@ -20485,7 +21268,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20485
21268
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20486
21269
  }
20487
21270
  for (const candidate of ["npm"]) {
20488
- const candidatePath = path20.join(binDir, candidate);
21271
+ const candidatePath = path21.join(binDir, candidate);
20489
21272
  if (fs9.existsSync(candidatePath)) {
20490
21273
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20491
21274
  }
@@ -20502,13 +21285,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20502
21285
  let currentDir = resolvedPath;
20503
21286
  try {
20504
21287
  if (fs9.statSync(resolvedPath).isFile()) {
20505
- currentDir = path20.dirname(resolvedPath);
21288
+ currentDir = path21.dirname(resolvedPath);
20506
21289
  }
20507
21290
  } catch {
20508
- currentDir = path20.dirname(resolvedPath);
21291
+ currentDir = path21.dirname(resolvedPath);
20509
21292
  }
20510
21293
  while (true) {
20511
- const packageJsonPath = path20.join(currentDir, "package.json");
21294
+ const packageJsonPath = path21.join(currentDir, "package.json");
20512
21295
  try {
20513
21296
  if (fs9.existsSync(packageJsonPath)) {
20514
21297
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20519,7 +21302,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20519
21302
  }
20520
21303
  } catch {
20521
21304
  }
20522
- const parentDir = path20.dirname(currentDir);
21305
+ const parentDir = path21.dirname(currentDir);
20523
21306
  if (parentDir === currentDir) {
20524
21307
  return null;
20525
21308
  }
@@ -20527,13 +21310,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20527
21310
  }
20528
21311
  }
20529
21312
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20530
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20531
- if (path20.basename(nodeModulesDir) !== "node_modules") {
21313
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
21314
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20532
21315
  return null;
20533
21316
  }
20534
- const maybeLibDir = path20.dirname(nodeModulesDir);
20535
- if (path20.basename(maybeLibDir) === "lib") {
20536
- return path20.dirname(maybeLibDir);
21317
+ const maybeLibDir = path21.dirname(nodeModulesDir);
21318
+ if (path21.basename(maybeLibDir) === "lib") {
21319
+ return path21.dirname(maybeLibDir);
20537
21320
  }
20538
21321
  return maybeLibDir;
20539
21322
  }
@@ -20648,7 +21431,7 @@ async function waitForPidExit(pid, timeoutMs) {
20648
21431
  }
20649
21432
  }
20650
21433
  function stopSessionHostProcesses(appName) {
20651
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
21434
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20652
21435
  try {
20653
21436
  if (fs9.existsSync(pidFile)) {
20654
21437
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20665,7 +21448,7 @@ function stopSessionHostProcesses(appName) {
20665
21448
  }
20666
21449
  }
20667
21450
  function removeDaemonPidFile() {
20668
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
21451
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20669
21452
  try {
20670
21453
  fs9.unlinkSync(pidFile);
20671
21454
  } catch {
@@ -20676,7 +21459,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20676
21459
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20677
21460
  if (!npmRoot) return;
20678
21461
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20679
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
21462
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20680
21463
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20681
21464
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20682
21465
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20684,25 +21467,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20684
21467
  }
20685
21468
  if (pkgName.startsWith("@")) {
20686
21469
  const [scope, name] = pkgName.split("/");
20687
- const scopeDir = path20.join(npmRoot, scope);
21470
+ const scopeDir = path21.join(npmRoot, scope);
20688
21471
  if (!fs9.existsSync(scopeDir)) return;
20689
21472
  for (const entry of fs9.readdirSync(scopeDir)) {
20690
21473
  if (!entry.startsWith(`.${name}-`)) continue;
20691
- fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
20692
- appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
21474
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
21475
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20693
21476
  }
20694
21477
  } else {
20695
21478
  for (const entry of fs9.readdirSync(npmRoot)) {
20696
21479
  if (!entry.startsWith(`.${pkgName}-`)) continue;
20697
- fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
20698
- appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
21480
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
21481
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20699
21482
  }
20700
21483
  }
20701
21484
  if (fs9.existsSync(binDir)) {
20702
21485
  for (const entry of fs9.readdirSync(binDir)) {
20703
21486
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
20704
- fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
20705
- appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
21487
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
21488
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20706
21489
  }
20707
21490
  }
20708
21491
  }
@@ -20803,6 +21586,56 @@ function normalizeReleaseChannel(value) {
20803
21586
  function resolveUpgradeChannel(args) {
20804
21587
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20805
21588
  }
21589
+ function readProviderPriorityFromPolicy(policy) {
21590
+ const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
21591
+ const raw = record.providerPriority;
21592
+ if (!Array.isArray(raw)) return [];
21593
+ const seen = /* @__PURE__ */ new Set();
21594
+ return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
21595
+ if (seen.has(type)) return false;
21596
+ seen.add(type);
21597
+ return true;
21598
+ });
21599
+ }
21600
+ async function resolveProviderTypeFromPriority(args) {
21601
+ if (!args.providerPriority.length) {
21602
+ return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
21603
+ }
21604
+ const failed = [];
21605
+ for (const requestedType of args.providerPriority) {
21606
+ const normalizedType = args.providerLoader.resolveAlias(requestedType);
21607
+ if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
21608
+ failed.push(`${requestedType}: disabled`);
21609
+ continue;
21610
+ }
21611
+ const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
21612
+ args.providerLoader.setCliDetectionResults([{
21613
+ id: normalizedType,
21614
+ installed: !!detected,
21615
+ path: detected?.path
21616
+ }], false);
21617
+ args.onStatusChange?.();
21618
+ if (detected) return { providerType: normalizedType };
21619
+ failed.push(`${requestedType}: not detected`);
21620
+ }
21621
+ return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
21622
+ }
21623
+ function loadYamlModule() {
21624
+ return yaml;
21625
+ }
21626
+ function getMcpServersKey(format) {
21627
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
21628
+ }
21629
+ function parseMeshCoordinatorMcpConfig(text, format) {
21630
+ if (!text.trim()) return {};
21631
+ if (format === "claude_mcp_json") return JSON.parse(text);
21632
+ const parsed = loadYamlModule().load(text);
21633
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
21634
+ }
21635
+ function serializeMeshCoordinatorMcpConfig(config, format) {
21636
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
21637
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
21638
+ }
20806
21639
  var CHAT_COMMANDS = [
20807
21640
  "send_chat",
20808
21641
  "new_chat",
@@ -20901,6 +21734,154 @@ var DaemonCommandRouter = class {
20901
21734
  constructor(deps) {
20902
21735
  this.deps = deps;
20903
21736
  }
21737
+ getCachedInlineMesh(meshId, inlineMesh) {
21738
+ if (inlineMesh && typeof inlineMesh === "object") {
21739
+ this.inlineMeshCache.set(meshId, inlineMesh);
21740
+ return inlineMesh;
21741
+ }
21742
+ return this.inlineMeshCache.get(meshId);
21743
+ }
21744
+ async getMeshForCommand(meshId, inlineMesh) {
21745
+ try {
21746
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21747
+ const mesh = getMesh3(meshId);
21748
+ if (mesh) return { mesh, inline: false };
21749
+ } catch {
21750
+ }
21751
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21752
+ return cached ? { mesh: cached, inline: true } : null;
21753
+ }
21754
+ updateInlineMeshNode(meshId, mesh, node) {
21755
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21756
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21757
+ if (idx >= 0) mesh.nodes[idx] = node;
21758
+ else mesh.nodes.push(node);
21759
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21760
+ this.inlineMeshCache.set(meshId, mesh);
21761
+ }
21762
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21763
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21764
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21765
+ if (idx === -1) return false;
21766
+ mesh.nodes.splice(idx, 1);
21767
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21768
+ this.inlineMeshCache.set(meshId, mesh);
21769
+ return true;
21770
+ }
21771
+ normalizeMeshSessionCleanupMode(value) {
21772
+ return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
21773
+ }
21774
+ sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
21775
+ const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
21776
+ if (!sessionId) return false;
21777
+ if (sessionIds?.size) return sessionIds.has(sessionId);
21778
+ const workspace = typeof node?.workspace === "string" ? node.workspace : "";
21779
+ if (workspace && record?.workspace === workspace) return true;
21780
+ if (record?.meta?.meshNodeId === nodeId) return true;
21781
+ return false;
21782
+ }
21783
+ isCompletedHostedSession(record) {
21784
+ return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
21785
+ }
21786
+ async cleanupMeshSessions(args) {
21787
+ if (args.mode === "preserve") {
21788
+ return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
21789
+ }
21790
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
21791
+ const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
21792
+ const sessions = await this.deps.sessionHostControl.listSessions();
21793
+ const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
21794
+ const hasExplicitSessionIds = !!requestedSessionIds?.size;
21795
+ const stoppedSessionIds = [];
21796
+ const deletedSessionIds = [];
21797
+ const skippedSessionIds = [];
21798
+ const skippedLiveSessionIds = [];
21799
+ const deleteUnsupportedSessionIds = [];
21800
+ const recordsRemainSessionIds = [];
21801
+ const errors = [];
21802
+ const matchedBySurfaceKind = {
21803
+ live_runtime: 0,
21804
+ recovery_snapshot: 0,
21805
+ inactive_record: 0
21806
+ };
21807
+ for (const record of matched) {
21808
+ const surfaceKind = getSessionHostSurfaceKind(record);
21809
+ matchedBySurfaceKind[surfaceKind] += 1;
21810
+ }
21811
+ for (const record of matched) {
21812
+ const sessionId = String(record.sessionId);
21813
+ const completed = this.isCompletedHostedSession(record);
21814
+ const surfaceKind = getSessionHostSurfaceKind(record);
21815
+ const liveRuntime = surfaceKind === "live_runtime";
21816
+ if (!hasExplicitSessionIds && liveRuntime) {
21817
+ skippedSessionIds.push(sessionId);
21818
+ skippedLiveSessionIds.push(sessionId);
21819
+ continue;
21820
+ }
21821
+ try {
21822
+ if (args.mode === "stop") {
21823
+ if (!completed) {
21824
+ if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
21825
+ stoppedSessionIds.push(sessionId);
21826
+ } else {
21827
+ skippedSessionIds.push(sessionId);
21828
+ }
21829
+ continue;
21830
+ }
21831
+ if (args.mode === "delete_stopped") {
21832
+ if (completed) {
21833
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
21834
+ deletedSessionIds.push(sessionId);
21835
+ } else {
21836
+ skippedSessionIds.push(sessionId);
21837
+ }
21838
+ continue;
21839
+ }
21840
+ if (args.mode === "stop_and_delete") {
21841
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
21842
+ deletedSessionIds.push(sessionId);
21843
+ continue;
21844
+ }
21845
+ } catch (e) {
21846
+ const message = e?.message || String(e);
21847
+ if (message.includes("Unsupported session host request: delete_session") && (args.mode === "delete_stopped" || args.mode === "stop_and_delete")) {
21848
+ deleteUnsupportedSessionIds.push(sessionId);
21849
+ recordsRemainSessionIds.push(sessionId);
21850
+ if (args.mode === "stop_and_delete" && !completed) {
21851
+ try {
21852
+ await this.deps.sessionHostControl.stopSession(sessionId);
21853
+ stoppedSessionIds.push(sessionId);
21854
+ } catch (stopError) {
21855
+ errors.push({ sessionId, error: stopError?.message || String(stopError) });
21856
+ continue;
21857
+ }
21858
+ }
21859
+ skippedSessionIds.push(sessionId);
21860
+ continue;
21861
+ }
21862
+ errors.push({ sessionId, error: message });
21863
+ }
21864
+ }
21865
+ const deleteUnsupported = deleteUnsupportedSessionIds.length > 0;
21866
+ return {
21867
+ success: errors.length === 0,
21868
+ mode: args.mode,
21869
+ dryRun: args.dryRun === true,
21870
+ matchedCount: matched.length,
21871
+ matchedBySurfaceKind,
21872
+ stoppedSessionIds,
21873
+ deletedSessionIds,
21874
+ skippedSessionIds,
21875
+ skippedLiveSessionIds,
21876
+ ...deleteUnsupported ? {
21877
+ deleteUnsupported: true,
21878
+ effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
21879
+ deleteUnsupportedSessionIds,
21880
+ recordsRemainSessionIds
21881
+ } : {},
21882
+ ...errors.length ? { errors } : {}
21883
+ };
21884
+ }
20904
21885
  async traceSessionHostAction(action, args, run, summarizeResult) {
20905
21886
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20906
21887
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -21020,6 +22001,9 @@ var DaemonCommandRouter = class {
21020
22001
  async executeDaemonCommand(cmd, args) {
21021
22002
  switch (cmd) {
21022
22003
  // ─── CLI / ACP commands ───
22004
+ case "mesh_forward_event": {
22005
+ return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
22006
+ }
21023
22007
  case "launch_cli":
21024
22008
  case "stop_cli":
21025
22009
  case "set_cli_view_mode":
@@ -21564,7 +22548,26 @@ var DaemonCommandRouter = class {
21564
22548
  if (!name) return { success: false, error: "name required" };
21565
22549
  try {
21566
22550
  const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21567
- const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
22551
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
22552
+ return { success: true, mesh };
22553
+ } catch (e) {
22554
+ return { success: false, error: e.message };
22555
+ }
22556
+ }
22557
+ case "update_mesh": {
22558
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22559
+ if (!meshId) return { success: false, error: "meshId required" };
22560
+ try {
22561
+ const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22562
+ const patch = {};
22563
+ if (typeof args?.name === "string") patch.name = args.name;
22564
+ if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
22565
+ if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
22566
+ if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
22567
+ if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
22568
+ const mesh = updateMesh2(meshId, patch);
22569
+ if (!mesh) return { success: false, error: "Mesh not found" };
22570
+ this.inlineMeshCache.set(meshId, mesh);
21568
22571
  return { success: true, mesh };
21569
22572
  } catch (e) {
21570
22573
  return { success: false, error: e.message };
@@ -21588,21 +22591,164 @@ var DaemonCommandRouter = class {
21588
22591
  if (!workspace) return { success: false, error: "workspace required" };
21589
22592
  try {
21590
22593
  const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21591
- const node = addNode3(meshId, { workspace });
22594
+ const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
22595
+ const readOnly = args?.readOnly === true;
22596
+ const policy = {
22597
+ ...readOnly ? { readOnly: true } : {},
22598
+ ...providerPriority.length ? { providerPriority } : {}
22599
+ };
22600
+ const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
21592
22601
  if (!node) return { success: false, error: "Mesh not found" };
21593
22602
  return { success: true, node };
21594
22603
  } catch (e) {
21595
22604
  return { success: false, error: e.message };
21596
22605
  }
21597
22606
  }
22607
+ case "update_mesh_node": {
22608
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22609
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22610
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22611
+ try {
22612
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22613
+ const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
22614
+ if (Array.isArray(args?.providerPriority)) {
22615
+ const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
22616
+ delete policy.provider_priority;
22617
+ if (providerPriority.length) {
22618
+ policy.providerPriority = providerPriority;
22619
+ } else {
22620
+ delete policy.providerPriority;
22621
+ }
22622
+ }
22623
+ const node = updateNode2(meshId, nodeId, { policy });
22624
+ if (!node) return { success: false, error: "Mesh node not found" };
22625
+ return { success: true, node };
22626
+ } catch (e) {
22627
+ return { success: false, error: e.message };
22628
+ }
22629
+ }
22630
+ case "cleanup_mesh_sessions": {
22631
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22632
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22633
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22634
+ try {
22635
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22636
+ const mesh = meshRecord?.mesh;
22637
+ if (!mesh) return { success: false, error: "Mesh not found" };
22638
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22639
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
22640
+ const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
22641
+ const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
22642
+ const result = await this.cleanupMeshSessions({
22643
+ meshId,
22644
+ nodeId,
22645
+ node,
22646
+ mode,
22647
+ sessionIds,
22648
+ dryRun: args?.dryRun === true
22649
+ });
22650
+ return result;
22651
+ } catch (e) {
22652
+ return { success: false, error: e.message };
22653
+ }
22654
+ }
21598
22655
  case "remove_mesh_node": {
21599
22656
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21600
22657
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21601
22658
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21602
22659
  try {
21603
- const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21604
- const removed = removeNode3(meshId, nodeId);
21605
- return { success: true, removed };
22660
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22661
+ const mesh = meshRecord?.mesh;
22662
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22663
+ const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
22664
+ args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
22665
+ );
22666
+ let sessionCleanup;
22667
+ if (node && sessionCleanupMode !== "preserve") {
22668
+ sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
22669
+ if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
22670
+ }
22671
+ if (node?.isLocalWorktree && node.workspace) {
22672
+ try {
22673
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
22674
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
22675
+ if (repoRoot) {
22676
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22677
+ await removeWorktree2(repoRoot, node.workspace);
22678
+ }
22679
+ } catch (e) {
22680
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
22681
+ }
22682
+ }
22683
+ let removed = false;
22684
+ if (meshRecord?.inline) {
22685
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
22686
+ } else {
22687
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22688
+ removed = removeNode3(meshId, nodeId);
22689
+ }
22690
+ return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
22691
+ } catch (e) {
22692
+ return { success: false, error: e.message };
22693
+ }
22694
+ }
22695
+ case "clone_mesh_node": {
22696
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22697
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
22698
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
22699
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
22700
+ if (!meshId) return { success: false, error: "meshId required" };
22701
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
22702
+ if (!branch) return { success: false, error: "branch required" };
22703
+ try {
22704
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22705
+ const mesh = meshRecord?.mesh;
22706
+ if (!mesh) return { success: false, error: "Mesh not found" };
22707
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
22708
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
22709
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
22710
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22711
+ const result = await createWorktree2({
22712
+ repoRoot,
22713
+ branch,
22714
+ baseBranch,
22715
+ meshName: mesh.name
22716
+ });
22717
+ let node;
22718
+ if (meshRecord.inline) {
22719
+ const { randomUUID: randomUUID8 } = await import("crypto");
22720
+ node = {
22721
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
22722
+ workspace: result.worktreePath,
22723
+ repoRoot: result.worktreePath,
22724
+ daemonId: sourceNode.daemonId,
22725
+ userOverrides: { ...sourceNode.userOverrides || {} },
22726
+ policy: { ...sourceNode.policy || {} },
22727
+ isLocalWorktree: true,
22728
+ worktreeBranch: result.branch,
22729
+ clonedFromNodeId: sourceNodeId
22730
+ };
22731
+ this.updateInlineMeshNode(meshId, mesh, node);
22732
+ } else {
22733
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22734
+ node = addNode3(meshId, {
22735
+ workspace: result.worktreePath,
22736
+ repoRoot: result.worktreePath,
22737
+ daemonId: sourceNode.daemonId,
22738
+ userOverrides: { ...sourceNode.userOverrides || {} },
22739
+ isLocalWorktree: true,
22740
+ worktreeBranch: result.branch,
22741
+ clonedFromNodeId: sourceNodeId,
22742
+ policy: { ...sourceNode.policy || {} }
22743
+ });
22744
+ if (!node) return { success: false, error: "Failed to register worktree node" };
22745
+ }
22746
+ return {
22747
+ success: true,
22748
+ node,
22749
+ worktreePath: result.worktreePath,
22750
+ branch: result.branch
22751
+ };
21606
22752
  } catch (e) {
21607
22753
  return { success: false, error: e.message };
21608
22754
  }
@@ -21610,7 +22756,7 @@ var DaemonCommandRouter = class {
21610
22756
  // ─── Mesh Coordinator Launch ───
21611
22757
  case "launch_mesh_coordinator": {
21612
22758
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21613
- const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
22759
+ let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
21614
22760
  if (!meshId) return { success: false, error: "meshId required" };
21615
22761
  try {
21616
22762
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -21638,9 +22784,29 @@ var DaemonCommandRouter = class {
21638
22784
  }
21639
22785
  const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
21640
22786
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
22787
+ if (!cliType) {
22788
+ const resolved = await resolveProviderTypeFromPriority({
22789
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
22790
+ providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
22791
+ providerLoader: this.deps.providerLoader,
22792
+ onStatusChange: this.deps.onStatusChange
22793
+ });
22794
+ if (!resolved.providerType) {
22795
+ return {
22796
+ success: false,
22797
+ code: "mesh_coordinator_provider_priority_unusable",
22798
+ error: resolved.error || "No usable provider found from node providerPriority",
22799
+ meshId,
22800
+ cliType,
22801
+ workspace
22802
+ };
22803
+ }
22804
+ cliType = resolved.providerType;
22805
+ }
21641
22806
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21642
22807
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21643
22808
  provider: providerMeta,
22809
+ cliType,
21644
22810
  meshId,
21645
22811
  workspace
21646
22812
  });
@@ -21665,7 +22831,8 @@ var DaemonCommandRouter = class {
21665
22831
  meshCoordinatorSetup: coordinatorSetup
21666
22832
  };
21667
22833
  }
21668
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
22834
+ const configFormat = coordinatorSetup.configFormat;
22835
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21669
22836
  return {
21670
22837
  success: false,
21671
22838
  code: "mesh_coordinator_unsupported",
@@ -21675,17 +22842,34 @@ var DaemonCommandRouter = class {
21675
22842
  workspace
21676
22843
  };
21677
22844
  }
21678
- const { existsSync: existsSync22, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3 } = await import("fs");
21679
- const mcpConfigPath = coordinatorSetup.configPath;
21680
- const hadExistingMcpConfig = existsSync22(mcpConfigPath);
21681
- let existingMcpConfig = {};
21682
- if (hadExistingMcpConfig) {
21683
- try {
21684
- existingMcpConfig = JSON.parse(readFileSync15(mcpConfigPath, "utf-8"));
21685
- copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
21686
- } catch {
21687
- }
22845
+ let systemPrompt = "";
22846
+ try {
22847
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
22848
+ } catch (error) {
22849
+ const message = error?.message || String(error);
22850
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
22851
+ return {
22852
+ success: false,
22853
+ code: "mesh_coordinator_prompt_failed",
22854
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
22855
+ meshId,
22856
+ cliType,
22857
+ workspace
22858
+ };
21688
22859
  }
22860
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22861
+ const { dirname: dirname9 } = await import("path");
22862
+ const mcpConfigPath = coordinatorSetup.configPath;
22863
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
22864
+ const returnManualFallback = (message) => ({
22865
+ success: false,
22866
+ code: "mesh_coordinator_manual_mcp_setup_required",
22867
+ error: message,
22868
+ meshId,
22869
+ cliType,
22870
+ workspace,
22871
+ meshCoordinatorSetup: hermesManualFallback
22872
+ });
21689
22873
  const mcpServerEntry = {
21690
22874
  command: coordinatorSetup.mcpServer.command,
21691
22875
  args: coordinatorSetup.mcpServer.args
@@ -21696,24 +22880,55 @@ var DaemonCommandRouter = class {
21696
22880
  ADHDEV_MCP_TRANSPORT: "ipc"
21697
22881
  };
21698
22882
  }
22883
+ try {
22884
+ mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
22885
+ } catch (error) {
22886
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22887
+ LOG.error("MeshCoordinator", message);
22888
+ if (hermesManualFallback) return returnManualFallback(message);
22889
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
22890
+ }
22891
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
22892
+ let existingMcpConfig = {};
22893
+ if (hadExistingMcpConfig) {
22894
+ try {
22895
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
22896
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
22897
+ } catch (error) {
22898
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
22899
+ return {
22900
+ success: false,
22901
+ code: "mesh_coordinator_config_parse_failed",
22902
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
22903
+ };
22904
+ }
22905
+ }
22906
+ const mcpServersKey = getMcpServersKey(configFormat);
22907
+ const existingServers = existingMcpConfig[mcpServersKey];
21699
22908
  const mcpConfig = {
21700
22909
  ...existingMcpConfig,
21701
- mcpServers: {
21702
- ...existingMcpConfig.mcpServers || {},
22910
+ [mcpServersKey]: {
22911
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21703
22912
  [coordinatorSetup.serverName]: mcpServerEntry
21704
22913
  }
21705
22914
  };
21706
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21707
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21708
- let systemPrompt = "";
21709
22915
  try {
21710
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
21711
- } catch {
21712
- systemPrompt = `You are a Repo Mesh Coordinator for "${mesh.name}". Use the adhdev-mesh MCP tools (mesh_status, mesh_list_nodes, mesh_send_task, mesh_read_chat, mesh_launch_session, etc.) to orchestrate work across ${mesh.nodes.length} node(s).`;
22916
+ writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22917
+ } catch (error) {
22918
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22919
+ LOG.error("MeshCoordinator", message);
22920
+ if (hermesManualFallback) return returnManualFallback(message);
22921
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21713
22922
  }
22923
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21714
22924
  const cliArgs = [];
22925
+ const launchEnv = {};
21715
22926
  if (systemPrompt) {
21716
- cliArgs.push("--append-system-prompt", systemPrompt);
22927
+ if (configFormat === "hermes_config_yaml") {
22928
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22929
+ } else {
22930
+ cliArgs.push("--append-system-prompt", systemPrompt);
22931
+ }
21717
22932
  }
21718
22933
  if (cliType === "claude-cli") {
21719
22934
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21722,6 +22937,7 @@ var DaemonCommandRouter = class {
21722
22937
  cliType,
21723
22938
  dir: workspace,
21724
22939
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22940
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21725
22941
  settings: {
21726
22942
  meshCoordinatorFor: meshId
21727
22943
  }
@@ -21901,6 +23117,12 @@ var DaemonStatusReporter = class {
21901
23117
  if (providerType) {
21902
23118
  payload.providerType = providerType;
21903
23119
  }
23120
+ if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
23121
+ payload.providerSessionId = event.providerSessionId.trim();
23122
+ }
23123
+ if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
23124
+ payload.workspaceName = event.workspaceName.trim();
23125
+ }
21904
23126
  if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
21905
23127
  payload.duration = event.duration;
21906
23128
  }
@@ -22122,7 +23344,8 @@ function prepareSessionChatTailUpdate(input) {
22122
23344
  update: null
22123
23345
  };
22124
23346
  }
22125
- const messages = Array.isArray(result.messages) ? result.messages : [];
23347
+ const fullMessages = normalizeChatMessages(Array.isArray(result.messages) ? result.messages : []);
23348
+ const messages = filterUserFacingChatMessages(fullMessages);
22126
23349
  const title = typeof result.title === "string" ? result.title : void 0;
22127
23350
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
22128
23351
  const status = typeof result.status === "string" ? result.status : "idle";
@@ -23148,7 +24371,10 @@ var ProviderInstanceManager = class {
23148
24371
  this.instances.get(id).dispose();
23149
24372
  }
23150
24373
  this.instances.set(id, instance);
23151
- await instance.init(context);
24374
+ await instance.init({
24375
+ ...context,
24376
+ emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
24377
+ });
23152
24378
  }
23153
24379
  /**
23154
24380
  * Instance remove
@@ -23310,6 +24536,17 @@ var ProviderInstanceManager = class {
23310
24536
  onEvent(listener) {
23311
24537
  this.eventListeners.push(listener);
23312
24538
  }
24539
+ emitProviderEvent(providerType, instanceId, event) {
24540
+ const payload = {
24541
+ ...event,
24542
+ providerType,
24543
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
24544
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
24545
+ };
24546
+ for (const listener of this.eventListeners) {
24547
+ listener(payload);
24548
+ }
24549
+ }
23313
24550
  emitPendingEvents(providerType, state, extra = {}) {
23314
24551
  for (const event of state.pendingEvents) {
23315
24552
  for (const listener of this.eventListeners) {
@@ -23382,11 +24619,11 @@ var ProviderInstanceManager = class {
23382
24619
 
23383
24620
  // src/providers/version-archive.ts
23384
24621
  var fs11 = __toESM(require("fs"));
23385
- var path21 = __toESM(require("path"));
23386
- var os19 = __toESM(require("os"));
24622
+ var path22 = __toESM(require("path"));
24623
+ var os20 = __toESM(require("os"));
23387
24624
  var import_child_process10 = require("child_process");
23388
24625
  var import_os3 = require("os");
23389
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
24626
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23390
24627
  var MAX_ENTRIES_PER_PROVIDER = 20;
23391
24628
  var VersionArchive = class {
23392
24629
  history = {};
@@ -23433,7 +24670,7 @@ var VersionArchive = class {
23433
24670
  }
23434
24671
  save() {
23435
24672
  try {
23436
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
24673
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23437
24674
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23438
24675
  } catch {
23439
24676
  }
@@ -23489,8 +24726,8 @@ function getVersion(binary, versionCommand) {
23489
24726
  function checkPathExists2(paths) {
23490
24727
  for (const p of paths) {
23491
24728
  if (p.includes("*")) {
23492
- const home = os19.homedir();
23493
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
24729
+ const home = os20.homedir();
24730
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23494
24731
  if (fs11.existsSync(resolved)) return resolved;
23495
24732
  } else {
23496
24733
  if (fs11.existsSync(p)) return p;
@@ -23500,7 +24737,7 @@ function checkPathExists2(paths) {
23500
24737
  }
23501
24738
  function getMacAppVersion(appPath) {
23502
24739
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
23503
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
24740
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23504
24741
  if (!fs11.existsSync(plistPath)) return null;
23505
24742
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23506
24743
  return raw || null;
@@ -23526,7 +24763,7 @@ async function detectAllVersions(loader, archive) {
23526
24763
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23527
24764
  let resolvedBin = cliBin;
23528
24765
  if (!resolvedBin && appPath && currentOs === "darwin") {
23529
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24766
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23530
24767
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23531
24768
  }
23532
24769
  info.installed = !!(appPath || resolvedBin);
@@ -23567,7 +24804,7 @@ async function detectAllVersions(loader, archive) {
23567
24804
  // src/daemon/dev-server.ts
23568
24805
  var http2 = __toESM(require("http"));
23569
24806
  var fs15 = __toESM(require("fs"));
23570
- var path25 = __toESM(require("path"));
24807
+ var path26 = __toESM(require("path"));
23571
24808
  init_config();
23572
24809
 
23573
24810
  // src/daemon/scaffold-template.ts
@@ -23918,7 +25155,7 @@ init_logger();
23918
25155
 
23919
25156
  // src/daemon/dev-cdp-handlers.ts
23920
25157
  var fs12 = __toESM(require("fs"));
23921
- var path22 = __toESM(require("path"));
25158
+ var path23 = __toESM(require("path"));
23922
25159
  init_logger();
23923
25160
  async function handleCdpEvaluate(ctx, req, res) {
23924
25161
  const body = await ctx.readBody(req);
@@ -24097,17 +25334,17 @@ async function handleScriptHints(ctx, type, _req, res) {
24097
25334
  return;
24098
25335
  }
24099
25336
  let scriptsPath = "";
24100
- const directScripts = path22.join(dir, "scripts.js");
25337
+ const directScripts = path23.join(dir, "scripts.js");
24101
25338
  if (fs12.existsSync(directScripts)) {
24102
25339
  scriptsPath = directScripts;
24103
25340
  } else {
24104
- const scriptsDir = path22.join(dir, "scripts");
25341
+ const scriptsDir = path23.join(dir, "scripts");
24105
25342
  if (fs12.existsSync(scriptsDir)) {
24106
25343
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
24107
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
25344
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
24108
25345
  }).sort().reverse();
24109
25346
  for (const ver of versions) {
24110
- const p = path22.join(scriptsDir, ver, "scripts.js");
25347
+ const p = path23.join(scriptsDir, ver, "scripts.js");
24111
25348
  if (fs12.existsSync(p)) {
24112
25349
  scriptsPath = p;
24113
25350
  break;
@@ -24936,7 +26173,7 @@ async function handleDomContext(ctx, type, req, res) {
24936
26173
 
24937
26174
  // src/daemon/dev-cli-debug.ts
24938
26175
  var fs13 = __toESM(require("fs"));
24939
- var path23 = __toESM(require("path"));
26176
+ var path24 = __toESM(require("path"));
24940
26177
  function slugifyFixtureName(value) {
24941
26178
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24942
26179
  return normalized || `fixture-${Date.now()}`;
@@ -24946,11 +26183,11 @@ function getCliFixtureDir(ctx, type) {
24946
26183
  if (!providerDir) {
24947
26184
  throw new Error(`Provider directory not found for '${type}'`);
24948
26185
  }
24949
- return path23.join(providerDir, "fixtures");
26186
+ return path24.join(providerDir, "fixtures");
24950
26187
  }
24951
26188
  function readCliFixture(ctx, type, name) {
24952
26189
  const fixtureDir = getCliFixtureDir(ctx, type);
24953
- const filePath = path23.join(fixtureDir, `${name}.json`);
26190
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24954
26191
  if (!fs13.existsSync(filePath)) {
24955
26192
  throw new Error(`Fixture not found: ${filePath}`);
24956
26193
  }
@@ -25118,7 +26355,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
25118
26355
  if (!adapter) return null;
25119
26356
  return { target, instance, adapter };
25120
26357
  }
25121
- function sleep(ms) {
26358
+ function sleep2(ms) {
25122
26359
  return new Promise((resolve16) => setTimeout(resolve16, ms));
25123
26360
  }
25124
26361
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
@@ -25135,7 +26372,7 @@ async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
25135
26372
  return bundle;
25136
26373
  }
25137
26374
  }
25138
- await sleep(100);
26375
+ await sleep2(100);
25139
26376
  }
25140
26377
  return getCliTargetBundle(ctx, type, instanceId);
25141
26378
  }
@@ -25191,7 +26428,7 @@ async function runCliExerciseInternal(ctx, body) {
25191
26428
  const message = String(lastLaunchError.message || "");
25192
26429
  const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
25193
26430
  if (!retryable || attempt === 2) break;
25194
- await sleep(1e3);
26431
+ await sleep2(1e3);
25195
26432
  }
25196
26433
  }
25197
26434
  if (!launched) {
@@ -25254,16 +26491,16 @@ async function runCliExerciseInternal(ctx, body) {
25254
26491
  const modal = debug?.activeModal || trace?.activeModal || null;
25255
26492
  noteStatus(status);
25256
26493
  if (resolveActiveModalIfNeeded(status, modal)) {
25257
- await sleep(150);
26494
+ await sleep2(150);
25258
26495
  continue;
25259
26496
  }
25260
26497
  const startupParseGate = !!debug?.startupParseGate;
25261
26498
  if (status === "idle" && !startupParseGate) break;
25262
- await sleep(150);
26499
+ await sleep2(150);
25263
26500
  }
25264
26501
  ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
25265
26502
  while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
25266
- await sleep(150);
26503
+ await sleep2(150);
25267
26504
  bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
25268
26505
  if (!bundle) {
25269
26506
  throw new Error("CLI instance disappeared during exercise");
@@ -25717,7 +26954,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25717
26954
  },
25718
26955
  notes: typeof body?.notes === "string" ? body.notes : void 0
25719
26956
  };
25720
- const filePath = path23.join(fixtureDir, `${name}.json`);
26957
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25721
26958
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25722
26959
  ctx.json(res, 200, {
25723
26960
  saved: true,
@@ -25741,7 +26978,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25741
26978
  return;
25742
26979
  }
25743
26980
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
25744
- const fullPath = path23.join(fixtureDir, file);
26981
+ const fullPath = path24.join(fixtureDir, file);
25745
26982
  try {
25746
26983
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25747
26984
  return {
@@ -25877,8 +27114,8 @@ async function handleCliRaw(ctx, req, res) {
25877
27114
 
25878
27115
  // src/daemon/dev-auto-implement.ts
25879
27116
  var fs14 = __toESM(require("fs"));
25880
- var path24 = __toESM(require("path"));
25881
- var os20 = __toESM(require("os"));
27117
+ var path25 = __toESM(require("path"));
27118
+ var os21 = __toESM(require("os"));
25882
27119
  function getAutoImplPid(ctx) {
25883
27120
  const pid = ctx.autoImplProcess?.pid;
25884
27121
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25927,22 +27164,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25927
27164
  if (!fs14.existsSync(scriptsDir)) return null;
25928
27165
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25929
27166
  try {
25930
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
27167
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25931
27168
  } catch {
25932
27169
  return false;
25933
27170
  }
25934
27171
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25935
27172
  if (versions.length === 0) return null;
25936
- return path24.join(scriptsDir, versions[0]);
27173
+ return path25.join(scriptsDir, versions[0]);
25937
27174
  }
25938
27175
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25939
- const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25940
- const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25941
- const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25942
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
27176
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
27177
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
27178
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
27179
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25943
27180
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25944
27181
  }
25945
- if (path24.basename(desiredDir) !== type) {
27182
+ if (path25.basename(desiredDir) !== type) {
25946
27183
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25947
27184
  }
25948
27185
  const sourceDir = ctx.findProviderDir(type);
@@ -25950,11 +27187,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25950
27187
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25951
27188
  }
25952
27189
  if (!fs14.existsSync(desiredDir)) {
25953
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
27190
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25954
27191
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25955
27192
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25956
27193
  }
25957
- const providerJson = path24.join(desiredDir, "provider.json");
27194
+ const providerJson = path25.join(desiredDir, "provider.json");
25958
27195
  if (!fs14.existsSync(providerJson)) {
25959
27196
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25960
27197
  }
@@ -25965,13 +27202,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25965
27202
  const refDir = ctx.findProviderDir(referenceType);
25966
27203
  if (!refDir || !fs14.existsSync(refDir)) return {};
25967
27204
  const referenceScripts = {};
25968
- const scriptsDir = path24.join(refDir, "scripts");
27205
+ const scriptsDir = path25.join(refDir, "scripts");
25969
27206
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25970
27207
  if (!latestDir) return referenceScripts;
25971
27208
  for (const file of fs14.readdirSync(latestDir)) {
25972
27209
  if (!file.endsWith(".js")) continue;
25973
27210
  try {
25974
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
27211
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25975
27212
  } catch {
25976
27213
  }
25977
27214
  }
@@ -26079,9 +27316,9 @@ async function handleAutoImplement(ctx, type, req, res) {
26079
27316
  });
26080
27317
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
26081
27318
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
26082
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
27319
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
26083
27320
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
26084
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
27321
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26085
27322
  fs14.writeFileSync(promptFile, prompt, "utf-8");
26086
27323
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
26087
27324
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26234,7 +27471,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26234
27471
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26235
27472
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26236
27473
  let shellCmd;
26237
- const isWin = os20.platform() === "win32";
27474
+ const isWin = os21.platform() === "win32";
26238
27475
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26239
27476
  const promptMode = autoImpl?.promptMode ?? "stdin";
26240
27477
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26273,7 +27510,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26273
27510
  try {
26274
27511
  const pty = require("node-pty");
26275
27512
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26276
- const isWin2 = os20.platform() === "win32";
27513
+ const isWin2 = os21.platform() === "win32";
26277
27514
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26278
27515
  name: "xterm-256color",
26279
27516
  cols: 120,
@@ -26513,7 +27750,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26513
27750
  setMode: "set_mode.js"
26514
27751
  };
26515
27752
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26516
- const scriptsDir = path24.join(providerDir, "scripts");
27753
+ const scriptsDir = path25.join(providerDir, "scripts");
26517
27754
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26518
27755
  if (latestScriptsDir) {
26519
27756
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26524,7 +27761,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26524
27761
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26525
27762
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26526
27763
  try {
26527
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27764
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26528
27765
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26529
27766
  lines.push("```javascript");
26530
27767
  lines.push(content);
@@ -26541,7 +27778,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26541
27778
  lines.push("");
26542
27779
  for (const file of refFiles) {
26543
27780
  try {
26544
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27781
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26545
27782
  lines.push(`### \`${file}\` \u{1F512}`);
26546
27783
  lines.push("```javascript");
26547
27784
  lines.push(content);
@@ -26582,10 +27819,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26582
27819
  lines.push("");
26583
27820
  }
26584
27821
  }
26585
- const docsDir = path24.join(providerDir, "../../docs");
27822
+ const docsDir = path25.join(providerDir, "../../docs");
26586
27823
  const loadGuide = (name) => {
26587
27824
  try {
26588
- const p = path24.join(docsDir, name);
27825
+ const p = path25.join(docsDir, name);
26589
27826
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26590
27827
  } catch {
26591
27828
  }
@@ -26822,7 +28059,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26822
28059
  parseApproval: "parse_approval.js"
26823
28060
  };
26824
28061
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26825
- const scriptsDir = path24.join(providerDir, "scripts");
28062
+ const scriptsDir = path25.join(providerDir, "scripts");
26826
28063
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26827
28064
  if (latestScriptsDir) {
26828
28065
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26834,7 +28071,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26834
28071
  if (!file.endsWith(".js")) continue;
26835
28072
  if (!targetFileNames.has(file)) continue;
26836
28073
  try {
26837
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
28074
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26838
28075
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26839
28076
  lines.push("```javascript");
26840
28077
  lines.push(content);
@@ -26850,7 +28087,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26850
28087
  lines.push("");
26851
28088
  for (const file of refFiles) {
26852
28089
  try {
26853
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
28090
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26854
28091
  lines.push(`### \`${file}\` \u{1F512}`);
26855
28092
  lines.push("```javascript");
26856
28093
  lines.push(content);
@@ -26883,10 +28120,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26883
28120
  lines.push("");
26884
28121
  }
26885
28122
  }
26886
- const docsDir = path24.join(providerDir, "../../docs");
28123
+ const docsDir = path25.join(providerDir, "../../docs");
26887
28124
  const loadGuide = (name) => {
26888
28125
  try {
26889
- const p = path24.join(docsDir, name);
28126
+ const p = path25.join(docsDir, name);
26890
28127
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26891
28128
  } catch {
26892
28129
  }
@@ -27333,8 +28570,8 @@ var DevServer = class _DevServer {
27333
28570
  }
27334
28571
  getEndpointList() {
27335
28572
  return this.routes.map((r) => {
27336
- const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27337
- return `${r.method.padEnd(5)} ${path26}`;
28573
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28574
+ return `${r.method.padEnd(5)} ${path27}`;
27338
28575
  });
27339
28576
  }
27340
28577
  async start(port = DEV_SERVER_PORT) {
@@ -27622,12 +28859,12 @@ var DevServer = class _DevServer {
27622
28859
  // ─── DevConsole SPA ───
27623
28860
  getConsoleDistDir() {
27624
28861
  const candidates = [
27625
- path25.resolve(__dirname, "../../web-devconsole/dist"),
27626
- path25.resolve(__dirname, "../../../web-devconsole/dist"),
27627
- path25.join(process.cwd(), "packages/web-devconsole/dist")
28862
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
28863
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
28864
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27628
28865
  ];
27629
28866
  for (const dir of candidates) {
27630
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
28867
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27631
28868
  }
27632
28869
  return null;
27633
28870
  }
@@ -27637,7 +28874,7 @@ var DevServer = class _DevServer {
27637
28874
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27638
28875
  return;
27639
28876
  }
27640
- const htmlPath = path25.join(distDir, "index.html");
28877
+ const htmlPath = path26.join(distDir, "index.html");
27641
28878
  try {
27642
28879
  const html = fs15.readFileSync(htmlPath, "utf-8");
27643
28880
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27662,15 +28899,15 @@ var DevServer = class _DevServer {
27662
28899
  this.json(res, 404, { error: "Not found" });
27663
28900
  return;
27664
28901
  }
27665
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27666
- const filePath = path25.join(distDir, safePath);
28902
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28903
+ const filePath = path26.join(distDir, safePath);
27667
28904
  if (!filePath.startsWith(distDir)) {
27668
28905
  this.json(res, 403, { error: "Forbidden" });
27669
28906
  return;
27670
28907
  }
27671
28908
  try {
27672
28909
  const content = fs15.readFileSync(filePath);
27673
- const ext = path25.extname(filePath);
28910
+ const ext = path26.extname(filePath);
27674
28911
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27675
28912
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27676
28913
  res.end(content);
@@ -27783,9 +29020,9 @@ var DevServer = class _DevServer {
27783
29020
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27784
29021
  if (entry.isDirectory()) {
27785
29022
  files.push({ path: rel, size: 0, type: "dir" });
27786
- scan(path25.join(d, entry.name), rel);
29023
+ scan(path26.join(d, entry.name), rel);
27787
29024
  } else {
27788
- const stat2 = fs15.statSync(path25.join(d, entry.name));
29025
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27789
29026
  files.push({ path: rel, size: stat2.size, type: "file" });
27790
29027
  }
27791
29028
  }
@@ -27808,7 +29045,7 @@ var DevServer = class _DevServer {
27808
29045
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27809
29046
  return;
27810
29047
  }
27811
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
29048
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27812
29049
  if (!fullPath.startsWith(dir)) {
27813
29050
  this.json(res, 403, { error: "Forbidden" });
27814
29051
  return;
@@ -27833,14 +29070,14 @@ var DevServer = class _DevServer {
27833
29070
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27834
29071
  return;
27835
29072
  }
27836
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
29073
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27837
29074
  if (!fullPath.startsWith(dir)) {
27838
29075
  this.json(res, 403, { error: "Forbidden" });
27839
29076
  return;
27840
29077
  }
27841
29078
  try {
27842
29079
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27843
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
29080
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27844
29081
  fs15.writeFileSync(fullPath, content, "utf-8");
27845
29082
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27846
29083
  this.providerLoader.reload();
@@ -27857,7 +29094,7 @@ var DevServer = class _DevServer {
27857
29094
  return;
27858
29095
  }
27859
29096
  for (const name of ["scripts.js", "provider.json"]) {
27860
- const p = path25.join(dir, name);
29097
+ const p = path26.join(dir, name);
27861
29098
  if (fs15.existsSync(p)) {
27862
29099
  const source = fs15.readFileSync(p, "utf-8");
27863
29100
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27878,8 +29115,8 @@ var DevServer = class _DevServer {
27878
29115
  this.json(res, 404, { error: `Provider not found: ${type}` });
27879
29116
  return;
27880
29117
  }
27881
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27882
- const targetPath = path25.join(dir, target);
29118
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
29119
+ const targetPath = path26.join(dir, target);
27883
29120
  try {
27884
29121
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27885
29122
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -28026,7 +29263,7 @@ var DevServer = class _DevServer {
28026
29263
  }
28027
29264
  let targetDir;
28028
29265
  targetDir = this.providerLoader.getUserProviderDir(category, type);
28029
- const jsonPath = path25.join(targetDir, "provider.json");
29266
+ const jsonPath = path26.join(targetDir, "provider.json");
28030
29267
  if (fs15.existsSync(jsonPath)) {
28031
29268
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
28032
29269
  return;
@@ -28038,8 +29275,8 @@ var DevServer = class _DevServer {
28038
29275
  const createdFiles = ["provider.json"];
28039
29276
  if (result.files) {
28040
29277
  for (const [relPath, content] of Object.entries(result.files)) {
28041
- const fullPath = path25.join(targetDir, relPath);
28042
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
29278
+ const fullPath = path26.join(targetDir, relPath);
29279
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
28043
29280
  fs15.writeFileSync(fullPath, content, "utf-8");
28044
29281
  createdFiles.push(relPath);
28045
29282
  }
@@ -28092,22 +29329,22 @@ var DevServer = class _DevServer {
28092
29329
  if (!fs15.existsSync(scriptsDir)) return null;
28093
29330
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
28094
29331
  try {
28095
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
29332
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
28096
29333
  } catch {
28097
29334
  return false;
28098
29335
  }
28099
29336
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
28100
29337
  if (versions.length === 0) return null;
28101
- return path25.join(scriptsDir, versions[0]);
29338
+ return path26.join(scriptsDir, versions[0]);
28102
29339
  }
28103
29340
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
28104
- const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
28105
- const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
28106
- const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
28107
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
29341
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
29342
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
29343
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
29344
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
28108
29345
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
28109
29346
  }
28110
- if (path25.basename(desiredDir) !== type) {
29347
+ if (path26.basename(desiredDir) !== type) {
28111
29348
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
28112
29349
  }
28113
29350
  const sourceDir = this.findProviderDir(type);
@@ -28115,11 +29352,11 @@ var DevServer = class _DevServer {
28115
29352
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
28116
29353
  }
28117
29354
  if (!fs15.existsSync(desiredDir)) {
28118
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
29355
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
28119
29356
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
28120
29357
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
28121
29358
  }
28122
- const providerJson = path25.join(desiredDir, "provider.json");
29359
+ const providerJson = path26.join(desiredDir, "provider.json");
28123
29360
  if (!fs15.existsSync(providerJson)) {
28124
29361
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
28125
29362
  }
@@ -28155,7 +29392,7 @@ var DevServer = class _DevServer {
28155
29392
  setMode: "set_mode.js"
28156
29393
  };
28157
29394
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28158
- const scriptsDir = path25.join(providerDir, "scripts");
29395
+ const scriptsDir = path26.join(providerDir, "scripts");
28159
29396
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28160
29397
  if (latestScriptsDir) {
28161
29398
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28166,7 +29403,7 @@ var DevServer = class _DevServer {
28166
29403
  for (const file of fs15.readdirSync(latestScriptsDir)) {
28167
29404
  if (file.endsWith(".js") && targetFileNames.has(file)) {
28168
29405
  try {
28169
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29406
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28170
29407
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28171
29408
  lines.push("```javascript");
28172
29409
  lines.push(content);
@@ -28183,7 +29420,7 @@ var DevServer = class _DevServer {
28183
29420
  lines.push("");
28184
29421
  for (const file of refFiles) {
28185
29422
  try {
28186
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29423
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28187
29424
  lines.push(`### \`${file}\` \u{1F512}`);
28188
29425
  lines.push("```javascript");
28189
29426
  lines.push(content);
@@ -28224,10 +29461,10 @@ var DevServer = class _DevServer {
28224
29461
  lines.push("");
28225
29462
  }
28226
29463
  }
28227
- const docsDir = path25.join(providerDir, "../../docs");
29464
+ const docsDir = path26.join(providerDir, "../../docs");
28228
29465
  const loadGuide = (name) => {
28229
29466
  try {
28230
- const p = path25.join(docsDir, name);
29467
+ const p = path26.join(docsDir, name);
28231
29468
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28232
29469
  } catch {
28233
29470
  }
@@ -28401,7 +29638,7 @@ var DevServer = class _DevServer {
28401
29638
  parseApproval: "parse_approval.js"
28402
29639
  };
28403
29640
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28404
- const scriptsDir = path25.join(providerDir, "scripts");
29641
+ const scriptsDir = path26.join(providerDir, "scripts");
28405
29642
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28406
29643
  if (latestScriptsDir) {
28407
29644
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28413,7 +29650,7 @@ var DevServer = class _DevServer {
28413
29650
  if (!file.endsWith(".js")) continue;
28414
29651
  if (!targetFileNames.has(file)) continue;
28415
29652
  try {
28416
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29653
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28417
29654
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28418
29655
  lines.push("```javascript");
28419
29656
  lines.push(content);
@@ -28429,7 +29666,7 @@ var DevServer = class _DevServer {
28429
29666
  lines.push("");
28430
29667
  for (const file of refFiles) {
28431
29668
  try {
28432
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29669
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28433
29670
  lines.push(`### \`${file}\` \u{1F512}`);
28434
29671
  lines.push("```javascript");
28435
29672
  lines.push(content);
@@ -28462,10 +29699,10 @@ var DevServer = class _DevServer {
28462
29699
  lines.push("");
28463
29700
  }
28464
29701
  }
28465
- const docsDir = path25.join(providerDir, "../../docs");
29702
+ const docsDir = path26.join(providerDir, "../../docs");
28466
29703
  const loadGuide = (name) => {
28467
29704
  try {
28468
- const p = path25.join(docsDir, name);
29705
+ const p = path26.join(docsDir, name);
28469
29706
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28470
29707
  } catch {
28471
29708
  }
@@ -29151,29 +30388,58 @@ function resolveSessionHostAppName(options = {}) {
29151
30388
  var import_session_host_core4 = require("@adhdev/session-host-core");
29152
30389
  var STARTUP_TIMEOUT_MS = DEFAULT_SESSION_HOST_READY_TIMEOUT_MS;
29153
30390
  var STARTUP_POLL_MS = 200;
29154
- async function canConnect(endpoint) {
30391
+ var SessionHostCompatibilityError = class extends Error {
30392
+ constructor(message) {
30393
+ super(message);
30394
+ this.name = "SessionHostCompatibilityError";
30395
+ }
30396
+ };
30397
+ function getMissingRequestTypes(diagnostics, requiredRequestTypes) {
30398
+ const supported = new Set(diagnostics?.supportedRequestTypes || []);
30399
+ return requiredRequestTypes.filter((requestType) => !supported.has(requestType));
30400
+ }
30401
+ async function assertRequiredRequestTypes(client, requiredRequestTypes) {
30402
+ if (requiredRequestTypes.length === 0) return;
30403
+ const response = await client.request({
30404
+ type: "get_host_diagnostics",
30405
+ payload: { includeSessions: false }
30406
+ });
30407
+ const missing = getMissingRequestTypes(response.success ? response.result : void 0, requiredRequestTypes);
30408
+ if (missing.length > 0) {
30409
+ const detail = response.success ? "" : ` (${response.error || "capability probe failed"})`;
30410
+ throw new SessionHostCompatibilityError(
30411
+ `Session host does not support required request types: ${missing.join(", ")}${detail}`
30412
+ );
30413
+ }
30414
+ }
30415
+ async function canConnect(endpoint, requiredRequestTypes = []) {
29155
30416
  const client = new import_session_host_core4.SessionHostClient({ endpoint });
29156
30417
  try {
29157
30418
  await client.connect();
29158
- await client.close();
30419
+ await assertRequiredRequestTypes(client, requiredRequestTypes);
29159
30420
  return true;
29160
- } catch {
30421
+ } catch (error) {
30422
+ if (error instanceof SessionHostCompatibilityError) throw error;
29161
30423
  return false;
30424
+ } finally {
30425
+ await client.close().catch(() => {
30426
+ });
29162
30427
  }
29163
30428
  }
29164
- async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
30429
+ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS, requiredRequestTypes = []) {
29165
30430
  const deadline = Date.now() + timeoutMs;
29166
30431
  while (Date.now() < deadline) {
29167
- if (await canConnect(endpoint)) return;
30432
+ if (await canConnect(endpoint, requiredRequestTypes)) return;
29168
30433
  await new Promise((resolve16) => setTimeout(resolve16, STARTUP_POLL_MS));
29169
30434
  }
29170
30435
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
29171
30436
  }
29172
30437
  async function ensureSessionHostReady(options) {
29173
30438
  const endpoint = (0, import_session_host_core4.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
29174
- if (await canConnect(endpoint)) return endpoint;
30439
+ const requiredRequestTypes = options.requiredRequestTypes || [];
30440
+ if (await canConnect(endpoint, requiredRequestTypes)) return endpoint;
29175
30441
  options.spawnHost();
29176
- await waitForReady(endpoint, options.timeoutMs);
30442
+ await waitForReady(endpoint, options.timeoutMs, requiredRequestTypes);
29177
30443
  return endpoint;
29178
30444
  }
29179
30445
  async function listHostedCliRuntimes(endpoint) {
@@ -29465,48 +30731,6 @@ var SessionRegistry = class {
29465
30731
  // src/boot/daemon-lifecycle.ts
29466
30732
  init_logger();
29467
30733
  init_config();
29468
-
29469
- // src/mesh/mesh-events.ts
29470
- init_mesh_config();
29471
- init_logger();
29472
- function setupMeshEventForwarding(components) {
29473
- components.instanceManager.onEvent((event) => {
29474
- if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
29475
- const instanceId = event.instanceId;
29476
- if (!instanceId) return;
29477
- const sourceInstance = components.instanceManager.getInstance(instanceId);
29478
- if (!sourceInstance || sourceInstance.category !== "cli") return;
29479
- const state = sourceInstance.getState();
29480
- const workspace = state.workspace;
29481
- if (!workspace) return;
29482
- const mesh = getMeshByRepo(workspace);
29483
- if (!mesh) return;
29484
- const allInstances = components.instanceManager.getByCategory("cli");
29485
- const coordinatorInstances = allInstances.filter((inst) => {
29486
- const instState = inst.getState();
29487
- if (instState.settings?.meshCoordinatorFor !== mesh.id) return false;
29488
- if (instState.instanceId === instanceId) return false;
29489
- return true;
29490
- });
29491
- if (coordinatorInstances.length === 0) return;
29492
- const targetNode = mesh.nodes.find((n) => n.workspace === workspace);
29493
- const nodeLabel = targetNode ? `Node '${targetNode.id}'` : `Agent at ${workspace}`;
29494
- let messageText = "";
29495
- if (event.event === "agent:generating_completed") {
29496
- messageText = `[System] ${nodeLabel} has completed its task and is now idle. You may use mesh_read_chat to review its progress.`;
29497
- } else if (event.event === "agent:waiting_approval") {
29498
- messageText = `[System] ${nodeLabel} is waiting for approval to proceed. You may use mesh_read_chat and mesh_approve to handle it.`;
29499
- }
29500
- if (!messageText) return;
29501
- for (const coord of coordinatorInstances) {
29502
- const coordState = coord.getState();
29503
- LOG.info("MeshEvents", `Forwarding event from ${workspace} to coordinator ${coordState.instanceId}`);
29504
- coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
29505
- }
29506
- });
29507
- }
29508
-
29509
- // src/boot/daemon-lifecycle.ts
29510
30734
  async function initDaemonComponents(config) {
29511
30735
  installGlobalInterceptor();
29512
30736
  const appConfig = loadConfig();
@@ -29739,6 +30963,12 @@ async function shutdownDaemonComponents(components) {
29739
30963
  AcpProviderInstance,
29740
30964
  AgentStreamPoller,
29741
30965
  BUILTIN_CHAT_MESSAGE_KINDS,
30966
+ CHAT_MESSAGE_ACTIVITY_SOURCES,
30967
+ CHAT_MESSAGE_AUDIENCES,
30968
+ CHAT_MESSAGE_INTERNAL_SOURCES,
30969
+ CHAT_MESSAGE_SOURCES,
30970
+ CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES,
30971
+ CHAT_MESSAGE_VISIBILITIES,
29742
30972
  CdpDomHandlers,
29743
30973
  CliProviderInstance,
29744
30974
  DAEMON_WS_PATH,
@@ -29801,6 +31031,7 @@ async function shutdownDaemonComponents(components) {
29801
31031
  buildThoughtChatMessage,
29802
31032
  buildToolChatMessage,
29803
31033
  buildUserChatMessage,
31034
+ classifyChatMessageVisibility,
29804
31035
  classifyHotChatSessionsForSubscriptionFlush,
29805
31036
  clearDebugTrace,
29806
31037
  compareGitSnapshots,
@@ -29813,12 +31044,17 @@ async function shutdownDaemonComponents(components) {
29813
31044
  createGitWorkspaceMonitor,
29814
31045
  createInteractionId,
29815
31046
  createMesh,
31047
+ createWorktree,
29816
31048
  deleteMesh,
29817
31049
  detectAllVersions,
29818
31050
  detectCLIs,
29819
31051
  detectIDEs,
29820
31052
  ensureSessionHostReady,
29821
31053
  execNpmCommandSync,
31054
+ filterActivityChatMessages,
31055
+ filterChatMessagesByVisibility,
31056
+ filterInternalChatMessages,
31057
+ filterUserFacingChatMessages,
29822
31058
  findCdpManager,
29823
31059
  flattenMessageParts,
29824
31060
  forwardAgentStreamsToIdeInstance,
@@ -29849,22 +31085,26 @@ async function shutdownDaemonComponents(components) {
29849
31085
  initDaemonComponents,
29850
31086
  installExtensions,
29851
31087
  installGlobalInterceptor,
31088
+ isActivityChatMessage,
29852
31089
  isBuiltinChatMessageKind,
29853
31090
  isCdpConnected,
29854
31091
  isExtensionInstalled,
29855
31092
  isGitCommandName,
29856
31093
  isIdeRunning,
31094
+ isInternalChatMessage,
29857
31095
  isManagedStatusWaiting,
29858
31096
  isManagedStatusWorking,
29859
31097
  isPathInside,
29860
31098
  isSessionHostLiveRuntime,
29861
31099
  isSessionHostRecoverySnapshot,
29862
31100
  isSetupComplete,
31101
+ isUserFacingChatMessage,
29863
31102
  killIdeProcess,
29864
31103
  launchIDE,
29865
31104
  launchWithCdp,
29866
31105
  listHostedCliRuntimes,
29867
31106
  listMeshes,
31107
+ listWorktrees,
29868
31108
  loadConfig,
29869
31109
  loadState,
29870
31110
  logCommand,
@@ -29884,6 +31124,7 @@ async function shutdownDaemonComponents(components) {
29884
31124
  normalizeSessionModalFields,
29885
31125
  parsePorcelainV2Status,
29886
31126
  parseProviderSourceConfigUpdate,
31127
+ parseWorktreeListOutput,
29887
31128
  partitionSessionHostDiagnosticsSessions,
29888
31129
  partitionSessionHostRecords,
29889
31130
  prepareSessionChatTailUpdate,
@@ -29893,6 +31134,7 @@ async function shutdownDaemonComponents(components) {
29893
31134
  recordDebugTrace,
29894
31135
  registerExtensionProviders,
29895
31136
  removeNode,
31137
+ removeWorktree,
29896
31138
  resetConfig,
29897
31139
  resetDebugRuntimeConfig,
29898
31140
  resetState,
@@ -29902,6 +31144,7 @@ async function shutdownDaemonComponents(components) {
29902
31144
  resolveGitRepository,
29903
31145
  resolveSessionHostAppName,
29904
31146
  resolveSessionHostAppNameResolution,
31147
+ resolveWorktreePath,
29905
31148
  runAsyncBatch,
29906
31149
  runGit,
29907
31150
  saveConfig,