@adhdev/daemon-core 0.9.76-rc.5 → 0.9.76-rc.50

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 +1382 -430
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +1409 -461
  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 +4 -0
  22. package/package.json +4 -5
  23. package/src/cli-adapters/provider-cli-adapter.ts +28 -7
  24. package/src/cli-adapters/provider-cli-runtime.ts +3 -2
  25. package/src/commands/chat-commands.ts +94 -8
  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 +554 -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 +4 -0
  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}`);
@@ -3177,7 +3336,14 @@ ${lastSnapshot}`;
3177
3336
  })() : null;
3178
3337
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
3179
3338
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
3180
- throw new Error(`${this.cliName} is still processing the previous prompt`);
3339
+ const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
3340
+ const parsedHasActionableModal = Boolean(
3341
+ parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
3342
+ );
3343
+ const terminalLooksIdle = this.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && !this.hasActionableApproval() && !parsedHasActionableModal;
3344
+ if (!terminalLooksIdle) {
3345
+ throw new Error(`${this.cliName} is still processing the previous prompt`);
3346
+ }
3181
3347
  }
3182
3348
  if (this.isWaitingForResponse && !allowInputDuringGeneration) {
3183
3349
  if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
@@ -3727,6 +3893,7 @@ __export(index_exports, {
3727
3893
  createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
3728
3894
  createInteractionId: () => createInteractionId,
3729
3895
  createMesh: () => createMesh,
3896
+ createWorktree: () => createWorktree,
3730
3897
  deleteMesh: () => deleteMesh,
3731
3898
  detectAllVersions: () => detectAllVersions,
3732
3899
  detectCLIs: () => detectCLIs,
@@ -3779,6 +3946,7 @@ __export(index_exports, {
3779
3946
  launchWithCdp: () => launchWithCdp,
3780
3947
  listHostedCliRuntimes: () => listHostedCliRuntimes,
3781
3948
  listMeshes: () => listMeshes,
3949
+ listWorktrees: () => listWorktrees,
3782
3950
  loadConfig: () => loadConfig,
3783
3951
  loadState: () => loadState,
3784
3952
  logCommand: () => logCommand,
@@ -3798,6 +3966,7 @@ __export(index_exports, {
3798
3966
  normalizeSessionModalFields: () => normalizeSessionModalFields,
3799
3967
  parsePorcelainV2Status: () => parsePorcelainV2Status,
3800
3968
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
3969
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
3801
3970
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
3802
3971
  partitionSessionHostRecords: () => partitionSessionHostRecords,
3803
3972
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
@@ -3807,6 +3976,7 @@ __export(index_exports, {
3807
3976
  recordDebugTrace: () => recordDebugTrace,
3808
3977
  registerExtensionProviders: () => registerExtensionProviders,
3809
3978
  removeNode: () => removeNode,
3979
+ removeWorktree: () => removeWorktree,
3810
3980
  resetConfig: () => resetConfig,
3811
3981
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
3812
3982
  resetState: () => resetState,
@@ -3816,6 +3986,7 @@ __export(index_exports, {
3816
3986
  resolveGitRepository: () => resolveGitRepository,
3817
3987
  resolveSessionHostAppName: () => resolveSessionHostAppName,
3818
3988
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
3989
+ resolveWorktreePath: () => resolveWorktreePath,
3819
3990
  runAsyncBatch: () => runAsyncBatch,
3820
3991
  runGit: () => runGit,
3821
3992
  saveConfig: () => saveConfig,
@@ -4739,6 +4910,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
4739
4910
  "dirty_index_required",
4740
4911
  "conflict",
4741
4912
  "invalid_args",
4913
+ "nothing_to_commit",
4742
4914
  "git_command_failed"
4743
4915
  ]);
4744
4916
  function failure(reason, error) {
@@ -4983,7 +5155,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
4983
5155
  } catch (err) {
4984
5156
  const output = (err?.stdout || "") + (err?.stderr || "");
4985
5157
  if (/nothing to commit/i.test(output)) {
4986
- throw new GitCommandError("git_command_failed", "Nothing to commit");
5158
+ throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
5159
+ stdout: err?.stdout,
5160
+ stderr: err?.stderr
5161
+ });
4987
5162
  }
4988
5163
  throw err;
4989
5164
  }
@@ -5175,20 +5350,23 @@ var TurnSnapshotTracker = class {
5175
5350
  }
5176
5351
  };
5177
5352
 
5353
+ // src/git/index.ts
5354
+ init_git_worktree();
5355
+
5178
5356
  // src/index.ts
5179
5357
  init_config();
5180
5358
 
5181
5359
  // src/config/workspaces.ts
5182
5360
  var fs = __toESM(require("fs"));
5183
5361
  var os = __toESM(require("os"));
5184
- var path4 = __toESM(require("path"));
5362
+ var path5 = __toESM(require("path"));
5185
5363
  var import_crypto2 = require("crypto");
5186
5364
  var MAX_WORKSPACES = 50;
5187
5365
  function expandPath(p) {
5188
5366
  const t = (p || "").trim();
5189
5367
  if (!t) return "";
5190
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5191
- return path4.resolve(t);
5368
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5369
+ return path5.resolve(t);
5192
5370
  }
5193
5371
  function validateWorkspacePath(absPath) {
5194
5372
  try {
@@ -5202,7 +5380,7 @@ function validateWorkspacePath(absPath) {
5202
5380
  }
5203
5381
  }
5204
5382
  function defaultWorkspaceLabel(absPath) {
5205
- const base = path4.basename(absPath) || absPath;
5383
+ const base = path5.basename(absPath) || absPath;
5206
5384
  return base;
5207
5385
  }
5208
5386
  function getDefaultWorkspacePath(config) {
@@ -5293,9 +5471,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5293
5471
  return getDefaultWorkspacePath(config) || void 0;
5294
5472
  }
5295
5473
  function findWorkspaceByPath(config, rawPath) {
5296
- const abs = path4.resolve(expandPath(rawPath));
5474
+ const abs = path5.resolve(expandPath(rawPath));
5297
5475
  if (!abs) return void 0;
5298
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5476
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5299
5477
  }
5300
5478
  function addWorkspaceEntry(config, rawPath, label, options) {
5301
5479
  const abs = expandPath(rawPath);
@@ -5311,7 +5489,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5311
5489
  const v = validateWorkspacePath(abs);
5312
5490
  if (!v.ok) return { error: v.error };
5313
5491
  const list = [...config.workspaces || []];
5314
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5492
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5315
5493
  return { error: "Workspace already in list" };
5316
5494
  }
5317
5495
  if (list.length >= MAX_WORKSPACES) {
@@ -5345,7 +5523,7 @@ function setDefaultWorkspaceId(config, id) {
5345
5523
  }
5346
5524
 
5347
5525
  // src/config/recent-activity.ts
5348
- var path5 = __toESM(require("path"));
5526
+ var path6 = __toESM(require("path"));
5349
5527
 
5350
5528
  // src/providers/summary-metadata.ts
5351
5529
  function normalizeSummaryItem(item) {
@@ -5414,9 +5592,9 @@ var MAX_ACTIVITY = 30;
5414
5592
  function normalizeWorkspace(workspace) {
5415
5593
  if (!workspace) return "";
5416
5594
  try {
5417
- return path5.resolve(expandPath(workspace));
5595
+ return path6.resolve(expandPath(workspace));
5418
5596
  } catch {
5419
- return path5.resolve(workspace);
5597
+ return path6.resolve(workspace);
5420
5598
  }
5421
5599
  }
5422
5600
  function buildRecentActivityKey(entry) {
@@ -5584,14 +5762,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5584
5762
  }
5585
5763
 
5586
5764
  // src/config/saved-sessions.ts
5587
- var path6 = __toESM(require("path"));
5765
+ var path7 = __toESM(require("path"));
5588
5766
  var MAX_SAVED_SESSIONS = 500;
5589
5767
  function normalizeWorkspace2(workspace) {
5590
5768
  if (!workspace) return "";
5591
5769
  try {
5592
- return path6.resolve(expandPath(workspace));
5770
+ return path7.resolve(expandPath(workspace));
5593
5771
  } catch {
5594
- return path6.resolve(workspace);
5772
+ return path7.resolve(workspace);
5595
5773
  }
5596
5774
  }
5597
5775
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5770,7 +5948,7 @@ function resetState() {
5770
5948
  var import_child_process = require("child_process");
5771
5949
  var import_fs4 = require("fs");
5772
5950
  var import_os2 = require("os");
5773
- var path7 = __toESM(require("path"));
5951
+ var path8 = __toESM(require("path"));
5774
5952
  var BUILTIN_IDE_DEFINITIONS = [];
5775
5953
  var registeredIDEs = /* @__PURE__ */ new Map();
5776
5954
  function registerIDEDefinition(def) {
@@ -5789,9 +5967,9 @@ function getMergedDefinitions() {
5789
5967
  function findCliCommand(command) {
5790
5968
  const trimmed = String(command || "").trim();
5791
5969
  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);
5970
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5971
+ const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5972
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5795
5973
  return (0, import_fs4.existsSync)(resolved) ? resolved : null;
5796
5974
  }
5797
5975
  try {
@@ -5819,7 +5997,7 @@ function getIdeVersion(cliCommand) {
5819
5997
  function checkPathExists(paths) {
5820
5998
  const home = (0, import_os2.homedir)();
5821
5999
  for (const p of paths) {
5822
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
6000
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5823
6001
  if (normalized.includes("*")) {
5824
6002
  const username = home.split(/[\\/]/).pop() || "";
5825
6003
  const resolved = normalized.replace("*", username);
@@ -5831,19 +6009,19 @@ function checkPathExists(paths) {
5831
6009
  return null;
5832
6010
  }
5833
6011
  async function detectIDEs(providerLoader) {
5834
- const os21 = (0, import_os2.platform)();
6012
+ const os22 = (0, import_os2.platform)();
5835
6013
  const results = [];
5836
6014
  for (const def of getMergedDefinitions()) {
5837
6015
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5838
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
6016
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5839
6017
  let resolvedCli = cliPath;
5840
- if (!resolvedCli && appPath && os21 === "darwin") {
6018
+ if (!resolvedCli && appPath && os22 === "darwin") {
5841
6019
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5842
6020
  if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
5843
6021
  }
5844
- if (!resolvedCli && appPath && os21 === "win32") {
5845
- const { dirname: dirname8 } = await import("path");
5846
- const appDir = dirname8(appPath);
6022
+ if (!resolvedCli && appPath && os22 === "win32") {
6023
+ const { dirname: dirname9 } = await import("path");
6024
+ const appDir = dirname9(appPath);
5847
6025
  const candidates = [
5848
6026
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5849
6027
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5858,7 +6036,7 @@ async function detectIDEs(providerLoader) {
5858
6036
  }
5859
6037
  }
5860
6038
  }
5861
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
6039
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5862
6040
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5863
6041
  results.push({
5864
6042
  id: def.id,
@@ -5877,7 +6055,7 @@ async function detectIDEs(providerLoader) {
5877
6055
  // src/detection/cli-detector.ts
5878
6056
  var import_child_process2 = require("child_process");
5879
6057
  var os2 = __toESM(require("os"));
5880
- var path8 = __toESM(require("path"));
6058
+ var path9 = __toESM(require("path"));
5881
6059
  var import_fs5 = require("fs");
5882
6060
  function parseVersion(raw) {
5883
6061
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -5890,18 +6068,18 @@ function shellQuote(value) {
5890
6068
  function expandHome(value) {
5891
6069
  const trimmed = value.trim();
5892
6070
  if (!trimmed.startsWith("~")) return trimmed;
5893
- return path8.join(os2.homedir(), trimmed.slice(1));
6071
+ return path9.join(os2.homedir(), trimmed.slice(1));
5894
6072
  }
5895
6073
  function isExplicitCommandPath(command) {
5896
6074
  const trimmed = command.trim();
5897
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
6075
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5898
6076
  }
5899
6077
  function resolveCommandPath(command) {
5900
6078
  const trimmed = command.trim();
5901
6079
  if (!trimmed) return null;
5902
6080
  if (isExplicitCommandPath(trimmed)) {
5903
6081
  const expanded = expandHome(trimmed);
5904
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
6082
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5905
6083
  return (0, import_fs5.existsSync)(candidate) ? candidate : null;
5906
6084
  }
5907
6085
  return null;
@@ -8170,9 +8348,9 @@ ${cleanBody}`;
8170
8348
 
8171
8349
  // src/config/chat-history.ts
8172
8350
  var fs3 = __toESM(require("fs"));
8173
- var path10 = __toESM(require("path"));
8351
+ var path11 = __toESM(require("path"));
8174
8352
  var os5 = __toESM(require("os"));
8175
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8353
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
8176
8354
  var RETAIN_DAYS = 30;
8177
8355
  var SAVED_HISTORY_INDEX_VERSION = 1;
8178
8356
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8335,7 +8513,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8335
8513
  function buildSavedHistoryFileSignatureMap(dir, files) {
8336
8514
  return new Map(files.map((file) => {
8337
8515
  try {
8338
- const stat2 = fs3.statSync(path10.join(dir, file));
8516
+ const stat2 = fs3.statSync(path11.join(dir, file));
8339
8517
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8340
8518
  } catch {
8341
8519
  return [file, `${file}:missing`];
@@ -8346,7 +8524,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8346
8524
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8347
8525
  }
8348
8526
  function getSavedHistoryIndexFilePath(dir) {
8349
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8527
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8350
8528
  }
8351
8529
  function getSavedHistoryIndexLockPath(dir) {
8352
8530
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8448,7 +8626,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8448
8626
  }
8449
8627
  for (const file of Array.from(currentEntries.keys())) {
8450
8628
  if (incomingFiles.has(file)) continue;
8451
- if (!fs3.existsSync(path10.join(dir, file))) {
8629
+ if (!fs3.existsSync(path11.join(dir, file))) {
8452
8630
  currentEntries.delete(file);
8453
8631
  }
8454
8632
  }
@@ -8474,7 +8652,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8474
8652
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8475
8653
  const files = listHistoryFiles(dir);
8476
8654
  for (const file of files) {
8477
- const stat2 = fs3.statSync(path10.join(dir, file));
8655
+ const stat2 = fs3.statSync(path11.join(dir, file));
8478
8656
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8479
8657
  }
8480
8658
  return false;
@@ -8484,14 +8662,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8484
8662
  }
8485
8663
  function buildSavedHistoryFileSignature(dir, file) {
8486
8664
  try {
8487
- const stat2 = fs3.statSync(path10.join(dir, file));
8665
+ const stat2 = fs3.statSync(path11.join(dir, file));
8488
8666
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8489
8667
  } catch {
8490
8668
  return `${file}:missing`;
8491
8669
  }
8492
8670
  }
8493
8671
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8494
- const filePath = path10.join(dir, file);
8672
+ const filePath = path11.join(dir, file);
8495
8673
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8496
8674
  const currentEntry = entries.get(file) || null;
8497
8675
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8564,7 +8742,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8564
8742
  function computeSavedHistoryFileSummary(dir, file) {
8565
8743
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8566
8744
  if (!historySessionId) return null;
8567
- const filePath = path10.join(dir, file);
8745
+ const filePath = path11.join(dir, file);
8568
8746
  const content = fs3.readFileSync(filePath, "utf-8");
8569
8747
  const lines = content.split("\n").filter(Boolean);
8570
8748
  let messageCount = 0;
@@ -8651,7 +8829,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8651
8829
  const summaryBySessionId = /* @__PURE__ */ new Map();
8652
8830
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8653
8831
  for (const file of files.slice().sort()) {
8654
- const filePath = path10.join(dir, file);
8832
+ const filePath = path11.join(dir, file);
8655
8833
  const signature = fileSignatures.get(file) || `${file}:missing`;
8656
8834
  const cached = savedHistoryFileSummaryCache.get(filePath);
8657
8835
  const persisted = persistedEntries.get(file);
@@ -8771,12 +8949,12 @@ var ChatHistoryWriter = class {
8771
8949
  });
8772
8950
  }
8773
8951
  if (newMessages.length === 0) return;
8774
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8952
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8775
8953
  fs3.mkdirSync(dir, { recursive: true });
8776
8954
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8777
8955
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8778
8956
  const fileName = `${filePrefix}${date}.jsonl`;
8779
- const filePath = path10.join(dir, fileName);
8957
+ const filePath = path11.join(dir, fileName);
8780
8958
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8781
8959
  fs3.appendFileSync(filePath, lines, "utf-8");
8782
8960
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8867,11 +9045,11 @@ var ChatHistoryWriter = class {
8867
9045
  const ws = String(workspace || "").trim();
8868
9046
  if (!id || !ws) return;
8869
9047
  try {
8870
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9048
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8871
9049
  fs3.mkdirSync(dir, { recursive: true });
8872
9050
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8873
9051
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8874
- const filePath = path10.join(dir, fileName);
9052
+ const filePath = path11.join(dir, fileName);
8875
9053
  const record = {
8876
9054
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8877
9055
  receivedAt: Date.now(),
@@ -8917,14 +9095,14 @@ var ChatHistoryWriter = class {
8917
9095
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8918
9096
  this.lastSeenCounts.delete(fromDedupKey);
8919
9097
  }
8920
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9098
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8921
9099
  if (!fs3.existsSync(dir)) return;
8922
9100
  const fromPrefix = `${this.sanitize(fromId)}_`;
8923
9101
  const toPrefix = `${this.sanitize(toId)}_`;
8924
9102
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8925
9103
  for (const file of files) {
8926
- const sourcePath = path10.join(dir, file);
8927
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
9104
+ const sourcePath = path11.join(dir, file);
9105
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8928
9106
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8929
9107
  const rewritten = sourceLines.map((line) => {
8930
9108
  try {
@@ -8958,13 +9136,13 @@ var ChatHistoryWriter = class {
8958
9136
  const sessionId = String(historySessionId || "").trim();
8959
9137
  if (!sessionId) return;
8960
9138
  try {
8961
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9139
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8962
9140
  if (!fs3.existsSync(dir)) return;
8963
9141
  const prefix = `${this.sanitize(sessionId)}_`;
8964
9142
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8965
9143
  const seen = /* @__PURE__ */ new Set();
8966
9144
  for (const file of files) {
8967
- const filePath = path10.join(dir, file);
9145
+ const filePath = path11.join(dir, file);
8968
9146
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8969
9147
  const next = [];
8970
9148
  for (const line of lines) {
@@ -9018,11 +9196,11 @@ var ChatHistoryWriter = class {
9018
9196
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
9019
9197
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
9020
9198
  for (const dir of agentDirs) {
9021
- const dirPath = path10.join(HISTORY_DIR, dir.name);
9199
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
9022
9200
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
9023
9201
  let removedAny = false;
9024
9202
  for (const file of files) {
9025
- const filePath = path10.join(dirPath, file);
9203
+ const filePath = path11.join(dirPath, file);
9026
9204
  const stat2 = fs3.statSync(filePath);
9027
9205
  if (stat2.mtimeMs < cutoff) {
9028
9206
  fs3.unlinkSync(filePath);
@@ -9072,13 +9250,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
9072
9250
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
9073
9251
  try {
9074
9252
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9075
- const dir = path10.join(HISTORY_DIR, sanitized);
9253
+ const dir = path11.join(HISTORY_DIR, sanitized);
9076
9254
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
9077
9255
  const files = listHistoryFiles(dir, historySessionId);
9078
9256
  const allMessages = [];
9079
9257
  const seen = /* @__PURE__ */ new Set();
9080
9258
  for (const file of files) {
9081
- const filePath = path10.join(dir, file);
9259
+ const filePath = path11.join(dir, file);
9082
9260
  const content = fs3.readFileSync(filePath, "utf-8");
9083
9261
  const lines = content.trim().split("\n").filter(Boolean);
9084
9262
  for (let i = 0; i < lines.length; i++) {
@@ -9102,7 +9280,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
9102
9280
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9103
9281
  try {
9104
9282
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9105
- const dir = path10.join(HISTORY_DIR, sanitized);
9283
+ const dir = path11.join(HISTORY_DIR, sanitized);
9106
9284
  if (!fs3.existsSync(dir)) {
9107
9285
  savedHistorySessionCache.delete(sanitized);
9108
9286
  return { sessions: [], hasMore: false };
@@ -9163,11 +9341,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9163
9341
  }
9164
9342
  function readExistingSessionStartRecord(agentType, historySessionId) {
9165
9343
  try {
9166
- const dir = path10.join(HISTORY_DIR, agentType);
9344
+ const dir = path11.join(HISTORY_DIR, agentType);
9167
9345
  if (!fs3.existsSync(dir)) return null;
9168
9346
  const files = listHistoryFiles(dir, historySessionId).sort();
9169
9347
  for (const file of files) {
9170
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9348
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
9171
9349
  for (const line of lines) {
9172
9350
  try {
9173
9351
  const parsed = JSON.parse(line);
@@ -9187,16 +9365,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
9187
9365
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
9188
9366
  if (records.length === 0) return false;
9189
9367
  try {
9190
- const dir = path10.join(HISTORY_DIR, agentType);
9368
+ const dir = path11.join(HISTORY_DIR, agentType);
9191
9369
  fs3.mkdirSync(dir, { recursive: true });
9192
9370
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9193
9371
  for (const file of fs3.readdirSync(dir)) {
9194
9372
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9195
- fs3.unlinkSync(path10.join(dir, file));
9373
+ fs3.unlinkSync(path11.join(dir, file));
9196
9374
  }
9197
9375
  }
9198
9376
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9199
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9377
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9200
9378
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9201
9379
  `, "utf-8");
9202
9380
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -11191,6 +11369,14 @@ function getActiveChatOptions(profile) {
11191
11369
  if (profile === "full") return {};
11192
11370
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11193
11371
  }
11372
+ function resolveSessionStatus(activeChat, providerStatus) {
11373
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11374
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11375
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11376
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11377
+ if (topLevelStatus !== "idle") return topLevelStatus;
11378
+ return chatStatus;
11379
+ }
11194
11380
  function shouldIncludeSessionControls(profile) {
11195
11381
  return profile !== "live";
11196
11382
  }
@@ -11269,9 +11455,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11269
11455
  providerName: state.name,
11270
11456
  kind: "workspace",
11271
11457
  transport: "cdp-page",
11272
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11273
- activeModal: activeChat?.activeModal || null
11274
- }),
11458
+ status: resolveSessionStatus(activeChat, state.status),
11275
11459
  title,
11276
11460
  workspace,
11277
11461
  ...git && { git },
@@ -11306,9 +11490,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11306
11490
  providerSessionId: ext.providerSessionId,
11307
11491
  kind: "agent",
11308
11492
  transport: "cdp-webview",
11309
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11310
- activeModal: activeChat?.activeModal || null
11311
- }),
11493
+ status: resolveSessionStatus(activeChat, ext.status),
11312
11494
  title: activeChat?.title || ext.name,
11313
11495
  workspace,
11314
11496
  ...git && { git },
@@ -11358,9 +11540,7 @@ function buildCliSession(state, options) {
11358
11540
  providerSessionId: state.providerSessionId,
11359
11541
  kind: "agent",
11360
11542
  transport: "pty",
11361
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11362
- activeModal: activeChat?.activeModal || null
11363
- }),
11543
+ status: resolveSessionStatus(activeChat, state.status),
11364
11544
  title: activeChat?.title || state.name,
11365
11545
  workspace,
11366
11546
  ...git && { git },
@@ -11408,9 +11588,7 @@ function buildAcpSession(state, options) {
11408
11588
  providerName: state.name,
11409
11589
  kind: "agent",
11410
11590
  transport: "acp",
11411
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11412
- activeModal: activeChat?.activeModal || null
11413
- }),
11591
+ status: resolveSessionStatus(activeChat, state.status),
11414
11592
  title: activeChat?.title || state.name,
11415
11593
  workspace,
11416
11594
  ...git && { git },
@@ -11533,7 +11711,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11533
11711
  // src/commands/chat-commands.ts
11534
11712
  var fs4 = __toESM(require("fs"));
11535
11713
  var os6 = __toESM(require("os"));
11536
- var path11 = __toESM(require("path"));
11714
+ var path12 = __toESM(require("path"));
11537
11715
  var import_node_crypto = require("crypto");
11538
11716
 
11539
11717
  // src/providers/provider-input-support.ts
@@ -11896,6 +12074,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11896
12074
  return raw;
11897
12075
  }
11898
12076
  }
12077
+ function isGeneratingLikeStatus(status) {
12078
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
12079
+ }
12080
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12081
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
12082
+ if (hasNonEmptyModalButtons(activeModal)) return false;
12083
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
12084
+ if (adapterRawStatus !== "idle") return false;
12085
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
12086
+ return true;
12087
+ }
12088
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12089
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
12090
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
12091
+ }
12092
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
12093
+ if (status !== "idle") return messages;
12094
+ return messages.map((message) => {
12095
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
12096
+ const hasStreamingMeta = meta?.streaming === true;
12097
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
12098
+ return {
12099
+ ...message,
12100
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
12101
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
12102
+ };
12103
+ });
12104
+ }
11899
12105
  function buildReadChatCommandResult(payload, args) {
11900
12106
  let validatedPayload;
11901
12107
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -12044,7 +12250,7 @@ function buildDebugBundleText(bundle) {
12044
12250
  }
12045
12251
  function getChatDebugBundleDir() {
12046
12252
  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");
12253
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12048
12254
  }
12049
12255
  function safeBundleIdSegment(value, fallback) {
12050
12256
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -12060,6 +12266,14 @@ function buildChatDebugBundleSummary(bundle) {
12060
12266
  const readChat = bundle.readChat && typeof bundle.readChat === "object" ? bundle.readChat : {};
12061
12267
  const cli = bundle.cli && typeof bundle.cli === "object" ? bundle.cli : null;
12062
12268
  const frontend = bundle.frontend && typeof bundle.frontend === "object" ? bundle.frontend : null;
12269
+ const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === "object" ? readChat.debugReadChat : {};
12270
+ const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === "object" ? cli.parsedStatus : null;
12271
+ const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : void 0;
12272
+ const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : void 0;
12273
+ const cliPartialResponse = typeof cli?.partialResponse === "string" ? cli.partialResponse : "";
12274
+ const readChatStatus = typeof readChat.status === "string" ? readChat.status : "";
12275
+ const cliStatus = typeof cli?.status === "string" ? cli.status : "";
12276
+ const cliParsedStatus = typeof parsedStatus?.status === "string" ? parsedStatus.status : "";
12063
12277
  return {
12064
12278
  createdAt: bundle.createdAt,
12065
12279
  targetSessionId: target.targetSessionId,
@@ -12068,8 +12282,22 @@ function buildChatDebugBundleSummary(bundle) {
12068
12282
  readChatSuccess: readChat.success,
12069
12283
  readChatStatus: readChat.status,
12070
12284
  readChatTotalMessages: readChat.totalMessages,
12285
+ readChatReturnedMessages,
12071
12286
  cliStatus: cli?.status,
12287
+ cliParsedStatus: cliParsedStatus || void 0,
12072
12288
  cliMessageCount: cli?.messageCount,
12289
+ cliParsedMessageCount,
12290
+ cliPartialResponseChars: cliPartialResponse.length,
12291
+ parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
12292
+ parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
12293
+ readChatDebug: Object.keys(debugReadChat).length ? {
12294
+ adapterStatus: debugReadChat.adapterStatus,
12295
+ parsedStatus: debugReadChat.parsedStatus,
12296
+ returnedStatus: debugReadChat.returnedStatus,
12297
+ parsedMsgCount: debugReadChat.parsedMsgCount,
12298
+ returnedMsgCount: debugReadChat.returnedMsgCount,
12299
+ shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages
12300
+ } : void 0,
12073
12301
  hasFrontendSnapshot: !!frontend
12074
12302
  };
12075
12303
  }
@@ -12077,7 +12305,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
12077
12305
  const bundleId = createChatDebugBundleId(targetSessionId);
12078
12306
  const dir = getChatDebugBundleDir();
12079
12307
  fs4.mkdirSync(dir, { recursive: true });
12080
- const savedPath = path11.join(dir, `${bundleId}.json`);
12308
+ const savedPath = path12.join(dir, `${bundleId}.json`);
12081
12309
  const json = `${JSON.stringify(bundle, null, 2)}
12082
12310
  `;
12083
12311
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12307,7 +12535,7 @@ async function handleChatHistory(h, args) {
12307
12535
  }
12308
12536
  }
12309
12537
  async function handleReadChat(h, args) {
12310
- const provider = h.getProvider(args?.agentType);
12538
+ const provider = h.getProvider(args?.agentType || args?.providerType);
12311
12539
  const transport = getTargetTransport(h, provider);
12312
12540
  const historySessionId = getHistorySessionId(h, args);
12313
12541
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
@@ -12334,10 +12562,13 @@ async function handleReadChat(h, args) {
12334
12562
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12335
12563
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12336
12564
  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}`);
12565
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12566
+ const runtimeMessageMerger = getTargetInstance(h, args);
12567
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12568
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12569
+ 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
12570
  return buildReadChatCommandResult({
12340
- messages: parsedRecord.messages,
12571
+ messages: returnedMessages,
12341
12572
  status: returnedStatus,
12342
12573
  activeModal,
12343
12574
  debugReadChat: {
@@ -12348,7 +12579,7 @@ async function handleReadChat(h, args) {
12348
12579
  returnedStatus: String(returnedStatus || ""),
12349
12580
  shouldPreferAdapterMessages: false,
12350
12581
  parsedMsgCount: parsedRecord.messages.length,
12351
- returnedMsgCount: parsedRecord.messages.length
12582
+ returnedMsgCount: returnedMessages.length
12352
12583
  },
12353
12584
  ...title ? { title } : {},
12354
12585
  ...providerSessionId ? { providerSessionId } : {},
@@ -13093,9 +13324,17 @@ async function handleResolveAction(h, args) {
13093
13324
  const targetState = targetInstance?.getState?.();
13094
13325
  const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons) && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? targetState.activeChat.activeModal : null;
13095
13326
  const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons) && status.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? status.activeModal : null;
13096
- const effectiveModal = statusModal || surfacedModal;
13097
- const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
13098
- LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
13327
+ const parsedStatus = !statusModal && !surfacedModal && typeof adapter.getScriptParsedStatus === "function" ? (() => {
13328
+ try {
13329
+ return parseMaybeJson(adapter.getScriptParsedStatus());
13330
+ } catch {
13331
+ return null;
13332
+ }
13333
+ })() : null;
13334
+ const parsedModal = parsedStatus?.status === "waiting_approval" && parsedStatus?.activeModal && Array.isArray(parsedStatus.activeModal.buttons) && parsedStatus.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? parsedStatus.activeModal : null;
13335
+ const effectiveModal = statusModal || surfacedModal || parsedModal;
13336
+ const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" || parsedStatus?.status === "waiting_approval" ? "waiting_approval" : status?.status;
13337
+ LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} parsedModal=${parsedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
13099
13338
  if (!effectiveModal) {
13100
13339
  return { success: false, error: "Not in approval state" };
13101
13340
  }
@@ -13221,7 +13460,7 @@ async function handleResolveAction(h, args) {
13221
13460
 
13222
13461
  // src/commands/cdp-commands.ts
13223
13462
  var fs5 = __toESM(require("fs"));
13224
- var path12 = __toESM(require("path"));
13463
+ var path13 = __toESM(require("path"));
13225
13464
  var os7 = __toESM(require("os"));
13226
13465
  var KEY_TO_VK = {
13227
13466
  Backspace: 8,
@@ -13478,25 +13717,25 @@ function resolveSafePath(requestedPath) {
13478
13717
  const inputPath = rawPath || ".";
13479
13718
  const home = os7.homedir();
13480
13719
  if (inputPath.startsWith("~")) {
13481
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13720
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13482
13721
  }
13483
13722
  if (process.platform === "win32") {
13484
13723
  const normalized = normalizeWindowsRequestedPath(inputPath);
13485
- if (path12.win32.isAbsolute(normalized)) {
13486
- return path12.win32.normalize(normalized);
13724
+ if (path13.win32.isAbsolute(normalized)) {
13725
+ return path13.win32.normalize(normalized);
13487
13726
  }
13488
- return path12.win32.resolve(normalized);
13727
+ return path13.win32.resolve(normalized);
13489
13728
  }
13490
- if (path12.isAbsolute(inputPath)) {
13491
- return path12.normalize(inputPath);
13729
+ if (path13.isAbsolute(inputPath)) {
13730
+ return path13.normalize(inputPath);
13492
13731
  }
13493
- return path12.resolve(inputPath);
13732
+ return path13.resolve(inputPath);
13494
13733
  }
13495
13734
  function listDirectoryEntriesSafe(dirPath) {
13496
13735
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13497
13736
  const files = [];
13498
13737
  for (const entry of entries) {
13499
- const entryPath = path12.join(dirPath, entry.name);
13738
+ const entryPath = path13.join(dirPath, entry.name);
13500
13739
  try {
13501
13740
  if (entry.isDirectory()) {
13502
13741
  files.push({ name: entry.name, type: "directory" });
@@ -13550,7 +13789,7 @@ async function handleFileRead(h, args) {
13550
13789
  async function handleFileWrite(h, args) {
13551
13790
  try {
13552
13791
  const filePath = resolveSafePath(args?.path);
13553
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
13792
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13554
13793
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13555
13794
  return { success: true, path: filePath };
13556
13795
  } catch (e) {
@@ -14334,9 +14573,11 @@ var DaemonCommandHandler = class {
14334
14573
  }
14335
14574
  const sessionLookupFailed = !!targetSessionId && !session;
14336
14575
  const managerKey = this.extractIdeType(args, sessionLookupFailed);
14337
- let providerType;
14576
+ let providerType = args?.agentType || args?.providerType;
14338
14577
  if (!sessionLookupFailed) {
14339
- providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
14578
+ providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
14579
+ } else if (!providerType) {
14580
+ providerType = this.inferProviderType(managerKey);
14340
14581
  }
14341
14582
  return { session, managerKey, providerType, sessionLookupFailed };
14342
14583
  }
@@ -14416,7 +14657,8 @@ var DaemonCommandHandler = class {
14416
14657
  "pty_resize",
14417
14658
  "invoke_provider_script"
14418
14659
  ]);
14419
- if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
14660
+ 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);
14661
+ if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
14420
14662
  const result2 = {
14421
14663
  success: false,
14422
14664
  error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
@@ -14669,7 +14911,7 @@ var DaemonCommandHandler = class {
14669
14911
 
14670
14912
  // src/commands/cli-manager.ts
14671
14913
  var os13 = __toESM(require("os"));
14672
- var path16 = __toESM(require("path"));
14914
+ var path17 = __toESM(require("path"));
14673
14915
  var crypto4 = __toESM(require("crypto"));
14674
14916
  var import_fs6 = require("fs");
14675
14917
  var import_child_process6 = require("child_process");
@@ -14679,7 +14921,7 @@ init_config();
14679
14921
 
14680
14922
  // src/providers/cli-provider-instance.ts
14681
14923
  var os12 = __toESM(require("os"));
14682
- var path15 = __toESM(require("path"));
14924
+ var path16 = __toESM(require("path"));
14683
14925
  var crypto3 = __toESM(require("crypto"));
14684
14926
  var fs6 = __toESM(require("fs"));
14685
14927
  var import_node_module = require("module");
@@ -14738,7 +14980,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14738
14980
  var CachedDatabaseSync = null;
14739
14981
  function getDatabaseSync() {
14740
14982
  if (CachedDatabaseSync) return CachedDatabaseSync;
14741
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14983
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14742
14984
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14743
14985
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14744
14986
  if (!CachedDatabaseSync) {
@@ -14791,7 +15033,7 @@ var CliProviderInstance = class {
14791
15033
  this.providerSessionId = options?.providerSessionId;
14792
15034
  this.launchMode = options?.launchMode || "new";
14793
15035
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14794
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
15036
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14795
15037
  this.monitor = new StatusMonitor();
14796
15038
  this.historyWriter = new ChatHistoryWriter();
14797
15039
  }
@@ -15268,7 +15510,19 @@ var CliProviderInstance = class {
15268
15510
  }
15269
15511
  }
15270
15512
  pushEvent(event) {
15271
- this.events.push(event);
15513
+ const enrichedEvent = {
15514
+ ...event,
15515
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
15516
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
15517
+ providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
15518
+ workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
15519
+ providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
15520
+ };
15521
+ if (this.context?.emitProviderEvent) {
15522
+ this.context.emitProviderEvent(enrichedEvent);
15523
+ return;
15524
+ }
15525
+ this.events.push(enrichedEvent);
15272
15526
  }
15273
15527
  flushEvents() {
15274
15528
  const events = [...this.events];
@@ -15475,12 +15729,31 @@ ${effect.notification.body || ""}`.trim();
15475
15729
  );
15476
15730
  }
15477
15731
  }
15732
+ mergeRuntimeChatMessages(parsedMessages) {
15733
+ return this.mergeConversationMessages(parsedMessages);
15734
+ }
15478
15735
  mergeConversationMessages(parsedMessages) {
15479
15736
  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;
15737
+ const parsedEntries = parsedMessages.map((message, index) => ({
15738
+ message,
15739
+ index,
15740
+ source: "parsed"
15741
+ }));
15742
+ const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
15743
+ message: entry.message,
15744
+ index: parsedMessages.length + index,
15745
+ source: "runtime"
15746
+ }));
15747
+ const getTime = (message) => {
15748
+ const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
15749
+ return Number.isFinite(value) && value > 0 ? value : 0;
15750
+ };
15751
+ return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
15752
+ const aTime = getTime(a.message);
15753
+ const bTime = getTime(b.message);
15754
+ if (aTime && bTime && aTime !== bTime) return aTime - bTime;
15755
+ if (aTime && !bTime && a.source === "runtime" && b.source === "parsed") return -1;
15756
+ if (!aTime && bTime && a.source === "parsed" && b.source === "runtime") return 1;
15484
15757
  return a.index - b.index;
15485
15758
  }).map((entry) => entry.message));
15486
15759
  }
@@ -16804,11 +17077,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16804
17077
  // src/commands/cli-manager.ts
16805
17078
  function isExplicitCommand(command) {
16806
17079
  const trimmed = command.trim();
16807
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17080
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16808
17081
  }
16809
17082
  function expandExecutable(command) {
16810
17083
  const trimmed = command.trim();
16811
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17084
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16812
17085
  }
16813
17086
  function commandExists(command) {
16814
17087
  const trimmed = command.trim();
@@ -16832,6 +17105,35 @@ function colorize(color, text) {
16832
17105
  const fn = chalkApi?.[color];
16833
17106
  return typeof fn === "function" ? fn(text) : text;
16834
17107
  }
17108
+ var COORDINATOR_DELEGATED_ENV_UNSETS = {
17109
+ ADHDEV_INLINE_MESH: "",
17110
+ ADHDEV_MCP_TRANSPORT: "",
17111
+ ADHDEV_MESH_ID: "",
17112
+ HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
17113
+ };
17114
+ function hasCliArg(args, flag) {
17115
+ return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
17116
+ }
17117
+ function ensureEmptyDelegatedMcpConfig(workspace) {
17118
+ const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
17119
+ (0, import_fs6.mkdirSync)(baseDir, { recursive: true });
17120
+ const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
17121
+ const filePath = path17.join(baseDir, `${workspaceHash}.json`);
17122
+ (0, import_fs6.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
17123
+ return filePath;
17124
+ }
17125
+ function buildCoordinatorDelegatedCliLaunchOptions(input) {
17126
+ const cliType = String(input.cliType || "").trim();
17127
+ const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
17128
+ const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
17129
+ if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
17130
+ cliArgs.unshift("--ignore-user-config");
17131
+ }
17132
+ if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
17133
+ cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
17134
+ }
17135
+ return { cliArgs, env };
17136
+ }
16835
17137
  function isUuid(value) {
16836
17138
  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
17139
  }
@@ -17002,7 +17304,7 @@ var DaemonCliManager = class {
17002
17304
  attachExisting
17003
17305
  }) || void 0;
17004
17306
  }
17005
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17307
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
17006
17308
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17007
17309
  const provider = this.providerLoader.getMeta(normalizedType);
17008
17310
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -17016,7 +17318,7 @@ var DaemonCliManager = class {
17016
17318
  providerSessionId,
17017
17319
  attachExisting
17018
17320
  );
17019
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17321
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
17020
17322
  }
17021
17323
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
17022
17324
  }
@@ -17089,7 +17391,7 @@ var DaemonCliManager = class {
17089
17391
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
17090
17392
  const trimmed = (workingDir || "").trim();
17091
17393
  if (!trimmed) throw new Error("working directory required");
17092
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17394
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
17093
17395
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17094
17396
  const rawProvider = this.providerLoader.getByAlias(cliType);
17095
17397
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17219,6 +17521,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17219
17521
  {
17220
17522
  providerSessionId: sessionBinding.providerSessionId,
17221
17523
  launchMode: sessionBinding.launchMode,
17524
+ extraEnv: options?.extraEnv,
17222
17525
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17223
17526
  this.persistRecentActivity({
17224
17527
  kind: "cli",
@@ -17239,7 +17542,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17239
17542
  resolvedCliArgs,
17240
17543
  key,
17241
17544
  sessionBinding.providerSessionId,
17242
- false
17545
+ false,
17546
+ options?.extraEnv
17243
17547
  );
17244
17548
  try {
17245
17549
  await adapter.spawn();
@@ -17463,12 +17767,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
17463
17767
  const dir = resolved.path;
17464
17768
  const launchSource = resolved.source;
17465
17769
  if (!cliType) throw new Error("cliType required");
17770
+ const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
17771
+ const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
17772
+ cliType,
17773
+ workspace: dir,
17774
+ cliArgs: args?.cliArgs,
17775
+ env: args?.env
17776
+ }) : null;
17466
17777
  const started = await this.startSession(
17467
17778
  cliType,
17468
17779
  dir,
17469
- args?.cliArgs,
17780
+ delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
17470
17781
  args?.initialModel,
17471
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
17782
+ {
17783
+ resumeSessionId: args?.resumeSessionId,
17784
+ settingsOverride,
17785
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
17786
+ }
17472
17787
  );
17473
17788
  return {
17474
17789
  success: true,
@@ -17590,11 +17905,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17590
17905
  var import_child_process7 = require("child_process");
17591
17906
  var net = __toESM(require("net"));
17592
17907
  var os15 = __toESM(require("os"));
17593
- var path18 = __toESM(require("path"));
17908
+ var path19 = __toESM(require("path"));
17594
17909
 
17595
17910
  // src/providers/provider-loader.ts
17596
17911
  var fs7 = __toESM(require("fs"));
17597
- var path17 = __toESM(require("path"));
17912
+ var path18 = __toESM(require("path"));
17598
17913
  var os14 = __toESM(require("os"));
17599
17914
  var chokidar = __toESM(require("chokidar"));
17600
17915
  init_logger();
@@ -17918,7 +18233,7 @@ var ProviderLoader = class _ProviderLoader {
17918
18233
  try {
17919
18234
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17920
18235
  return ["ide", "extension", "cli", "acp"].some(
17921
- (category) => fs7.existsSync(path17.join(candidate, category))
18236
+ (category) => fs7.existsSync(path18.join(candidate, category))
17922
18237
  );
17923
18238
  } catch {
17924
18239
  return false;
@@ -17926,20 +18241,20 @@ var ProviderLoader = class _ProviderLoader {
17926
18241
  }
17927
18242
  static hasProviderRootMarker(candidate) {
17928
18243
  try {
17929
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18244
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17930
18245
  } catch {
17931
18246
  return false;
17932
18247
  }
17933
18248
  }
17934
18249
  detectDefaultUserDir() {
17935
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
18250
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17936
18251
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17937
18252
  const visited = /* @__PURE__ */ new Set();
17938
18253
  for (const start of this.probeStarts) {
17939
- let current = path17.resolve(start);
18254
+ let current = path18.resolve(start);
17940
18255
  while (!visited.has(current)) {
17941
18256
  visited.add(current);
17942
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18257
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17943
18258
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17944
18259
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17945
18260
  if (envOptIn || hasMarker) {
@@ -17961,7 +18276,7 @@ var ProviderLoader = class _ProviderLoader {
17961
18276
  return { path: siblingCandidate, source };
17962
18277
  }
17963
18278
  }
17964
- const parent = path17.dirname(current);
18279
+ const parent = path18.dirname(current);
17965
18280
  if (parent === current) break;
17966
18281
  current = parent;
17967
18282
  }
@@ -17971,11 +18286,11 @@ var ProviderLoader = class _ProviderLoader {
17971
18286
  constructor(options) {
17972
18287
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17973
18288
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17974
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
18289
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17975
18290
  const detected = this.detectDefaultUserDir();
17976
18291
  this.userDir = detected.path;
17977
18292
  this.userDirSource = detected.source;
17978
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18293
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17979
18294
  this.disableUpstream = false;
17980
18295
  this.applySourceConfig({
17981
18296
  userDir: options?.userDir,
@@ -18034,7 +18349,7 @@ var ProviderLoader = class _ProviderLoader {
18034
18349
  this.userDir = detected.path;
18035
18350
  this.userDirSource = detected.source;
18036
18351
  }
18037
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18352
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
18038
18353
  this.disableUpstream = this.sourceMode === "no-upstream";
18039
18354
  if (this.explicitProviderDir) {
18040
18355
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -18048,7 +18363,7 @@ var ProviderLoader = class _ProviderLoader {
18048
18363
  * Canonical provider directory shape for a given root.
18049
18364
  */
18050
18365
  getProviderDir(root, category, type) {
18051
- return path17.join(root, category, type);
18366
+ return path18.join(root, category, type);
18052
18367
  }
18053
18368
  /**
18054
18369
  * Canonical user override directory for a provider.
@@ -18075,7 +18390,7 @@ var ProviderLoader = class _ProviderLoader {
18075
18390
  resolveProviderFile(type, ...segments) {
18076
18391
  const dir = this.findProviderDirInternal(type);
18077
18392
  if (!dir) return null;
18078
- return path17.join(dir, ...segments);
18393
+ return path18.join(dir, ...segments);
18079
18394
  }
18080
18395
  /**
18081
18396
  * Load all providers (3-tier priority)
@@ -18114,7 +18429,7 @@ var ProviderLoader = class _ProviderLoader {
18114
18429
  if (!fs7.existsSync(this.upstreamDir)) return false;
18115
18430
  try {
18116
18431
  return fs7.readdirSync(this.upstreamDir).some(
18117
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18432
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
18118
18433
  );
18119
18434
  } catch {
18120
18435
  return false;
@@ -18611,8 +18926,8 @@ var ProviderLoader = class _ProviderLoader {
18611
18926
  resolved._resolvedScriptDir = entry.scriptDir;
18612
18927
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18613
18928
  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;
18929
+ const fullDir = path18.join(providerDir, entry.scriptDir);
18930
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18616
18931
  }
18617
18932
  matched = true;
18618
18933
  }
@@ -18627,8 +18942,8 @@ var ProviderLoader = class _ProviderLoader {
18627
18942
  resolved._resolvedScriptDir = base.defaultScriptDir;
18628
18943
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18629
18944
  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;
18945
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18946
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18632
18947
  }
18633
18948
  }
18634
18949
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18645,8 +18960,8 @@ var ProviderLoader = class _ProviderLoader {
18645
18960
  resolved._resolvedScriptDir = dirOverride;
18646
18961
  resolved._resolvedScriptsSource = `versions:${range}`;
18647
18962
  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;
18963
+ const fullDir = path18.join(providerDir, dirOverride);
18964
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18650
18965
  }
18651
18966
  }
18652
18967
  } else if (override.scripts) {
@@ -18662,8 +18977,8 @@ var ProviderLoader = class _ProviderLoader {
18662
18977
  resolved._resolvedScriptDir = base.defaultScriptDir;
18663
18978
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18664
18979
  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;
18980
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18981
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18667
18982
  }
18668
18983
  }
18669
18984
  }
@@ -18695,14 +19010,14 @@ var ProviderLoader = class _ProviderLoader {
18695
19010
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18696
19011
  return null;
18697
19012
  }
18698
- const dir = path17.join(providerDir, scriptDir);
19013
+ const dir = path18.join(providerDir, scriptDir);
18699
19014
  if (!fs7.existsSync(dir)) {
18700
19015
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18701
19016
  return null;
18702
19017
  }
18703
19018
  const cached = this.scriptsCache.get(dir);
18704
19019
  if (cached) return cached;
18705
- const scriptsJs = path17.join(dir, "scripts.js");
19020
+ const scriptsJs = path18.join(dir, "scripts.js");
18706
19021
  if (fs7.existsSync(scriptsJs)) {
18707
19022
  try {
18708
19023
  delete require.cache[require.resolve(scriptsJs)];
@@ -18744,7 +19059,7 @@ var ProviderLoader = class _ProviderLoader {
18744
19059
  return;
18745
19060
  }
18746
19061
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18747
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
19062
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18748
19063
  this.reload();
18749
19064
  }
18750
19065
  };
@@ -18799,7 +19114,7 @@ var ProviderLoader = class _ProviderLoader {
18799
19114
  }
18800
19115
  const https = require("https");
18801
19116
  const { execSync: execSync7 } = require("child_process");
18802
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
19117
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18803
19118
  let prevEtag = "";
18804
19119
  let prevTimestamp = 0;
18805
19120
  try {
@@ -18859,17 +19174,17 @@ var ProviderLoader = class _ProviderLoader {
18859
19174
  return { updated: false };
18860
19175
  }
18861
19176
  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()}`);
19177
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19178
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18864
19179
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18865
19180
  fs7.mkdirSync(tmpExtract, { recursive: true });
18866
19181
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18867
19182
  const extracted = fs7.readdirSync(tmpExtract);
18868
19183
  const rootDir = extracted.find(
18869
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19184
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18870
19185
  );
18871
19186
  if (!rootDir) throw new Error("Unexpected tarball structure");
18872
- const sourceDir = path17.join(tmpExtract, rootDir);
19187
+ const sourceDir = path18.join(tmpExtract, rootDir);
18873
19188
  const backupDir = this.upstreamDir + ".bak";
18874
19189
  if (fs7.existsSync(this.upstreamDir)) {
18875
19190
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18944,8 +19259,8 @@ var ProviderLoader = class _ProviderLoader {
18944
19259
  copyDirRecursive(src, dest) {
18945
19260
  fs7.mkdirSync(dest, { recursive: true });
18946
19261
  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);
19262
+ const srcPath = path18.join(src, entry.name);
19263
+ const destPath = path18.join(dest, entry.name);
18949
19264
  if (entry.isDirectory()) {
18950
19265
  this.copyDirRecursive(srcPath, destPath);
18951
19266
  } else {
@@ -18956,7 +19271,7 @@ var ProviderLoader = class _ProviderLoader {
18956
19271
  /** .meta.json save */
18957
19272
  writeMeta(metaPath, etag, timestamp) {
18958
19273
  try {
18959
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
19274
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18960
19275
  fs7.writeFileSync(metaPath, JSON.stringify({
18961
19276
  etag,
18962
19277
  timestamp,
@@ -18973,7 +19288,7 @@ var ProviderLoader = class _ProviderLoader {
18973
19288
  const scan = (d) => {
18974
19289
  try {
18975
19290
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18976
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
19291
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18977
19292
  else if (entry.name === "provider.json") count++;
18978
19293
  }
18979
19294
  } catch {
@@ -19201,17 +19516,17 @@ var ProviderLoader = class _ProviderLoader {
19201
19516
  for (const root of searchRoots) {
19202
19517
  if (!fs7.existsSync(root)) continue;
19203
19518
  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);
19519
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19520
+ const catDir = path18.join(root, cat);
19206
19521
  if (fs7.existsSync(catDir)) {
19207
19522
  try {
19208
19523
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19209
19524
  if (!entry.isDirectory()) continue;
19210
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19525
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19211
19526
  if (fs7.existsSync(jsonPath)) {
19212
19527
  try {
19213
19528
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19214
- if (data.type === type) return path17.join(catDir, entry.name);
19529
+ if (data.type === type) return path18.join(catDir, entry.name);
19215
19530
  } catch {
19216
19531
  }
19217
19532
  }
@@ -19228,7 +19543,7 @@ var ProviderLoader = class _ProviderLoader {
19228
19543
  * (template substitution is NOT applied here — scripts.js handles that)
19229
19544
  */
19230
19545
  buildScriptWrappersFromDir(dir) {
19231
- const scriptsJs = path17.join(dir, "scripts.js");
19546
+ const scriptsJs = path18.join(dir, "scripts.js");
19232
19547
  if (fs7.existsSync(scriptsJs)) {
19233
19548
  try {
19234
19549
  delete require.cache[require.resolve(scriptsJs)];
@@ -19242,7 +19557,7 @@ var ProviderLoader = class _ProviderLoader {
19242
19557
  for (const file of fs7.readdirSync(dir)) {
19243
19558
  if (!file.endsWith(".js")) continue;
19244
19559
  const scriptName = toCamel(file.replace(".js", ""));
19245
- const filePath = path17.join(dir, file);
19560
+ const filePath = path18.join(dir, file);
19246
19561
  result[scriptName] = (...args) => {
19247
19562
  try {
19248
19563
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19302,7 +19617,7 @@ var ProviderLoader = class _ProviderLoader {
19302
19617
  }
19303
19618
  const hasJson = entries.some((e) => e.name === "provider.json");
19304
19619
  if (hasJson) {
19305
- const jsonPath = path17.join(d, "provider.json");
19620
+ const jsonPath = path18.join(d, "provider.json");
19306
19621
  try {
19307
19622
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19308
19623
  const mod = JSON.parse(raw);
@@ -19323,7 +19638,7 @@ var ProviderLoader = class _ProviderLoader {
19323
19638
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19324
19639
  } else {
19325
19640
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19326
- const scriptsPath = path17.join(d, "scripts.js");
19641
+ const scriptsPath = path18.join(d, "scripts.js");
19327
19642
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19328
19643
  try {
19329
19644
  delete require.cache[require.resolve(scriptsPath)];
@@ -19349,7 +19664,7 @@ var ProviderLoader = class _ProviderLoader {
19349
19664
  if (!entry.isDirectory()) continue;
19350
19665
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19351
19666
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19352
- scan(path17.join(d, entry.name));
19667
+ scan(path18.join(d, entry.name));
19353
19668
  }
19354
19669
  }
19355
19670
  };
@@ -19674,8 +19989,8 @@ function detectCurrentWorkspace(ideId) {
19674
19989
  const appNameMap = getMacAppIdentifiers();
19675
19990
  const appName = appNameMap[ideId];
19676
19991
  if (appName) {
19677
- const storagePath = path18.join(
19678
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
19992
+ const storagePath = path19.join(
19993
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19679
19994
  appName,
19680
19995
  "storage.json"
19681
19996
  );
@@ -19864,9 +20179,9 @@ init_logger();
19864
20179
 
19865
20180
  // src/logging/command-log.ts
19866
20181
  var fs8 = __toESM(require("fs"));
19867
- var path19 = __toESM(require("path"));
20182
+ var path20 = __toESM(require("path"));
19868
20183
  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");
20184
+ 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
20185
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19871
20186
  var MAX_DAYS = 7;
19872
20187
  try {
@@ -19904,13 +20219,13 @@ function getDateStr2() {
19904
20219
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19905
20220
  }
19906
20221
  var currentDate2 = getDateStr2();
19907
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20222
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19908
20223
  var writeCount2 = 0;
19909
20224
  function checkRotation() {
19910
20225
  const today = getDateStr2();
19911
20226
  if (today !== currentDate2) {
19912
20227
  currentDate2 = today;
19913
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20228
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19914
20229
  cleanOldFiles();
19915
20230
  }
19916
20231
  }
@@ -19924,7 +20239,7 @@ function cleanOldFiles() {
19924
20239
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19925
20240
  if (dateMatch && dateMatch[1] < cutoffStr) {
19926
20241
  try {
19927
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
20242
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19928
20243
  } catch {
19929
20244
  }
19930
20245
  }
@@ -20007,14 +20322,66 @@ function getRecentCommands(count = 50) {
20007
20322
  cleanOldFiles();
20008
20323
 
20009
20324
  // src/commands/router.ts
20325
+ var yaml = __toESM(require("js-yaml"));
20010
20326
  init_logger();
20011
20327
 
20012
20328
  // src/commands/mesh-coordinator.ts
20013
- var import_node_fs2 = require("fs");
20329
+ var import_node_child_process3 = require("child_process");
20330
+ var import_node_fs3 = require("fs");
20014
20331
  var import_node_module2 = require("module");
20332
+ var os17 = __toESM(require("os"));
20015
20333
  var import_node_path = require("path");
20016
20334
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
20017
20335
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20336
+ var HERMES_CLI_TYPE = "hermes-cli";
20337
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20338
+ function isHermesProvider(provider, cliType) {
20339
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20340
+ return type === HERMES_CLI_TYPE;
20341
+ }
20342
+ function resolveHermesMeshCoordinatorSetup(options) {
20343
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20344
+ meshId: options.meshId,
20345
+ nodeExecutable: options.nodeExecutable,
20346
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20347
+ });
20348
+ if (!mcpServer) {
20349
+ return {
20350
+ kind: "unsupported",
20351
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20352
+ };
20353
+ }
20354
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20355
+ if (!configPath.trim()) {
20356
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20357
+ }
20358
+ return {
20359
+ kind: "auto_import",
20360
+ serverName: DEFAULT_SERVER_NAME,
20361
+ configPath,
20362
+ configFormat: "hermes_config_yaml",
20363
+ mcpServer
20364
+ };
20365
+ }
20366
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20367
+ return {
20368
+ kind: "manual",
20369
+ serverName: DEFAULT_SERVER_NAME,
20370
+ configFormat: "hermes_config_yaml",
20371
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20372
+ requiresRestart: true,
20373
+ 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.",
20374
+ template: renderMeshCoordinatorTemplate(
20375
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20376
+ {
20377
+ meshId,
20378
+ workspace,
20379
+ serverName: DEFAULT_SERVER_NAME,
20380
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20381
+ }
20382
+ )
20383
+ };
20384
+ }
20018
20385
  function resolveMeshCoordinatorSetup(options) {
20019
20386
  const { provider, meshId, workspace } = options;
20020
20387
  const config = provider?.meshCoordinator;
@@ -20024,6 +20391,9 @@ function resolveMeshCoordinatorSetup(options) {
20024
20391
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
20025
20392
  };
20026
20393
  }
20394
+ if (isHermesProvider(provider, options.cliType)) {
20395
+ return resolveHermesMeshCoordinatorSetup(options);
20396
+ }
20027
20397
  const mcpConfig = config.mcpConfig;
20028
20398
  if (!mcpConfig || mcpConfig.mode === "none") {
20029
20399
  return {
@@ -20033,8 +20403,8 @@ function resolveMeshCoordinatorSetup(options) {
20033
20403
  }
20034
20404
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
20035
20405
  if (mcpConfig.mode === "auto_import") {
20036
- const path26 = mcpConfig.path?.trim();
20037
- if (!path26) {
20406
+ const path27 = mcpConfig.path?.trim();
20407
+ if (!path27) {
20038
20408
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
20039
20409
  }
20040
20410
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -20045,13 +20415,13 @@ function resolveMeshCoordinatorSetup(options) {
20045
20415
  if (!mcpServer) {
20046
20416
  return {
20047
20417
  kind: "unsupported",
20048
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20418
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20049
20419
  };
20050
20420
  }
20051
20421
  return {
20052
20422
  kind: "auto_import",
20053
20423
  serverName,
20054
- configPath: (0, import_node_path.join)(workspace, path26),
20424
+ configPath: resolveMcpConfigPath(path27, workspace),
20055
20425
  configFormat: mcpConfig.format,
20056
20426
  mcpServer
20057
20427
  };
@@ -20085,14 +20455,85 @@ function resolveMeshCoordinatorSetup(options) {
20085
20455
  function renderMeshCoordinatorTemplate(template, values) {
20086
20456
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
20087
20457
  }
20458
+ function resolveMcpConfigPath(configPath, workspace) {
20459
+ const trimmed = configPath.trim();
20460
+ if (trimmed === "~") return os17.homedir();
20461
+ if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
20462
+ if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
20463
+ return (0, import_node_path.join)(workspace, trimmed);
20464
+ }
20088
20465
  function resolveAdhdevMcpServerLaunch(options) {
20089
20466
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
20090
20467
  if (!entryPath) return null;
20468
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20469
+ if (!nodeExecutable) return null;
20091
20470
  return {
20092
- command: options.nodeExecutable?.trim() || process.execPath,
20093
- args: [entryPath, "--repo-mesh", options.meshId]
20471
+ command: nodeExecutable,
20472
+ args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
20094
20473
  };
20095
20474
  }
20475
+ function resolveMcpNodeExecutable(explicitExecutable) {
20476
+ const explicit = explicitExecutable?.trim();
20477
+ if (explicit) return explicit;
20478
+ const candidates = [];
20479
+ const addCandidate = (candidate) => {
20480
+ const trimmed = candidate?.trim();
20481
+ if (!trimmed) return;
20482
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20483
+ if (!candidates.includes(normalized)) candidates.push(normalized);
20484
+ };
20485
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20486
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20487
+ addCandidate(process.env.npm_node_execpath);
20488
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20489
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20490
+ addCandidate("/opt/homebrew/bin/node");
20491
+ addCandidate("/usr/local/bin/node");
20492
+ addCandidate("/usr/bin/node");
20493
+ addCandidate(process.execPath);
20494
+ for (const candidate of candidates) {
20495
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20496
+ }
20497
+ return null;
20498
+ }
20499
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20500
+ for (const entry of (pathValue || "").split(":")) {
20501
+ const dir = entry.trim();
20502
+ if (!dir) continue;
20503
+ addCandidate((0, import_node_path.join)(dir, "node"));
20504
+ }
20505
+ }
20506
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20507
+ const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
20508
+ try {
20509
+ const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20510
+ for (const versionDir of versionDirs) {
20511
+ addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
20512
+ }
20513
+ } catch {
20514
+ }
20515
+ }
20516
+ function compareNodeVersionNamesDescending(a, b) {
20517
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20518
+ const left = parse(a);
20519
+ const right = parse(b);
20520
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20521
+ const diff = (right[i] || 0) - (left[i] || 0);
20522
+ if (diff !== 0) return diff;
20523
+ }
20524
+ return b.localeCompare(a);
20525
+ }
20526
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20527
+ try {
20528
+ (0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20529
+ stdio: "ignore",
20530
+ timeout: 3e3
20531
+ });
20532
+ return true;
20533
+ } catch {
20534
+ return false;
20535
+ }
20536
+ }
20096
20537
  function resolveAdhdevMcpEntryPath(explicitPath) {
20097
20538
  const explicit = explicitPath?.trim();
20098
20539
  if (explicit) return normalizeExistingPath(explicit) || explicit;
@@ -20128,15 +20569,109 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
20128
20569
  }
20129
20570
  function normalizeExistingPath(filePath) {
20130
20571
  try {
20131
- if (!(0, import_node_fs2.existsSync)(filePath)) return null;
20132
- return import_node_fs2.realpathSync.native(filePath);
20572
+ if (!(0, import_node_fs3.existsSync)(filePath)) return null;
20573
+ return import_node_fs3.realpathSync.native(filePath);
20133
20574
  } catch {
20134
20575
  return null;
20135
20576
  }
20136
20577
  }
20137
20578
 
20579
+ // src/mesh/mesh-events.ts
20580
+ init_mesh_config();
20581
+ init_logger();
20582
+ function readNonEmptyString(value) {
20583
+ return typeof value === "string" && value.trim() ? value.trim() : "";
20584
+ }
20585
+ function formatCompletionMetadata(event) {
20586
+ const parts = [
20587
+ readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
20588
+ readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
20589
+ readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
20590
+ ].filter(Boolean);
20591
+ return parts.length > 0 ? ` (${parts.join("; ")})` : "";
20592
+ }
20593
+ function buildMeshSystemMessage(args) {
20594
+ const metadata = formatCompletionMetadata(args.metadataEvent);
20595
+ if (args.event === "agent:generating_completed") {
20596
+ return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path; use mesh_read_chat once to review its final progress, but do not poll repeatedly.`;
20597
+ }
20598
+ if (args.event === "agent:waiting_approval") {
20599
+ return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
20600
+ }
20601
+ return "";
20602
+ }
20603
+ function injectMeshSystemMessage(components, args) {
20604
+ const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
20605
+ const instState = inst.getState();
20606
+ if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
20607
+ if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
20608
+ return true;
20609
+ });
20610
+ if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
20611
+ const messageText = buildMeshSystemMessage({
20612
+ event: args.event,
20613
+ nodeLabel: args.nodeLabel,
20614
+ metadataEvent: args.metadataEvent
20615
+ });
20616
+ if (!messageText) return { success: false, error: "unsupported mesh event" };
20617
+ for (const coord of coordinatorInstances) {
20618
+ const coordState = coord.getState();
20619
+ LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
20620
+ coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
20621
+ }
20622
+ return { success: true, forwarded: coordinatorInstances.length };
20623
+ }
20624
+ function handleMeshForwardEvent(components, payload) {
20625
+ const eventName = readNonEmptyString(payload.event);
20626
+ if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
20627
+ return { success: false, error: "unsupported mesh event" };
20628
+ }
20629
+ const meshId = readNonEmptyString(payload.meshId);
20630
+ if (!meshId) return { success: false, error: "meshId required" };
20631
+ const nodeId = readNonEmptyString(payload.nodeId);
20632
+ const workspace = readNonEmptyString(payload.workspace);
20633
+ const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
20634
+ return injectMeshSystemMessage(components, {
20635
+ meshId,
20636
+ nodeLabel,
20637
+ event: eventName,
20638
+ metadataEvent: {
20639
+ targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
20640
+ providerType: readNonEmptyString(payload.providerType),
20641
+ providerSessionId: readNonEmptyString(payload.providerSessionId)
20642
+ }
20643
+ });
20644
+ }
20645
+ function setupMeshEventForwarding(components) {
20646
+ components.instanceManager.onEvent((event) => {
20647
+ if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
20648
+ const instanceId = readNonEmptyString(event.instanceId);
20649
+ if (!instanceId) return;
20650
+ const sourceInstance = components.instanceManager.getInstance(instanceId);
20651
+ if (!sourceInstance || sourceInstance.category !== "cli") return;
20652
+ const state = sourceInstance.getState();
20653
+ const workspace = readNonEmptyString(state.workspace);
20654
+ if (!workspace) return;
20655
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
20656
+ const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
20657
+ const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
20658
+ const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
20659
+ if (!meshId) return;
20660
+ const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
20661
+ const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
20662
+ const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
20663
+ injectMeshSystemMessage(components, {
20664
+ meshId,
20665
+ sourceInstanceId: instanceId,
20666
+ nodeLabel,
20667
+ event: event.event,
20668
+ metadataEvent: event
20669
+ });
20670
+ });
20671
+ }
20672
+
20138
20673
  // src/status/snapshot.ts
20139
- var os17 = __toESM(require("os"));
20674
+ var os18 = __toESM(require("os"));
20140
20675
  init_config();
20141
20676
  init_terminal_screen();
20142
20677
  init_logger();
@@ -20192,8 +20727,8 @@ function buildAvailableProviders(providerLoader) {
20192
20727
  }
20193
20728
  function buildMachineInfo(profile = "full") {
20194
20729
  const base = {
20195
- hostname: os17.hostname(),
20196
- platform: os17.platform()
20730
+ hostname: os18.hostname(),
20731
+ platform: os18.platform()
20197
20732
  };
20198
20733
  if (profile === "live") {
20199
20734
  return base;
@@ -20202,23 +20737,23 @@ function buildMachineInfo(profile = "full") {
20202
20737
  const memSnap2 = getHostMemorySnapshot();
20203
20738
  return {
20204
20739
  ...base,
20205
- arch: os17.arch(),
20206
- cpus: os17.cpus().length,
20740
+ arch: os18.arch(),
20741
+ cpus: os18.cpus().length,
20207
20742
  totalMem: memSnap2.totalMem,
20208
- release: os17.release()
20743
+ release: os18.release()
20209
20744
  };
20210
20745
  }
20211
20746
  const memSnap = getHostMemorySnapshot();
20212
20747
  return {
20213
20748
  ...base,
20214
- arch: os17.arch(),
20215
- cpus: os17.cpus().length,
20749
+ arch: os18.arch(),
20750
+ cpus: os18.cpus().length,
20216
20751
  totalMem: memSnap.totalMem,
20217
20752
  freeMem: memSnap.freeMem,
20218
20753
  availableMem: memSnap.availableMem,
20219
- loadavg: os17.loadavg(),
20220
- uptime: os17.uptime(),
20221
- release: os17.release()
20754
+ loadavg: os18.loadavg(),
20755
+ uptime: os18.uptime(),
20756
+ release: os18.release()
20222
20757
  };
20223
20758
  }
20224
20759
  function parseMessageTime(value) {
@@ -20452,14 +20987,14 @@ function buildStatusSnapshot(options) {
20452
20987
  var import_child_process8 = require("child_process");
20453
20988
  var import_child_process9 = require("child_process");
20454
20989
  var fs9 = __toESM(require("fs"));
20455
- var os18 = __toESM(require("os"));
20456
- var path20 = __toESM(require("path"));
20990
+ var os19 = __toESM(require("os"));
20991
+ var path21 = __toESM(require("path"));
20457
20992
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20458
20993
  function getUpgradeLogPath() {
20459
- const home = os18.homedir();
20460
- const dir = path20.join(home, ".adhdev");
20994
+ const home = os19.homedir();
20995
+ const dir = path21.join(home, ".adhdev");
20461
20996
  fs9.mkdirSync(dir, { recursive: true });
20462
- return path20.join(dir, "daemon-upgrade.log");
20997
+ return path21.join(dir, "daemon-upgrade.log");
20463
20998
  }
20464
20999
  function appendUpgradeLog(message) {
20465
21000
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20470,14 +21005,14 @@ function appendUpgradeLog(message) {
20470
21005
  }
20471
21006
  }
20472
21007
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20473
- const binDir = path20.dirname(nodeExecutable);
21008
+ const binDir = path21.dirname(nodeExecutable);
20474
21009
  if (platform10 === "win32") {
20475
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
21010
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20476
21011
  if (fs9.existsSync(npmCliPath)) {
20477
21012
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20478
21013
  }
20479
21014
  for (const candidate of ["npm.exe", "npm"]) {
20480
- const candidatePath = path20.join(binDir, candidate);
21015
+ const candidatePath = path21.join(binDir, candidate);
20481
21016
  if (fs9.existsSync(candidatePath)) {
20482
21017
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20483
21018
  }
@@ -20485,7 +21020,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20485
21020
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20486
21021
  }
20487
21022
  for (const candidate of ["npm"]) {
20488
- const candidatePath = path20.join(binDir, candidate);
21023
+ const candidatePath = path21.join(binDir, candidate);
20489
21024
  if (fs9.existsSync(candidatePath)) {
20490
21025
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20491
21026
  }
@@ -20502,13 +21037,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20502
21037
  let currentDir = resolvedPath;
20503
21038
  try {
20504
21039
  if (fs9.statSync(resolvedPath).isFile()) {
20505
- currentDir = path20.dirname(resolvedPath);
21040
+ currentDir = path21.dirname(resolvedPath);
20506
21041
  }
20507
21042
  } catch {
20508
- currentDir = path20.dirname(resolvedPath);
21043
+ currentDir = path21.dirname(resolvedPath);
20509
21044
  }
20510
21045
  while (true) {
20511
- const packageJsonPath = path20.join(currentDir, "package.json");
21046
+ const packageJsonPath = path21.join(currentDir, "package.json");
20512
21047
  try {
20513
21048
  if (fs9.existsSync(packageJsonPath)) {
20514
21049
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20519,7 +21054,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20519
21054
  }
20520
21055
  } catch {
20521
21056
  }
20522
- const parentDir = path20.dirname(currentDir);
21057
+ const parentDir = path21.dirname(currentDir);
20523
21058
  if (parentDir === currentDir) {
20524
21059
  return null;
20525
21060
  }
@@ -20527,13 +21062,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20527
21062
  }
20528
21063
  }
20529
21064
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20530
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20531
- if (path20.basename(nodeModulesDir) !== "node_modules") {
21065
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
21066
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20532
21067
  return null;
20533
21068
  }
20534
- const maybeLibDir = path20.dirname(nodeModulesDir);
20535
- if (path20.basename(maybeLibDir) === "lib") {
20536
- return path20.dirname(maybeLibDir);
21069
+ const maybeLibDir = path21.dirname(nodeModulesDir);
21070
+ if (path21.basename(maybeLibDir) === "lib") {
21071
+ return path21.dirname(maybeLibDir);
20537
21072
  }
20538
21073
  return maybeLibDir;
20539
21074
  }
@@ -20648,7 +21183,7 @@ async function waitForPidExit(pid, timeoutMs) {
20648
21183
  }
20649
21184
  }
20650
21185
  function stopSessionHostProcesses(appName) {
20651
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
21186
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20652
21187
  try {
20653
21188
  if (fs9.existsSync(pidFile)) {
20654
21189
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20665,7 +21200,7 @@ function stopSessionHostProcesses(appName) {
20665
21200
  }
20666
21201
  }
20667
21202
  function removeDaemonPidFile() {
20668
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
21203
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20669
21204
  try {
20670
21205
  fs9.unlinkSync(pidFile);
20671
21206
  } catch {
@@ -20676,7 +21211,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20676
21211
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20677
21212
  if (!npmRoot) return;
20678
21213
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20679
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
21214
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20680
21215
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20681
21216
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20682
21217
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20684,25 +21219,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20684
21219
  }
20685
21220
  if (pkgName.startsWith("@")) {
20686
21221
  const [scope, name] = pkgName.split("/");
20687
- const scopeDir = path20.join(npmRoot, scope);
21222
+ const scopeDir = path21.join(npmRoot, scope);
20688
21223
  if (!fs9.existsSync(scopeDir)) return;
20689
21224
  for (const entry of fs9.readdirSync(scopeDir)) {
20690
21225
  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)}`);
21226
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
21227
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20693
21228
  }
20694
21229
  } else {
20695
21230
  for (const entry of fs9.readdirSync(npmRoot)) {
20696
21231
  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)}`);
21232
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
21233
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20699
21234
  }
20700
21235
  }
20701
21236
  if (fs9.existsSync(binDir)) {
20702
21237
  for (const entry of fs9.readdirSync(binDir)) {
20703
21238
  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)}`);
21239
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
21240
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20706
21241
  }
20707
21242
  }
20708
21243
  }
@@ -20803,6 +21338,56 @@ function normalizeReleaseChannel(value) {
20803
21338
  function resolveUpgradeChannel(args) {
20804
21339
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20805
21340
  }
21341
+ function readProviderPriorityFromPolicy(policy) {
21342
+ const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
21343
+ const raw = record.providerPriority;
21344
+ if (!Array.isArray(raw)) return [];
21345
+ const seen = /* @__PURE__ */ new Set();
21346
+ return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
21347
+ if (seen.has(type)) return false;
21348
+ seen.add(type);
21349
+ return true;
21350
+ });
21351
+ }
21352
+ async function resolveProviderTypeFromPriority(args) {
21353
+ if (!args.providerPriority.length) {
21354
+ return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
21355
+ }
21356
+ const failed = [];
21357
+ for (const requestedType of args.providerPriority) {
21358
+ const normalizedType = args.providerLoader.resolveAlias(requestedType);
21359
+ if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
21360
+ failed.push(`${requestedType}: disabled`);
21361
+ continue;
21362
+ }
21363
+ const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
21364
+ args.providerLoader.setCliDetectionResults([{
21365
+ id: normalizedType,
21366
+ installed: !!detected,
21367
+ path: detected?.path
21368
+ }], false);
21369
+ args.onStatusChange?.();
21370
+ if (detected) return { providerType: normalizedType };
21371
+ failed.push(`${requestedType}: not detected`);
21372
+ }
21373
+ return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
21374
+ }
21375
+ function loadYamlModule() {
21376
+ return yaml;
21377
+ }
21378
+ function getMcpServersKey(format) {
21379
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
21380
+ }
21381
+ function parseMeshCoordinatorMcpConfig(text, format) {
21382
+ if (!text.trim()) return {};
21383
+ if (format === "claude_mcp_json") return JSON.parse(text);
21384
+ const parsed = loadYamlModule().load(text);
21385
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
21386
+ }
21387
+ function serializeMeshCoordinatorMcpConfig(config, format) {
21388
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
21389
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
21390
+ }
20806
21391
  var CHAT_COMMANDS = [
20807
21392
  "send_chat",
20808
21393
  "new_chat",
@@ -20901,6 +21486,154 @@ var DaemonCommandRouter = class {
20901
21486
  constructor(deps) {
20902
21487
  this.deps = deps;
20903
21488
  }
21489
+ getCachedInlineMesh(meshId, inlineMesh) {
21490
+ if (inlineMesh && typeof inlineMesh === "object") {
21491
+ this.inlineMeshCache.set(meshId, inlineMesh);
21492
+ return inlineMesh;
21493
+ }
21494
+ return this.inlineMeshCache.get(meshId);
21495
+ }
21496
+ async getMeshForCommand(meshId, inlineMesh) {
21497
+ try {
21498
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21499
+ const mesh = getMesh3(meshId);
21500
+ if (mesh) return { mesh, inline: false };
21501
+ } catch {
21502
+ }
21503
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21504
+ return cached ? { mesh: cached, inline: true } : null;
21505
+ }
21506
+ updateInlineMeshNode(meshId, mesh, node) {
21507
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21508
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21509
+ if (idx >= 0) mesh.nodes[idx] = node;
21510
+ else mesh.nodes.push(node);
21511
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21512
+ this.inlineMeshCache.set(meshId, mesh);
21513
+ }
21514
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21515
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21516
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21517
+ if (idx === -1) return false;
21518
+ mesh.nodes.splice(idx, 1);
21519
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21520
+ this.inlineMeshCache.set(meshId, mesh);
21521
+ return true;
21522
+ }
21523
+ normalizeMeshSessionCleanupMode(value) {
21524
+ return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
21525
+ }
21526
+ sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
21527
+ const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
21528
+ if (!sessionId) return false;
21529
+ if (sessionIds?.size) return sessionIds.has(sessionId);
21530
+ const workspace = typeof node?.workspace === "string" ? node.workspace : "";
21531
+ if (workspace && record?.workspace === workspace) return true;
21532
+ if (record?.meta?.meshNodeId === nodeId) return true;
21533
+ return false;
21534
+ }
21535
+ isCompletedHostedSession(record) {
21536
+ return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
21537
+ }
21538
+ async cleanupMeshSessions(args) {
21539
+ if (args.mode === "preserve") {
21540
+ return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
21541
+ }
21542
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
21543
+ const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
21544
+ const sessions = await this.deps.sessionHostControl.listSessions();
21545
+ const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
21546
+ const hasExplicitSessionIds = !!requestedSessionIds?.size;
21547
+ const stoppedSessionIds = [];
21548
+ const deletedSessionIds = [];
21549
+ const skippedSessionIds = [];
21550
+ const skippedLiveSessionIds = [];
21551
+ const deleteUnsupportedSessionIds = [];
21552
+ const recordsRemainSessionIds = [];
21553
+ const errors = [];
21554
+ const matchedBySurfaceKind = {
21555
+ live_runtime: 0,
21556
+ recovery_snapshot: 0,
21557
+ inactive_record: 0
21558
+ };
21559
+ for (const record of matched) {
21560
+ const surfaceKind = getSessionHostSurfaceKind(record);
21561
+ matchedBySurfaceKind[surfaceKind] += 1;
21562
+ }
21563
+ for (const record of matched) {
21564
+ const sessionId = String(record.sessionId);
21565
+ const completed = this.isCompletedHostedSession(record);
21566
+ const surfaceKind = getSessionHostSurfaceKind(record);
21567
+ const liveRuntime = surfaceKind === "live_runtime";
21568
+ if (!hasExplicitSessionIds && liveRuntime) {
21569
+ skippedSessionIds.push(sessionId);
21570
+ skippedLiveSessionIds.push(sessionId);
21571
+ continue;
21572
+ }
21573
+ try {
21574
+ if (args.mode === "stop") {
21575
+ if (!completed) {
21576
+ if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
21577
+ stoppedSessionIds.push(sessionId);
21578
+ } else {
21579
+ skippedSessionIds.push(sessionId);
21580
+ }
21581
+ continue;
21582
+ }
21583
+ if (args.mode === "delete_stopped") {
21584
+ if (completed) {
21585
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
21586
+ deletedSessionIds.push(sessionId);
21587
+ } else {
21588
+ skippedSessionIds.push(sessionId);
21589
+ }
21590
+ continue;
21591
+ }
21592
+ if (args.mode === "stop_and_delete") {
21593
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
21594
+ deletedSessionIds.push(sessionId);
21595
+ continue;
21596
+ }
21597
+ } catch (e) {
21598
+ const message = e?.message || String(e);
21599
+ if (message.includes("Unsupported session host request: delete_session") && (args.mode === "delete_stopped" || args.mode === "stop_and_delete")) {
21600
+ deleteUnsupportedSessionIds.push(sessionId);
21601
+ recordsRemainSessionIds.push(sessionId);
21602
+ if (args.mode === "stop_and_delete" && !completed) {
21603
+ try {
21604
+ await this.deps.sessionHostControl.stopSession(sessionId);
21605
+ stoppedSessionIds.push(sessionId);
21606
+ } catch (stopError) {
21607
+ errors.push({ sessionId, error: stopError?.message || String(stopError) });
21608
+ continue;
21609
+ }
21610
+ }
21611
+ skippedSessionIds.push(sessionId);
21612
+ continue;
21613
+ }
21614
+ errors.push({ sessionId, error: message });
21615
+ }
21616
+ }
21617
+ const deleteUnsupported = deleteUnsupportedSessionIds.length > 0;
21618
+ return {
21619
+ success: errors.length === 0,
21620
+ mode: args.mode,
21621
+ dryRun: args.dryRun === true,
21622
+ matchedCount: matched.length,
21623
+ matchedBySurfaceKind,
21624
+ stoppedSessionIds,
21625
+ deletedSessionIds,
21626
+ skippedSessionIds,
21627
+ skippedLiveSessionIds,
21628
+ ...deleteUnsupported ? {
21629
+ deleteUnsupported: true,
21630
+ effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
21631
+ deleteUnsupportedSessionIds,
21632
+ recordsRemainSessionIds
21633
+ } : {},
21634
+ ...errors.length ? { errors } : {}
21635
+ };
21636
+ }
20904
21637
  async traceSessionHostAction(action, args, run, summarizeResult) {
20905
21638
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20906
21639
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -21020,6 +21753,9 @@ var DaemonCommandRouter = class {
21020
21753
  async executeDaemonCommand(cmd, args) {
21021
21754
  switch (cmd) {
21022
21755
  // ─── CLI / ACP commands ───
21756
+ case "mesh_forward_event": {
21757
+ return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
21758
+ }
21023
21759
  case "launch_cli":
21024
21760
  case "stop_cli":
21025
21761
  case "set_cli_view_mode":
@@ -21564,7 +22300,26 @@ var DaemonCommandRouter = class {
21564
22300
  if (!name) return { success: false, error: "name required" };
21565
22301
  try {
21566
22302
  const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21567
- const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
22303
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
22304
+ return { success: true, mesh };
22305
+ } catch (e) {
22306
+ return { success: false, error: e.message };
22307
+ }
22308
+ }
22309
+ case "update_mesh": {
22310
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22311
+ if (!meshId) return { success: false, error: "meshId required" };
22312
+ try {
22313
+ const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22314
+ const patch = {};
22315
+ if (typeof args?.name === "string") patch.name = args.name;
22316
+ if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
22317
+ if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
22318
+ if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
22319
+ if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
22320
+ const mesh = updateMesh2(meshId, patch);
22321
+ if (!mesh) return { success: false, error: "Mesh not found" };
22322
+ this.inlineMeshCache.set(meshId, mesh);
21568
22323
  return { success: true, mesh };
21569
22324
  } catch (e) {
21570
22325
  return { success: false, error: e.message };
@@ -21588,21 +22343,164 @@ var DaemonCommandRouter = class {
21588
22343
  if (!workspace) return { success: false, error: "workspace required" };
21589
22344
  try {
21590
22345
  const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21591
- const node = addNode3(meshId, { workspace });
22346
+ const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
22347
+ const readOnly = args?.readOnly === true;
22348
+ const policy = {
22349
+ ...readOnly ? { readOnly: true } : {},
22350
+ ...providerPriority.length ? { providerPriority } : {}
22351
+ };
22352
+ const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
21592
22353
  if (!node) return { success: false, error: "Mesh not found" };
21593
22354
  return { success: true, node };
21594
22355
  } catch (e) {
21595
22356
  return { success: false, error: e.message };
21596
22357
  }
21597
22358
  }
22359
+ case "update_mesh_node": {
22360
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22361
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22362
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22363
+ try {
22364
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22365
+ const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
22366
+ if (Array.isArray(args?.providerPriority)) {
22367
+ const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
22368
+ delete policy.provider_priority;
22369
+ if (providerPriority.length) {
22370
+ policy.providerPriority = providerPriority;
22371
+ } else {
22372
+ delete policy.providerPriority;
22373
+ }
22374
+ }
22375
+ const node = updateNode2(meshId, nodeId, { policy });
22376
+ if (!node) return { success: false, error: "Mesh node not found" };
22377
+ return { success: true, node };
22378
+ } catch (e) {
22379
+ return { success: false, error: e.message };
22380
+ }
22381
+ }
22382
+ case "cleanup_mesh_sessions": {
22383
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22384
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22385
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22386
+ try {
22387
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22388
+ const mesh = meshRecord?.mesh;
22389
+ if (!mesh) return { success: false, error: "Mesh not found" };
22390
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22391
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
22392
+ const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
22393
+ const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
22394
+ const result = await this.cleanupMeshSessions({
22395
+ meshId,
22396
+ nodeId,
22397
+ node,
22398
+ mode,
22399
+ sessionIds,
22400
+ dryRun: args?.dryRun === true
22401
+ });
22402
+ return result;
22403
+ } catch (e) {
22404
+ return { success: false, error: e.message };
22405
+ }
22406
+ }
21598
22407
  case "remove_mesh_node": {
21599
22408
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21600
22409
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21601
22410
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21602
22411
  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 };
22412
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22413
+ const mesh = meshRecord?.mesh;
22414
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22415
+ const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
22416
+ args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
22417
+ );
22418
+ let sessionCleanup;
22419
+ if (node && sessionCleanupMode !== "preserve") {
22420
+ sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
22421
+ if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
22422
+ }
22423
+ if (node?.isLocalWorktree && node.workspace) {
22424
+ try {
22425
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
22426
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
22427
+ if (repoRoot) {
22428
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22429
+ await removeWorktree2(repoRoot, node.workspace);
22430
+ }
22431
+ } catch (e) {
22432
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
22433
+ }
22434
+ }
22435
+ let removed = false;
22436
+ if (meshRecord?.inline) {
22437
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
22438
+ } else {
22439
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22440
+ removed = removeNode3(meshId, nodeId);
22441
+ }
22442
+ return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
22443
+ } catch (e) {
22444
+ return { success: false, error: e.message };
22445
+ }
22446
+ }
22447
+ case "clone_mesh_node": {
22448
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22449
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
22450
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
22451
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
22452
+ if (!meshId) return { success: false, error: "meshId required" };
22453
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
22454
+ if (!branch) return { success: false, error: "branch required" };
22455
+ try {
22456
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22457
+ const mesh = meshRecord?.mesh;
22458
+ if (!mesh) return { success: false, error: "Mesh not found" };
22459
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
22460
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
22461
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
22462
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22463
+ const result = await createWorktree2({
22464
+ repoRoot,
22465
+ branch,
22466
+ baseBranch,
22467
+ meshName: mesh.name
22468
+ });
22469
+ let node;
22470
+ if (meshRecord.inline) {
22471
+ const { randomUUID: randomUUID8 } = await import("crypto");
22472
+ node = {
22473
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
22474
+ workspace: result.worktreePath,
22475
+ repoRoot: result.worktreePath,
22476
+ daemonId: sourceNode.daemonId,
22477
+ userOverrides: { ...sourceNode.userOverrides || {} },
22478
+ policy: { ...sourceNode.policy || {} },
22479
+ isLocalWorktree: true,
22480
+ worktreeBranch: result.branch,
22481
+ clonedFromNodeId: sourceNodeId
22482
+ };
22483
+ this.updateInlineMeshNode(meshId, mesh, node);
22484
+ } else {
22485
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22486
+ node = addNode3(meshId, {
22487
+ workspace: result.worktreePath,
22488
+ repoRoot: result.worktreePath,
22489
+ daemonId: sourceNode.daemonId,
22490
+ userOverrides: { ...sourceNode.userOverrides || {} },
22491
+ isLocalWorktree: true,
22492
+ worktreeBranch: result.branch,
22493
+ clonedFromNodeId: sourceNodeId,
22494
+ policy: { ...sourceNode.policy || {} }
22495
+ });
22496
+ if (!node) return { success: false, error: "Failed to register worktree node" };
22497
+ }
22498
+ return {
22499
+ success: true,
22500
+ node,
22501
+ worktreePath: result.worktreePath,
22502
+ branch: result.branch
22503
+ };
21606
22504
  } catch (e) {
21607
22505
  return { success: false, error: e.message };
21608
22506
  }
@@ -21610,7 +22508,7 @@ var DaemonCommandRouter = class {
21610
22508
  // ─── Mesh Coordinator Launch ───
21611
22509
  case "launch_mesh_coordinator": {
21612
22510
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21613
- const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
22511
+ let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
21614
22512
  if (!meshId) return { success: false, error: "meshId required" };
21615
22513
  try {
21616
22514
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -21638,9 +22536,29 @@ var DaemonCommandRouter = class {
21638
22536
  }
21639
22537
  const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
21640
22538
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
22539
+ if (!cliType) {
22540
+ const resolved = await resolveProviderTypeFromPriority({
22541
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
22542
+ providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
22543
+ providerLoader: this.deps.providerLoader,
22544
+ onStatusChange: this.deps.onStatusChange
22545
+ });
22546
+ if (!resolved.providerType) {
22547
+ return {
22548
+ success: false,
22549
+ code: "mesh_coordinator_provider_priority_unusable",
22550
+ error: resolved.error || "No usable provider found from node providerPriority",
22551
+ meshId,
22552
+ cliType,
22553
+ workspace
22554
+ };
22555
+ }
22556
+ cliType = resolved.providerType;
22557
+ }
21641
22558
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21642
22559
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21643
22560
  provider: providerMeta,
22561
+ cliType,
21644
22562
  meshId,
21645
22563
  workspace
21646
22564
  });
@@ -21665,7 +22583,8 @@ var DaemonCommandRouter = class {
21665
22583
  meshCoordinatorSetup: coordinatorSetup
21666
22584
  };
21667
22585
  }
21668
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
22586
+ const configFormat = coordinatorSetup.configFormat;
22587
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21669
22588
  return {
21670
22589
  success: false,
21671
22590
  code: "mesh_coordinator_unsupported",
@@ -21675,44 +22594,93 @@ var DaemonCommandRouter = class {
21675
22594
  workspace
21676
22595
  };
21677
22596
  }
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
- }
22597
+ let systemPrompt = "";
22598
+ try {
22599
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
22600
+ } catch (error) {
22601
+ const message = error?.message || String(error);
22602
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
22603
+ return {
22604
+ success: false,
22605
+ code: "mesh_coordinator_prompt_failed",
22606
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
22607
+ meshId,
22608
+ cliType,
22609
+ workspace
22610
+ };
21688
22611
  }
22612
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22613
+ const { dirname: dirname9 } = await import("path");
22614
+ const mcpConfigPath = coordinatorSetup.configPath;
22615
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
22616
+ const returnManualFallback = (message) => ({
22617
+ success: false,
22618
+ code: "mesh_coordinator_manual_mcp_setup_required",
22619
+ error: message,
22620
+ meshId,
22621
+ cliType,
22622
+ workspace,
22623
+ meshCoordinatorSetup: hermesManualFallback
22624
+ });
21689
22625
  const mcpServerEntry = {
21690
22626
  command: coordinatorSetup.mcpServer.command,
21691
22627
  args: coordinatorSetup.mcpServer.args
21692
22628
  };
21693
22629
  if (args?.inlineMesh) {
21694
22630
  mcpServerEntry.env = {
21695
- ADHDEV_INLINE_MESH: JSON.stringify(mesh)
22631
+ ADHDEV_INLINE_MESH: JSON.stringify(mesh),
22632
+ ADHDEV_MCP_TRANSPORT: "ipc"
21696
22633
  };
21697
22634
  }
22635
+ try {
22636
+ mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
22637
+ } catch (error) {
22638
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22639
+ LOG.error("MeshCoordinator", message);
22640
+ if (hermesManualFallback) return returnManualFallback(message);
22641
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
22642
+ }
22643
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
22644
+ let existingMcpConfig = {};
22645
+ if (hadExistingMcpConfig) {
22646
+ try {
22647
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
22648
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
22649
+ } catch (error) {
22650
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
22651
+ return {
22652
+ success: false,
22653
+ code: "mesh_coordinator_config_parse_failed",
22654
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
22655
+ };
22656
+ }
22657
+ }
22658
+ const mcpServersKey = getMcpServersKey(configFormat);
22659
+ const existingServers = existingMcpConfig[mcpServersKey];
21698
22660
  const mcpConfig = {
21699
22661
  ...existingMcpConfig,
21700
- mcpServers: {
21701
- ...existingMcpConfig.mcpServers || {},
22662
+ [mcpServersKey]: {
22663
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21702
22664
  [coordinatorSetup.serverName]: mcpServerEntry
21703
22665
  }
21704
22666
  };
21705
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21706
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21707
- let systemPrompt = "";
21708
22667
  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).`;
22668
+ writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22669
+ } catch (error) {
22670
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22671
+ LOG.error("MeshCoordinator", message);
22672
+ if (hermesManualFallback) return returnManualFallback(message);
22673
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21712
22674
  }
22675
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21713
22676
  const cliArgs = [];
22677
+ const launchEnv = {};
21714
22678
  if (systemPrompt) {
21715
- cliArgs.push("--append-system-prompt", systemPrompt);
22679
+ if (configFormat === "hermes_config_yaml") {
22680
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22681
+ } else {
22682
+ cliArgs.push("--append-system-prompt", systemPrompt);
22683
+ }
21716
22684
  }
21717
22685
  if (cliType === "claude-cli") {
21718
22686
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21721,6 +22689,7 @@ var DaemonCommandRouter = class {
21721
22689
  cliType,
21722
22690
  dir: workspace,
21723
22691
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22692
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21724
22693
  settings: {
21725
22694
  meshCoordinatorFor: meshId
21726
22695
  }
@@ -21900,6 +22869,12 @@ var DaemonStatusReporter = class {
21900
22869
  if (providerType) {
21901
22870
  payload.providerType = providerType;
21902
22871
  }
22872
+ if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
22873
+ payload.providerSessionId = event.providerSessionId.trim();
22874
+ }
22875
+ if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
22876
+ payload.workspaceName = event.workspaceName.trim();
22877
+ }
21903
22878
  if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
21904
22879
  payload.duration = event.duration;
21905
22880
  }
@@ -23147,7 +24122,10 @@ var ProviderInstanceManager = class {
23147
24122
  this.instances.get(id).dispose();
23148
24123
  }
23149
24124
  this.instances.set(id, instance);
23150
- await instance.init(context);
24125
+ await instance.init({
24126
+ ...context,
24127
+ emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
24128
+ });
23151
24129
  }
23152
24130
  /**
23153
24131
  * Instance remove
@@ -23309,6 +24287,17 @@ var ProviderInstanceManager = class {
23309
24287
  onEvent(listener) {
23310
24288
  this.eventListeners.push(listener);
23311
24289
  }
24290
+ emitProviderEvent(providerType, instanceId, event) {
24291
+ const payload = {
24292
+ ...event,
24293
+ providerType,
24294
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
24295
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
24296
+ };
24297
+ for (const listener of this.eventListeners) {
24298
+ listener(payload);
24299
+ }
24300
+ }
23312
24301
  emitPendingEvents(providerType, state, extra = {}) {
23313
24302
  for (const event of state.pendingEvents) {
23314
24303
  for (const listener of this.eventListeners) {
@@ -23381,11 +24370,11 @@ var ProviderInstanceManager = class {
23381
24370
 
23382
24371
  // src/providers/version-archive.ts
23383
24372
  var fs11 = __toESM(require("fs"));
23384
- var path21 = __toESM(require("path"));
23385
- var os19 = __toESM(require("os"));
24373
+ var path22 = __toESM(require("path"));
24374
+ var os20 = __toESM(require("os"));
23386
24375
  var import_child_process10 = require("child_process");
23387
24376
  var import_os3 = require("os");
23388
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
24377
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23389
24378
  var MAX_ENTRIES_PER_PROVIDER = 20;
23390
24379
  var VersionArchive = class {
23391
24380
  history = {};
@@ -23432,7 +24421,7 @@ var VersionArchive = class {
23432
24421
  }
23433
24422
  save() {
23434
24423
  try {
23435
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
24424
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23436
24425
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23437
24426
  } catch {
23438
24427
  }
@@ -23488,8 +24477,8 @@ function getVersion(binary, versionCommand) {
23488
24477
  function checkPathExists2(paths) {
23489
24478
  for (const p of paths) {
23490
24479
  if (p.includes("*")) {
23491
- const home = os19.homedir();
23492
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
24480
+ const home = os20.homedir();
24481
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23493
24482
  if (fs11.existsSync(resolved)) return resolved;
23494
24483
  } else {
23495
24484
  if (fs11.existsSync(p)) return p;
@@ -23499,7 +24488,7 @@ function checkPathExists2(paths) {
23499
24488
  }
23500
24489
  function getMacAppVersion(appPath) {
23501
24490
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
23502
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
24491
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23503
24492
  if (!fs11.existsSync(plistPath)) return null;
23504
24493
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23505
24494
  return raw || null;
@@ -23525,7 +24514,7 @@ async function detectAllVersions(loader, archive) {
23525
24514
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23526
24515
  let resolvedBin = cliBin;
23527
24516
  if (!resolvedBin && appPath && currentOs === "darwin") {
23528
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24517
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23529
24518
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23530
24519
  }
23531
24520
  info.installed = !!(appPath || resolvedBin);
@@ -23566,7 +24555,7 @@ async function detectAllVersions(loader, archive) {
23566
24555
  // src/daemon/dev-server.ts
23567
24556
  var http2 = __toESM(require("http"));
23568
24557
  var fs15 = __toESM(require("fs"));
23569
- var path25 = __toESM(require("path"));
24558
+ var path26 = __toESM(require("path"));
23570
24559
  init_config();
23571
24560
 
23572
24561
  // src/daemon/scaffold-template.ts
@@ -23917,7 +24906,7 @@ init_logger();
23917
24906
 
23918
24907
  // src/daemon/dev-cdp-handlers.ts
23919
24908
  var fs12 = __toESM(require("fs"));
23920
- var path22 = __toESM(require("path"));
24909
+ var path23 = __toESM(require("path"));
23921
24910
  init_logger();
23922
24911
  async function handleCdpEvaluate(ctx, req, res) {
23923
24912
  const body = await ctx.readBody(req);
@@ -24096,17 +25085,17 @@ async function handleScriptHints(ctx, type, _req, res) {
24096
25085
  return;
24097
25086
  }
24098
25087
  let scriptsPath = "";
24099
- const directScripts = path22.join(dir, "scripts.js");
25088
+ const directScripts = path23.join(dir, "scripts.js");
24100
25089
  if (fs12.existsSync(directScripts)) {
24101
25090
  scriptsPath = directScripts;
24102
25091
  } else {
24103
- const scriptsDir = path22.join(dir, "scripts");
25092
+ const scriptsDir = path23.join(dir, "scripts");
24104
25093
  if (fs12.existsSync(scriptsDir)) {
24105
25094
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
24106
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
25095
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
24107
25096
  }).sort().reverse();
24108
25097
  for (const ver of versions) {
24109
- const p = path22.join(scriptsDir, ver, "scripts.js");
25098
+ const p = path23.join(scriptsDir, ver, "scripts.js");
24110
25099
  if (fs12.existsSync(p)) {
24111
25100
  scriptsPath = p;
24112
25101
  break;
@@ -24935,7 +25924,7 @@ async function handleDomContext(ctx, type, req, res) {
24935
25924
 
24936
25925
  // src/daemon/dev-cli-debug.ts
24937
25926
  var fs13 = __toESM(require("fs"));
24938
- var path23 = __toESM(require("path"));
25927
+ var path24 = __toESM(require("path"));
24939
25928
  function slugifyFixtureName(value) {
24940
25929
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24941
25930
  return normalized || `fixture-${Date.now()}`;
@@ -24945,11 +25934,11 @@ function getCliFixtureDir(ctx, type) {
24945
25934
  if (!providerDir) {
24946
25935
  throw new Error(`Provider directory not found for '${type}'`);
24947
25936
  }
24948
- return path23.join(providerDir, "fixtures");
25937
+ return path24.join(providerDir, "fixtures");
24949
25938
  }
24950
25939
  function readCliFixture(ctx, type, name) {
24951
25940
  const fixtureDir = getCliFixtureDir(ctx, type);
24952
- const filePath = path23.join(fixtureDir, `${name}.json`);
25941
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24953
25942
  if (!fs13.existsSync(filePath)) {
24954
25943
  throw new Error(`Fixture not found: ${filePath}`);
24955
25944
  }
@@ -25716,7 +26705,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25716
26705
  },
25717
26706
  notes: typeof body?.notes === "string" ? body.notes : void 0
25718
26707
  };
25719
- const filePath = path23.join(fixtureDir, `${name}.json`);
26708
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25720
26709
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25721
26710
  ctx.json(res, 200, {
25722
26711
  saved: true,
@@ -25740,7 +26729,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25740
26729
  return;
25741
26730
  }
25742
26731
  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);
26732
+ const fullPath = path24.join(fixtureDir, file);
25744
26733
  try {
25745
26734
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25746
26735
  return {
@@ -25876,8 +26865,8 @@ async function handleCliRaw(ctx, req, res) {
25876
26865
 
25877
26866
  // src/daemon/dev-auto-implement.ts
25878
26867
  var fs14 = __toESM(require("fs"));
25879
- var path24 = __toESM(require("path"));
25880
- var os20 = __toESM(require("os"));
26868
+ var path25 = __toESM(require("path"));
26869
+ var os21 = __toESM(require("os"));
25881
26870
  function getAutoImplPid(ctx) {
25882
26871
  const pid = ctx.autoImplProcess?.pid;
25883
26872
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25926,22 +26915,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25926
26915
  if (!fs14.existsSync(scriptsDir)) return null;
25927
26916
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25928
26917
  try {
25929
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
26918
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25930
26919
  } catch {
25931
26920
  return false;
25932
26921
  }
25933
26922
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25934
26923
  if (versions.length === 0) return null;
25935
- return path24.join(scriptsDir, versions[0]);
26924
+ return path25.join(scriptsDir, versions[0]);
25936
26925
  }
25937
26926
  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}`)) {
26927
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26928
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26929
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26930
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25942
26931
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25943
26932
  }
25944
- if (path24.basename(desiredDir) !== type) {
26933
+ if (path25.basename(desiredDir) !== type) {
25945
26934
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25946
26935
  }
25947
26936
  const sourceDir = ctx.findProviderDir(type);
@@ -25949,11 +26938,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25949
26938
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25950
26939
  }
25951
26940
  if (!fs14.existsSync(desiredDir)) {
25952
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
26941
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25953
26942
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25954
26943
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25955
26944
  }
25956
- const providerJson = path24.join(desiredDir, "provider.json");
26945
+ const providerJson = path25.join(desiredDir, "provider.json");
25957
26946
  if (!fs14.existsSync(providerJson)) {
25958
26947
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25959
26948
  }
@@ -25964,13 +26953,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25964
26953
  const refDir = ctx.findProviderDir(referenceType);
25965
26954
  if (!refDir || !fs14.existsSync(refDir)) return {};
25966
26955
  const referenceScripts = {};
25967
- const scriptsDir = path24.join(refDir, "scripts");
26956
+ const scriptsDir = path25.join(refDir, "scripts");
25968
26957
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25969
26958
  if (!latestDir) return referenceScripts;
25970
26959
  for (const file of fs14.readdirSync(latestDir)) {
25971
26960
  if (!file.endsWith(".js")) continue;
25972
26961
  try {
25973
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
26962
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25974
26963
  } catch {
25975
26964
  }
25976
26965
  }
@@ -26078,9 +27067,9 @@ async function handleAutoImplement(ctx, type, req, res) {
26078
27067
  });
26079
27068
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
26080
27069
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
26081
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
27070
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
26082
27071
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
26083
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
27072
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26084
27073
  fs14.writeFileSync(promptFile, prompt, "utf-8");
26085
27074
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
26086
27075
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26233,7 +27222,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26233
27222
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26234
27223
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26235
27224
  let shellCmd;
26236
- const isWin = os20.platform() === "win32";
27225
+ const isWin = os21.platform() === "win32";
26237
27226
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26238
27227
  const promptMode = autoImpl?.promptMode ?? "stdin";
26239
27228
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26272,7 +27261,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26272
27261
  try {
26273
27262
  const pty = require("node-pty");
26274
27263
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26275
- const isWin2 = os20.platform() === "win32";
27264
+ const isWin2 = os21.platform() === "win32";
26276
27265
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26277
27266
  name: "xterm-256color",
26278
27267
  cols: 120,
@@ -26512,7 +27501,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26512
27501
  setMode: "set_mode.js"
26513
27502
  };
26514
27503
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26515
- const scriptsDir = path24.join(providerDir, "scripts");
27504
+ const scriptsDir = path25.join(providerDir, "scripts");
26516
27505
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26517
27506
  if (latestScriptsDir) {
26518
27507
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26523,7 +27512,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26523
27512
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26524
27513
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26525
27514
  try {
26526
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27515
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26527
27516
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26528
27517
  lines.push("```javascript");
26529
27518
  lines.push(content);
@@ -26540,7 +27529,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26540
27529
  lines.push("");
26541
27530
  for (const file of refFiles) {
26542
27531
  try {
26543
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27532
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26544
27533
  lines.push(`### \`${file}\` \u{1F512}`);
26545
27534
  lines.push("```javascript");
26546
27535
  lines.push(content);
@@ -26581,10 +27570,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26581
27570
  lines.push("");
26582
27571
  }
26583
27572
  }
26584
- const docsDir = path24.join(providerDir, "../../docs");
27573
+ const docsDir = path25.join(providerDir, "../../docs");
26585
27574
  const loadGuide = (name) => {
26586
27575
  try {
26587
- const p = path24.join(docsDir, name);
27576
+ const p = path25.join(docsDir, name);
26588
27577
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26589
27578
  } catch {
26590
27579
  }
@@ -26821,7 +27810,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26821
27810
  parseApproval: "parse_approval.js"
26822
27811
  };
26823
27812
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26824
- const scriptsDir = path24.join(providerDir, "scripts");
27813
+ const scriptsDir = path25.join(providerDir, "scripts");
26825
27814
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26826
27815
  if (latestScriptsDir) {
26827
27816
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26833,7 +27822,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26833
27822
  if (!file.endsWith(".js")) continue;
26834
27823
  if (!targetFileNames.has(file)) continue;
26835
27824
  try {
26836
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27825
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26837
27826
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26838
27827
  lines.push("```javascript");
26839
27828
  lines.push(content);
@@ -26849,7 +27838,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26849
27838
  lines.push("");
26850
27839
  for (const file of refFiles) {
26851
27840
  try {
26852
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27841
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26853
27842
  lines.push(`### \`${file}\` \u{1F512}`);
26854
27843
  lines.push("```javascript");
26855
27844
  lines.push(content);
@@ -26882,10 +27871,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26882
27871
  lines.push("");
26883
27872
  }
26884
27873
  }
26885
- const docsDir = path24.join(providerDir, "../../docs");
27874
+ const docsDir = path25.join(providerDir, "../../docs");
26886
27875
  const loadGuide = (name) => {
26887
27876
  try {
26888
- const p = path24.join(docsDir, name);
27877
+ const p = path25.join(docsDir, name);
26889
27878
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26890
27879
  } catch {
26891
27880
  }
@@ -27332,8 +28321,8 @@ var DevServer = class _DevServer {
27332
28321
  }
27333
28322
  getEndpointList() {
27334
28323
  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}`;
28324
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28325
+ return `${r.method.padEnd(5)} ${path27}`;
27337
28326
  });
27338
28327
  }
27339
28328
  async start(port = DEV_SERVER_PORT) {
@@ -27621,12 +28610,12 @@ var DevServer = class _DevServer {
27621
28610
  // ─── DevConsole SPA ───
27622
28611
  getConsoleDistDir() {
27623
28612
  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")
28613
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
28614
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
28615
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27627
28616
  ];
27628
28617
  for (const dir of candidates) {
27629
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
28618
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27630
28619
  }
27631
28620
  return null;
27632
28621
  }
@@ -27636,7 +28625,7 @@ var DevServer = class _DevServer {
27636
28625
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27637
28626
  return;
27638
28627
  }
27639
- const htmlPath = path25.join(distDir, "index.html");
28628
+ const htmlPath = path26.join(distDir, "index.html");
27640
28629
  try {
27641
28630
  const html = fs15.readFileSync(htmlPath, "utf-8");
27642
28631
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27661,15 +28650,15 @@ var DevServer = class _DevServer {
27661
28650
  this.json(res, 404, { error: "Not found" });
27662
28651
  return;
27663
28652
  }
27664
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27665
- const filePath = path25.join(distDir, safePath);
28653
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28654
+ const filePath = path26.join(distDir, safePath);
27666
28655
  if (!filePath.startsWith(distDir)) {
27667
28656
  this.json(res, 403, { error: "Forbidden" });
27668
28657
  return;
27669
28658
  }
27670
28659
  try {
27671
28660
  const content = fs15.readFileSync(filePath);
27672
- const ext = path25.extname(filePath);
28661
+ const ext = path26.extname(filePath);
27673
28662
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27674
28663
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27675
28664
  res.end(content);
@@ -27782,9 +28771,9 @@ var DevServer = class _DevServer {
27782
28771
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27783
28772
  if (entry.isDirectory()) {
27784
28773
  files.push({ path: rel, size: 0, type: "dir" });
27785
- scan(path25.join(d, entry.name), rel);
28774
+ scan(path26.join(d, entry.name), rel);
27786
28775
  } else {
27787
- const stat2 = fs15.statSync(path25.join(d, entry.name));
28776
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27788
28777
  files.push({ path: rel, size: stat2.size, type: "file" });
27789
28778
  }
27790
28779
  }
@@ -27807,7 +28796,7 @@ var DevServer = class _DevServer {
27807
28796
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27808
28797
  return;
27809
28798
  }
27810
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28799
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27811
28800
  if (!fullPath.startsWith(dir)) {
27812
28801
  this.json(res, 403, { error: "Forbidden" });
27813
28802
  return;
@@ -27832,14 +28821,14 @@ var DevServer = class _DevServer {
27832
28821
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27833
28822
  return;
27834
28823
  }
27835
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28824
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27836
28825
  if (!fullPath.startsWith(dir)) {
27837
28826
  this.json(res, 403, { error: "Forbidden" });
27838
28827
  return;
27839
28828
  }
27840
28829
  try {
27841
28830
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27842
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28831
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27843
28832
  fs15.writeFileSync(fullPath, content, "utf-8");
27844
28833
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27845
28834
  this.providerLoader.reload();
@@ -27856,7 +28845,7 @@ var DevServer = class _DevServer {
27856
28845
  return;
27857
28846
  }
27858
28847
  for (const name of ["scripts.js", "provider.json"]) {
27859
- const p = path25.join(dir, name);
28848
+ const p = path26.join(dir, name);
27860
28849
  if (fs15.existsSync(p)) {
27861
28850
  const source = fs15.readFileSync(p, "utf-8");
27862
28851
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27877,8 +28866,8 @@ var DevServer = class _DevServer {
27877
28866
  this.json(res, 404, { error: `Provider not found: ${type}` });
27878
28867
  return;
27879
28868
  }
27880
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27881
- const targetPath = path25.join(dir, target);
28869
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28870
+ const targetPath = path26.join(dir, target);
27882
28871
  try {
27883
28872
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27884
28873
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -28025,7 +29014,7 @@ var DevServer = class _DevServer {
28025
29014
  }
28026
29015
  let targetDir;
28027
29016
  targetDir = this.providerLoader.getUserProviderDir(category, type);
28028
- const jsonPath = path25.join(targetDir, "provider.json");
29017
+ const jsonPath = path26.join(targetDir, "provider.json");
28029
29018
  if (fs15.existsSync(jsonPath)) {
28030
29019
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
28031
29020
  return;
@@ -28037,8 +29026,8 @@ var DevServer = class _DevServer {
28037
29026
  const createdFiles = ["provider.json"];
28038
29027
  if (result.files) {
28039
29028
  for (const [relPath, content] of Object.entries(result.files)) {
28040
- const fullPath = path25.join(targetDir, relPath);
28041
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
29029
+ const fullPath = path26.join(targetDir, relPath);
29030
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
28042
29031
  fs15.writeFileSync(fullPath, content, "utf-8");
28043
29032
  createdFiles.push(relPath);
28044
29033
  }
@@ -28091,22 +29080,22 @@ var DevServer = class _DevServer {
28091
29080
  if (!fs15.existsSync(scriptsDir)) return null;
28092
29081
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
28093
29082
  try {
28094
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
29083
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
28095
29084
  } catch {
28096
29085
  return false;
28097
29086
  }
28098
29087
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
28099
29088
  if (versions.length === 0) return null;
28100
- return path25.join(scriptsDir, versions[0]);
29089
+ return path26.join(scriptsDir, versions[0]);
28101
29090
  }
28102
29091
  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}`)) {
29092
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
29093
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
29094
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
29095
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
28107
29096
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
28108
29097
  }
28109
- if (path25.basename(desiredDir) !== type) {
29098
+ if (path26.basename(desiredDir) !== type) {
28110
29099
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
28111
29100
  }
28112
29101
  const sourceDir = this.findProviderDir(type);
@@ -28114,11 +29103,11 @@ var DevServer = class _DevServer {
28114
29103
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
28115
29104
  }
28116
29105
  if (!fs15.existsSync(desiredDir)) {
28117
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
29106
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
28118
29107
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
28119
29108
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
28120
29109
  }
28121
- const providerJson = path25.join(desiredDir, "provider.json");
29110
+ const providerJson = path26.join(desiredDir, "provider.json");
28122
29111
  if (!fs15.existsSync(providerJson)) {
28123
29112
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
28124
29113
  }
@@ -28154,7 +29143,7 @@ var DevServer = class _DevServer {
28154
29143
  setMode: "set_mode.js"
28155
29144
  };
28156
29145
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28157
- const scriptsDir = path25.join(providerDir, "scripts");
29146
+ const scriptsDir = path26.join(providerDir, "scripts");
28158
29147
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28159
29148
  if (latestScriptsDir) {
28160
29149
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28165,7 +29154,7 @@ var DevServer = class _DevServer {
28165
29154
  for (const file of fs15.readdirSync(latestScriptsDir)) {
28166
29155
  if (file.endsWith(".js") && targetFileNames.has(file)) {
28167
29156
  try {
28168
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29157
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28169
29158
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28170
29159
  lines.push("```javascript");
28171
29160
  lines.push(content);
@@ -28182,7 +29171,7 @@ var DevServer = class _DevServer {
28182
29171
  lines.push("");
28183
29172
  for (const file of refFiles) {
28184
29173
  try {
28185
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29174
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28186
29175
  lines.push(`### \`${file}\` \u{1F512}`);
28187
29176
  lines.push("```javascript");
28188
29177
  lines.push(content);
@@ -28223,10 +29212,10 @@ var DevServer = class _DevServer {
28223
29212
  lines.push("");
28224
29213
  }
28225
29214
  }
28226
- const docsDir = path25.join(providerDir, "../../docs");
29215
+ const docsDir = path26.join(providerDir, "../../docs");
28227
29216
  const loadGuide = (name) => {
28228
29217
  try {
28229
- const p = path25.join(docsDir, name);
29218
+ const p = path26.join(docsDir, name);
28230
29219
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28231
29220
  } catch {
28232
29221
  }
@@ -28400,7 +29389,7 @@ var DevServer = class _DevServer {
28400
29389
  parseApproval: "parse_approval.js"
28401
29390
  };
28402
29391
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28403
- const scriptsDir = path25.join(providerDir, "scripts");
29392
+ const scriptsDir = path26.join(providerDir, "scripts");
28404
29393
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28405
29394
  if (latestScriptsDir) {
28406
29395
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28412,7 +29401,7 @@ var DevServer = class _DevServer {
28412
29401
  if (!file.endsWith(".js")) continue;
28413
29402
  if (!targetFileNames.has(file)) continue;
28414
29403
  try {
28415
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29404
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28416
29405
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28417
29406
  lines.push("```javascript");
28418
29407
  lines.push(content);
@@ -28428,7 +29417,7 @@ var DevServer = class _DevServer {
28428
29417
  lines.push("");
28429
29418
  for (const file of refFiles) {
28430
29419
  try {
28431
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29420
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28432
29421
  lines.push(`### \`${file}\` \u{1F512}`);
28433
29422
  lines.push("```javascript");
28434
29423
  lines.push(content);
@@ -28461,10 +29450,10 @@ var DevServer = class _DevServer {
28461
29450
  lines.push("");
28462
29451
  }
28463
29452
  }
28464
- const docsDir = path25.join(providerDir, "../../docs");
29453
+ const docsDir = path26.join(providerDir, "../../docs");
28465
29454
  const loadGuide = (name) => {
28466
29455
  try {
28467
- const p = path25.join(docsDir, name);
29456
+ const p = path26.join(docsDir, name);
28468
29457
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28469
29458
  } catch {
28470
29459
  }
@@ -29464,48 +30453,6 @@ var SessionRegistry = class {
29464
30453
  // src/boot/daemon-lifecycle.ts
29465
30454
  init_logger();
29466
30455
  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
30456
  async function initDaemonComponents(config) {
29510
30457
  installGlobalInterceptor();
29511
30458
  const appConfig = loadConfig();
@@ -29812,6 +30759,7 @@ async function shutdownDaemonComponents(components) {
29812
30759
  createGitWorkspaceMonitor,
29813
30760
  createInteractionId,
29814
30761
  createMesh,
30762
+ createWorktree,
29815
30763
  deleteMesh,
29816
30764
  detectAllVersions,
29817
30765
  detectCLIs,
@@ -29864,6 +30812,7 @@ async function shutdownDaemonComponents(components) {
29864
30812
  launchWithCdp,
29865
30813
  listHostedCliRuntimes,
29866
30814
  listMeshes,
30815
+ listWorktrees,
29867
30816
  loadConfig,
29868
30817
  loadState,
29869
30818
  logCommand,
@@ -29883,6 +30832,7 @@ async function shutdownDaemonComponents(components) {
29883
30832
  normalizeSessionModalFields,
29884
30833
  parsePorcelainV2Status,
29885
30834
  parseProviderSourceConfigUpdate,
30835
+ parseWorktreeListOutput,
29886
30836
  partitionSessionHostDiagnosticsSessions,
29887
30837
  partitionSessionHostRecords,
29888
30838
  prepareSessionChatTailUpdate,
@@ -29892,6 +30842,7 @@ async function shutdownDaemonComponents(components) {
29892
30842
  recordDebugTrace,
29893
30843
  registerExtensionProviders,
29894
30844
  removeNode,
30845
+ removeWorktree,
29895
30846
  resetConfig,
29896
30847
  resetDebugRuntimeConfig,
29897
30848
  resetState,
@@ -29901,6 +30852,7 @@ async function shutdownDaemonComponents(components) {
29901
30852
  resolveGitRepository,
29902
30853
  resolveSessionHostAppName,
29903
30854
  resolveSessionHostAppNameResolution,
30855
+ resolveWorktreePath,
29904
30856
  runAsyncBatch,
29905
30857
  runGit,
29906
30858
  saveConfig,