@adhdev/daemon-core 0.9.76-rc.4 → 0.9.76-rc.41

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 (46) 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.js +1318 -426
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +1345 -457
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/mesh/coordinator-prompt.d.ts +1 -0
  15. package/dist/mesh/mesh-events.d.ts +9 -0
  16. package/dist/providers/chat-message-normalization.d.ts +11 -0
  17. package/dist/providers/cli-provider-instance.d.ts +3 -0
  18. package/dist/providers/provider-instance-manager.d.ts +1 -0
  19. package/dist/providers/provider-instance.d.ts +2 -0
  20. package/dist/repo-mesh-types.d.ts +13 -0
  21. package/dist/shared-types.d.ts +22 -1
  22. package/package.json +3 -4
  23. package/src/cli-adapters/provider-cli-adapter.ts +13 -6
  24. package/src/cli-adapters/provider-cli-runtime.ts +3 -2
  25. package/src/commands/chat-commands.ts +76 -5
  26. package/src/commands/cli-manager.ts +78 -5
  27. package/src/commands/handler.ts +13 -4
  28. package/src/commands/mesh-coordinator.ts +149 -6
  29. package/src/commands/router.d.ts +1 -0
  30. package/src/commands/router.ts +505 -34
  31. package/src/config/mesh-config.ts +23 -2
  32. package/src/git/git-commands.ts +5 -1
  33. package/src/git/git-types.ts +1 -0
  34. package/src/git/git-worktree.ts +214 -0
  35. package/src/git/index.ts +14 -0
  36. package/src/mesh/coordinator-prompt.ts +25 -10
  37. package/src/mesh/mesh-events.ts +109 -43
  38. package/src/providers/chat-message-normalization.ts +54 -0
  39. package/src/providers/cli-provider-instance.d.ts +2 -0
  40. package/src/providers/cli-provider-instance.ts +55 -7
  41. package/src/providers/provider-instance-manager.ts +20 -1
  42. package/src/providers/provider-instance.ts +2 -0
  43. package/src/repo-mesh-types.ts +15 -0
  44. package/src/shared-types.ts +24 -1
  45. package/src/status/builders.ts +17 -12
  46. package/src/status/reporter.ts +6 -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.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
674
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
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.
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.
543
710
  4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
544
711
  5. **Verify** \u2014 When a task reports completion, 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}`);
@@ -3727,6 +3886,7 @@ __export(index_exports, {
3727
3886
  createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
3728
3887
  createInteractionId: () => createInteractionId,
3729
3888
  createMesh: () => createMesh,
3889
+ createWorktree: () => createWorktree,
3730
3890
  deleteMesh: () => deleteMesh,
3731
3891
  detectAllVersions: () => detectAllVersions,
3732
3892
  detectCLIs: () => detectCLIs,
@@ -3779,6 +3939,7 @@ __export(index_exports, {
3779
3939
  launchWithCdp: () => launchWithCdp,
3780
3940
  listHostedCliRuntimes: () => listHostedCliRuntimes,
3781
3941
  listMeshes: () => listMeshes,
3942
+ listWorktrees: () => listWorktrees,
3782
3943
  loadConfig: () => loadConfig,
3783
3944
  loadState: () => loadState,
3784
3945
  logCommand: () => logCommand,
@@ -3798,6 +3959,7 @@ __export(index_exports, {
3798
3959
  normalizeSessionModalFields: () => normalizeSessionModalFields,
3799
3960
  parsePorcelainV2Status: () => parsePorcelainV2Status,
3800
3961
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
3962
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
3801
3963
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
3802
3964
  partitionSessionHostRecords: () => partitionSessionHostRecords,
3803
3965
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
@@ -3807,6 +3969,7 @@ __export(index_exports, {
3807
3969
  recordDebugTrace: () => recordDebugTrace,
3808
3970
  registerExtensionProviders: () => registerExtensionProviders,
3809
3971
  removeNode: () => removeNode,
3972
+ removeWorktree: () => removeWorktree,
3810
3973
  resetConfig: () => resetConfig,
3811
3974
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
3812
3975
  resetState: () => resetState,
@@ -3816,6 +3979,7 @@ __export(index_exports, {
3816
3979
  resolveGitRepository: () => resolveGitRepository,
3817
3980
  resolveSessionHostAppName: () => resolveSessionHostAppName,
3818
3981
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
3982
+ resolveWorktreePath: () => resolveWorktreePath,
3819
3983
  runAsyncBatch: () => runAsyncBatch,
3820
3984
  runGit: () => runGit,
3821
3985
  saveConfig: () => saveConfig,
@@ -4739,6 +4903,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
4739
4903
  "dirty_index_required",
4740
4904
  "conflict",
4741
4905
  "invalid_args",
4906
+ "nothing_to_commit",
4742
4907
  "git_command_failed"
4743
4908
  ]);
4744
4909
  function failure(reason, error) {
@@ -4983,7 +5148,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
4983
5148
  } catch (err) {
4984
5149
  const output = (err?.stdout || "") + (err?.stderr || "");
4985
5150
  if (/nothing to commit/i.test(output)) {
4986
- throw new GitCommandError("git_command_failed", "Nothing to commit");
5151
+ throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
5152
+ stdout: err?.stdout,
5153
+ stderr: err?.stderr
5154
+ });
4987
5155
  }
4988
5156
  throw err;
4989
5157
  }
@@ -5175,20 +5343,23 @@ var TurnSnapshotTracker = class {
5175
5343
  }
5176
5344
  };
5177
5345
 
5346
+ // src/git/index.ts
5347
+ init_git_worktree();
5348
+
5178
5349
  // src/index.ts
5179
5350
  init_config();
5180
5351
 
5181
5352
  // src/config/workspaces.ts
5182
5353
  var fs = __toESM(require("fs"));
5183
5354
  var os = __toESM(require("os"));
5184
- var path4 = __toESM(require("path"));
5355
+ var path5 = __toESM(require("path"));
5185
5356
  var import_crypto2 = require("crypto");
5186
5357
  var MAX_WORKSPACES = 50;
5187
5358
  function expandPath(p) {
5188
5359
  const t = (p || "").trim();
5189
5360
  if (!t) return "";
5190
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5191
- return path4.resolve(t);
5361
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5362
+ return path5.resolve(t);
5192
5363
  }
5193
5364
  function validateWorkspacePath(absPath) {
5194
5365
  try {
@@ -5202,7 +5373,7 @@ function validateWorkspacePath(absPath) {
5202
5373
  }
5203
5374
  }
5204
5375
  function defaultWorkspaceLabel(absPath) {
5205
- const base = path4.basename(absPath) || absPath;
5376
+ const base = path5.basename(absPath) || absPath;
5206
5377
  return base;
5207
5378
  }
5208
5379
  function getDefaultWorkspacePath(config) {
@@ -5293,9 +5464,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5293
5464
  return getDefaultWorkspacePath(config) || void 0;
5294
5465
  }
5295
5466
  function findWorkspaceByPath(config, rawPath) {
5296
- const abs = path4.resolve(expandPath(rawPath));
5467
+ const abs = path5.resolve(expandPath(rawPath));
5297
5468
  if (!abs) return void 0;
5298
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5469
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5299
5470
  }
5300
5471
  function addWorkspaceEntry(config, rawPath, label, options) {
5301
5472
  const abs = expandPath(rawPath);
@@ -5311,7 +5482,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5311
5482
  const v = validateWorkspacePath(abs);
5312
5483
  if (!v.ok) return { error: v.error };
5313
5484
  const list = [...config.workspaces || []];
5314
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5485
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5315
5486
  return { error: "Workspace already in list" };
5316
5487
  }
5317
5488
  if (list.length >= MAX_WORKSPACES) {
@@ -5345,7 +5516,7 @@ function setDefaultWorkspaceId(config, id) {
5345
5516
  }
5346
5517
 
5347
5518
  // src/config/recent-activity.ts
5348
- var path5 = __toESM(require("path"));
5519
+ var path6 = __toESM(require("path"));
5349
5520
 
5350
5521
  // src/providers/summary-metadata.ts
5351
5522
  function normalizeSummaryItem(item) {
@@ -5414,9 +5585,9 @@ var MAX_ACTIVITY = 30;
5414
5585
  function normalizeWorkspace(workspace) {
5415
5586
  if (!workspace) return "";
5416
5587
  try {
5417
- return path5.resolve(expandPath(workspace));
5588
+ return path6.resolve(expandPath(workspace));
5418
5589
  } catch {
5419
- return path5.resolve(workspace);
5590
+ return path6.resolve(workspace);
5420
5591
  }
5421
5592
  }
5422
5593
  function buildRecentActivityKey(entry) {
@@ -5584,14 +5755,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5584
5755
  }
5585
5756
 
5586
5757
  // src/config/saved-sessions.ts
5587
- var path6 = __toESM(require("path"));
5758
+ var path7 = __toESM(require("path"));
5588
5759
  var MAX_SAVED_SESSIONS = 500;
5589
5760
  function normalizeWorkspace2(workspace) {
5590
5761
  if (!workspace) return "";
5591
5762
  try {
5592
- return path6.resolve(expandPath(workspace));
5763
+ return path7.resolve(expandPath(workspace));
5593
5764
  } catch {
5594
- return path6.resolve(workspace);
5765
+ return path7.resolve(workspace);
5595
5766
  }
5596
5767
  }
5597
5768
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5770,7 +5941,7 @@ function resetState() {
5770
5941
  var import_child_process = require("child_process");
5771
5942
  var import_fs4 = require("fs");
5772
5943
  var import_os2 = require("os");
5773
- var path7 = __toESM(require("path"));
5944
+ var path8 = __toESM(require("path"));
5774
5945
  var BUILTIN_IDE_DEFINITIONS = [];
5775
5946
  var registeredIDEs = /* @__PURE__ */ new Map();
5776
5947
  function registerIDEDefinition(def) {
@@ -5789,9 +5960,9 @@ function getMergedDefinitions() {
5789
5960
  function findCliCommand(command) {
5790
5961
  const trimmed = String(command || "").trim();
5791
5962
  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);
5963
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5964
+ const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5965
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5795
5966
  return (0, import_fs4.existsSync)(resolved) ? resolved : null;
5796
5967
  }
5797
5968
  try {
@@ -5819,7 +5990,7 @@ function getIdeVersion(cliCommand) {
5819
5990
  function checkPathExists(paths) {
5820
5991
  const home = (0, import_os2.homedir)();
5821
5992
  for (const p of paths) {
5822
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
5993
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5823
5994
  if (normalized.includes("*")) {
5824
5995
  const username = home.split(/[\\/]/).pop() || "";
5825
5996
  const resolved = normalized.replace("*", username);
@@ -5831,19 +6002,19 @@ function checkPathExists(paths) {
5831
6002
  return null;
5832
6003
  }
5833
6004
  async function detectIDEs(providerLoader) {
5834
- const os21 = (0, import_os2.platform)();
6005
+ const os22 = (0, import_os2.platform)();
5835
6006
  const results = [];
5836
6007
  for (const def of getMergedDefinitions()) {
5837
6008
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5838
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
6009
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5839
6010
  let resolvedCli = cliPath;
5840
- if (!resolvedCli && appPath && os21 === "darwin") {
6011
+ if (!resolvedCli && appPath && os22 === "darwin") {
5841
6012
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5842
6013
  if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
5843
6014
  }
5844
- if (!resolvedCli && appPath && os21 === "win32") {
5845
- const { dirname: dirname8 } = await import("path");
5846
- const appDir = dirname8(appPath);
6015
+ if (!resolvedCli && appPath && os22 === "win32") {
6016
+ const { dirname: dirname9 } = await import("path");
6017
+ const appDir = dirname9(appPath);
5847
6018
  const candidates = [
5848
6019
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5849
6020
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5858,7 +6029,7 @@ async function detectIDEs(providerLoader) {
5858
6029
  }
5859
6030
  }
5860
6031
  }
5861
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
6032
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5862
6033
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5863
6034
  results.push({
5864
6035
  id: def.id,
@@ -5877,7 +6048,7 @@ async function detectIDEs(providerLoader) {
5877
6048
  // src/detection/cli-detector.ts
5878
6049
  var import_child_process2 = require("child_process");
5879
6050
  var os2 = __toESM(require("os"));
5880
- var path8 = __toESM(require("path"));
6051
+ var path9 = __toESM(require("path"));
5881
6052
  var import_fs5 = require("fs");
5882
6053
  function parseVersion(raw) {
5883
6054
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -5890,18 +6061,18 @@ function shellQuote(value) {
5890
6061
  function expandHome(value) {
5891
6062
  const trimmed = value.trim();
5892
6063
  if (!trimmed.startsWith("~")) return trimmed;
5893
- return path8.join(os2.homedir(), trimmed.slice(1));
6064
+ return path9.join(os2.homedir(), trimmed.slice(1));
5894
6065
  }
5895
6066
  function isExplicitCommandPath(command) {
5896
6067
  const trimmed = command.trim();
5897
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
6068
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5898
6069
  }
5899
6070
  function resolveCommandPath(command) {
5900
6071
  const trimmed = command.trim();
5901
6072
  if (!trimmed) return null;
5902
6073
  if (isExplicitCommandPath(trimmed)) {
5903
6074
  const expanded = expandHome(trimmed);
5904
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
6075
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5905
6076
  return (0, import_fs5.existsSync)(candidate) ? candidate : null;
5906
6077
  }
5907
6078
  return null;
@@ -8170,9 +8341,9 @@ ${cleanBody}`;
8170
8341
 
8171
8342
  // src/config/chat-history.ts
8172
8343
  var fs3 = __toESM(require("fs"));
8173
- var path10 = __toESM(require("path"));
8344
+ var path11 = __toESM(require("path"));
8174
8345
  var os5 = __toESM(require("os"));
8175
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8346
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
8176
8347
  var RETAIN_DAYS = 30;
8177
8348
  var SAVED_HISTORY_INDEX_VERSION = 1;
