@adhdev/daemon-core 0.9.76-rc.2 → 0.9.76-rc.20

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.
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();
@@ -4983,20 +5129,23 @@ var TurnSnapshotTracker = class {
4983
5129
  }
4984
5130
  };
4985
5131
 
5132
+ // src/git/index.ts
5133
+ init_git_worktree();
5134
+
4986
5135
  // src/index.ts
4987
5136
  init_config();
4988
5137
 
4989
5138
  // src/config/workspaces.ts
4990
5139
  import * as fs from "fs";
4991
5140
  import * as os from "os";
4992
- import * as path4 from "path";
5141
+ import * as path5 from "path";
4993
5142
  import { randomUUID as randomUUID2 } from "crypto";
4994
5143
  var MAX_WORKSPACES = 50;
4995
5144
  function expandPath(p) {
4996
5145
  const t = (p || "").trim();
4997
5146
  if (!t) return "";
4998
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
4999
- return path4.resolve(t);
5147
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5148
+ return path5.resolve(t);
5000
5149
  }
5001
5150
  function validateWorkspacePath(absPath) {
5002
5151
  try {
@@ -5010,7 +5159,7 @@ function validateWorkspacePath(absPath) {
5010
5159
  }
5011
5160
  }
5012
5161
  function defaultWorkspaceLabel(absPath) {
5013
- const base = path4.basename(absPath) || absPath;
5162
+ const base = path5.basename(absPath) || absPath;
5014
5163
  return base;
5015
5164
  }
5016
5165
  function getDefaultWorkspacePath(config) {
@@ -5101,9 +5250,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5101
5250
  return getDefaultWorkspacePath(config) || void 0;
5102
5251
  }
5103
5252
  function findWorkspaceByPath(config, rawPath) {
5104
- const abs = path4.resolve(expandPath(rawPath));
5253
+ const abs = path5.resolve(expandPath(rawPath));
5105
5254
  if (!abs) return void 0;
5106
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5255
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5107
5256
  }
5108
5257
  function addWorkspaceEntry(config, rawPath, label, options) {
5109
5258
  const abs = expandPath(rawPath);
@@ -5119,7 +5268,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5119
5268
  const v = validateWorkspacePath(abs);
5120
5269
  if (!v.ok) return { error: v.error };
5121
5270
  const list = [...config.workspaces || []];
5122
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5271
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5123
5272
  return { error: "Workspace already in list" };
5124
5273
  }
5125
5274
  if (list.length >= MAX_WORKSPACES) {
@@ -5153,7 +5302,7 @@ function setDefaultWorkspaceId(config, id) {
5153
5302
  }
5154
5303
 
5155
5304
  // src/config/recent-activity.ts
5156
- import * as path5 from "path";
5305
+ import * as path6 from "path";
5157
5306
 
5158
5307
  // src/providers/summary-metadata.ts
5159
5308
  function normalizeSummaryItem(item) {
@@ -5222,9 +5371,9 @@ var MAX_ACTIVITY = 30;
5222
5371
  function normalizeWorkspace(workspace) {
5223
5372
  if (!workspace) return "";
5224
5373
  try {
5225
- return path5.resolve(expandPath(workspace));
5374
+ return path6.resolve(expandPath(workspace));
5226
5375
  } catch {
5227
- return path5.resolve(workspace);
5376
+ return path6.resolve(workspace);
5228
5377
  }
5229
5378
  }
5230
5379
  function buildRecentActivityKey(entry) {
@@ -5392,14 +5541,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5392
5541
  }
5393
5542
 
5394
5543
  // src/config/saved-sessions.ts
5395
- import * as path6 from "path";
5544
+ import * as path7 from "path";
5396
5545
  var MAX_SAVED_SESSIONS = 500;
5397
5546
  function normalizeWorkspace2(workspace) {
5398
5547
  if (!workspace) return "";
5399
5548
  try {
5400
- return path6.resolve(expandPath(workspace));
5549
+ return path7.resolve(expandPath(workspace));
5401
5550
  } catch {
5402
- return path6.resolve(workspace);
5551
+ return path7.resolve(workspace);
5403
5552
  }
5404
5553
  }
5405
5554
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5505,8 +5654,8 @@ async function syncMeshes(transport) {
5505
5654
 
5506
5655
  // src/config/state-store.ts
5507
5656
  init_config();
5508
- import { existsSync as existsSync4, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5509
- import { join as join4 } from "path";
5657
+ import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
5658
+ import { join as join5 } from "path";
5510
5659
  var DEFAULT_STATE = {
5511
5660
  recentActivity: [],
5512
5661
  savedProviderSessions: [],
@@ -5519,7 +5668,7 @@ function isPlainObject2(value) {
5519
5668
  return !!value && typeof value === "object" && !Array.isArray(value);
5520
5669
  }
5521
5670
  function getStatePath() {
5522
- return join4(getConfigDir(), "state.json");
5671
+ return join5(getConfigDir(), "state.json");
5523
5672
  }
5524
5673
  function normalizeState(raw) {
5525
5674
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -5555,7 +5704,7 @@ function normalizeState(raw) {
5555
5704
  }
5556
5705
  function loadState() {
5557
5706
  const statePath = getStatePath();
5558
- if (!existsSync4(statePath)) {
5707
+ if (!existsSync5(statePath)) {
5559
5708
  return { ...DEFAULT_STATE };
5560
5709
  }
5561
5710
  try {
@@ -5576,9 +5725,9 @@ function resetState() {
5576
5725
 
5577
5726
  // src/detection/ide-detector.ts
5578
5727
  import { execSync } from "child_process";
5579
- import { existsSync as existsSync5 } from "fs";
5728
+ import { existsSync as existsSync6 } from "fs";
5580
5729
  import { platform, homedir as homedir3 } from "os";
5581
- import * as path7 from "path";
5730
+ import * as path8 from "path";
5582
5731
  var BUILTIN_IDE_DEFINITIONS = [];
5583
5732
  var registeredIDEs = /* @__PURE__ */ new Map();
5584
5733
  function registerIDEDefinition(def) {
@@ -5597,10 +5746,10 @@ function getMergedDefinitions() {
5597
5746
  function findCliCommand(command) {
5598
5747
  const trimmed = String(command || "").trim();
5599
5748
  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;
5749
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5750
+ const candidate = trimmed.startsWith("~") ? path8.join(homedir3(), trimmed.slice(1)) : trimmed;
5751
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5752
+ return existsSync6(resolved) ? resolved : null;
5604
5753
  }
5605
5754
  try {
5606
5755
  const result = execSync(
@@ -5627,31 +5776,31 @@ function getIdeVersion(cliCommand) {
5627
5776
  function checkPathExists(paths) {
5628
5777
  const home = homedir3();
5629
5778
  for (const p of paths) {
5630
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
5779
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5631
5780
  if (normalized.includes("*")) {
5632
5781
  const username = home.split(/[\\/]/).pop() || "";
5633
5782
  const resolved = normalized.replace("*", username);
5634
- if (existsSync5(resolved)) return resolved;
5783
+ if (existsSync6(resolved)) return resolved;
5635
5784
  } else {
5636
- if (existsSync5(normalized)) return normalized;
5785
+ if (existsSync6(normalized)) return normalized;
5637
5786
  }
5638
5787
  }
5639
5788
  return null;
5640
5789
  }
5641
5790
  async function detectIDEs(providerLoader) {
5642
- const os21 = platform();
5791
+ const os22 = platform();
5643
5792
  const results = [];
5644
5793
  for (const def of getMergedDefinitions()) {
5645
5794
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5646
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
5795
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5647
5796
  let resolvedCli = cliPath;
5648
- if (!resolvedCli && appPath && os21 === "darwin") {
5797
+ if (!resolvedCli && appPath && os22 === "darwin") {
5649
5798
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5650
- if (existsSync5(bundledCli)) resolvedCli = bundledCli;
5799
+ if (existsSync6(bundledCli)) resolvedCli = bundledCli;
5651
5800
  }
5652
- if (!resolvedCli && appPath && os21 === "win32") {
5653
- const { dirname: dirname8 } = await import("path");
5654
- const appDir = dirname8(appPath);
5801
+ if (!resolvedCli && appPath && os22 === "win32") {
5802
+ const { dirname: dirname9 } = await import("path");
5803
+ const appDir = dirname9(appPath);
5655
5804
  const candidates = [
5656
5805
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5657
5806
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5660,13 +5809,13 @@ async function detectIDEs(providerLoader) {
5660
5809
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
5661
5810
  ];
5662
5811
  for (const c of candidates) {
5663
- if (existsSync5(c)) {
5812
+ if (existsSync6(c)) {
5664
5813
  resolvedCli = c;
5665
5814
  break;
5666
5815
  }
5667
5816
  }
5668
5817
  }
5669
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5818
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5670
5819
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5671
5820
  results.push({
5672
5821
  id: def.id,
@@ -5685,8 +5834,8 @@ async function detectIDEs(providerLoader) {
5685
5834
  // src/detection/cli-detector.ts
5686
5835
  import { exec } from "child_process";
5687
5836
  import * as os2 from "os";
5688
- import * as path8 from "path";
5689
- import { existsSync as existsSync6 } from "fs";
5837
+ import * as path9 from "path";
5838
+ import { existsSync as existsSync7 } from "fs";
5690
5839
  function parseVersion(raw) {
5691
5840
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
5692
5841
  return match ? match[1] : raw.split("\n")[0].slice(0, 100);
@@ -5698,19 +5847,19 @@ function shellQuote(value) {
5698
5847
  function expandHome(value) {
5699
5848
  const trimmed = value.trim();
5700
5849
  if (!trimmed.startsWith("~")) return trimmed;
5701
- return path8.join(os2.homedir(), trimmed.slice(1));
5850
+ return path9.join(os2.homedir(), trimmed.slice(1));
5702
5851
  }
5703
5852
  function isExplicitCommandPath(command) {
5704
5853
  const trimmed = command.trim();
5705
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5854
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5706
5855
  }
5707
5856
  function resolveCommandPath(command) {
5708
5857
  const trimmed = command.trim();
5709
5858
  if (!trimmed) return null;
5710
5859
  if (isExplicitCommandPath(trimmed)) {
5711
5860
  const expanded = expandHome(trimmed);
5712
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
5713
- return existsSync6(candidate) ? candidate : null;
5861
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5862
+ return existsSync7(candidate) ? candidate : null;
5714
5863
  }
5715
5864
  return null;
5716
5865
  }
@@ -7978,9 +8127,9 @@ ${cleanBody}`;
7978
8127
 
7979
8128
  // src/config/chat-history.ts
7980
8129
  import * as fs3 from "fs";
7981
- import * as path10 from "path";
8130
+ import * as path11 from "path";
7982
8131
  import * as os5 from "os";
7983
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8132
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
7984
8133
  var RETAIN_DAYS = 30;
7985
8134
  var SAVED_HISTORY_INDEX_VERSION = 1;
7986
8135
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8143,7 +8292,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8143
8292
  function buildSavedHistoryFileSignatureMap(dir, files) {
8144
8293
  return new Map(files.map((file) => {
8145
8294
  try {
8146
- const stat2 = fs3.statSync(path10.join(dir, file));
8295
+ const stat2 = fs3.statSync(path11.join(dir, file));
8147
8296
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8148
8297
  } catch {
8149
8298
  return [file, `${file}:missing`];
@@ -8154,7 +8303,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8154
8303
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8155
8304
  }
8156
8305
  function getSavedHistoryIndexFilePath(dir) {
8157
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8306
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8158
8307
  }
8159
8308
  function getSavedHistoryIndexLockPath(dir) {
8160
8309
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8256,7 +8405,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8256
8405
  }
8257
8406
  for (const file of Array.from(currentEntries.keys())) {
8258
8407
  if (incomingFiles.has(file)) continue;
8259
- if (!fs3.existsSync(path10.join(dir, file))) {
8408
+ if (!fs3.existsSync(path11.join(dir, file))) {
8260
8409
  currentEntries.delete(file);
8261
8410
  }
8262
8411
  }
@@ -8282,7 +8431,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8282
8431
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8283
8432
  const files = listHistoryFiles(dir);
8284
8433
  for (const file of files) {
8285
- const stat2 = fs3.statSync(path10.join(dir, file));
8434
+ const stat2 = fs3.statSync(path11.join(dir, file));
8286
8435
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8287
8436
  }
8288
8437
  return false;
@@ -8292,14 +8441,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8292
8441
  }
8293
8442
  function buildSavedHistoryFileSignature(dir, file) {
8294
8443
  try {
8295
- const stat2 = fs3.statSync(path10.join(dir, file));
8444
+ const stat2 = fs3.statSync(path11.join(dir, file));
8296
8445
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8297
8446
  } catch {
8298
8447
  return `${file}:missing`;
8299
8448
  }
8300
8449
  }
8301
8450
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8302
- const filePath = path10.join(dir, file);
8451
+ const filePath = path11.join(dir, file);
8303
8452
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8304
8453
  const currentEntry = entries.get(file) || null;
8305
8454
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8372,7 +8521,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8372
8521
  function computeSavedHistoryFileSummary(dir, file) {
8373
8522
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8374
8523
  if (!historySessionId) return null;
8375
- const filePath = path10.join(dir, file);
8524
+ const filePath = path11.join(dir, file);
8376
8525
  const content = fs3.readFileSync(filePath, "utf-8");
8377
8526
  const lines = content.split("\n").filter(Boolean);
8378
8527
  let messageCount = 0;
@@ -8459,7 +8608,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8459
8608
  const summaryBySessionId = /* @__PURE__ */ new Map();
8460
8609
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8461
8610
  for (const file of files.slice().sort()) {
8462
- const filePath = path10.join(dir, file);
8611
+ const filePath = path11.join(dir, file);
8463
8612
  const signature = fileSignatures.get(file) || `${file}:missing`;
8464
8613
  const cached = savedHistoryFileSummaryCache.get(filePath);
8465
8614
  const persisted = persistedEntries.get(file);
@@ -8579,12 +8728,12 @@ var ChatHistoryWriter = class {
8579
8728
  });
8580
8729
  }
8581
8730
  if (newMessages.length === 0) return;
8582
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8731
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8583
8732
  fs3.mkdirSync(dir, { recursive: true });
8584
8733
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8585
8734
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8586
8735
  const fileName = `${filePrefix}${date}.jsonl`;
8587
- const filePath = path10.join(dir, fileName);
8736
+ const filePath = path11.join(dir, fileName);
8588
8737
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8589
8738
  fs3.appendFileSync(filePath, lines, "utf-8");
8590
8739
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8675,11 +8824,11 @@ var ChatHistoryWriter = class {
8675
8824
  const ws = String(workspace || "").trim();
8676
8825
  if (!id || !ws) return;
8677
8826
  try {
8678
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8827
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8679
8828
  fs3.mkdirSync(dir, { recursive: true });
8680
8829
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8681
8830
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8682
- const filePath = path10.join(dir, fileName);
8831
+ const filePath = path11.join(dir, fileName);
8683
8832
  const record = {
8684
8833
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8685
8834
  receivedAt: Date.now(),
@@ -8725,14 +8874,14 @@ var ChatHistoryWriter = class {
8725
8874
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8726
8875
  this.lastSeenCounts.delete(fromDedupKey);
8727
8876
  }
8728
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8877
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8729
8878
  if (!fs3.existsSync(dir)) return;
8730
8879
  const fromPrefix = `${this.sanitize(fromId)}_`;
8731
8880
  const toPrefix = `${this.sanitize(toId)}_`;
8732
8881
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8733
8882
  for (const file of files) {
8734
- const sourcePath = path10.join(dir, file);
8735
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8883
+ const sourcePath = path11.join(dir, file);
8884
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8736
8885
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8737
8886
  const rewritten = sourceLines.map((line) => {
8738
8887
  try {
@@ -8766,13 +8915,13 @@ var ChatHistoryWriter = class {
8766
8915
  const sessionId = String(historySessionId || "").trim();
8767
8916
  if (!sessionId) return;
8768
8917
  try {
8769
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8918
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8770
8919
  if (!fs3.existsSync(dir)) return;
8771
8920
  const prefix = `${this.sanitize(sessionId)}_`;
8772
8921
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8773
8922
  const seen = /* @__PURE__ */ new Set();
8774
8923
  for (const file of files) {
8775
- const filePath = path10.join(dir, file);
8924
+ const filePath = path11.join(dir, file);
8776
8925
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8777
8926
  const next = [];
8778
8927
  for (const line of lines) {
@@ -8826,11 +8975,11 @@ var ChatHistoryWriter = class {
8826
8975
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
8827
8976
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
8828
8977
  for (const dir of agentDirs) {
8829
- const dirPath = path10.join(HISTORY_DIR, dir.name);
8978
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
8830
8979
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
8831
8980
  let removedAny = false;
8832
8981
  for (const file of files) {
8833
- const filePath = path10.join(dirPath, file);
8982
+ const filePath = path11.join(dirPath, file);
8834
8983
  const stat2 = fs3.statSync(filePath);
8835
8984
  if (stat2.mtimeMs < cutoff) {
8836
8985
  fs3.unlinkSync(filePath);
@@ -8880,13 +9029,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
8880
9029
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
8881
9030
  try {
8882
9031
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8883
- const dir = path10.join(HISTORY_DIR, sanitized);
9032
+ const dir = path11.join(HISTORY_DIR, sanitized);
8884
9033
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
8885
9034
  const files = listHistoryFiles(dir, historySessionId);
8886
9035
  const allMessages = [];
8887
9036
  const seen = /* @__PURE__ */ new Set();
8888
9037
  for (const file of files) {
8889
- const filePath = path10.join(dir, file);
9038
+ const filePath = path11.join(dir, file);
8890
9039
  const content = fs3.readFileSync(filePath, "utf-8");
8891
9040
  const lines = content.trim().split("\n").filter(Boolean);
8892
9041
  for (let i = 0; i < lines.length; i++) {
@@ -8910,7 +9059,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
8910
9059
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8911
9060
  try {
8912
9061
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
8913
- const dir = path10.join(HISTORY_DIR, sanitized);
9062
+ const dir = path11.join(HISTORY_DIR, sanitized);
8914
9063
  if (!fs3.existsSync(dir)) {
8915
9064
  savedHistorySessionCache.delete(sanitized);
8916
9065
  return { sessions: [], hasMore: false };
@@ -8971,11 +9120,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
8971
9120
  }
8972
9121
  function readExistingSessionStartRecord(agentType, historySessionId) {
8973
9122
  try {
8974
- const dir = path10.join(HISTORY_DIR, agentType);
9123
+ const dir = path11.join(HISTORY_DIR, agentType);
8975
9124
  if (!fs3.existsSync(dir)) return null;
8976
9125
  const files = listHistoryFiles(dir, historySessionId).sort();
8977
9126
  for (const file of files) {
8978
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9127
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
8979
9128
  for (const line of lines) {
8980
9129
  try {
8981
9130
  const parsed = JSON.parse(line);
@@ -8995,16 +9144,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
8995
9144
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
8996
9145
  if (records.length === 0) return false;
8997
9146
  try {
8998
- const dir = path10.join(HISTORY_DIR, agentType);
9147
+ const dir = path11.join(HISTORY_DIR, agentType);
8999
9148
  fs3.mkdirSync(dir, { recursive: true });
9000
9149
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9001
9150
  for (const file of fs3.readdirSync(dir)) {
9002
9151
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9003
- fs3.unlinkSync(path10.join(dir, file));
9152
+ fs3.unlinkSync(path11.join(dir, file));
9004
9153
  }
9005
9154
  }
9006
9155
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9007
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9156
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9008
9157
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9009
9158
  `, "utf-8");
9010
9159
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -10999,6 +11148,14 @@ function getActiveChatOptions(profile) {
10999
11148
  if (profile === "full") return {};
11000
11149
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11001
11150
  }
11151
+ function resolveSessionStatus(activeChat, providerStatus) {
11152
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11153
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11154
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11155
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11156
+ if (topLevelStatus !== "idle") return topLevelStatus;
11157
+ return chatStatus;
11158
+ }
11002
11159
  function shouldIncludeSessionControls(profile) {
11003
11160
  return profile !== "live";
11004
11161
  }
@@ -11077,9 +11234,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11077
11234
  providerName: state.name,
11078
11235
  kind: "workspace",
11079
11236
  transport: "cdp-page",
11080
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11081
- activeModal: activeChat?.activeModal || null
11082
- }),
11237
+ status: resolveSessionStatus(activeChat, state.status),
11083
11238
  title,
11084
11239
  workspace,
11085
11240
  ...git && { git },
@@ -11114,9 +11269,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11114
11269
  providerSessionId: ext.providerSessionId,
11115
11270
  kind: "agent",
11116
11271
  transport: "cdp-webview",
11117
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11118
- activeModal: activeChat?.activeModal || null
11119
- }),
11272
+ status: resolveSessionStatus(activeChat, ext.status),
11120
11273
  title: activeChat?.title || ext.name,
11121
11274
  workspace,
11122
11275
  ...git && { git },
@@ -11166,9 +11319,7 @@ function buildCliSession(state, options) {
11166
11319
  providerSessionId: state.providerSessionId,
11167
11320
  kind: "agent",
11168
11321
  transport: "pty",
11169
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11170
- activeModal: activeChat?.activeModal || null
11171
- }),
11322
+ status: resolveSessionStatus(activeChat, state.status),
11172
11323
  title: activeChat?.title || state.name,
11173
11324
  workspace,
11174
11325
  ...git && { git },
@@ -11216,9 +11367,7 @@ function buildAcpSession(state, options) {
11216
11367
  providerName: state.name,
11217
11368
  kind: "agent",
11218
11369
  transport: "acp",
11219
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11220
- activeModal: activeChat?.activeModal || null
11221
- }),
11370
+ status: resolveSessionStatus(activeChat, state.status),
11222
11371
  title: activeChat?.title || state.name,
11223
11372
  workspace,
11224
11373
  ...git && { git },
@@ -11341,7 +11490,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11341
11490
  // src/commands/chat-commands.ts
11342
11491
  import * as fs4 from "fs";
11343
11492
  import * as os6 from "os";
11344
- import * as path11 from "path";
11493
+ import * as path12 from "path";
11345
11494
  import { randomUUID as randomUUID5 } from "crypto";
11346
11495
 
11347
11496
  // src/providers/provider-input-support.ts
@@ -11704,6 +11853,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11704
11853
  return raw;
11705
11854
  }
11706
11855
  }
11856
+ function isGeneratingLikeStatus(status) {
11857
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
11858
+ }
11859
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
11860
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
11861
+ if (hasNonEmptyModalButtons(activeModal)) return false;
11862
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
11863
+ if (adapterRawStatus !== "idle") return false;
11864
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
11865
+ return true;
11866
+ }
11867
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
11868
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
11869
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
11870
+ }
11871
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
11872
+ if (status !== "idle") return messages;
11873
+ return messages.map((message) => {
11874
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
11875
+ const hasStreamingMeta = meta?.streaming === true;
11876
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
11877
+ return {
11878
+ ...message,
11879
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
11880
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
11881
+ };
11882
+ });
11883
+ }
11707
11884
  function buildReadChatCommandResult(payload, args) {
11708
11885
  let validatedPayload;
11709
11886
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -11852,7 +12029,7 @@ function buildDebugBundleText(bundle) {
11852
12029
  }
11853
12030
  function getChatDebugBundleDir() {
11854
12031
  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");
12032
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
11856
12033
  }
11857
12034
  function safeBundleIdSegment(value, fallback) {
11858
12035
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -11885,7 +12062,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
11885
12062
  const bundleId = createChatDebugBundleId(targetSessionId);
11886
12063
  const dir = getChatDebugBundleDir();
11887
12064
  fs4.mkdirSync(dir, { recursive: true });
11888
- const savedPath = path11.join(dir, `${bundleId}.json`);
12065
+ const savedPath = path12.join(dir, `${bundleId}.json`);
11889
12066
  const json = `${JSON.stringify(bundle, null, 2)}
11890
12067
  `;
11891
12068
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12142,10 +12319,13 @@ async function handleReadChat(h, args) {
12142
12319
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12143
12320
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12144
12321
  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}`);
12322
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12323
+ const runtimeMessageMerger = getTargetInstance(h, args);
12324
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12325
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12326
+ 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
12327
  return buildReadChatCommandResult({
12148
- messages: parsedRecord.messages,
12328
+ messages: returnedMessages,
12149
12329
  status: returnedStatus,
12150
12330
  activeModal,
12151
12331
  debugReadChat: {
@@ -12156,7 +12336,7 @@ async function handleReadChat(h, args) {
12156
12336
  returnedStatus: String(returnedStatus || ""),
12157
12337
  shouldPreferAdapterMessages: false,
12158
12338
  parsedMsgCount: parsedRecord.messages.length,
12159
- returnedMsgCount: parsedRecord.messages.length
12339
+ returnedMsgCount: returnedMessages.length
12160
12340
  },
12161
12341
  ...title ? { title } : {},
12162
12342
  ...providerSessionId ? { providerSessionId } : {},
@@ -13029,7 +13209,7 @@ async function handleResolveAction(h, args) {
13029
13209
 
13030
13210
  // src/commands/cdp-commands.ts
13031
13211
  import * as fs5 from "fs";
13032
- import * as path12 from "path";
13212
+ import * as path13 from "path";
13033
13213
  import * as os7 from "os";
13034
13214
  var KEY_TO_VK = {
13035
13215
  Backspace: 8,
@@ -13286,25 +13466,25 @@ function resolveSafePath(requestedPath) {
13286
13466
  const inputPath = rawPath || ".";
13287
13467
  const home = os7.homedir();
13288
13468
  if (inputPath.startsWith("~")) {
13289
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13469
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13290
13470
  }
13291
13471
  if (process.platform === "win32") {
13292
13472
  const normalized = normalizeWindowsRequestedPath(inputPath);
13293
- if (path12.win32.isAbsolute(normalized)) {
13294
- return path12.win32.normalize(normalized);
13473
+ if (path13.win32.isAbsolute(normalized)) {
13474
+ return path13.win32.normalize(normalized);
13295
13475
  }
13296
- return path12.win32.resolve(normalized);
13476
+ return path13.win32.resolve(normalized);
13297
13477
  }
13298
- if (path12.isAbsolute(inputPath)) {
13299
- return path12.normalize(inputPath);
13478
+ if (path13.isAbsolute(inputPath)) {
13479
+ return path13.normalize(inputPath);
13300
13480
  }
13301
- return path12.resolve(inputPath);
13481
+ return path13.resolve(inputPath);
13302
13482
  }
13303
13483
  function listDirectoryEntriesSafe(dirPath) {
13304
13484
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13305
13485
  const files = [];
13306
13486
  for (const entry of entries) {
13307
- const entryPath = path12.join(dirPath, entry.name);
13487
+ const entryPath = path13.join(dirPath, entry.name);
13308
13488
  try {
13309
13489
  if (entry.isDirectory()) {
13310
13490
  files.push({ name: entry.name, type: "directory" });
@@ -13358,7 +13538,7 @@ async function handleFileRead(h, args) {
13358
13538
  async function handleFileWrite(h, args) {
13359
13539
  try {
13360
13540
  const filePath = resolveSafePath(args?.path);
13361
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
13541
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13362
13542
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13363
13543
  return { success: true, path: filePath };
13364
13544
  } catch (e) {
@@ -14478,16 +14658,16 @@ var DaemonCommandHandler = class {
14478
14658
  // src/commands/cli-manager.ts
14479
14659
  init_provider_cli_adapter();
14480
14660
  import * as os13 from "os";
14481
- import * as path16 from "path";
14661
+ import * as path17 from "path";
14482
14662
  import * as crypto4 from "crypto";
14483
- import { existsSync as existsSync11 } from "fs";
14663
+ import { existsSync as existsSync12 } from "fs";
14484
14664
  import { execFileSync } from "child_process";
14485
14665
  import chalk from "chalk";
14486
14666
  init_config();
14487
14667
 
14488
14668
  // src/providers/cli-provider-instance.ts
14489
14669
  import * as os12 from "os";
14490
- import * as path15 from "path";
14670
+ import * as path16 from "path";
14491
14671
  import * as crypto3 from "crypto";
14492
14672
  import * as fs6 from "fs";
14493
14673
  import { createRequire } from "module";
@@ -14546,7 +14726,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14546
14726
  var CachedDatabaseSync = null;
14547
14727
  function getDatabaseSync() {
14548
14728
  if (CachedDatabaseSync) return CachedDatabaseSync;
14549
- const requireFn = typeof __require === "function" ? __require : createRequire(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14729
+ const requireFn = typeof __require === "function" ? __require : createRequire(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14550
14730
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14551
14731
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14552
14732
  if (!CachedDatabaseSync) {
@@ -14599,7 +14779,7 @@ var CliProviderInstance = class {
14599
14779
  this.providerSessionId = options?.providerSessionId;
14600
14780
  this.launchMode = options?.launchMode || "new";
14601
14781
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14602
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
14782
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14603
14783
  this.monitor = new StatusMonitor();
14604
14784
  this.historyWriter = new ChatHistoryWriter();
14605
14785
  }
@@ -15283,6 +15463,9 @@ ${effect.notification.body || ""}`.trim();
15283
15463
  );
15284
15464
  }
15285
15465
  }
15466
+ mergeRuntimeChatMessages(parsedMessages) {
15467
+ return this.mergeConversationMessages(parsedMessages);
15468
+ }
15286
15469
  mergeConversationMessages(parsedMessages) {
15287
15470
  if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
15288
15471
  return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
@@ -16617,17 +16800,17 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16617
16800
  // src/commands/cli-manager.ts
16618
16801
  function isExplicitCommand(command) {
16619
16802
  const trimmed = command.trim();
16620
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16803
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16621
16804
  }
16622
16805
  function expandExecutable(command) {
16623
16806
  const trimmed = command.trim();
16624
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16807
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16625
16808
  }
16626
16809
  function commandExists(command) {
16627
16810
  const trimmed = command.trim();
16628
16811
  if (!trimmed) return false;
16629
16812
  if (isExplicitCommand(trimmed)) {
16630
- return existsSync11(expandExecutable(trimmed));
16813
+ return existsSync12(expandExecutable(trimmed));
16631
16814
  }
16632
16815
  try {
16633
16816
  execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -16815,7 +16998,7 @@ var DaemonCliManager = class {
16815
16998
  attachExisting
16816
16999
  }) || void 0;
16817
17000
  }
16818
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17001
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
16819
17002
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16820
17003
  const provider = this.providerLoader.getMeta(normalizedType);
16821
17004
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -16829,7 +17012,7 @@ var DaemonCliManager = class {
16829
17012
  providerSessionId,
16830
17013
  attachExisting
16831
17014
  );
16832
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17015
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
16833
17016
  }
16834
17017
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
16835
17018
  }
@@ -16902,7 +17085,7 @@ var DaemonCliManager = class {
16902
17085
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
16903
17086
  const trimmed = (workingDir || "").trim();
16904
17087
  if (!trimmed) throw new Error("working directory required");
16905
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17088
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
16906
17089
  const normalizedType = this.providerLoader.resolveAlias(cliType);
16907
17090
  const rawProvider = this.providerLoader.getByAlias(cliType);
16908
17091
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17032,6 +17215,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17032
17215
  {
17033
17216
  providerSessionId: sessionBinding.providerSessionId,
17034
17217
  launchMode: sessionBinding.launchMode,
17218
+ extraEnv: options?.extraEnv,
17035
17219
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17036
17220
  this.persistRecentActivity({
17037
17221
  kind: "cli",
@@ -17052,7 +17236,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17052
17236
  resolvedCliArgs,
17053
17237
  key,
17054
17238
  sessionBinding.providerSessionId,
17055
- false
17239
+ false,
17240
+ options?.extraEnv
17056
17241
  );
17057
17242
  try {
17058
17243
  await adapter.spawn();
@@ -17281,7 +17466,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17281
17466
  dir,
17282
17467
  args?.cliArgs,
17283
17468
  args?.initialModel,
17284
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
17469
+ { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings, extraEnv: args?.env }
17285
17470
  );
17286
17471
  return {
17287
17472
  success: true,
@@ -17403,11 +17588,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17403
17588
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
17404
17589
  import * as net from "net";
17405
17590
  import * as os15 from "os";
17406
- import * as path18 from "path";
17591
+ import * as path19 from "path";
17407
17592
 
17408
17593
  // src/providers/provider-loader.ts
17409
17594
  import * as fs7 from "fs";
17410
- import * as path17 from "path";
17595
+ import * as path18 from "path";
17411
17596
  import * as os14 from "os";
17412
17597
  import * as chokidar from "chokidar";
17413
17598
  init_logger();
@@ -17731,7 +17916,7 @@ var ProviderLoader = class _ProviderLoader {
17731
17916
  try {
17732
17917
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17733
17918
  return ["ide", "extension", "cli", "acp"].some(
17734
- (category) => fs7.existsSync(path17.join(candidate, category))
17919
+ (category) => fs7.existsSync(path18.join(candidate, category))
17735
17920
  );
17736
17921
  } catch {
17737
17922
  return false;
@@ -17739,20 +17924,20 @@ var ProviderLoader = class _ProviderLoader {
17739
17924
  }
17740
17925
  static hasProviderRootMarker(candidate) {
17741
17926
  try {
17742
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17927
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17743
17928
  } catch {
17744
17929
  return false;
17745
17930
  }
17746
17931
  }
17747
17932
  detectDefaultUserDir() {
17748
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
17933
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17749
17934
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17750
17935
  const visited = /* @__PURE__ */ new Set();
17751
17936
  for (const start of this.probeStarts) {
17752
- let current = path17.resolve(start);
17937
+ let current = path18.resolve(start);
17753
17938
  while (!visited.has(current)) {
17754
17939
  visited.add(current);
17755
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17940
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17756
17941
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17757
17942
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17758
17943
  if (envOptIn || hasMarker) {
@@ -17774,7 +17959,7 @@ var ProviderLoader = class _ProviderLoader {
17774
17959
  return { path: siblingCandidate, source };
17775
17960
  }
17776
17961
  }
17777
- const parent = path17.dirname(current);
17962
+ const parent = path18.dirname(current);
17778
17963
  if (parent === current) break;
17779
17964
  current = parent;
17780
17965
  }
@@ -17784,11 +17969,11 @@ var ProviderLoader = class _ProviderLoader {
17784
17969
  constructor(options) {
17785
17970
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17786
17971
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17787
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
17972
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17788
17973
  const detected = this.detectDefaultUserDir();
17789
17974
  this.userDir = detected.path;
17790
17975
  this.userDirSource = detected.source;
17791
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
17976
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17792
17977
  this.disableUpstream = false;
17793
17978
  this.applySourceConfig({
17794
17979
  userDir: options?.userDir,
@@ -17847,7 +18032,7 @@ var ProviderLoader = class _ProviderLoader {
17847
18032
  this.userDir = detected.path;
17848
18033
  this.userDirSource = detected.source;
17849
18034
  }
17850
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18035
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17851
18036
  this.disableUpstream = this.sourceMode === "no-upstream";
17852
18037
  if (this.explicitProviderDir) {
17853
18038
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -17861,7 +18046,7 @@ var ProviderLoader = class _ProviderLoader {
17861
18046
  * Canonical provider directory shape for a given root.
17862
18047
  */
17863
18048
  getProviderDir(root, category, type) {
17864
- return path17.join(root, category, type);
18049
+ return path18.join(root, category, type);
17865
18050
  }
17866
18051
  /**
17867
18052
  * Canonical user override directory for a provider.
@@ -17888,7 +18073,7 @@ var ProviderLoader = class _ProviderLoader {
17888
18073
  resolveProviderFile(type, ...segments) {
17889
18074
  const dir = this.findProviderDirInternal(type);
17890
18075
  if (!dir) return null;
17891
- return path17.join(dir, ...segments);
18076
+ return path18.join(dir, ...segments);
17892
18077
  }
17893
18078
  /**
17894
18079
  * Load all providers (3-tier priority)
@@ -17927,7 +18112,7 @@ var ProviderLoader = class _ProviderLoader {
17927
18112
  if (!fs7.existsSync(this.upstreamDir)) return false;
17928
18113
  try {
17929
18114
  return fs7.readdirSync(this.upstreamDir).some(
17930
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18115
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
17931
18116
  );
17932
18117
  } catch {
17933
18118
  return false;
@@ -18424,8 +18609,8 @@ var ProviderLoader = class _ProviderLoader {
18424
18609
  resolved._resolvedScriptDir = entry.scriptDir;
18425
18610
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18426
18611
  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;
18612
+ const fullDir = path18.join(providerDir, entry.scriptDir);
18613
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18429
18614
  }
18430
18615
  matched = true;
18431
18616
  }
@@ -18440,8 +18625,8 @@ var ProviderLoader = class _ProviderLoader {
18440
18625
  resolved._resolvedScriptDir = base.defaultScriptDir;
18441
18626
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18442
18627
  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;
18628
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18629
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18445
18630
  }
18446
18631
  }
18447
18632
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18458,8 +18643,8 @@ var ProviderLoader = class _ProviderLoader {
18458
18643
  resolved._resolvedScriptDir = dirOverride;
18459
18644
  resolved._resolvedScriptsSource = `versions:${range}`;
18460
18645
  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;
18646
+ const fullDir = path18.join(providerDir, dirOverride);
18647
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18463
18648
  }
18464
18649
  }
18465
18650
  } else if (override.scripts) {
@@ -18475,8 +18660,8 @@ var ProviderLoader = class _ProviderLoader {
18475
18660
  resolved._resolvedScriptDir = base.defaultScriptDir;
18476
18661
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18477
18662
  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;
18663
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18664
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18480
18665
  }
18481
18666
  }
18482
18667
  }
@@ -18508,14 +18693,14 @@ var ProviderLoader = class _ProviderLoader {
18508
18693
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18509
18694
  return null;
18510
18695
  }
18511
- const dir = path17.join(providerDir, scriptDir);
18696
+ const dir = path18.join(providerDir, scriptDir);
18512
18697
  if (!fs7.existsSync(dir)) {
18513
18698
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18514
18699
  return null;
18515
18700
  }
18516
18701
  const cached = this.scriptsCache.get(dir);
18517
18702
  if (cached) return cached;
18518
- const scriptsJs = path17.join(dir, "scripts.js");
18703
+ const scriptsJs = path18.join(dir, "scripts.js");
18519
18704
  if (fs7.existsSync(scriptsJs)) {
18520
18705
  try {
18521
18706
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -18557,7 +18742,7 @@ var ProviderLoader = class _ProviderLoader {
18557
18742
  return;
18558
18743
  }
18559
18744
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18560
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
18745
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18561
18746
  this.reload();
18562
18747
  }
18563
18748
  };
@@ -18612,7 +18797,7 @@ var ProviderLoader = class _ProviderLoader {
18612
18797
  }
18613
18798
  const https = __require("https");
18614
18799
  const { execSync: execSync7 } = __require("child_process");
18615
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
18800
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18616
18801
  let prevEtag = "";
18617
18802
  let prevTimestamp = 0;
18618
18803
  try {
@@ -18672,17 +18857,17 @@ var ProviderLoader = class _ProviderLoader {
18672
18857
  return { updated: false };
18673
18858
  }
18674
18859
  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()}`);
18860
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18861
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18677
18862
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18678
18863
  fs7.mkdirSync(tmpExtract, { recursive: true });
18679
18864
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18680
18865
  const extracted = fs7.readdirSync(tmpExtract);
18681
18866
  const rootDir = extracted.find(
18682
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18867
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18683
18868
  );
18684
18869
  if (!rootDir) throw new Error("Unexpected tarball structure");
18685
- const sourceDir = path17.join(tmpExtract, rootDir);
18870
+ const sourceDir = path18.join(tmpExtract, rootDir);
18686
18871
  const backupDir = this.upstreamDir + ".bak";
18687
18872
  if (fs7.existsSync(this.upstreamDir)) {
18688
18873
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18757,8 +18942,8 @@ var ProviderLoader = class _ProviderLoader {
18757
18942
  copyDirRecursive(src, dest) {
18758
18943
  fs7.mkdirSync(dest, { recursive: true });
18759
18944
  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);
18945
+ const srcPath = path18.join(src, entry.name);
18946
+ const destPath = path18.join(dest, entry.name);
18762
18947
  if (entry.isDirectory()) {
18763
18948
  this.copyDirRecursive(srcPath, destPath);
18764
18949
  } else {
@@ -18769,7 +18954,7 @@ var ProviderLoader = class _ProviderLoader {
18769
18954
  /** .meta.json save */
18770
18955
  writeMeta(metaPath, etag, timestamp) {
18771
18956
  try {
18772
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
18957
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18773
18958
  fs7.writeFileSync(metaPath, JSON.stringify({
18774
18959
  etag,
18775
18960
  timestamp,
@@ -18786,7 +18971,7 @@ var ProviderLoader = class _ProviderLoader {
18786
18971
  const scan = (d) => {
18787
18972
  try {
18788
18973
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18789
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
18974
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18790
18975
  else if (entry.name === "provider.json") count++;
18791
18976
  }
18792
18977
  } catch {
@@ -19014,17 +19199,17 @@ var ProviderLoader = class _ProviderLoader {
19014
19199
  for (const root of searchRoots) {
19015
19200
  if (!fs7.existsSync(root)) continue;
19016
19201
  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);
19202
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19203
+ const catDir = path18.join(root, cat);
19019
19204
  if (fs7.existsSync(catDir)) {
19020
19205
  try {
19021
19206
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19022
19207
  if (!entry.isDirectory()) continue;
19023
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19208
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19024
19209
  if (fs7.existsSync(jsonPath)) {
19025
19210
  try {
19026
19211
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19027
- if (data.type === type) return path17.join(catDir, entry.name);
19212
+ if (data.type === type) return path18.join(catDir, entry.name);
19028
19213
  } catch {
19029
19214
  }
19030
19215
  }
@@ -19041,7 +19226,7 @@ var ProviderLoader = class _ProviderLoader {
19041
19226
  * (template substitution is NOT applied here — scripts.js handles that)
19042
19227
  */
19043
19228
  buildScriptWrappersFromDir(dir) {
19044
- const scriptsJs = path17.join(dir, "scripts.js");
19229
+ const scriptsJs = path18.join(dir, "scripts.js");
19045
19230
  if (fs7.existsSync(scriptsJs)) {
19046
19231
  try {
19047
19232
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -19055,7 +19240,7 @@ var ProviderLoader = class _ProviderLoader {
19055
19240
  for (const file of fs7.readdirSync(dir)) {
19056
19241
  if (!file.endsWith(".js")) continue;
19057
19242
  const scriptName = toCamel(file.replace(".js", ""));
19058
- const filePath = path17.join(dir, file);
19243
+ const filePath = path18.join(dir, file);
19059
19244
  result[scriptName] = (...args) => {
19060
19245
  try {
19061
19246
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19115,7 +19300,7 @@ var ProviderLoader = class _ProviderLoader {
19115
19300
  }
19116
19301
  const hasJson = entries.some((e) => e.name === "provider.json");
19117
19302
  if (hasJson) {
19118
- const jsonPath = path17.join(d, "provider.json");
19303
+ const jsonPath = path18.join(d, "provider.json");
19119
19304
  try {
19120
19305
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19121
19306
  const mod = JSON.parse(raw);
@@ -19136,7 +19321,7 @@ var ProviderLoader = class _ProviderLoader {
19136
19321
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19137
19322
  } else {
19138
19323
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19139
- const scriptsPath = path17.join(d, "scripts.js");
19324
+ const scriptsPath = path18.join(d, "scripts.js");
19140
19325
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19141
19326
  try {
19142
19327
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -19162,7 +19347,7 @@ var ProviderLoader = class _ProviderLoader {
19162
19347
  if (!entry.isDirectory()) continue;
19163
19348
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19164
19349
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19165
- scan(path17.join(d, entry.name));
19350
+ scan(path18.join(d, entry.name));
19166
19351
  }
19167
19352
  }
19168
19353
  };
@@ -19487,8 +19672,8 @@ function detectCurrentWorkspace(ideId) {
19487
19672
  const appNameMap = getMacAppIdentifiers();
19488
19673
  const appName = appNameMap[ideId];
19489
19674
  if (appName) {
19490
- const storagePath = path18.join(
19491
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
19675
+ const storagePath = path19.join(
19676
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19492
19677
  appName,
19493
19678
  "storage.json"
19494
19679
  );
@@ -19677,9 +19862,9 @@ init_logger();
19677
19862
 
19678
19863
  // src/logging/command-log.ts
19679
19864
  import * as fs8 from "fs";
19680
- import * as path19 from "path";
19865
+ import * as path20 from "path";
19681
19866
  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");
19867
+ 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
19868
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19684
19869
  var MAX_DAYS = 7;
19685
19870
  try {
@@ -19717,13 +19902,13 @@ function getDateStr2() {
19717
19902
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19718
19903
  }
19719
19904
  var currentDate2 = getDateStr2();
19720
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19905
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19721
19906
  var writeCount2 = 0;
19722
19907
  function checkRotation() {
19723
19908
  const today = getDateStr2();
19724
19909
  if (today !== currentDate2) {
19725
19910
  currentDate2 = today;
19726
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19911
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19727
19912
  cleanOldFiles();
19728
19913
  }
19729
19914
  }
@@ -19737,7 +19922,7 @@ function cleanOldFiles() {
19737
19922
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19738
19923
  if (dateMatch && dateMatch[1] < cutoffStr) {
19739
19924
  try {
19740
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
19925
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19741
19926
  } catch {
19742
19927
  }
19743
19928
  }
@@ -19821,13 +20006,65 @@ cleanOldFiles();
19821
20006
 
19822
20007
  // src/commands/router.ts
19823
20008
  init_logger();
20009
+ import * as yaml from "js-yaml";
19824
20010
 
19825
20011
  // src/commands/mesh-coordinator.ts
19826
- import { existsSync as existsSync14, realpathSync as realpathSync2 } from "fs";
20012
+ import { execFileSync as execFileSync2 } from "child_process";
20013
+ import { existsSync as existsSync15, readdirSync as readdirSync6, realpathSync as realpathSync2 } from "fs";
19827
20014
  import { createRequire as createRequire2 } from "module";
19828
- import { dirname as dirname3, join as join17, resolve as resolve13 } from "path";
20015
+ import * as os17 from "os";
20016
+ import { dirname as dirname4, isAbsolute as isAbsolute10, join as join18, resolve as resolve13 } from "path";
19829
20017
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
19830
20018
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20019
+ var HERMES_CLI_TYPE = "hermes-cli";
20020
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20021
+ function isHermesProvider(provider, cliType) {
20022
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20023
+ return type === HERMES_CLI_TYPE;
20024
+ }
20025
+ function resolveHermesMeshCoordinatorSetup(options) {
20026
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20027
+ meshId: options.meshId,
20028
+ nodeExecutable: options.nodeExecutable,
20029
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20030
+ });
20031
+ if (!mcpServer) {
20032
+ return {
20033
+ kind: "unsupported",
20034
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20035
+ };
20036
+ }
20037
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20038
+ if (!configPath.trim()) {
20039
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20040
+ }
20041
+ return {
20042
+ kind: "auto_import",
20043
+ serverName: DEFAULT_SERVER_NAME,
20044
+ configPath,
20045
+ configFormat: "hermes_config_yaml",
20046
+ mcpServer
20047
+ };
20048
+ }
20049
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20050
+ return {
20051
+ kind: "manual",
20052
+ serverName: DEFAULT_SERVER_NAME,
20053
+ configFormat: "hermes_config_yaml",
20054
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20055
+ requiresRestart: true,
20056
+ 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.",
20057
+ template: renderMeshCoordinatorTemplate(
20058
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20059
+ {
20060
+ meshId,
20061
+ workspace,
20062
+ serverName: DEFAULT_SERVER_NAME,
20063
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20064
+ }
20065
+ )
20066
+ };
20067
+ }
19831
20068
  function resolveMeshCoordinatorSetup(options) {
19832
20069
  const { provider, meshId, workspace } = options;
19833
20070
  const config = provider?.meshCoordinator;
@@ -19837,6 +20074,9 @@ function resolveMeshCoordinatorSetup(options) {
19837
20074
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
19838
20075
  };
19839
20076
  }
20077
+ if (isHermesProvider(provider, options.cliType)) {
20078
+ return resolveHermesMeshCoordinatorSetup(options);
20079
+ }
19840
20080
  const mcpConfig = config.mcpConfig;
19841
20081
  if (!mcpConfig || mcpConfig.mode === "none") {
19842
20082
  return {
@@ -19846,8 +20086,8 @@ function resolveMeshCoordinatorSetup(options) {
19846
20086
  }
19847
20087
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
19848
20088
  if (mcpConfig.mode === "auto_import") {
19849
- const path26 = mcpConfig.path?.trim();
19850
- if (!path26) {
20089
+ const path27 = mcpConfig.path?.trim();
20090
+ if (!path27) {
19851
20091
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
19852
20092
  }
19853
20093
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -19858,13 +20098,13 @@ function resolveMeshCoordinatorSetup(options) {
19858
20098
  if (!mcpServer) {
19859
20099
  return {
19860
20100
  kind: "unsupported",
19861
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20101
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
19862
20102
  };
19863
20103
  }
19864
20104
  return {
19865
20105
  kind: "auto_import",
19866
20106
  serverName,
19867
- configPath: join17(workspace, path26),
20107
+ configPath: resolveMcpConfigPath(path27, workspace),
19868
20108
  configFormat: mcpConfig.format,
19869
20109
  mcpServer
19870
20110
  };
@@ -19898,13 +20138,84 @@ function resolveMeshCoordinatorSetup(options) {
19898
20138
  function renderMeshCoordinatorTemplate(template, values) {
19899
20139
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
19900
20140
  }
20141
+ function resolveMcpConfigPath(configPath, workspace) {
20142
+ const trimmed = configPath.trim();
20143
+ if (trimmed === "~") return os17.homedir();
20144
+ if (trimmed.startsWith("~/")) return join18(os17.homedir(), trimmed.slice(2));
20145
+ if (isAbsolute10(trimmed)) return trimmed;
20146
+ return join18(workspace, trimmed);
20147
+ }
19901
20148
  function resolveAdhdevMcpServerLaunch(options) {
19902
20149
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
19903
20150
  if (!entryPath) return null;
20151
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20152
+ if (!nodeExecutable) return null;
19904
20153
  return {
19905
- command: options.nodeExecutable?.trim() || process.execPath,
19906
- args: [entryPath, "--repo-mesh", options.meshId]
20154
+ command: nodeExecutable,
20155
+ args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
20156
+ };
20157
+ }
20158
+ function resolveMcpNodeExecutable(explicitExecutable) {
20159
+ const explicit = explicitExecutable?.trim();
20160
+ if (explicit) return explicit;
20161
+ const candidates = [];
20162
+ const addCandidate = (candidate) => {
20163
+ const trimmed = candidate?.trim();
20164
+ if (!trimmed) return;
20165
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20166
+ if (!candidates.includes(normalized)) candidates.push(normalized);
19907
20167
  };
20168
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20169
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20170
+ addCandidate(process.env.npm_node_execpath);
20171
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20172
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20173
+ addCandidate("/opt/homebrew/bin/node");
20174
+ addCandidate("/usr/local/bin/node");
20175
+ addCandidate("/usr/bin/node");
20176
+ addCandidate(process.execPath);
20177
+ for (const candidate of candidates) {
20178
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20179
+ }
20180
+ return null;
20181
+ }
20182
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20183
+ for (const entry of (pathValue || "").split(":")) {
20184
+ const dir = entry.trim();
20185
+ if (!dir) continue;
20186
+ addCandidate(join18(dir, "node"));
20187
+ }
20188
+ }
20189
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20190
+ const versionsDir = join18(homeDir, ".nvm", "versions", "node");
20191
+ try {
20192
+ const versionDirs = readdirSync6(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20193
+ for (const versionDir of versionDirs) {
20194
+ addCandidate(join18(versionsDir, versionDir, "bin", "node"));
20195
+ }
20196
+ } catch {
20197
+ }
20198
+ }
20199
+ function compareNodeVersionNamesDescending(a, b) {
20200
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20201
+ const left = parse(a);
20202
+ const right = parse(b);
20203
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20204
+ const diff = (right[i] || 0) - (left[i] || 0);
20205
+ if (diff !== 0) return diff;
20206
+ }
20207
+ return b.localeCompare(a);
20208
+ }
20209
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20210
+ try {
20211
+ execFileSync2(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20212
+ stdio: "ignore",
20213
+ timeout: 3e3
20214
+ });
20215
+ return true;
20216
+ } catch {
20217
+ return false;
20218
+ }
19908
20219
  }
19909
20220
  function resolveAdhdevMcpEntryPath(explicitPath) {
19910
20221
  const explicit = explicitPath?.trim();
@@ -19918,7 +20229,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19918
20229
  const addPackagedCandidates = (baseFile) => {
19919
20230
  if (!baseFile) return;
19920
20231
  const realBase = normalizeExistingPath(baseFile) || baseFile;
19921
- const dir = dirname3(realBase);
20232
+ const dir = dirname4(realBase);
19922
20233
  addCandidate(resolve13(dir, "../vendor/mcp-server/index.js"));
19923
20234
  addCandidate(resolve13(dir, "../../vendor/mcp-server/index.js"));
19924
20235
  addCandidate(resolve13(dir, "../../../vendor/mcp-server/index.js"));
@@ -19931,7 +20242,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19931
20242
  if (normalized) return normalized;
19932
20243
  }
19933
20244
  try {
19934
- const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join17(process.cwd(), "adhdev-daemon.js");
20245
+ const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join18(process.cwd(), "adhdev-daemon.js");
19935
20246
  const req = createRequire2(requireBase);
19936
20247
  const resolvedModule = req.resolve("@adhdev/mcp-server");
19937
20248
  return normalizeExistingPath(resolvedModule) || resolvedModule;
@@ -19941,7 +20252,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
19941
20252
  }
19942
20253
  function normalizeExistingPath(filePath) {
19943
20254
  try {
19944
- if (!existsSync14(filePath)) return null;
20255
+ if (!existsSync15(filePath)) return null;
19945
20256
  return realpathSync2.native(filePath);
19946
20257
  } catch {
19947
20258
  return null;
@@ -19950,7 +20261,7 @@ function normalizeExistingPath(filePath) {
19950
20261
 
19951
20262
  // src/status/snapshot.ts
19952
20263
  init_config();
19953
- import * as os17 from "os";
20264
+ import * as os18 from "os";
19954
20265
  init_terminal_screen();
19955
20266
  init_logger();
19956
20267
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
@@ -20005,8 +20316,8 @@ function buildAvailableProviders(providerLoader) {
20005
20316
  }
20006
20317
  function buildMachineInfo(profile = "full") {
20007
20318
  const base = {
20008
- hostname: os17.hostname(),
20009
- platform: os17.platform()
20319
+ hostname: os18.hostname(),
20320
+ platform: os18.platform()
20010
20321
  };
20011
20322
  if (profile === "live") {
20012
20323
  return base;
@@ -20015,23 +20326,23 @@ function buildMachineInfo(profile = "full") {
20015
20326
  const memSnap2 = getHostMemorySnapshot();
20016
20327
  return {
20017
20328
  ...base,
20018
- arch: os17.arch(),
20019
- cpus: os17.cpus().length,
20329
+ arch: os18.arch(),
20330
+ cpus: os18.cpus().length,
20020
20331
  totalMem: memSnap2.totalMem,
20021
- release: os17.release()
20332
+ release: os18.release()
20022
20333
  };
20023
20334
  }
20024
20335
  const memSnap = getHostMemorySnapshot();
20025
20336
  return {
20026
20337
  ...base,
20027
- arch: os17.arch(),
20028
- cpus: os17.cpus().length,
20338
+ arch: os18.arch(),
20339
+ cpus: os18.cpus().length,
20029
20340
  totalMem: memSnap.totalMem,
20030
20341
  freeMem: memSnap.freeMem,
20031
20342
  availableMem: memSnap.availableMem,
20032
- loadavg: os17.loadavg(),
20033
- uptime: os17.uptime(),
20034
- release: os17.release()
20343
+ loadavg: os18.loadavg(),
20344
+ uptime: os18.uptime(),
20345
+ release: os18.release()
20035
20346
  };
20036
20347
  }
20037
20348
  function parseMessageTime(value) {
@@ -20262,17 +20573,17 @@ function buildStatusSnapshot(options) {
20262
20573
  }
20263
20574
 
20264
20575
  // src/commands/upgrade-helper.ts
20265
- import { execFileSync as execFileSync2 } from "child_process";
20576
+ import { execFileSync as execFileSync3 } from "child_process";
20266
20577
  import { spawn as spawn3 } from "child_process";
20267
20578
  import * as fs9 from "fs";
20268
- import * as os18 from "os";
20269
- import * as path20 from "path";
20579
+ import * as os19 from "os";
20580
+ import * as path21 from "path";
20270
20581
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20271
20582
  function getUpgradeLogPath() {
20272
- const home = os18.homedir();
20273
- const dir = path20.join(home, ".adhdev");
20583
+ const home = os19.homedir();
20584
+ const dir = path21.join(home, ".adhdev");
20274
20585
  fs9.mkdirSync(dir, { recursive: true });
20275
- return path20.join(dir, "daemon-upgrade.log");
20586
+ return path21.join(dir, "daemon-upgrade.log");
20276
20587
  }
20277
20588
  function appendUpgradeLog(message) {
20278
20589
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20283,14 +20594,14 @@ function appendUpgradeLog(message) {
20283
20594
  }
20284
20595
  }
20285
20596
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20286
- const binDir = path20.dirname(nodeExecutable);
20597
+ const binDir = path21.dirname(nodeExecutable);
20287
20598
  if (platform10 === "win32") {
20288
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20599
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20289
20600
  if (fs9.existsSync(npmCliPath)) {
20290
20601
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20291
20602
  }
20292
20603
  for (const candidate of ["npm.exe", "npm"]) {
20293
- const candidatePath = path20.join(binDir, candidate);
20604
+ const candidatePath = path21.join(binDir, candidate);
20294
20605
  if (fs9.existsSync(candidatePath)) {
20295
20606
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20296
20607
  }
@@ -20298,7 +20609,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20298
20609
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20299
20610
  }
20300
20611
  for (const candidate of ["npm"]) {
20301
- const candidatePath = path20.join(binDir, candidate);
20612
+ const candidatePath = path21.join(binDir, candidate);
20302
20613
  if (fs9.existsSync(candidatePath)) {
20303
20614
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20304
20615
  }
@@ -20315,13 +20626,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20315
20626
  let currentDir = resolvedPath;
20316
20627
  try {
20317
20628
  if (fs9.statSync(resolvedPath).isFile()) {
20318
- currentDir = path20.dirname(resolvedPath);
20629
+ currentDir = path21.dirname(resolvedPath);
20319
20630
  }
20320
20631
  } catch {
20321
- currentDir = path20.dirname(resolvedPath);
20632
+ currentDir = path21.dirname(resolvedPath);
20322
20633
  }
20323
20634
  while (true) {
20324
- const packageJsonPath = path20.join(currentDir, "package.json");
20635
+ const packageJsonPath = path21.join(currentDir, "package.json");
20325
20636
  try {
20326
20637
  if (fs9.existsSync(packageJsonPath)) {
20327
20638
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20332,7 +20643,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20332
20643
  }
20333
20644
  } catch {
20334
20645
  }
20335
- const parentDir = path20.dirname(currentDir);
20646
+ const parentDir = path21.dirname(currentDir);
20336
20647
  if (parentDir === currentDir) {
20337
20648
  return null;
20338
20649
  }
@@ -20340,13 +20651,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20340
20651
  }
20341
20652
  }
20342
20653
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20343
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20344
- if (path20.basename(nodeModulesDir) !== "node_modules") {
20654
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
20655
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20345
20656
  return null;
20346
20657
  }
20347
- const maybeLibDir = path20.dirname(nodeModulesDir);
20348
- if (path20.basename(maybeLibDir) === "lib") {
20349
- return path20.dirname(maybeLibDir);
20658
+ const maybeLibDir = path21.dirname(nodeModulesDir);
20659
+ if (path21.basename(maybeLibDir) === "lib") {
20660
+ return path21.dirname(maybeLibDir);
20350
20661
  }
20351
20662
  return maybeLibDir;
20352
20663
  }
@@ -20382,7 +20693,7 @@ function getNpmExecOptions(platform10 = process.platform) {
20382
20693
  }
20383
20694
  function execNpmCommandSync(args, options = {}, surface) {
20384
20695
  const execOptions = surface?.execOptions || getNpmExecOptions();
20385
- return execFileSync2(
20696
+ return execFileSync3(
20386
20697
  surface?.npmExecutable || "npm",
20387
20698
  [...surface?.npmArgsPrefix || [], ...args],
20388
20699
  {
@@ -20395,7 +20706,7 @@ function execNpmCommandSync(args, options = {}, surface) {
20395
20706
  function killPid(pid) {
20396
20707
  try {
20397
20708
  if (process.platform === "win32") {
20398
- execFileSync2("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
20709
+ execFileSync3("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
20399
20710
  } else {
20400
20711
  process.kill(pid, "SIGTERM");
20401
20712
  }
@@ -20407,7 +20718,7 @@ function killPid(pid) {
20407
20718
  function getWindowsProcessCommandLine(pid) {
20408
20719
  const pidFilter = `ProcessId=${pid}`;
20409
20720
  try {
20410
- const psOut = execFileSync2("powershell.exe", [
20721
+ const psOut = execFileSync3("powershell.exe", [
20411
20722
  "-NoProfile",
20412
20723
  "-NonInteractive",
20413
20724
  "-ExecutionPolicy",
@@ -20419,7 +20730,7 @@ function getWindowsProcessCommandLine(pid) {
20419
20730
  } catch {
20420
20731
  }
20421
20732
  try {
20422
- const wmicOut = execFileSync2("wmic", [
20733
+ const wmicOut = execFileSync3("wmic", [
20423
20734
  "process",
20424
20735
  "where",
20425
20736
  pidFilter,
@@ -20435,7 +20746,7 @@ function getProcessCommandLine(pid) {
20435
20746
  if (!Number.isFinite(pid) || pid <= 0) return null;
20436
20747
  if (process.platform === "win32") return getWindowsProcessCommandLine(pid);
20437
20748
  try {
20438
- const text = execFileSync2("ps", ["-o", "command=", "-p", String(pid)], {
20749
+ const text = execFileSync3("ps", ["-o", "command=", "-p", String(pid)], {
20439
20750
  encoding: "utf8",
20440
20751
  timeout: 3e3,
20441
20752
  stdio: ["ignore", "pipe", "ignore"]
@@ -20461,7 +20772,7 @@ async function waitForPidExit(pid, timeoutMs) {
20461
20772
  }
20462
20773
  }
20463
20774
  function stopSessionHostProcesses(appName) {
20464
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
20775
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20465
20776
  try {
20466
20777
  if (fs9.existsSync(pidFile)) {
20467
20778
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20478,7 +20789,7 @@ function stopSessionHostProcesses(appName) {
20478
20789
  }
20479
20790
  }
20480
20791
  function removeDaemonPidFile() {
20481
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
20792
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20482
20793
  try {
20483
20794
  fs9.unlinkSync(pidFile);
20484
20795
  } catch {
@@ -20489,7 +20800,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20489
20800
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20490
20801
  if (!npmRoot) return;
20491
20802
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20492
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
20803
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20493
20804
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20494
20805
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20495
20806
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20497,25 +20808,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20497
20808
  }
20498
20809
  if (pkgName.startsWith("@")) {
20499
20810
  const [scope, name] = pkgName.split("/");
20500
- const scopeDir = path20.join(npmRoot, scope);
20811
+ const scopeDir = path21.join(npmRoot, scope);
20501
20812
  if (!fs9.existsSync(scopeDir)) return;
20502
20813
  for (const entry of fs9.readdirSync(scopeDir)) {
20503
20814
  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)}`);
20815
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
20816
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20506
20817
  }
20507
20818
  } else {
20508
20819
  for (const entry of fs9.readdirSync(npmRoot)) {
20509
20820
  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)}`);
20821
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
20822
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20512
20823
  }
20513
20824
  }
20514
20825
  if (fs9.existsSync(binDir)) {
20515
20826
  for (const entry of fs9.readdirSync(binDir)) {
20516
20827
  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)}`);
20828
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
20829
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20519
20830
  }
20520
20831
  }
20521
20832
  }
@@ -20551,7 +20862,7 @@ async function runDaemonUpgradeHelper(payload) {
20551
20862
  cleanupStaleGlobalInstallDirs(payload.packageName, installCommand.surface);
20552
20863
  const spec = `${payload.packageName}@${payload.targetVersion || "latest"}`;
20553
20864
  appendUpgradeLog(`Installing ${spec}`);
20554
- const installOutput = execFileSync2(
20865
+ const installOutput = execFileSync3(
20555
20866
  installCommand.command,
20556
20867
  installCommand.args,
20557
20868
  {
@@ -20602,6 +20913,10 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
20602
20913
  // src/commands/router.ts
20603
20914
  import * as fs10 from "fs";
20604
20915
  var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
20916
+ var CHANNEL_SERVER_URL = {
20917
+ stable: "https://api.adhf.dev",
20918
+ preview: "https://api-preview.adhf.dev"
20919
+ };
20605
20920
  function normalizeReleaseChannel(value) {
20606
20921
  if (typeof value !== "string") return null;
20607
20922
  const normalized = value.trim().toLowerCase();
@@ -20612,6 +20927,22 @@ function normalizeReleaseChannel(value) {
20612
20927
  function resolveUpgradeChannel(args) {
20613
20928
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20614
20929
  }
20930
+ function loadYamlModule() {
20931
+ return yaml;
20932
+ }
20933
+ function getMcpServersKey(format) {
20934
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
20935
+ }
20936
+ function parseMeshCoordinatorMcpConfig(text, format) {
20937
+ if (!text.trim()) return {};
20938
+ if (format === "claude_mcp_json") return JSON.parse(text);
20939
+ const parsed = loadYamlModule().load(text);
20940
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
20941
+ }
20942
+ function serializeMeshCoordinatorMcpConfig(config, format) {
20943
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
20944
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
20945
+ }
20615
20946
  var CHAT_COMMANDS = [
20616
20947
  "send_chat",
20617
20948
  "new_chat",
@@ -20710,6 +21041,40 @@ var DaemonCommandRouter = class {
20710
21041
  constructor(deps) {
20711
21042
  this.deps = deps;
20712
21043
  }
21044
+ getCachedInlineMesh(meshId, inlineMesh) {
21045
+ if (inlineMesh && typeof inlineMesh === "object") {
21046
+ this.inlineMeshCache.set(meshId, inlineMesh);
21047
+ return inlineMesh;
21048
+ }
21049
+ return this.inlineMeshCache.get(meshId);
21050
+ }
21051
+ async getMeshForCommand(meshId, inlineMesh) {
21052
+ try {
21053
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21054
+ const mesh = getMesh3(meshId);
21055
+ if (mesh) return { mesh, inline: false };
21056
+ } catch {
21057
+ }
21058
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21059
+ return cached ? { mesh: cached, inline: true } : null;
21060
+ }
21061
+ updateInlineMeshNode(meshId, mesh, node) {
21062
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21063
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21064
+ if (idx >= 0) mesh.nodes[idx] = node;
21065
+ else mesh.nodes.push(node);
21066
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21067
+ this.inlineMeshCache.set(meshId, mesh);
21068
+ }
21069
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21070
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21071
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21072
+ if (idx === -1) return false;
21073
+ mesh.nodes.splice(idx, 1);
21074
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21075
+ this.inlineMeshCache.set(meshId, mesh);
21076
+ return true;
21077
+ }
20713
21078
  async traceSessionHostAction(action, args, run, summarizeResult) {
20714
21079
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20715
21080
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -21298,6 +21663,7 @@ var DaemonCommandRouter = class {
21298
21663
  const npmTag = CHANNEL_NPM_TAG[channel];
21299
21664
  const latest = String(execNpmCommandSync(["view", `${pkgName}@${npmTag}`, "version"], { encoding: "utf-8", timeout: 1e4 }, npmSurface)).trim();
21300
21665
  LOG.info("Upgrade", `Latest ${pkgName}@${npmTag}: v${latest}`);
21666
+ updateConfig({ updateChannel: channel, serverUrl: CHANNEL_SERVER_URL[channel] });
21301
21667
  let currentInstalled = null;
21302
21668
  try {
21303
21669
  const currentJson = String(execNpmCommandSync(["ls", "-g", pkgName, "--depth=0", "--json"], {
@@ -21408,13 +21774,94 @@ var DaemonCommandRouter = class {
21408
21774
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21409
21775
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21410
21776
  try {
21411
- const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21412
- const removed = removeNode3(meshId, nodeId);
21777
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
21778
+ const mesh = meshRecord?.mesh;
21779
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
21780
+ if (node?.isLocalWorktree && node.workspace) {
21781
+ try {
21782
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
21783
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
21784
+ if (repoRoot) {
21785
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
21786
+ await removeWorktree2(repoRoot, node.workspace);
21787
+ }
21788
+ } catch (e) {
21789
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
21790
+ }
21791
+ }
21792
+ let removed = false;
21793
+ if (meshRecord?.inline) {
21794
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
21795
+ } else {
21796
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21797
+ removed = removeNode3(meshId, nodeId);
21798
+ }
21413
21799
  return { success: true, removed };
21414
21800
  } catch (e) {
21415
21801
  return { success: false, error: e.message };
21416
21802
  }
21417
21803
  }
21804
+ case "clone_mesh_node": {
21805
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21806
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
21807
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
21808
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
21809
+ if (!meshId) return { success: false, error: "meshId required" };
21810
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
21811
+ if (!branch) return { success: false, error: "branch required" };
21812
+ try {
21813
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
21814
+ const mesh = meshRecord?.mesh;
21815
+ if (!mesh) return { success: false, error: "Mesh not found" };
21816
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
21817
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
21818
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
21819
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
21820
+ const result = await createWorktree2({
21821
+ repoRoot,
21822
+ branch,
21823
+ baseBranch,
21824
+ meshName: mesh.name
21825
+ });
21826
+ let node;
21827
+ if (meshRecord.inline) {
21828
+ const { randomUUID: randomUUID8 } = await import("crypto");
21829
+ node = {
21830
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
21831
+ workspace: result.worktreePath,
21832
+ repoRoot: result.worktreePath,
21833
+ daemonId: sourceNode.daemonId,
21834
+ userOverrides: { ...sourceNode.userOverrides || {} },
21835
+ policy: { ...sourceNode.policy || {} },
21836
+ isLocalWorktree: true,
21837
+ worktreeBranch: result.branch,
21838
+ clonedFromNodeId: sourceNodeId
21839
+ };
21840
+ this.updateInlineMeshNode(meshId, mesh, node);
21841
+ } else {
21842
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21843
+ node = addNode3(meshId, {
21844
+ workspace: result.worktreePath,
21845
+ repoRoot: result.worktreePath,
21846
+ daemonId: sourceNode.daemonId,
21847
+ userOverrides: { ...sourceNode.userOverrides || {} },
21848
+ isLocalWorktree: true,
21849
+ worktreeBranch: result.branch,
21850
+ clonedFromNodeId: sourceNodeId,
21851
+ policy: { ...sourceNode.policy || {} }
21852
+ });
21853
+ if (!node) return { success: false, error: "Failed to register worktree node" };
21854
+ }
21855
+ return {
21856
+ success: true,
21857
+ node,
21858
+ worktreePath: result.worktreePath,
21859
+ branch: result.branch
21860
+ };
21861
+ } catch (e) {
21862
+ return { success: false, error: e.message };
21863
+ }
21864
+ }
21418
21865
  // ─── Mesh Coordinator Launch ───
21419
21866
  case "launch_mesh_coordinator": {
21420
21867
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
@@ -21449,6 +21896,7 @@ var DaemonCommandRouter = class {
21449
21896
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21450
21897
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21451
21898
  provider: providerMeta,
21899
+ cliType,
21452
21900
  meshId,
21453
21901
  workspace
21454
21902
  });
@@ -21473,7 +21921,8 @@ var DaemonCommandRouter = class {
21473
21921
  meshCoordinatorSetup: coordinatorSetup
21474
21922
  };
21475
21923
  }
21476
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
21924
+ const configFormat = coordinatorSetup.configFormat;
21925
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21477
21926
  return {
21478
21927
  success: false,
21479
21928
  code: "mesh_coordinator_unsupported",
@@ -21483,44 +21932,93 @@ var DaemonCommandRouter = class {
21483
21932
  workspace
21484
21933
  };
21485
21934
  }
21486
- const { existsSync: existsSync22, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3 } = await import("fs");
21487
- const mcpConfigPath = coordinatorSetup.configPath;
21488
- const hadExistingMcpConfig = existsSync22(mcpConfigPath);
21489
- let existingMcpConfig = {};
21490
- if (hadExistingMcpConfig) {
21491
- try {
21492
- existingMcpConfig = JSON.parse(readFileSync15(mcpConfigPath, "utf-8"));
21493
- copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
21494
- } catch {
21495
- }
21935
+ let systemPrompt = "";
21936
+ try {
21937
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
21938
+ } catch (error) {
21939
+ const message = error?.message || String(error);
21940
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
21941
+ return {
21942
+ success: false,
21943
+ code: "mesh_coordinator_prompt_failed",
21944
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
21945
+ meshId,
21946
+ cliType,
21947
+ workspace
21948
+ };
21496
21949
  }
21950
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3, mkdirSync: mkdirSync14 } = await import("fs");
21951
+ const { dirname: dirname9 } = await import("path");
21952
+ const mcpConfigPath = coordinatorSetup.configPath;
21953
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
21954
+ const returnManualFallback = (message) => ({
21955
+ success: false,
21956
+ code: "mesh_coordinator_manual_mcp_setup_required",
21957
+ error: message,
21958
+ meshId,
21959
+ cliType,
21960
+ workspace,
21961
+ meshCoordinatorSetup: hermesManualFallback
21962
+ });
21497
21963
  const mcpServerEntry = {
21498
21964
  command: coordinatorSetup.mcpServer.command,
21499
21965
  args: coordinatorSetup.mcpServer.args
21500
21966
  };
21501
21967
  if (args?.inlineMesh) {
21502
21968
  mcpServerEntry.env = {
21503
- ADHDEV_INLINE_MESH: JSON.stringify(mesh)
21969
+ ADHDEV_INLINE_MESH: JSON.stringify(mesh),
21970
+ ADHDEV_MCP_TRANSPORT: "ipc"
21504
21971
  };
21505
21972
  }
21973
+ try {
21974
+ mkdirSync14(dirname9(mcpConfigPath), { recursive: true });
21975
+ } catch (error) {
21976
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
21977
+ LOG.error("MeshCoordinator", message);
21978
+ if (hermesManualFallback) return returnManualFallback(message);
21979
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21980
+ }
21981
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
21982
+ let existingMcpConfig = {};
21983
+ if (hadExistingMcpConfig) {
21984
+ try {
21985
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
21986
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
21987
+ } catch (error) {
21988
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
21989
+ return {
21990
+ success: false,
21991
+ code: "mesh_coordinator_config_parse_failed",
21992
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
21993
+ };
21994
+ }
21995
+ }
21996
+ const mcpServersKey = getMcpServersKey(configFormat);
21997
+ const existingServers = existingMcpConfig[mcpServersKey];
21506
21998
  const mcpConfig = {
21507
21999
  ...existingMcpConfig,
21508
- mcpServers: {
21509
- ...existingMcpConfig.mcpServers || {},
22000
+ [mcpServersKey]: {
22001
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21510
22002
  [coordinatorSetup.serverName]: mcpServerEntry
21511
22003
  }
21512
22004
  };
21513
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21514
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21515
- let systemPrompt = "";
21516
22005
  try {
21517
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
21518
- } catch {
21519
- 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).`;
22006
+ writeFileSync12(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22007
+ } catch (error) {
22008
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22009
+ LOG.error("MeshCoordinator", message);
22010
+ if (hermesManualFallback) return returnManualFallback(message);
22011
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21520
22012
  }
22013
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21521
22014
  const cliArgs = [];
22015
+ const launchEnv = {};
21522
22016
  if (systemPrompt) {
21523
- cliArgs.push("--append-system-prompt", systemPrompt);
22017
+ if (configFormat === "hermes_config_yaml") {
22018
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22019
+ } else {
22020
+ cliArgs.push("--append-system-prompt", systemPrompt);
22021
+ }
21524
22022
  }
21525
22023
  if (cliType === "claude-cli") {
21526
22024
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21529,6 +22027,7 @@ var DaemonCommandRouter = class {
21529
22027
  cliType,
21530
22028
  dir: workspace,
21531
22029
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22030
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21532
22031
  settings: {
21533
22032
  meshCoordinatorFor: meshId
21534
22033
  }
@@ -23189,11 +23688,11 @@ var ProviderInstanceManager = class {
23189
23688
 
23190
23689
  // src/providers/version-archive.ts
23191
23690
  import * as fs11 from "fs";
23192
- import * as path21 from "path";
23193
- import * as os19 from "os";
23691
+ import * as path22 from "path";
23692
+ import * as os20 from "os";
23194
23693
  import { execSync as execSync5 } from "child_process";
23195
23694
  import { platform as platform8 } from "os";
23196
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
23695
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23197
23696
  var MAX_ENTRIES_PER_PROVIDER = 20;
23198
23697
  var VersionArchive = class {
23199
23698
  history = {};
@@ -23240,7 +23739,7 @@ var VersionArchive = class {
23240
23739
  }
23241
23740
  save() {
23242
23741
  try {
23243
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
23742
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23244
23743
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23245
23744
  } catch {
23246
23745
  }
@@ -23296,8 +23795,8 @@ function getVersion(binary, versionCommand) {
23296
23795
  function checkPathExists2(paths) {
23297
23796
  for (const p of paths) {
23298
23797
  if (p.includes("*")) {
23299
- const home = os19.homedir();
23300
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
23798
+ const home = os20.homedir();
23799
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23301
23800
  if (fs11.existsSync(resolved)) return resolved;
23302
23801
  } else {
23303
23802
  if (fs11.existsSync(p)) return p;
@@ -23307,7 +23806,7 @@ function checkPathExists2(paths) {
23307
23806
  }
23308
23807
  function getMacAppVersion(appPath) {
23309
23808
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
23310
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
23809
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23311
23810
  if (!fs11.existsSync(plistPath)) return null;
23312
23811
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23313
23812
  return raw || null;
@@ -23333,7 +23832,7 @@ async function detectAllVersions(loader, archive) {
23333
23832
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23334
23833
  let resolvedBin = cliBin;
23335
23834
  if (!resolvedBin && appPath && currentOs === "darwin") {
23336
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23835
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23337
23836
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23338
23837
  }
23339
23838
  info.installed = !!(appPath || resolvedBin);
@@ -23374,7 +23873,7 @@ async function detectAllVersions(loader, archive) {
23374
23873
  // src/daemon/dev-server.ts
23375
23874
  import * as http2 from "http";
23376
23875
  import * as fs15 from "fs";
23377
- import * as path25 from "path";
23876
+ import * as path26 from "path";
23378
23877
  init_config();
23379
23878
 
23380
23879
  // src/daemon/scaffold-template.ts
@@ -23726,7 +24225,7 @@ init_logger();
23726
24225
  // src/daemon/dev-cdp-handlers.ts
23727
24226
  init_logger();
23728
24227
  import * as fs12 from "fs";
23729
- import * as path22 from "path";
24228
+ import * as path23 from "path";
23730
24229
  async function handleCdpEvaluate(ctx, req, res) {
23731
24230
  const body = await ctx.readBody(req);
23732
24231
  const { expression, timeout, ideType } = body;
@@ -23904,17 +24403,17 @@ async function handleScriptHints(ctx, type, _req, res) {
23904
24403
  return;
23905
24404
  }
23906
24405
  let scriptsPath = "";
23907
- const directScripts = path22.join(dir, "scripts.js");
24406
+ const directScripts = path23.join(dir, "scripts.js");
23908
24407
  if (fs12.existsSync(directScripts)) {
23909
24408
  scriptsPath = directScripts;
23910
24409
  } else {
23911
- const scriptsDir = path22.join(dir, "scripts");
24410
+ const scriptsDir = path23.join(dir, "scripts");
23912
24411
  if (fs12.existsSync(scriptsDir)) {
23913
24412
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
23914
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
24413
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
23915
24414
  }).sort().reverse();
23916
24415
  for (const ver of versions) {
23917
- const p = path22.join(scriptsDir, ver, "scripts.js");
24416
+ const p = path23.join(scriptsDir, ver, "scripts.js");
23918
24417
  if (fs12.existsSync(p)) {
23919
24418
  scriptsPath = p;
23920
24419
  break;
@@ -24743,7 +25242,7 @@ async function handleDomContext(ctx, type, req, res) {
24743
25242
 
24744
25243
  // src/daemon/dev-cli-debug.ts
24745
25244
  import * as fs13 from "fs";
24746
- import * as path23 from "path";
25245
+ import * as path24 from "path";
24747
25246
  function slugifyFixtureName(value) {
24748
25247
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24749
25248
  return normalized || `fixture-${Date.now()}`;
@@ -24753,11 +25252,11 @@ function getCliFixtureDir(ctx, type) {
24753
25252
  if (!providerDir) {
24754
25253
  throw new Error(`Provider directory not found for '${type}'`);
24755
25254
  }
24756
- return path23.join(providerDir, "fixtures");
25255
+ return path24.join(providerDir, "fixtures");
24757
25256
  }
24758
25257
  function readCliFixture(ctx, type, name) {
24759
25258
  const fixtureDir = getCliFixtureDir(ctx, type);
24760
- const filePath = path23.join(fixtureDir, `${name}.json`);
25259
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24761
25260
  if (!fs13.existsSync(filePath)) {
24762
25261
  throw new Error(`Fixture not found: ${filePath}`);
24763
25262
  }
@@ -25524,7 +26023,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25524
26023
  },
25525
26024
  notes: typeof body?.notes === "string" ? body.notes : void 0
25526
26025
  };
25527
- const filePath = path23.join(fixtureDir, `${name}.json`);
26026
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25528
26027
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25529
26028
  ctx.json(res, 200, {
25530
26029
  saved: true,
@@ -25548,7 +26047,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25548
26047
  return;
25549
26048
  }
25550
26049
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
25551
- const fullPath = path23.join(fixtureDir, file);
26050
+ const fullPath = path24.join(fixtureDir, file);
25552
26051
  try {
25553
26052
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25554
26053
  return {
@@ -25684,8 +26183,8 @@ async function handleCliRaw(ctx, req, res) {
25684
26183
 
25685
26184
  // src/daemon/dev-auto-implement.ts
25686
26185
  import * as fs14 from "fs";
25687
- import * as path24 from "path";
25688
- import * as os20 from "os";
26186
+ import * as path25 from "path";
26187
+ import * as os21 from "os";
25689
26188
  function getAutoImplPid(ctx) {
25690
26189
  const pid = ctx.autoImplProcess?.pid;
25691
26190
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25734,22 +26233,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25734
26233
  if (!fs14.existsSync(scriptsDir)) return null;
25735
26234
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25736
26235
  try {
25737
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
26236
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25738
26237
  } catch {
25739
26238
  return false;
25740
26239
  }
25741
26240
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25742
26241
  if (versions.length === 0) return null;
25743
- return path24.join(scriptsDir, versions[0]);
26242
+ return path25.join(scriptsDir, versions[0]);
25744
26243
  }
25745
26244
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25746
- const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25747
- const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25748
- const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25749
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
26245
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26246
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26247
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26248
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25750
26249
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25751
26250
  }
25752
- if (path24.basename(desiredDir) !== type) {
26251
+ if (path25.basename(desiredDir) !== type) {
25753
26252
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25754
26253
  }
25755
26254
  const sourceDir = ctx.findProviderDir(type);
@@ -25757,11 +26256,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25757
26256
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25758
26257
  }
25759
26258
  if (!fs14.existsSync(desiredDir)) {
25760
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
26259
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25761
26260
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25762
26261
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25763
26262
  }
25764
- const providerJson = path24.join(desiredDir, "provider.json");
26263
+ const providerJson = path25.join(desiredDir, "provider.json");
25765
26264
  if (!fs14.existsSync(providerJson)) {
25766
26265
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25767
26266
  }
@@ -25772,13 +26271,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25772
26271
  const refDir = ctx.findProviderDir(referenceType);
25773
26272
  if (!refDir || !fs14.existsSync(refDir)) return {};
25774
26273
  const referenceScripts = {};
25775
- const scriptsDir = path24.join(refDir, "scripts");
26274
+ const scriptsDir = path25.join(refDir, "scripts");
25776
26275
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25777
26276
  if (!latestDir) return referenceScripts;
25778
26277
  for (const file of fs14.readdirSync(latestDir)) {
25779
26278
  if (!file.endsWith(".js")) continue;
25780
26279
  try {
25781
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
26280
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25782
26281
  } catch {
25783
26282
  }
25784
26283
  }
@@ -25886,9 +26385,9 @@ async function handleAutoImplement(ctx, type, req, res) {
25886
26385
  });
25887
26386
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
25888
26387
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
25889
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
26388
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
25890
26389
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
25891
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26390
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
25892
26391
  fs14.writeFileSync(promptFile, prompt, "utf-8");
25893
26392
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
25894
26393
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26041,7 +26540,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26041
26540
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26042
26541
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26043
26542
  let shellCmd;
26044
- const isWin = os20.platform() === "win32";
26543
+ const isWin = os21.platform() === "win32";
26045
26544
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26046
26545
  const promptMode = autoImpl?.promptMode ?? "stdin";
26047
26546
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26080,7 +26579,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26080
26579
  try {
26081
26580
  const pty = __require("node-pty");
26082
26581
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26083
- const isWin2 = os20.platform() === "win32";
26582
+ const isWin2 = os21.platform() === "win32";
26084
26583
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26085
26584
  name: "xterm-256color",
26086
26585
  cols: 120,
@@ -26320,7 +26819,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26320
26819
  setMode: "set_mode.js"
26321
26820
  };
26322
26821
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26323
- const scriptsDir = path24.join(providerDir, "scripts");
26822
+ const scriptsDir = path25.join(providerDir, "scripts");
26324
26823
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26325
26824
  if (latestScriptsDir) {
26326
26825
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26331,7 +26830,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26331
26830
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26332
26831
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26333
26832
  try {
26334
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
26833
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26335
26834
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26336
26835
  lines.push("```javascript");
26337
26836
  lines.push(content);
@@ -26348,7 +26847,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26348
26847
  lines.push("");
26349
26848
  for (const file of refFiles) {
26350
26849
  try {
26351
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
26850
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26352
26851
  lines.push(`### \`${file}\` \u{1F512}`);
26353
26852
  lines.push("```javascript");
26354
26853
  lines.push(content);
@@ -26389,10 +26888,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26389
26888
  lines.push("");
26390
26889
  }
26391
26890
  }
26392
- const docsDir = path24.join(providerDir, "../../docs");
26891
+ const docsDir = path25.join(providerDir, "../../docs");
26393
26892
  const loadGuide = (name) => {
26394
26893
  try {
26395
- const p = path24.join(docsDir, name);
26894
+ const p = path25.join(docsDir, name);
26396
26895
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26397
26896
  } catch {
26398
26897
  }
@@ -26629,7 +27128,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26629
27128
  parseApproval: "parse_approval.js"
26630
27129
  };
26631
27130
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26632
- const scriptsDir = path24.join(providerDir, "scripts");
27131
+ const scriptsDir = path25.join(providerDir, "scripts");
26633
27132
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26634
27133
  if (latestScriptsDir) {
26635
27134
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26641,7 +27140,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26641
27140
  if (!file.endsWith(".js")) continue;
26642
27141
  if (!targetFileNames.has(file)) continue;
26643
27142
  try {
26644
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27143
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26645
27144
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26646
27145
  lines.push("```javascript");
26647
27146
  lines.push(content);
@@ -26657,7 +27156,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26657
27156
  lines.push("");
26658
27157
  for (const file of refFiles) {
26659
27158
  try {
26660
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27159
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26661
27160
  lines.push(`### \`${file}\` \u{1F512}`);
26662
27161
  lines.push("```javascript");
26663
27162
  lines.push(content);
@@ -26690,10 +27189,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26690
27189
  lines.push("");
26691
27190
  }
26692
27191
  }
26693
- const docsDir = path24.join(providerDir, "../../docs");
27192
+ const docsDir = path25.join(providerDir, "../../docs");
26694
27193
  const loadGuide = (name) => {
26695
27194
  try {
26696
- const p = path24.join(docsDir, name);
27195
+ const p = path25.join(docsDir, name);
26697
27196
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26698
27197
  } catch {
26699
27198
  }
@@ -27140,8 +27639,8 @@ var DevServer = class _DevServer {
27140
27639
  }
27141
27640
  getEndpointList() {
27142
27641
  return this.routes.map((r) => {
27143
- const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27144
- return `${r.method.padEnd(5)} ${path26}`;
27642
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27643
+ return `${r.method.padEnd(5)} ${path27}`;
27145
27644
  });
27146
27645
  }
27147
27646
  async start(port = DEV_SERVER_PORT) {
@@ -27429,12 +27928,12 @@ var DevServer = class _DevServer {
27429
27928
  // ─── DevConsole SPA ───
27430
27929
  getConsoleDistDir() {
27431
27930
  const candidates = [
27432
- path25.resolve(__dirname, "../../web-devconsole/dist"),
27433
- path25.resolve(__dirname, "../../../web-devconsole/dist"),
27434
- path25.join(process.cwd(), "packages/web-devconsole/dist")
27931
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
27932
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
27933
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27435
27934
  ];
27436
27935
  for (const dir of candidates) {
27437
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
27936
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27438
27937
  }
27439
27938
  return null;
27440
27939
  }
@@ -27444,7 +27943,7 @@ var DevServer = class _DevServer {
27444
27943
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27445
27944
  return;
27446
27945
  }
27447
- const htmlPath = path25.join(distDir, "index.html");
27946
+ const htmlPath = path26.join(distDir, "index.html");
27448
27947
  try {
27449
27948
  const html = fs15.readFileSync(htmlPath, "utf-8");
27450
27949
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27469,15 +27968,15 @@ var DevServer = class _DevServer {
27469
27968
  this.json(res, 404, { error: "Not found" });
27470
27969
  return;
27471
27970
  }
27472
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27473
- const filePath = path25.join(distDir, safePath);
27971
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
27972
+ const filePath = path26.join(distDir, safePath);
27474
27973
  if (!filePath.startsWith(distDir)) {
27475
27974
  this.json(res, 403, { error: "Forbidden" });
27476
27975
  return;
27477
27976
  }
27478
27977
  try {
27479
27978
  const content = fs15.readFileSync(filePath);
27480
- const ext = path25.extname(filePath);
27979
+ const ext = path26.extname(filePath);
27481
27980
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27482
27981
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27483
27982
  res.end(content);
@@ -27590,9 +28089,9 @@ var DevServer = class _DevServer {
27590
28089
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27591
28090
  if (entry.isDirectory()) {
27592
28091
  files.push({ path: rel, size: 0, type: "dir" });
27593
- scan(path25.join(d, entry.name), rel);
28092
+ scan(path26.join(d, entry.name), rel);
27594
28093
  } else {
27595
- const stat2 = fs15.statSync(path25.join(d, entry.name));
28094
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27596
28095
  files.push({ path: rel, size: stat2.size, type: "file" });
27597
28096
  }
27598
28097
  }
@@ -27615,7 +28114,7 @@ var DevServer = class _DevServer {
27615
28114
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27616
28115
  return;
27617
28116
  }
27618
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28117
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27619
28118
  if (!fullPath.startsWith(dir)) {
27620
28119
  this.json(res, 403, { error: "Forbidden" });
27621
28120
  return;
@@ -27640,14 +28139,14 @@ var DevServer = class _DevServer {
27640
28139
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27641
28140
  return;
27642
28141
  }
27643
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28142
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27644
28143
  if (!fullPath.startsWith(dir)) {
27645
28144
  this.json(res, 403, { error: "Forbidden" });
27646
28145
  return;
27647
28146
  }
27648
28147
  try {
27649
28148
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27650
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28149
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27651
28150
  fs15.writeFileSync(fullPath, content, "utf-8");
27652
28151
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27653
28152
  this.providerLoader.reload();
@@ -27664,7 +28163,7 @@ var DevServer = class _DevServer {
27664
28163
  return;
27665
28164
  }
27666
28165
  for (const name of ["scripts.js", "provider.json"]) {
27667
- const p = path25.join(dir, name);
28166
+ const p = path26.join(dir, name);
27668
28167
  if (fs15.existsSync(p)) {
27669
28168
  const source = fs15.readFileSync(p, "utf-8");
27670
28169
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27685,8 +28184,8 @@ var DevServer = class _DevServer {
27685
28184
  this.json(res, 404, { error: `Provider not found: ${type}` });
27686
28185
  return;
27687
28186
  }
27688
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27689
- const targetPath = path25.join(dir, target);
28187
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28188
+ const targetPath = path26.join(dir, target);
27690
28189
  try {
27691
28190
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27692
28191
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -27833,7 +28332,7 @@ var DevServer = class _DevServer {
27833
28332
  }
27834
28333
  let targetDir;
27835
28334
  targetDir = this.providerLoader.getUserProviderDir(category, type);
27836
- const jsonPath = path25.join(targetDir, "provider.json");
28335
+ const jsonPath = path26.join(targetDir, "provider.json");
27837
28336
  if (fs15.existsSync(jsonPath)) {
27838
28337
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
27839
28338
  return;
@@ -27845,8 +28344,8 @@ var DevServer = class _DevServer {
27845
28344
  const createdFiles = ["provider.json"];
27846
28345
  if (result.files) {
27847
28346
  for (const [relPath, content] of Object.entries(result.files)) {
27848
- const fullPath = path25.join(targetDir, relPath);
27849
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28347
+ const fullPath = path26.join(targetDir, relPath);
28348
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27850
28349
  fs15.writeFileSync(fullPath, content, "utf-8");
27851
28350
  createdFiles.push(relPath);
27852
28351
  }
@@ -27899,22 +28398,22 @@ var DevServer = class _DevServer {
27899
28398
  if (!fs15.existsSync(scriptsDir)) return null;
27900
28399
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
27901
28400
  try {
27902
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
28401
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
27903
28402
  } catch {
27904
28403
  return false;
27905
28404
  }
27906
28405
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
27907
28406
  if (versions.length === 0) return null;
27908
- return path25.join(scriptsDir, versions[0]);
28407
+ return path26.join(scriptsDir, versions[0]);
27909
28408
  }
27910
28409
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
27911
- const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
27912
- const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
27913
- const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
27914
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
28410
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
28411
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
28412
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
28413
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
27915
28414
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
27916
28415
  }
27917
- if (path25.basename(desiredDir) !== type) {
28416
+ if (path26.basename(desiredDir) !== type) {
27918
28417
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
27919
28418
  }
27920
28419
  const sourceDir = this.findProviderDir(type);
@@ -27922,11 +28421,11 @@ var DevServer = class _DevServer {
27922
28421
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
27923
28422
  }
27924
28423
  if (!fs15.existsSync(desiredDir)) {
27925
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
28424
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
27926
28425
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
27927
28426
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
27928
28427
  }
27929
- const providerJson = path25.join(desiredDir, "provider.json");
28428
+ const providerJson = path26.join(desiredDir, "provider.json");
27930
28429
  if (!fs15.existsSync(providerJson)) {
27931
28430
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
27932
28431
  }
@@ -27962,7 +28461,7 @@ var DevServer = class _DevServer {
27962
28461
  setMode: "set_mode.js"
27963
28462
  };
27964
28463
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27965
- const scriptsDir = path25.join(providerDir, "scripts");
28464
+ const scriptsDir = path26.join(providerDir, "scripts");
27966
28465
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
27967
28466
  if (latestScriptsDir) {
27968
28467
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27973,7 +28472,7 @@ var DevServer = class _DevServer {
27973
28472
  for (const file of fs15.readdirSync(latestScriptsDir)) {
27974
28473
  if (file.endsWith(".js") && targetFileNames.has(file)) {
27975
28474
  try {
27976
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28475
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27977
28476
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27978
28477
  lines.push("```javascript");
27979
28478
  lines.push(content);
@@ -27990,7 +28489,7 @@ var DevServer = class _DevServer {
27990
28489
  lines.push("");
27991
28490
  for (const file of refFiles) {
27992
28491
  try {
27993
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28492
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27994
28493
  lines.push(`### \`${file}\` \u{1F512}`);
27995
28494
  lines.push("```javascript");
27996
28495
  lines.push(content);
@@ -28031,10 +28530,10 @@ var DevServer = class _DevServer {
28031
28530
  lines.push("");
28032
28531
  }
28033
28532
  }
28034
- const docsDir = path25.join(providerDir, "../../docs");
28533
+ const docsDir = path26.join(providerDir, "../../docs");
28035
28534
  const loadGuide = (name) => {
28036
28535
  try {
28037
- const p = path25.join(docsDir, name);
28536
+ const p = path26.join(docsDir, name);
28038
28537
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28039
28538
  } catch {
28040
28539
  }
@@ -28208,7 +28707,7 @@ var DevServer = class _DevServer {
28208
28707
  parseApproval: "parse_approval.js"
28209
28708
  };
28210
28709
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28211
- const scriptsDir = path25.join(providerDir, "scripts");
28710
+ const scriptsDir = path26.join(providerDir, "scripts");
28212
28711
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28213
28712
  if (latestScriptsDir) {
28214
28713
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28220,7 +28719,7 @@ var DevServer = class _DevServer {
28220
28719
  if (!file.endsWith(".js")) continue;
28221
28720
  if (!targetFileNames.has(file)) continue;
28222
28721
  try {
28223
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28722
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28224
28723
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28225
28724
  lines.push("```javascript");
28226
28725
  lines.push(content);
@@ -28236,7 +28735,7 @@ var DevServer = class _DevServer {
28236
28735
  lines.push("");
28237
28736
  for (const file of refFiles) {
28238
28737
  try {
28239
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28738
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28240
28739
  lines.push(`### \`${file}\` \u{1F512}`);
28241
28740
  lines.push("```javascript");
28242
28741
  lines.push(content);
@@ -28269,10 +28768,10 @@ var DevServer = class _DevServer {
28269
28768
  lines.push("");
28270
28769
  }
28271
28770
  }
28272
- const docsDir = path25.join(providerDir, "../../docs");
28771
+ const docsDir = path26.join(providerDir, "../../docs");
28273
28772
  const loadGuide = (name) => {
28274
28773
  try {
28275
- const p = path25.join(docsDir, name);
28774
+ const p = path26.join(docsDir, name);
28276
28775
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28277
28776
  } catch {
28278
28777
  }
@@ -29624,6 +30123,7 @@ export {
29624
30123
  createGitWorkspaceMonitor,
29625
30124
  createInteractionId,
29626
30125
  createMesh,
30126
+ createWorktree,
29627
30127
  deleteMesh,
29628
30128
  detectAllVersions,
29629
30129
  detectCLIs,
@@ -29676,6 +30176,7 @@ export {
29676
30176
  launchWithCdp,
29677
30177
  listHostedCliRuntimes,
29678
30178
  listMeshes,
30179
+ listWorktrees,
29679
30180
  loadConfig,
29680
30181
  loadState,
29681
30182
  logCommand,
@@ -29695,6 +30196,7 @@ export {
29695
30196
  normalizeSessionModalFields,
29696
30197
  parsePorcelainV2Status,
29697
30198
  parseProviderSourceConfigUpdate,
30199
+ parseWorktreeListOutput,
29698
30200
  partitionSessionHostDiagnosticsSessions,
29699
30201
  partitionSessionHostRecords,
29700
30202
  prepareSessionChatTailUpdate,
@@ -29704,6 +30206,7 @@ export {
29704
30206
  recordDebugTrace,
29705
30207
  registerExtensionProviders,
29706
30208
  removeNode,
30209
+ removeWorktree,
29707
30210
  resetConfig,
29708
30211
  resetDebugRuntimeConfig,
29709
30212
  resetState,
@@ -29713,6 +30216,7 @@ export {
29713
30216
  resolveGitRepository,
29714
30217
  resolveSessionHostAppName,
29715
30218
  resolveSessionHostAppNameResolution,
30219
+ resolveWorktreePath,
29716
30220
  runAsyncBatch,
29717
30221
  runGit,
29718
30222
  saveConfig,