@adhdev/daemon-core 0.9.76-rc.3 → 0.9.76-rc.31

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 (42) 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 +4 -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 +1058 -384
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +1085 -416
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/mesh/coordinator-prompt.d.ts +1 -0
  15. package/dist/providers/cli-provider-instance.d.ts +3 -0
  16. package/dist/providers/provider-instance-manager.d.ts +1 -0
  17. package/dist/providers/provider-instance.d.ts +2 -0
  18. package/dist/repo-mesh-types.d.ts +6 -0
  19. package/dist/shared-types.d.ts +22 -1
  20. package/package.json +3 -4
  21. package/src/cli-adapters/provider-cli-adapter.ts +6 -3
  22. package/src/cli-adapters/provider-cli-runtime.ts +3 -2
  23. package/src/commands/chat-commands.ts +50 -5
  24. package/src/commands/cli-manager.ts +78 -5
  25. package/src/commands/handler.ts +13 -4
  26. package/src/commands/mesh-coordinator.ts +149 -6
  27. package/src/commands/router.ts +319 -32
  28. package/src/config/mesh-config.ts +6 -0
  29. package/src/git/git-commands.ts +5 -1
  30. package/src/git/git-types.ts +1 -0
  31. package/src/git/git-worktree.ts +214 -0
  32. package/src/git/index.ts +14 -0
  33. package/src/mesh/coordinator-prompt.ts +25 -10
  34. package/src/mesh/mesh-events.ts +40 -17
  35. package/src/providers/cli-provider-instance.d.ts +2 -0
  36. package/src/providers/cli-provider-instance.ts +55 -7
  37. package/src/providers/provider-instance-manager.ts +20 -1
  38. package/src/providers/provider-instance.ts +2 -0
  39. package/src/repo-mesh-types.ts +6 -0
  40. package/src/shared-types.ts +24 -1
  41. package/src/status/builders.ts +17 -12
  42. package/src/status/reporter.ts +6 -0
package/dist/index.mjs CHANGED
@@ -41,6 +41,134 @@ var init_repo_mesh_types = __esm({
41
41
  }
42
42
  });
43
43
 
