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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -1
  2. package/dist/cli-adapters/provider-cli-runtime.d.ts +1 -0
  3. package/dist/commands/cli-manager.d.ts +17 -4
  4. package/dist/commands/mesh-coordinator.d.ts +2 -0
  5. package/dist/commands/router.d.ts +11 -0
  6. package/dist/config/mesh-config.d.ts +3 -0
  7. package/dist/git/git-types.d.ts +1 -1
  8. package/dist/git/git-worktree.d.ts +64 -0
  9. package/dist/git/index.d.ts +2 -0
  10. package/dist/index.js +1318 -426
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +1345 -457
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/mesh/coordinator-prompt.d.ts +1 -0
  15. package/dist/mesh/mesh-events.d.ts +9 -0
  16. package/dist/providers/chat-message-normalization.d.ts +11 -0
  17. package/dist/providers/cli-provider-instance.d.ts +3 -0
  18. package/dist/providers/provider-instance-manager.d.ts +1 -0
  19. package/dist/providers/provider-instance.d.ts +2 -0
  20. package/dist/repo-mesh-types.d.ts +13 -0
  21. package/dist/shared-types.d.ts +22 -1
  22. package/package.json +3 -4
  23. package/src/cli-adapters/provider-cli-adapter.ts +13 -6
  24. package/src/cli-adapters/provider-cli-runtime.ts +3 -2
  25. package/src/commands/chat-commands.ts +76 -5
  26. package/src/commands/cli-manager.ts +78 -5
  27. package/src/commands/handler.ts +13 -4
  28. package/src/commands/mesh-coordinator.ts +149 -6
  29. package/src/commands/router.d.ts +1 -0
  30. package/src/commands/router.ts +505 -34
  31. package/src/config/mesh-config.ts +23 -2
  32. package/src/git/git-commands.ts +5 -1
  33. package/src/git/git-types.ts +1 -0
  34. package/src/git/git-worktree.ts +214 -0
  35. package/src/git/index.ts +14 -0
  36. package/src/mesh/coordinator-prompt.ts +25 -10
  37. package/src/mesh/mesh-events.ts +109 -43
  38. package/src/providers/chat-message-normalization.ts +54 -0
  39. package/src/providers/cli-provider-instance.d.ts +2 -0
  40. package/src/providers/cli-provider-instance.ts +55 -7
  41. package/src/providers/provider-instance-manager.ts +20 -1
  42. package/src/providers/provider-instance.ts +2 -0
  43. package/src/repo-mesh-types.ts +15 -0
  44. package/src/shared-types.ts +24 -1
  45. package/src/status/builders.ts +17 -12
  46. package/src/status/reporter.ts +6 -0
package/dist/index.mjs CHANGED
@@ -36,11 +36,140 @@ var init_repo_mesh_types = __esm({
36
36
  requireApprovalForPush: true,
37
37
  requireApprovalForDestructiveGit: true,
38
38
  dirtyWorkspaceBehavior: "warn",
39
- maxParallelTasks: 2
39
+ maxParallelTasks: 2,
40
+ sessionCleanupOnNodeRemove: "preserve"
40
41
  };
41
42
  }
42
43
  });
43
44
 
45
+ // src/git/git-worktree.ts
46
+ var git_worktree_exports = {};
47
+ __export(git_worktree_exports, {
48
+ createWorktree: () => createWorktree,
49
+ listWorktrees: () => listWorktrees,
50
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
51
+ removeWorktree: () => removeWorktree,
52
+ resolveWorktreePath: () => resolveWorktreePath
53
+ });
54
+ import * as path4 from "path";
55
+ import { mkdir } from "fs/promises";
56
+ import { existsSync } from "fs";
57
+ import { execFile as execFile2 } from "child_process";
58
+ import { promisify as promisify2 } from "util";
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 (existsSync(targetDir)) {
69
+ throw new Error(`Worktree target directory already exists: ${targetDir}`);
70
+ }
71
+ await 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 (!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 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
+ execFileAsync2 = promisify2(execFile2);
167
+ WORKTREE_DIR_NAME = ".adhdev-worktrees";
168
+ GIT_TIMEOUT_MS = 3e4;
169
+ GIT_MAX_BUFFER = 4 * 1024 * 1024;
170
+ }
171
+ });
172
+
44
173
  // src/config/config.ts
45
174
  var config_exports = {};