8178
8349
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8335,7 +8506,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8335
8506
  function buildSavedHistoryFileSignatureMap(dir, files) {
8336
8507
  return new Map(files.map((file) => {
8337
8508
  try {
8338
- const stat2 = fs3.statSync(path10.join(dir, file));
8509
+ const stat2 = fs3.statSync(path11.join(dir, file));
8339
8510
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8340
8511
  } catch {
8341
8512
  return [file, `${file}:missing`];
@@ -8346,7 +8517,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8346
8517
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8347
8518
  }
8348
8519
  function getSavedHistoryIndexFilePath(dir) {
8349
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8520
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8350
8521
  }
8351
8522
  function getSavedHistoryIndexLockPath(dir) {
8352
8523
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8448,7 +8619,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8448
8619
  }
8449
8620
  for (const file of Array.from(currentEntries.keys())) {
8450
8621
  if (incomingFiles.has(file)) continue;
8451
- if (!fs3.existsSync(path10.join(dir, file))) {
8622
+ if (!fs3.existsSync(path11.join(dir, file))) {
8452
8623
  currentEntries.delete(file);
8453
8624
  }
8454
8625
  }
@@ -8474,7 +8645,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8474
8645
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8475
8646
  const files = listHistoryFiles(dir);
8476
8647
  for (const file of files) {
8477
- const stat2 = fs3.statSync(path10.join(dir, file));
8648
+ const stat2 = fs3.statSync(path11.join(dir, file));
8478
8649
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8479
8650
  }
8480
8651
  return false;
@@ -8484,14 +8655,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8484
8655
  }
8485
8656
  function buildSavedHistoryFileSignature(dir, file) {
8486
8657
  try {
8487
- const stat2 = fs3.statSync(path10.join(dir, file));
8658
+ const stat2 = fs3.statSync(path11.join(dir, file));
8488
8659
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8489
8660
  } catch {
8490
8661
  return `${file}:missing`;
8491
8662
  }
8492
8663
  }
8493
8664
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8494
- const filePath = path10.join(dir, file);
8665
+ const filePath = path11.join(dir, file);
8495
8666
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8496
8667
  const currentEntry = entries.get(file) || null;
8497
8668
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8564,7 +8735,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8564
8735
  function computeSavedHistoryFileSummary(dir, file) {
8565
8736
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8566
8737
  if (!historySessionId) return null;
8567
- const filePath = path10.join(dir, file);
8738
+ const filePath = path11.join(dir, file);
8568
8739
  const content = fs3.readFileSync(filePath, "utf-8");
8569
8740
  const lines = content.split("\n").filter(Boolean);
8570
8741
  let messageCount = 0;
@@ -8651,7 +8822,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8651
8822
  const summaryBySessionId = /* @__PURE__ */ new Map();
8652
8823
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8653
8824
  for (const file of files.slice().sort()) {
8654
- const filePath = path10.join(dir, file);
8825
+ const filePath = path11.join(dir, file);
8655
8826
  const signature = fileSignatures.get(file) || `${file}:missing`;
8656
8827
  const cached = savedHistoryFileSummaryCache.get(filePath);
8657
8828
  const persisted = persistedEntries.get(file);
@@ -8771,12 +8942,12 @@ var ChatHistoryWriter = class {
8771
8942
  });
8772
8943
  }
8773
8944
  if (newMessages.length === 0) return;
8774
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8945
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8775
8946
  fs3.mkdirSync(dir, { recursive: true });
8776
8947
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8777
8948
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8778
8949
  const fileName = `${filePrefix}${date}.jsonl`;
8779
- const filePath = path10.join(dir, fileName);
8950
+ const filePath = path11.join(dir, fileName);
8780
8951
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8781
8952
  fs3.appendFileSync(filePath, lines, "utf-8");
8782
8953
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8867,11 +9038,11 @@ var ChatHistoryWriter = class {
8867
9038
  const ws = String(workspace || "").trim();
8868
9039
  if (!id || !ws) return;
8869
9040
  try {
8870
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9041
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8871
9042
  fs3.mkdirSync(dir, { recursive: true });
8872
9043
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8873
9044
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8874
- const filePath = path10.join(dir, fileName);
9045
+ const filePath = path11.join(dir, fileName);
8875
9046
  const record = {
8876
9047
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8877
9048
  receivedAt: Date.now(),
@@ -8917,14 +9088,14 @@ var ChatHistoryWriter = class {
8917
9088
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8918
9089
  this.lastSeenCounts.delete(fromDedupKey);
8919
9090
  }
8920
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9091
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8921
9092
  if (!fs3.existsSync(dir)) return;
8922
9093
  const fromPrefix = `${this.sanitize(fromId)}_`;
8923
9094
  const toPrefix = `${this.sanitize(toId)}_`;
8924
9095
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8925
9096
  for (const file of files) {
8926
- const sourcePath = path10.join(dir, file);
8927
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
9097
+ const sourcePath = path11.join(dir, file);
9098
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8928
9099
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8929
9100
  const rewritten = sourceLines.map((line) => {
8930
9101
  try {
@@ -8958,13 +9129,13 @@ var ChatHistoryWriter = class {
8958
9129
  const sessionId = String(historySessionId || "").trim();
8959
9130
  if (!sessionId) return;
8960
9131
  try {
8961
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9132
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8962
9133
  if (!fs3.existsSync(dir)) return;
8963
9134
  const prefix = `${this.sanitize(sessionId)}_`;
8964
9135
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8965
9136
  const seen = /* @__PURE__ */ new Set();
8966
9137
  for (const file of files) {
8967
- const filePath = path10.join(dir, file);
9138
+ const filePath = path11.join(dir, file);
8968
9139
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8969
9140
  const next = [];
8970
9141
  for (const line of lines) {
@@ -9018,11 +9189,11 @@ var ChatHistoryWriter = class {
9018
9189
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
9019
9190
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
9020
9191
  for (const dir of agentDirs) {
9021
- const dirPath = path10.join(HISTORY_DIR, dir.name);
9192
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
9022
9193
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
9023
9194
  let removedAny = false;
9024
9195
  for (const file of files) {
9025
- const filePath = path10.join(dirPath, file);
9196
+ const filePath = path11.join(dirPath, file);
9026
9197
  const stat2 = fs3.statSync(filePath);
9027
9198
  if (stat2.mtimeMs < cutoff) {
9028
9199
  fs3.unlinkSync(filePath);
@@ -9072,13 +9243,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
9072
9243
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
9073
9244
  try {
9074
9245
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9075
- const dir = path10.join(HISTORY_DIR, sanitized);
9246
+ const dir = path11.join(HISTORY_DIR, sanitized);
9076
9247
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
9077
9248
  const files = listHistoryFiles(dir, historySessionId);
9078
9249
  const allMessages = [];
9079
9250
  const seen = /* @__PURE__ */ new Set();
9080
9251
  for (const file of files) {
9081
- const filePath = path10.join(dir, file);
9252
+ const filePath = path11.join(dir, file);
9082
9253
  const content = fs3.readFileSync(filePath, "utf-8");
9083
9254
  const lines = content.trim().split("\n").filter(Boolean);
9084
9255
  for (let i = 0; i < lines.length; i++) {
@@ -9102,7 +9273,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
9102
9273
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9103
9274
  try {
9104
9275
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9105
- const dir = path10.join(HISTORY_DIR, sanitized);
9276
+ const dir = path11.join(HISTORY_DIR, sanitized);
9106
9277
  if (!fs3.existsSync(dir)) {
9107
9278
  savedHistorySessionCache.delete(sanitized);
9108
9279
  return { sessions: [], hasMore: false };
@@ -9163,11 +9334,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9163
9334
  }
9164
9335
  function readExistingSessionStartRecord(agentType, historySessionId) {
9165
9336
  try {
9166
- const dir = path10.join(HISTORY_DIR, agentType);
9337
+ const dir = path11.join(HISTORY_DIR, agentType);
9167
9338
  if (!fs3.existsSync(dir)) return null;
9168
9339
  const files = listHistoryFiles(dir, historySessionId).sort();
9169
9340
  for (const file of files) {
9170
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9341
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
9171
9342
  for (const line of lines) {
9172
9343
  try {
9173
9344
  const parsed = JSON.parse(line);
@@ -9187,16 +9358,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
9187
9358
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
9188
9359
  if (records.length === 0) return false;
9189
9360
  try {
9190
- const dir = path10.join(HISTORY_DIR, agentType);
9361
+ const dir = path11.join(HISTORY_DIR, agentType);
9191
9362
  fs3.mkdirSync(dir, { recursive: true });
9192
9363
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9193
9364
  for (const file of fs3.readdirSync(dir)) {
9194
9365
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9195
- fs3.unlinkSync(path10.join(dir, file));
9366
+ fs3.unlinkSync(path11.join(dir, file));
9196
9367
  }
9197
9368
  }
9198
9369
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9199
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9370
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9200
9371
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9201
9372
  `, "utf-8");
9202
9373
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -11191,6 +11362,14 @@ function getActiveChatOptions(profile) {
11191
11362
  if (profile === "full") return {};
11192
11363
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11193
11364
  }
11365
+ function resolveSessionStatus(activeChat, providerStatus) {
11366
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11367
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11368
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11369
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11370
+ if (topLevelStatus !== "idle") return topLevelStatus;
11371
+ return chatStatus;
11372
+ }
11194
11373
  function shouldIncludeSessionControls(profile) {
11195
11374
  return profile !== "live";
11196
11375
  }
@@ -11269,9 +11448,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11269
11448
  providerName: state.name,
11270
11449
  kind: "workspace",
11271
11450
  transport: "cdp-page",
11272
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11273
- activeModal: activeChat?.activeModal || null
11274
- }),
11451
+ status: resolveSessionStatus(activeChat, state.status),
11275
11452
  title,
11276
11453
  workspace,
11277
11454
  ...git && { git },
@@ -11306,9 +11483,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11306
11483
  providerSessionId: ext.providerSessionId,
11307
11484
  kind: "agent",
11308
11485
  transport: "cdp-webview",
11309
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11310
- activeModal: activeChat?.activeModal || null
11311
- }),
11486
+ status: resolveSessionStatus(activeChat, ext.status),
11312
11487
  title: activeChat?.title || ext.name,
11313
11488
  workspace,
11314
11489
  ...git && { git },
@@ -11358,9 +11533,7 @@ function buildCliSession(state, options) {
11358
11533
  providerSessionId: state.providerSessionId,
11359
11534
  kind: "agent",
11360
11535
  transport: "pty",
11361
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11362
- activeModal: activeChat?.activeModal || null
11363
- }),
11536
+ status: resolveSessionStatus(activeChat, state.status),
11364
11537
  title: activeChat?.title || state.name,
11365
11538
  workspace,
11366
11539
  ...git && { git },
@@ -11408,9 +11581,7 @@ function buildAcpSession(state, options) {
11408
11581
  providerName: state.name,
11409
11582
  kind: "agent",
11410
11583
  transport: "acp",
11411
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11412
- activeModal: activeChat?.activeModal || null
11413
- }),
11584
+ status: resolveSessionStatus(activeChat, state.status),
11414
11585
  title: activeChat?.title || state.name,
11415
11586
  workspace,
11416
11587
  ...git && { git },
@@ -11533,7 +11704,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11533
11704
  // src/commands/chat-commands.ts
11534
11705
  var fs4 = __toESM(require("fs"));
11535
11706
  var os6 = __toESM(require("os"));
11536
- var path11 = __toESM(require("path"));
11707
+ var path12 = __toESM(require("path"));
11537
11708
  var import_node_crypto = require("crypto");
11538
11709
 
11539
11710
  // src/providers/provider-input-support.ts
@@ -11896,6 +12067,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11896
12067
  return raw;
11897
12068
  }
11898
12069
  }
12070
+ function isGeneratingLikeStatus(status) {
12071
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
12072
+ }
12073
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12074
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
12075
+ if (hasNonEmptyModalButtons(activeModal)) return false;
12076
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
12077
+ if (adapterRawStatus !== "idle") return false;
12078
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
12079
+ return true;
12080
+ }
12081
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12082
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
12083
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
12084
+ }
12085
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
12086
+ if (status !== "idle") return messages;
12087
+ return messages.map((message) => {
12088
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
12089
+ const hasStreamingMeta = meta?.streaming === true;
12090
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
12091
+ return {
12092
+ ...message,
12093
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
12094
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
12095
+ };
12096
+ });
12097
+ }
11899
12098
  function buildReadChatCommandResult(payload, args) {
11900
12099
  let validatedPayload;
11901
12100
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -12044,7 +12243,7 @@ function buildDebugBundleText(bundle) {
12044
12243
  }
12045
12244
  function getChatDebugBundleDir() {
12046
12245
  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");
12246
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12048
12247
  }
12049
12248
  function safeBundleIdSegment(value, fallback) {
12050
12249
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -12060,6 +12259,14 @@ function buildChatDebugBundleSummary(bundle) {
12060
12259
  const readChat = bundle.readChat && typeof bundle.readChat === "object" ? bundle.readChat : {};
12061
12260
  const cli = bundle.cli && typeof bundle.cli === "object" ? bundle.cli : null;
12062
12261
  const frontend = bundle.frontend && typeof bundle.frontend === "object" ? bundle.frontend : null;
12262
+ const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === "object" ? readChat.debugReadChat : {};
12263
+ const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === "object" ? cli.parsedStatus : null;
12264
+ const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : void 0;
12265
+ const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : void 0;
12266
+ const cliPartialResponse = typeof cli?.partialResponse === "string" ? cli.partialResponse : "";
12267
+ const readChatStatus = typeof readChat.status === "string" ? readChat.status : "";
12268
+ const cliStatus = typeof cli?.status === "string" ? cli.status : "";
12269
+ const cliParsedStatus = typeof parsedStatus?.status === "string" ? parsedStatus.status : "";
12063
12270
  return {
12064
12271
  createdAt: bundle.createdAt,
12065
12272
  targetSessionId: target.targetSessionId,
@@ -12068,8 +12275,22 @@ function buildChatDebugBundleSummary(bundle) {
12068
12275
  readChatSuccess: readChat.success,
12069
12276
  readChatStatus: readChat.status,
12070
12277
  readChatTotalMessages: readChat.totalMessages,
12278
+ readChatReturnedMessages,
12071
12279
  cliStatus: cli?.status,
12280
+ cliParsedStatus: cliParsedStatus || void 0,
12072
12281
  cliMessageCount: cli?.messageCount,
12282
+ cliParsedMessageCount,
12283
+ cliPartialResponseChars: cliPartialResponse.length,
12284
+ parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
12285
+ parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
12286
+ readChatDebug: Object.keys(debugReadChat).length ? {
12287
+ adapterStatus: debugReadChat.adapterStatus,
12288
+ parsedStatus: debugReadChat.parsedStatus,
12289
+ returnedStatus: debugReadChat.returnedStatus,
12290
+ parsedMsgCount: debugReadChat.parsedMsgCount,
12291
+ returnedMsgCount: debugReadChat.returnedMsgCount,
12292
+ shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages
12293
+ } : void 0,
12073
12294
  hasFrontendSnapshot: !!frontend
12074
12295
  };
12075
12296
  }
@@ -12077,7 +12298,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
12077
12298
  const bundleId = createChatDebugBundleId(targetSessionId);
12078
12299
  const dir = getChatDebugBundleDir();
12079
12300
  fs4.mkdirSync(dir, { recursive: true });
12080
- const savedPath = path11.join(dir, `${bundleId}.json`);
12301
+ const savedPath = path12.join(dir, `${bundleId}.json`);
12081
12302
  const json = `${JSON.stringify(bundle, null, 2)}
12082
12303
  `;
12083
12304
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12307,7 +12528,7 @@ async function handleChatHistory(h, args) {
12307
12528
  }
12308
12529
  }
12309
12530
  async function handleReadChat(h, args) {
12310
- const provider = h.getProvider(args?.agentType);
12531
+ const provider = h.getProvider(args?.agentType || args?.providerType);
12311
12532
  const transport = getTargetTransport(h, provider);
12312
12533
  const historySessionId = getHistorySessionId(h, args);
12313
12534
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
@@ -12334,10 +12555,13 @@ async function handleReadChat(h, args) {
12334
12555
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12335
12556
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12336
12557
  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}`);
12558
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12559
+ const runtimeMessageMerger = getTargetInstance(h, args);
12560
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12561
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12562
+ 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
12563
  return buildReadChatCommandResult({
12340
- messages: parsedRecord.messages,
12564
+ messages: returnedMessages,
12341
12565
  status: returnedStatus,
12342
12566
  activeModal,
12343
12567
  debugReadChat: {
@@ -12348,7 +12572,7 @@ async function handleReadChat(h, args) {
12348
12572
  returnedStatus: String(returnedStatus || ""),
12349
12573
  shouldPreferAdapterMessages: false,
12350
12574
  parsedMsgCount: parsedRecord.messages.length,
12351
- returnedMsgCount: parsedRecord.messages.length
12575
+ returnedMsgCount: returnedMessages.length
12352
12576
  },
12353
12577
  ...title ? { title } : {},
12354
12578
  ...providerSessionId ? { providerSessionId } : {},
@@ -13221,7 +13445,7 @@ async function handleResolveAction(h, args) {
13221
13445
 
13222
13446
  // src/commands/cdp-commands.ts
13223
13447
  var fs5 = __toESM(require("fs"));
13224
- var path12 = __toESM(require("path"));
13448
+ var path13 = __toESM(require("path"));
13225
13449
  var os7 = __toESM(require("os"));
13226
13450
  var KEY_TO_VK = {
13227
13451
  Backspace: 8,
@@ -13478,25 +13702,25 @@ function resolveSafePath(requestedPath) {
13478
13702
  const inputPath = rawPath || ".";
13479
13703
  const home = os7.homedir();
13480
13704
  if (inputPath.startsWith("~")) {
13481
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13705
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13482
13706
  }
13483
13707
  if (process.platform === "win32") {
13484
13708
  const normalized = normalizeWindowsRequestedPath(inputPath);
13485
- if (path12.win32.isAbsolute(normalized)) {
13486
- return path12.win32.normalize(normalized);
13709
+ if (path13.win32.isAbsolute(normalized)) {
13710
+ return path13.win32.normalize(normalized);
13487
13711
  }
13488
- return path12.win32.resolve(normalized);
13712
+ return path13.win32.resolve(normalized);
13489
13713
  }
13490
- if (path12.isAbsolute(inputPath)) {
13491
- return path12.normalize(inputPath);
13714
+ if (path13.isAbsolute(inputPath)) {
13715
+ return path13.normalize(inputPath);
13492
13716
  }
13493
- return path12.resolve(inputPath);
13717
+ return path13.resolve(inputPath);
13494
13718
  }
13495
13719
  function listDirectoryEntriesSafe(dirPath) {
13496
13720
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13497
13721
  const files = [];
13498
13722
  for (const entry of entries) {
13499
- const entryPath = path12.join(dirPath, entry.name);
13723
+ const entryPath = path13.join(dirPath, entry.name);
13500
13724
  try {
13501
13725
  if (entry.isDirectory()) {
13502
13726
  files.push({ name: entry.name, type: "directory" });
@@ -13550,7 +13774,7 @@ async function handleFileRead(h, args) {
13550
13774
  async function handleFileWrite(h, args) {
13551
13775
  try {
13552
13776
  const filePath = resolveSafePath(args?.path);
13553
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
13777
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13554
13778
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13555
13779
  return { success: true, path: filePath };
13556
13780
  } catch (e) {
@@ -14334,9 +14558,11 @@ var DaemonCommandHandler = class {
14334
14558
  }
14335
14559
  const sessionLookupFailed = !!targetSessionId && !session;
14336
14560
  const managerKey = this.extractIdeType(args, sessionLookupFailed);
14337
- let providerType;
14561
+ let providerType = args?.agentType || args?.providerType;
14338
14562
  if (!sessionLookupFailed) {
14339
- providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
14563
+ providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
14564
+ } else if (!providerType) {
14565
+ providerType = this.inferProviderType(managerKey);
14340
14566
  }
14341
14567
  return { session, managerKey, providerType, sessionLookupFailed };
14342
14568
  }
@@ -14416,7 +14642,8 @@ var DaemonCommandHandler = class {
14416
14642
  "pty_resize",
14417
14643
  "invoke_provider_script"
14418
14644
  ]);
14419
- if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
14645
+ 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);
14646
+ if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
14420
14647
  const result2 = {
14421
14648
  success: false,
14422
14649
  error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
@@ -14669,7 +14896,7 @@ var DaemonCommandHandler = class {
14669
14896
 
14670
14897
  // src/commands/cli-manager.ts
14671
14898
  var os13 = __toESM(require("os"));
14672
- var path16 = __toESM(require("path"));
14899
+ var path17 = __toESM(require("path"));
14673
14900
  var crypto4 = __toESM(require("crypto"));
14674
14901
  var import_fs6 = require("fs");
14675
14902
  var import_child_process6 = require("child_process");
@@ -14679,7 +14906,7 @@ init_config();
14679
14906
 
14680
14907
  // src/providers/cli-provider-instance.ts
14681
14908
  var os12 = __toESM(require("os"));
14682
- var path15 = __toESM(require("path"));
14909
+ var path16 = __toESM(require("path"));
14683
14910
  var crypto3 = __toESM(require("crypto"));
14684
14911
  var fs6 = __toESM(require("fs"));
14685
14912
  var import_node_module = require("module");
@@ -14738,7 +14965,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14738
14965
  var CachedDatabaseSync = null;
14739
14966
  function getDatabaseSync() {
14740
14967
  if (CachedDatabaseSync) return CachedDatabaseSync;
14741
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14968
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14742
14969
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14743
14970
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14744
14971
  if (!CachedDatabaseSync) {
@@ -14791,7 +15018,7 @@ var CliProviderInstance = class {
14791
15018
  this.providerSessionId = options?.providerSessionId;
14792
15019
  this.launchMode = options?.launchMode || "new";
14793
15020
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14794
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
15021
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14795
15022
  this.monitor = new StatusMonitor();
14796
15023
  this.historyWriter = new ChatHistoryWriter();
14797
15024
  }
@@ -15268,7 +15495,19 @@ var CliProviderInstance = class {
15268
15495
  }
15269
15496
  }
15270
15497
  pushEvent(event) {
15271
- this.events.push(event);
15498
+ const enrichedEvent = {
15499
+ ...event,
15500
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
15501
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
15502
+ providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
15503
+ workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
15504
+ providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
15505
+ };
15506
+ if (this.context?.emitProviderEvent) {
15507
+ this.context.emitProviderEvent(enrichedEvent);
15508
+ return;
15509
+ }
15510
+ this.events.push(enrichedEvent);
15272
15511
  }
15273
15512
  flushEvents() {
15274
15513
  const events = [...this.events];
@@ -15475,12 +15714,31 @@ ${effect.notification.body || ""}`.trim();
15475
15714
  );
15476
15715
  }
15477
15716
  }
15717
+ mergeRuntimeChatMessages(parsedMessages) {
15718
+ return this.mergeConversationMessages(parsedMessages);
15719
+ }
15478
15720
  mergeConversationMessages(parsedMessages) {
15479
15721
  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;
15722
+ const parsedEntries = parsedMessages.map((message, index) => ({
15723
+ message,
15724
+ index,
15725
+ source: "parsed"
15726
+ }));
15727
+ const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
15728
+ message: entry.message,
15729
+ index: parsedMessages.length + index,
15730
+ source: "runtime"
15731
+ }));
15732
+ const getTime = (message) => {
15733
+ const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
15734
+ return Number.isFinite(value) && value > 0 ? value : 0;
15735
+ };
15736
+ return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
15737
+ const aTime = getTime(a.message);
15738
+ const bTime = getTime(b.message);
15739
+ if (aTime && bTime && aTime !== bTime) return aTime - bTime;
15740
+ if (aTime && !bTime && a.source === "runtime" && b.source === "parsed") return -1;
15741
+ if (!aTime && bTime && a.source === "parsed" && b.source === "runtime") return 1;
15484
15742
  return a.index - b.index;
15485
15743
  }).map((entry) => entry.message));
15486
15744
  }
@@ -16804,11 +17062,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16804
17062
  // src/commands/cli-manager.ts
16805
17063
  function isExplicitCommand(command) {
16806
17064
  const trimmed = command.trim();
16807
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17065
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16808
17066
  }
16809
17067
  function expandExecutable(command) {
16810
17068
  const trimmed = command.trim();
16811
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17069
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16812
17070
  }
16813
17071
  function commandExists(command) {
16814
17072
  const trimmed = command.trim();
@@ -16832,6 +17090,35 @@ function colorize(color, text) {
16832
17090
  const fn = chalkApi?.[color];
16833
17091
  return typeof fn === "function" ? fn(text) : text;
16834
17092
  }
17093
+ var COORDINATOR_DELEGATED_ENV_UNSETS = {
17094
+ ADHDEV_INLINE_MESH: "",
17095
+ ADHDEV_MCP_TRANSPORT: "",
17096
+ ADHDEV_MESH_ID: "",
17097
+ HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
17098
+ };
17099
+ function hasCliArg(args, flag) {
17100
+ return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
17101
+ }
17102
+ function ensureEmptyDelegatedMcpConfig(workspace) {
17103
+ const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
17104
+ (0, import_fs6.mkdirSync)(baseDir, { recursive: true });
17105
+ const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
17106
+ const filePath = path17.join(baseDir, `${workspaceHash}.json`);
17107
+ (0, import_fs6.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
17108
+ return filePath;
17109
+ }
17110
+ function buildCoordinatorDelegatedCliLaunchOptions(input) {
17111
+ const cliType = String(input.cliType || "").trim();
17112
+ const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
17113
+ const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
17114
+ if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
17115
+ cliArgs.unshift("--ignore-user-config");
17116
+ }
17117
+ if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
17118
+ cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
17119
+ }
17120
+ return { cliArgs, env };
17121
+ }
16835
17122
  function isUuid(value) {
16836
17123
  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
17124
  }
@@ -17002,7 +17289,7 @@ var DaemonCliManager = class {
17002
17289
  attachExisting
17003
17290
  }) || void 0;
17004
17291
  }
17005
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17292
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
17006
17293
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17007
17294
  const provider = this.providerLoader.getMeta(normalizedType);
17008
17295
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -17016,7 +17303,7 @@ var DaemonCliManager = class {
17016
17303
  providerSessionId,
17017
17304
  attachExisting
17018
17305
  );
17019
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17306
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
17020
17307
  }
17021
17308
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
17022
17309
  }
@@ -17089,7 +17376,7 @@ var DaemonCliManager = class {
17089
17376
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
17090
17377
  const trimmed = (workingDir || "").trim();
17091
17378
  if (!trimmed) throw new Error("working directory required");
17092
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17379
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
17093
17380
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17094
17381
  const rawProvider = this.providerLoader.getByAlias(cliType);
17095
17382
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17219,6 +17506,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17219
17506
  {
17220
17507
  providerSessionId: sessionBinding.providerSessionId,
17221
17508
  launchMode: sessionBinding.launchMode,
17509
+ extraEnv: options?.extraEnv,
17222
17510
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17223
17511
  this.persistRecentActivity({
17224
17512
  kind: "cli",
@@ -17239,7 +17527,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17239
17527
  resolvedCliArgs,
17240
17528
  key,
17241
17529
  sessionBinding.providerSessionId,
17242
- false
17530
+ false,
17531
+ options?.extraEnv
17243
17532
  );
17244
17533
  try {
17245
17534
  await adapter.spawn();
@@ -17463,12 +17752,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
17463
17752
  const dir = resolved.path;
17464
17753
  const launchSource = resolved.source;
17465
17754
  if (!cliType) throw new Error("cliType required");
17755
+ const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
17756
+ const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
17757
+ cliType,
17758
+ workspace: dir,
17759
+ cliArgs: args?.cliArgs,
17760
+ env: args?.env
17761
+ }) : null;
17466
17762
  const started = await this.startSession(
17467
17763
  cliType,
17468
17764
  dir,
17469
- args?.cliArgs,
17765
+ delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
17470
17766
  args?.initialModel,
17471
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
17767
+ {
17768
+ resumeSessionId: args?.resumeSessionId,
17769
+ settingsOverride,
17770
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
17771
+ }
17472
17772
  );
17473
17773
  return {
17474
17774
  success: true,
@@ -17590,11 +17890,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17590
17890
  var import_child_process7 = require("child_process");
17591
17891
  var net = __toESM(require("net"));
17592
17892
  var os15 = __toESM(require("os"));
17593
- var path18 = __toESM(require("path"));
17893
+ var path19 = __toESM(require("path"));
17594
17894
 
17595
17895
  // src/providers/provider-loader.ts
17596
17896
  var fs7 = __toESM(require("fs"));
17597
- var path17 = __toESM(require("path"));
17897
+ var path18 = __toESM(require("path"));
17598
17898
  var os14 = __toESM(require("os"));
17599
17899
  var chokidar = __toESM(require("chokidar"));
17600
17900
  init_logger();
@@ -17918,7 +18218,7 @@ var ProviderLoader = class _ProviderLoader {
17918
18218
  try {
17919
18219
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17920
18220
  return ["ide", "extension", "cli", "acp"].some(
17921
- (category) => fs7.existsSync(path17.join(candidate, category))
18221
+ (category) => fs7.existsSync(path18.join(candidate, category))
17922
18222
  );
17923
18223
  } catch {
17924
18224
  return false;
@@ -17926,20 +18226,20 @@ var ProviderLoader = class _ProviderLoader {
17926
18226
  }
17927
18227
  static hasProviderRootMarker(candidate) {
17928
18228
  try {
17929
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18229
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17930
18230
  } catch {
17931
18231
  return false;
17932
18232
  }
17933
18233
  }
17934
18234
  detectDefaultUserDir() {
17935
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
18235
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17936
18236
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17937
18237
  const visited = /* @__PURE__ */ new Set();
17938
18238
  for (const start of this.probeStarts) {
17939
- let current = path17.resolve(start);
18239
+ let current = path18.resolve(start);
17940
18240
  while (!visited.has(current)) {
17941
18241
  visited.add(current);
17942
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18242
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17943
18243
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17944
18244
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17945
18245
  if (envOptIn || hasMarker) {
@@ -17961,7 +18261,7 @@ var ProviderLoader = class _ProviderLoader {
17961
18261
  return { path: siblingCandidate, source };
17962
18262
  }
17963
18263
  }
17964
- const parent = path17.dirname(current);
18264
+ const parent = path18.dirname(current);
17965
18265
  if (parent === current) break;
17966
18266
  current = parent;
17967
18267
  }
@@ -17971,11 +18271,11 @@ var ProviderLoader = class _ProviderLoader {
17971
18271
  constructor(options) {
17972
18272
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17973
18273
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17974
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
18274
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17975
18275
  const detected = this.detectDefaultUserDir();
17976
18276
  this.userDir = detected.path;
17977
18277
  this.userDirSource = detected.source;
17978
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18278
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17979
18279
  this.disableUpstream = false;
17980
18280
  this.applySourceConfig({
17981
18281
  userDir: options?.userDir,
@@ -18034,7 +18334,7 @@ var ProviderLoader = class _ProviderLoader {
18034
18334
  this.userDir = detected.path;
18035
18335
  this.userDirSource = detected.source;
18036
18336
  }
18037
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18337
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
18038
18338
  this.disableUpstream = this.sourceMode === "no-upstream";
18039
18339
  if (this.explicitProviderDir) {
18040
18340
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -18048,7 +18348,7 @@ var ProviderLoader = class _ProviderLoader {
18048
18348
  * Canonical provider directory shape for a given root.
18049
18349
  */
18050
18350
  getProviderDir(root, category, type) {
18051
- return path17.join(root, category, type);
18351
+ return path18.join(root, category, type);
18052
18352
  }
18053
18353
  /**
18054
18354
  * Canonical user override directory for a provider.
@@ -18075,7 +18375,7 @@ var ProviderLoader = class _ProviderLoader {
18075
18375
  resolveProviderFile(type, ...segments) {
18076
18376
  const dir = this.findProviderDirInternal(type);
18077
18377
  if (!dir) return null;
18078
- return path17.join(dir, ...segments);
18378
+ return path18.join(dir, ...segments);
18079
18379
  }
18080
18380
  /**
18081
18381
  * Load all providers (3-tier priority)
@@ -18114,7 +18414,7 @@ var ProviderLoader = class _ProviderLoader {
18114
18414
  if (!fs7.existsSync(this.upstreamDir)) return false;
18115
18415
  try {
18116
18416
  return fs7.readdirSync(this.upstreamDir).some(
18117
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18417
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
18118
18418
  );
18119
18419
  } catch {
18120
18420
  return false;
@@ -18611,8 +18911,8 @@ var ProviderLoader = class _ProviderLoader {
18611
18911
  resolved._resolvedScriptDir = entry.scriptDir;
18612
18912
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18613
18913
  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;
18914
+ const fullDir = path18.join(providerDir, entry.scriptDir);
18915
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18616
18916
  }
18617
18917
  matched = true;
18618
18918
  }
@@ -18627,8 +18927,8 @@ var ProviderLoader = class _ProviderLoader {
18627
18927
  resolved._resolvedScriptDir = base.defaultScriptDir;
18628
18928
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18629
18929
  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;
18930
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18931
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18632
18932
  }
18633
18933
  }
18634
18934
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18645,8 +18945,8 @@ var ProviderLoader = class _ProviderLoader {
18645
18945
  resolved._resolvedScriptDir = dirOverride;
18646
18946
  resolved._resolvedScriptsSource = `versions:${range}`;
18647
18947
  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;
18948
+ const fullDir = path18.join(providerDir, dirOverride);
18949
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18650
18950
  }
18651
18951
  }
18652
18952
  } else if (override.scripts) {
@@ -18662,8 +18962,8 @@ var ProviderLoader = class _ProviderLoader {
18662
18962
  resolved._resolvedScriptDir = base.defaultScriptDir;
18663
18963
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18664
18964
  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;
18965
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18966
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18667
18967
  }
18668
18968
  }
18669
18969
  }
@@ -18695,14 +18995,14 @@ var ProviderLoader = class _ProviderLoader {
18695
18995
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18696
18996
  return null;
18697
18997
  }
18698
- const dir = path17.join(providerDir, scriptDir);
18998
+ const dir = path18.join(providerDir, scriptDir);
18699
18999
  if (!fs7.existsSync(dir)) {
18700
19000
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18701
19001
  return null;
18702
19002
  }
18703
19003
  const cached = this.scriptsCache.get(dir);
18704
19004
  if (cached) return cached;
18705
- const scriptsJs = path17.join(dir, "scripts.js");
19005
+ const scriptsJs = path18.join(dir, "scripts.js");
18706
19006
  if (fs7.existsSync(scriptsJs)) {
18707
19007
  try {
18708
19008
  delete require.cache[require.resolve(scriptsJs)];
@@ -18744,7 +19044,7 @@ var ProviderLoader = class _ProviderLoader {
18744
19044
  return;
18745
19045
  }
18746
19046
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18747
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
19047
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18748
19048
  this.reload();
18749
19049
  }
18750
19050
  };
@@ -18799,7 +19099,7 @@ var ProviderLoader = class _ProviderLoader {
18799
19099
  }
18800
19100
  const https = require("https");
18801
19101
  const { execSync: execSync7 } = require("child_process");
18802
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
19102
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18803
19103
  let prevEtag = "";
18804
19104
  let prevTimestamp = 0;
18805
19105
  try {
@@ -18859,17 +19159,17 @@ var ProviderLoader = class _ProviderLoader {
18859
19159
  return { updated: false };
18860
19160
  }
18861
19161
  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()}`);
19162
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19163
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18864
19164
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18865
19165
  fs7.mkdirSync(tmpExtract, { recursive: true });
18866
19166
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18867
19167
  const extracted = fs7.readdirSync(tmpExtract);
18868
19168
  const rootDir = extracted.find(
18869
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19169
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18870
19170
  );
18871
19171
  if (!rootDir) throw new Error("Unexpected tarball structure");
18872
- const sourceDir = path17.join(tmpExtract, rootDir);
19172
+ const sourceDir = path18.join(tmpExtract, rootDir);
18873
19173
  const backupDir = this.upstreamDir + ".bak";
18874
19174
  if (fs7.existsSync(this.upstreamDir)) {
18875
19175
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18944,8 +19244,8 @@ var ProviderLoader = class _ProviderLoader {
18944
19244
  copyDirRecursive(src, dest) {
18945
19245
  fs7.mkdirSync(dest, { recursive: true });
18946
19246
  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);
19247
+ const srcPath = path18.join(src, entry.name);
19248
+ const destPath = path18.join(dest, entry.name);
18949
19249
  if (entry.isDirectory()) {
18950
19250
  this.copyDirRecursive(srcPath, destPath);
18951
19251
  } else {
@@ -18956,7 +19256,7 @@ var ProviderLoader = class _ProviderLoader {
18956
19256
  /** .meta.json save */
18957
19257
  writeMeta(metaPath, etag, timestamp) {
18958
19258
  try {
18959
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
19259
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18960
19260
  fs7.writeFileSync(metaPath, JSON.stringify({
18961
19261
  etag,
18962
19262
  timestamp,
@@ -18973,7 +19273,7 @@ var ProviderLoader = class _ProviderLoader {
18973
19273
  const scan = (d) => {
18974
19274
  try {
18975
19275
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18976
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
19276
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18977
19277
  else if (entry.name === "provider.json") count++;
18978
19278
  }
18979
19279
  } catch {
@@ -19201,17 +19501,17 @@ var ProviderLoader = class _ProviderLoader {
19201
19501
  for (const root of searchRoots) {
19202
19502
  if (!fs7.existsSync(root)) continue;
19203
19503
  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);
19504
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19505
+ const catDir = path18.join(root, cat);
19206
19506
  if (fs7.existsSync(catDir)) {
19207
19507
  try {
19208
19508
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19209
19509
  if (!entry.isDirectory()) continue;
19210
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19510
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19211
19511
  if (fs7.existsSync(jsonPath)) {
19212
19512
  try {
19213
19513
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19214
- if (data.type === type) return path17.join(catDir, entry.name);
19514
+ if (data.type === type) return path18.join(catDir, entry.name);
19215
19515
  } catch {
19216
19516
  }
19217
19517
  }
@@ -19228,7 +19528,7 @@ var ProviderLoader = class _ProviderLoader {
19228
19528
  * (template substitution is NOT applied here — scripts.js handles that)
19229
19529
  */
19230
19530
  buildScriptWrappersFromDir(dir) {
19231
- const scriptsJs = path17.join(dir, "scripts.js");
19531
+ const scriptsJs = path18.join(dir, "scripts.js");
19232
19532
  if (fs7.existsSync(scriptsJs)) {
19233
19533
  try {
19234
19534
  delete require.cache[require.resolve(scriptsJs)];
@@ -19242,7 +19542,7 @@ var ProviderLoader = class _ProviderLoader {
19242
19542
  for (const file of fs7.readdirSync(dir)) {
19243
19543
  if (!file.endsWith(".js")) continue;
19244
19544
  const scriptName = toCamel(file.replace(".js", ""));
19245
- const filePath = path17.join(dir, file);
19545
+ const filePath = path18.join(dir, file);
19246
19546
  result[scriptName] = (...args) => {
19247
19547
  try {
19248
19548
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19302,7 +19602,7 @@ var ProviderLoader = class _ProviderLoader {
19302
19602
  }
19303
19603
  const hasJson = entries.some((e) => e.name === "provider.json");
19304
19604
  if (hasJson) {
19305
- const jsonPath = path17.join(d, "provider.json");
19605
+ const jsonPath = path18.join(d, "provider.json");
19306
19606
  try {
19307
19607
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19308
19608
  const mod = JSON.parse(raw);
@@ -19323,7 +19623,7 @@ var ProviderLoader = class _ProviderLoader {
19323
19623
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19324
19624
  } else {
19325
19625
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19326
- const scriptsPath = path17.join(d, "scripts.js");
19626
+ const scriptsPath = path18.join(d, "scripts.js");
19327
19627
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19328
19628
  try {
19329
19629
  delete require.cache[require.resolve(scriptsPath)];
@@ -19349,7 +19649,7 @@ var ProviderLoader = class _ProviderLoader {
19349
19649
  if (!entry.isDirectory()) continue;
19350
19650
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19351
19651
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19352
- scan(path17.join(d, entry.name));
19652
+ scan(path18.join(d, entry.name));
19353
19653
  }
19354
19654
  }
19355
19655
  };
@@ -19674,8 +19974,8 @@ function detectCurrentWorkspace(ideId) {
19674
19974
  const appNameMap = getMacAppIdentifiers();
19675
19975
  const appName = appNameMap[ideId];
19676
19976
  if (appName) {
19677
- const storagePath = path18.join(
19678
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
19977
+ const storagePath = path19.join(
19978
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19679
19979
  appName,
19680
19980
  "storage.json"
19681
19981
  );
@@ -19864,9 +20164,9 @@ init_logger();
19864
20164
 
19865
20165
  // src/logging/command-log.ts
19866
20166
  var fs8 = __toESM(require("fs"));
19867
- var path19 = __toESM(require("path"));
20167
+ var path20 = __toESM(require("path"));
19868
20168
  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");
20169
+ 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
20170
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19871
20171
  var MAX_DAYS = 7;
19872
20172
  try {
@@ -19904,13 +20204,13 @@ function getDateStr2() {
19904
20204
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19905
20205
  }
19906
20206
  var currentDate2 = getDateStr2();
19907
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20207
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19908
20208
  var writeCount2 = 0;
19909
20209
  function checkRotation() {
19910
20210
  const today = getDateStr2();
19911
20211
  if (today !== currentDate2) {
19912
20212
  currentDate2 = today;
19913
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20213
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19914
20214
  cleanOldFiles();
19915
20215
  }
19916
20216
  }
@@ -19924,7 +20224,7 @@ function cleanOldFiles() {
19924
20224
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19925
20225
  if (dateMatch && dateMatch[1] < cutoffStr) {
19926
20226
  try {
19927
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
20227
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19928
20228
  } catch {
19929
20229
  }
19930
20230
  }
@@ -20007,14 +20307,66 @@ function getRecentCommands(count = 50) {
20007
20307
  cleanOldFiles();
20008
20308
 
20009
20309
  // src/commands/router.ts
20310
+ var yaml = __toESM(require("js-yaml"));
20010
20311
  init_logger();
20011
20312
 
20012
20313
  // src/commands/mesh-coordinator.ts
20013
- var import_node_fs2 = require("fs");
20314
+ var import_node_child_process3 = require("child_process");
20315
+ var import_node_fs3 = require("fs");
20014
20316
  var import_node_module2 = require("module");
20317
+ var os17 = __toESM(require("os"));
20015
20318
  var import_node_path = require("path");
20016
20319
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
20017
20320
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20321
+ var HERMES_CLI_TYPE = "hermes-cli";
20322
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20323
+ function isHermesProvider(provider, cliType) {
20324
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20325
+ return type === HERMES_CLI_TYPE;
20326
+ }
20327
+ function resolveHermesMeshCoordinatorSetup(options) {
20328
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20329
+ meshId: options.meshId,
20330
+ nodeExecutable: options.nodeExecutable,
20331
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20332
+ });
20333
+ if (!mcpServer) {
20334
+ return {
20335
+ kind: "unsupported",
20336
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20337
+ };
20338
+ }
20339
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20340
+ if (!configPath.trim()) {
20341
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20342
+ }
20343
+ return {
20344
+ kind: "auto_import",
20345
+ serverName: DEFAULT_SERVER_NAME,
20346
+ configPath,
20347
+ configFormat: "hermes_config_yaml",
20348
+ mcpServer
20349
+ };
20350
+ }
20351
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20352
+ return {
20353
+ kind: "manual",
20354
+ serverName: DEFAULT_SERVER_NAME,
20355
+ configFormat: "hermes_config_yaml",
20356
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20357
+ requiresRestart: true,
20358
+ 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.",
20359
+ template: renderMeshCoordinatorTemplate(
20360
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20361
+ {
20362
+ meshId,
20363
+ workspace,
20364
+ serverName: DEFAULT_SERVER_NAME,
20365
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20366
+ }
20367
+ )
20368
+ };
20369
+ }
20018
20370
  function resolveMeshCoordinatorSetup(options) {
20019
20371
  const { provider, meshId, workspace } = options;
20020
20372
  const config = provider?.meshCoordinator;
@@ -20024,6 +20376,9 @@ function resolveMeshCoordinatorSetup(options) {
20024
20376
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
20025
20377
  };
20026
20378
  }
20379
+ if (isHermesProvider(provider, options.cliType)) {
20380
+ return resolveHermesMeshCoordinatorSetup(options);
20381
+ }
20027
20382
  const mcpConfig = config.mcpConfig;
20028
20383
  if (!mcpConfig || mcpConfig.mode === "none") {
20029
20384
  return {
@@ -20033,8 +20388,8 @@ function resolveMeshCoordinatorSetup(options) {
20033
20388
  }
20034
20389
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
20035
20390
  if (mcpConfig.mode === "auto_import") {
20036
- const path26 = mcpConfig.path?.trim();
20037
- if (!path26) {
20391
+ const path27 = mcpConfig.path?.trim();
20392
+ if (!path27) {
20038
20393
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
20039
20394
  }
20040
20395
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -20045,13 +20400,13 @@ function resolveMeshCoordinatorSetup(options) {
20045
20400
  if (!mcpServer) {
20046
20401
  return {
20047
20402
  kind: "unsupported",
20048
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20403
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20049
20404
  };
20050
20405
  }
20051
20406
  return {
20052
20407
  kind: "auto_import",
20053
20408
  serverName,
20054
- configPath: (0, import_node_path.join)(workspace, path26),
20409
+ configPath: resolveMcpConfigPath(path27, workspace),
20055
20410
  configFormat: mcpConfig.format,
20056
20411
  mcpServer
20057
20412
  };
@@ -20085,13 +20440,84 @@ function resolveMeshCoordinatorSetup(options) {
20085
20440
  function renderMeshCoordinatorTemplate(template, values) {
20086
20441
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
20087
20442
  }
20443
+ function resolveMcpConfigPath(configPath, workspace) {
20444
+ const trimmed = configPath.trim();
20445
+ if (trimmed === "~") return os17.homedir();
20446
+ if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
20447
+ if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
20448
+ return (0, import_node_path.join)(workspace, trimmed);
20449
+ }
20088
20450
  function resolveAdhdevMcpServerLaunch(options) {
20089
20451
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
20090
20452
  if (!entryPath) return null;
20453
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20454
+ if (!nodeExecutable) return null;
20091
20455
  return {
20092
- command: options.nodeExecutable?.trim() || process.execPath,
20093
- args: [entryPath, "--repo-mesh", options.meshId]
20456
+ command: nodeExecutable,
20457
+ args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
20458
+ };
20459
+ }
20460
+ function resolveMcpNodeExecutable(explicitExecutable) {
20461
+ const explicit = explicitExecutable?.trim();
20462
+ if (explicit) return explicit;
20463
+ const candidates = [];
20464
+ const addCandidate = (candidate) => {
20465
+ const trimmed = candidate?.trim();
20466
+ if (!trimmed) return;
20467
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20468
+ if (!candidates.includes(normalized)) candidates.push(normalized);
20094
20469
  };
20470
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20471
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20472
+ addCandidate(process.env.npm_node_execpath);
20473
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20474
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20475
+ addCandidate("/opt/homebrew/bin/node");
20476
+ addCandidate("/usr/local/bin/node");
20477
+ addCandidate("/usr/bin/node");
20478
+ addCandidate(process.execPath);
20479
+ for (const candidate of candidates) {
20480
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20481
+ }
20482
+ return null;
20483
+ }
20484
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20485
+ for (const entry of (pathValue || "").split(":")) {
20486
+ const dir = entry.trim();
20487
+ if (!dir) continue;
20488
+ addCandidate((0, import_node_path.join)(dir, "node"));
20489
+ }
20490
+ }
20491
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20492
+ const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
20493
+ try {
20494
+ const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20495
+ for (const versionDir of versionDirs) {
20496
+ addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
20497
+ }
20498
+ } catch {
20499
+ }
20500
+ }
20501
+ function compareNodeVersionNamesDescending(a, b) {
20502
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20503
+ const left = parse(a);
20504
+ const right = parse(b);
20505
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20506
+ const diff = (right[i] || 0) - (left[i] || 0);
20507
+ if (diff !== 0) return diff;
20508
+ }
20509
+ return b.localeCompare(a);
20510
+ }
20511
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20512
+ try {
20513
+ (0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20514
+ stdio: "ignore",
20515
+ timeout: 3e3
20516
+ });
20517
+ return true;
20518
+ } catch {
20519
+ return false;
20520
+ }
20095
20521
  }
20096
20522
  function resolveAdhdevMcpEntryPath(explicitPath) {
20097
20523
  const explicit = explicitPath?.trim();
@@ -20128,15 +20554,109 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
20128
20554
  }
20129
20555
  function normalizeExistingPath(filePath) {
20130
20556
  try {
20131
- if (!(0, import_node_fs2.existsSync)(filePath)) return null;
20132
- return import_node_fs2.realpathSync.native(filePath);
20557
+ if (!(0, import_node_fs3.existsSync)(filePath)) return null;
20558
+ return import_node_fs3.realpathSync.native(filePath);
20133
20559
  } catch {
20134
20560
  return null;
20135
20561
  }
20136
20562
  }
20137
20563
 
20564
+ // src/mesh/mesh-events.ts
20565
+ init_mesh_config();
20566
+ init_logger();
20567
+ function readNonEmptyString(value) {
20568
+ return typeof value === "string" && value.trim() ? value.trim() : "";
20569
+ }
20570
+ function formatCompletionMetadata(event) {
20571
+ const parts = [
20572
+ readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
20573
+ readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
20574
+ readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
20575
+ ].filter(Boolean);
20576
+ return parts.length > 0 ? ` (${parts.join("; ")})` : "";
20577
+ }
20578
+ function buildMeshSystemMessage(args) {
20579
+ const metadata = formatCompletionMetadata(args.metadataEvent);
20580
+ if (args.event === "agent:generating_completed") {
20581
+ return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. You may use mesh_read_chat to review its progress.`;
20582
+ }
20583
+ if (args.event === "agent:waiting_approval") {
20584
+ return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
20585
+ }
20586
+ return "";
20587
+ }
20588
+ function injectMeshSystemMessage(components, args) {
20589
+ const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
20590
+ const instState = inst.getState();
20591
+ if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
20592
+ if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
20593
+ return true;
20594
+ });
20595
+ if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
20596
+ const messageText = buildMeshSystemMessage({
20597
+ event: args.event,
20598
+ nodeLabel: args.nodeLabel,
20599
+ metadataEvent: args.metadataEvent
20600
+ });
20601
+ if (!messageText) return { success: false, error: "unsupported mesh event" };
20602
+ for (const coord of coordinatorInstances) {
20603
+ const coordState = coord.getState();
20604
+ LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
20605
+ coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
20606
+ }
20607
+ return { success: true, forwarded: coordinatorInstances.length };
20608
+ }
20609
+ function handleMeshForwardEvent(components, payload) {
20610
+ const eventName = readNonEmptyString(payload.event);
20611
+ if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
20612
+ return { success: false, error: "unsupported mesh event" };
20613
+ }
20614
+ const meshId = readNonEmptyString(payload.meshId);
20615
+ if (!meshId) return { success: false, error: "meshId required" };
20616
+ const nodeId = readNonEmptyString(payload.nodeId);
20617
+ const workspace = readNonEmptyString(payload.workspace);
20618
+ const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
20619
+ return injectMeshSystemMessage(components, {
20620
+ meshId,
20621
+ nodeLabel,
20622
+ event: eventName,
20623
+ metadataEvent: {
20624
+ targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
20625
+ providerType: readNonEmptyString(payload.providerType),
20626
+ providerSessionId: readNonEmptyString(payload.providerSessionId)
20627
+ }
20628
+ });
20629
+ }
20630
+ function setupMeshEventForwarding(components) {
20631
+ components.instanceManager.onEvent((event) => {
20632
+ if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
20633
+ const instanceId = readNonEmptyString(event.instanceId);
20634
+ if (!instanceId) return;
20635
+ const sourceInstance = components.instanceManager.getInstance(instanceId);
20636
+ if (!sourceInstance || sourceInstance.category !== "cli") return;
20637
+ const state = sourceInstance.getState();
20638
+ const workspace = readNonEmptyString(state.workspace);
20639
+ if (!workspace) return;
20640
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
20641
+ const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
20642
+ const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
20643
+ const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
20644
+ if (!meshId) return;
20645
+ const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
20646
+ const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
20647
+ const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
20648
+ injectMeshSystemMessage(components, {
20649
+ meshId,
20650
+ sourceInstanceId: instanceId,
20651
+ nodeLabel,
20652
+ event: event.event,
20653
+ metadataEvent: event
20654
+ });
20655
+ });
20656
+ }
20657
+
20138
20658
  // src/status/snapshot.ts
20139
- var os17 = __toESM(require("os"));
20659
+ var os18 = __toESM(require("os"));
20140
20660
  init_config();
20141
20661
  init_terminal_screen();
20142
20662
  init_logger();
@@ -20192,8 +20712,8 @@ function buildAvailableProviders(providerLoader) {
20192
20712
  }
20193
20713
  function buildMachineInfo(profile = "full") {
20194
20714
  const base = {
20195
- hostname: os17.hostname(),
20196
- platform: os17.platform()
20715
+ hostname: os18.hostname(),
20716
+ platform: os18.platform()
20197
20717
  };
20198
20718
  if (profile === "live") {
20199
20719
  return base;
@@ -20202,23 +20722,23 @@ function buildMachineInfo(profile = "full") {
20202
20722
  const memSnap2 = getHostMemorySnapshot();
20203
20723
  return {
20204
20724
  ...base,
20205
- arch: os17.arch(),
20206
- cpus: os17.cpus().length,
20725
+ arch: os18.arch(),
20726
+ cpus: os18.cpus().length,
20207
20727
  totalMem: memSnap2.totalMem,
20208
- release: os17.release()
20728
+ release: os18.release()
20209
20729
  };
20210
20730
  }
20211
20731
  const memSnap = getHostMemorySnapshot();
20212
20732
  return {
20213
20733
  ...base,
20214
- arch: os17.arch(),
20215
- cpus: os17.cpus().length,
20734
+ arch: os18.arch(),
20735
+ cpus: os18.cpus().length,
20216
20736
  totalMem: memSnap.totalMem,
20217
20737
  freeMem: memSnap.freeMem,
20218
20738
  availableMem: memSnap.availableMem,
20219
- loadavg: os17.loadavg(),
20220
- uptime: os17.uptime(),
20221
- release: os17.release()
20739
+ loadavg: os18.loadavg(),
20740
+ uptime: os18.uptime(),
20741
+ release: os18.release()
20222
20742
  };
20223
20743
  }
20224
20744
  function parseMessageTime(value) {
@@ -20452,14 +20972,14 @@ function buildStatusSnapshot(options) {
20452
20972
  var import_child_process8 = require("child_process");
20453
20973
  var import_child_process9 = require("child_process");
20454
20974
  var fs9 = __toESM(require("fs"));
20455
- var os18 = __toESM(require("os"));
20456
- var path20 = __toESM(require("path"));
20975
+ var os19 = __toESM(require("os"));
20976
+ var path21 = __toESM(require("path"));
20457
20977
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20458
20978
  function getUpgradeLogPath() {
20459
- const home = os18.homedir();
20460
- const dir = path20.join(home, ".adhdev");
20979
+ const home = os19.homedir();
20980
+ const dir = path21.join(home, ".adhdev");
20461
20981
  fs9.mkdirSync(dir, { recursive: true });
20462
- return path20.join(dir, "daemon-upgrade.log");
20982
+ return path21.join(dir, "daemon-upgrade.log");
20463
20983
  }
20464
20984
  function appendUpgradeLog(message) {
20465
20985
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20470,14 +20990,14 @@ function appendUpgradeLog(message) {
20470
20990
  }
20471
20991
  }
20472
20992
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20473
- const binDir = path20.dirname(nodeExecutable);
20993
+ const binDir = path21.dirname(nodeExecutable);
20474
20994
  if (platform10 === "win32") {
20475
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20995
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20476
20996
  if (fs9.existsSync(npmCliPath)) {
20477
20997
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20478
20998
  }
20479
20999
  for (const candidate of ["npm.exe", "npm"]) {
20480
- const candidatePath = path20.join(binDir, candidate);
21000
+ const candidatePath = path21.join(binDir, candidate);
20481
21001
  if (fs9.existsSync(candidatePath)) {
20482
21002
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20483
21003
  }
@@ -20485,7 +21005,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20485
21005
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20486
21006
  }
20487
21007
  for (const candidate of ["npm"]) {
20488
- const candidatePath = path20.join(binDir, candidate);
21008
+ const candidatePath = path21.join(binDir, candidate);
20489
21009
  if (fs9.existsSync(candidatePath)) {
20490
21010
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20491
21011
  }
@@ -20502,13 +21022,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20502
21022
  let currentDir = resolvedPath;
20503
21023
  try {
20504
21024
  if (fs9.statSync(resolvedPath).isFile()) {
20505
- currentDir = path20.dirname(resolvedPath);
21025
+ currentDir = path21.dirname(resolvedPath);
20506
21026
  }
20507
21027
  } catch {
20508
- currentDir = path20.dirname(resolvedPath);
21028
+ currentDir = path21.dirname(resolvedPath);
20509
21029
  }
20510
21030
  while (true) {
20511
- const packageJsonPath = path20.join(currentDir, "package.json");
21031
+ const packageJsonPath = path21.join(currentDir, "package.json");
20512
21032
  try {
20513
21033
  if (fs9.existsSync(packageJsonPath)) {
20514
21034
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20519,7 +21039,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20519
21039
  }
20520
21040
  } catch {
20521
21041
  }
20522
- const parentDir = path20.dirname(currentDir);
21042
+ const parentDir = path21.dirname(currentDir);
20523
21043
  if (parentDir === currentDir) {
20524
21044
  return null;
20525
21045
  }
@@ -20527,13 +21047,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20527
21047
  }
20528
21048
  }
20529
21049
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20530
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20531
- if (path20.basename(nodeModulesDir) !== "node_modules") {
21050
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
21051
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20532
21052
  return null;
20533
21053
  }
20534
- const maybeLibDir = path20.dirname(nodeModulesDir);
20535
- if (path20.basename(maybeLibDir) === "lib") {
20536
- return path20.dirname(maybeLibDir);
21054
+ const maybeLibDir = path21.dirname(nodeModulesDir);
21055
+ if (path21.basename(maybeLibDir) === "lib") {
21056
+ return path21.dirname(maybeLibDir);
20537
21057
  }
20538
21058
  return maybeLibDir;
20539
21059
  }
@@ -20648,7 +21168,7 @@ async function waitForPidExit(pid, timeoutMs) {
20648
21168
  }
20649
21169
  }
20650
21170
  function stopSessionHostProcesses(appName) {
20651
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
21171
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20652
21172
  try {
20653
21173
  if (fs9.existsSync(pidFile)) {
20654
21174
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20665,7 +21185,7 @@ function stopSessionHostProcesses(appName) {
20665
21185
  }
20666
21186
  }
20667
21187
  function removeDaemonPidFile() {
20668
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
21188
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20669
21189
  try {
20670
21190
  fs9.unlinkSync(pidFile);
20671
21191
  } catch {
@@ -20676,7 +21196,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20676
21196
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20677
21197
  if (!npmRoot) return;
20678
21198
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20679
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
21199
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20680
21200
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20681
21201
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20682
21202
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20684,25 +21204,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20684
21204
  }
20685
21205
  if (pkgName.startsWith("@")) {
20686
21206
  const [scope, name] = pkgName.split("/");
20687
- const scopeDir = path20.join(npmRoot, scope);
21207
+ const scopeDir = path21.join(npmRoot, scope);
20688
21208
  if (!fs9.existsSync(scopeDir)) return;
20689
21209
  for (const entry of fs9.readdirSync(scopeDir)) {
20690
21210
  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)}`);
21211
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
21212
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20693
21213
  }
20694
21214
  } else {
20695
21215
  for (const entry of fs9.readdirSync(npmRoot)) {
20696
21216
  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)}`);
21217
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
21218
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20699
21219
  }
20700
21220
  }
20701
21221
  if (fs9.existsSync(binDir)) {
20702
21222
  for (const entry of fs9.readdirSync(binDir)) {
20703
21223
  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)}`);
21224
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
21225
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20706
21226
  }
20707
21227
  }
20708
21228
  }
@@ -20803,6 +21323,56 @@ function normalizeReleaseChannel(value) {
20803
21323
  function resolveUpgradeChannel(args) {
20804
21324
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20805
21325
  }
21326
+ function readProviderPriorityFromPolicy(policy) {
21327
+ const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
21328
+ const raw = record.providerPriority;
21329
+ if (!Array.isArray(raw)) return [];
21330
+ const seen = /* @__PURE__ */ new Set();
21331
+ return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
21332
+ if (seen.has(type)) return false;
21333
+ seen.add(type);
21334
+ return true;
21335
+ });
21336
+ }
21337
+ async function resolveProviderTypeFromPriority(args) {
21338
+ if (!args.providerPriority.length) {
21339
+ return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
21340
+ }
21341
+ const failed = [];
21342
+ for (const requestedType of args.providerPriority) {
21343
+ const normalizedType = args.providerLoader.resolveAlias(requestedType);
21344
+ if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
21345
+ failed.push(`${requestedType}: disabled`);
21346
+ continue;
21347
+ }
21348
+ const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
21349
+ args.providerLoader.setCliDetectionResults([{
21350
+ id: normalizedType,
21351
+ installed: !!detected,
21352
+ path: detected?.path
21353
+ }], false);
21354
+ args.onStatusChange?.();
21355
+ if (detected) return { providerType: normalizedType };
21356
+ failed.push(`${requestedType}: not detected`);
21357
+ }
21358
+ return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
21359
+ }
21360
+ function loadYamlModule() {
21361
+ return yaml;
21362
+ }
21363
+ function getMcpServersKey(format) {
21364
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
21365
+ }
21366
+ function parseMeshCoordinatorMcpConfig(text, format) {
21367
+ if (!text.trim()) return {};
21368
+ if (format === "claude_mcp_json") return JSON.parse(text);
21369
+ const parsed = loadYamlModule().load(text);
21370
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
21371
+ }
21372
+ function serializeMeshCoordinatorMcpConfig(config, format) {
21373
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
21374
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
21375
+ }
20806
21376
  var CHAT_COMMANDS = [
20807
21377
  "send_chat",
20808
21378
  "new_chat",
@@ -20901,6 +21471,109 @@ var DaemonCommandRouter = class {
20901
21471
  constructor(deps) {
20902
21472
  this.deps = deps;
20903
21473
  }
21474
+ getCachedInlineMesh(meshId, inlineMesh) {
21475
+ if (inlineMesh && typeof inlineMesh === "object") {
21476
+ this.inlineMeshCache.set(meshId, inlineMesh);
21477
+ return inlineMesh;
21478
+ }
21479
+ return this.inlineMeshCache.get(meshId);
21480
+ }
21481
+ async getMeshForCommand(meshId, inlineMesh) {
21482
+ try {
21483
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21484
+ const mesh = getMesh3(meshId);
21485
+ if (mesh) return { mesh, inline: false };
21486
+ } catch {
21487
+ }
21488
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21489
+ return cached ? { mesh: cached, inline: true } : null;
21490
+ }
21491
+ updateInlineMeshNode(meshId, mesh, node) {
21492
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21493
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21494
+ if (idx >= 0) mesh.nodes[idx] = node;
21495
+ else mesh.nodes.push(node);
21496
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21497
+ this.inlineMeshCache.set(meshId, mesh);
21498
+ }
21499
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21500
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21501
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21502
+ if (idx === -1) return false;
21503
+ mesh.nodes.splice(idx, 1);
21504
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21505
+ this.inlineMeshCache.set(meshId, mesh);
21506
+ return true;
21507
+ }
21508
+ normalizeMeshSessionCleanupMode(value) {
21509
+ return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
21510
+ }
21511
+ sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
21512
+ const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
21513
+ if (!sessionId) return false;
21514
+ if (sessionIds?.size) return sessionIds.has(sessionId);
21515
+ const workspace = typeof node?.workspace === "string" ? node.workspace : "";
21516
+ if (workspace && record?.workspace === workspace) return true;
21517
+ if (record?.meta?.meshNodeId === nodeId) return true;
21518
+ return false;
21519
+ }
21520
+ isCompletedHostedSession(record) {
21521
+ return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
21522
+ }
21523
+ async cleanupMeshSessions(args) {
21524
+ if (args.mode === "preserve") {
21525
+ return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
21526
+ }
21527
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
21528
+ const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
21529
+ const sessions = await this.deps.sessionHostControl.listSessions();
21530
+ const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
21531
+ const stoppedSessionIds = [];
21532
+ const deletedSessionIds = [];
21533
+ const skippedSessionIds = [];
21534
+ const errors = [];
21535
+ for (const record of matched) {
21536
+ const sessionId = String(record.sessionId);
21537
+ const completed = this.isCompletedHostedSession(record);
21538
+ try {
21539
+ if (args.mode === "stop") {
21540
+ if (!completed) {
21541
+ if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
21542
+ stoppedSessionIds.push(sessionId);
21543
+ } else {
21544
+ skippedSessionIds.push(sessionId);
21545
+ }
21546
+ continue;
21547
+ }
21548
+ if (args.mode === "delete_stopped") {
21549
+ if (completed) {
21550
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
21551
+ deletedSessionIds.push(sessionId);
21552
+ } else {
21553
+ skippedSessionIds.push(sessionId);
21554
+ }
21555
+ continue;
21556
+ }
21557
+ if (args.mode === "stop_and_delete") {
21558
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
21559
+ deletedSessionIds.push(sessionId);
21560
+ continue;
21561
+ }
21562
+ } catch (e) {
21563
+ errors.push({ sessionId, error: e?.message || String(e) });
21564
+ }
21565
+ }
21566
+ return {
21567
+ success: errors.length === 0,
21568
+ mode: args.mode,
21569
+ dryRun: args.dryRun === true,
21570
+ matchedCount: matched.length,
21571
+ stoppedSessionIds,
21572
+ deletedSessionIds,
21573
+ skippedSessionIds,
21574
+ ...errors.length ? { errors } : {}
21575
+ };
21576
+ }
20904
21577
  async traceSessionHostAction(action, args, run, summarizeResult) {
20905
21578
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20906
21579
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -21020,6 +21693,9 @@ var DaemonCommandRouter = class {
21020
21693
  async executeDaemonCommand(cmd, args) {
21021
21694
  switch (cmd) {
21022
21695
  // ─── CLI / ACP commands ───
21696
+ case "mesh_forward_event": {
21697
+ return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
21698
+ }
21023
21699
  case "launch_cli":
21024
21700
  case "stop_cli":
21025
21701
  case "set_cli_view_mode":
@@ -21564,7 +22240,26 @@ var DaemonCommandRouter = class {
21564
22240
  if (!name) return { success: false, error: "name required" };
21565
22241
  try {
21566
22242
  const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21567
- const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
22243
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
22244
+ return { success: true, mesh };
22245
+ } catch (e) {
22246
+ return { success: false, error: e.message };
22247
+ }
22248
+ }
22249
+ case "update_mesh": {
22250
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22251
+ if (!meshId) return { success: false, error: "meshId required" };
22252
+ try {
22253
+ const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22254
+ const patch = {};
22255
+ if (typeof args?.name === "string") patch.name = args.name;
22256
+ if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
22257
+ if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
22258
+ if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
22259
+ if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
22260
+ const mesh = updateMesh2(meshId, patch);
22261
+ if (!mesh) return { success: false, error: "Mesh not found" };
22262
+ this.inlineMeshCache.set(meshId, mesh);
21568
22263
  return { success: true, mesh };
21569
22264
  } catch (e) {
21570
22265
  return { success: false, error: e.message };
@@ -21588,21 +22283,164 @@ var DaemonCommandRouter = class {
21588
22283
  if (!workspace) return { success: false, error: "workspace required" };
21589
22284
  try {
21590
22285
  const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21591
- const node = addNode3(meshId, { workspace });
22286
+ const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
22287
+ const readOnly = args?.readOnly === true;
22288
+ const policy = {
22289
+ ...readOnly ? { readOnly: true } : {},
22290
+ ...providerPriority.length ? { providerPriority } : {}
22291
+ };
22292
+ const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
21592
22293
  if (!node) return { success: false, error: "Mesh not found" };
21593
22294
  return { success: true, node };
21594
22295
  } catch (e) {
21595
22296
  return { success: false, error: e.message };
21596
22297
  }
21597
22298
  }
22299
+ case "update_mesh_node": {
22300
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22301
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22302
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22303
+ try {
22304
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22305
+ const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
22306
+ if (Array.isArray(args?.providerPriority)) {
22307
+ const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
22308
+ delete policy.provider_priority;
22309
+ if (providerPriority.length) {
22310
+ policy.providerPriority = providerPriority;
22311
+ } else {
22312
+ delete policy.providerPriority;
22313
+ }
22314
+ }
22315
+ const node = updateNode2(meshId, nodeId, { policy });
22316
+ if (!node) return { success: false, error: "Mesh node not found" };
22317
+ return { success: true, node };
22318
+ } catch (e) {
22319
+ return { success: false, error: e.message };
22320
+ }
22321
+ }
22322
+ case "cleanup_mesh_sessions": {
22323
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22324
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22325
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22326
+ try {
22327
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22328
+ const mesh = meshRecord?.mesh;
22329
+ if (!mesh) return { success: false, error: "Mesh not found" };
22330
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22331
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
22332
+ const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
22333
+ const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
22334
+ const result = await this.cleanupMeshSessions({
22335
+ meshId,
22336
+ nodeId,
22337
+ node,
22338
+ mode,
22339
+ sessionIds,
22340
+ dryRun: args?.dryRun === true
22341
+ });
22342
+ return result;
22343
+ } catch (e) {
22344
+ return { success: false, error: e.message };
22345
+ }
22346
+ }
21598
22347
  case "remove_mesh_node": {
21599
22348
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21600
22349
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21601
22350
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21602
22351
  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 };
22352
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22353
+ const mesh = meshRecord?.mesh;
22354
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22355
+ const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
22356
+ args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
22357
+ );
22358
+ let sessionCleanup;
22359
+ if (node && sessionCleanupMode !== "preserve") {
22360
+ sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
22361
+ if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
22362
+ }
22363
+ if (node?.isLocalWorktree && node.workspace) {
22364
+ try {
22365
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
22366
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
22367
+ if (repoRoot) {
22368
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22369
+ await removeWorktree2(repoRoot, node.workspace);
22370
+ }
22371
+ } catch (e) {
22372
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
22373
+ }
22374
+ }
22375
+ let removed = false;
22376
+ if (meshRecord?.inline) {
22377
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
22378
+ } else {
22379
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22380
+ removed = removeNode3(meshId, nodeId);
22381
+ }
22382
+ return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
22383
+ } catch (e) {
22384
+ return { success: false, error: e.message };
22385
+ }
22386
+ }
22387
+ case "clone_mesh_node": {
22388
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22389
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
22390
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
22391
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
22392
+ if (!meshId) return { success: false, error: "meshId required" };
22393
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
22394
+ if (!branch) return { success: false, error: "branch required" };
22395
+ try {
22396
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22397
+ const mesh = meshRecord?.mesh;
22398
+ if (!mesh) return { success: false, error: "Mesh not found" };
22399
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
22400
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
22401
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
22402
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22403
+ const result = await createWorktree2({
22404
+ repoRoot,
22405
+ branch,
22406
+ baseBranch,
22407
+ meshName: mesh.name
22408
+ });
22409
+ let node;
22410
+ if (meshRecord.inline) {
22411
+ const { randomUUID: randomUUID8 } = await import("crypto");
22412
+ node = {
22413
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
22414
+ workspace: result.worktreePath,
22415
+ repoRoot: result.worktreePath,
22416
+ daemonId: sourceNode.daemonId,
22417
+ userOverrides: { ...sourceNode.userOverrides || {} },
22418
+ policy: { ...sourceNode.policy || {} },
22419
+ isLocalWorktree: true,
22420
+ worktreeBranch: result.branch,
22421
+ clonedFromNodeId: sourceNodeId
22422
+ };
22423
+ this.updateInlineMeshNode(meshId, mesh, node);
22424
+ } else {
22425
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22426
+ node = addNode3(meshId, {
22427
+ workspace: result.worktreePath,
22428
+ repoRoot: result.worktreePath,
22429
+ daemonId: sourceNode.daemonId,
22430
+ userOverrides: { ...sourceNode.userOverrides || {} },
22431
+ isLocalWorktree: true,
22432
+ worktreeBranch: result.branch,
22433
+ clonedFromNodeId: sourceNodeId,
22434
+ policy: { ...sourceNode.policy || {} }
22435
+ });
22436
+ if (!node) return { success: false, error: "Failed to register worktree node" };
22437
+ }
22438
+ return {
22439
+ success: true,
22440
+ node,
22441
+ worktreePath: result.worktreePath,
22442
+ branch: result.branch
22443
+ };
21606
22444
  } catch (e) {
21607
22445
  return { success: false, error: e.message };
21608
22446
  }
@@ -21610,7 +22448,7 @@ var DaemonCommandRouter = class {
21610
22448
  // ─── Mesh Coordinator Launch ───
21611
22449
  case "launch_mesh_coordinator": {
21612
22450
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21613
- const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
22451
+ let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
21614
22452
  if (!meshId) return { success: false, error: "meshId required" };
21615
22453
  try {
21616
22454
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -21638,9 +22476,29 @@ var DaemonCommandRouter = class {
21638
22476
  }
21639
22477
  const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
21640
22478
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
22479
+ if (!cliType) {
22480
+ const resolved = await resolveProviderTypeFromPriority({
22481
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
22482
+ providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
22483
+ providerLoader: this.deps.providerLoader,
22484
+ onStatusChange: this.deps.onStatusChange
22485
+ });
22486
+ if (!resolved.providerType) {
22487
+ return {
22488
+ success: false,
22489
+ code: "mesh_coordinator_provider_priority_unusable",
22490
+ error: resolved.error || "No usable provider found from node providerPriority",
22491
+ meshId,
22492
+ cliType,
22493
+ workspace
22494
+ };
22495
+ }
22496
+ cliType = resolved.providerType;
22497
+ }
21641
22498
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21642
22499
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21643
22500
  provider: providerMeta,
22501
+ cliType,
21644
22502
  meshId,
21645
22503
  workspace
21646
22504
  });
@@ -21665,7 +22523,8 @@ var DaemonCommandRouter = class {
21665
22523
  meshCoordinatorSetup: coordinatorSetup
21666
22524
  };
21667
22525
  }
21668
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
22526
+ const configFormat = coordinatorSetup.configFormat;
22527
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21669
22528
  return {
21670
22529
  success: false,
21671
22530
  code: "mesh_coordinator_unsupported",
@@ -21675,44 +22534,93 @@ var DaemonCommandRouter = class {
21675
22534
  workspace
21676
22535
  };
21677
22536
  }
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
- }
22537
+ let systemPrompt = "";
22538
+ try {
22539
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
22540
+ } catch (error) {
22541
+ const message = error?.message || String(error);
22542
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
22543
+ return {
22544
+ success: false,
22545
+ code: "mesh_coordinator_prompt_failed",
22546
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
22547
+ meshId,
22548
+ cliType,
22549
+ workspace
22550
+ };
21688
22551
  }
22552
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22553
+ const { dirname: dirname9 } = await import("path");
22554
+ const mcpConfigPath = coordinatorSetup.configPath;
22555
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
22556
+ const returnManualFallback = (message) => ({
22557
+ success: false,
22558
+ code: "mesh_coordinator_manual_mcp_setup_required",
22559
+ error: message,
22560
+ meshId,
22561
+ cliType,
22562
+ workspace,
22563
+ meshCoordinatorSetup: hermesManualFallback
22564
+ });
21689
22565
  const mcpServerEntry = {
21690
22566
  command: coordinatorSetup.mcpServer.command,
21691
22567
  args: coordinatorSetup.mcpServer.args
21692
22568
  };
21693
22569
  if (args?.inlineMesh) {
21694
22570
  mcpServerEntry.env = {
21695
- ADHDEV_INLINE_MESH: JSON.stringify(mesh)
22571
+ ADHDEV_INLINE_MESH: JSON.stringify(mesh),
22572
+ ADHDEV_MCP_TRANSPORT: "ipc"
21696
22573
  };
21697
22574
  }
22575
+ try {
22576
+ mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
22577
+ } catch (error) {
22578
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22579
+ LOG.error("MeshCoordinator", message);
22580
+ if (hermesManualFallback) return returnManualFallback(message);
22581
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
22582
+ }
22583
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
22584
+ let existingMcpConfig = {};
22585
+ if (hadExistingMcpConfig) {
22586
+ try {
22587
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
22588
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
22589
+ } catch (error) {
22590
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
22591
+ return {
22592
+ success: false,
22593
+ code: "mesh_coordinator_config_parse_failed",
22594
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
22595
+ };
22596
+ }
22597
+ }
22598
+ const mcpServersKey = getMcpServersKey(configFormat);
22599
+ const existingServers = existingMcpConfig[mcpServersKey];
21698
22600
  const mcpConfig = {
21699
22601
  ...existingMcpConfig,
21700
- mcpServers: {
21701
- ...existingMcpConfig.mcpServers || {},
22602
+ [mcpServersKey]: {
22603
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21702
22604
  [coordinatorSetup.serverName]: mcpServerEntry
21703
22605
  }
21704
22606
  };
21705
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21706
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21707
- let systemPrompt = "";
21708
22607
  try {
21709
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
21710
- } catch {
21711
- 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).`;
22608
+ writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22609
+ } catch (error) {
22610
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22611
+ LOG.error("MeshCoordinator", message);
22612
+ if (hermesManualFallback) return returnManualFallback(message);
22613
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21712
22614
  }
22615
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21713
22616
  const cliArgs = [];
22617
+ const launchEnv = {};
21714
22618
  if (systemPrompt) {
21715
- cliArgs.push("--append-system-prompt", systemPrompt);
22619
+ if (configFormat === "hermes_config_yaml") {
22620
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22621
+ } else {
22622
+ cliArgs.push("--append-system-prompt", systemPrompt);
22623
+ }
21716
22624
  }
21717
22625
  if (cliType === "claude-cli") {
21718
22626
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21721,6 +22629,7 @@ var DaemonCommandRouter = class {
21721
22629
  cliType,
21722
22630
  dir: workspace,
21723
22631
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22632
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21724
22633
  settings: {
21725
22634
  meshCoordinatorFor: meshId
21726
22635
  }
@@ -21900,6 +22809,12 @@ var DaemonStatusReporter = class {
21900
22809
  if (providerType) {
21901
22810
  payload.providerType = providerType;
21902
22811
  }
22812
+ if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
22813
+ payload.providerSessionId = event.providerSessionId.trim();
22814
+ }
22815
+ if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
22816
+ payload.workspaceName = event.workspaceName.trim();
22817
+ }
21903
22818
  if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
21904
22819
  payload.duration = event.duration;
21905
22820
  }
@@ -23147,7 +24062,10 @@ var ProviderInstanceManager = class {
23147
24062
  this.instances.get(id).dispose();
23148
24063
  }
23149
24064
  this.instances.set(id, instance);
23150
- await instance.init(context);
24065
+ await instance.init({
24066
+ ...context,
24067
+ emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
24068
+ });
23151
24069
  }
23152
24070
  /**
23153
24071
  * Instance remove
@@ -23309,6 +24227,17 @@ var ProviderInstanceManager = class {
23309
24227
  onEvent(listener) {
23310
24228
  this.eventListeners.push(listener);
23311
24229
  }
24230
+ emitProviderEvent(providerType, instanceId, event) {
24231
+ const payload = {
24232
+ ...event,
24233
+ providerType,
24234
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
24235
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
24236
+ };
24237
+ for (const listener of this.eventListeners) {
24238
+ listener(payload);
24239
+ }
24240
+ }
23312
24241
  emitPendingEvents(providerType, state, extra = {}) {
23313
24242
  for (const event of state.pendingEvents) {
23314
24243
  for (const listener of this.eventListeners) {
@@ -23381,11 +24310,11 @@ var ProviderInstanceManager = class {
23381
24310
 
23382
24311
  // src/providers/version-archive.ts
23383
24312
  var fs11 = __toESM(require("fs"));
23384
- var path21 = __toESM(require("path"));
23385
- var os19 = __toESM(require("os"));
24313
+ var path22 = __toESM(require("path"));
24314
+ var os20 = __toESM(require("os"));
23386
24315
  var import_child_process10 = require("child_process");
23387
24316
  var import_os3 = require("os");
23388
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
24317
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23389
24318
  var MAX_ENTRIES_PER_PROVIDER = 20;
23390
24319
  var VersionArchive = class {
23391
24320
  history = {};
@@ -23432,7 +24361,7 @@ var VersionArchive = class {
23432
24361
  }
23433
24362
  save() {
23434
24363
  try {
23435
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
24364
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23436
24365
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23437
24366
  } catch {
23438
24367
  }
@@ -23488,8 +24417,8 @@ function getVersion(binary, versionCommand) {
23488
24417
  function checkPathExists2(paths) {
23489
24418
  for (const p of paths) {
23490
24419
  if (p.includes("*")) {
23491
- const home = os19.homedir();
23492
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
24420
+ const home = os20.homedir();
24421
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23493
24422
  if (fs11.existsSync(resolved)) return resolved;
23494
24423
  } else {
23495
24424
  if (fs11.existsSync(p)) return p;
@@ -23499,7 +24428,7 @@ function checkPathExists2(paths) {
23499
24428
  }
23500
24429
  function getMacAppVersion(appPath) {
23501
24430
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
23502
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
24431
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23503
24432
  if (!fs11.existsSync(plistPath)) return null;
23504
24433
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23505
24434
  return raw || null;
@@ -23525,7 +24454,7 @@ async function detectAllVersions(loader, archive) {
23525
24454
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23526
24455
  let resolvedBin = cliBin;
23527
24456
  if (!resolvedBin && appPath && currentOs === "darwin") {
23528
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24457
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23529
24458
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23530
24459
  }
23531
24460
  info.installed = !!(appPath || resolvedBin);
@@ -23566,7 +24495,7 @@ async function detectAllVersions(loader, archive) {
23566
24495
  // src/daemon/dev-server.ts
23567
24496
  var http2 = __toESM(require("http"));
23568
24497
  var fs15 = __toESM(require("fs"));
23569
- var path25 = __toESM(require("path"));
24498
+ var path26 = __toESM(require("path"));
23570
24499
  init_config();
23571
24500
 
23572
24501
  // src/daemon/scaffold-template.ts
@@ -23917,7 +24846,7 @@ init_logger();
23917
24846
 
23918
24847
  // src/daemon/dev-cdp-handlers.ts
23919
24848
  var fs12 = __toESM(require("fs"));
23920
- var path22 = __toESM(require("path"));
24849
+ var path23 = __toESM(require("path"));
23921
24850
  init_logger();
23922
24851
  async function handleCdpEvaluate(ctx, req, res) {
23923
24852
  const body = await ctx.readBody(req);
@@ -24096,17 +25025,17 @@ async function handleScriptHints(ctx, type, _req, res) {
24096
25025
  return;
24097
25026
  }
24098
25027
  let scriptsPath = "";
24099
- const directScripts = path22.join(dir, "scripts.js");
25028
+ const directScripts = path23.join(dir, "scripts.js");
24100
25029
  if (fs12.existsSync(directScripts)) {
24101
25030
  scriptsPath = directScripts;
24102
25031
  } else {
24103
- const scriptsDir = path22.join(dir, "scripts");
25032
+ const scriptsDir = path23.join(dir, "scripts");
24104
25033
  if (fs12.existsSync(scriptsDir)) {
24105
25034
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
24106
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
25035
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
24107
25036
  }).sort().reverse();
24108
25037
  for (const ver of versions) {
24109
- const p = path22.join(scriptsDir, ver, "scripts.js");
25038
+ const p = path23.join(scriptsDir, ver, "scripts.js");
24110
25039
  if (fs12.existsSync(p)) {
24111
25040
  scriptsPath = p;
24112
25041
  break;
@@ -24935,7 +25864,7 @@ async function handleDomContext(ctx, type, req, res) {
24935
25864
 
24936
25865
  // src/daemon/dev-cli-debug.ts
24937
25866
  var fs13 = __toESM(require("fs"));
24938
- var path23 = __toESM(require("path"));
25867
+ var path24 = __toESM(require("path"));
24939
25868
  function slugifyFixtureName(value) {
24940
25869
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24941
25870
  return normalized || `fixture-${Date.now()}`;
@@ -24945,11 +25874,11 @@ function getCliFixtureDir(ctx, type) {
24945
25874
  if (!providerDir) {
24946
25875
  throw new Error(`Provider directory not found for '${type}'`);
24947
25876
  }
24948
- return path23.join(providerDir, "fixtures");
25877
+ return path24.join(providerDir, "fixtures");
24949
25878
  }
24950
25879
  function readCliFixture(ctx, type, name) {
24951
25880
  const fixtureDir = getCliFixtureDir(ctx, type);
24952
- const filePath = path23.join(fixtureDir, `${name}.json`);
25881
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24953
25882
  if (!fs13.existsSync(filePath)) {
24954
25883
  throw new Error(`Fixture not found: ${filePath}`);
24955
25884
  }
@@ -25716,7 +26645,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25716
26645
  },
25717
26646
  notes: typeof body?.notes === "string" ? body.notes : void 0
25718
26647
  };
25719
- const filePath = path23.join(fixtureDir, `${name}.json`);
26648
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25720
26649
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25721
26650
  ctx.json(res, 200, {
25722
26651
  saved: true,
@@ -25740,7 +26669,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25740
26669
  return;
25741
26670
  }
25742
26671
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
25743
- const fullPath = path23.join(fixtureDir, file);
26672
+ const fullPath = path24.join(fixtureDir, file);
25744
26673
  try {
25745
26674
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25746
26675
  return {
@@ -25876,8 +26805,8 @@ async function handleCliRaw(ctx, req, res) {
25876
26805
 
25877
26806
  // src/daemon/dev-auto-implement.ts
25878
26807
  var fs14 = __toESM(require("fs"));
25879
- var path24 = __toESM(require("path"));
25880
- var os20 = __toESM(require("os"));
26808
+ var path25 = __toESM(require("path"));
26809
+ var os21 = __toESM(require("os"));
25881
26810
  function getAutoImplPid(ctx) {
25882
26811
  const pid = ctx.autoImplProcess?.pid;
25883
26812
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25926,22 +26855,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25926
26855
  if (!fs14.existsSync(scriptsDir)) return null;
25927
26856
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25928
26857
  try {
25929
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
26858
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25930
26859
  } catch {
25931
26860
  return false;
25932
26861
  }
25933
26862
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25934
26863
  if (versions.length === 0) return null;
25935
- return path24.join(scriptsDir, versions[0]);
26864
+ return path25.join(scriptsDir, versions[0]);
25936
26865
  }
25937
26866
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25938
- const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25939
- const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25940
- const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25941
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
26867
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26868
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26869
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26870
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25942
26871
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25943
26872
  }
25944
- if (path24.basename(desiredDir) !== type) {
26873
+ if (path25.basename(desiredDir) !== type) {
25945
26874
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25946
26875
  }
25947
26876
  const sourceDir = ctx.findProviderDir(type);
@@ -25949,11 +26878,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25949
26878
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25950
26879
  }
25951
26880
  if (!fs14.existsSync(desiredDir)) {
25952
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
26881
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25953
26882
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25954
26883
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25955
26884
  }
25956
- const providerJson = path24.join(desiredDir, "provider.json");
26885
+ const providerJson = path25.join(desiredDir, "provider.json");
25957
26886
  if (!fs14.existsSync(providerJson)) {
25958
26887
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25959
26888
  }
@@ -25964,13 +26893,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25964
26893
  const refDir = ctx.findProviderDir(referenceType);
25965
26894
  if (!refDir || !fs14.existsSync(refDir)) return {};
25966
26895
  const referenceScripts = {};
25967
- const scriptsDir = path24.join(refDir, "scripts");
26896
+ const scriptsDir = path25.join(refDir, "scripts");
25968
26897
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25969
26898
  if (!latestDir) return referenceScripts;
25970
26899
  for (const file of fs14.readdirSync(latestDir)) {
25971
26900
  if (!file.endsWith(".js")) continue;
25972
26901
  try {
25973
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
26902
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25974
26903
  } catch {
25975
26904
  }
25976
26905
  }
@@ -26078,9 +27007,9 @@ async function handleAutoImplement(ctx, type, req, res) {
26078
27007
  });
26079
27008
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
26080
27009
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
26081
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
27010
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
26082
27011
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
26083
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
27012
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26084
27013
  fs14.writeFileSync(promptFile, prompt, "utf-8");
26085
27014
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
26086
27015
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26233,7 +27162,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26233
27162
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26234
27163
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26235
27164
  let shellCmd;
26236
- const isWin = os20.platform() === "win32";
27165
+ const isWin = os21.platform() === "win32";
26237
27166
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26238
27167
  const promptMode = autoImpl?.promptMode ?? "stdin";
26239
27168
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26272,7 +27201,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26272
27201
  try {
26273
27202
  const pty = require("node-pty");
26274
27203
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26275
- const isWin2 = os20.platform() === "win32";
27204
+ const isWin2 = os21.platform() === "win32";
26276
27205
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26277
27206
  name: "xterm-256color",
26278
27207
  cols: 120,
@@ -26512,7 +27441,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26512
27441
  setMode: "set_mode.js"
26513
27442
  };
26514
27443
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26515
- const scriptsDir = path24.join(providerDir, "scripts");
27444
+ const scriptsDir = path25.join(providerDir, "scripts");
26516
27445
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26517
27446
  if (latestScriptsDir) {
26518
27447
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26523,7 +27452,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26523
27452
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26524
27453
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26525
27454
  try {
26526
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27455
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26527
27456
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26528
27457
  lines.push("```javascript");
26529
27458
  lines.push(content);
@@ -26540,7 +27469,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26540
27469
  lines.push("");
26541
27470
  for (const file of refFiles) {
26542
27471
  try {
26543
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27472
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26544
27473
  lines.push(`### \`${file}\` \u{1F512}`);
26545
27474
  lines.push("```javascript");
26546
27475
  lines.push(content);
@@ -26581,10 +27510,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26581
27510
  lines.push("");
26582
27511
  }
26583
27512
  }
26584
- const docsDir = path24.join(providerDir, "../../docs");
27513
+ const docsDir = path25.join(providerDir, "../../docs");
26585
27514
  const loadGuide = (name) => {
26586
27515
  try {
26587
- const p = path24.join(docsDir, name);
27516
+ const p = path25.join(docsDir, name);
26588
27517
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26589
27518
  } catch {
26590
27519
  }
@@ -26821,7 +27750,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26821
27750
  parseApproval: "parse_approval.js"
26822
27751
  };
26823
27752
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26824
- const scriptsDir = path24.join(providerDir, "scripts");
27753
+ const scriptsDir = path25.join(providerDir, "scripts");
26825
27754
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26826
27755
  if (latestScriptsDir) {
26827
27756
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26833,7 +27762,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26833
27762
  if (!file.endsWith(".js")) continue;
26834
27763
  if (!targetFileNames.has(file)) continue;
26835
27764
  try {
26836
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27765
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26837
27766
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26838
27767
  lines.push("```javascript");
26839
27768
  lines.push(content);
@@ -26849,7 +27778,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26849
27778
  lines.push("");
26850
27779
  for (const file of refFiles) {
26851
27780
  try {
26852
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27781
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26853
27782
  lines.push(`### \`${file}\` \u{1F512}`);
26854
27783
  lines.push("```javascript");
26855
27784
  lines.push(content);
@@ -26882,10 +27811,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26882
27811
  lines.push("");
26883
27812
  }
26884
27813
  }
26885
- const docsDir = path24.join(providerDir, "../../docs");
27814
+ const docsDir = path25.join(providerDir, "../../docs");
26886
27815
  const loadGuide = (name) => {
26887
27816
  try {
26888
- const p = path24.join(docsDir, name);
27817
+ const p = path25.join(docsDir, name);
26889
27818
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26890
27819
  } catch {
26891
27820
  }
@@ -27332,8 +28261,8 @@ var DevServer = class _DevServer {
27332
28261
  }
27333
28262
  getEndpointList() {
27334
28263
  return this.routes.map((r) => {
27335
- const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27336
- return `${r.method.padEnd(5)} ${path26}`;
28264
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28265
+ return `${r.method.padEnd(5)} ${path27}`;
27337
28266
  });
27338
28267
  }
27339
28268
  async start(port = DEV_SERVER_PORT) {
@@ -27621,12 +28550,12 @@ var DevServer = class _DevServer {
27621
28550
  // ─── DevConsole SPA ───
27622
28551
  getConsoleDistDir() {
27623
28552
  const candidates = [
27624
- path25.resolve(__dirname, "../../web-devconsole/dist"),
27625
- path25.resolve(__dirname, "../../../web-devconsole/dist"),
27626
- path25.join(process.cwd(), "packages/web-devconsole/dist")
28553
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
28554
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
28555
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27627
28556
  ];
27628
28557
  for (const dir of candidates) {
27629
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
28558
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27630
28559
  }
27631
28560
  return null;
27632
28561
  }
@@ -27636,7 +28565,7 @@ var DevServer = class _DevServer {
27636
28565
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27637
28566
  return;
27638
28567
  }
27639
- const htmlPath = path25.join(distDir, "index.html");
28568
+ const htmlPath = path26.join(distDir, "index.html");
27640
28569
  try {
27641
28570
  const html = fs15.readFileSync(htmlPath, "utf-8");
27642
28571
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27661,15 +28590,15 @@ var DevServer = class _DevServer {
27661
28590
  this.json(res, 404, { error: "Not found" });
27662
28591
  return;
27663
28592
  }
27664
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27665
- const filePath = path25.join(distDir, safePath);
28593
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28594
+ const filePath = path26.join(distDir, safePath);
27666
28595
  if (!filePath.startsWith(distDir)) {
27667
28596
  this.json(res, 403, { error: "Forbidden" });
27668
28597
  return;
27669
28598
  }
27670
28599
  try {
27671
28600
  const content = fs15.readFileSync(filePath);
27672
- const ext = path25.extname(filePath);
28601
+ const ext = path26.extname(filePath);
27673
28602
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27674
28603
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27675
28604
  res.end(content);
@@ -27782,9 +28711,9 @@ var DevServer = class _DevServer {
27782
28711
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27783
28712
  if (entry.isDirectory()) {
27784
28713
  files.push({ path: rel, size: 0, type: "dir" });
27785
- scan(path25.join(d, entry.name), rel);
28714
+ scan(path26.join(d, entry.name), rel);
27786
28715
  } else {
27787
- const stat2 = fs15.statSync(path25.join(d, entry.name));
28716
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27788
28717
  files.push({ path: rel, size: stat2.size, type: "file" });
27789
28718
  }
27790
28719
  }
@@ -27807,7 +28736,7 @@ var DevServer = class _DevServer {
27807
28736
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27808
28737
  return;
27809
28738
  }
27810
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28739
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27811
28740
  if (!fullPath.startsWith(dir)) {
27812
28741
  this.json(res, 403, { error: "Forbidden" });
27813
28742
  return;
@@ -27832,14 +28761,14 @@ var DevServer = class _DevServer {
27832
28761
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27833
28762
  return;
27834
28763
  }
27835
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28764
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27836
28765
  if (!fullPath.startsWith(dir)) {
27837
28766
  this.json(res, 403, { error: "Forbidden" });
27838
28767
  return;
27839
28768
  }
27840
28769
  try {
27841
28770
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27842
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28771
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27843
28772
  fs15.writeFileSync(fullPath, content, "utf-8");
27844
28773
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27845
28774
  this.providerLoader.reload();
@@ -27856,7 +28785,7 @@ var DevServer = class _DevServer {
27856
28785
  return;
27857
28786
  }
27858
28787
  for (const name of ["scripts.js", "provider.json"]) {
27859
- const p = path25.join(dir, name);
28788
+ const p = path26.join(dir, name);
27860
28789
  if (fs15.existsSync(p)) {
27861
28790
  const source = fs15.readFileSync(p, "utf-8");
27862
28791
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27877,8 +28806,8 @@ var DevServer = class _DevServer {
27877
28806
  this.json(res, 404, { error: `Provider not found: ${type}` });
27878
28807
  return;
27879
28808
  }
27880
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27881
- const targetPath = path25.join(dir, target);
28809
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28810
+ const targetPath = path26.join(dir, target);
27882
28811
  try {
27883
28812
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27884
28813
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -28025,7 +28954,7 @@ var DevServer = class _DevServer {
28025
28954
  }
28026
28955
  let targetDir;
28027
28956
  targetDir = this.providerLoader.getUserProviderDir(category, type);
28028
- const jsonPath = path25.join(targetDir, "provider.json");
28957
+ const jsonPath = path26.join(targetDir, "provider.json");
28029
28958
  if (fs15.existsSync(jsonPath)) {
28030
28959
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
28031
28960
  return;
@@ -28037,8 +28966,8 @@ var DevServer = class _DevServer {
28037
28966
  const createdFiles = ["provider.json"];
28038
28967
  if (result.files) {
28039
28968
  for (const [relPath, content] of Object.entries(result.files)) {
28040
- const fullPath = path25.join(targetDir, relPath);
28041
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28969
+ const fullPath = path26.join(targetDir, relPath);
28970
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
28042
28971
  fs15.writeFileSync(fullPath, content, "utf-8");
28043
28972
  createdFiles.push(relPath);
28044
28973
  }
@@ -28091,22 +29020,22 @@ var DevServer = class _DevServer {
28091
29020
  if (!fs15.existsSync(scriptsDir)) return null;
28092
29021
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
28093
29022
  try {
28094
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
29023
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
28095
29024
  } catch {
28096
29025
  return false;
28097
29026
  }
28098
29027
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
28099
29028
  if (versions.length === 0) return null;
28100
- return path25.join(scriptsDir, versions[0]);
29029
+ return path26.join(scriptsDir, versions[0]);
28101
29030
  }
28102
29031
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
28103
- const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
28104
- const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
28105
- const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
28106
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
29032
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
29033
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
29034
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
29035
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
28107
29036
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
28108
29037
  }
28109
- if (path25.basename(desiredDir) !== type) {
29038
+ if (path26.basename(desiredDir) !== type) {
28110
29039
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
28111
29040
  }
28112
29041
  const sourceDir = this.findProviderDir(type);
@@ -28114,11 +29043,11 @@ var DevServer = class _DevServer {
28114
29043
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
28115
29044
  }
28116
29045
  if (!fs15.existsSync(desiredDir)) {
28117
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
29046
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
28118
29047
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
28119
29048
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
28120
29049
  }
28121
- const providerJson = path25.join(desiredDir, "provider.json");
29050
+ const providerJson = path26.join(desiredDir, "provider.json");
28122
29051
  if (!fs15.existsSync(providerJson)) {
28123
29052
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
28124
29053
  }
@@ -28154,7 +29083,7 @@ var DevServer = class _DevServer {
28154
29083
  setMode: "set_mode.js"
28155
29084
  };
28156
29085
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28157
- const scriptsDir = path25.join(providerDir, "scripts");
29086
+ const scriptsDir = path26.join(providerDir, "scripts");
28158
29087
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28159
29088
  if (latestScriptsDir) {
28160
29089
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28165,7 +29094,7 @@ var DevServer = class _DevServer {
28165
29094
  for (const file of fs15.readdirSync(latestScriptsDir)) {
28166
29095
  if (file.endsWith(".js") && targetFileNames.has(file)) {
28167
29096
  try {
28168
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29097
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28169
29098
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28170
29099
  lines.push("```javascript");
28171
29100
  lines.push(content);
@@ -28182,7 +29111,7 @@ var DevServer = class _DevServer {
28182
29111
  lines.push("");
28183
29112
  for (const file of refFiles) {
28184
29113
  try {
28185
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29114
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28186
29115
  lines.push(`### \`${file}\` \u{1F512}`);
28187
29116
  lines.push("```javascript");
28188
29117
  lines.push(content);
@@ -28223,10 +29152,10 @@ var DevServer = class _DevServer {
28223
29152
  lines.push("");
28224
29153
  }
28225
29154
  }
28226
- const docsDir = path25.join(providerDir, "../../docs");
29155
+ const docsDir = path26.join(providerDir, "../../docs");
28227
29156
  const loadGuide = (name) => {
28228
29157
  try {
28229
- const p = path25.join(docsDir, name);
29158
+ const p = path26.join(docsDir, name);
28230
29159
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28231
29160
  } catch {
28232
29161
  }
@@ -28400,7 +29329,7 @@ var DevServer = class _DevServer {
28400
29329
  parseApproval: "parse_approval.js"
28401
29330
  };
28402
29331
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28403
- const scriptsDir = path25.join(providerDir, "scripts");
29332
+ const scriptsDir = path26.join(providerDir, "scripts");
28404
29333
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28405
29334
  if (latestScriptsDir) {
28406
29335
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28412,7 +29341,7 @@ var DevServer = class _DevServer {
28412
29341
  if (!file.endsWith(".js")) continue;
28413
29342
  if (!targetFileNames.has(file)) continue;
28414
29343
  try {
28415
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29344
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28416
29345
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28417
29346
  lines.push("```javascript");
28418
29347
  lines.push(content);
@@ -28428,7 +29357,7 @@ var DevServer = class _DevServer {
28428
29357
  lines.push("");
28429
29358
  for (const file of refFiles) {
28430
29359
  try {
28431
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29360
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28432
29361
  lines.push(`### \`${file}\` \u{1F512}`);
28433
29362
  lines.push("```javascript");
28434
29363
  lines.push(content);
@@ -28461,10 +29390,10 @@ var DevServer = class _DevServer {
28461
29390
  lines.push("");
28462
29391
  }
28463
29392
  }
28464
- const docsDir = path25.join(providerDir, "../../docs");
29393
+ const docsDir = path26.join(providerDir, "../../docs");
28465
29394
  const loadGuide = (name) => {
28466
29395
  try {
28467
- const p = path25.join(docsDir, name);
29396
+ const p = path26.join(docsDir, name);
28468
29397
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28469
29398
  } catch {
28470
29399
  }
@@ -29464,48 +30393,6 @@ var SessionRegistry = class {
29464
30393
  // src/boot/daemon-lifecycle.ts
29465
30394
  init_logger();
29466
30395
  init_config();
29467
-
29468
- // src/mesh/mesh-events.ts
29469
- init_mesh_config();
29470
- init_logger();
29471
- function setupMeshEventForwarding(components) {
29472
- components.instanceManager.onEvent((event) => {
29473
- if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
29474
- const instanceId = event.instanceId;
29475
- if (!instanceId) return;
29476
- const sourceInstance = components.instanceManager.getInstance(instanceId);
29477
- if (!sourceInstance || sourceInstance.category !== "cli") return;
29478
- const state = sourceInstance.getState();
29479
- const workspace = state.workspace;
29480
- if (!workspace) return;
29481
- const mesh = getMeshByRepo(workspace);
29482
- if (!mesh) return;
29483
- const allInstances = components.instanceManager.getByCategory("cli");
29484
- const coordinatorInstances = allInstances.filter((inst) => {
29485
- const instState = inst.getState();
29486
- if (instState.settings?.meshCoordinatorFor !== mesh.id) return false;
29487
- if (instState.instanceId === instanceId) return false;
29488
- return true;
29489
- });
29490
- if (coordinatorInstances.length === 0) return;
29491
- const targetNode = mesh.nodes.find((n) => n.workspace === workspace);
29492
- const nodeLabel = targetNode ? `Node '${targetNode.id}'` : `Agent at ${workspace}`;
29493
- let messageText = "";
29494
- if (event.event === "agent:generating_completed") {
29495
- messageText = `[System] ${nodeLabel} has completed its task and is now idle. You may use mesh_read_chat to review its progress.`;
29496
- } else if (event.event === "agent:waiting_approval") {
29497
- messageText = `[System] ${nodeLabel} is waiting for approval to proceed. You may use mesh_read_chat and mesh_approve to handle it.`;
29498
- }
29499
- if (!messageText) return;
29500
- for (const coord of coordinatorInstances) {
29501
- const coordState = coord.getState();
29502
- LOG.info("MeshEvents", `Forwarding event from ${workspace} to coordinator ${coordState.instanceId}`);
29503
- coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
29504
- }
29505
- });
29506
- }
29507
-
29508
- // src/boot/daemon-lifecycle.ts
29509
30396
  async function initDaemonComponents(config) {
29510
30397
  installGlobalInterceptor();
29511
30398
  const appConfig = loadConfig();
@@ -29812,6 +30699,7 @@ async function shutdownDaemonComponents(components) {
29812
30699
  createGitWorkspaceMonitor,
29813
30700
  createInteractionId,
29814
30701
  createMesh,
30702
+ createWorktree,
29815
30703
  deleteMesh,
29816
30704
  detectAllVersions,
29817
30705
  detectCLIs,
@@ -29864,6 +30752,7 @@ async function shutdownDaemonComponents(components) {
29864
30752
  launchWithCdp,
29865
30753
  listHostedCliRuntimes,
29866
30754
  listMeshes,
30755
+ listWorktrees,
29867
30756
  loadConfig,
29868
30757
  loadState,
29869
30758
  logCommand,
@@ -29883,6 +30772,7 @@ async function shutdownDaemonComponents(components) {
29883
30772
  normalizeSessionModalFields,
29884
30773
  parsePorcelainV2Status,
29885
30774
  parseProviderSourceConfigUpdate,
30775
+ parseWorktreeListOutput,
29886
30776
  partitionSessionHostDiagnosticsSessions,
29887
30777
  partitionSessionHostRecords,
29888
30778
  prepareSessionChatTailUpdate,
@@ -29892,6 +30782,7 @@ async function shutdownDaemonComponents(components) {
29892
30782
  recordDebugTrace,
29893
30783
  registerExtensionProviders,
29894
30784
  removeNode,
30785
+ removeWorktree,
29895
30786
  resetConfig,
29896
30787
  resetDebugRuntimeConfig,
29897
30788
  resetState,
@@ -29901,6 +30792,7 @@ async function shutdownDaemonComponents(components) {
29901
30792
  resolveGitRepository,
29902
30793
  resolveSessionHostAppName,
29903
30794
  resolveSessionHostAppNameResolution,
30795
+ resolveWorktreePath,
29904
30796
  runAsyncBatch,
29905
30797
  runGit,
29906
30798
  saveConfig,