44
+ // src/git/git-worktree.ts
45
+ var git_worktree_exports = {};
46
+ __export(git_worktree_exports, {
47
+ createWorktree: () => createWorktree,
48
+ listWorktrees: () => listWorktrees,
49
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
50
+ removeWorktree: () => removeWorktree,
51
+ resolveWorktreePath: () => resolveWorktreePath
52
+ });
53
+ import * as path4 from "path";
54
+ import { mkdir } from "fs/promises";
55
+ import { existsSync } from "fs";
56
+ import { execFile as execFile2 } from "child_process";
57
+ import { promisify as promisify2 } from "util";
58
+ function resolveWorktreePath(repoRoot, meshName, branch) {
59
+ const safeBranch = branch.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
60
+ const safeMeshName = meshName.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
61
+ const parentDir = path4.dirname(repoRoot);
62
+ return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
63
+ }
64
+ async function createWorktree(opts) {
65
+ const { repoRoot, branch, baseBranch, meshName } = opts;
66
+ const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
67
+ if (existsSync(targetDir)) {
68
+ throw new Error(`Worktree target directory already exists: ${targetDir}`);
69
+ }
70
+ await mkdir(path4.dirname(targetDir), { recursive: true });
71
+ const args = ["worktree", "add", targetDir, "-b", branch];
72
+ if (baseBranch) {
73
+ args.push(baseBranch);
74
+ }
75
+ try {
76
+ await execFileAsync2("git", args, {
77
+ cwd: repoRoot,
78
+ encoding: "utf8",
79
+ timeout: GIT_TIMEOUT_MS,
80
+ maxBuffer: GIT_MAX_BUFFER,
81
+ windowsHide: true
82
+ });
83
+ } catch (error) {
84
+ const stderr = typeof error.stderr === "string" ? error.stderr : "";
85
+ if (/already exists/i.test(stderr)) {
86
+ throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
87
+ }
88
+ throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
89
+ }
90
+ return {
91
+ success: true,
92
+ worktreePath: targetDir,
93
+ branch
94
+ };
95
+ }
96
+ async function removeWorktree(repoRoot, worktreePath) {
97
+ if (!existsSync(worktreePath)) {
98
+ await pruneWorktrees(repoRoot);
99
+ return { success: true, removedPath: worktreePath };
100
+ }
101
+ try {
102
+ await execFileAsync2("git", ["worktree", "remove", worktreePath, "--force"], {
103
+ cwd: repoRoot,
104
+ encoding: "utf8",
105
+ timeout: GIT_TIMEOUT_MS,
106
+ maxBuffer: GIT_MAX_BUFFER,
107
+ windowsHide: true
108
+ });
109
+ } catch (error) {
110
+ const stderr = typeof error.stderr === "string" ? error.stderr : "";
111
+ throw new Error(`git worktree remove failed: ${stderr.trim() || error.message}`);
112
+ }
113
+ return { success: true, removedPath: worktreePath };
114
+ }
115
+ async function listWorktrees(repoRoot) {
116
+ const { stdout } = await execFileAsync2("git", ["worktree", "list", "--porcelain"], {
117
+ cwd: repoRoot,
118
+ encoding: "utf8",
119
+ timeout: GIT_TIMEOUT_MS,
120
+ maxBuffer: GIT_MAX_BUFFER,
121
+ windowsHide: true
122
+ });
123
+ return parseWorktreeListOutput(stdout);
124
+ }
125
+ function parseWorktreeListOutput(output) {
126
+ const entries = [];
127
+ const blocks = output.trim().split(/\n\n+/);
128
+ for (const block of blocks) {
129
+ if (!block.trim()) continue;
130
+ const lines = block.trim().split("\n");
131
+ const entry = { path: "", head: "", branch: null, bare: false };
132
+ for (const line of lines) {
133
+ if (line.startsWith("worktree ")) {
134
+ entry.path = line.slice("worktree ".length).trim();
135
+ } else if (line.startsWith("HEAD ")) {
136
+ entry.head = line.slice("HEAD ".length).trim();
137
+ } else if (line.startsWith("branch ")) {
138
+ const ref = line.slice("branch ".length).trim();
139
+ entry.branch = ref.replace(/^refs\/heads\//, "");
140
+ } else if (line === "bare") {
141
+ entry.bare = true;
142
+ }
143
+ }
144
+ if (entry.path) {
145
+ entries.push(entry);
146
+ }
147
+ }
148
+ return entries;
149
+ }
150
+ async function pruneWorktrees(repoRoot) {
151
+ try {
152
+ await execFileAsync2("git", ["worktree", "prune"], {
153
+ cwd: repoRoot,
154
+ encoding: "utf8",
155
+ timeout: GIT_TIMEOUT_MS,
156
+ windowsHide: true
157
+ });
158
+ } catch {
159
+ }
160
+ }
161
+ var execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER;
162
+ var init_git_worktree = __esm({
163
+ "src/git/git-worktree.ts"() {
164
+ "use strict";
165
+ execFileAsync2 = promisify2(execFile2);
166
+ WORKTREE_DIR_NAME = ".adhdev-worktrees";
167
+ GIT_TIMEOUT_MS = 3e4;
168
+ GIT_MAX_BUFFER = 4 * 1024 * 1024;
169
+ }
170
+ });
171
+
44
172
  // src/config/config.ts
45
173
  var config_exports = {};
46
174
  __export(config_exports, {
@@ -56,8 +184,8 @@ __export(config_exports, {
56
184
  updateConfig: () => updateConfig
57
185
  });
58
186
  import { homedir } from "os";
59
- import { join } from "path";
60
- import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
187
+ import { join as join2 } from "path";
188
+ import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
61
189
  import { randomUUID } from "crypto";
62
190
  function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
63
191
  if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
@@ -151,18 +279,18 @@ function ensureMachineId(config) {
151
279
  };
152
280
  }
153
281
  function getConfigDir() {
154
- const dir = join(homedir(), ".adhdev");
155
- if (!existsSync(dir)) {
282
+ const dir = join2(homedir(), ".adhdev");
283
+ if (!existsSync2(dir)) {
156
284
  mkdirSync(dir, { recursive: true });
157
285
  }
158
286
  return dir;
159
287
  }
160
288
  function getConfigPath() {
161
- return join(getConfigDir(), "config.json");
289
+ return join2(getConfigDir(), "config.json");
162
290
  }
163
291
  function migrateStateToStateFile(raw) {
164
- const statePath = join(getConfigDir(), "state.json");
165
- if (existsSync(statePath)) return;
292
+ const statePath = join2(getConfigDir(), "state.json");
293
+ if (existsSync2(statePath)) return;
166
294
  const recentActivity = Array.isArray(raw.recentActivity) ? raw.recentActivity : [];
167
295
  const savedProviderSessions = Array.isArray(raw.savedProviderSessions) ? raw.savedProviderSessions : [];
168
296
  const legacySessionReads = isPlainObject(raw.recentSessionReads) ? raw.recentSessionReads : {};
@@ -186,7 +314,7 @@ function migrateStateToStateFile(raw) {
186
314
  }
187
315
  function loadConfig() {
188
316
  const configPath = getConfigPath();
189
- if (!existsSync(configPath)) {
317
+ if (!existsSync2(configPath)) {
190
318
  const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
191
319
  try {
192
320
  saveConfig(initialized.config);
@@ -217,7 +345,7 @@ function saveConfig(config) {
217
345
  const configPath = getConfigPath();
218
346
  const dir = getConfigDir();
219
347
  const normalized = normalizeConfig(config);
220
- if (!existsSync(dir)) {
348
+ if (!existsSync2(dir)) {
221
349
  mkdirSync(dir, { recursive: true, mode: 448 });
222
350
  }
223
351
  writeFileSync(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
@@ -295,17 +423,17 @@ __export(mesh_config_exports, {
295
423
  updateMesh: () => updateMesh,
296
424
  updateNode: () => updateNode
297
425
  });
298
- import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
299
- import { join as join3 } from "path";
426
+ import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
427
+ import { join as join4 } from "path";
300
428
  import { randomUUID as randomUUID3 } from "crypto";
301
429
  function getMeshConfigPath() {
302
- return join3(getConfigDir(), "meshes.json");
430
+ return join4(getConfigDir(), "meshes.json");
303
431
  }
304
432
  function loadMeshConfig() {
305
- const path26 = getMeshConfigPath();
306
- if (!existsSync3(path26)) return { meshes: [] };
433
+ const path27 = getMeshConfigPath();
434
+ if (!existsSync4(path27)) return { meshes: [] };
307
435
  try {
308
- const raw = JSON.parse(readFileSync2(path26, "utf-8"));
436
+ const raw = JSON.parse(readFileSync2(path27, "utf-8"));
309
437
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
310
438
  return raw;
311
439
  } catch {
@@ -313,16 +441,16 @@ function loadMeshConfig() {
313
441
  }
314
442
  }
315
443
  function saveMeshConfig(config) {
316
- const path26 = getMeshConfigPath();
317
- writeFileSync2(path26, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
444
+ const path27 = getMeshConfigPath();
445
+ writeFileSync2(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
318
446
  }
319
447
  function normalizeRepoIdentity(remoteUrl) {
320
448
  let identity = remoteUrl.trim();
321
449
  if (identity.startsWith("http://") || identity.startsWith("https://")) {
322
450
  try {
323
451
  const url = new URL(identity);
324
- const path26 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
325
- return `${url.hostname}/${path26}`;
452
+ const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
453
+ return `${url.hostname}/${path27}`;
326
454
  } catch {
327
455
  }
328
456
  }
@@ -397,9 +525,12 @@ function addNode(meshId, opts) {
397
525
  id: `node_${randomUUID3().replace(/-/g, "")}`,
398
526
  workspace: opts.workspace.trim(),
399
527
  repoRoot: opts.repoRoot,
528
+ daemonId: opts.daemonId,
400
529
  userOverrides: opts.userOverrides || {},
401
530
  policy: opts.policy || {},
402
- isLocalWorktree: opts.isLocalWorktree
531
+ isLocalWorktree: opts.isLocalWorktree,
532
+ worktreeBranch: opts.worktreeBranch,
533
+ clonedFromNodeId: opts.clonedFromNodeId
403
534
  };
404
535
  mesh.nodes.push(node);
405
536
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -443,7 +574,7 @@ __export(coordinator_prompt_exports, {
443
574
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
444
575
  });
445
576
  function buildCoordinatorSystemPrompt(ctx) {
446
- const { mesh, status, userInstruction } = ctx;
577
+ const { mesh, status, userInstruction, coordinatorCliType } = ctx;
447
578
  const sections = [];
448
579
  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
580
 
@@ -457,15 +588,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
457
588
  } else {
458
589
  sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
459
590
  }
460
- sections.push(buildPolicySection(mesh.policy));
591
+ sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
461
592
  sections.push(TOOLS_SECTION);
462
593
  sections.push(WORKFLOW_SECTION);
463
- sections.push(RULES_SECTION);
594
+ sections.push(buildRulesSection(coordinatorCliType));
464
595
  if (userInstruction) {
465
596
  sections.push(`## Additional Context
466
597
  ${userInstruction}`);
467
598
  }
468
- if (mesh.coordinator.systemPromptSuffix) {
599
+ if (mesh.coordinator?.systemPromptSuffix) {
469
600
  sections.push(mesh.coordinator.systemPromptSuffix);
470
601
  }
471
602
  return sections.join("\n\n");
@@ -510,10 +641,29 @@ function buildPolicySection(policy) {
510
641
  return `## Policy
511
642
  ${rules.join("\n")}`;
512
643
  }
513
- var TOOLS_SECTION, WORKFLOW_SECTION, RULES_SECTION;
644
+ function buildRulesSection(coordinatorCliType) {
645
+ const coordinatorNote = coordinatorCliType ? `
646
+ - **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.` : "";
647
+ return `## Rules
648
+
649
+ - **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.
650
+ - **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.
651
+ - **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.
652
+ - **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.
653
+ - **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
654
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
655
+ - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
656
+ - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
657
+ - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
658
+ - **Never fabricate tool results.** Always call the actual tool; never pretend you did.
659
+ - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
660
+ - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
661
+ }
662
+ var TOOLS_SECTION, WORKFLOW_SECTION;
514
663
  var init_coordinator_prompt = __esm({
515
664
  "src/mesh/coordinator-prompt.ts"() {
516
665
  "use strict";
666
+ init_repo_mesh_types();
517
667
  TOOLS_SECTION = `## Available Tools
518
668
 
519
669
  | Tool | Purpose |
@@ -525,36 +675,29 @@ var init_coordinator_prompt = __esm({
525
675
  | \`mesh_read_chat\` | Read an agent's recent messages to check progress |
526
676
  | \`mesh_git_status\` | Check git status on a specific node |
527
677
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
528
- | \`mesh_approve\` | Approve/reject a pending agent action |`;
678
+ | \`mesh_approve\` | Approve/reject a pending agent action |
679
+ | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
680
+ | \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
529
681
  WORKFLOW_SECTION = `## Orchestration Workflow
530
682
 
531
683
  1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
532
684
  2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
533
685
  3. **Delegate** \u2014 For each task:
534
686
  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.
687
+ b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
688
+ c. If no session exists, call \`mesh_launch_session\` to start one.
689
+ 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
690
  4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
538
691
  5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
539
692
  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.`;
693
+ 7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
694
+ 8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
552
695
  }
553
696
  });
554
697
 
555
698
  // src/logging/logger.ts
556
699
  import * as fs2 from "fs";
557
- import * as path9 from "path";
700
+ import * as path10 from "path";
558
701
  import * as os4 from "os";
559
702
  function setLogLevel(level) {
560
703
  currentLevel = level;
@@ -570,13 +713,13 @@ function getDaemonLogDir() {
570
713
  return LOG_DIR;
571
714
  }
572
715
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
573
- return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
716
+ return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
574
717
  }
575
718
  function checkDateRotation() {
576
719
  const today = getDateStr();
577
720
  if (today !== currentDate) {
578
721
  currentDate = today;
579
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
722
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
580
723
  cleanOldLogs();
581
724
  }
582
725
  }
@@ -590,7 +733,7 @@ function cleanOldLogs() {
590
733
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
591
734
  if (dateMatch && dateMatch[1] < cutoffStr) {
592
735
  try {
593
- fs2.unlinkSync(path9.join(LOG_DIR, file));
736
+ fs2.unlinkSync(path10.join(LOG_DIR, file));
594
737
  } catch {
595
738
  }
596
739
  }
@@ -713,7 +856,7 @@ var init_logger = __esm({
713
856
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
714
857
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
715
858
  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");
859
+ 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
860
  MAX_LOG_SIZE = 5 * 1024 * 1024;
718
861
  MAX_LOG_DAYS = 7;
719
862
  try {
@@ -721,16 +864,16 @@ var init_logger = __esm({
721
864
  } catch {
722
865
  }
723
866
  currentDate = getDateStr();
724
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
867
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
725
868
  cleanOldLogs();
726
869
  try {
727
- const oldLog = path9.join(LOG_DIR, "daemon.log");
870
+ const oldLog = path10.join(LOG_DIR, "daemon.log");
728
871
  if (fs2.existsSync(oldLog)) {
729
872
  const stat2 = fs2.statSync(oldLog);
730
873
  const oldDate = stat2.mtime.toISOString().slice(0, 10);
731
- fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
874
+ fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
732
875
  }
733
- const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
876
+ const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
734
877
  if (fs2.existsSync(oldLogBackup)) {
735
878
  fs2.unlinkSync(oldLogBackup);
736
879
  }
@@ -762,7 +905,7 @@ var init_logger = __esm({
762
905
  }
763
906
  };
764
907
  interceptorInstalled = false;
765
- LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
908
+ LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
766
909
  }
767
910
  });
768
911
 
@@ -1171,7 +1314,7 @@ var init_pty_transport = __esm({
1171
1314
 
1172
1315
  // src/cli-adapters/provider-cli-shared.ts
1173
1316
  import * as os9 from "os";
1174
- import * as path13 from "path";
1317
+ import * as path14 from "path";
1175
1318
  import { execSync as execSync3 } from "child_process";
1176
1319
  function stripAnsi(str) {
1177
1320
  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 +1379,9 @@ function buildCliScreenSnapshot(text) {
1236
1379
  function findBinary(name) {
1237
1380
  const trimmed = String(name || "").trim();
1238
1381
  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);
1382
+ const expanded = trimmed.startsWith("~") ? path14.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1383
+ if (path14.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1384
+ return path14.isAbsolute(expanded) ? expanded : path14.resolve(expanded);
1242
1385
  }
1243
1386
  const isWin = os9.platform() === "win32";
1244
1387
  try {
@@ -1254,7 +1397,7 @@ function findBinary(name) {
1254
1397
  }
1255
1398
  }
1256
1399
  function isScriptBinary(binaryPath) {
1257
- if (!path13.isAbsolute(binaryPath)) return false;
1400
+ if (!path14.isAbsolute(binaryPath)) return false;
1258
1401
  try {
1259
1402
  const fs16 = __require("fs");
1260
1403
  const resolved = fs16.realpathSync(binaryPath);
@@ -1270,7 +1413,7 @@ function isScriptBinary(binaryPath) {
1270
1413
  }
1271
1414
  }
1272
1415
  function looksLikeMachOOrElf(filePath) {
1273
- if (!path13.isAbsolute(filePath)) return false;
1416
+ if (!path14.isAbsolute(filePath)) return false;
1274
1417
  try {
1275
1418
  const fs16 = __require("fs");
1276
1419
  const resolved = fs16.realpathSync(filePath);
@@ -1484,10 +1627,10 @@ var init_provider_cli_config = __esm({
1484
1627
 
1485
1628
  // src/cli-adapters/provider-cli-runtime.ts
1486
1629
  import * as os10 from "os";
1487
- import * as path14 from "path";
1630
+ import * as path15 from "path";
1488
1631
  import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from "@adhdev/session-host-core";
1489
1632
  function resolveCliSpawnPlan(options) {
1490
- const { provider, runtimeSettings, workingDir, extraArgs } = options;
1633
+ const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
1491
1634
  const { spawn: spawnConfig } = provider;
1492
1635
  const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
1493
1636
  const binaryPath = findBinary(configuredCommand);
@@ -1495,9 +1638,9 @@ function resolveCliSpawnPlan(options) {
1495
1638
  const allArgs = [...spawnConfig.args, ...extraArgs];
1496
1639
  let shellCmd;
1497
1640
  let shellArgs;
1498
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1641
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1499
1642
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1500
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1643
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1501
1644
  const useShell = isWin ? useShellWin : useShellUnix;
1502
1645
  if (useShell) {
1503
1646
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -1511,7 +1654,7 @@ function resolveCliSpawnPlan(options) {
1511
1654
  shellCmd = binaryPath;
1512
1655
  shellArgs = allArgs;
1513
1656
  }
1514
- const env = buildCliSpawnEnv(process.env, spawnConfig.env);
1657
+ const env = buildCliSpawnEnv(process.env, { ...spawnConfig.env || {}, ...extraEnv || {} });
1515
1658
  env.TERMINAL_CWD = workingDir;
1516
1659
  return {
1517
1660
  binaryPath,
@@ -1610,8 +1753,9 @@ var init_provider_cli_adapter = __esm({
1610
1753
  init_provider_cli_runtime();
1611
1754
  init_provider_cli_shared();
1612
1755
  ProviderCliAdapter = class _ProviderCliAdapter {
1613
- constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
1756
+ constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
1614
1757
  this.extraArgs = extraArgs;
1758
+ this.extraEnv = extraEnv;
1615
1759
  this.provider = provider;
1616
1760
  this.transportFactory = transportFactory;
1617
1761
  this.cliType = provider.type;
@@ -1762,8 +1906,9 @@ var init_provider_cli_adapter = __esm({
1762
1906
  const currentSnapshot = normalizeScreenSnapshot(screenText);
1763
1907
  const lastSnapshot = this.lastScreenSnapshot;
1764
1908
  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);
1909
+ 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;
1910
+ const staleSnapshotLooksActive = activeScreenPattern.test(lastSnapshot);
1911
+ const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:Try\s+["“][^\n\r"”]+["”])?\s*(?:\n|\r|$)/.test(screenText) && !activeScreenPattern.test(screenText);
1767
1912
  if (staleSnapshotLooksActive && currentScreenLooksIdle) return screenText;
1768
1913
  if (currentSnapshot.length >= lastSnapshot.length) return screenText;
1769
1914
  return `${screenText}
@@ -1926,7 +2071,8 @@ ${lastSnapshot}`;
1926
2071
  provider: this.provider,
1927
2072
  runtimeSettings: this.runtimeSettings,
1928
2073
  workingDir: this.workingDir,
1929
- extraArgs: this.extraArgs
2074
+ extraArgs: this.extraArgs,
2075
+ extraEnv: this.extraEnv
1930
2076
  });
1931
2077
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1932
2078
  this.resetTraceSession();
@@ -4547,6 +4693,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
4547
4693
  "dirty_index_required",
4548
4694
  "conflict",
4549
4695
  "invalid_args",
4696
+ "nothing_to_commit",
4550
4697
  "git_command_failed"
4551
4698
  ]);
4552
4699
  function failure(reason, error) {
@@ -4791,7 +4938,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
4791
4938
  } catch (err) {
4792
4939
  const output = (err?.stdout || "") + (err?.stderr || "");
4793
4940
  if (/nothing to commit/i.test(output)) {
4794
- throw new GitCommandError("git_command_failed", "Nothing to commit");
4941
+ throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
4942
+ stdout: err?.stdout,
4943
+ stderr: err?.stderr
4944
+ });
4795
4945
  }
4796
4946
  throw err;
4797
4947
  }
@@ -4983,20 +5133,23 @@ var TurnSnapshotTracker = class {
4983
5133
  }
4984
5134
  };
4985
5135
 
5136
+ // src/git/index.ts
5137
+ init_git_worktree();
5138
+
4986
5139
  // src/index.ts
4987
5140
  init_config();
4988
5141
 
4989
5142
  // src/config/workspaces.ts
4990
5143
  import * as fs from "fs";
4991
5144
  import * as os from "os";
4992
- import * as path4 from "path";
5145
+ import * as path5 from "path";
4993
5146
  import { randomUUID as randomUUID2 } from "crypto";
4994
5147
  var MAX_WORKSPACES = 50;
4995
5148
  function expandPath(p) {
4996
5149
  const t = (p || "").trim();
4997
5150
  if (!t) return "";
4998
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
4999
- return path4.resolve(t);
5151
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5152
+ return path5.resolve(t);
5000
5153
  }
5001
5154
  function validateWorkspacePath(absPath) {
5002
5155
  try {
@@ -5010,7 +5163,7 @@ function validateWorkspacePath(absPath) {
5010
5163
  }
5011
5164
  }
5012
5165
  function defaultWorkspaceLabel(absPath) {
5013
- const base = path4.basename(absPath) || absPath;
5166
+ const base = path5.basename(absPath) || absPath;
5014
5167
  return base;
5015
5168
  }
5016
5169
  function getDefaultWorkspacePath(config) {
@@ -5101,9 +5254,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5101
5254
  return getDefaultWorkspacePath(config) || void 0;
5102
5255
  }
5103
5256
  function findWorkspaceByPath(config, rawPath) {
5104
- const abs = path4.resolve(expandPath(rawPath));
5257
+ const abs = path5.resolve(expandPath(rawPath));
5105
5258
  if (!abs) return void 0;
5106
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5259
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5107
5260
  }
5108
5261
  function addWorkspaceEntry(config, rawPath, label, options) {
5109
5262
  const abs = expandPath(rawPath);
@@ -5119,7 +5272,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5119
5272
  const v = validateWorkspacePath(abs);
5120
5273
  if (!v.ok) return { error: v.error };
5121
5274
  const list = [...config.workspaces || []];
5122
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5275
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5123
5276
  return { error: "Workspace already in list" };
5124
5277
  }
5125
5278
  if (list.length >= MAX_WORKSPACES) {
@@ -5153,7 +5306,7 @@ function setDefaultWorkspaceId(config, id) {
5153
5306
  }
5154
5307
 
5155
5308
  // src/config/recent-activity.ts
5156
- import * as path5 from "path";
5309
+ import * as path6 from "path";
5157
5310
 
5158
5311
  // src/providers/summary-metadata.ts
5159
5312
  function normalizeSummaryItem(item) {
@@ -5222,9 +5375,9 @@ var MAX_ACTIVITY = 30;
5222
5375
  function normalizeWorkspace(workspace) {
5223
5376
  if (!workspace) return "";
5224
5377
  try {
5225
- return path5.resolve(expandPath(workspace));
5378
+ return path6.resolve(expandPath(workspace));
5226
5379
  } catch {
5227
- return path5.resolve(workspace);
5380
+ return path6.resolve(workspace);
5228
5381
  }
5229
5382
  }
5230
5383
  function buildRecentActivityKey(entry) {
@@ -5392,14 +5545,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5392
5545
  }
5393
5546
 
5394
5547
  // src/config/saved-sessions.ts
5395
- import * as path6 from "path";
5548
+ import * as path7 from "path";
5396
5549
  var MAX_SAVED_SESSIONS = 500;
5397
5550
  function normalizeWorkspace2(workspace) {
5398
5551
  if (!workspace) return "";
5399
5552
  try {
5400
- return path6.resolve(expandPath(workspace));
5553
+ return path7.resolve(expandPath(workspace));
5401
5554
  } catch {
5402
- return path6.resolve(workspace);
5555
+ return path7.resolve(workspace);
5403
5556
  }
5404
5557
  }
5405
5558
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5505,8 +5658,8 @@ async function syncMeshes(transport) {
5505
5658
 
5506
5659
  // src/config/state-store.ts
5507
5660
  init_config();
5508
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5509
- import { join as join4 } from "path";
5661
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5662
+ import { join as join5 } from "path";
5510
5663
  var DEFAULT_STATE = {
5511
5664
  recentActivity: [],
5512
5665
  savedProviderSessions: [],
@@ -5519,7 +5672,7 @@ function isPlainObject2(value) {
5519
5672
  return !!value && typeof value === "object" && !Array.isArray(value);
5520
5673
  }
5521
5674
  function getStatePath() {
5522
- return join4(getConfigDir(), "state.json");
5675
+ return join5(getConfigDir(), "state.json");
5523
5676
  }
5524
5677
  function normalizeState(raw) {
5525
5678
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -5555,7 +5708,7 @@ function normalizeState(raw) {
5555
5708
  }
5556
5709
  function loadState() {
5557
5710
  const statePath = getStatePath();
5558
- if (!existsSync4(statePath)) {
5711
+ if (!existsSync5(statePath)) {
5559
5712
  return { ...DEFAULT_STATE };
5560
5713
  }
5561
5714
  try {
@@ -5576,9 +5729,9 @@ function resetState() {
5576
5729
 
5577
5730
  // src/detection/ide-detector.ts
5578
5731
  import { execSync } from "child_process";
5579
- import { existsSync as existsSync5 } from "fs";
5732
+ import { existsSync as existsSync6 } from "fs";
5580
5733
  import { platform, homedir as homedir3 } from "os";
5581
- import * as path7 from "path";
5734
+ import * as path8 from "path";
5582
5735
  var BUILTIN_IDE_DEFINITIONS = [];
5583
5736
  var registeredIDEs = /* @__PURE__ */ new Map();
5584
5737
  function registerIDEDefinition(def) {
@@ -5597,10 +5750,10 @@ function getMergedDefinitions() {
5597
5750
  function findCliCommand(command) {
5598
5751
  const trimmed = String(command || "").trim();
5599
5752
  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;
5753
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5754
+ const candidate = trimmed.startsWith("~") ? path8.join(homedir3(), trimmed.slice(1)) : trimmed;
5755
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5756
+ return existsSync6(resolved) ? resolved : null;
5604
5757
  }
5605
5758
  try {
5606
5759
  const result = execSync(
@@ -5627,31 +5780,31 @@ function getIdeVersion(cliCommand) {
5627
5780
  function checkPathExists(paths) {
5628
5781
  const home = homedir3();
5629
5782
  for (const p of paths) {
5630
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
5783
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5631
5784
  if (normalized.includes("*")) {
5632
5785
  const username = home.split(/[\\/]/).pop() || "";
5633
5786
  const resolved = normalized.replace("*", username);
5634
- if (existsSync5(resolved)) return resolved;
5787
+ if (existsSync6(resolved)) return resolved;
5635
5788
  } else {
5636
- if (existsSync5(normalized)) return normalized;
5789
+ if (existsSync6(normalized)) return normalized;
5637
5790
  }
5638
5791
  }
5639
5792
  return null;
5640
5793
  }
5641
5794
  async function detectIDEs(providerLoader) {
5642
- const os21 = platform();
5795
+ const os22 = platform();
5643
5796
  const results = [];
5644
5797
  for (const def of getMergedDefinitions()) {
5645
5798
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5646
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
5799
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5647
5800
  let resolvedCli = cliPath;
5648
- if (!resolvedCli && appPath && os21 === "darwin") {
5801
+ if (!resolvedCli && appPath && os22 === "darwin") {
5649
5802
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5650
- if (existsSync5(bundledCli)) resolvedCli = bundledCli;
5803
+ if (existsSync6(bundledCli)) resolvedCli = bundledCli;
5651
5804
  }
5652
- if (!resolvedCli && appPath && os21 === "win32") {
5653
- const { dirname: dirname8 } = await import("path");
5654
- const appDir = dirname8(appPath);
5805
+ if (!resolvedCli && appPath && os22 === "win32") {
5806
+ const { dirname: dirname9 } = await import("path");
5807
+ const appDir = dirname9(appPath);
5655
5808
  const candidates = [
5656
5809
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5657
5810
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5660,13 +5813,13 @@ async function detectIDEs(providerLoader) {
5660
5813
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
5661
5814
  ];
5662
5815
  for (const c of candidates) {
5663
- if (existsSync5(c)) {
5816
+ if (existsSync6(c)) {
5664
5817
  resolvedCli = c;
5665
5818
  break;
5666
5819
  }
5667
5820
  }
5668
5821
  }
5669
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5822
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5670
5823
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5671
5824
  results.push({
5672
5825
  id: def.id,
@@ -5685,8 +5838,8 @@ async function detectIDEs(providerLoader) {
5685
5838
  // src/detection/cli-detector.ts
5686
5839
  import { exec } from "child_process";
5687
5840
  import * as os2 from "os";
5688
- import * as path8 from "path";
5689
- import { existsSync as existsSync6 } from "fs";
5841
+ import * as path9 from "path";
5842
+ import { existsSync as existsSync7 } from "fs";
5690
5843
  function parseVersion(raw) {
5691
5844
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
5692
5845
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
@@ -5698,19 +5851,19 @@ function shellQuote(value) {
5698
5851
  function expandHome(value) {
5699
5852
  const trimmed = value.trim();
5700
5853
  if (!trimmed.startsWith("~")) return trimmed;
5701
- return path8.join(os2.homedir(), trimmed.slice(1));
5854
+ return path9.join(os2.homedir(), trimmed.slice(1));
5702
5855
  }
5703
5856
  function isExplicitCommandPath(command) {
5704
5857
  const trimmed = command.trim();
5705
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5858
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5706
5859
  }
5707
5860
  function resolveCommandPath(command) {
5708
5861
  const trimmed = command.trim();
5709
5862
  if (!trimmed) return null;
5710
5863
  if (isExplicitCommandPath(trimmed)) {
5711
5864
  const expanded = expandHome(trimmed);
5712
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
5713
- return existsSync6(candidate) ? candidate : null;
5865
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5866
+ return existsSync7(candidate) ? candidate : null;
5714
5867
  }
5715
5868
  return null;
5716
5869
  }
@@ -7978,9 +8131,9 @@ ${cleanBody}`;
7978
8131
 
7979
8132
  // src/config/chat-history.ts
7980
8133
  import * as fs3 from "fs";
7981
- import * as path10 from "path";
8134
+ import * as path11 from "path";
7982
8135
  import * as os5 from "os";
7983
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8136
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
7984
8137
  var RETAIN_DAYS = 30;
7985
8138
  var SAVED_HISTORY_INDEX_VERSION = 1;
7986
8139
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8143,7 +8296,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8143
8296
  function buildSavedHistoryFileSignatureMap(dir, files) {
8144
8297
  return new Map(files.map((file) => {
8145
8298
  try {
8146
- const stat2 = fs3.statSync(path10.join(dir, file));
8299
+ const stat2 = fs3.statSync(path11.join(dir, file));
8147
8300
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8148
8301
  } catch {
8149
8302
  return [file, `${file}:missing`];
@@ -8154,7 +8307,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8154
8307
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8155
8308
  }
8156
8309
  function getSavedHistoryIndexFilePath(dir) {
8157
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8310
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8158
8311
  }
8159
8312
  function getSavedHistoryIndexLockPath(dir) {
8160
8313
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8256,7 +8409,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8256
8409
  }
8257
8410
  for (const file of Array.from(currentEntries.keys())) {
8258
8411
  if (incomingFiles.has(file)) continue;
8259
- if (!fs3.existsSync(path10.join(dir, file))) {
8412
+ if (!fs3.existsSync(path11.join(dir, file))) {
8260
8413
  currentEntries.delete(file);
8261
8414
  }
8262
8415
  }
@@ -8282,7 +8435,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8282
8435
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8283
8436
  const files = listHistoryFiles(dir);
8284
8437
  for (const file of files) {
8285
- const stat2 = fs3.statSync(path10.join(dir, file));
8438
+ const stat2 = fs3.statSync(path11.join(dir, file));
8286
8439
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8287
8440
  }
8288
8441
  return false;
@@ -8292,14 +8445,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8292
8445
  }
8293
8446
  function buildSavedHistoryFileSignature(dir, file) {
8294
8447
  try {
8295
- const stat2 = fs3.statSync(path10.join(dir, file));
8448
+ const stat2 = fs3.statSync(path11.join(dir, file));
8296
8449
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8297
8450
  } catch {
8298
8451
  return `${file}:missing`;
8299
8452
  }
8300
8453
  }
8301
8454
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8302
- const filePath = path10.join(dir, file);
8455
+ const filePath = path11.join(dir, file);
8303
8456
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8304
8457
  const currentEntry = entries.get(file) || null;
8305
8458
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8372,7 +8525,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8372
8525
  function computeSavedHistoryFileSummary(dir, file) {
8373
8526
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8374
8527
  if (!historySessionId) return null;
8375
- const filePath = path10.join(dir, file);
8528
+ const filePath = path11.join(dir, file);
8376
8529
  const content = fs3.readFileSync(filePath, "utf-8");
8377
8530
  const lines = content.split("\n").filter(Boolean);
8378
8531
  let messageCount = 0;
@@ -8459,7 +8612,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8459
8612
  const summaryBySessionId = /* @__PURE__ */ new Map();
8460
8613
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8461
8614
  for (const file of files.slice().sort()) {
8462
- const filePath = path10.join(dir, file);
8615
+ const filePath = path11.join(dir, file);
8463
8616
  const signature = fileSignatures.get(file) || `${file}:missing`;
8464
8617
  const cached = savedHistoryFileSummaryCache.get(filePath);
8465
8618
  const persisted = persistedEntries.get(file);
@@ -8579,12 +8732,12 @@ var ChatHistoryWriter = class {
8579
8732
  });
8580
8733
  }
8581
8734
  if (newMessages.length === 0) return;
8582
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8735
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8583
8736
  fs3.mkdirSync(dir, { recursive: true });
8584
8737
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8585
8738
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8586
8739
  const fileName = `${filePrefix}${date}.jsonl`;
8587
- const filePath = path10.join(dir, fileName);
8740
+ const filePath = path11.join(dir, fileName);
8588
8741
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8589
8742
  fs3.appendFileSync(filePath, lines, "utf-8");
8590
8743
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8675,11 +8828,11 @@ var ChatHistoryWriter = class {
8675
8828
  const ws = String(workspace || "").trim();
8676
8829
  if (!id || !ws) return;
8677
8830
  try {
8678
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8831
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8679
8832
  fs3.mkdirSync(dir, { recursive: true });
8680
8833
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8681
8834
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8682
- const filePath = path10.join(dir, fileName);
8835
+ const filePath = path11.join(dir, fileName);
8683
8836
  const record = {
8684
8837
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8685
8838
  receivedAt: Date.now(),
@@ -8725,14 +8878,14 @@ var ChatHistoryWriter = class {
8725
8878
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8726
8879
  this.lastSeenCounts.delete(fromDedupKey);
8727
8880
  }
8728
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8881
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8729
8882
  if (!fs3.existsSync(dir)) return;
8730
8883
  const fromPrefix = `${this.sanitize(fromId)}_`;
8731
8884
  const toPrefix = `${this.sanitize(toId)}_`;
8732
8885
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8733
8886
  for (const file of files) {
8734
- const sourcePath = path10.join(dir, file);
8735
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8887
+ const sourcePath = path11.join(dir, file);
8888
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8736
8889
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8737
8890
  const rewritten = sourceLines.map((line) => {
8738
8891
  try {
@@ -8766,13 +8919,13 @@ var ChatHistoryWriter = class {
8766
8919
  const sessionId = String(historySessionId || "").trim();
8767
8920
  if (!sessionId) return;
8768
8921
  try {
8769
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8922
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8770
8923
  if (!fs3.existsSync(dir)) return;
8771
8924
  const prefix = `${this.sanitize(sessionId)}_`;
8772
8925
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8773
8926
  const seen = /* @__PURE__ */ new Set();
8774
8927
  for (const file of files) {
8775
- const filePath = path10.join(dir, file);
8928
+ const filePath = path11.join(dir, file);
8776
8929
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8777
8930
  const next = [];
8778
8931
  for (const line of lines) {
@@ -8826,11 +8979,11 @@ var ChatHistoryWriter = class {
8826
8979
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
8827
8980
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
8828
8981
  for (const dir of agentDirs) {
8829
- const dirPath = path10.join(HISTORY_DIR, dir.name);
8982
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
8830
8983
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
8831
8984
  let removedAny = false;
8832
8985
  for (const file of files) {
8833
- const filePath = path10.join(dirPath, file);
8986
+ const filePath = path11.join(dirPath, file);
8834
8987
  const stat2 = fs3.statSync(filePath);
8835
8988
  if (stat2.mtimeMs < cutoff) {
8836
8989
  fs3.unlinkSync(filePath);
@@ -8880,13 +9033,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8880
9033
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8881
9034
  try {
8882
9035
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8883
- const dir = path10.join(HISTORY_DIR, sanitized);
9036
+ const dir = path11.join(HISTORY_DIR, sanitized);
8884
9037
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8885
9038
  const files = listHistoryFiles(dir, historySessionId);
8886
9039
  const allMessages = [];
8887
9040
  const seen = /* @__PURE__ */ new Set();
8888
9041
  for (const file of files) {
8889
- const filePath = path10.join(dir, file);
9042
+ const filePath = path11.join(dir, file);
8890
9043
  const content = fs3.readFileSync(filePath, "utf-8");
8891
9044
  const lines = content.trim().split("\n").filter(Boolean);
8892
9045
  for (let i = 0; i < lines.length; i++) {
@@ -8910,7 +9063,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8910
9063
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8911
9064
  try {
8912
9065
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8913
- const dir = path10.join(HISTORY_DIR, sanitized);
9066
+ const dir = path11.join(HISTORY_DIR, sanitized);
8914
9067
  if (!fs3.existsSync(dir)) {
8915
9068
  savedHistorySessionCache.delete(sanitized);
8916
9069
  return { sessions: [], hasMore: false };
@@ -8971,11 +9124,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8971
9124
  }
8972
9125
  function readExistingSessionStartRecord(agentType, historySessionId) {
8973
9126
  try {
8974
- const dir = path10.join(HISTORY_DIR, agentType);
9127
+ const dir = path11.join(HISTORY_DIR, agentType);
8975
9128
  if (!fs3.existsSync(dir)) return null;
8976
9129
  const files = listHistoryFiles(dir, historySessionId).sort();
8977
9130
  for (const file of files) {
8978
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9131
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
8979
9132
  for (const line of lines) {
8980
9133
  try {
8981
9134
  const parsed = JSON.parse(line);
@@ -8995,16 +9148,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8995
9148
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8996
9149
  if (records.length === 0) return false;
8997
9150
  try {
8998
- const dir = path10.join(HISTORY_DIR, agentType);
9151
+ const dir = path11.join(HISTORY_DIR, agentType);
8999
9152
  fs3.mkdirSync(dir, { recursive: true });
9000
9153
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9001
9154
  for (const file of fs3.readdirSync(dir)) {
9002
9155
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9003
- fs3.unlinkSync(path10.join(dir, file));
9156
+ fs3.unlinkSync(path11.join(dir, file));
9004
9157
  }
9005
9158
  }
9006
9159
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9007
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9160
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9008
9161
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9009
9162
  `, "utf-8");
9010
9163
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10999,6 +11152,14 @@ function getActiveChatOptions(profile) {
10999
11152
  if (profile === "full") return {};
11000
11153
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11001
11154
  }
11155
+ function resolveSessionStatus(activeChat, providerStatus) {
11156
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11157
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11158
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11159
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11160
+ if (topLevelStatus !== "idle") return topLevelStatus;
11161
+ return chatStatus;
11162
+ }
11002
11163
  function shouldIncludeSessionControls(profile) {
11003
11164
  return profile !== "live";
11004
11165
  }
@@ -11077,9 +11238,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11077
11238
  providerName: state.name,
11078
11239
  kind: "workspace",
11079
11240
  transport: "cdp-page",
11080
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11081
- activeModal: activeChat?.activeModal || null
11082
- }),
11241
+ status: resolveSessionStatus(activeChat, state.status),
11083
11242
  title,
11084
11243
  workspace,
11085
11244
  ...git && { git },
@@ -11114,9 +11273,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11114
11273
  providerSessionId: ext.providerSessionId,
11115
11274
  kind: "agent",
11116
11275
  transport: "cdp-webview",
11117
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11118
- activeModal: activeChat?.activeModal || null
11119
- }),
11276
+ status: resolveSessionStatus(activeChat, ext.status),
11120
11277
  title: activeChat?.title || ext.name,
11121
11278
  workspace,
11122
11279
  ...git && { git },
@@ -11166,9 +11323,7 @@ function buildCliSession(state, options) {
11166
11323
  providerSessionId: state.providerSessionId,
11167
11324
  kind: "agent",
11168
11325
  transport: "pty",
11169
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11170
- activeModal: activeChat?.activeModal || null
11171
- }),
11326
+ status: resolveSessionStatus(activeChat, state.status),
11172
11327
  title: activeChat?.title || state.name,
11173
11328
  workspace,
11174
11329
  ...git && { git },
@@ -11216,9 +11371,7 @@ function buildAcpSession(state, options) {
11216
11371
  providerName: state.name,
11217
11372
  kind: "agent",
11218
11373
  transport: "acp",
11219
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11220
- activeModal: activeChat?.activeModal || null
11221
- }),
11374
+ status: resolveSessionStatus(activeChat, state.status),
11222
11375
  title: activeChat?.title || state.name,
11223
11376
  workspace,
11224
11377
  ...git && { git },
@@ -11341,7 +11494,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11341
11494
  // src/commands/chat-commands.ts
11342
11495
  import * as fs4 from "fs";
11343
11496
  import * as os6 from "os";
11344
- import * as path11 from "path";
11497
+ import * as path12 from "path";
11345
11498
  import { randomUUID as randomUUID5 } from "crypto";
11346
11499
 
11347
11500
  // src/providers/provider-input-support.ts
@@ -11704,6 +11857,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11704
11857
  return raw;
11705
11858
  }
11706
11859
  }
11860
+ function isGeneratingLikeStatus(status) {
11861
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
11862
+ }
11863
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
11864
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
11865
+ if (hasNonEmptyModalButtons(activeModal)) return false;
11866
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
11867
+ if (adapterRawStatus !== "idle") return false;
11868
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
11869
+ return true;
11870
+ }
11871
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
11872
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
11873
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
11874
+ }
11875
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
11876
+ if (status !== "idle") return messages;
11877
+ return messages.map((message) => {
11878
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
11879
+ const hasStreamingMeta = meta?.streaming === true;
11880
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
11881
+ return {
11882
+ ...message,
11883
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
11884
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
11885
+ };
11886
+ });
11887
+ }
11707
11888
  function buildReadChatCommandResult(payload, args) {
11708
11889
  let validatedPayload;
11709
11890
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -11852,7 +12033,7 @@ function buildDebugBundleText(bundle) {
11852
12033
  }
11853
12034
  function getChatDebugBundleDir() {
11854
12035
  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");
12036
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11856
12037
  }
11857
12038
  function safeBundleIdSegment(value, fallback) {
11858
12039
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11885,7 +12066,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11885
12066
  const bundleId = createChatDebugBundleId(targetSessionId);
11886
12067
  const dir = getChatDebugBundleDir();
11887
12068
  fs4.mkdirSync(dir, { recursive: true });
11888
- const savedPath = path11.join(dir, `${bundleId}.json`);
12069
+ const savedPath = path12.join(dir, `${bundleId}.json`);
11889
12070
  const json = `${JSON.stringify(bundle, null, 2)}
11890
12071
  `;
11891
12072
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12115,7 +12296,7 @@ async function handleChatHistory(h, args) {
12115
12296
  }
12116
12297
  }
12117
12298
  async function handleReadChat(h, args) {
12118
- const provider = h.getProvider(args?.agentType);
12299
+ const provider = h.getProvider(args?.agentType || args?.providerType);
12119
12300
  const transport = getTargetTransport(h, provider);
12120
12301
  const historySessionId = getHistorySessionId(h, args);
12121
12302
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
@@ -12142,10 +12323,13 @@ async function handleReadChat(h, args) {
12142
12323
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12143
12324
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12144
12325
  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}`);
12326
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12327
+ const runtimeMessageMerger = getTargetInstance(h, args);
12328
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12329
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12330
+ 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
12331
  return buildReadChatCommandResult({
12148
- messages: parsedRecord.messages,
12332
+ messages: returnedMessages,
12149
12333
  status: returnedStatus,
12150
12334
  activeModal,
12151
12335
  debugReadChat: {
@@ -12156,7 +12340,7 @@ async function handleReadChat(h, args) {
12156
12340
  returnedStatus: String(returnedStatus || ""),
12157
12341
  shouldPreferAdapterMessages: false,
12158
12342
  parsedMsgCount: parsedRecord.messages.length,
12159
- returnedMsgCount: parsedRecord.messages.length
12343
+ returnedMsgCount: returnedMessages.length
12160
12344
  },
12161
12345
  ...title ? { title } : {},
12162
12346
  ...providerSessionId ? { providerSessionId } : {},
@@ -13029,7 +13213,7 @@ async function handleResolveAction(h, args) {
13029
13213
 
13030
13214
  // src/commands/cdp-commands.ts
13031
13215
  import * as fs5 from "fs";
13032
- import * as path12 from "path";
13216
+ import * as path13 from "path";
13033
13217
  import * as os7 from "os";
13034
13218
  var KEY_TO_VK = {
13035
13219
  Backspace: 8,
@@ -13286,25 +13470,25 @@ function resolveSafePath(requestedPath) {
13286
13470
  const inputPath = rawPath || ".";
13287
13471
  const home = os7.homedir();
13288
13472
  if (inputPath.startsWith("~")) {
13289
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13473
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13290
13474
  }
13291
13475
  if (process.platform === "win32") {
13292
13476
  const normalized = normalizeWindowsRequestedPath(inputPath);
13293
- if (path12.win32.isAbsolute(normalized)) {
13294
- return path12.win32.normalize(normalized);
13477
+ if (path13.win32.isAbsolute(normalized)) {
13478
+ return path13.win32.normalize(normalized);
13295
13479
  }
13296
- return path12.win32.resolve(normalized);
13480
+ return path13.win32.resolve(normalized);
13297
13481
  }
13298
- if (path12.isAbsolute(inputPath)) {
13299
- return path12.normalize(inputPath);
13482
+ if (path13.isAbsolute(inputPath)) {
13483
+ return path13.normalize(inputPath);
13300
13484
  }
13301
- return path12.resolve(inputPath);
13485
+ return path13.resolve(inputPath);
13302
13486
  }
13303
13487
  function listDirectoryEntriesSafe(dirPath) {
13304
13488
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13305
13489
  const files = [];
13306
13490
  for (const entry of entries) {
13307
- const entryPath = path12.join(dirPath, entry.name);
13491
+ const entryPath = path13.join(dirPath, entry.name);
13308
13492
  try {
13309
13493
  if (entry.isDirectory()) {
13310
13494
  files.push({ name: entry.name, type: "directory" });
@@ -13358,7 +13542,7 @@ async function handleFileRead(h, args) {
13358
13542
  async function handleFileWrite(h, args) {
13359
13543
  try {
13360
13544
  const filePath = resolveSafePath(args?.path);
13361
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
13545
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13362
13546
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13363
13547
  return { success: true, path: filePath };
13364
13548
  } catch (e) {
@@ -14142,9 +14326,11 @@ var DaemonCommandHandler = class {
14142
14326
  }
14143
14327
  const sessionLookupFailed = !!targetSessionId && !session;
14144
14328
  const managerKey = this.extractIdeType(args, sessionLookupFailed);
14145
- let providerType;
14329
+ let providerType = args?.agentType || args?.providerType;
14146
14330
  if (!sessionLookupFailed) {
14147
- providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
14331
+ providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
14332
+ } else if (!providerType) {
14333
+ providerType = this.inferProviderType(managerKey);
14148
14334
  }
14149
14335
  return { session, managerKey, providerType, sessionLookupFailed };
14150
14336
  }
@@ -14224,7 +14410,8 @@ var DaemonCommandHandler = class {
14224
14410
  "pty_resize",
14225
14411
  "invoke_provider_script"
14226
14412
  ]);
14227
- if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
14413
+ 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);
14414
+ if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
14228
14415
  const result2 = {
14229
14416
  success: false,
14230
14417
  error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
@@ -14478,16 +14665,16 @@ var DaemonCommandHandler = class {
14478
14665
  // src/commands/cli-manager.ts
14479
14666
  init_provider_cli_adapter();
14480
14667
  import * as os13 from "os";
14481
- import * as path16 from "path";
14668
+ import * as path17 from "path";
14482
14669
  import * as crypto4 from "crypto";
14483
- import { existsSync as existsSync11 } from "fs";
14670
+ import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
14484
14671
  import { execFileSync } from "child_process";
14485
14672
  import chalk from "chalk";
14486
14673
  init_config();
14487
14674
 
14488
14675
  // src/providers/cli-provider-instance.ts
14489
14676
  import * as os12 from "os";
14490
- import * as path15 from "path";
14677
+ import * as path16 from "path";
14491
14678
  import * as crypto3 from "crypto";
14492
14679
  import * as fs6 from "fs";
14493
14680
  import { createRequire } from "module";
@@ -14546,7 +14733,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14546
14733
  var CachedDatabaseSync = null;
14547
14734
  function getDatabaseSync() {
14548
14735
  if (CachedDatabaseSync) return CachedDatabaseSync;
14549
- const requireFn = typeof __require === "function" ? __require : createRequire(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14736
+ const requireFn = typeof __require === "function" ? __require : createRequire(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14550
14737
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14551
14738
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14552
14739
  if (!CachedDatabaseSync) {
@@ -14599,7 +14786,7 @@ var CliProviderInstance = class {
14599
14786
  this.providerSessionId = options?.providerSessionId;
14600
14787
  this.launchMode = options?.launchMode || "new";
14601
14788
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14602
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
14789
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14603
14790
  this.monitor = new StatusMonitor();
14604
14791
  this.historyWriter = new ChatHistoryWriter();
14605
14792
  }
@@ -15076,7 +15263,19 @@ var CliProviderInstance = class {
15076
15263
  }
15077
15264
  }
15078
15265
  pushEvent(event) {
15079
- this.events.push(event);
15266
+ const enrichedEvent = {
15267
+ ...event,
15268
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
15269
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
15270
+ providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
15271
+ workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
15272
+ providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
15273
+ };
15274
+ if (this.context?.emitProviderEvent) {
15275
+ this.context.emitProviderEvent(enrichedEvent);
15276
+ return;
15277
+ }
15278
+ this.events.push(enrichedEvent);
15080
15279
  }
15081
15280
  flushEvents() {
15082
15281
  const events = [...this.events];
@@ -15283,12 +15482,31 @@ ${effect.notification.body || ""}`.trim();
15283
15482
  );
15284
15483
  }
15285
15484
  }
15485
+ mergeRuntimeChatMessages(parsedMessages) {
15486
+ return this.mergeConversationMessages(parsedMessages);
15487
+ }
15286
15488
  mergeConversationMessages(parsedMessages) {
15287
15489
  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;
15490
+ const parsedEntries = parsedMessages.map((message, index) => ({
15491
+ message,
15492
+ index,
15493
+ source: "parsed"
15494
+ }));
15495
+ const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
15496
+ message: entry.message,
15497
+ index: parsedMessages.length + index,
15498
+ source: "runtime"
15499
+ }));
15500
+ const getTime = (message) => {
15501
+ const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
15502
+ return Number.isFinite(value) && value > 0 ? value : 0;
15503
+ };
15504
+ return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
15505
+ const aTime = getTime(a.message);
15506
+ const bTime = getTime(b.message);
15507
+ if (aTime && bTime && aTime !== bTime) return aTime - bTime;
15508
+ if (aTime && !bTime && a.source === "runtime" && b.source === "parsed") return -1;
15509
+ if (!aTime && bTime && a.source === "parsed" && b.source === "runtime") return 1;
15292
15510
  return a.index - b.index;
15293
15511
  }).map((entry) => entry.message));
15294
15512
  }
@@ -16617,17 +16835,17 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16617
16835
  // src/commands/cli-manager.ts
16618
16836
  function isExplicitCommand(command) {
16619
16837
  const trimmed = command.trim();
16620
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16838
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16621
16839
  }
16622
16840
  function expandExecutable(command) {
16623
16841
  const trimmed = command.trim();
16624
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16842
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16625
16843
  }
16626
16844
  function commandExists(command) {
16627
16845
  const trimmed = command.trim();
16628
16846
  if (!trimmed) return false;
16629
16847
  if (isExplicitCommand(trimmed)) {
16630
- return existsSync11(expandExecutable(trimmed));
16848
+ return existsSync12(expandExecutable(trimmed));
16631
16849
  }
16632
16850
  try {
16633
16851
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -16645,6 +16863,35 @@ function colorize(color, text) {
16645
16863
  const fn = chalkApi?.[color];
16646
16864
  return typeof fn === "function" ? fn(text) : text;
16647
16865
  }
16866
+ var COORDINATOR_DELEGATED_ENV_UNSETS = {
16867
+ ADHDEV_INLINE_MESH: "",
16868
+ ADHDEV_MCP_TRANSPORT: "",
16869
+ ADHDEV_MESH_ID: "",
16870
+ HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
16871
+ };
16872
+ function hasCliArg(args, flag) {
16873
+ return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
16874
+ }
16875
+ function ensureEmptyDelegatedMcpConfig(workspace) {
16876
+ const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
16877
+ mkdirSync7(baseDir, { recursive: true });
16878
+ const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
16879
+ const filePath = path17.join(baseDir, `${workspaceHash}.json`);
16880
+ writeFileSync7(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
16881
+ return filePath;
16882
+ }
16883
+ function buildCoordinatorDelegatedCliLaunchOptions(input) {
16884
+ const cliType = String(input.cliType || "").trim();
16885
+ const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
16886
+ const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
16887
+ if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
16888
+ cliArgs.unshift("--ignore-user-config");
16889
+ }
16890
+ if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
16891
+ cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
16892
+ }
16893
+ return { cliArgs, env };
16894
+ }
16648
16895
  function isUuid(value) {
16649
16896
  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
16897
  }
@@ -16815,7 +17062,7 @@ var DaemonCliManager = class {
16815
17062
  attachExisting
16816
17063
  }) || void 0;
16817
17064
  }
16818
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17065
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
16819
17066
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16820
17067
  const provider = this.providerLoader.getMeta(normalizedType);
16821
17068
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -16829,7 +17076,7 @@ var DaemonCliManager = class {
16829
17076
  providerSessionId,
16830
17077
  attachExisting
16831
17078
  );
16832
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17079
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
16833
17080
  }
16834
17081
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
16835
17082
  }
@@ -16902,7 +17149,7 @@ var DaemonCliManager = class {
16902
17149
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16903
17150
  const trimmed = (workingDir || "").trim();
16904
17151
  if (!trimmed) throw new Error("working directory required");
16905
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17152
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
16906
17153
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16907
17154
  const rawProvider = this.providerLoader.getByAlias(cliType);
16908
17155
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17032,6 +17279,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17032
17279
  {
17033
17280
  providerSessionId: sessionBinding.providerSessionId,
17034
17281
  launchMode: sessionBinding.launchMode,
17282
+ extraEnv: options?.extraEnv,
17035
17283
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17036
17284
  this.persistRecentActivity({
17037
17285
  kind: "cli",
@@ -17052,7 +17300,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17052
17300
  resolvedCliArgs,
17053
17301
  key,
17054
17302
  sessionBinding.providerSessionId,
17055
- false
17303
+ false,
17304
+ options?.extraEnv
17056
17305
  );
17057
17306
  try {
17058
17307
  await adapter.spawn();
@@ -17276,12 +17525,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
17276
17525
  const dir = resolved.path;
17277
17526
  const launchSource = resolved.source;
17278
17527
  if (!cliType) throw new Error("cliType required");
17528
+ const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
17529
+ const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
17530
+ cliType,
17531
+ workspace: dir,
17532
+ cliArgs: args?.cliArgs,
17533
+ env: args?.env
17534
+ }) : null;
17279
17535
  const started = await this.startSession(
17280
17536
  cliType,
17281
17537
  dir,
17282
- args?.cliArgs,
17538
+ delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
17283
17539
  args?.initialModel,
17284
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
17540
+ {
17541
+ resumeSessionId: args?.resumeSessionId,
17542
+ settingsOverride,
17543
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
17544
+ }
17285
17545
  );
17286
17546
  return {
17287
17547
  success: true,
@@ -17403,11 +17663,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17403
17663
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
17404
17664
  import * as net from "net";
17405
17665
  import * as os15 from "os";
17406
- import * as path18 from "path";
17666
+ import * as path19 from "path";
17407
17667
 
17408
17668
  // src/providers/provider-loader.ts
17409
17669
  import * as fs7 from "fs";
17410
- import * as path17 from "path";
17670
+ import * as path18 from "path";
17411
17671
  import * as os14 from "os";
17412
17672
  import * as chokidar from "chokidar";
17413
17673
  init_logger();
@@ -17731,7 +17991,7 @@ var ProviderLoader = class _ProviderLoader {
17731
17991
  try {
17732
17992
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17733
17993
  return ["ide", "extension", "cli", "acp"].some(
17734
- (category) => fs7.existsSync(path17.join(candidate, category))
17994
+ (category) => fs7.existsSync(path18.join(candidate, category))
17735
17995
  );
17736
17996
  } catch {
17737
17997
  return false;
@@ -17739,20 +17999,20 @@ var ProviderLoader = class _ProviderLoader {
17739
17999
  }
17740
18000
  static hasProviderRootMarker(candidate) {
17741
18001
  try {
17742
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18002
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17743
18003
  } catch {
17744
18004
  return false;
17745
18005
  }
17746
18006
  }
17747
18007
  detectDefaultUserDir() {
17748
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
18008
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17749
18009
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17750
18010
  const visited = /* @__PURE__ */ new Set();
17751
18011
  for (const start of this.probeStarts) {
17752
- let current = path17.resolve(start);
18012
+ let current = path18.resolve(start);
17753
18013
  while (!visited.has(current)) {
17754
18014
  visited.add(current);
17755
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18015
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17756
18016
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17757
18017
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17758
18018
  if (envOptIn || hasMarker) {
@@ -17774,7 +18034,7 @@ var ProviderLoader = class _ProviderLoader {
17774
18034
  return { path: siblingCandidate, source };
17775
18035
  }
17776
18036
  }
17777
- const parent = path17.dirname(current);
18037
+ const parent = path18.dirname(current);
17778
18038
  if (parent === current) break;
17779
18039
  current = parent;
17780
18040
  }
@@ -17784,11 +18044,11 @@ var ProviderLoader = class _ProviderLoader {
17784
18044
  constructor(options) {
17785
18045
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17786
18046
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17787
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
18047
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17788
18048
  const detected = this.detectDefaultUserDir();
17789
18049
  this.userDir = detected.path;
17790
18050
  this.userDirSource = detected.source;
17791
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18051
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17792
18052
  this.disableUpstream = false;
17793
18053
  this.applySourceConfig({
17794
18054
  userDir: options?.userDir,
@@ -17847,7 +18107,7 @@ var ProviderLoader = class _ProviderLoader {
17847
18107
  this.userDir = detected.path;
17848
18108
  this.userDirSource = detected.source;
17849
18109
  }
17850
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18110
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17851
18111
  this.disableUpstream = this.sourceMode === "no-upstream";
17852
18112
  if (this.explicitProviderDir) {
17853
18113
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -17861,7 +18121,7 @@ var ProviderLoader = class _ProviderLoader {
17861
18121
  * Canonical provider directory shape for a given root.
17862
18122
  */
17863
18123
  getProviderDir(root, category, type) {
17864
- return path17.join(root, category, type);
18124
+ return path18.join(root, category, type);
17865
18125
  }
17866
18126
  /**
17867
18127
  * Canonical user override directory for a provider.
@@ -17888,7 +18148,7 @@ var ProviderLoader = class _ProviderLoader {
17888
18148
  resolveProviderFile(type, ...segments) {
17889
18149
  const dir = this.findProviderDirInternal(type);
17890
18150
  if (!dir) return null;
17891
- return path17.join(dir, ...segments);
18151
+ return path18.join(dir, ...segments);
17892
18152
  }
17893
18153
  /**
17894
18154
  * Load all providers (3-tier priority)
@@ -17927,7 +18187,7 @@ var ProviderLoader = class _ProviderLoader {
17927
18187
  if (!fs7.existsSync(this.upstreamDir)) return false;
17928
18188
  try {
17929
18189
  return fs7.readdirSync(this.upstreamDir).some(
17930
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18190
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
17931
18191
  );
17932
18192
  } catch {
17933
18193
  return false;
@@ -18424,8 +18684,8 @@ var ProviderLoader = class _ProviderLoader {
18424
18684
  resolved._resolvedScriptDir = entry.scriptDir;
18425
18685
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18426
18686
  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;
18687
+ const fullDir = path18.join(providerDir, entry.scriptDir);
18688
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18429
18689
  }
18430
18690
  matched = true;
18431
18691
  }
@@ -18440,8 +18700,8 @@ var ProviderLoader = class _ProviderLoader {
18440
18700
  resolved._resolvedScriptDir = base.defaultScriptDir;
18441
18701
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18442
18702
  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;
18703
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18704
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18445
18705
  }
18446
18706
  }
18447
18707
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18458,8 +18718,8 @@ var ProviderLoader = class _ProviderLoader {
18458
18718
  resolved._resolvedScriptDir = dirOverride;
18459
18719
  resolved._resolvedScriptsSource = `versions:${range}`;
18460
18720
  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;
18721
+ const fullDir = path18.join(providerDir, dirOverride);
18722
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18463
18723
  }
18464
18724
  }
18465
18725
  } else if (override.scripts) {
@@ -18475,8 +18735,8 @@ var ProviderLoader = class _ProviderLoader {
18475
18735
  resolved._resolvedScriptDir = base.defaultScriptDir;
18476
18736
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18477
18737
  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;
18738
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18739
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18480
18740
  }
18481
18741
  }
18482
18742
  }
@@ -18508,14 +18768,14 @@ var ProviderLoader = class _ProviderLoader {
18508
18768
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18509
18769
  return null;
18510
18770
  }
18511
- const dir = path17.join(providerDir, scriptDir);
18771
+ const dir = path18.join(providerDir, scriptDir);
18512
18772
  if (!fs7.existsSync(dir)) {
18513
18773
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18514
18774
  return null;
18515
18775
  }
18516
18776
  const cached = this.scriptsCache.get(dir);
18517
18777
  if (cached) return cached;
18518
- const scriptsJs = path17.join(dir, "scripts.js");
18778
+ const scriptsJs = path18.join(dir, "scripts.js");
18519
18779
  if (fs7.existsSync(scriptsJs)) {
18520
18780
  try {
18521
18781
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -18557,7 +18817,7 @@ var ProviderLoader = class _ProviderLoader {
18557
18817
  return;
18558
18818
  }
18559
18819
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18560
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
18820
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18561
18821
  this.reload();
18562
18822
  }
18563
18823
  };
@@ -18612,7 +18872,7 @@ var ProviderLoader = class _ProviderLoader {
18612
18872
  }
18613
18873
  const https = __require("https");
18614
18874
  const { execSync: execSync7 } = __require("child_process");
18615
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
18875
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18616
18876
  let prevEtag = "";
18617
18877
  let prevTimestamp = 0;
18618
18878
  try {
@@ -18672,17 +18932,17 @@ var ProviderLoader = class _ProviderLoader {
18672
18932
  return { updated: false };
18673
18933
  }
18674
18934
  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()}`);
18935
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18936
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18677
18937
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18678
18938
  fs7.mkdirSync(tmpExtract, { recursive: true });
18679
18939
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18680
18940
  const extracted = fs7.readdirSync(tmpExtract);
18681
18941
  const rootDir = extracted.find(
18682
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18942
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18683
18943
  );
18684
18944
  if (!rootDir) throw new Error("Unexpected tarball structure");
18685
- const sourceDir = path17.join(tmpExtract, rootDir);
18945
+ const sourceDir = path18.join(tmpExtract, rootDir);
18686
18946
  const backupDir = this.upstreamDir + ".bak";
18687
18947
  if (fs7.existsSync(this.upstreamDir)) {
18688
18948
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18757,8 +19017,8 @@ var ProviderLoader = class _ProviderLoader {
18757
19017
  copyDirRecursive(src, dest) {
18758
19018
  fs7.mkdirSync(dest, { recursive: true });
18759
19019
  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);
19020
+ const srcPath = path18.join(src, entry.name);
19021
+ const destPath = path18.join(dest, entry.name);
18762
19022
  if (entry.isDirectory()) {
18763
19023
  this.copyDirRecursive(srcPath, destPath);
18764
19024
  } else {
@@ -18769,7 +19029,7 @@ var ProviderLoader = class _ProviderLoader {
18769
19029
  /** .meta.json save */
18770
19030
  writeMeta(metaPath, etag, timestamp) {
18771
19031
  try {
18772
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
19032
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18773
19033
  fs7.writeFileSync(metaPath, JSON.stringify({
18774
19034
  etag,
18775
19035
  timestamp,
@@ -18786,7 +19046,7 @@ var ProviderLoader = class _ProviderLoader {
18786
19046
  const scan = (d) => {
18787
19047
  try {
18788
19048
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18789
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
19049
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18790
19050
  else if (entry.name === "provider.json") count++;
18791
19051
  }
18792
19052
  } catch {
@@ -19014,17 +19274,17 @@ var ProviderLoader = class _ProviderLoader {
19014
19274
  for (const root of searchRoots) {
19015
19275
  if (!fs7.existsSync(root)) continue;
19016
19276
  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);
19277
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19278
+ const catDir = path18.join(root, cat);
19019
19279
  if (fs7.existsSync(catDir)) {
19020
19280
  try {
19021
19281
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19022
19282
  if (!entry.isDirectory()) continue;
19023
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19283
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19024
19284
  if (fs7.existsSync(jsonPath)) {
19025
19285
  try {
19026
19286
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19027
- if (data.type === type) return path17.join(catDir, entry.name);
19287
+ if (data.type === type) return path18.join(catDir, entry.name);
19028
19288
  } catch {
19029
19289
  }
19030
19290
  }
@@ -19041,7 +19301,7 @@ var ProviderLoader = class _ProviderLoader {
19041
19301
  * (template substitution is NOT applied here — scripts.js handles that)
19042
19302
  */
19043
19303
  buildScriptWrappersFromDir(dir) {
19044
- const scriptsJs = path17.join(dir, "scripts.js");
19304
+ const scriptsJs = path18.join(dir, "scripts.js");
19045
19305
  if (fs7.existsSync(scriptsJs)) {
19046
19306
  try {
19047
19307
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -19055,7 +19315,7 @@ var ProviderLoader = class _ProviderLoader {
19055
19315
  for (const file of fs7.readdirSync(dir)) {
19056
19316
  if (!file.endsWith(".js")) continue;
19057
19317
  const scriptName = toCamel(file.replace(".js", ""));
19058
- const filePath = path17.join(dir, file);
19318
+ const filePath = path18.join(dir, file);
19059
19319
  result[scriptName] = (...args) => {
19060
19320
  try {
19061
19321
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19115,7 +19375,7 @@ var ProviderLoader = class _ProviderLoader {
19115
19375
  }
19116
19376
  const hasJson = entries.some((e) => e.name === "provider.json");
19117
19377
  if (hasJson) {
19118
- const jsonPath = path17.join(d, "provider.json");
19378
+ const jsonPath = path18.join(d, "provider.json");
19119
19379
  try {
19120
19380
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19121
19381
  const mod = JSON.parse(raw);
@@ -19136,7 +19396,7 @@ var ProviderLoader = class _ProviderLoader {
19136
19396
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19137
19397
  } else {
19138
19398
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19139
- const scriptsPath = path17.join(d, "scripts.js");
19399
+ const scriptsPath = path18.join(d, "scripts.js");
19140
19400
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19141
19401
  try {
19142
19402
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -19162,7 +19422,7 @@ var ProviderLoader = class _ProviderLoader {
19162
19422
  if (!entry.isDirectory()) continue;
19163
19423
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19164
19424
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19165
- scan(path17.join(d, entry.name));
19425
+ scan(path18.join(d, entry.name));
19166
19426
  }
19167
19427
  }
19168
19428
  };
@@ -19487,8 +19747,8 @@ function detectCurrentWorkspace(ideId) {
19487
19747
  const appNameMap = getMacAppIdentifiers();
19488
19748
  const appName = appNameMap[ideId];
19489
19749
  if (appName) {
19490
- const storagePath = path18.join(
19491
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
19750
+ const storagePath = path19.join(
19751
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19492
19752
  appName,
19493
19753
  "storage.json"
19494
19754
  );
@@ -19677,9 +19937,9 @@ init_logger();
19677
19937
 
19678
19938
  // src/logging/command-log.ts
19679
19939
  import * as fs8 from "fs";
19680
- import * as path19 from "path";
19940
+ import * as path20 from "path";
19681
19941
  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");
19942
+ 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
19943
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19684
19944
  var MAX_DAYS = 7;
19685
19945
  try {
@@ -19717,13 +19977,13 @@ function getDateStr2() {
19717
19977
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19718
19978
  }
19719
19979
  var currentDate2 = getDateStr2();
19720
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19980
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19721
19981
  var writeCount2 = 0;
19722
19982
  function checkRotation() {
19723
19983
  const today = getDateStr2();
19724
19984
  if (today !== currentDate2) {
19725
19985
  currentDate2 = today;
19726
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19986
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19727
19987
  cleanOldFiles();
19728
19988
  }
19729
19989
  }
@@ -19737,7 +19997,7 @@ function cleanOldFiles() {
19737
19997
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19738
19998
  if (dateMatch && dateMatch[1] < cutoffStr) {
19739
19999
  try {
19740
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
20000
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19741
20001
  } catch {
19742
20002
  }
19743
20003
  }
@@ -19821,13 +20081,65 @@ cleanOldFiles();
19821
20081
 
19822
20082
  // src/commands/router.ts
19823
20083
  init_logger();
20084
+ import * as yaml from "js-yaml";
19824
20085
 
19825
20086
  // src/commands/mesh-coordinator.ts
19826
- import { existsSync as existsSync14, realpathSync as realpathSync2 } from "fs";
20087
+ import { execFileSync as execFileSync2 } from "child_process";
20088
+ import { existsSync as existsSync15, readdirSync as readdirSync6, realpathSync as realpathSync2 } from "fs";
19827
20089
  import { createRequire as createRequire2 } from "module";
19828
- import { dirname as dirname3, join as join17, resolve as resolve13 } from "path";
20090
+ import * as os17 from "os";
20091
+ import { dirname as dirname4, isAbsolute as isAbsolute10, join as join18, resolve as resolve13 } from "path";
19829
20092
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
19830
20093
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20094
+ var HERMES_CLI_TYPE = "hermes-cli";
20095
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20096
+ function isHermesProvider(provider, cliType) {
20097
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20098
+ return type === HERMES_CLI_TYPE;
20099
+ }
20100
+ function resolveHermesMeshCoordinatorSetup(options) {
20101
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20102
+ meshId: options.meshId,
20103
+ nodeExecutable: options.nodeExecutable,
20104
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20105
+ });
20106
+ if (!mcpServer) {
20107
+ return {
20108
+ kind: "unsupported",
20109
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20110
+ };
20111
+ }
20112
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20113
+ if (!configPath.trim()) {
20114
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20115
+ }
20116
+ return {
20117
+ kind: "auto_import",
20118
+ serverName: DEFAULT_SERVER_NAME,
20119
+ configPath,
20120
+ configFormat: "hermes_config_yaml",
20121
+ mcpServer
20122
+ };
20123
+ }
20124
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20125
+ return {
20126
+ kind: "manual",
20127
+ serverName: DEFAULT_SERVER_NAME,
20128
+ configFormat: "hermes_config_yaml",
20129
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20130
+ requiresRestart: true,
20131
+ 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.",
20132
+ template: renderMeshCoordinatorTemplate(
20133
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20134
+ {
20135
+ meshId,
20136
+ workspace,
20137
+ serverName: DEFAULT_SERVER_NAME,
20138
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20139
+ }
20140
+ )
20141
+ };
20142
+ }
19831
20143
  function resolveMeshCoordinatorSetup(options) {
19832
20144
  const { provider, meshId, workspace } = options;
19833
20145
  const config = provider?.meshCoordinator;
@@ -19837,6 +20149,9 @@ function resolveMeshCoordinatorSetup(options) {
19837
20149
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
19838
20150
  };
19839
20151
  }
20152
+ if (isHermesProvider(provider, options.cliType)) {
20153
+ return resolveHermesMeshCoordinatorSetup(options);
20154
+ }
19840
20155
  const mcpConfig = config.mcpConfig;
19841
20156
  if (!mcpConfig || mcpConfig.mode === "none") {
19842
20157
  return {
@@ -19846,8 +20161,8 @@ function resolveMeshCoordinatorSetup(options) {
19846
20161
  }
19847
20162
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
19848
20163
  if (mcpConfig.mode === "auto_import") {
19849
- const path26 = mcpConfig.path?.trim();
19850
- if (!path26) {
20164
+ const path27 = mcpConfig.path?.trim();
20165
+ if (!path27) {
19851
20166
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
19852
20167
  }
19853
20168
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -19858,13 +20173,13 @@ function resolveMeshCoordinatorSetup(options) {
19858
20173
  if (!mcpServer) {
19859
20174
  return {
19860
20175
  kind: "unsupported",
19861
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20176
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
19862
20177
  };
19863
20178
  }
19864
20179
  return {
19865
20180
  kind: "auto_import",
19866
20181
  serverName,
19867
- configPath: join17(workspace, path26),
20182
+ configPath: resolveMcpConfigPath(path27, workspace),
19868
20183
  configFormat: mcpConfig.format,
19869
20184
  mcpServer
19870
20185
  };
@@ -19898,13 +20213,84 @@ function resolveMeshCoordinatorSetup(options) {
19898
20213
  function renderMeshCoordinatorTemplate(template, values) {
19899
20214
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
19900
20215
  }
20216
+ function resolveMcpConfigPath(configPath, workspace) {
20217
+ const trimmed = configPath.trim();
20218
+ if (trimmed === "~") return os17.homedir();
20219
+ if (trimmed.startsWith("~/")) return join18(os17.homedir(), trimmed.slice(2));
20220
+ if (isAbsolute10(trimmed)) return trimmed;
20221
+ return join18(workspace, trimmed);
20222
+ }
19901
20223
  function resolveAdhdevMcpServerLaunch(options) {
19902
20224
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
19903
20225
  if (!entryPath) return null;
20226
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20227
+ if (!nodeExecutable) return null;
19904
20228
  return {
19905
- command: options.nodeExecutable?.trim() || process.execPath,
19906
- args: [entryPath, "--repo-mesh", options.meshId]
20229
+ command: nodeExecutable,
20230
+ args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
20231
+ };
20232
+ }
20233
+ function resolveMcpNodeExecutable(explicitExecutable) {
20234
+ const explicit = explicitExecutable?.trim();
20235
+ if (explicit) return explicit;
20236
+ const candidates = [];
20237
+ const addCandidate = (candidate) => {
20238
+ const trimmed = candidate?.trim();
20239
+ if (!trimmed) return;
20240
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20241
+ if (!candidates.includes(normalized)) candidates.push(normalized);
19907
20242
  };
20243
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20244
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20245
+ addCandidate(process.env.npm_node_execpath);
20246
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20247
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20248
+ addCandidate("/opt/homebrew/bin/node");
20249
+ addCandidate("/usr/local/bin/node");
20250
+ addCandidate("/usr/bin/node");
20251
+ addCandidate(process.execPath);
20252
+ for (const candidate of candidates) {
20253
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20254
+ }
20255
+ return null;
20256
+ }
20257
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20258
+ for (const entry of (pathValue || "").split(":")) {
20259
+ const dir = entry.trim();
20260
+ if (!dir) continue;
20261
+ addCandidate(join18(dir, "node"));
20262
+ }
20263
+ }
20264
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20265
+ const versionsDir = join18(homeDir, ".nvm", "versions", "node");
20266
+ try {
20267
+ const versionDirs = readdirSync6(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20268
+ for (const versionDir of versionDirs) {
20269
+ addCandidate(join18(versionsDir, versionDir, "bin", "node"));
20270
+ }
20271
+ } catch {
20272
+ }
20273
+ }
20274
+ function compareNodeVersionNamesDescending(a, b) {
20275
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20276
+ const left = parse(a);
20277
+ const right = parse(b);
20278
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20279
+ const diff = (right[i] || 0) - (left[i] || 0);
20280
+ if (diff !== 0) return diff;
20281
+ }
20282
+ return b.localeCompare(a);
20283
+ }
20284
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20285
+ try {
20286
+ execFileSync2(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20287
+ stdio: "ignore",
20288
+ timeout: 3e3
20289
+ });
20290
+ return true;
20291
+ } catch {
20292
+ return false;
20293
+ }
19908
20294
  }
19909
20295
  function resolveAdhdevMcpEntryPath(explicitPath) {
19910
20296
  const explicit = explicitPath?.trim();
@@ -19918,7 +20304,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19918
20304
  const addPackagedCandidates = (baseFile) => {
19919
20305
  if (!baseFile) return;
19920
20306
  const realBase = normalizeExistingPath(baseFile) || baseFile;
19921
- const dir = dirname3(realBase);
20307
+ const dir = dirname4(realBase);
19922
20308
  addCandidate(resolve13(dir, "../vendor/mcp-server/index.js"));
19923
20309
  addCandidate(resolve13(dir, "../../vendor/mcp-server/index.js"));
19924
20310
  addCandidate(resolve13(dir, "../../../vendor/mcp-server/index.js"));
@@ -19931,7 +20317,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19931
20317
  if (normalized) return normalized;
19932
20318
  }
19933
20319
  try {
19934
- const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join17(process.cwd(), "adhdev-daemon.js");
20320
+ const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join18(process.cwd(), "adhdev-daemon.js");
19935
20321
  const req = createRequire2(requireBase);
19936
20322
  const resolvedModule = req.resolve("@adhdev/mcp-server");
19937
20323
  return normalizeExistingPath(resolvedModule) || resolvedModule;
@@ -19941,7 +20327,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19941
20327
  }
19942
20328
  function normalizeExistingPath(filePath) {
19943
20329
  try {
19944
- if (!existsSync14(filePath)) return null;
20330
+ if (!existsSync15(filePath)) return null;
19945
20331
  return realpathSync2.native(filePath);
19946
20332
  } catch {
19947
20333
  return null;
@@ -19950,7 +20336,7 @@ function normalizeExistingPath(filePath) {
19950
20336
 
19951
20337
  // src/status/snapshot.ts
19952
20338
  init_config();
19953
- import * as os17 from "os";
20339
+ import * as os18 from "os";
19954
20340
  init_terminal_screen();
19955
20341
  init_logger();
19956
20342
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
@@ -20005,8 +20391,8 @@ function buildAvailableProviders(providerLoader) {
20005
20391
  }
20006
20392
  function buildMachineInfo(profile = "full") {
20007
20393
  const base = {
20008
- hostname: os17.hostname(),
20009
- platform: os17.platform()
20394
+ hostname: os18.hostname(),
20395
+ platform: os18.platform()
20010
20396
  };
20011
20397
  if (profile === "live") {
20012
20398
  return base;
@@ -20015,23 +20401,23 @@ function buildMachineInfo(profile = "full") {
20015
20401
  const memSnap2 = getHostMemorySnapshot();
20016
20402
  return {
20017
20403
  ...base,
20018
- arch: os17.arch(),
20019
- cpus: os17.cpus().length,
20404
+ arch: os18.arch(),
20405
+ cpus: os18.cpus().length,
20020
20406
  totalMem: memSnap2.totalMem,
20021
- release: os17.release()
20407
+ release: os18.release()
20022
20408
  };
20023
20409
  }
20024
20410
  const memSnap = getHostMemorySnapshot();
20025
20411
  return {
20026
20412
  ...base,
20027
- arch: os17.arch(),
20028
- cpus: os17.cpus().length,
20413
+ arch: os18.arch(),
20414
+ cpus: os18.cpus().length,
20029
20415
  totalMem: memSnap.totalMem,
20030
20416
  freeMem: memSnap.freeMem,
20031
20417
  availableMem: memSnap.availableMem,
20032
- loadavg: os17.loadavg(),
20033
- uptime: os17.uptime(),
20034
- release: os17.release()
20418
+ loadavg: os18.loadavg(),
20419
+ uptime: os18.uptime(),
20420
+ release: os18.release()
20035
20421
  };
20036
20422
  }
20037
20423
  function parseMessageTime(value) {
@@ -20262,17 +20648,17 @@ function buildStatusSnapshot(options) {
20262
20648
  }
20263
20649
 
20264
20650
  // src/commands/upgrade-helper.ts
20265
- import { execFileSync as execFileSync2 } from "child_process";
20651
+ import { execFileSync as execFileSync3 } from "child_process";
20266
20652
  import { spawn as spawn3 } from "child_process";
20267
20653
  import * as fs9 from "fs";
20268
- import * as os18 from "os";
20269
- import * as path20 from "path";
20654
+ import * as os19 from "os";
20655
+ import * as path21 from "path";
20270
20656
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20271
20657
  function getUpgradeLogPath() {
20272
- const home = os18.homedir();
20273
- const dir = path20.join(home, ".adhdev");
20658
+ const home = os19.homedir();
20659
+ const dir = path21.join(home, ".adhdev");
20274
20660
  fs9.mkdirSync(dir, { recursive: true });
20275
- return path20.join(dir, "daemon-upgrade.log");
20661
+ return path21.join(dir, "daemon-upgrade.log");
20276
20662
  }
20277
20663
  function appendUpgradeLog(message) {
20278
20664
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20283,14 +20669,14 @@ function appendUpgradeLog(message) {
20283
20669
  }
20284
20670
  }
20285
20671
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20286
- const binDir = path20.dirname(nodeExecutable);
20672
+ const binDir = path21.dirname(nodeExecutable);
20287
20673
  if (platform10 === "win32") {
20288
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20674
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20289
20675
  if (fs9.existsSync(npmCliPath)) {
20290
20676
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20291
20677
  }
20292
20678
  for (const candidate of ["npm.exe", "npm"]) {
20293
- const candidatePath = path20.join(binDir, candidate);
20679
+ const candidatePath = path21.join(binDir, candidate);
20294
20680
  if (fs9.existsSync(candidatePath)) {
20295
20681
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20296
20682
  }
@@ -20298,7 +20684,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20298
20684
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20299
20685
  }
20300
20686
  for (const candidate of ["npm"]) {
20301
- const candidatePath = path20.join(binDir, candidate);
20687
+ const candidatePath = path21.join(binDir, candidate);
20302
20688
  if (fs9.existsSync(candidatePath)) {
20303
20689
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20304
20690
  }
@@ -20315,13 +20701,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20315
20701
  let currentDir = resolvedPath;
20316
20702
  try {
20317
20703
  if (fs9.statSync(resolvedPath).isFile()) {
20318
- currentDir = path20.dirname(resolvedPath);
20704
+ currentDir = path21.dirname(resolvedPath);
20319
20705
  }
20320
20706
  } catch {
20321
- currentDir = path20.dirname(resolvedPath);
20707
+ currentDir = path21.dirname(resolvedPath);
20322
20708
  }
20323
20709
  while (true) {
20324
- const packageJsonPath = path20.join(currentDir, "package.json");
20710
+ const packageJsonPath = path21.join(currentDir, "package.json");
20325
20711
  try {
20326
20712
  if (fs9.existsSync(packageJsonPath)) {
20327
20713
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20332,7 +20718,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20332
20718
  }
20333
20719
  } catch {
20334
20720
  }
20335
- const parentDir = path20.dirname(currentDir);
20721
+ const parentDir = path21.dirname(currentDir);
20336
20722
  if (parentDir === currentDir) {
20337
20723
  return null;
20338
20724
  }
@@ -20340,13 +20726,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20340
20726
  }
20341
20727
  }
20342
20728
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20343
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20344
- if (path20.basename(nodeModulesDir) !== "node_modules") {
20729
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
20730
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20345
20731
  return null;
20346
20732
  }
20347
- const maybeLibDir = path20.dirname(nodeModulesDir);
20348
- if (path20.basename(maybeLibDir) === "lib") {
20349
- return path20.dirname(maybeLibDir);
20733
+ const maybeLibDir = path21.dirname(nodeModulesDir);
20734
+ if (path21.basename(maybeLibDir) === "lib") {
20735
+ return path21.dirname(maybeLibDir);
20350
20736
  }
20351
20737
  return maybeLibDir;
20352
20738
  }
@@ -20382,7 +20768,7 @@ function getNpmExecOptions(platform10 = process.platform) {
20382
20768
  }
20383
20769
  function execNpmCommandSync(args, options = {}, surface) {
20384
20770
  const execOptions = surface?.execOptions || getNpmExecOptions();
20385
- return execFileSync2(
20771
+ return execFileSync3(
20386
20772
  surface?.npmExecutable || "npm",
20387
20773
  [...surface?.npmArgsPrefix || [], ...args],
20388
20774
  {
@@ -20395,7 +20781,7 @@ function execNpmCommandSync(args, options = {}, surface) {
20395
20781
  function killPid(pid) {
20396
20782
  try {
20397
20783
  if (process.platform === "win32") {
20398
- execFileSync2("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
20784
+ execFileSync3("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
20399
20785
  } else {
20400
20786
  process.kill(pid, "SIGTERM");
20401
20787
  }
@@ -20407,7 +20793,7 @@ function killPid(pid) {
20407
20793
  function getWindowsProcessCommandLine(pid) {
20408
20794
  const pidFilter = `ProcessId=${pid}`;
20409
20795
  try {
20410
- const psOut = execFileSync2("powershell.exe", [
20796
+ const psOut = execFileSync3("powershell.exe", [
20411
20797
  "-NoProfile",
20412
20798
  "-NonInteractive",
20413
20799
  "-ExecutionPolicy",
@@ -20419,7 +20805,7 @@ function getWindowsProcessCommandLine(pid) {
20419
20805
  } catch {
20420
20806
  }
20421
20807
  try {
20422
- const wmicOut = execFileSync2("wmic", [
20808
+ const wmicOut = execFileSync3("wmic", [
20423
20809
  "process",
20424
20810
  "where",
20425
20811
  pidFilter,
@@ -20435,7 +20821,7 @@ function getProcessCommandLine(pid) {
20435
20821
  if (!Number.isFinite(pid) || pid <= 0) return null;
20436
20822
  if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
20437
20823
  try {
20438
- const text = execFileSync2("ps", ["-o", "command=", "-p", String(pid)], {
20824
+ const text = execFileSync3("ps", ["-o", "command=", "-p", String(pid)], {
20439
20825
  encoding: "utf8",
20440
20826
  timeout: 3e3,
20441
20827
  stdio: ["ignore", "pipe", "ignore"]
@@ -20461,7 +20847,7 @@ async function waitForPidExit(pid, timeoutMs) {
20461
20847
  }
20462
20848
  }
20463
20849
  function stopSessionHostProcesses(appName) {
20464
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20850
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20465
20851
  try {
20466
20852
  if (fs9.existsSync(pidFile)) {
20467
20853
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20478,7 +20864,7 @@ function stopSessionHostProcesses(appName) {
20478
20864
  }
20479
20865
  }
20480
20866
  function removeDaemonPidFile() {
20481
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
20867
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20482
20868
  try {
20483
20869
  fs9.unlinkSync(pidFile);
20484
20870
  } catch {
@@ -20489,7 +20875,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20489
20875
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20490
20876
  if (!npmRoot) return;
20491
20877
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20492
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
20878
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20493
20879
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20494
20880
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20495
20881
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20497,25 +20883,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20497
20883
  }
20498
20884
  if (pkgName.startsWith("@")) {
20499
20885
  const [scope, name] = pkgName.split("/");
20500
- const scopeDir = path20.join(npmRoot, scope);
20886
+ const scopeDir = path21.join(npmRoot, scope);
20501
20887
  if (!fs9.existsSync(scopeDir)) return;
20502
20888
  for (const entry of fs9.readdirSync(scopeDir)) {
20503
20889
  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)}`);
20890
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
20891
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20506
20892
  }
20507
20893
  } else {
20508
20894
  for (const entry of fs9.readdirSync(npmRoot)) {
20509
20895
  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)}`);
20896
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
20897
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20512
20898
  }
20513
20899
  }
20514
20900
  if (fs9.existsSync(binDir)) {
20515
20901
  for (const entry of fs9.readdirSync(binDir)) {
20516
20902
  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)}`);
20903
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
20904
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20519
20905
  }
20520
20906
  }
20521
20907
  }
@@ -20551,7 +20937,7 @@ async function runDaemonUpgradeHelper(payload) {
20551
20937
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
20552
20938
  const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
20553
20939
  appendUpgradeLog(`Installing ${spec}`);
20554
- const installOutput = execFileSync2(
20940
+ const installOutput = execFileSync3(
20555
20941
  installCommand.command,
20556
20942
  installCommand.args,
20557
20943
  {
@@ -20616,6 +21002,56 @@ function normalizeReleaseChannel(value) {
20616
21002
  function resolveUpgradeChannel(args) {
20617
21003
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20618
21004
  }
21005
+ function readProviderPriorityFromPolicy(policy) {
21006
+ const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
21007
+ const raw = record.providerPriority;
21008
+ if (!Array.isArray(raw)) return [];
21009
+ const seen = /* @__PURE__ */ new Set();
21010
+ return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
21011
+ if (seen.has(type)) return false;
21012
+ seen.add(type);
21013
+ return true;
21014
+ });
21015
+ }
21016
+ async function resolveProviderTypeFromPriority(args) {
21017
+ if (!args.providerPriority.length) {
21018
+ return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
21019
+ }
21020
+ const failed = [];
21021
+ for (const requestedType of args.providerPriority) {
21022
+ const normalizedType = args.providerLoader.resolveAlias(requestedType);
21023
+ if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
21024
+ failed.push(`${requestedType}: disabled`);
21025
+ continue;
21026
+ }
21027
+ const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
21028
+ args.providerLoader.setCliDetectionResults([{
21029
+ id: normalizedType,
21030
+ installed: !!detected,
21031
+ path: detected?.path
21032
+ }], false);
21033
+ args.onStatusChange?.();
21034
+ if (detected) return { providerType: normalizedType };
21035
+ failed.push(`${requestedType}: not detected`);
21036
+ }
21037
+ return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
21038
+ }
21039
+ function loadYamlModule() {
21040
+ return yaml;
21041
+ }
21042
+ function getMcpServersKey(format) {
21043
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
21044
+ }
21045
+ function parseMeshCoordinatorMcpConfig(text, format) {
21046
+ if (!text.trim()) return {};
21047
+ if (format === "claude_mcp_json") return JSON.parse(text);
21048
+ const parsed = loadYamlModule().load(text);
21049
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
21050
+ }
21051
+ function serializeMeshCoordinatorMcpConfig(config, format) {
21052
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
21053
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
21054
+ }
20619
21055
  var CHAT_COMMANDS = [
20620
21056
  "send_chat",
20621
21057
  "new_chat",
@@ -20714,6 +21150,40 @@ var DaemonCommandRouter = class {
20714
21150
  constructor(deps) {
20715
21151
  this.deps = deps;
20716
21152
  }
21153
+ getCachedInlineMesh(meshId, inlineMesh) {
21154
+ if (inlineMesh && typeof inlineMesh === "object") {
21155
+ this.inlineMeshCache.set(meshId, inlineMesh);
21156
+ return inlineMesh;
21157
+ }
21158
+ return this.inlineMeshCache.get(meshId);
21159
+ }
21160
+ async getMeshForCommand(meshId, inlineMesh) {
21161
+ try {
21162
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21163
+ const mesh = getMesh3(meshId);
21164
+ if (mesh) return { mesh, inline: false };
21165
+ } catch {
21166
+ }
21167
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21168
+ return cached ? { mesh: cached, inline: true } : null;
21169
+ }
21170
+ updateInlineMeshNode(meshId, mesh, node) {
21171
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21172
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21173
+ if (idx >= 0) mesh.nodes[idx] = node;
21174
+ else mesh.nodes.push(node);
21175
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21176
+ this.inlineMeshCache.set(meshId, mesh);
21177
+ }
21178
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21179
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21180
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21181
+ if (idx === -1) return false;
21182
+ mesh.nodes.splice(idx, 1);
21183
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21184
+ this.inlineMeshCache.set(meshId, mesh);
21185
+ return true;
21186
+ }
20717
21187
  async traceSessionHostAction(action, args, run, summarizeResult) {
20718
21188
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20719
21189
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -21401,7 +21871,13 @@ var DaemonCommandRouter = class {
21401
21871
  if (!workspace) return { success: false, error: "workspace required" };
21402
21872
  try {
21403
21873
  const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21404
- const node = addNode3(meshId, { workspace });
21874
+ const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
21875
+ const readOnly = args?.readOnly === true;
21876
+ const policy = {
21877
+ ...readOnly ? { readOnly: true } : {},
21878
+ ...providerPriority.length ? { providerPriority } : {}
21879
+ };
21880
+ const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
21405
21881
  if (!node) return { success: false, error: "Mesh not found" };
21406
21882
  return { success: true, node };
21407
21883
  } catch (e) {
@@ -21413,17 +21889,98 @@ var DaemonCommandRouter = class {
21413
21889
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21414
21890
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21415
21891
  try {
21416
- const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21417
- const removed = removeNode3(meshId, nodeId);
21892
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
21893
+ const mesh = meshRecord?.mesh;
21894
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
21895
+ if (node?.isLocalWorktree && node.workspace) {
21896
+ try {
21897
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
21898
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
21899
+ if (repoRoot) {
21900
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
21901
+ await removeWorktree2(repoRoot, node.workspace);
21902
+ }
21903
+ } catch (e) {
21904
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
21905
+ }
21906
+ }
21907
+ let removed = false;
21908
+ if (meshRecord?.inline) {
21909
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
21910
+ } else {
21911
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21912
+ removed = removeNode3(meshId, nodeId);
21913
+ }
21418
21914
  return { success: true, removed };
21419
21915
  } catch (e) {
21420
21916
  return { success: false, error: e.message };
21421
21917
  }
21422
21918
  }
21919
+ case "clone_mesh_node": {
21920
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21921
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
21922
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
21923
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
21924
+ if (!meshId) return { success: false, error: "meshId required" };
21925
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
21926
+ if (!branch) return { success: false, error: "branch required" };
21927
+ try {
21928
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
21929
+ const mesh = meshRecord?.mesh;
21930
+ if (!mesh) return { success: false, error: "Mesh not found" };
21931
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
21932
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
21933
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
21934
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
21935
+ const result = await createWorktree2({
21936
+ repoRoot,
21937
+ branch,
21938
+ baseBranch,
21939
+ meshName: mesh.name
21940
+ });
21941
+ let node;
21942
+ if (meshRecord.inline) {
21943
+ const { randomUUID: randomUUID8 } = await import("crypto");
21944
+ node = {
21945
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
21946
+ workspace: result.worktreePath,
21947
+ repoRoot: result.worktreePath,
21948
+ daemonId: sourceNode.daemonId,
21949
+ userOverrides: { ...sourceNode.userOverrides || {} },
21950
+ policy: { ...sourceNode.policy || {} },
21951
+ isLocalWorktree: true,
21952
+ worktreeBranch: result.branch,
21953
+ clonedFromNodeId: sourceNodeId
21954
+ };
21955
+ this.updateInlineMeshNode(meshId, mesh, node);
21956
+ } else {
21957
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21958
+ node = addNode3(meshId, {
21959
+ workspace: result.worktreePath,
21960
+ repoRoot: result.worktreePath,
21961
+ daemonId: sourceNode.daemonId,
21962
+ userOverrides: { ...sourceNode.userOverrides || {} },
21963
+ isLocalWorktree: true,
21964
+ worktreeBranch: result.branch,
21965
+ clonedFromNodeId: sourceNodeId,
21966
+ policy: { ...sourceNode.policy || {} }
21967
+ });
21968
+ if (!node) return { success: false, error: "Failed to register worktree node" };
21969
+ }
21970
+ return {
21971
+ success: true,
21972
+ node,
21973
+ worktreePath: result.worktreePath,
21974
+ branch: result.branch
21975
+ };
21976
+ } catch (e) {
21977
+ return { success: false, error: e.message };
21978
+ }
21979
+ }
21423
21980
  // ─── Mesh Coordinator Launch ───
21424
21981
  case "launch_mesh_coordinator": {
21425
21982
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21426
- const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
21983
+ let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
21427
21984
  if (!meshId) return { success: false, error: "meshId required" };
21428
21985
  try {
21429
21986
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -21451,9 +22008,29 @@ var DaemonCommandRouter = class {
21451
22008
  }
21452
22009
  const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
21453
22010
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
22011
+ if (!cliType) {
22012
+ const resolved = await resolveProviderTypeFromPriority({
22013
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
22014
+ providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
22015
+ providerLoader: this.deps.providerLoader,
22016
+ onStatusChange: this.deps.onStatusChange
22017
+ });
22018
+ if (!resolved.providerType) {
22019
+ return {
22020
+ success: false,
22021
+ code: "mesh_coordinator_provider_priority_unusable",
22022
+ error: resolved.error || "No usable provider found from node providerPriority",
22023
+ meshId,
22024
+ cliType,
22025
+ workspace
22026
+ };
22027
+ }
22028
+ cliType = resolved.providerType;
22029
+ }
21454
22030
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21455
22031
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21456
22032
  provider: providerMeta,
22033
+ cliType,
21457
22034
  meshId,
21458
22035
  workspace
21459
22036
  });
@@ -21478,7 +22055,8 @@ var DaemonCommandRouter = class {
21478
22055
  meshCoordinatorSetup: coordinatorSetup
21479
22056
  };
21480
22057
  }
21481
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
22058
+ const configFormat = coordinatorSetup.configFormat;
22059
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21482
22060
  return {
21483
22061
  success: false,
21484
22062
  code: "mesh_coordinator_unsupported",
@@ -21488,44 +22066,93 @@ var DaemonCommandRouter = class {
21488
22066
  workspace
21489
22067
  };
21490
22068
  }
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
- }
22069
+ let systemPrompt = "";
22070
+ try {
22071
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
22072
+ } catch (error) {
22073
+ const message = error?.message || String(error);
22074
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
22075
+ return {
22076
+ success: false,
22077
+ code: "mesh_coordinator_prompt_failed",
22078
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
22079
+ meshId,
22080
+ cliType,
22081
+ workspace
22082
+ };
21501
22083
  }
22084
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22085
+ const { dirname: dirname9 } = await import("path");
22086
+ const mcpConfigPath = coordinatorSetup.configPath;
22087
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
22088
+ const returnManualFallback = (message) => ({
22089
+ success: false,
22090
+ code: "mesh_coordinator_manual_mcp_setup_required",
22091
+ error: message,
22092
+ meshId,
22093
+ cliType,
22094
+ workspace,
22095
+ meshCoordinatorSetup: hermesManualFallback
22096
+ });
21502
22097
  const mcpServerEntry = {
21503
22098
  command: coordinatorSetup.mcpServer.command,
21504
22099
  args: coordinatorSetup.mcpServer.args
21505
22100
  };
21506
22101
  if (args?.inlineMesh) {
21507
22102
  mcpServerEntry.env = {
21508
- ADHDEV_INLINE_MESH: JSON.stringify(mesh)
22103
+ ADHDEV_INLINE_MESH: JSON.stringify(mesh),
22104
+ ADHDEV_MCP_TRANSPORT: "ipc"
21509
22105
  };
21510
22106
  }
22107
+ try {
22108
+ mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
22109
+ } catch (error) {
22110
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22111
+ LOG.error("MeshCoordinator", message);
22112
+ if (hermesManualFallback) return returnManualFallback(message);
22113
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
22114
+ }
22115
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
22116
+ let existingMcpConfig = {};
22117
+ if (hadExistingMcpConfig) {
22118
+ try {
22119
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
22120
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
22121
+ } catch (error) {
22122
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
22123
+ return {
22124
+ success: false,
22125
+ code: "mesh_coordinator_config_parse_failed",
22126
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
22127
+ };
22128
+ }
22129
+ }
22130
+ const mcpServersKey = getMcpServersKey(configFormat);
22131
+ const existingServers = existingMcpConfig[mcpServersKey];
21511
22132
  const mcpConfig = {
21512
22133
  ...existingMcpConfig,
21513
- mcpServers: {
21514
- ...existingMcpConfig.mcpServers || {},
22134
+ [mcpServersKey]: {
22135
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21515
22136
  [coordinatorSetup.serverName]: mcpServerEntry
21516
22137
  }
21517
22138
  };
21518
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21519
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21520
- let systemPrompt = "";
21521
22139
  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).`;
22140
+ writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22141
+ } catch (error) {
22142
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22143
+ LOG.error("MeshCoordinator", message);
22144
+ if (hermesManualFallback) return returnManualFallback(message);
22145
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21525
22146
  }
22147
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21526
22148
  const cliArgs = [];
22149
+ const launchEnv = {};
21527
22150
  if (systemPrompt) {
21528
- cliArgs.push("--append-system-prompt", systemPrompt);
22151
+ if (configFormat === "hermes_config_yaml") {
22152
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22153
+ } else {
22154
+ cliArgs.push("--append-system-prompt", systemPrompt);
22155
+ }
21529
22156
  }
21530
22157
  if (cliType === "claude-cli") {
21531
22158
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21534,6 +22161,7 @@ var DaemonCommandRouter = class {
21534
22161
  cliType,
21535
22162
  dir: workspace,
21536
22163
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22164
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21537
22165
  settings: {
21538
22166
  meshCoordinatorFor: meshId
21539
22167
  }
@@ -21713,6 +22341,12 @@ var DaemonStatusReporter = class {
21713
22341
  if (providerType) {
21714
22342
  payload.providerType = providerType;
21715
22343
  }
22344
+ if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
22345
+ payload.providerSessionId = event.providerSessionId.trim();
22346
+ }
22347
+ if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
22348
+ payload.workspaceName = event.workspaceName.trim();
22349
+ }
21716
22350
  if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
21717
22351
  payload.duration = event.duration;
21718
22352
  }
@@ -22960,7 +23594,10 @@ var ProviderInstanceManager = class {
22960
23594
  this.instances.get(id).dispose();
22961
23595
  }
22962
23596
  this.instances.set(id, instance);
22963
- await instance.init(context);
23597
+ await instance.init({
23598
+ ...context,
23599
+ emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
23600
+ });
22964
23601
  }
22965
23602
  /**
22966
23603
  * Instance remove
@@ -23122,6 +23759,17 @@ var ProviderInstanceManager = class {
23122
23759
  onEvent(listener) {
23123
23760
  this.eventListeners.push(listener);
23124
23761
  }
23762
+ emitProviderEvent(providerType, instanceId, event) {
23763
+ const payload = {
23764
+ ...event,
23765
+ providerType,
23766
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
23767
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
23768
+ };
23769
+ for (const listener of this.eventListeners) {
23770
+ listener(payload);
23771
+ }
23772
+ }
23125
23773
  emitPendingEvents(providerType, state, extra = {}) {
23126
23774
  for (const event of state.pendingEvents) {
23127
23775
  for (const listener of this.eventListeners) {
@@ -23194,11 +23842,11 @@ var ProviderInstanceManager = class {
23194
23842
 
23195
23843
  // src/providers/version-archive.ts
23196
23844
  import * as fs11 from "fs";
23197
- import * as path21 from "path";
23198
- import * as os19 from "os";
23845
+ import * as path22 from "path";
23846
+ import * as os20 from "os";
23199
23847
  import { execSync as execSync5 } from "child_process";
23200
23848
  import { platform as platform8 } from "os";
23201
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
23849
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23202
23850
  var MAX_ENTRIES_PER_PROVIDER = 20;
23203
23851
  var VersionArchive = class {
23204
23852
  history = {};
@@ -23245,7 +23893,7 @@ var VersionArchive = class {
23245
23893
  }
23246
23894
  save() {
23247
23895
  try {
23248
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
23896
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23249
23897
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23250
23898
  } catch {
23251
23899
  }
@@ -23301,8 +23949,8 @@ function getVersion(binary, versionCommand) {
23301
23949
  function checkPathExists2(paths) {
23302
23950
  for (const p of paths) {
23303
23951
  if (p.includes("*")) {
23304
- const home = os19.homedir();
23305
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
23952
+ const home = os20.homedir();
23953
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23306
23954
  if (fs11.existsSync(resolved)) return resolved;
23307
23955
  } else {
23308
23956
  if (fs11.existsSync(p)) return p;
@@ -23312,7 +23960,7 @@ function checkPathExists2(paths) {
23312
23960
  }
23313
23961
  function getMacAppVersion(appPath) {
23314
23962
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
23315
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
23963
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23316
23964
  if (!fs11.existsSync(plistPath)) return null;
23317
23965
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23318
23966
  return raw || null;
@@ -23338,7 +23986,7 @@ async function detectAllVersions(loader, archive) {
23338
23986
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23339
23987
  let resolvedBin = cliBin;
23340
23988
  if (!resolvedBin && appPath && currentOs === "darwin") {
23341
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23989
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23342
23990
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23343
23991
  }
23344
23992
  info.installed = !!(appPath || resolvedBin);
@@ -23379,7 +24027,7 @@ async function detectAllVersions(loader, archive) {
23379
24027
  // src/daemon/dev-server.ts
23380
24028
  import * as http2 from "http";
23381
24029
  import * as fs15 from "fs";
23382
- import * as path25 from "path";
24030
+ import * as path26 from "path";
23383
24031
  init_config();
23384
24032
 
23385
24033
  // src/daemon/scaffold-template.ts
@@ -23731,7 +24379,7 @@ init_logger();
23731
24379
  // src/daemon/dev-cdp-handlers.ts
23732
24380
  init_logger();
23733
24381
  import * as fs12 from "fs";
23734
- import * as path22 from "path";
24382
+ import * as path23 from "path";
23735
24383
  async function handleCdpEvaluate(ctx, req, res) {
23736
24384
  const body = await ctx.readBody(req);
23737
24385
  const { expression, timeout, ideType } = body;
@@ -23909,17 +24557,17 @@ async function handleScriptHints(ctx, type, _req, res) {
23909
24557
  return;
23910
24558
  }
23911
24559
  let scriptsPath = "";
23912
- const directScripts = path22.join(dir, "scripts.js");
24560
+ const directScripts = path23.join(dir, "scripts.js");
23913
24561
  if (fs12.existsSync(directScripts)) {
23914
24562
  scriptsPath = directScripts;
23915
24563
  } else {
23916
- const scriptsDir = path22.join(dir, "scripts");
24564
+ const scriptsDir = path23.join(dir, "scripts");
23917
24565
  if (fs12.existsSync(scriptsDir)) {
23918
24566
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
23919
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
24567
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
23920
24568
  }).sort().reverse();
23921
24569
  for (const ver of versions) {
23922
- const p = path22.join(scriptsDir, ver, "scripts.js");
24570
+ const p = path23.join(scriptsDir, ver, "scripts.js");
23923
24571
  if (fs12.existsSync(p)) {
23924
24572
  scriptsPath = p;
23925
24573
  break;
@@ -24748,7 +25396,7 @@ async function handleDomContext(ctx, type, req, res) {
24748
25396
 
24749
25397
  // src/daemon/dev-cli-debug.ts
24750
25398
  import * as fs13 from "fs";
24751
- import * as path23 from "path";
25399
+ import * as path24 from "path";
24752
25400
  function slugifyFixtureName(value) {
24753
25401
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24754
25402
  return normalized || `fixture-${Date.now()}`;
@@ -24758,11 +25406,11 @@ function getCliFixtureDir(ctx, type) {
24758
25406
  if (!providerDir) {
24759
25407
  throw new Error(`Provider directory not found for '${type}'`);
24760
25408
  }
24761
- return path23.join(providerDir, "fixtures");
25409
+ return path24.join(providerDir, "fixtures");
24762
25410
  }
24763
25411
  function readCliFixture(ctx, type, name) {
24764
25412
  const fixtureDir = getCliFixtureDir(ctx, type);
24765
- const filePath = path23.join(fixtureDir, `${name}.json`);
25413
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24766
25414
  if (!fs13.existsSync(filePath)) {
24767
25415
  throw new Error(`Fixture not found: ${filePath}`);
24768
25416
  }
@@ -25529,7 +26177,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25529
26177
  },
25530
26178
  notes: typeof body?.notes === "string" ? body.notes : void 0
25531
26179
  };
25532
- const filePath = path23.join(fixtureDir, `${name}.json`);
26180
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25533
26181
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25534
26182
  ctx.json(res, 200, {
25535
26183
  saved: true,
@@ -25553,7 +26201,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25553
26201
  return;
25554
26202
  }
25555
26203
  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);
26204
+ const fullPath = path24.join(fixtureDir, file);
25557
26205
  try {
25558
26206
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25559
26207
  return {
@@ -25689,8 +26337,8 @@ async function handleCliRaw(ctx, req, res) {
25689
26337
 
25690
26338
  // src/daemon/dev-auto-implement.ts
25691
26339
  import * as fs14 from "fs";
25692
- import * as path24 from "path";
25693
- import * as os20 from "os";
26340
+ import * as path25 from "path";
26341
+ import * as os21 from "os";
25694
26342
  function getAutoImplPid(ctx) {
25695
26343
  const pid = ctx.autoImplProcess?.pid;
25696
26344
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25739,22 +26387,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25739
26387
  if (!fs14.existsSync(scriptsDir)) return null;
25740
26388
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25741
26389
  try {
25742
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
26390
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25743
26391
  } catch {
25744
26392
  return false;
25745
26393
  }
25746
26394
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25747
26395
  if (versions.length === 0) return null;
25748
- return path24.join(scriptsDir, versions[0]);
26396
+ return path25.join(scriptsDir, versions[0]);
25749
26397
  }
25750
26398
  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}`)) {
26399
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26400
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26401
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26402
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25755
26403
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25756
26404
  }
25757
- if (path24.basename(desiredDir) !== type) {
26405
+ if (path25.basename(desiredDir) !== type) {
25758
26406
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25759
26407
  }
25760
26408
  const sourceDir = ctx.findProviderDir(type);
@@ -25762,11 +26410,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25762
26410
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25763
26411
  }
25764
26412
  if (!fs14.existsSync(desiredDir)) {
25765
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
26413
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25766
26414
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25767
26415
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25768
26416
  }
25769
- const providerJson = path24.join(desiredDir, "provider.json");
26417
+ const providerJson = path25.join(desiredDir, "provider.json");
25770
26418
  if (!fs14.existsSync(providerJson)) {
25771
26419
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25772
26420
  }
@@ -25777,13 +26425,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25777
26425
  const refDir = ctx.findProviderDir(referenceType);
25778
26426
  if (!refDir || !fs14.existsSync(refDir)) return {};
25779
26427
  const referenceScripts = {};
25780
- const scriptsDir = path24.join(refDir, "scripts");
26428
+ const scriptsDir = path25.join(refDir, "scripts");
25781
26429
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25782
26430
  if (!latestDir) return referenceScripts;
25783
26431
  for (const file of fs14.readdirSync(latestDir)) {
25784
26432
  if (!file.endsWith(".js")) continue;
25785
26433
  try {
25786
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
26434
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25787
26435
  } catch {
25788
26436
  }
25789
26437
  }
@@ -25891,9 +26539,9 @@ async function handleAutoImplement(ctx, type, req, res) {
25891
26539
  });
25892
26540
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
25893
26541
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
25894
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
26542
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
25895
26543
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
25896
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26544
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25897
26545
  fs14.writeFileSync(promptFile, prompt, "utf-8");
25898
26546
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
25899
26547
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26046,7 +26694,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26046
26694
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26047
26695
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26048
26696
  let shellCmd;
26049
- const isWin = os20.platform() === "win32";
26697
+ const isWin = os21.platform() === "win32";
26050
26698
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26051
26699
  const promptMode = autoImpl?.promptMode ?? "stdin";
26052
26700
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26085,7 +26733,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26085
26733
  try {
26086
26734
  const pty = __require("node-pty");
26087
26735
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26088
- const isWin2 = os20.platform() === "win32";
26736
+ const isWin2 = os21.platform() === "win32";
26089
26737
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26090
26738
  name: "xterm-256color",
26091
26739
  cols: 120,
@@ -26325,7 +26973,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26325
26973
  setMode: "set_mode.js"
26326
26974
  };
26327
26975
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26328
- const scriptsDir = path24.join(providerDir, "scripts");
26976
+ const scriptsDir = path25.join(providerDir, "scripts");
26329
26977
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26330
26978
  if (latestScriptsDir) {
26331
26979
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26336,7 +26984,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26336
26984
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26337
26985
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26338
26986
  try {
26339
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
26987
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26340
26988
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26341
26989
  lines.push("```javascript");
26342
26990
  lines.push(content);
@@ -26353,7 +27001,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26353
27001
  lines.push("");
26354
27002
  for (const file of refFiles) {
26355
27003
  try {
26356
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27004
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26357
27005
  lines.push(`### \`${file}\` \u{1F512}`);
26358
27006
  lines.push("```javascript");
26359
27007
  lines.push(content);
@@ -26394,10 +27042,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26394
27042
  lines.push("");
26395
27043
  }
26396
27044
  }
26397
- const docsDir = path24.join(providerDir, "../../docs");
27045
+ const docsDir = path25.join(providerDir, "../../docs");
26398
27046
  const loadGuide = (name) => {
26399
27047
  try {
26400
- const p = path24.join(docsDir, name);
27048
+ const p = path25.join(docsDir, name);
26401
27049
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26402
27050
  } catch {
26403
27051
  }
@@ -26634,7 +27282,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26634
27282
  parseApproval: "parse_approval.js"
26635
27283
  };
26636
27284
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26637
- const scriptsDir = path24.join(providerDir, "scripts");
27285
+ const scriptsDir = path25.join(providerDir, "scripts");
26638
27286
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26639
27287
  if (latestScriptsDir) {
26640
27288
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26646,7 +27294,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26646
27294
  if (!file.endsWith(".js")) continue;
26647
27295
  if (!targetFileNames.has(file)) continue;
26648
27296
  try {
26649
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27297
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26650
27298
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26651
27299
  lines.push("```javascript");
26652
27300
  lines.push(content);
@@ -26662,7 +27310,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26662
27310
  lines.push("");
26663
27311
  for (const file of refFiles) {
26664
27312
  try {
26665
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27313
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26666
27314
  lines.push(`### \`${file}\` \u{1F512}`);
26667
27315
  lines.push("```javascript");
26668
27316
  lines.push(content);
@@ -26695,10 +27343,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26695
27343
  lines.push("");
26696
27344
  }
26697
27345
  }
26698
- const docsDir = path24.join(providerDir, "../../docs");
27346
+ const docsDir = path25.join(providerDir, "../../docs");
26699
27347
  const loadGuide = (name) => {
26700
27348
  try {
26701
- const p = path24.join(docsDir, name);
27349
+ const p = path25.join(docsDir, name);
26702
27350
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26703
27351
  } catch {
26704
27352
  }
@@ -27145,8 +27793,8 @@ var DevServer = class _DevServer {
27145
27793
  }
27146
27794
  getEndpointList() {
27147
27795
  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}`;
27796
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27797
+ return `${r.method.padEnd(5)} ${path27}`;
27150
27798
  });
27151
27799
  }
27152
27800
  async start(port = DEV_SERVER_PORT) {
@@ -27434,12 +28082,12 @@ var DevServer = class _DevServer {
27434
28082
  // ─── DevConsole SPA ───
27435
28083
  getConsoleDistDir() {
27436
28084
  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")
28085
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
28086
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
28087
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27440
28088
  ];
27441
28089
  for (const dir of candidates) {
27442
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
28090
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27443
28091
  }
27444
28092
  return null;
27445
28093
  }
@@ -27449,7 +28097,7 @@ var DevServer = class _DevServer {
27449
28097
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27450
28098
  return;
27451
28099
  }
27452
- const htmlPath = path25.join(distDir, "index.html");
28100
+ const htmlPath = path26.join(distDir, "index.html");
27453
28101
  try {
27454
28102
  const html = fs15.readFileSync(htmlPath, "utf-8");
27455
28103
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27474,15 +28122,15 @@ var DevServer = class _DevServer {
27474
28122
  this.json(res, 404, { error: "Not found" });
27475
28123
  return;
27476
28124
  }
27477
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27478
- const filePath = path25.join(distDir, safePath);
28125
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28126
+ const filePath = path26.join(distDir, safePath);
27479
28127
  if (!filePath.startsWith(distDir)) {
27480
28128
  this.json(res, 403, { error: "Forbidden" });
27481
28129
  return;
27482
28130
  }
27483
28131
  try {
27484
28132
  const content = fs15.readFileSync(filePath);
27485
- const ext = path25.extname(filePath);
28133
+ const ext = path26.extname(filePath);
27486
28134
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27487
28135
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27488
28136
  res.end(content);
@@ -27595,9 +28243,9 @@ var DevServer = class _DevServer {
27595
28243
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27596
28244
  if (entry.isDirectory()) {
27597
28245
  files.push({ path: rel, size: 0, type: "dir" });
27598
- scan(path25.join(d, entry.name), rel);
28246
+ scan(path26.join(d, entry.name), rel);
27599
28247
  } else {
27600
- const stat2 = fs15.statSync(path25.join(d, entry.name));
28248
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27601
28249
  files.push({ path: rel, size: stat2.size, type: "file" });
27602
28250
  }
27603
28251
  }
@@ -27620,7 +28268,7 @@ var DevServer = class _DevServer {
27620
28268
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27621
28269
  return;
27622
28270
  }
27623
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28271
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27624
28272
  if (!fullPath.startsWith(dir)) {
27625
28273
  this.json(res, 403, { error: "Forbidden" });
27626
28274
  return;
@@ -27645,14 +28293,14 @@ var DevServer = class _DevServer {
27645
28293
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27646
28294
  return;
27647
28295
  }
27648
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28296
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27649
28297
  if (!fullPath.startsWith(dir)) {
27650
28298
  this.json(res, 403, { error: "Forbidden" });
27651
28299
  return;
27652
28300
  }
27653
28301
  try {
27654
28302
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27655
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28303
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27656
28304
  fs15.writeFileSync(fullPath, content, "utf-8");
27657
28305
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27658
28306
  this.providerLoader.reload();
@@ -27669,7 +28317,7 @@ var DevServer = class _DevServer {
27669
28317
  return;
27670
28318
  }
27671
28319
  for (const name of ["scripts.js", "provider.json"]) {
27672
- const p = path25.join(dir, name);
28320
+ const p = path26.join(dir, name);
27673
28321
  if (fs15.existsSync(p)) {
27674
28322
  const source = fs15.readFileSync(p, "utf-8");
27675
28323
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27690,8 +28338,8 @@ var DevServer = class _DevServer {
27690
28338
  this.json(res, 404, { error: `Provider not found: ${type}` });
27691
28339
  return;
27692
28340
  }
27693
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27694
- const targetPath = path25.join(dir, target);
28341
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28342
+ const targetPath = path26.join(dir, target);
27695
28343
  try {
27696
28344
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27697
28345
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -27838,7 +28486,7 @@ var DevServer = class _DevServer {
27838
28486
  }
27839
28487
  let targetDir;
27840
28488
  targetDir = this.providerLoader.getUserProviderDir(category, type);
27841
- const jsonPath = path25.join(targetDir, "provider.json");
28489
+ const jsonPath = path26.join(targetDir, "provider.json");
27842
28490
  if (fs15.existsSync(jsonPath)) {
27843
28491
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
27844
28492
  return;
@@ -27850,8 +28498,8 @@ var DevServer = class _DevServer {
27850
28498
  const createdFiles = ["provider.json"];
27851
28499
  if (result.files) {
27852
28500
  for (const [relPath, content] of Object.entries(result.files)) {
27853
- const fullPath = path25.join(targetDir, relPath);
27854
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28501
+ const fullPath = path26.join(targetDir, relPath);
28502
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27855
28503
  fs15.writeFileSync(fullPath, content, "utf-8");
27856
28504
  createdFiles.push(relPath);
27857
28505
  }
@@ -27904,22 +28552,22 @@ var DevServer = class _DevServer {
27904
28552
  if (!fs15.existsSync(scriptsDir)) return null;
27905
28553
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
27906
28554
  try {
27907
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
28555
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
27908
28556
  } catch {
27909
28557
  return false;
27910
28558
  }
27911
28559
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
27912
28560
  if (versions.length === 0) return null;
27913
- return path25.join(scriptsDir, versions[0]);
28561
+ return path26.join(scriptsDir, versions[0]);
27914
28562
  }
27915
28563
  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}`)) {
28564
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
28565
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
28566
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
28567
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
27920
28568
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
27921
28569
  }
27922
- if (path25.basename(desiredDir) !== type) {
28570
+ if (path26.basename(desiredDir) !== type) {
27923
28571
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
27924
28572
  }
27925
28573
  const sourceDir = this.findProviderDir(type);
@@ -27927,11 +28575,11 @@ var DevServer = class _DevServer {
27927
28575
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
27928
28576
  }
27929
28577
  if (!fs15.existsSync(desiredDir)) {
27930
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
28578
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
27931
28579
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
27932
28580
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
27933
28581
  }
27934
- const providerJson = path25.join(desiredDir, "provider.json");
28582
+ const providerJson = path26.join(desiredDir, "provider.json");
27935
28583
  if (!fs15.existsSync(providerJson)) {
27936
28584
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
27937
28585
  }
@@ -27967,7 +28615,7 @@ var DevServer = class _DevServer {
27967
28615
  setMode: "set_mode.js"
27968
28616
  };
27969
28617
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27970
- const scriptsDir = path25.join(providerDir, "scripts");
28618
+ const scriptsDir = path26.join(providerDir, "scripts");
27971
28619
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
27972
28620
  if (latestScriptsDir) {
27973
28621
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27978,7 +28626,7 @@ var DevServer = class _DevServer {
27978
28626
  for (const file of fs15.readdirSync(latestScriptsDir)) {
27979
28627
  if (file.endsWith(".js") && targetFileNames.has(file)) {
27980
28628
  try {
27981
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28629
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27982
28630
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27983
28631
  lines.push("```javascript");
27984
28632
  lines.push(content);
@@ -27995,7 +28643,7 @@ var DevServer = class _DevServer {
27995
28643
  lines.push("");
27996
28644
  for (const file of refFiles) {
27997
28645
  try {
27998
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28646
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27999
28647
  lines.push(`### \`${file}\` \u{1F512}`);
28000
28648
  lines.push("```javascript");
28001
28649
  lines.push(content);
@@ -28036,10 +28684,10 @@ var DevServer = class _DevServer {
28036
28684
  lines.push("");
28037
28685
  }
28038
28686
  }
28039
- const docsDir = path25.join(providerDir, "../../docs");
28687
+ const docsDir = path26.join(providerDir, "../../docs");
28040
28688
  const loadGuide = (name) => {
28041
28689
  try {
28042
- const p = path25.join(docsDir, name);
28690
+ const p = path26.join(docsDir, name);
28043
28691
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28044
28692
  } catch {
28045
28693
  }
@@ -28213,7 +28861,7 @@ var DevServer = class _DevServer {
28213
28861
  parseApproval: "parse_approval.js"
28214
28862
  };
28215
28863
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28216
- const scriptsDir = path25.join(providerDir, "scripts");
28864
+ const scriptsDir = path26.join(providerDir, "scripts");
28217
28865
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28218
28866
  if (latestScriptsDir) {
28219
28867
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28225,7 +28873,7 @@ var DevServer = class _DevServer {
28225
28873
  if (!file.endsWith(".js")) continue;
28226
28874
  if (!targetFileNames.has(file)) continue;
28227
28875
  try {
28228
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28876
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28229
28877
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28230
28878
  lines.push("```javascript");
28231
28879
  lines.push(content);
@@ -28241,7 +28889,7 @@ var DevServer = class _DevServer {
28241
28889
  lines.push("");
28242
28890
  for (const file of refFiles) {
28243
28891
  try {
28244
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28892
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28245
28893
  lines.push(`### \`${file}\` \u{1F512}`);
28246
28894
  lines.push("```javascript");
28247
28895
  lines.push(content);
@@ -28274,10 +28922,10 @@ var DevServer = class _DevServer {
28274
28922
  lines.push("");
28275
28923
  }
28276
28924
  }
28277
- const docsDir = path25.join(providerDir, "../../docs");
28925
+ const docsDir = path26.join(providerDir, "../../docs");
28278
28926
  const loadGuide = (name) => {
28279
28927
  try {
28280
- const p = path25.join(docsDir, name);
28928
+ const p = path26.join(docsDir, name);
28281
28929
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28282
28930
  } catch {
28283
28931
  }
@@ -29286,33 +29934,49 @@ init_config();
29286
29934
  // src/mesh/mesh-events.ts
29287
29935
  init_mesh_config();
29288
29936
  init_logger();
29937
+ function readNonEmptyString(value) {
29938
+ return typeof value === "string" && value.trim() ? value.trim() : "";
29939
+ }
29940
+ function formatCompletionMetadata(event) {
29941
+ const parts = [
29942
+ readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
29943
+ readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
29944
+ readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
29945
+ ].filter(Boolean);
29946
+ return parts.length > 0 ? ` (${parts.join("; ")})` : "";
29947
+ }
29289
29948
  function setupMeshEventForwarding(components) {
29290
29949
  components.instanceManager.onEvent((event) => {
29291
29950
  if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
29292
- const instanceId = event.instanceId;
29951
+ const instanceId = readNonEmptyString(event.instanceId);
29293
29952
  if (!instanceId) return;
29294
29953
  const sourceInstance = components.instanceManager.getInstance(instanceId);
29295
29954
  if (!sourceInstance || sourceInstance.category !== "cli") return;
29296
29955
  const state = sourceInstance.getState();
29297
- const workspace = state.workspace;
29956
+ const workspace = readNonEmptyString(state.workspace);
29298
29957
  if (!workspace) return;
29299
- const mesh = getMeshByRepo(workspace);
29300
- if (!mesh) return;
29958
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
29959
+ const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
29960
+ const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
29961
+ const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
29962
+ if (!meshId) return;
29301
29963
  const allInstances = components.instanceManager.getByCategory("cli");
29302
29964
  const coordinatorInstances = allInstances.filter((inst) => {
29303
29965
  const instState = inst.getState();
29304
- if (instState.settings?.meshCoordinatorFor !== mesh.id) return false;
29966
+ if (instState.settings?.meshCoordinatorFor !== meshId) return false;
29305
29967
  if (instState.instanceId === instanceId) return false;
29306
29968
  return true;
29307
29969
  });
29308
29970
  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}`;
29971
+ const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
29972
+ const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
29973
+ const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
29974
+ const metadata = formatCompletionMetadata(event);
29311
29975
  let messageText = "";
29312
29976
  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.`;
29977
+ messageText = `[System] ${nodeLabel} has completed its task and is now idle${metadata}. You may use mesh_read_chat to review its progress.`;
29314
29978
  } 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.`;
29979
+ messageText = `[System] ${nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
29316
29980
  }
29317
29981
  if (!messageText) return;
29318
29982
  for (const coord of coordinatorInstances) {
@@ -29629,6 +30293,7 @@ export {
29629
30293
  createGitWorkspaceMonitor,
29630
30294
  createInteractionId,
29631
30295
  createMesh,
30296
+ createWorktree,
29632
30297
  deleteMesh,
29633
30298
  detectAllVersions,
29634
30299
  detectCLIs,
@@ -29681,6 +30346,7 @@ export {
29681
30346
  launchWithCdp,
29682
30347
  listHostedCliRuntimes,
29683
30348
  listMeshes,
30349
+ listWorktrees,
29684
30350
  loadConfig,
29685
30351
  loadState,
29686
30352
  logCommand,
@@ -29700,6 +30366,7 @@ export {
29700
30366
  normalizeSessionModalFields,
29701
30367
  parsePorcelainV2Status,
29702
30368
  parseProviderSourceConfigUpdate,
30369
+ parseWorktreeListOutput,
29703
30370
  partitionSessionHostDiagnosticsSessions,
29704
30371
  partitionSessionHostRecords,
29705
30372
  prepareSessionChatTailUpdate,
@@ -29709,6 +30376,7 @@ export {
29709
30376
  recordDebugTrace,
29710
30377
  registerExtensionProviders,
29711
30378
  removeNode,
30379
+ removeWorktree,
29712
30380
  resetConfig,
29713
30381
  resetDebugRuntimeConfig,
29714
30382
  resetState,
@@ -29718,6 +30386,7 @@ export {
29718
30386
  resolveGitRepository,
29719
30387
  resolveSessionHostAppName,
29720
30388
  resolveSessionHostAppNameResolution,
30389
+ resolveWorktreePath,
29721
30390
  runAsyncBatch,
29722
30391
  runGit,
29723
30392
  saveConfig,