46
175
  __export(config_exports, {
@@ -56,8 +185,8 @@ __export(config_exports, {
56
185
  updateConfig: () => updateConfig
57
186
  });
58
187
  import { homedir } from "os";
59
- import { join } from "path";
60
- import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
188
+ import { join as join2 } from "path";
189
+ import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
61
190
  import { randomUUID } from "crypto";
62
191
  function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
63
192
  if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
@@ -151,18 +280,18 @@ function ensureMachineId(config) {
151
280
  };
152
281
  }
153
282
  function getConfigDir() {
154
- const dir = join(homedir(), ".adhdev");
155
- if (!existsSync(dir)) {
283
+ const dir = join2(homedir(), ".adhdev");
284
+ if (!existsSync2(dir)) {
156
285
  mkdirSync(dir, { recursive: true });
157
286
  }
158
287
  return dir;
159
288
  }
160
289
  function getConfigPath() {
161
- return join(getConfigDir(), "config.json");
290
+ return join2(getConfigDir(), "config.json");
162
291
  }
163
292
  function migrateStateToStateFile(raw) {
164
- const statePath = join(getConfigDir(), "state.json");
165
- if (existsSync(statePath)) return;
293
+ const statePath = join2(getConfigDir(), "state.json");
294
+ if (existsSync2(statePath)) return;
166
295
  const recentActivity = Array.isArray(raw.recentActivity) ? raw.recentActivity : [];
167
296
  const savedProviderSessions = Array.isArray(raw.savedProviderSessions) ? raw.savedProviderSessions : [];
168
297
  const legacySessionReads = isPlainObject(raw.recentSessionReads) ? raw.recentSessionReads : {};
@@ -186,7 +315,7 @@ function migrateStateToStateFile(raw) {
186
315
  }
187
316
  function loadConfig() {
188
317
  const configPath = getConfigPath();
189
- if (!existsSync(configPath)) {
318
+ if (!existsSync2(configPath)) {
190
319
  const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
191
320
  try {
192
321
  saveConfig(initialized.config);
@@ -217,7 +346,7 @@ function saveConfig(config) {
217
346
  const configPath = getConfigPath();
218
347
  const dir = getConfigDir();
219
348
  const normalized = normalizeConfig(config);
220
- if (!existsSync(dir)) {
349
+ if (!existsSync2(dir)) {
221
350
  mkdirSync(dir, { recursive: true, mode: 448 });
222
351
  }
223
352
  writeFileSync(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
@@ -295,17 +424,17 @@ __export(mesh_config_exports, {
295
424
  updateMesh: () => updateMesh,
296
425
  updateNode: () => updateNode
297
426
  });
298
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
299
- import { join as join3 } from "path";
427
+ import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
428
+ import { join as join4 } from "path";
300
429
  import { randomUUID as randomUUID3 } from "crypto";
301
430
  function getMeshConfigPath() {
302
- return join3(getConfigDir(), "meshes.json");
431
+ return join4(getConfigDir(), "meshes.json");
303
432
  }
304
433
  function loadMeshConfig() {
305
- const path26 = getMeshConfigPath();
306
- if (!existsSync3(path26)) return { meshes: [] };
434
+ const path27 = getMeshConfigPath();
435
+ if (!existsSync4(path27)) return { meshes: [] };
307
436
  try {
308
- const raw = JSON.parse(readFileSync2(path26, "utf-8"));
437
+ const raw = JSON.parse(readFileSync2(path27, "utf-8"));
309
438
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
310
439
  return raw;
311
440
  } catch {
@@ -313,16 +442,16 @@ function loadMeshConfig() {
313
442
  }
314
443
  }
315
444
  function saveMeshConfig(config) {
316
- const path26 = getMeshConfigPath();
317
- writeFileSync2(path26, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
445
+ const path27 = getMeshConfigPath();
446
+ writeFileSync2(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
318
447
  }
319
448
  function normalizeRepoIdentity(remoteUrl) {
320
449
  let identity = remoteUrl.trim();
321
450
  if (identity.startsWith("http://") || identity.startsWith("https://")) {
322
451
  try {
323
452
  const url = new URL(identity);
324
- const path26 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
325
- return `${url.hostname}/${path26}`;
453
+ const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
454
+ return `${url.hostname}/${path27}`;
326
455
  } catch {
327
456
  }
328
457
  }
@@ -330,6 +459,18 @@ function normalizeRepoIdentity(remoteUrl) {
330
459
  if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
331
460
  return identity;
332
461
  }
462
+ function mergeMeshPolicy(base, patch) {
463
+ const policy = { ...DEFAULT_MESH_POLICY, ...base || {}, ...patch || {} };
464
+ if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
465
+ policy.dirtyWorkspaceBehavior = "warn";
466
+ }
467
+ const maxParallelTasks = Number(policy.maxParallelTasks);
468
+ policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
469
+ if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
470
+ policy.sessionCleanupOnNodeRemove = "preserve";
471
+ }
472
+ return policy;
473
+ }
333
474
  function listMeshes() {
334
475
  return loadMeshConfig().meshes;
335
476
  }
@@ -353,7 +494,7 @@ function createMesh(opts) {
353
494
  repoIdentity,
354
495
  repoRemoteUrl: opts.repoRemoteUrl,
355
496
  defaultBranch: opts.defaultBranch,
356
- policy: { ...DEFAULT_MESH_POLICY, ...opts.policy },
497
+ policy: mergeMeshPolicy(void 0, opts.policy),
357
498
  coordinator: opts.coordinator || {},
358
499
  nodes: [],
359
500
  createdAt: now,
@@ -369,7 +510,7 @@ function updateMesh(meshId, opts) {
369
510
  if (!mesh) return void 0;
370
511
  if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
371
512
  if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
372
- if (opts.policy) mesh.policy = { ...mesh.policy, ...opts.policy };
513
+ if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
373
514
  if (opts.coordinator) mesh.coordinator = opts.coordinator;
374
515
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
375
516
  saveMeshConfig(config);
@@ -397,9 +538,12 @@ function addNode(meshId, opts) {
397
538
  id: `node_${randomUUID3().replace(/-/g, "")}`,
398
539
  workspace: opts.workspace.trim(),
399
540
  repoRoot: opts.repoRoot,
541
+ daemonId: opts.daemonId,
400
542
  userOverrides: opts.userOverrides || {},
401
543
  policy: opts.policy || {},
402
- isLocalWorktree: opts.isLocalWorktree
544
+ isLocalWorktree: opts.isLocalWorktree,
545
+ worktreeBranch: opts.worktreeBranch,
546
+ clonedFromNodeId: opts.clonedFromNodeId
403
547
  };
404
548
  mesh.nodes.push(node);
405
549
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -429,11 +573,13 @@ function updateNode(meshId, nodeId, opts) {
429
573
  saveMeshConfig(config);
430
574
  return node;
431
575
  }
576
+ var SESSION_CLEANUP_MODES;
432
577
  var init_mesh_config = __esm({
433
578
  "src/config/mesh-config.ts"() {
434
579
  "use strict";
435
580
  init_config();
436
581
  init_repo_mesh_types();
582
+ SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
437
583
  }
438
584
  });
439
585
 
@@ -443,7 +589,7 @@ __export(coordinator_prompt_exports, {
443
589
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
444
590
  });
445
591
  function buildCoordinatorSystemPrompt(ctx) {
446
- const { mesh, status, userInstruction } = ctx;
592
+ const { mesh, status, userInstruction, coordinatorCliType } = ctx;
447
593
  const sections = [];
448
594
  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.
449
595
 
@@ -457,15 +603,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
457
603
  } else {
458
604
  sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
459
605
  }
460
- sections.push(buildPolicySection(mesh.policy));
606
+ sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
461
607
  sections.push(TOOLS_SECTION);
462
608
  sections.push(WORKFLOW_SECTION);
463
- sections.push(RULES_SECTION);
609
+ sections.push(buildRulesSection(coordinatorCliType));
464
610
  if (userInstruction) {
465
611
  sections.push(`## Additional Context
466
612
  ${userInstruction}`);
467
613
  }
468
- if (mesh.coordinator.systemPromptSuffix) {
614
+ if (mesh.coordinator?.systemPromptSuffix) {
469
615
  sections.push(mesh.coordinator.systemPromptSuffix);
470
616
  }
471
617
  return sections.join("\n\n");
@@ -510,10 +656,29 @@ function buildPolicySection(policy) {
510
656
  return `## Policy
511
657
  ${rules.join("\n")}`;
512
658
  }
513
- var TOOLS_SECTION, WORKFLOW_SECTION, RULES_SECTION;
659
+ function buildRulesSection(coordinatorCliType) {
660
+ const coordinatorNote = coordinatorCliType ? `
661
+ - **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.` : "";
662
+ return `## Rules
663
+
664
+ - **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.
665
+ - **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.
666
+ - **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.
667
+ - **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.
668
+ - **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
669
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
670
+ - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
671
+ - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
672
+ - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
673
+ - **Never fabricate tool results.** Always call the actual tool; never pretend you did.
674
+ - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
675
+ - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
676
+ }
677
+ var TOOLS_SECTION, WORKFLOW_SECTION;
514
678
  var init_coordinator_prompt = __esm({
515
679
  "src/mesh/coordinator-prompt.ts"() {
516
680
  "use strict";
681
+ init_repo_mesh_types();
517
682
  TOOLS_SECTION = `## Available Tools
518
683
 
519
684
  | Tool | Purpose |
@@ -525,36 +690,29 @@ var init_coordinator_prompt = __esm({
525
690
  | \`mesh_read_chat\` | Read an agent's recent messages to check progress |
526
691
  | \`mesh_git_status\` | Check git status on a specific node |
527
692
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
528
- | \`mesh_approve\` | Approve/reject a pending agent action |`;
693
+ | \`mesh_approve\` | Approve/reject a pending agent action |
694
+ | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
695
+ | \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
529
696
  WORKFLOW_SECTION = `## Orchestration Workflow
530
697
 
531
698
  1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
532
699
  2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
533
700
  3. **Delegate** \u2014 For each task:
534
701
  a. Pick the best node (consider: health, dirty state, current workload).
535
- b. If no session exists, call \`mesh_launch_session\` to start one.
536
- 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.
702
+ b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
703
+ c. If no session exists, call \`mesh_launch_session\` to start one.
704
+ 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.
537
705
  4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
538
706
  5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
539
707
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
540
- 7. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
541
- RULES_SECTION = `## Rules
542
-
543
- - **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.
544
- - **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.
545
- - **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.
546
- - **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
547
- - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
548
- - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
549
- - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
550
- - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
551
- - **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
708
+ 7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
709
+ 8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
552
710
  }
553
711
  });
554
712
 
555
713
  // src/logging/logger.ts
556
714
  import * as fs2 from "fs";
557
- import * as path9 from "path";
715
+ import * as path10 from "path";
558
716
  import * as os4 from "os";
559
717
  function setLogLevel(level) {
560
718
  currentLevel = level;
@@ -570,13 +728,13 @@ function getDaemonLogDir() {
570
728
  return LOG_DIR;
571
729
  }
572
730
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
573
- return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
731
+ return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
574
732
  }
575
733
  function checkDateRotation() {
576
734
  const today = getDateStr();
577
735
  if (today !== currentDate) {
578
736
  currentDate = today;
579
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
737
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
580
738
  cleanOldLogs();
581
739
  }
582
740
  }
@@ -590,7 +748,7 @@ function cleanOldLogs() {
590
748
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
591
749
  if (dateMatch && dateMatch[1] < cutoffStr) {
592
750
  try {
593
- fs2.unlinkSync(path9.join(LOG_DIR, file));
751
+ fs2.unlinkSync(path10.join(LOG_DIR, file));
594
752
  } catch {
595
753
  }
596
754
  }
@@ -713,7 +871,7 @@ var init_logger = __esm({
713
871
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
714
872
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
715
873
  currentLevel = "info";
716
- 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");
874
+ 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");
717
875
  MAX_LOG_SIZE = 5 * 1024 * 1024;
718
876
  MAX_LOG_DAYS = 7;
719
877
  try {
@@ -721,16 +879,16 @@ var init_logger = __esm({
721
879
  } catch {
722
880
  }
723
881
  currentDate = getDateStr();
724
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
882
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
725
883
  cleanOldLogs();
726
884
  try {
727
- const oldLog = path9.join(LOG_DIR, "daemon.log");
885
+ const oldLog = path10.join(LOG_DIR, "daemon.log");
728
886
  if (fs2.existsSync(oldLog)) {
729
887
  const stat2 = fs2.statSync(oldLog);
730
888
  const oldDate = stat2.mtime.toISOString().slice(0, 10);
731
- fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
889
+ fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
732
890
  }
733
- const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
891
+ const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
734
892
  if (fs2.existsSync(oldLogBackup)) {
735
893
  fs2.unlinkSync(oldLogBackup);
736
894
  }
@@ -762,7 +920,7 @@ var init_logger = __esm({
762
920
  }
763
921
  };
764
922
  interceptorInstalled = false;
765
- LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
923
+ LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
766
924
  }
767
925
  });
768
926
 
@@ -1171,7 +1329,7 @@ var init_pty_transport = __esm({
1171
1329
 
1172
1330
  // src/cli-adapters/provider-cli-shared.ts
1173
1331
  import * as os9 from "os";
1174
- import * as path13 from "path";
1332
+ import * as path14 from "path";
1175
1333
  import { execSync as execSync3 } from "child_process";
1176
1334
  function stripAnsi(str) {
1177
1335
  return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
@@ -1236,9 +1394,9 @@ function buildCliScreenSnapshot(text) {
1236
1394
  function findBinary(name) {
1237
1395
  const trimmed = String(name || "").trim();
1238
1396
  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);
1397
+ const expanded = trimmed.startsWith("~") ? path14.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1398
+ if (path14.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1399
+ return path14.isAbsolute(expanded) ? expanded : path14.resolve(expanded);
1242
1400
  }
1243
1401
  const isWin = os9.platform() === "win32";
1244
1402
  try {
@@ -1254,7 +1412,7 @@ function findBinary(name) {
1254
1412
  }
1255
1413
  }
1256
1414
  function isScriptBinary(binaryPath) {
1257
- if (!path13.isAbsolute(binaryPath)) return false;
1415
+ if (!path14.isAbsolute(binaryPath)) return false;
1258
1416
  try {
1259
1417
  const fs16 = __require("fs");
1260
1418
  const resolved = fs16.realpathSync(binaryPath);
@@ -1270,7 +1428,7 @@ function isScriptBinary(binaryPath) {
1270
1428
  }
1271
1429
  }
1272
1430
  function looksLikeMachOOrElf(filePath) {
1273
- if (!path13.isAbsolute(filePath)) return false;
1431
+ if (!path14.isAbsolute(filePath)) return false;
1274
1432
  try {
1275
1433
  const fs16 = __require("fs");
1276
1434
  const resolved = fs16.realpathSync(filePath);
@@ -1484,10 +1642,10 @@ var init_provider_cli_config = __esm({
1484
1642
 
1485
1643
  // src/cli-adapters/provider-cli-runtime.ts
1486
1644
  import * as os10 from "os";
1487
- import * as path14 from "path";
1645
+ import * as path15 from "path";
1488
1646
  import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from "@adhdev/session-host-core";
1489
1647
  function resolveCliSpawnPlan(options) {
1490
- const { provider, runtimeSettings, workingDir, extraArgs } = options;
1648
+ const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
1491
1649
  const { spawn: spawnConfig } = provider;
1492
1650
  const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
1493
1651
  const binaryPath = findBinary(configuredCommand);
@@ -1495,9 +1653,9 @@ function resolveCliSpawnPlan(options) {
1495
1653
  const allArgs = [...spawnConfig.args, ...extraArgs];
1496
1654
  let shellCmd;
1497
1655
  let shellArgs;
1498
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1656
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1499
1657
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1500
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1658
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1501
1659
  const useShell = isWin ? useShellWin : useShellUnix;
1502
1660
  if (useShell) {
1503
1661
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -1511,7 +1669,7 @@ function resolveCliSpawnPlan(options) {
1511
1669
  shellCmd = binaryPath;
1512
1670
  shellArgs = allArgs;
1513
1671
  }
1514
- const env = buildCliSpawnEnv(process.env, spawnConfig.env);
1672
+ const env = buildCliSpawnEnv(process.env, { ...spawnConfig.env || {}, ...extraEnv || {} });
1515
1673
  env.TERMINAL_CWD = workingDir;
1516
1674
  return {
1517
1675
  binaryPath,
@@ -1610,8 +1768,9 @@ var init_provider_cli_adapter = __esm({
1610
1768
  init_provider_cli_runtime();
1611
1769
  init_provider_cli_shared();
1612
1770
  ProviderCliAdapter = class _ProviderCliAdapter {
1613
- constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
1771
+ constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
1614
1772
  this.extraArgs = extraArgs;
1773
+ this.extraEnv = extraEnv;
1615
1774
  this.provider = provider;
1616
1775
  this.transportFactory = transportFactory;
1617
1776
  this.cliType = provider.type;
@@ -1762,8 +1921,9 @@ var init_provider_cli_adapter = __esm({
1762
1921
  const currentSnapshot = normalizeScreenSnapshot(screenText);
1763
1922
  const lastSnapshot = this.lastScreenSnapshot;
1764
1923
  if (!lastSnapshot || lastSnapshot === currentSnapshot) return screenText;
1765
- const staleSnapshotLooksActive = /\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel/i.test(lastSnapshot);
1766
- 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);
1924
+ 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;
1925
+ const staleSnapshotLooksActive = activeScreenPattern.test(lastSnapshot);
1926
+ const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:Try\s+["“][^\n\r"”]+["”])?\s*(?:\n|\r|$)/.test(screenText) && !activeScreenPattern.test(screenText);
1767
1927
  if (staleSnapshotLooksActive && currentScreenLooksIdle) return screenText;
1768
1928
  if (currentSnapshot.length >= lastSnapshot.length) return screenText;
1769
1929
  return `${screenText}
@@ -1926,7 +2086,8 @@ ${lastSnapshot}`;
1926
2086
  provider: this.provider,
1927
2087
  runtimeSettings: this.runtimeSettings,
1928
2088
  workingDir: this.workingDir,
1929
- extraArgs: this.extraArgs
2089
+ extraArgs: this.extraArgs,
2090
+ extraEnv: this.extraEnv
1930
2091
  });
1931
2092
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1932
2093
  this.resetTraceSession();
@@ -3124,9 +3285,8 @@ ${lastSnapshot}`;
3124
3285
  };
3125
3286
  this.recordTrace("submit_echo_missing", diagnostic);
3126
3287
  if (this.requirePromptEchoBeforeSubmit) {
3127
- const message = `${this.cliName} prompt echo was not observed on the PTY screen before submit`;
3128
- LOG.warn("CLI", `[${this.cliType}] ${message} elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
3129
- completion.rejectOnce(new Error(message));
3288
+ 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)}`);
3289
+ this.submitSendKey(state, completion);
3130
3290
  return;
3131
3291
  }
3132
3292
  LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
@@ -4547,6 +4707,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
4547
4707
  "dirty_index_required",
4548
4708
  "conflict",
4549
4709
  "invalid_args",
4710
+ "nothing_to_commit",
4550
4711
  "git_command_failed"
4551
4712
  ]);
4552
4713
  function failure(reason, error) {
@@ -4791,7 +4952,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
4791
4952
  } catch (err) {
4792
4953
  const output = (err?.stdout || "") + (err?.stderr || "");
4793
4954
  if (/nothing to commit/i.test(output)) {
4794
- throw new GitCommandError("git_command_failed", "Nothing to commit");
4955
+ throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
4956
+ stdout: err?.stdout,
4957
+ stderr: err?.stderr
4958
+ });
4795
4959
  }
4796
4960
  throw err;
4797
4961
  }
@@ -4983,20 +5147,23 @@ var TurnSnapshotTracker = class {
4983
5147
  }
4984
5148
  };
4985
5149
 
5150
+ // src/git/index.ts
5151
+ init_git_worktree();
5152
+
4986
5153
  // src/index.ts
4987
5154
  init_config();
4988
5155
 
4989
5156
  // src/config/workspaces.ts
4990
5157
  import * as fs from "fs";
4991
5158
  import * as os from "os";
4992
- import * as path4 from "path";
5159
+ import * as path5 from "path";
4993
5160
  import { randomUUID as randomUUID2 } from "crypto";
4994
5161
  var MAX_WORKSPACES = 50;
4995
5162
  function expandPath(p) {
4996
5163
  const t = (p || "").trim();
4997
5164
  if (!t) return "";
4998
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
4999
- return path4.resolve(t);
5165
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5166
+ return path5.resolve(t);
5000
5167
  }
5001
5168
  function validateWorkspacePath(absPath) {
5002
5169
  try {
@@ -5010,7 +5177,7 @@ function validateWorkspacePath(absPath) {
5010
5177
  }
5011
5178
  }
5012
5179
  function defaultWorkspaceLabel(absPath) {
5013
- const base = path4.basename(absPath) || absPath;
5180
+ const base = path5.basename(absPath) || absPath;
5014
5181
  return base;
5015
5182
  }
5016
5183
  function getDefaultWorkspacePath(config) {
@@ -5101,9 +5268,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5101
5268
  return getDefaultWorkspacePath(config) || void 0;
5102
5269
  }
5103
5270
  function findWorkspaceByPath(config, rawPath) {
5104
- const abs = path4.resolve(expandPath(rawPath));
5271
+ const abs = path5.resolve(expandPath(rawPath));
5105
5272
  if (!abs) return void 0;
5106
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5273
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5107
5274
  }
5108
5275
  function addWorkspaceEntry(config, rawPath, label, options) {
5109
5276
  const abs = expandPath(rawPath);
@@ -5119,7 +5286,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5119
5286
  const v = validateWorkspacePath(abs);
5120
5287
  if (!v.ok) return { error: v.error };
5121
5288
  const list = [...config.workspaces || []];
5122
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5289
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5123
5290
  return { error: "Workspace already in list" };
5124
5291
  }
5125
5292
  if (list.length >= MAX_WORKSPACES) {
@@ -5153,7 +5320,7 @@ function setDefaultWorkspaceId(config, id) {
5153
5320
  }
5154
5321
 
5155
5322
  // src/config/recent-activity.ts
5156
- import * as path5 from "path";
5323
+ import * as path6 from "path";
5157
5324
 
5158
5325
  // src/providers/summary-metadata.ts
5159
5326
  function normalizeSummaryItem(item) {
@@ -5222,9 +5389,9 @@ var MAX_ACTIVITY = 30;
5222
5389
  function normalizeWorkspace(workspace) {
5223
5390
  if (!workspace) return "";
5224
5391
  try {
5225
- return path5.resolve(expandPath(workspace));
5392
+ return path6.resolve(expandPath(workspace));
5226
5393
  } catch {
5227
- return path5.resolve(workspace);
5394
+ return path6.resolve(workspace);
5228
5395
  }
5229
5396
  }
5230
5397
  function buildRecentActivityKey(entry) {
@@ -5392,14 +5559,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5392
5559
  }
5393
5560
 
5394
5561
  // src/config/saved-sessions.ts
5395
- import * as path6 from "path";
5562
+ import * as path7 from "path";
5396
5563
  var MAX_SAVED_SESSIONS = 500;
5397
5564
  function normalizeWorkspace2(workspace) {
5398
5565
  if (!workspace) return "";
5399
5566
  try {
5400
- return path6.resolve(expandPath(workspace));
5567
+ return path7.resolve(expandPath(workspace));
5401
5568
  } catch {
5402
- return path6.resolve(workspace);
5569
+ return path7.resolve(workspace);
5403
5570
  }
5404
5571
  }
5405
5572
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5505,8 +5672,8 @@ async function syncMeshes(transport) {
5505
5672
 
5506
5673
  // src/config/state-store.ts
5507
5674
  init_config();
5508
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5509
- import { join as join4 } from "path";
5675
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5676
+ import { join as join5 } from "path";
5510
5677
  var DEFAULT_STATE = {
5511
5678
  recentActivity: [],
5512
5679
  savedProviderSessions: [],
@@ -5519,7 +5686,7 @@ function isPlainObject2(value) {
5519
5686
  return !!value && typeof value === "object" && !Array.isArray(value);
5520
5687
  }
5521
5688
  function getStatePath() {
5522
- return join4(getConfigDir(), "state.json");
5689
+ return join5(getConfigDir(), "state.json");
5523
5690
  }
5524
5691
  function normalizeState(raw) {
5525
5692
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -5555,7 +5722,7 @@ function normalizeState(raw) {
5555
5722
  }
5556
5723
  function loadState() {
5557
5724
  const statePath = getStatePath();
5558
- if (!existsSync4(statePath)) {
5725
+ if (!existsSync5(statePath)) {
5559
5726
  return { ...DEFAULT_STATE };
5560
5727
  }
5561
5728
  try {
@@ -5576,9 +5743,9 @@ function resetState() {
5576
5743
 
5577
5744
  // src/detection/ide-detector.ts
5578
5745
  import { execSync } from "child_process";
5579
- import { existsSync as existsSync5 } from "fs";
5746
+ import { existsSync as existsSync6 } from "fs";
5580
5747
  import { platform, homedir as homedir3 } from "os";
5581
- import * as path7 from "path";
5748
+ import * as path8 from "path";
5582
5749
  var BUILTIN_IDE_DEFINITIONS = [];
5583
5750
  var registeredIDEs = /* @__PURE__ */ new Map();
5584
5751
  function registerIDEDefinition(def) {
@@ -5597,10 +5764,10 @@ function getMergedDefinitions() {
5597
5764
  function findCliCommand(command) {
5598
5765
  const trimmed = String(command || "").trim();
5599
5766
  if (!trimmed) return null;
5600
- if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5601
- const candidate = trimmed.startsWith("~") ? path7.join(homedir3(), trimmed.slice(1)) : trimmed;
5602
- const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
5603
- return existsSync5(resolved) ? resolved : null;
5767
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5768
+ const candidate = trimmed.startsWith("~") ? path8.join(homedir3(), trimmed.slice(1)) : trimmed;
5769
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5770
+ return existsSync6(resolved) ? resolved : null;
5604
5771
  }
5605
5772
  try {
5606
5773
  const result = execSync(
@@ -5627,31 +5794,31 @@ function getIdeVersion(cliCommand) {
5627
5794
  function checkPathExists(paths) {
5628
5795
  const home = homedir3();
5629
5796
  for (const p of paths) {
5630
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
5797
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5631
5798
  if (normalized.includes("*")) {
5632
5799
  const username = home.split(/[\\/]/).pop() || "";
5633
5800
  const resolved = normalized.replace("*", username);
5634
- if (existsSync5(resolved)) return resolved;
5801
+ if (existsSync6(resolved)) return resolved;
5635
5802
  } else {
5636
- if (existsSync5(normalized)) return normalized;
5803
+ if (existsSync6(normalized)) return normalized;
5637
5804
  }
5638
5805
  }
5639
5806
  return null;
5640
5807
  }
5641
5808
  async function detectIDEs(providerLoader) {
5642
- const os21 = platform();
5809
+ const os22 = platform();
5643
5810
  const results = [];
5644
5811
  for (const def of getMergedDefinitions()) {
5645
5812
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5646
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
5813
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5647
5814
  let resolvedCli = cliPath;
5648
- if (!resolvedCli && appPath && os21 === "darwin") {
5815
+ if (!resolvedCli && appPath && os22 === "darwin") {
5649
5816
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5650
- if (existsSync5(bundledCli)) resolvedCli = bundledCli;
5817
+ if (existsSync6(bundledCli)) resolvedCli = bundledCli;
5651
5818
  }
5652
- if (!resolvedCli && appPath && os21 === "win32") {
5653
- const { dirname: dirname8 } = await import("path");
5654
- const appDir = dirname8(appPath);
5819
+ if (!resolvedCli && appPath && os22 === "win32") {
5820
+ const { dirname: dirname9 } = await import("path");
5821
+ const appDir = dirname9(appPath);
5655
5822
  const candidates = [
5656
5823
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5657
5824
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5660,13 +5827,13 @@ async function detectIDEs(providerLoader) {
5660
5827
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
5661
5828
  ];
5662
5829
  for (const c of candidates) {
5663
- if (existsSync5(c)) {
5830
+ if (existsSync6(c)) {
5664
5831
  resolvedCli = c;
5665
5832
  break;
5666
5833
  }
5667
5834
  }
5668
5835
  }
5669
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5836
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5670
5837
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5671
5838
  results.push({
5672
5839
  id: def.id,
@@ -5685,8 +5852,8 @@ async function detectIDEs(providerLoader) {
5685
5852
  // src/detection/cli-detector.ts
5686
5853
  import { exec } from "child_process";
5687
5854
  import * as os2 from "os";
5688
- import * as path8 from "path";
5689
- import { existsSync as existsSync6 } from "fs";
5855
+ import * as path9 from "path";
5856
+ import { existsSync as existsSync7 } from "fs";
5690
5857
  function parseVersion(raw) {
5691
5858
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
5692
5859
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
@@ -5698,19 +5865,19 @@ function shellQuote(value) {
5698
5865
  function expandHome(value) {
5699
5866
  const trimmed = value.trim();
5700
5867
  if (!trimmed.startsWith("~")) return trimmed;
5701
- return path8.join(os2.homedir(), trimmed.slice(1));
5868
+ return path9.join(os2.homedir(), trimmed.slice(1));
5702
5869
  }
5703
5870
  function isExplicitCommandPath(command) {
5704
5871
  const trimmed = command.trim();
5705
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5872
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5706
5873
  }
5707
5874
  function resolveCommandPath(command) {
5708
5875
  const trimmed = command.trim();
5709
5876
  if (!trimmed) return null;
5710
5877
  if (isExplicitCommandPath(trimmed)) {
5711
5878
  const expanded = expandHome(trimmed);
5712
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
5713
- return existsSync6(candidate) ? candidate : null;
5879
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5880
+ return existsSync7(candidate) ? candidate : null;
5714
5881
  }
5715
5882
  return null;
5716
5883
  }
@@ -7978,9 +8145,9 @@ ${cleanBody}`;
7978
8145
 
7979
8146
  // src/config/chat-history.ts
7980
8147
  import * as fs3 from "fs";
7981
- import * as path10 from "path";
8148
+ import * as path11 from "path";
7982
8149
  import * as os5 from "os";
7983
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8150
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
7984
8151
  var RETAIN_DAYS = 30;
7985
8152
  var SAVED_HISTORY_INDEX_VERSION = 1;
7986
8153
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8143,7 +8310,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8143
8310
  function buildSavedHistoryFileSignatureMap(dir, files) {
8144
8311
  return new Map(files.map((file) => {
8145
8312
  try {
8146
- const stat2 = fs3.statSync(path10.join(dir, file));
8313
+ const stat2 = fs3.statSync(path11.join(dir, file));
8147
8314
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8148
8315
  } catch {
8149
8316
  return [file, `${file}:missing`];
@@ -8154,7 +8321,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8154
8321
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8155
8322
  }
8156
8323
  function getSavedHistoryIndexFilePath(dir) {
8157
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8324
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8158
8325
  }
8159
8326
  function getSavedHistoryIndexLockPath(dir) {
8160
8327
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8256,7 +8423,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8256
8423
  }
8257
8424
  for (const file of Array.from(currentEntries.keys())) {
8258
8425
  if (incomingFiles.has(file)) continue;
8259
- if (!fs3.existsSync(path10.join(dir, file))) {
8426
+ if (!fs3.existsSync(path11.join(dir, file))) {
8260
8427
  currentEntries.delete(file);
8261
8428
  }
8262
8429
  }
@@ -8282,7 +8449,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8282
8449
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8283
8450
  const files = listHistoryFiles(dir);
8284
8451
  for (const file of files) {
8285
- const stat2 = fs3.statSync(path10.join(dir, file));
8452
+ const stat2 = fs3.statSync(path11.join(dir, file));
8286
8453
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8287
8454
  }
8288
8455
  return false;
@@ -8292,14 +8459,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8292
8459
  }
8293
8460
  function buildSavedHistoryFileSignature(dir, file) {
8294
8461
  try {
8295
- const stat2 = fs3.statSync(path10.join(dir, file));
8462
+ const stat2 = fs3.statSync(path11.join(dir, file));
8296
8463
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8297
8464
  } catch {
8298
8465
  return `${file}:missing`;
8299
8466
  }
8300
8467
  }
8301
8468
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8302
- const filePath = path10.join(dir, file);
8469
+ const filePath = path11.join(dir, file);
8303
8470
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8304
8471
  const currentEntry = entries.get(file) || null;
8305
8472
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8372,7 +8539,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8372
8539
  function computeSavedHistoryFileSummary(dir, file) {
8373
8540
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8374
8541
  if (!historySessionId) return null;
8375
- const filePath = path10.join(dir, file);
8542
+ const filePath = path11.join(dir, file);
8376
8543
  const content = fs3.readFileSync(filePath, "utf-8");
8377
8544
  const lines = content.split("\n").filter(Boolean);
8378
8545
  let messageCount = 0;
@@ -8459,7 +8626,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8459
8626
  const summaryBySessionId = /* @__PURE__ */ new Map();
8460
8627
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8461
8628
  for (const file of files.slice().sort()) {
8462
- const filePath = path10.join(dir, file);
8629
+ const filePath = path11.join(dir, file);
8463
8630
  const signature = fileSignatures.get(file) || `${file}:missing`;
8464
8631
  const cached = savedHistoryFileSummaryCache.get(filePath);
8465
8632
  const persisted = persistedEntries.get(file);
@@ -8579,12 +8746,12 @@ var ChatHistoryWriter = class {
8579
8746
  });
8580
8747
  }
8581
8748
  if (newMessages.length === 0) return;
8582
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8749
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8583
8750
  fs3.mkdirSync(dir, { recursive: true });
8584
8751
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8585
8752
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8586
8753
  const fileName = `${filePrefix}${date}.jsonl`;
8587
- const filePath = path10.join(dir, fileName);
8754
+ const filePath = path11.join(dir, fileName);
8588
8755
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8589
8756
  fs3.appendFileSync(filePath, lines, "utf-8");
8590
8757
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8675,11 +8842,11 @@ var ChatHistoryWriter = class {
8675
8842
  const ws = String(workspace || "").trim();
8676
8843
  if (!id || !ws) return;
8677
8844
  try {
8678
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8845
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8679
8846
  fs3.mkdirSync(dir, { recursive: true });
8680
8847
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8681
8848
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8682
- const filePath = path10.join(dir, fileName);
8849
+ const filePath = path11.join(dir, fileName);
8683
8850
  const record = {
8684
8851
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8685
8852
  receivedAt: Date.now(),
@@ -8725,14 +8892,14 @@ var ChatHistoryWriter = class {
8725
8892
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8726
8893
  this.lastSeenCounts.delete(fromDedupKey);
8727
8894
  }
8728
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8895
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8729
8896
  if (!fs3.existsSync(dir)) return;
8730
8897
  const fromPrefix = `${this.sanitize(fromId)}_`;
8731
8898
  const toPrefix = `${this.sanitize(toId)}_`;
8732
8899
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8733
8900
  for (const file of files) {
8734
- const sourcePath = path10.join(dir, file);
8735
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8901
+ const sourcePath = path11.join(dir, file);
8902
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8736
8903
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8737
8904
  const rewritten = sourceLines.map((line) => {
8738
8905
  try {
@@ -8766,13 +8933,13 @@ var ChatHistoryWriter = class {
8766
8933
  const sessionId = String(historySessionId || "").trim();
8767
8934
  if (!sessionId) return;
8768
8935
  try {
8769
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8936
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8770
8937
  if (!fs3.existsSync(dir)) return;
8771
8938
  const prefix = `${this.sanitize(sessionId)}_`;
8772
8939
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8773
8940
  const seen = /* @__PURE__ */ new Set();
8774
8941
  for (const file of files) {
8775
- const filePath = path10.join(dir, file);
8942
+ const filePath = path11.join(dir, file);
8776
8943
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8777
8944
  const next = [];
8778
8945
  for (const line of lines) {
@@ -8826,11 +8993,11 @@ var ChatHistoryWriter = class {
8826
8993
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
8827
8994
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
8828
8995
  for (const dir of agentDirs) {
8829
- const dirPath = path10.join(HISTORY_DIR, dir.name);
8996
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
8830
8997
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
8831
8998
  let removedAny = false;
8832
8999
  for (const file of files) {
8833
- const filePath = path10.join(dirPath, file);
9000
+ const filePath = path11.join(dirPath, file);
8834
9001
  const stat2 = fs3.statSync(filePath);
8835
9002
  if (stat2.mtimeMs < cutoff) {
8836
9003
  fs3.unlinkSync(filePath);
@@ -8880,13 +9047,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8880
9047
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8881
9048
  try {
8882
9049
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8883
- const dir = path10.join(HISTORY_DIR, sanitized);
9050
+ const dir = path11.join(HISTORY_DIR, sanitized);
8884
9051
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8885
9052
  const files = listHistoryFiles(dir, historySessionId);
8886
9053
  const allMessages = [];
8887
9054
  const seen = /* @__PURE__ */ new Set();
8888
9055
  for (const file of files) {
8889
- const filePath = path10.join(dir, file);
9056
+ const filePath = path11.join(dir, file);
8890
9057
  const content = fs3.readFileSync(filePath, "utf-8");
8891
9058
  const lines = content.trim().split("\n").filter(Boolean);
8892
9059
  for (let i = 0; i < lines.length; i++) {
@@ -8910,7 +9077,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8910
9077
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8911
9078
  try {
8912
9079
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8913
- const dir = path10.join(HISTORY_DIR, sanitized);
9080
+ const dir = path11.join(HISTORY_DIR, sanitized);
8914
9081
  if (!fs3.existsSync(dir)) {
8915
9082
  savedHistorySessionCache.delete(sanitized);
8916
9083
  return { sessions: [], hasMore: false };
@@ -8971,11 +9138,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8971
9138
  }
8972
9139
  function readExistingSessionStartRecord(agentType, historySessionId) {
8973
9140
  try {
8974
- const dir = path10.join(HISTORY_DIR, agentType);
9141
+ const dir = path11.join(HISTORY_DIR, agentType);
8975
9142
  if (!fs3.existsSync(dir)) return null;
8976
9143
  const files = listHistoryFiles(dir, historySessionId).sort();
8977
9144
  for (const file of files) {
8978
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9145
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
8979
9146
  for (const line of lines) {
8980
9147
  try {
8981
9148
  const parsed = JSON.parse(line);
@@ -8995,16 +9162,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8995
9162
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8996
9163
  if (records.length === 0) return false;
8997
9164
  try {
8998
- const dir = path10.join(HISTORY_DIR, agentType);
9165
+ const dir = path11.join(HISTORY_DIR, agentType);
8999
9166
  fs3.mkdirSync(dir, { recursive: true });
9000
9167
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9001
9168
  for (const file of fs3.readdirSync(dir)) {
9002
9169
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9003
- fs3.unlinkSync(path10.join(dir, file));
9170
+ fs3.unlinkSync(path11.join(dir, file));
9004
9171
  }
9005
9172
  }
9006
9173
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9007
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9174
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9008
9175
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9009
9176
  `, "utf-8");
9010
9177
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10999,6 +11166,14 @@ function getActiveChatOptions(profile) {
10999
11166
  if (profile === "full") return {};
11000
11167
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11001
11168
  }
11169
+ function resolveSessionStatus(activeChat, providerStatus) {
11170
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11171
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11172
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11173
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11174
+ if (topLevelStatus !== "idle") return topLevelStatus;
11175
+ return chatStatus;
11176
+ }
11002
11177
  function shouldIncludeSessionControls(profile) {
11003
11178
  return profile !== "live";
11004
11179
  }
@@ -11077,9 +11252,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11077
11252
  providerName: state.name,
11078
11253
  kind: "workspace",
11079
11254
  transport: "cdp-page",
11080
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11081
- activeModal: activeChat?.activeModal || null
11082
- }),
11255
+ status: resolveSessionStatus(activeChat, state.status),
11083
11256
  title,
11084
11257
  workspace,
11085
11258
  ...git && { git },
@@ -11114,9 +11287,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11114
11287
  providerSessionId: ext.providerSessionId,
11115
11288
  kind: "agent",
11116
11289
  transport: "cdp-webview",
11117
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11118
- activeModal: activeChat?.activeModal || null
11119
- }),
11290
+ status: resolveSessionStatus(activeChat, ext.status),
11120
11291
  title: activeChat?.title || ext.name,
11121
11292
  workspace,
11122
11293
  ...git && { git },
@@ -11166,9 +11337,7 @@ function buildCliSession(state, options) {
11166
11337
  providerSessionId: state.providerSessionId,
11167
11338
  kind: "agent",
11168
11339
  transport: "pty",
11169
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11170
- activeModal: activeChat?.activeModal || null
11171
- }),
11340
+ status: resolveSessionStatus(activeChat, state.status),
11172
11341
  title: activeChat?.title || state.name,
11173
11342
  workspace,
11174
11343
  ...git && { git },
@@ -11216,9 +11385,7 @@ function buildAcpSession(state, options) {
11216
11385
  providerName: state.name,
11217
11386
  kind: "agent",
11218
11387
  transport: "acp",
11219
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11220
- activeModal: activeChat?.activeModal || null
11221
- }),
11388
+ status: resolveSessionStatus(activeChat, state.status),
11222
11389
  title: activeChat?.title || state.name,
11223
11390
  workspace,
11224
11391
  ...git && { git },
@@ -11341,7 +11508,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11341
11508
  // src/commands/chat-commands.ts
11342
11509
  import * as fs4 from "fs";
11343
11510
  import * as os6 from "os";
11344
- import * as path11 from "path";
11511
+ import * as path12 from "path";
11345
11512
  import { randomUUID as randomUUID5 } from "crypto";
11346
11513
 
11347
11514
  // src/providers/provider-input-support.ts
@@ -11704,6 +11871,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11704
11871
  return raw;
11705
11872
  }
11706
11873
  }
11874
+ function isGeneratingLikeStatus(status) {
11875
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
11876
+ }
11877
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
11878
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
11879
+ if (hasNonEmptyModalButtons(activeModal)) return false;
11880
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
11881
+ if (adapterRawStatus !== "idle") return false;
11882
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
11883
+ return true;
11884
+ }
11885
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
11886
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
11887
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
11888
+ }
11889
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
11890
+ if (status !== "idle") return messages;
11891
+ return messages.map((message) => {
11892
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
11893
+ const hasStreamingMeta = meta?.streaming === true;
11894
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
11895
+ return {
11896
+ ...message,
11897
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
11898
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
11899
+ };
11900
+ });
11901
+ }
11707
11902
  function buildReadChatCommandResult(payload, args) {
11708
11903
  let validatedPayload;
11709
11904
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -11852,7 +12047,7 @@ function buildDebugBundleText(bundle) {
11852
12047
  }
11853
12048
  function getChatDebugBundleDir() {
11854
12049
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
11855
- return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12050
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11856
12051
  }
11857
12052
  function safeBundleIdSegment(value, fallback) {
11858
12053
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11868,6 +12063,14 @@ function buildChatDebugBundleSummary(bundle) {
11868
12063
  const readChat = bundle.readChat && typeof bundle.readChat === "object" ? bundle.readChat : {};
11869
12064
  const cli = bundle.cli && typeof bundle.cli === "object" ? bundle.cli : null;
11870
12065
  const frontend = bundle.frontend && typeof bundle.frontend === "object" ? bundle.frontend : null;
12066
+ const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === "object" ? readChat.debugReadChat : {};
12067
+ const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === "object" ? cli.parsedStatus : null;
12068
+ const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : void 0;
12069
+ const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : void 0;
12070
+ const cliPartialResponse = typeof cli?.partialResponse === "string" ? cli.partialResponse : "";
12071
+ const readChatStatus = typeof readChat.status === "string" ? readChat.status : "";
12072
+ const cliStatus = typeof cli?.status === "string" ? cli.status : "";
12073
+ const cliParsedStatus = typeof parsedStatus?.status === "string" ? parsedStatus.status : "";
11871
12074
  return {
11872
12075
  createdAt: bundle.createdAt,
11873
12076
  targetSessionId: target.targetSessionId,
@@ -11876,8 +12079,22 @@ function buildChatDebugBundleSummary(bundle) {
11876
12079
  readChatSuccess: readChat.success,
11877
12080
  readChatStatus: readChat.status,
11878
12081
  readChatTotalMessages: readChat.totalMessages,
12082
+ readChatReturnedMessages,
11879
12083
  cliStatus: cli?.status,
12084
+ cliParsedStatus: cliParsedStatus || void 0,
11880
12085
  cliMessageCount: cli?.messageCount,
12086
+ cliParsedMessageCount,
12087
+ cliPartialResponseChars: cliPartialResponse.length,
12088
+ parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
12089
+ parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
12090
+ readChatDebug: Object.keys(debugReadChat).length ? {
12091
+ adapterStatus: debugReadChat.adapterStatus,
12092
+ parsedStatus: debugReadChat.parsedStatus,
12093
+ returnedStatus: debugReadChat.returnedStatus,
12094
+ parsedMsgCount: debugReadChat.parsedMsgCount,
12095
+ returnedMsgCount: debugReadChat.returnedMsgCount,
12096
+ shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages
12097
+ } : void 0,
11881
12098
  hasFrontendSnapshot: !!frontend
11882
12099
  };
11883
12100
  }
@@ -11885,7 +12102,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11885
12102
  const bundleId = createChatDebugBundleId(targetSessionId);
11886
12103
  const dir = getChatDebugBundleDir();
11887
12104
  fs4.mkdirSync(dir, { recursive: true });
11888
- const savedPath = path11.join(dir, `${bundleId}.json`);
12105
+ const savedPath = path12.join(dir, `${bundleId}.json`);
11889
12106
  const json = `${JSON.stringify(bundle, null, 2)}
11890
12107
  `;
11891
12108
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12115,7 +12332,7 @@ async function handleChatHistory(h, args) {
12115
12332
  }
12116
12333
  }
12117
12334
  async function handleReadChat(h, args) {
12118
- const provider = h.getProvider(args?.agentType);
12335
+ const provider = h.getProvider(args?.agentType || args?.providerType);
12119
12336
  const transport = getTargetTransport(h, provider);
12120
12337
  const historySessionId = getHistorySessionId(h, args);
12121
12338
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
@@ -12142,10 +12359,13 @@ async function handleReadChat(h, args) {
12142
12359
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12143
12360
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12144
12361
  const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
12145
- const returnedStatus = parsedRecord.status || "idle";
12146
- 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}`);
12362
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12363
+ const runtimeMessageMerger = getTargetInstance(h, args);
12364
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12365
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12366
+ 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}`);
12147
12367
  return buildReadChatCommandResult({
12148
- messages: parsedRecord.messages,
12368
+ messages: returnedMessages,
12149
12369
  status: returnedStatus,
12150
12370
  activeModal,
12151
12371
  debugReadChat: {
@@ -12156,7 +12376,7 @@ async function handleReadChat(h, args) {
12156
12376
  returnedStatus: String(returnedStatus || ""),
12157
12377
  shouldPreferAdapterMessages: false,
12158
12378
  parsedMsgCount: parsedRecord.messages.length,
12159
- returnedMsgCount: parsedRecord.messages.length
12379
+ returnedMsgCount: returnedMessages.length
12160
12380
  },
12161
12381
  ...title ? { title } : {},
12162
12382
  ...providerSessionId ? { providerSessionId } : {},
@@ -13029,7 +13249,7 @@ async function handleResolveAction(h, args) {
13029
13249
 
13030
13250
  // src/commands/cdp-commands.ts
13031
13251
  import * as fs5 from "fs";
13032
- import * as path12 from "path";
13252
+ import * as path13 from "path";
13033
13253
  import * as os7 from "os";
13034
13254
  var KEY_TO_VK = {
13035
13255
  Backspace: 8,
@@ -13286,25 +13506,25 @@ function resolveSafePath(requestedPath) {
13286
13506
  const inputPath = rawPath || ".";
13287
13507
  const home = os7.homedir();
13288
13508
  if (inputPath.startsWith("~")) {
13289
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13509
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13290
13510
  }
13291
13511
  if (process.platform === "win32") {
13292
13512
  const normalized = normalizeWindowsRequestedPath(inputPath);
13293
- if (path12.win32.isAbsolute(normalized)) {
13294
- return path12.win32.normalize(normalized);
13513
+ if (path13.win32.isAbsolute(normalized)) {
13514
+ return path13.win32.normalize(normalized);
13295
13515
  }
13296
- return path12.win32.resolve(normalized);
13516
+ return path13.win32.resolve(normalized);
13297
13517
  }
13298
- if (path12.isAbsolute(inputPath)) {
13299
- return path12.normalize(inputPath);
13518
+ if (path13.isAbsolute(inputPath)) {
13519
+ return path13.normalize(inputPath);
13300
13520
  }
13301
- return path12.resolve(inputPath);
13521
+ return path13.resolve(inputPath);
13302
13522
  }
13303
13523
  function listDirectoryEntriesSafe(dirPath) {
13304
13524
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13305
13525
  const files = [];
13306
13526
  for (const entry of entries) {
13307
- const entryPath = path12.join(dirPath, entry.name);
13527
+ const entryPath = path13.join(dirPath, entry.name);
13308
13528
  try {
13309
13529
  if (entry.isDirectory()) {
13310
13530
  files.push({ name: entry.name, type: "directory" });
@@ -13358,7 +13578,7 @@ async function handleFileRead(h, args) {
13358
13578
  async function handleFileWrite(h, args) {
13359
13579
  try {
13360
13580
  const filePath = resolveSafePath(args?.path);
13361
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
13581
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13362
13582
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13363
13583
  return { success: true, path: filePath };
13364
13584
  } catch (e) {
@@ -14142,9 +14362,11 @@ var DaemonCommandHandler = class {
14142
14362
  }
14143
14363
  const sessionLookupFailed = !!targetSessionId && !session;
14144
14364
  const managerKey = this.extractIdeType(args, sessionLookupFailed);
14145
- let providerType;
14365
+ let providerType = args?.agentType || args?.providerType;
14146
14366
  if (!sessionLookupFailed) {
14147
- providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
14367
+ providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
14368
+ } else if (!providerType) {
14369
+ providerType = this.inferProviderType(managerKey);
14148
14370
  }
14149
14371
  return { session, managerKey, providerType, sessionLookupFailed };
14150
14372
  }
@@ -14224,7 +14446,8 @@ var DaemonCommandHandler = class {
14224
14446
  "pty_resize",
14225
14447
  "invoke_provider_script"
14226
14448
  ]);
14227
- if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
14449
+ 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);
14450
+ if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
14228
14451
  const result2 = {
14229
14452
  success: false,
14230
14453
  error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
@@ -14478,16 +14701,16 @@ var DaemonCommandHandler = class {
14478
14701
  // src/commands/cli-manager.ts
14479
14702
  init_provider_cli_adapter();
14480
14703
  import * as os13 from "os";
14481
- import * as path16 from "path";
14704
+ import * as path17 from "path";
14482
14705
  import * as crypto4 from "crypto";
14483
- import { existsSync as existsSync11 } from "fs";
14706
+ import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
14484
14707
  import { execFileSync } from "child_process";
14485
14708
  import chalk from "chalk";
14486
14709
  init_config();
14487
14710
 
14488
14711
  // src/providers/cli-provider-instance.ts
14489
14712
  import * as os12 from "os";
14490
- import * as path15 from "path";
14713
+ import * as path16 from "path";
14491
14714
  import * as crypto3 from "crypto";
14492
14715
  import * as fs6 from "fs";
14493
14716
  import { createRequire } from "module";
@@ -14546,7 +14769,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14546
14769
  var CachedDatabaseSync = null;
14547
14770
  function getDatabaseSync() {
14548
14771
  if (CachedDatabaseSync) return CachedDatabaseSync;
14549
- const requireFn = typeof __require === "function" ? __require : createRequire(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14772
+ const requireFn = typeof __require === "function" ? __require : createRequire(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14550
14773
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14551
14774
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14552
14775
  if (!CachedDatabaseSync) {
@@ -14599,7 +14822,7 @@ var CliProviderInstance = class {
14599
14822
  this.providerSessionId = options?.providerSessionId;
14600
14823
  this.launchMode = options?.launchMode || "new";
14601
14824
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14602
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
14825
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14603
14826
  this.monitor = new StatusMonitor();
14604
14827
  this.historyWriter = new ChatHistoryWriter();
14605
14828
  }
@@ -15076,7 +15299,19 @@ var CliProviderInstance = class {
15076
15299
  }
15077
15300
  }
15078
15301
  pushEvent(event) {
15079
- this.events.push(event);
15302
+ const enrichedEvent = {
15303
+ ...event,
15304
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
15305
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
15306
+ providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
15307
+ workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
15308
+ providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
15309
+ };
15310
+ if (this.context?.emitProviderEvent) {
15311
+ this.context.emitProviderEvent(enrichedEvent);
15312
+ return;
15313
+ }
15314
+ this.events.push(enrichedEvent);
15080
15315
  }
15081
15316
  flushEvents() {
15082
15317
  const events = [...this.events];
@@ -15283,12 +15518,31 @@ ${effect.notification.body || ""}`.trim();
15283
15518
  );
15284
15519
  }
15285
15520
  }
15521
+ mergeRuntimeChatMessages(parsedMessages) {
15522
+ return this.mergeConversationMessages(parsedMessages);
15523
+ }
15286
15524
  mergeConversationMessages(parsedMessages) {
15287
15525
  if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
15288
- return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
15289
- const aTime = a.message.receivedAt || a.message.timestamp || 0;
15290
- const bTime = b.message.receivedAt || b.message.timestamp || 0;
15291
- if (aTime !== bTime) return aTime - bTime;
15526
+ const parsedEntries = parsedMessages.map((message, index) => ({
15527
+ message,
15528
+ index,
15529
+ source: "parsed"
15530
+ }));
15531
+ const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
15532
+ message: entry.message,
15533
+ index: parsedMessages.length + index,
15534
+ source: "runtime"
15535
+ }));
15536
+ const getTime = (message) => {
15537
+ const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
15538
+ return Number.isFinite(value) && value > 0 ? value : 0;
15539
+ };
15540
+ return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
15541
+ const aTime = getTime(a.message);
15542
+ const bTime = getTime(b.message);
15543
+ if (aTime && bTime && aTime !== bTime) return aTime - bTime;
15544
+ if (aTime && !bTime && a.source === "runtime" && b.source === "parsed") return -1;
15545
+ if (!aTime && bTime && a.source === "parsed" && b.source === "runtime") return 1;
15292
15546
  return a.index - b.index;
15293
15547
  }).map((entry) => entry.message));
15294
15548
  }
@@ -16617,17 +16871,17 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16617
16871
  // src/commands/cli-manager.ts
16618
16872
  function isExplicitCommand(command) {
16619
16873
  const trimmed = command.trim();
16620
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16874
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16621
16875
  }
16622
16876
  function expandExecutable(command) {
16623
16877
  const trimmed = command.trim();
16624
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16878
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16625
16879
  }
16626
16880
  function commandExists(command) {
16627
16881
  const trimmed = command.trim();
16628
16882
  if (!trimmed) return false;
16629
16883
  if (isExplicitCommand(trimmed)) {
16630
- return existsSync11(expandExecutable(trimmed));
16884
+ return existsSync12(expandExecutable(trimmed));
16631
16885
  }
16632
16886
  try {
16633
16887
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -16645,6 +16899,35 @@ function colorize(color, text) {
16645
16899
  const fn = chalkApi?.[color];
16646
16900
  return typeof fn === "function" ? fn(text) : text;
16647
16901
  }
16902
+ var COORDINATOR_DELEGATED_ENV_UNSETS = {
16903
+ ADHDEV_INLINE_MESH: "",
16904
+ ADHDEV_MCP_TRANSPORT: "",
16905
+ ADHDEV_MESH_ID: "",
16906
+ HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
16907
+ };
16908
+ function hasCliArg(args, flag) {
16909
+ return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
16910
+ }
16911
+ function ensureEmptyDelegatedMcpConfig(workspace) {
16912
+ const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
16913
+ mkdirSync7(baseDir, { recursive: true });
16914
+ const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
16915
+ const filePath = path17.join(baseDir, `${workspaceHash}.json`);
16916
+ writeFileSync7(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
16917
+ return filePath;
16918
+ }
16919
+ function buildCoordinatorDelegatedCliLaunchOptions(input) {
16920
+ const cliType = String(input.cliType || "").trim();
16921
+ const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
16922
+ const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
16923
+ if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
16924
+ cliArgs.unshift("--ignore-user-config");
16925
+ }
16926
+ if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
16927
+ cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
16928
+ }
16929
+ return { cliArgs, env };
16930
+ }
16648
16931
  function isUuid(value) {
16649
16932
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
16650
16933
  }
@@ -16815,7 +17098,7 @@ var DaemonCliManager = class {
16815
17098
  attachExisting
16816
17099
  }) || void 0;
16817
17100
  }
16818
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17101
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
16819
17102
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16820
17103
  const provider = this.providerLoader.getMeta(normalizedType);
16821
17104
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -16829,7 +17112,7 @@ var DaemonCliManager = class {
16829
17112
  providerSessionId,
16830
17113
  attachExisting
16831
17114
  );
16832
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17115
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
16833
17116
  }
16834
17117
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
16835
17118
  }
@@ -16902,7 +17185,7 @@ var DaemonCliManager = class {
16902
17185
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16903
17186
  const trimmed = (workingDir || "").trim();
16904
17187
  if (!trimmed) throw new Error("working directory required");
16905
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17188
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
16906
17189
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16907
17190
  const rawProvider = this.providerLoader.getByAlias(cliType);
16908
17191
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17032,6 +17315,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17032
17315
  {
17033
17316
  providerSessionId: sessionBinding.providerSessionId,
17034
17317
  launchMode: sessionBinding.launchMode,
17318
+ extraEnv: options?.extraEnv,
17035
17319
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17036
17320
  this.persistRecentActivity({
17037
17321
  kind: "cli",
@@ -17052,7 +17336,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17052
17336
  resolvedCliArgs,
17053
17337
  key,
17054
17338
  sessionBinding.providerSessionId,
17055
- false
17339
+ false,
17340
+ options?.extraEnv
17056
17341
  );
17057
17342
  try {
17058
17343
  await adapter.spawn();
@@ -17276,12 +17561,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
17276
17561
  const dir = resolved.path;
17277
17562
  const launchSource = resolved.source;
17278
17563
  if (!cliType) throw new Error("cliType required");
17564
+ const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
17565
+ const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
17566
+ cliType,
17567
+ workspace: dir,
17568
+ cliArgs: args?.cliArgs,
17569
+ env: args?.env
17570
+ }) : null;
17279
17571
  const started = await this.startSession(
17280
17572
  cliType,
17281
17573
  dir,
17282
- args?.cliArgs,
17574
+ delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
17283
17575
  args?.initialModel,
17284
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
17576
+ {
17577
+ resumeSessionId: args?.resumeSessionId,
17578
+ settingsOverride,
17579
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
17580
+ }
17285
17581
  );
17286
17582
  return {
17287
17583
  success: true,
@@ -17403,11 +17699,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17403
17699
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
17404
17700
  import * as net from "net";
17405
17701
  import * as os15 from "os";
17406
- import * as path18 from "path";
17702
+ import * as path19 from "path";
17407
17703
 
17408
17704
  // src/providers/provider-loader.ts
17409
17705
  import * as fs7 from "fs";
17410
- import * as path17 from "path";
17706
+ import * as path18 from "path";
17411
17707
  import * as os14 from "os";
17412
17708
  import * as chokidar from "chokidar";
17413
17709
  init_logger();
@@ -17731,7 +18027,7 @@ var ProviderLoader = class _ProviderLoader {
17731
18027
  try {
17732
18028
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17733
18029
  return ["ide", "extension", "cli", "acp"].some(
17734
- (category) => fs7.existsSync(path17.join(candidate, category))
18030
+ (category) => fs7.existsSync(path18.join(candidate, category))
17735
18031
  );
17736
18032
  } catch {
17737
18033
  return false;
@@ -17739,20 +18035,20 @@ var ProviderLoader = class _ProviderLoader {
17739
18035
  }
17740
18036
  static hasProviderRootMarker(candidate) {
17741
18037
  try {
17742
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18038
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17743
18039
  } catch {
17744
18040
  return false;
17745
18041
  }
17746
18042
  }
17747
18043
  detectDefaultUserDir() {
17748
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
18044
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17749
18045
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17750
18046
  const visited = /* @__PURE__ */ new Set();
17751
18047
  for (const start of this.probeStarts) {
17752
- let current = path17.resolve(start);
18048
+ let current = path18.resolve(start);
17753
18049
  while (!visited.has(current)) {
17754
18050
  visited.add(current);
17755
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18051
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17756
18052
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17757
18053
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17758
18054
  if (envOptIn || hasMarker) {
@@ -17774,7 +18070,7 @@ var ProviderLoader = class _ProviderLoader {
17774
18070
  return { path: siblingCandidate, source };
17775
18071
  }
17776
18072
  }
17777
- const parent = path17.dirname(current);
18073
+ const parent = path18.dirname(current);
17778
18074
  if (parent === current) break;
17779
18075
  current = parent;
17780
18076
  }
@@ -17784,11 +18080,11 @@ var ProviderLoader = class _ProviderLoader {
17784
18080
  constructor(options) {
17785
18081
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17786
18082
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17787
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
18083
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17788
18084
  const detected = this.detectDefaultUserDir();
17789
18085
  this.userDir = detected.path;
17790
18086
  this.userDirSource = detected.source;
17791
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18087
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17792
18088
  this.disableUpstream = false;
17793
18089
  this.applySourceConfig({
17794
18090
  userDir: options?.userDir,
@@ -17847,7 +18143,7 @@ var ProviderLoader = class _ProviderLoader {
17847
18143
  this.userDir = detected.path;
17848
18144
  this.userDirSource = detected.source;
17849
18145
  }
17850
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18146
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17851
18147
  this.disableUpstream = this.sourceMode === "no-upstream";
17852
18148
  if (this.explicitProviderDir) {
17853
18149
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -17861,7 +18157,7 @@ var ProviderLoader = class _ProviderLoader {
17861
18157
  * Canonical provider directory shape for a given root.
17862
18158
  */
17863
18159
  getProviderDir(root, category, type) {
17864
- return path17.join(root, category, type);
18160
+ return path18.join(root, category, type);
17865
18161
  }
17866
18162
  /**
17867
18163
  * Canonical user override directory for a provider.
@@ -17888,7 +18184,7 @@ var ProviderLoader = class _ProviderLoader {
17888
18184
  resolveProviderFile(type, ...segments) {
17889
18185
  const dir = this.findProviderDirInternal(type);
17890
18186
  if (!dir) return null;
17891
- return path17.join(dir, ...segments);
18187
+ return path18.join(dir, ...segments);
17892
18188
  }
17893
18189
  /**
17894
18190
  * Load all providers (3-tier priority)
@@ -17927,7 +18223,7 @@ var ProviderLoader = class _ProviderLoader {
17927
18223
  if (!fs7.existsSync(this.upstreamDir)) return false;
17928
18224
  try {
17929
18225
  return fs7.readdirSync(this.upstreamDir).some(
17930
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18226
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
17931
18227
  );
17932
18228
  } catch {
17933
18229
  return false;
@@ -18424,8 +18720,8 @@ var ProviderLoader = class _ProviderLoader {
18424
18720
  resolved._resolvedScriptDir = entry.scriptDir;
18425
18721
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18426
18722
  if (providerDir) {
18427
- const fullDir = path17.join(providerDir, entry.scriptDir);
18428
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18723
+ const fullDir = path18.join(providerDir, entry.scriptDir);
18724
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18429
18725
  }
18430
18726
  matched = true;
18431
18727
  }
@@ -18440,8 +18736,8 @@ var ProviderLoader = class _ProviderLoader {
18440
18736
  resolved._resolvedScriptDir = base.defaultScriptDir;
18441
18737
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18442
18738
  if (providerDir) {
18443
- const fullDir = path17.join(providerDir, base.defaultScriptDir);
18444
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18739
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18740
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18445
18741
  }
18446
18742
  }
18447
18743
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18458,8 +18754,8 @@ var ProviderLoader = class _ProviderLoader {
18458
18754
  resolved._resolvedScriptDir = dirOverride;
18459
18755
  resolved._resolvedScriptsSource = `versions:${range}`;
18460
18756
  if (providerDir) {
18461
- const fullDir = path17.join(providerDir, dirOverride);
18462
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18757
+ const fullDir = path18.join(providerDir, dirOverride);
18758
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18463
18759
  }
18464
18760
  }
18465
18761
  } else if (override.scripts) {
@@ -18475,8 +18771,8 @@ var ProviderLoader = class _ProviderLoader {
18475
18771
  resolved._resolvedScriptDir = base.defaultScriptDir;
18476
18772
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18477
18773
  if (providerDir) {
18478
- const fullDir = path17.join(providerDir, base.defaultScriptDir);
18479
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18774
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18775
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18480
18776
  }
18481
18777
  }
18482
18778
  }
@@ -18508,14 +18804,14 @@ var ProviderLoader = class _ProviderLoader {
18508
18804
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18509
18805
  return null;
18510
18806
  }
18511
- const dir = path17.join(providerDir, scriptDir);
18807
+ const dir = path18.join(providerDir, scriptDir);
18512
18808
  if (!fs7.existsSync(dir)) {
18513
18809
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18514
18810
  return null;
18515
18811
  }
18516
18812
  const cached = this.scriptsCache.get(dir);
18517
18813
  if (cached) return cached;
18518
- const scriptsJs = path17.join(dir, "scripts.js");
18814
+ const scriptsJs = path18.join(dir, "scripts.js");
18519
18815
  if (fs7.existsSync(scriptsJs)) {
18520
18816
  try {
18521
18817
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -18557,7 +18853,7 @@ var ProviderLoader = class _ProviderLoader {
18557
18853
  return;
18558
18854
  }
18559
18855
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18560
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
18856
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18561
18857
  this.reload();
18562
18858
  }
18563
18859
  };
@@ -18612,7 +18908,7 @@ var ProviderLoader = class _ProviderLoader {
18612
18908
  }
18613
18909
  const https = __require("https");
18614
18910
  const { execSync: execSync7 } = __require("child_process");
18615
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
18911
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18616
18912
  let prevEtag = "";
18617
18913
  let prevTimestamp = 0;
18618
18914
  try {
@@ -18672,17 +18968,17 @@ var ProviderLoader = class _ProviderLoader {
18672
18968
  return { updated: false };
18673
18969
  }
18674
18970
  this.log("Downloading latest providers from GitHub...");
18675
- const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18676
- const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18971
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18972
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18677
18973
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18678
18974
  fs7.mkdirSync(tmpExtract, { recursive: true });
18679
18975
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18680
18976
  const extracted = fs7.readdirSync(tmpExtract);
18681
18977
  const rootDir = extracted.find(
18682
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18978
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18683
18979
  );
18684
18980
  if (!rootDir) throw new Error("Unexpected tarball structure");
18685
- const sourceDir = path17.join(tmpExtract, rootDir);
18981
+ const sourceDir = path18.join(tmpExtract, rootDir);
18686
18982
  const backupDir = this.upstreamDir + ".bak";
18687
18983
  if (fs7.existsSync(this.upstreamDir)) {
18688
18984
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18757,8 +19053,8 @@ var ProviderLoader = class _ProviderLoader {
18757
19053
  copyDirRecursive(src, dest) {
18758
19054
  fs7.mkdirSync(dest, { recursive: true });
18759
19055
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
18760
- const srcPath = path17.join(src, entry.name);
18761
- const destPath = path17.join(dest, entry.name);
19056
+ const srcPath = path18.join(src, entry.name);
19057
+ const destPath = path18.join(dest, entry.name);
18762
19058
  if (entry.isDirectory()) {
18763
19059
  this.copyDirRecursive(srcPath, destPath);
18764
19060
  } else {
@@ -18769,7 +19065,7 @@ var ProviderLoader = class _ProviderLoader {
18769
19065
  /** .meta.json save */
18770
19066
  writeMeta(metaPath, etag, timestamp) {
18771
19067
  try {
18772
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
19068
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18773
19069
  fs7.writeFileSync(metaPath, JSON.stringify({
18774
19070
  etag,
18775
19071
  timestamp,
@@ -18786,7 +19082,7 @@ var ProviderLoader = class _ProviderLoader {
18786
19082
  const scan = (d) => {
18787
19083
  try {
18788
19084
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18789
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
19085
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18790
19086
  else if (entry.name === "provider.json") count++;
18791
19087
  }
18792
19088
  } catch {
@@ -19014,17 +19310,17 @@ var ProviderLoader = class _ProviderLoader {
19014
19310
  for (const root of searchRoots) {
19015
19311
  if (!fs7.existsSync(root)) continue;
19016
19312
  const candidate = this.getProviderDir(root, cat, type);
19017
- if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19018
- const catDir = path17.join(root, cat);
19313
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19314
+ const catDir = path18.join(root, cat);
19019
19315
  if (fs7.existsSync(catDir)) {
19020
19316
  try {
19021
19317
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19022
19318
  if (!entry.isDirectory()) continue;
19023
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19319
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19024
19320
  if (fs7.existsSync(jsonPath)) {
19025
19321
  try {
19026
19322
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19027
- if (data.type === type) return path17.join(catDir, entry.name);
19323
+ if (data.type === type) return path18.join(catDir, entry.name);
19028
19324
  } catch {
19029
19325
  }
19030
19326
  }
@@ -19041,7 +19337,7 @@ var ProviderLoader = class _ProviderLoader {
19041
19337
  * (template substitution is NOT applied here — scripts.js handles that)
19042
19338
  */
19043
19339
  buildScriptWrappersFromDir(dir) {
19044
- const scriptsJs = path17.join(dir, "scripts.js");
19340
+ const scriptsJs = path18.join(dir, "scripts.js");
19045
19341
  if (fs7.existsSync(scriptsJs)) {
19046
19342
  try {
19047
19343
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -19055,7 +19351,7 @@ var ProviderLoader = class _ProviderLoader {
19055
19351
  for (const file of fs7.readdirSync(dir)) {
19056
19352
  if (!file.endsWith(".js")) continue;
19057
19353
  const scriptName = toCamel(file.replace(".js", ""));
19058
- const filePath = path17.join(dir, file);
19354
+ const filePath = path18.join(dir, file);
19059
19355
  result[scriptName] = (...args) => {
19060
19356
  try {
19061
19357
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19115,7 +19411,7 @@ var ProviderLoader = class _ProviderLoader {
19115
19411
  }
19116
19412
  const hasJson = entries.some((e) => e.name === "provider.json");
19117
19413
  if (hasJson) {
19118
- const jsonPath = path17.join(d, "provider.json");
19414
+ const jsonPath = path18.join(d, "provider.json");
19119
19415
  try {
19120
19416
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19121
19417
  const mod = JSON.parse(raw);
@@ -19136,7 +19432,7 @@ var ProviderLoader = class _ProviderLoader {
19136
19432
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19137
19433
  } else {
19138
19434
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19139
- const scriptsPath = path17.join(d, "scripts.js");
19435
+ const scriptsPath = path18.join(d, "scripts.js");
19140
19436
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19141
19437
  try {
19142
19438
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -19162,7 +19458,7 @@ var ProviderLoader = class _ProviderLoader {
19162
19458
  if (!entry.isDirectory()) continue;
19163
19459
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19164
19460
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19165
- scan(path17.join(d, entry.name));
19461
+ scan(path18.join(d, entry.name));
19166
19462
  }
19167
19463
  }
19168
19464
  };
@@ -19487,8 +19783,8 @@ function detectCurrentWorkspace(ideId) {
19487
19783
  const appNameMap = getMacAppIdentifiers();
19488
19784
  const appName = appNameMap[ideId];
19489
19785
  if (appName) {
19490
- const storagePath = path18.join(
19491
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
19786
+ const storagePath = path19.join(
19787
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19492
19788
  appName,
19493
19789
  "storage.json"
19494
19790
  );
@@ -19677,9 +19973,9 @@ init_logger();
19677
19973
 
19678
19974
  // src/logging/command-log.ts
19679
19975
  import * as fs8 from "fs";
19680
- import * as path19 from "path";
19976
+ import * as path20 from "path";
19681
19977
  import * as os16 from "os";
19682
- 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");
19978
+ 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");
19683
19979
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19684
19980
  var MAX_DAYS = 7;
19685
19981
  try {
@@ -19717,13 +20013,13 @@ function getDateStr2() {
19717
20013
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19718
20014
  }
19719
20015
  var currentDate2 = getDateStr2();
19720
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20016
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19721
20017
  var writeCount2 = 0;
19722
20018
  function checkRotation() {
19723
20019
  const today = getDateStr2();
19724
20020
  if (today !== currentDate2) {
19725
20021
  currentDate2 = today;
19726
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20022
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19727
20023
  cleanOldFiles();
19728
20024
  }
19729
20025
  }
@@ -19737,7 +20033,7 @@ function cleanOldFiles() {
19737
20033
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19738
20034
  if (dateMatch && dateMatch[1] < cutoffStr) {
19739
20035
  try {
19740
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
20036
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19741
20037
  } catch {
19742
20038
  }
19743
20039
  }
@@ -19821,13 +20117,65 @@ cleanOldFiles();
19821
20117
 
19822
20118
  // src/commands/router.ts
19823
20119
  init_logger();
20120
+ import * as yaml from "js-yaml";
19824
20121
 
19825
20122
  // src/commands/mesh-coordinator.ts
19826
- import { existsSync as existsSync14, realpathSync as realpathSync2 } from "fs";
20123
+ import { execFileSync as execFileSync2 } from "child_process";
20124
+ import { existsSync as existsSync15, readdirSync as readdirSync6, realpathSync as realpathSync2 } from "fs";
19827
20125
  import { createRequire as createRequire2 } from "module";
19828
- import { dirname as dirname3, join as join17, resolve as resolve13 } from "path";
20126
+ import * as os17 from "os";
20127
+ import { dirname as dirname4, isAbsolute as isAbsolute10, join as join18, resolve as resolve13 } from "path";
19829
20128
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
19830
20129
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20130
+ var HERMES_CLI_TYPE = "hermes-cli";
20131
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20132
+ function isHermesProvider(provider, cliType) {
20133
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20134
+ return type === HERMES_CLI_TYPE;
20135
+ }
20136
+ function resolveHermesMeshCoordinatorSetup(options) {
20137
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20138
+ meshId: options.meshId,
20139
+ nodeExecutable: options.nodeExecutable,
20140
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20141
+ });
20142
+ if (!mcpServer) {
20143
+ return {
20144
+ kind: "unsupported",
20145
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20146
+ };
20147
+ }
20148
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20149
+ if (!configPath.trim()) {
20150
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20151
+ }
20152
+ return {
20153
+ kind: "auto_import",
20154
+ serverName: DEFAULT_SERVER_NAME,
20155
+ configPath,
20156
+ configFormat: "hermes_config_yaml",
20157
+ mcpServer
20158
+ };
20159
+ }
20160
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20161
+ return {
20162
+ kind: "manual",
20163
+ serverName: DEFAULT_SERVER_NAME,
20164
+ configFormat: "hermes_config_yaml",
20165
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20166
+ requiresRestart: true,
20167
+ 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.",
20168
+ template: renderMeshCoordinatorTemplate(
20169
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20170
+ {
20171
+ meshId,
20172
+ workspace,
20173
+ serverName: DEFAULT_SERVER_NAME,
20174
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20175
+ }
20176
+ )
20177
+ };
20178
+ }
19831
20179
  function resolveMeshCoordinatorSetup(options) {
19832
20180
  const { provider, meshId, workspace } = options;
19833
20181
  const config = provider?.meshCoordinator;
@@ -19837,6 +20185,9 @@ function resolveMeshCoordinatorSetup(options) {
19837
20185
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
19838
20186
  };
19839
20187
  }
20188
+ if (isHermesProvider(provider, options.cliType)) {
20189
+ return resolveHermesMeshCoordinatorSetup(options);
20190
+ }
19840
20191
  const mcpConfig = config.mcpConfig;
19841
20192
  if (!mcpConfig || mcpConfig.mode === "none") {
19842
20193
  return {
@@ -19846,8 +20197,8 @@ function resolveMeshCoordinatorSetup(options) {
19846
20197
  }
19847
20198
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
19848
20199
  if (mcpConfig.mode === "auto_import") {
19849
- const path26 = mcpConfig.path?.trim();
19850
- if (!path26) {
20200
+ const path27 = mcpConfig.path?.trim();
20201
+ if (!path27) {
19851
20202
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
19852
20203
  }
19853
20204
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -19858,13 +20209,13 @@ function resolveMeshCoordinatorSetup(options) {
19858
20209
  if (!mcpServer) {
19859
20210
  return {
19860
20211
  kind: "unsupported",
19861
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20212
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
19862
20213
  };
19863
20214
  }
19864
20215
  return {
19865
20216
  kind: "auto_import",
19866
20217
  serverName,
19867
- configPath: join17(workspace, path26),
20218
+ configPath: resolveMcpConfigPath(path27, workspace),
19868
20219
  configFormat: mcpConfig.format,
19869
20220
  mcpServer
19870
20221
  };
@@ -19898,14 +20249,85 @@ function resolveMeshCoordinatorSetup(options) {
19898
20249
  function renderMeshCoordinatorTemplate(template, values) {
19899
20250
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
19900
20251
  }
20252
+ function resolveMcpConfigPath(configPath, workspace) {
20253
+ const trimmed = configPath.trim();
20254
+ if (trimmed === "~") return os17.homedir();
20255
+ if (trimmed.startsWith("~/")) return join18(os17.homedir(), trimmed.slice(2));
20256
+ if (isAbsolute10(trimmed)) return trimmed;
20257
+ return join18(workspace, trimmed);
20258
+ }
19901
20259
  function resolveAdhdevMcpServerLaunch(options) {
19902
20260
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
19903
20261
  if (!entryPath) return null;
20262
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20263
+ if (!nodeExecutable) return null;
19904
20264
  return {
19905
- command: options.nodeExecutable?.trim() || process.execPath,
19906
- args: [entryPath, "--repo-mesh", options.meshId]
20265
+ command: nodeExecutable,
20266
+ args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
19907
20267
  };
19908
20268
  }
20269
+ function resolveMcpNodeExecutable(explicitExecutable) {
20270
+ const explicit = explicitExecutable?.trim();
20271
+ if (explicit) return explicit;
20272
+ const candidates = [];
20273
+ const addCandidate = (candidate) => {
20274
+ const trimmed = candidate?.trim();
20275
+ if (!trimmed) return;
20276
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20277
+ if (!candidates.includes(normalized)) candidates.push(normalized);
20278
+ };
20279
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20280
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20281
+ addCandidate(process.env.npm_node_execpath);
20282
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20283
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20284
+ addCandidate("/opt/homebrew/bin/node");
20285
+ addCandidate("/usr/local/bin/node");
20286
+ addCandidate("/usr/bin/node");
20287
+ addCandidate(process.execPath);
20288
+ for (const candidate of candidates) {
20289
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20290
+ }
20291
+ return null;
20292
+ }
20293
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20294
+ for (const entry of (pathValue || "").split(":")) {
20295
+ const dir = entry.trim();
20296
+ if (!dir) continue;
20297
+ addCandidate(join18(dir, "node"));
20298
+ }
20299
+ }
20300
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20301
+ const versionsDir = join18(homeDir, ".nvm", "versions", "node");
20302
+ try {
20303
+ const versionDirs = readdirSync6(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20304
+ for (const versionDir of versionDirs) {
20305
+ addCandidate(join18(versionsDir, versionDir, "bin", "node"));
20306
+ }
20307
+ } catch {
20308
+ }
20309
+ }
20310
+ function compareNodeVersionNamesDescending(a, b) {
20311
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20312
+ const left = parse(a);
20313
+ const right = parse(b);
20314
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20315
+ const diff = (right[i] || 0) - (left[i] || 0);
20316
+ if (diff !== 0) return diff;
20317
+ }
20318
+ return b.localeCompare(a);
20319
+ }
20320
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20321
+ try {
20322
+ execFileSync2(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20323
+ stdio: "ignore",
20324
+ timeout: 3e3
20325
+ });
20326
+ return true;
20327
+ } catch {
20328
+ return false;
20329
+ }
20330
+ }
19909
20331
  function resolveAdhdevMcpEntryPath(explicitPath) {
19910
20332
  const explicit = explicitPath?.trim();
19911
20333
  if (explicit) return normalizeExistingPath(explicit) || explicit;
@@ -19918,7 +20340,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19918
20340
  const addPackagedCandidates = (baseFile) => {
19919
20341
  if (!baseFile) return;
19920
20342
  const realBase = normalizeExistingPath(baseFile) || baseFile;
19921
- const dir = dirname3(realBase);
20343
+ const dir = dirname4(realBase);
19922
20344
  addCandidate(resolve13(dir, "../vendor/mcp-server/index.js"));
19923
20345
  addCandidate(resolve13(dir, "../../vendor/mcp-server/index.js"));
19924
20346
  addCandidate(resolve13(dir, "../../../vendor/mcp-server/index.js"));
@@ -19931,7 +20353,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19931
20353
  if (normalized) return normalized;
19932
20354
  }
19933
20355
  try {
19934
- const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join17(process.cwd(), "adhdev-daemon.js");
20356
+ const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join18(process.cwd(), "adhdev-daemon.js");
19935
20357
  const req = createRequire2(requireBase);
19936
20358
  const resolvedModule = req.resolve("@adhdev/mcp-server");
19937
20359
  return normalizeExistingPath(resolvedModule) || resolvedModule;
@@ -19941,16 +20363,110 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19941
20363
  }
19942
20364
  function normalizeExistingPath(filePath) {
19943
20365
  try {
19944
- if (!existsSync14(filePath)) return null;
20366
+ if (!existsSync15(filePath)) return null;
19945
20367
  return realpathSync2.native(filePath);
19946
20368
  } catch {
19947
20369
  return null;
19948
20370
  }
19949
20371
  }
19950
20372
 
20373
+ // src/mesh/mesh-events.ts
20374
+ init_mesh_config();
20375
+ init_logger();
20376
+ function readNonEmptyString(value) {
20377
+ return typeof value === "string" && value.trim() ? value.trim() : "";
20378
+ }
20379
+ function formatCompletionMetadata(event) {
20380
+ const parts = [
20381
+ readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
20382
+ readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
20383
+ readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
20384
+ ].filter(Boolean);
20385
+ return parts.length > 0 ? ` (${parts.join("; ")})` : "";
20386
+ }
20387
+ function buildMeshSystemMessage(args) {
20388
+ const metadata = formatCompletionMetadata(args.metadataEvent);
20389
+ if (args.event === "agent:generating_completed") {
20390
+ return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. You may use mesh_read_chat to review its progress.`;
20391
+ }
20392
+ if (args.event === "agent:waiting_approval") {
20393
+ return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
20394
+ }
20395
+ return "";
20396
+ }
20397
+ function injectMeshSystemMessage(components, args) {
20398
+ const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
20399
+ const instState = inst.getState();
20400
+ if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
20401
+ if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
20402
+ return true;
20403
+ });
20404
+ if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
20405
+ const messageText = buildMeshSystemMessage({
20406
+ event: args.event,
20407
+ nodeLabel: args.nodeLabel,
20408
+ metadataEvent: args.metadataEvent
20409
+ });
20410
+ if (!messageText) return { success: false, error: "unsupported mesh event" };
20411
+ for (const coord of coordinatorInstances) {
20412
+ const coordState = coord.getState();
20413
+ LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
20414
+ coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
20415
+ }
20416
+ return { success: true, forwarded: coordinatorInstances.length };
20417
+ }
20418
+ function handleMeshForwardEvent(components, payload) {
20419
+ const eventName = readNonEmptyString(payload.event);
20420
+ if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
20421
+ return { success: false, error: "unsupported mesh event" };
20422
+ }
20423
+ const meshId = readNonEmptyString(payload.meshId);
20424
+ if (!meshId) return { success: false, error: "meshId required" };
20425
+ const nodeId = readNonEmptyString(payload.nodeId);
20426
+ const workspace = readNonEmptyString(payload.workspace);
20427
+ const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
20428
+ return injectMeshSystemMessage(components, {
20429
+ meshId,
20430
+ nodeLabel,
20431
+ event: eventName,
20432
+ metadataEvent: {
20433
+ targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
20434
+ providerType: readNonEmptyString(payload.providerType),
20435
+ providerSessionId: readNonEmptyString(payload.providerSessionId)
20436
+ }
20437
+ });
20438
+ }
20439
+ function setupMeshEventForwarding(components) {
20440
+ components.instanceManager.onEvent((event) => {
20441
+ if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
20442
+ const instanceId = readNonEmptyString(event.instanceId);
20443
+ if (!instanceId) return;
20444
+ const sourceInstance = components.instanceManager.getInstance(instanceId);
20445
+ if (!sourceInstance || sourceInstance.category !== "cli") return;
20446
+ const state = sourceInstance.getState();
20447
+ const workspace = readNonEmptyString(state.workspace);
20448
+ if (!workspace) return;
20449
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
20450
+ const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
20451
+ const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
20452
+ const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
20453
+ if (!meshId) return;
20454
+ const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
20455
+ const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
20456
+ const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
20457
+ injectMeshSystemMessage(components, {
20458
+ meshId,
20459
+ sourceInstanceId: instanceId,
20460
+ nodeLabel,
20461
+ event: event.event,
20462
+ metadataEvent: event
20463
+ });
20464
+ });
20465
+ }
20466
+
19951
20467
  // src/status/snapshot.ts
19952
20468
  init_config();
19953
- import * as os17 from "os";
20469
+ import * as os18 from "os";
19954
20470
  init_terminal_screen();
19955
20471
  init_logger();
19956
20472
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
@@ -20005,8 +20521,8 @@ function buildAvailableProviders(providerLoader) {
20005
20521
  }
20006
20522
  function buildMachineInfo(profile = "full") {
20007
20523
  const base = {
20008
- hostname: os17.hostname(),
20009
- platform: os17.platform()
20524
+ hostname: os18.hostname(),
20525
+ platform: os18.platform()
20010
20526
  };
20011
20527
  if (profile === "live") {
20012
20528
  return base;
@@ -20015,23 +20531,23 @@ function buildMachineInfo(profile = "full") {
20015
20531
  const memSnap2 = getHostMemorySnapshot();
20016
20532
  return {
20017
20533
  ...base,
20018
- arch: os17.arch(),
20019
- cpus: os17.cpus().length,
20534
+ arch: os18.arch(),
20535
+ cpus: os18.cpus().length,
20020
20536
  totalMem: memSnap2.totalMem,
20021
- release: os17.release()
20537
+ release: os18.release()
20022
20538
  };
20023
20539
  }
20024
20540
  const memSnap = getHostMemorySnapshot();
20025
20541
  return {
20026
20542
  ...base,
20027
- arch: os17.arch(),
20028
- cpus: os17.cpus().length,
20543
+ arch: os18.arch(),
20544
+ cpus: os18.cpus().length,
20029
20545
  totalMem: memSnap.totalMem,
20030
20546
  freeMem: memSnap.freeMem,
20031
20547
  availableMem: memSnap.availableMem,
20032
- loadavg: os17.loadavg(),
20033
- uptime: os17.uptime(),
20034
- release: os17.release()
20548
+ loadavg: os18.loadavg(),
20549
+ uptime: os18.uptime(),
20550
+ release: os18.release()
20035
20551
  };
20036
20552
  }
20037
20553
  function parseMessageTime(value) {
@@ -20262,17 +20778,17 @@ function buildStatusSnapshot(options) {
20262
20778
  }
20263
20779
 
20264
20780
  // src/commands/upgrade-helper.ts
20265
- import { execFileSync as execFileSync2 } from "child_process";
20781
+ import { execFileSync as execFileSync3 } from "child_process";
20266
20782
  import { spawn as spawn3 } from "child_process";
20267
20783
  import * as fs9 from "fs";
20268
- import * as os18 from "os";
20269
- import * as path20 from "path";
20784
+ import * as os19 from "os";
20785
+ import * as path21 from "path";
20270
20786
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20271
20787
  function getUpgradeLogPath() {
20272
- const home = os18.homedir();
20273
- const dir = path20.join(home, ".adhdev");
20788
+ const home = os19.homedir();
20789
+ const dir = path21.join(home, ".adhdev");
20274
20790
  fs9.mkdirSync(dir, { recursive: true });
20275
- return path20.join(dir, "daemon-upgrade.log");
20791
+ return path21.join(dir, "daemon-upgrade.log");
20276
20792
  }
20277
20793
  function appendUpgradeLog(message) {
20278
20794
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20283,14 +20799,14 @@ function appendUpgradeLog(message) {
20283
20799
  }
20284
20800
  }
20285
20801
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20286
- const binDir = path20.dirname(nodeExecutable);
20802
+ const binDir = path21.dirname(nodeExecutable);
20287
20803
  if (platform10 === "win32") {
20288
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20804
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20289
20805
  if (fs9.existsSync(npmCliPath)) {
20290
20806
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20291
20807
  }
20292
20808
  for (const candidate of ["npm.exe", "npm"]) {
20293
- const candidatePath = path20.join(binDir, candidate);
20809
+ const candidatePath = path21.join(binDir, candidate);
20294
20810
  if (fs9.existsSync(candidatePath)) {
20295
20811
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20296
20812
  }
@@ -20298,7 +20814,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20298
20814
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20299
20815
  }
20300
20816
  for (const candidate of ["npm"]) {
20301
- const candidatePath = path20.join(binDir, candidate);
20817
+ const candidatePath = path21.join(binDir, candidate);
20302
20818
  if (fs9.existsSync(candidatePath)) {
20303
20819
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20304
20820
  }
@@ -20315,13 +20831,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20315
20831
  let currentDir = resolvedPath;
20316
20832
  try {
20317
20833
  if (fs9.statSync(resolvedPath).isFile()) {
20318
- currentDir = path20.dirname(resolvedPath);
20834
+ currentDir = path21.dirname(resolvedPath);
20319
20835
  }
20320
20836
  } catch {
20321
- currentDir = path20.dirname(resolvedPath);
20837
+ currentDir = path21.dirname(resolvedPath);
20322
20838
  }
20323
20839
  while (true) {
20324
- const packageJsonPath = path20.join(currentDir, "package.json");
20840
+ const packageJsonPath = path21.join(currentDir, "package.json");
20325
20841
  try {
20326
20842
  if (fs9.existsSync(packageJsonPath)) {
20327
20843
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20332,7 +20848,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20332
20848
  }
20333
20849
  } catch {
20334
20850
  }
20335
- const parentDir = path20.dirname(currentDir);
20851
+ const parentDir = path21.dirname(currentDir);
20336
20852
  if (parentDir === currentDir) {
20337
20853
  return null;
20338
20854
  }
@@ -20340,13 +20856,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20340
20856
  }
20341
20857
  }
20342
20858
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20343
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20344
- if (path20.basename(nodeModulesDir) !== "node_modules") {
20859
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
20860
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20345
20861
  return null;
20346
20862
  }
20347
- const maybeLibDir = path20.dirname(nodeModulesDir);
20348
- if (path20.basename(maybeLibDir) === "lib") {
20349
- return path20.dirname(maybeLibDir);
20863
+ const maybeLibDir = path21.dirname(nodeModulesDir);
20864
+ if (path21.basename(maybeLibDir) === "lib") {
20865
+ return path21.dirname(maybeLibDir);
20350
20866
  }
20351
20867
  return maybeLibDir;
20352
20868
  }
@@ -20382,7 +20898,7 @@ function getNpmExecOptions(platform10 = process.platform) {
20382
20898
  }
20383
20899
  function execNpmCommandSync(args, options = {}, surface) {
20384
20900
  const execOptions = surface?.execOptions || getNpmExecOptions();
20385
- return execFileSync2(
20901
+ return execFileSync3(
20386
20902
  surface?.npmExecutable || "npm",
20387
20903
  [...surface?.npmArgsPrefix || [], ...args],
20388
20904
  {
@@ -20395,7 +20911,7 @@ function execNpmCommandSync(args, options = {}, surface) {
20395
20911
  function killPid(pid) {
20396
20912
  try {
20397
20913
  if (process.platform === "win32") {
20398
- execFileSync2("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
20914
+ execFileSync3("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
20399
20915
  } else {
20400
20916
  process.kill(pid, "SIGTERM");
20401
20917
  }
@@ -20407,7 +20923,7 @@ function killPid(pid) {
20407
20923
  function getWindowsProcessCommandLine(pid) {
20408
20924
  const pidFilter = `ProcessId=${pid}`;
20409
20925
  try {
20410
- const psOut = execFileSync2("powershell.exe", [
20926
+ const psOut = execFileSync3("powershell.exe", [
20411
20927
  "-NoProfile",
20412
20928
  "-NonInteractive",
20413
20929
  "-ExecutionPolicy",
@@ -20419,7 +20935,7 @@ function getWindowsProcessCommandLine(pid) {
20419
20935
  } catch {
20420
20936
  }
20421
20937
  try {
20422
- const wmicOut = execFileSync2("wmic", [
20938
+ const wmicOut = execFileSync3("wmic", [
20423
20939
  "process",
20424
20940
  "where",
20425
20941
  pidFilter,
@@ -20435,7 +20951,7 @@ function getProcessCommandLine(pid) {
20435
20951
  if (!Number.isFinite(pid) || pid <= 0) return null;
20436
20952
  if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
20437
20953
  try {
20438
- const text = execFileSync2("ps", ["-o", "command=", "-p", String(pid)], {
20954
+ const text = execFileSync3("ps", ["-o", "command=", "-p", String(pid)], {
20439
20955
  encoding: "utf8",
20440
20956
  timeout: 3e3,
20441
20957
  stdio: ["ignore", "pipe", "ignore"]
@@ -20461,7 +20977,7 @@ async function waitForPidExit(pid, timeoutMs) {
20461
20977
  }
20462
20978
  }
20463
20979
  function stopSessionHostProcesses(appName) {
20464
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20980
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20465
20981
  try {
20466
20982
  if (fs9.existsSync(pidFile)) {
20467
20983
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20478,7 +20994,7 @@ function stopSessionHostProcesses(appName) {
20478
20994
  }
20479
20995
  }
20480
20996
  function removeDaemonPidFile() {
20481
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
20997
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20482
20998
  try {
20483
20999
  fs9.unlinkSync(pidFile);
20484
21000
  } catch {
@@ -20489,7 +21005,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20489
21005
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20490
21006
  if (!npmRoot) return;
20491
21007
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20492
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
21008
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20493
21009
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20494
21010
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20495
21011
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20497,25 +21013,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20497
21013
  }
20498
21014
  if (pkgName.startsWith("@")) {
20499
21015
  const [scope, name] = pkgName.split("/");
20500
- const scopeDir = path20.join(npmRoot, scope);
21016
+ const scopeDir = path21.join(npmRoot, scope);
20501
21017
  if (!fs9.existsSync(scopeDir)) return;
20502
21018
  for (const entry of fs9.readdirSync(scopeDir)) {
20503
21019
  if (!entry.startsWith(`.${name}-`)) continue;
20504
- fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
20505
- appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
21020
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
21021
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20506
21022
  }
20507
21023
  } else {
20508
21024
  for (const entry of fs9.readdirSync(npmRoot)) {
20509
21025
  if (!entry.startsWith(`.${pkgName}-`)) continue;
20510
- fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
20511
- appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
21026
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
21027
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20512
21028
  }
20513
21029
  }
20514
21030
  if (fs9.existsSync(binDir)) {
20515
21031
  for (const entry of fs9.readdirSync(binDir)) {
20516
21032
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
20517
- fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
20518
- appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
21033
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
21034
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20519
21035
  }
20520
21036
  }
20521
21037
  }
@@ -20551,7 +21067,7 @@ async function runDaemonUpgradeHelper(payload) {
20551
21067
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
20552
21068
  const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
20553
21069
  appendUpgradeLog(`Installing ${spec}`);
20554
- const installOutput = execFileSync2(
21070
+ const installOutput = execFileSync3(
20555
21071
  installCommand.command,
20556
21072
  installCommand.args,
20557
21073
  {
@@ -20616,6 +21132,56 @@ function normalizeReleaseChannel(value) {
20616
21132
  function resolveUpgradeChannel(args) {
20617
21133
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20618
21134
  }
21135
+ function readProviderPriorityFromPolicy(policy) {
21136
+ const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
21137
+ const raw = record.providerPriority;
21138
+ if (!Array.isArray(raw)) return [];
21139
+ const seen = /* @__PURE__ */ new Set();
21140
+ return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
21141
+ if (seen.has(type)) return false;
21142
+ seen.add(type);
21143
+ return true;
21144
+ });
21145
+ }
21146
+ async function resolveProviderTypeFromPriority(args) {
21147
+ if (!args.providerPriority.length) {
21148
+ return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
21149
+ }
21150
+ const failed = [];
21151
+ for (const requestedType of args.providerPriority) {
21152
+ const normalizedType = args.providerLoader.resolveAlias(requestedType);
21153
+ if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
21154
+ failed.push(`${requestedType}: disabled`);
21155
+ continue;
21156
+ }
21157
+ const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
21158
+ args.providerLoader.setCliDetectionResults([{
21159
+ id: normalizedType,
21160
+ installed: !!detected,
21161
+ path: detected?.path
21162
+ }], false);
21163
+ args.onStatusChange?.();
21164
+ if (detected) return { providerType: normalizedType };
21165
+ failed.push(`${requestedType}: not detected`);
21166
+ }
21167
+ return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
21168
+ }
21169
+ function loadYamlModule() {
21170
+ return yaml;
21171
+ }
21172
+ function getMcpServersKey(format) {
21173
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
21174
+ }
21175
+ function parseMeshCoordinatorMcpConfig(text, format) {
21176
+ if (!text.trim()) return {};
21177
+ if (format === "claude_mcp_json") return JSON.parse(text);
21178
+ const parsed = loadYamlModule().load(text);
21179
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
21180
+ }
21181
+ function serializeMeshCoordinatorMcpConfig(config, format) {
21182
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
21183
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
21184
+ }
20619
21185
  var CHAT_COMMANDS = [
20620
21186
  "send_chat",
20621
21187
  "new_chat",
@@ -20714,6 +21280,109 @@ var DaemonCommandRouter = class {
20714
21280
  constructor(deps) {
20715
21281
  this.deps = deps;
20716
21282
  }
21283
+ getCachedInlineMesh(meshId, inlineMesh) {
21284
+ if (inlineMesh && typeof inlineMesh === "object") {
21285
+ this.inlineMeshCache.set(meshId, inlineMesh);
21286
+ return inlineMesh;
21287
+ }
21288
+ return this.inlineMeshCache.get(meshId);
21289
+ }
21290
+ async getMeshForCommand(meshId, inlineMesh) {
21291
+ try {
21292
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21293
+ const mesh = getMesh3(meshId);
21294
+ if (mesh) return { mesh, inline: false };
21295
+ } catch {
21296
+ }
21297
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21298
+ return cached ? { mesh: cached, inline: true } : null;
21299
+ }
21300
+ updateInlineMeshNode(meshId, mesh, node) {
21301
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21302
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21303
+ if (idx >= 0) mesh.nodes[idx] = node;
21304
+ else mesh.nodes.push(node);
21305
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21306
+ this.inlineMeshCache.set(meshId, mesh);
21307
+ }
21308
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21309
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21310
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21311
+ if (idx === -1) return false;
21312
+ mesh.nodes.splice(idx, 1);
21313
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21314
+ this.inlineMeshCache.set(meshId, mesh);
21315
+ return true;
21316
+ }
21317
+ normalizeMeshSessionCleanupMode(value) {
21318
+ return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
21319
+ }
21320
+ sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
21321
+ const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
21322
+ if (!sessionId) return false;
21323
+ if (sessionIds?.size) return sessionIds.has(sessionId);
21324
+ const workspace = typeof node?.workspace === "string" ? node.workspace : "";
21325
+ if (workspace && record?.workspace === workspace) return true;
21326
+ if (record?.meta?.meshNodeId === nodeId) return true;
21327
+ return false;
21328
+ }
21329
+ isCompletedHostedSession(record) {
21330
+ return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
21331
+ }
21332
+ async cleanupMeshSessions(args) {
21333
+ if (args.mode === "preserve") {
21334
+ return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
21335
+ }
21336
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
21337
+ const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
21338
+ const sessions = await this.deps.sessionHostControl.listSessions();
21339
+ const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
21340
+ const stoppedSessionIds = [];
21341
+ const deletedSessionIds = [];
21342
+ const skippedSessionIds = [];
21343
+ const errors = [];
21344
+ for (const record of matched) {
21345
+ const sessionId = String(record.sessionId);
21346
+ const completed = this.isCompletedHostedSession(record);
21347
+ try {
21348
+ if (args.mode === "stop") {
21349
+ if (!completed) {
21350
+ if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
21351
+ stoppedSessionIds.push(sessionId);
21352
+ } else {
21353
+ skippedSessionIds.push(sessionId);
21354
+ }
21355
+ continue;
21356
+ }
21357
+ if (args.mode === "delete_stopped") {
21358
+ if (completed) {
21359
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
21360
+ deletedSessionIds.push(sessionId);
21361
+ } else {
21362
+ skippedSessionIds.push(sessionId);
21363
+ }
21364
+ continue;
21365
+ }
21366
+ if (args.mode === "stop_and_delete") {
21367
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
21368
+ deletedSessionIds.push(sessionId);
21369
+ continue;
21370
+ }
21371
+ } catch (e) {
21372
+ errors.push({ sessionId, error: e?.message || String(e) });
21373
+ }
21374
+ }
21375
+ return {
21376
+ success: errors.length === 0,
21377
+ mode: args.mode,
21378
+ dryRun: args.dryRun === true,
21379
+ matchedCount: matched.length,
21380
+ stoppedSessionIds,
21381
+ deletedSessionIds,
21382
+ skippedSessionIds,
21383
+ ...errors.length ? { errors } : {}
21384
+ };
21385
+ }
20717
21386
  async traceSessionHostAction(action, args, run, summarizeResult) {
20718
21387
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20719
21388
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -20833,6 +21502,9 @@ var DaemonCommandRouter = class {
20833
21502
  async executeDaemonCommand(cmd, args) {
20834
21503
  switch (cmd) {
20835
21504
  // ─── CLI / ACP commands ───
21505
+ case "mesh_forward_event": {
21506
+ return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
21507
+ }
20836
21508
  case "launch_cli":
20837
21509
  case "stop_cli":
20838
21510
  case "set_cli_view_mode":
@@ -21377,7 +22049,26 @@ var DaemonCommandRouter = class {
21377
22049
  if (!name) return { success: false, error: "name required" };
21378
22050
  try {
21379
22051
  const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21380
- const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
22052
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
22053
+ return { success: true, mesh };
22054
+ } catch (e) {
22055
+ return { success: false, error: e.message };
22056
+ }
22057
+ }
22058
+ case "update_mesh": {
22059
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22060
+ if (!meshId) return { success: false, error: "meshId required" };
22061
+ try {
22062
+ const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22063
+ const patch = {};
22064
+ if (typeof args?.name === "string") patch.name = args.name;
22065
+ if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
22066
+ if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
22067
+ if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
22068
+ if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
22069
+ const mesh = updateMesh2(meshId, patch);
22070
+ if (!mesh) return { success: false, error: "Mesh not found" };
22071
+ this.inlineMeshCache.set(meshId, mesh);
21381
22072
  return { success: true, mesh };
21382
22073
  } catch (e) {
21383
22074
  return { success: false, error: e.message };
@@ -21401,21 +22092,164 @@ var DaemonCommandRouter = class {
21401
22092
  if (!workspace) return { success: false, error: "workspace required" };
21402
22093
  try {
21403
22094
  const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21404
- const node = addNode3(meshId, { workspace });
22095
+ const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
22096
+ const readOnly = args?.readOnly === true;
22097
+ const policy = {
22098
+ ...readOnly ? { readOnly: true } : {},
22099
+ ...providerPriority.length ? { providerPriority } : {}
22100
+ };
22101
+ const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
21405
22102
  if (!node) return { success: false, error: "Mesh not found" };
21406
22103
  return { success: true, node };
21407
22104
  } catch (e) {
21408
22105
  return { success: false, error: e.message };
21409
22106
  }
21410
22107
  }
22108
+ case "update_mesh_node": {
22109
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22110
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22111
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22112
+ try {
22113
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22114
+ const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
22115
+ if (Array.isArray(args?.providerPriority)) {
22116
+ const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
22117
+ delete policy.provider_priority;
22118
+ if (providerPriority.length) {
22119
+ policy.providerPriority = providerPriority;
22120
+ } else {
22121
+ delete policy.providerPriority;
22122
+ }
22123
+ }
22124
+ const node = updateNode2(meshId, nodeId, { policy });
22125
+ if (!node) return { success: false, error: "Mesh node not found" };
22126
+ return { success: true, node };
22127
+ } catch (e) {
22128
+ return { success: false, error: e.message };
22129
+ }
22130
+ }
22131
+ case "cleanup_mesh_sessions": {
22132
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22133
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22134
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22135
+ try {
22136
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22137
+ const mesh = meshRecord?.mesh;
22138
+ if (!mesh) return { success: false, error: "Mesh not found" };
22139
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22140
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
22141
+ const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
22142
+ const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
22143
+ const result = await this.cleanupMeshSessions({
22144
+ meshId,
22145
+ nodeId,
22146
+ node,
22147
+ mode,
22148
+ sessionIds,
22149
+ dryRun: args?.dryRun === true
22150
+ });
22151
+ return result;
22152
+ } catch (e) {
22153
+ return { success: false, error: e.message };
22154
+ }
22155
+ }
21411
22156
  case "remove_mesh_node": {
21412
22157
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21413
22158
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21414
22159
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21415
22160
  try {
21416
- const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21417
- const removed = removeNode3(meshId, nodeId);
21418
- return { success: true, removed };
22161
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22162
+ const mesh = meshRecord?.mesh;
22163
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22164
+ const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
22165
+ args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
22166
+ );
22167
+ let sessionCleanup;
22168
+ if (node && sessionCleanupMode !== "preserve") {
22169
+ sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
22170
+ if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
22171
+ }
22172
+ if (node?.isLocalWorktree && node.workspace) {
22173
+ try {
22174
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
22175
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
22176
+ if (repoRoot) {
22177
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22178
+ await removeWorktree2(repoRoot, node.workspace);
22179
+ }
22180
+ } catch (e) {
22181
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
22182
+ }
22183
+ }
22184
+ let removed = false;
22185
+ if (meshRecord?.inline) {
22186
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
22187
+ } else {
22188
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22189
+ removed = removeNode3(meshId, nodeId);
22190
+ }
22191
+ return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
22192
+ } catch (e) {
22193
+ return { success: false, error: e.message };
22194
+ }
22195
+ }
22196
+ case "clone_mesh_node": {
22197
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22198
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
22199
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
22200
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
22201
+ if (!meshId) return { success: false, error: "meshId required" };
22202
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
22203
+ if (!branch) return { success: false, error: "branch required" };
22204
+ try {
22205
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22206
+ const mesh = meshRecord?.mesh;
22207
+ if (!mesh) return { success: false, error: "Mesh not found" };
22208
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
22209
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
22210
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
22211
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22212
+ const result = await createWorktree2({
22213
+ repoRoot,
22214
+ branch,
22215
+ baseBranch,
22216
+ meshName: mesh.name
22217
+ });
22218
+ let node;
22219
+ if (meshRecord.inline) {
22220
+ const { randomUUID: randomUUID8 } = await import("crypto");
22221
+ node = {
22222
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
22223
+ workspace: result.worktreePath,
22224
+ repoRoot: result.worktreePath,
22225
+ daemonId: sourceNode.daemonId,
22226
+ userOverrides: { ...sourceNode.userOverrides || {} },
22227
+ policy: { ...sourceNode.policy || {} },
22228
+ isLocalWorktree: true,
22229
+ worktreeBranch: result.branch,
22230
+ clonedFromNodeId: sourceNodeId
22231
+ };
22232
+ this.updateInlineMeshNode(meshId, mesh, node);
22233
+ } else {
22234
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22235
+ node = addNode3(meshId, {
22236
+ workspace: result.worktreePath,
22237
+ repoRoot: result.worktreePath,
22238
+ daemonId: sourceNode.daemonId,
22239
+ userOverrides: { ...sourceNode.userOverrides || {} },
22240
+ isLocalWorktree: true,
22241
+ worktreeBranch: result.branch,
22242
+ clonedFromNodeId: sourceNodeId,
22243
+ policy: { ...sourceNode.policy || {} }
22244
+ });
22245
+ if (!node) return { success: false, error: "Failed to register worktree node" };
22246
+ }
22247
+ return {
22248
+ success: true,
22249
+ node,
22250
+ worktreePath: result.worktreePath,
22251
+ branch: result.branch
22252
+ };
21419
22253
  } catch (e) {
21420
22254
  return { success: false, error: e.message };
21421
22255
  }
@@ -21423,7 +22257,7 @@ var DaemonCommandRouter = class {
21423
22257
  // ─── Mesh Coordinator Launch ───
21424
22258
  case "launch_mesh_coordinator": {
21425
22259
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21426
- const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
22260
+ let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
21427
22261
  if (!meshId) return { success: false, error: "meshId required" };
21428
22262
  try {
21429
22263
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -21451,9 +22285,29 @@ var DaemonCommandRouter = class {
21451
22285
  }
21452
22286
  const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
21453
22287
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
22288
+ if (!cliType) {
22289
+ const resolved = await resolveProviderTypeFromPriority({
22290
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
22291
+ providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
22292
+ providerLoader: this.deps.providerLoader,
22293
+ onStatusChange: this.deps.onStatusChange
22294
+ });
22295
+ if (!resolved.providerType) {
22296
+ return {
22297
+ success: false,
22298
+ code: "mesh_coordinator_provider_priority_unusable",
22299
+ error: resolved.error || "No usable provider found from node providerPriority",
22300
+ meshId,
22301
+ cliType,
22302
+ workspace
22303
+ };
22304
+ }
22305
+ cliType = resolved.providerType;
22306
+ }
21454
22307
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21455
22308
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21456
22309
  provider: providerMeta,
22310
+ cliType,
21457
22311
  meshId,
21458
22312
  workspace
21459
22313
  });
@@ -21478,7 +22332,8 @@ var DaemonCommandRouter = class {
21478
22332
  meshCoordinatorSetup: coordinatorSetup
21479
22333
  };
21480
22334
  }
21481
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
22335
+ const configFormat = coordinatorSetup.configFormat;
22336
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21482
22337
  return {
21483
22338
  success: false,
21484
22339
  code: "mesh_coordinator_unsupported",
@@ -21488,44 +22343,93 @@ var DaemonCommandRouter = class {
21488
22343
  workspace
21489
22344
  };
21490
22345
  }
21491
- const { existsSync: existsSync22, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3 } = await import("fs");
21492
- const mcpConfigPath = coordinatorSetup.configPath;
21493
- const hadExistingMcpConfig = existsSync22(mcpConfigPath);
21494
- let existingMcpConfig = {};
21495
- if (hadExistingMcpConfig) {
21496
- try {
21497
- existingMcpConfig = JSON.parse(readFileSync15(mcpConfigPath, "utf-8"));
21498
- copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
21499
- } catch {
21500
- }
22346
+ let systemPrompt = "";
22347
+ try {
22348
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
22349
+ } catch (error) {
22350
+ const message = error?.message || String(error);
22351
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
22352
+ return {
22353
+ success: false,
22354
+ code: "mesh_coordinator_prompt_failed",
22355
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
22356
+ meshId,
22357
+ cliType,
22358
+ workspace
22359
+ };
21501
22360
  }
22361
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22362
+ const { dirname: dirname9 } = await import("path");
22363
+ const mcpConfigPath = coordinatorSetup.configPath;
22364
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
22365
+ const returnManualFallback = (message) => ({
22366
+ success: false,
22367
+ code: "mesh_coordinator_manual_mcp_setup_required",
22368
+ error: message,
22369
+ meshId,
22370
+ cliType,
22371
+ workspace,
22372
+ meshCoordinatorSetup: hermesManualFallback
22373
+ });
21502
22374
  const mcpServerEntry = {
21503
22375
  command: coordinatorSetup.mcpServer.command,
21504
22376
  args: coordinatorSetup.mcpServer.args
21505
22377
  };
21506
22378
  if (args?.inlineMesh) {
21507
22379
  mcpServerEntry.env = {
21508
- ADHDEV_INLINE_MESH: JSON.stringify(mesh)
22380
+ ADHDEV_INLINE_MESH: JSON.stringify(mesh),
22381
+ ADHDEV_MCP_TRANSPORT: "ipc"
21509
22382
  };
21510
22383
  }
22384
+ try {
22385
+ mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
22386
+ } catch (error) {
22387
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22388
+ LOG.error("MeshCoordinator", message);
22389
+ if (hermesManualFallback) return returnManualFallback(message);
22390
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
22391
+ }
22392
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
22393
+ let existingMcpConfig = {};
22394
+ if (hadExistingMcpConfig) {
22395
+ try {
22396
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
22397
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
22398
+ } catch (error) {
22399
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
22400
+ return {
22401
+ success: false,
22402
+ code: "mesh_coordinator_config_parse_failed",
22403
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
22404
+ };
22405
+ }
22406
+ }
22407
+ const mcpServersKey = getMcpServersKey(configFormat);
22408
+ const existingServers = existingMcpConfig[mcpServersKey];
21511
22409
  const mcpConfig = {
21512
22410
  ...existingMcpConfig,
21513
- mcpServers: {
21514
- ...existingMcpConfig.mcpServers || {},
22411
+ [mcpServersKey]: {
22412
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21515
22413
  [coordinatorSetup.serverName]: mcpServerEntry
21516
22414
  }
21517
22415
  };
21518
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21519
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21520
- let systemPrompt = "";
21521
22416
  try {
21522
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
21523
- } catch {
21524
- 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).`;
22417
+ writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22418
+ } catch (error) {
22419
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22420
+ LOG.error("MeshCoordinator", message);
22421
+ if (hermesManualFallback) return returnManualFallback(message);
22422
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21525
22423
  }
22424
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21526
22425
  const cliArgs = [];
22426
+ const launchEnv = {};
21527
22427
  if (systemPrompt) {
21528
- cliArgs.push("--append-system-prompt", systemPrompt);
22428
+ if (configFormat === "hermes_config_yaml") {
22429
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22430
+ } else {
22431
+ cliArgs.push("--append-system-prompt", systemPrompt);
22432
+ }
21529
22433
  }
21530
22434
  if (cliType === "claude-cli") {
21531
22435
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21534,6 +22438,7 @@ var DaemonCommandRouter = class {
21534
22438
  cliType,
21535
22439
  dir: workspace,
21536
22440
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22441
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21537
22442
  settings: {
21538
22443
  meshCoordinatorFor: meshId
21539
22444
  }
@@ -21713,6 +22618,12 @@ var DaemonStatusReporter = class {
21713
22618
  if (providerType) {
21714
22619
  payload.providerType = providerType;
21715
22620
  }
22621
+ if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
22622
+ payload.providerSessionId = event.providerSessionId.trim();
22623
+ }
22624
+ if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
22625
+ payload.workspaceName = event.workspaceName.trim();
22626
+ }
21716
22627
  if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
21717
22628
  payload.duration = event.duration;
21718
22629
  }
@@ -22960,7 +23871,10 @@ var ProviderInstanceManager = class {
22960
23871
  this.instances.get(id).dispose();
22961
23872
  }
22962
23873
  this.instances.set(id, instance);
22963
- await instance.init(context);
23874
+ await instance.init({
23875
+ ...context,
23876
+ emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
23877
+ });
22964
23878
  }
22965
23879
  /**
22966
23880
  * Instance remove
@@ -23122,6 +24036,17 @@ var ProviderInstanceManager = class {
23122
24036
  onEvent(listener) {
23123
24037
  this.eventListeners.push(listener);
23124
24038
  }
24039
+ emitProviderEvent(providerType, instanceId, event) {
24040
+ const payload = {
24041
+ ...event,
24042
+ providerType,
24043
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
24044
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
24045
+ };
24046
+ for (const listener of this.eventListeners) {
24047
+ listener(payload);
24048
+ }
24049
+ }
23125
24050
  emitPendingEvents(providerType, state, extra = {}) {
23126
24051
  for (const event of state.pendingEvents) {
23127
24052
  for (const listener of this.eventListeners) {
@@ -23194,11 +24119,11 @@ var ProviderInstanceManager = class {
23194
24119
 
23195
24120
  // src/providers/version-archive.ts
23196
24121
  import * as fs11 from "fs";
23197
- import * as path21 from "path";
23198
- import * as os19 from "os";
24122
+ import * as path22 from "path";
24123
+ import * as os20 from "os";
23199
24124
  import { execSync as execSync5 } from "child_process";
23200
24125
  import { platform as platform8 } from "os";
23201
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
24126
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23202
24127
  var MAX_ENTRIES_PER_PROVIDER = 20;
23203
24128
  var VersionArchive = class {
23204
24129
  history = {};
@@ -23245,7 +24170,7 @@ var VersionArchive = class {
23245
24170
  }
23246
24171
  save() {
23247
24172
  try {
23248
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
24173
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23249
24174
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23250
24175
  } catch {
23251
24176
  }
@@ -23301,8 +24226,8 @@ function getVersion(binary, versionCommand) {
23301
24226
  function checkPathExists2(paths) {
23302
24227
  for (const p of paths) {
23303
24228
  if (p.includes("*")) {
23304
- const home = os19.homedir();
23305
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
24229
+ const home = os20.homedir();
24230
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23306
24231
  if (fs11.existsSync(resolved)) return resolved;
23307
24232
  } else {
23308
24233
  if (fs11.existsSync(p)) return p;
@@ -23312,7 +24237,7 @@ function checkPathExists2(paths) {
23312
24237
  }
23313
24238
  function getMacAppVersion(appPath) {
23314
24239
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
23315
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
24240
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23316
24241
  if (!fs11.existsSync(plistPath)) return null;
23317
24242
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23318
24243
  return raw || null;
@@ -23338,7 +24263,7 @@ async function detectAllVersions(loader, archive) {
23338
24263
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23339
24264
  let resolvedBin = cliBin;
23340
24265
  if (!resolvedBin && appPath && currentOs === "darwin") {
23341
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24266
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23342
24267
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23343
24268
  }
23344
24269
  info.installed = !!(appPath || resolvedBin);
@@ -23379,7 +24304,7 @@ async function detectAllVersions(loader, archive) {
23379
24304
  // src/daemon/dev-server.ts
23380
24305
  import * as http2 from "http";
23381
24306
  import * as fs15 from "fs";
23382
- import * as path25 from "path";
24307
+ import * as path26 from "path";
23383
24308
  init_config();
23384
24309
 
23385
24310
  // src/daemon/scaffold-template.ts
@@ -23731,7 +24656,7 @@ init_logger();
23731
24656
  // src/daemon/dev-cdp-handlers.ts
23732
24657
  init_logger();
23733
24658
  import * as fs12 from "fs";
23734
- import * as path22 from "path";
24659
+ import * as path23 from "path";
23735
24660
  async function handleCdpEvaluate(ctx, req, res) {
23736
24661
  const body = await ctx.readBody(req);
23737
24662
  const { expression, timeout, ideType } = body;
@@ -23909,17 +24834,17 @@ async function handleScriptHints(ctx, type, _req, res) {
23909
24834
  return;
23910
24835
  }
23911
24836
  let scriptsPath = "";
23912
- const directScripts = path22.join(dir, "scripts.js");
24837
+ const directScripts = path23.join(dir, "scripts.js");
23913
24838
  if (fs12.existsSync(directScripts)) {
23914
24839
  scriptsPath = directScripts;
23915
24840
  } else {
23916
- const scriptsDir = path22.join(dir, "scripts");
24841
+ const scriptsDir = path23.join(dir, "scripts");
23917
24842
  if (fs12.existsSync(scriptsDir)) {
23918
24843
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
23919
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
24844
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
23920
24845
  }).sort().reverse();
23921
24846
  for (const ver of versions) {
23922
- const p = path22.join(scriptsDir, ver, "scripts.js");
24847
+ const p = path23.join(scriptsDir, ver, "scripts.js");
23923
24848
  if (fs12.existsSync(p)) {
23924
24849
  scriptsPath = p;
23925
24850
  break;
@@ -24748,7 +25673,7 @@ async function handleDomContext(ctx, type, req, res) {
24748
25673
 
24749
25674
  // src/daemon/dev-cli-debug.ts
24750
25675
  import * as fs13 from "fs";
24751
- import * as path23 from "path";
25676
+ import * as path24 from "path";
24752
25677
  function slugifyFixtureName(value) {
24753
25678
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24754
25679
  return normalized || `fixture-${Date.now()}`;
@@ -24758,11 +25683,11 @@ function getCliFixtureDir(ctx, type) {
24758
25683
  if (!providerDir) {
24759
25684
  throw new Error(`Provider directory not found for '${type}'`);
24760
25685
  }
24761
- return path23.join(providerDir, "fixtures");
25686
+ return path24.join(providerDir, "fixtures");
24762
25687
  }
24763
25688
  function readCliFixture(ctx, type, name) {
24764
25689
  const fixtureDir = getCliFixtureDir(ctx, type);
24765
- const filePath = path23.join(fixtureDir, `${name}.json`);
25690
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24766
25691
  if (!fs13.existsSync(filePath)) {
24767
25692
  throw new Error(`Fixture not found: ${filePath}`);
24768
25693
  }
@@ -25529,7 +26454,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25529
26454
  },
25530
26455
  notes: typeof body?.notes === "string" ? body.notes : void 0
25531
26456
  };
25532
- const filePath = path23.join(fixtureDir, `${name}.json`);
26457
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25533
26458
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25534
26459
  ctx.json(res, 200, {
25535
26460
  saved: true,
@@ -25553,7 +26478,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25553
26478
  return;
25554
26479
  }
25555
26480
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
25556
- const fullPath = path23.join(fixtureDir, file);
26481
+ const fullPath = path24.join(fixtureDir, file);
25557
26482
  try {
25558
26483
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25559
26484
  return {
@@ -25689,8 +26614,8 @@ async function handleCliRaw(ctx, req, res) {
25689
26614
 
25690
26615
  // src/daemon/dev-auto-implement.ts
25691
26616
  import * as fs14 from "fs";
25692
- import * as path24 from "path";
25693
- import * as os20 from "os";
26617
+ import * as path25 from "path";
26618
+ import * as os21 from "os";
25694
26619
  function getAutoImplPid(ctx) {
25695
26620
  const pid = ctx.autoImplProcess?.pid;
25696
26621
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25739,22 +26664,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25739
26664
  if (!fs14.existsSync(scriptsDir)) return null;
25740
26665
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25741
26666
  try {
25742
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
26667
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25743
26668
  } catch {
25744
26669
  return false;
25745
26670
  }
25746
26671
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25747
26672
  if (versions.length === 0) return null;
25748
- return path24.join(scriptsDir, versions[0]);
26673
+ return path25.join(scriptsDir, versions[0]);
25749
26674
  }
25750
26675
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25751
- const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25752
- const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25753
- const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25754
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
26676
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26677
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26678
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26679
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25755
26680
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25756
26681
  }
25757
- if (path24.basename(desiredDir) !== type) {
26682
+ if (path25.basename(desiredDir) !== type) {
25758
26683
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25759
26684
  }
25760
26685
  const sourceDir = ctx.findProviderDir(type);
@@ -25762,11 +26687,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25762
26687
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25763
26688
  }
25764
26689
  if (!fs14.existsSync(desiredDir)) {
25765
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
26690
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25766
26691
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25767
26692
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25768
26693
  }
25769
- const providerJson = path24.join(desiredDir, "provider.json");
26694
+ const providerJson = path25.join(desiredDir, "provider.json");
25770
26695
  if (!fs14.existsSync(providerJson)) {
25771
26696
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25772
26697
  }
@@ -25777,13 +26702,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25777
26702
  const refDir = ctx.findProviderDir(referenceType);
25778
26703
  if (!refDir || !fs14.existsSync(refDir)) return {};
25779
26704
  const referenceScripts = {};
25780
- const scriptsDir = path24.join(refDir, "scripts");
26705
+ const scriptsDir = path25.join(refDir, "scripts");
25781
26706
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25782
26707
  if (!latestDir) return referenceScripts;
25783
26708
  for (const file of fs14.readdirSync(latestDir)) {
25784
26709
  if (!file.endsWith(".js")) continue;
25785
26710
  try {
25786
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
26711
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25787
26712
  } catch {
25788
26713
  }
25789
26714
  }
@@ -25891,9 +26816,9 @@ async function handleAutoImplement(ctx, type, req, res) {
25891
26816
  });
25892
26817
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
25893
26818
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
25894
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
26819
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
25895
26820
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
25896
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26821
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25897
26822
  fs14.writeFileSync(promptFile, prompt, "utf-8");
25898
26823
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
25899
26824
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26046,7 +26971,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26046
26971
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26047
26972
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26048
26973
  let shellCmd;
26049
- const isWin = os20.platform() === "win32";
26974
+ const isWin = os21.platform() === "win32";
26050
26975
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26051
26976
  const promptMode = autoImpl?.promptMode ?? "stdin";
26052
26977
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26085,7 +27010,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26085
27010
  try {
26086
27011
  const pty = __require("node-pty");
26087
27012
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26088
- const isWin2 = os20.platform() === "win32";
27013
+ const isWin2 = os21.platform() === "win32";
26089
27014
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26090
27015
  name: "xterm-256color",
26091
27016
  cols: 120,
@@ -26325,7 +27250,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26325
27250
  setMode: "set_mode.js"
26326
27251
  };
26327
27252
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26328
- const scriptsDir = path24.join(providerDir, "scripts");
27253
+ const scriptsDir = path25.join(providerDir, "scripts");
26329
27254
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26330
27255
  if (latestScriptsDir) {
26331
27256
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26336,7 +27261,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26336
27261
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26337
27262
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26338
27263
  try {
26339
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27264
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26340
27265
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26341
27266
  lines.push("```javascript");
26342
27267
  lines.push(content);
@@ -26353,7 +27278,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26353
27278
  lines.push("");
26354
27279
  for (const file of refFiles) {
26355
27280
  try {
26356
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27281
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26357
27282
  lines.push(`### \`${file}\` \u{1F512}`);
26358
27283
  lines.push("```javascript");
26359
27284
  lines.push(content);
@@ -26394,10 +27319,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26394
27319
  lines.push("");
26395
27320
  }
26396
27321
  }
26397
- const docsDir = path24.join(providerDir, "../../docs");
27322
+ const docsDir = path25.join(providerDir, "../../docs");
26398
27323
  const loadGuide = (name) => {
26399
27324
  try {
26400
- const p = path24.join(docsDir, name);
27325
+ const p = path25.join(docsDir, name);
26401
27326
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26402
27327
  } catch {
26403
27328
  }
@@ -26634,7 +27559,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26634
27559
  parseApproval: "parse_approval.js"
26635
27560
  };
26636
27561
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26637
- const scriptsDir = path24.join(providerDir, "scripts");
27562
+ const scriptsDir = path25.join(providerDir, "scripts");
26638
27563
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26639
27564
  if (latestScriptsDir) {
26640
27565
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26646,7 +27571,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26646
27571
  if (!file.endsWith(".js")) continue;
26647
27572
  if (!targetFileNames.has(file)) continue;
26648
27573
  try {
26649
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27574
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26650
27575
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26651
27576
  lines.push("```javascript");
26652
27577
  lines.push(content);
@@ -26662,7 +27587,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26662
27587
  lines.push("");
26663
27588
  for (const file of refFiles) {
26664
27589
  try {
26665
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27590
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26666
27591
  lines.push(`### \`${file}\` \u{1F512}`);
26667
27592
  lines.push("```javascript");
26668
27593
  lines.push(content);
@@ -26695,10 +27620,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26695
27620
  lines.push("");
26696
27621
  }
26697
27622
  }
26698
- const docsDir = path24.join(providerDir, "../../docs");
27623
+ const docsDir = path25.join(providerDir, "../../docs");
26699
27624
  const loadGuide = (name) => {
26700
27625
  try {
26701
- const p = path24.join(docsDir, name);
27626
+ const p = path25.join(docsDir, name);
26702
27627
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26703
27628
  } catch {
26704
27629
  }
@@ -27145,8 +28070,8 @@ var DevServer = class _DevServer {
27145
28070
  }
27146
28071
  getEndpointList() {
27147
28072
  return this.routes.map((r) => {
27148
- const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27149
- return `${r.method.padEnd(5)} ${path26}`;
28073
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28074
+ return `${r.method.padEnd(5)} ${path27}`;
27150
28075
  });
27151
28076
  }
27152
28077
  async start(port = DEV_SERVER_PORT) {
@@ -27434,12 +28359,12 @@ var DevServer = class _DevServer {
27434
28359
  // ─── DevConsole SPA ───
27435
28360
  getConsoleDistDir() {
27436
28361
  const candidates = [
27437
- path25.resolve(__dirname, "../../web-devconsole/dist"),
27438
- path25.resolve(__dirname, "../../../web-devconsole/dist"),
27439
- path25.join(process.cwd(), "packages/web-devconsole/dist")
28362
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
28363
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
28364
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27440
28365
  ];
27441
28366
  for (const dir of candidates) {
27442
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
28367
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27443
28368
  }
27444
28369
  return null;
27445
28370
  }
@@ -27449,7 +28374,7 @@ var DevServer = class _DevServer {
27449
28374
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27450
28375
  return;
27451
28376
  }
27452
- const htmlPath = path25.join(distDir, "index.html");
28377
+ const htmlPath = path26.join(distDir, "index.html");
27453
28378
  try {
27454
28379
  const html = fs15.readFileSync(htmlPath, "utf-8");
27455
28380
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27474,15 +28399,15 @@ var DevServer = class _DevServer {
27474
28399
  this.json(res, 404, { error: "Not found" });
27475
28400
  return;
27476
28401
  }
27477
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27478
- const filePath = path25.join(distDir, safePath);
28402
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28403
+ const filePath = path26.join(distDir, safePath);
27479
28404
  if (!filePath.startsWith(distDir)) {
27480
28405
  this.json(res, 403, { error: "Forbidden" });
27481
28406
  return;
27482
28407
  }
27483
28408
  try {
27484
28409
  const content = fs15.readFileSync(filePath);
27485
- const ext = path25.extname(filePath);
28410
+ const ext = path26.extname(filePath);
27486
28411
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27487
28412
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27488
28413
  res.end(content);
@@ -27595,9 +28520,9 @@ var DevServer = class _DevServer {
27595
28520
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27596
28521
  if (entry.isDirectory()) {
27597
28522
  files.push({ path: rel, size: 0, type: "dir" });
27598
- scan(path25.join(d, entry.name), rel);
28523
+ scan(path26.join(d, entry.name), rel);
27599
28524
  } else {
27600
- const stat2 = fs15.statSync(path25.join(d, entry.name));
28525
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27601
28526
  files.push({ path: rel, size: stat2.size, type: "file" });
27602
28527
  }
27603
28528
  }
@@ -27620,7 +28545,7 @@ var DevServer = class _DevServer {
27620
28545
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27621
28546
  return;
27622
28547
  }
27623
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28548
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27624
28549
  if (!fullPath.startsWith(dir)) {
27625
28550
  this.json(res, 403, { error: "Forbidden" });
27626
28551
  return;
@@ -27645,14 +28570,14 @@ var DevServer = class _DevServer {
27645
28570
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27646
28571
  return;
27647
28572
  }
27648
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28573
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27649
28574
  if (!fullPath.startsWith(dir)) {
27650
28575
  this.json(res, 403, { error: "Forbidden" });
27651
28576
  return;
27652
28577
  }
27653
28578
  try {
27654
28579
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27655
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28580
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27656
28581
  fs15.writeFileSync(fullPath, content, "utf-8");
27657
28582
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27658
28583
  this.providerLoader.reload();
@@ -27669,7 +28594,7 @@ var DevServer = class _DevServer {
27669
28594
  return;
27670
28595
  }
27671
28596
  for (const name of ["scripts.js", "provider.json"]) {
27672
- const p = path25.join(dir, name);
28597
+ const p = path26.join(dir, name);
27673
28598
  if (fs15.existsSync(p)) {
27674
28599
  const source = fs15.readFileSync(p, "utf-8");
27675
28600
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27690,8 +28615,8 @@ var DevServer = class _DevServer {
27690
28615
  this.json(res, 404, { error: `Provider not found: ${type}` });
27691
28616
  return;
27692
28617
  }
27693
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27694
- const targetPath = path25.join(dir, target);
28618
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28619
+ const targetPath = path26.join(dir, target);
27695
28620
  try {
27696
28621
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27697
28622
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -27838,7 +28763,7 @@ var DevServer = class _DevServer {
27838
28763
  }
27839
28764
  let targetDir;
27840
28765
  targetDir = this.providerLoader.getUserProviderDir(category, type);
27841
- const jsonPath = path25.join(targetDir, "provider.json");
28766
+ const jsonPath = path26.join(targetDir, "provider.json");
27842
28767
  if (fs15.existsSync(jsonPath)) {
27843
28768
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
27844
28769
  return;
@@ -27850,8 +28775,8 @@ var DevServer = class _DevServer {
27850
28775
  const createdFiles = ["provider.json"];
27851
28776
  if (result.files) {
27852
28777
  for (const [relPath, content] of Object.entries(result.files)) {
27853
- const fullPath = path25.join(targetDir, relPath);
27854
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28778
+ const fullPath = path26.join(targetDir, relPath);
28779
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27855
28780
  fs15.writeFileSync(fullPath, content, "utf-8");
27856
28781
  createdFiles.push(relPath);
27857
28782
  }
@@ -27904,22 +28829,22 @@ var DevServer = class _DevServer {
27904
28829
  if (!fs15.existsSync(scriptsDir)) return null;
27905
28830
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
27906
28831
  try {
27907
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
28832
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
27908
28833
  } catch {
27909
28834
  return false;
27910
28835
  }
27911
28836
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
27912
28837
  if (versions.length === 0) return null;
27913
- return path25.join(scriptsDir, versions[0]);
28838
+ return path26.join(scriptsDir, versions[0]);
27914
28839
  }
27915
28840
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
27916
- const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
27917
- const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
27918
- const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
27919
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
28841
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
28842
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
28843
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
28844
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
27920
28845
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
27921
28846
  }
27922
- if (path25.basename(desiredDir) !== type) {
28847
+ if (path26.basename(desiredDir) !== type) {
27923
28848
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
27924
28849
  }
27925
28850
  const sourceDir = this.findProviderDir(type);
@@ -27927,11 +28852,11 @@ var DevServer = class _DevServer {
27927
28852
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
27928
28853
  }
27929
28854
  if (!fs15.existsSync(desiredDir)) {
27930
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
28855
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
27931
28856
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
27932
28857
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
27933
28858
  }
27934
- const providerJson = path25.join(desiredDir, "provider.json");
28859
+ const providerJson = path26.join(desiredDir, "provider.json");
27935
28860
  if (!fs15.existsSync(providerJson)) {
27936
28861
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
27937
28862
  }
@@ -27967,7 +28892,7 @@ var DevServer = class _DevServer {
27967
28892
  setMode: "set_mode.js"
27968
28893
  };
27969
28894
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27970
- const scriptsDir = path25.join(providerDir, "scripts");
28895
+ const scriptsDir = path26.join(providerDir, "scripts");
27971
28896
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
27972
28897
  if (latestScriptsDir) {
27973
28898
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27978,7 +28903,7 @@ var DevServer = class _DevServer {
27978
28903
  for (const file of fs15.readdirSync(latestScriptsDir)) {
27979
28904
  if (file.endsWith(".js") && targetFileNames.has(file)) {
27980
28905
  try {
27981
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28906
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27982
28907
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27983
28908
  lines.push("```javascript");
27984
28909
  lines.push(content);
@@ -27995,7 +28920,7 @@ var DevServer = class _DevServer {
27995
28920
  lines.push("");
27996
28921
  for (const file of refFiles) {
27997
28922
  try {
27998
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28923
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27999
28924
  lines.push(`### \`${file}\` \u{1F512}`);
28000
28925
  lines.push("```javascript");
28001
28926
  lines.push(content);
@@ -28036,10 +28961,10 @@ var DevServer = class _DevServer {
28036
28961
  lines.push("");
28037
28962
  }
28038
28963
  }
28039
- const docsDir = path25.join(providerDir, "../../docs");
28964
+ const docsDir = path26.join(providerDir, "../../docs");
28040
28965
  const loadGuide = (name) => {
28041
28966
  try {
28042
- const p = path25.join(docsDir, name);
28967
+ const p = path26.join(docsDir, name);
28043
28968
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28044
28969
  } catch {
28045
28970
  }
@@ -28213,7 +29138,7 @@ var DevServer = class _DevServer {
28213
29138
  parseApproval: "parse_approval.js"
28214
29139
  };
28215
29140
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28216
- const scriptsDir = path25.join(providerDir, "scripts");
29141
+ const scriptsDir = path26.join(providerDir, "scripts");
28217
29142
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28218
29143
  if (latestScriptsDir) {
28219
29144
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28225,7 +29150,7 @@ var DevServer = class _DevServer {
28225
29150
  if (!file.endsWith(".js")) continue;
28226
29151
  if (!targetFileNames.has(file)) continue;
28227
29152
  try {
28228
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29153
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28229
29154
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28230
29155
  lines.push("```javascript");
28231
29156
  lines.push(content);
@@ -28241,7 +29166,7 @@ var DevServer = class _DevServer {
28241
29166
  lines.push("");
28242
29167
  for (const file of refFiles) {
28243
29168
  try {
28244
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29169
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28245
29170
  lines.push(`### \`${file}\` \u{1F512}`);
28246
29171
  lines.push("```javascript");
28247
29172
  lines.push(content);
@@ -28274,10 +29199,10 @@ var DevServer = class _DevServer {
28274
29199
  lines.push("");
28275
29200
  }
28276
29201
  }
28277
- const docsDir = path25.join(providerDir, "../../docs");
29202
+ const docsDir = path26.join(providerDir, "../../docs");
28278
29203
  const loadGuide = (name) => {
28279
29204
  try {
28280
- const p = path25.join(docsDir, name);
29205
+ const p = path26.join(docsDir, name);
28281
29206
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28282
29207
  } catch {
28283
29208
  }
@@ -29282,48 +30207,6 @@ var SessionRegistry = class {
29282
30207
  // src/boot/daemon-lifecycle.ts
29283
30208
  init_logger();
29284
30209
  init_config();
29285
-
29286
- // src/mesh/mesh-events.ts
29287
- init_mesh_config();
29288
- init_logger();
29289
- function setupMeshEventForwarding(components) {
29290
- components.instanceManager.onEvent((event) => {
29291
- if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
29292
- const instanceId = event.instanceId;
29293
- if (!instanceId) return;
29294
- const sourceInstance = components.instanceManager.getInstance(instanceId);
29295
- if (!sourceInstance || sourceInstance.category !== "cli") return;
29296
- const state = sourceInstance.getState();
29297
- const workspace = state.workspace;
29298
- if (!workspace) return;
29299
- const mesh = getMeshByRepo(workspace);
29300
- if (!mesh) return;
29301
- const allInstances = components.instanceManager.getByCategory("cli");
29302
- const coordinatorInstances = allInstances.filter((inst) => {
29303
- const instState = inst.getState();
29304
- if (instState.settings?.meshCoordinatorFor !== mesh.id) return false;
29305
- if (instState.instanceId === instanceId) return false;
29306
- return true;
29307
- });
29308
- if (coordinatorInstances.length === 0) return;
29309
- const targetNode = mesh.nodes.find((n) => n.workspace === workspace);
29310
- const nodeLabel = targetNode ? `Node '${targetNode.id}'` : `Agent at ${workspace}`;
29311
- let messageText = "";
29312
- if (event.event === "agent:generating_completed") {
29313
- messageText = `[System] ${nodeLabel} has completed its task and is now idle. You may use mesh_read_chat to review its progress.`;
29314
- } else if (event.event === "agent:waiting_approval") {
29315
- messageText = `[System] ${nodeLabel} is waiting for approval to proceed. You may use mesh_read_chat and mesh_approve to handle it.`;
29316
- }
29317
- if (!messageText) return;
29318
- for (const coord of coordinatorInstances) {
29319
- const coordState = coord.getState();
29320
- LOG.info("MeshEvents", `Forwarding event from ${workspace} to coordinator ${coordState.instanceId}`);
29321
- coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
29322
- }
29323
- });
29324
- }
29325
-
29326
- // src/boot/daemon-lifecycle.ts
29327
30210
  async function initDaemonComponents(config) {
29328
30211
  installGlobalInterceptor();
29329
30212
  const appConfig = loadConfig();
@@ -29629,6 +30512,7 @@ export {
29629
30512
  createGitWorkspaceMonitor,
29630
30513
  createInteractionId,
29631
30514
  createMesh,
30515
+ createWorktree,
29632
30516
  deleteMesh,
29633
30517
  detectAllVersions,
29634
30518
  detectCLIs,
@@ -29681,6 +30565,7 @@ export {
29681
30565
  launchWithCdp,
29682
30566
  listHostedCliRuntimes,
29683
30567
  listMeshes,
30568
+ listWorktrees,
29684
30569
  loadConfig,
29685
30570
  loadState,
29686
30571
  logCommand,
@@ -29700,6 +30585,7 @@ export {
29700
30585
  normalizeSessionModalFields,
29701
30586
  parsePorcelainV2Status,
29702
30587
  parseProviderSourceConfigUpdate,
30588
+ parseWorktreeListOutput,
29703
30589
  partitionSessionHostDiagnosticsSessions,
29704
30590
  partitionSessionHostRecords,
29705
30591
  prepareSessionChatTailUpdate,
@@ -29709,6 +30595,7 @@ export {
29709
30595
  recordDebugTrace,
29710
30596
  registerExtensionProviders,
29711
30597
  removeNode,
30598
+ removeWorktree,
29712
30599
  resetConfig,
29713
30600
  resetDebugRuntimeConfig,
29714
30601
  resetState,
@@ -29718,6 +30605,7 @@ export {
29718
30605
  resolveGitRepository,
29719
30606
  resolveSessionHostAppName,
29720
30607
  resolveSessionHostAppNameResolution,
30608
+ resolveWorktreePath,
29721
30609
  runAsyncBatch,
29722
30610
  runGit,
29723
30611
  saveConfig,