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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -1
  2. package/dist/cli-adapters/provider-cli-runtime.d.ts +1 -0
  3. package/dist/commands/cli-manager.d.ts +17 -4
  4. package/dist/commands/mesh-coordinator.d.ts +2 -0
  5. package/dist/commands/router.d.ts +11 -0
  6. package/dist/config/mesh-config.d.ts +3 -0
  7. package/dist/git/git-types.d.ts +1 -1
  8. package/dist/git/git-worktree.d.ts +64 -0
  9. package/dist/git/index.d.ts +2 -0
  10. package/dist/index.js +1398 -436
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +1425 -467
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/mesh/coordinator-prompt.d.ts +1 -0
  15. package/dist/mesh/mesh-events.d.ts +9 -0
  16. package/dist/providers/chat-message-normalization.d.ts +11 -0
  17. package/dist/providers/cli-provider-instance.d.ts +3 -0
  18. package/dist/providers/provider-instance-manager.d.ts +1 -0
  19. package/dist/providers/provider-instance.d.ts +2 -0
  20. package/dist/repo-mesh-types.d.ts +13 -0
  21. package/dist/shared-types.d.ts +4 -0
  22. package/package.json +4 -5
  23. package/src/cli-adapters/provider-cli-adapter.ts +28 -7
  24. package/src/cli-adapters/provider-cli-runtime.ts +3 -2
  25. package/src/commands/chat-commands.ts +109 -8
  26. package/src/commands/cli-manager.ts +78 -5
  27. package/src/commands/handler.ts +13 -4
  28. package/src/commands/mesh-coordinator.ts +149 -6
  29. package/src/commands/router.d.ts +1 -0
  30. package/src/commands/router.ts +554 -34
  31. package/src/config/mesh-config.ts +23 -2
  32. package/src/git/git-commands.ts +5 -1
  33. package/src/git/git-types.ts +1 -0
  34. package/src/git/git-worktree.ts +214 -0
  35. package/src/git/index.ts +14 -0
  36. package/src/mesh/coordinator-prompt.ts +25 -10
  37. package/src/mesh/mesh-events.ts +109 -43
  38. package/src/providers/chat-message-normalization.ts +54 -0
  39. package/src/providers/cli-provider-instance.d.ts +2 -0
  40. package/src/providers/cli-provider-instance.ts +58 -7
  41. package/src/providers/provider-instance-manager.ts +20 -1
  42. package/src/providers/provider-instance.ts +2 -0
  43. package/src/repo-mesh-types.ts +15 -0
  44. package/src/shared-types.ts +4 -0
  45. package/src/status/builders.ts +17 -12
  46. package/src/status/reporter.ts +6 -0
package/dist/index.js CHANGED
@@ -41,11 +41,140 @@ var init_repo_mesh_types = __esm({
41
41
  requireApprovalForPush: true,
42
42
  requireApprovalForDestructiveGit: true,
43
43
  dirtyWorkspaceBehavior: "warn",
44
- maxParallelTasks: 2
44
+ maxParallelTasks: 2,
45
+ sessionCleanupOnNodeRemove: "preserve"
45
46
  };
46
47
  }
47
48
  });
48
49
 
50
+ // src/git/git-worktree.ts
51
+ var git_worktree_exports = {};
52
+ __export(git_worktree_exports, {
53
+ createWorktree: () => createWorktree,
54
+ listWorktrees: () => listWorktrees,
55
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
56
+ removeWorktree: () => removeWorktree,
57
+ resolveWorktreePath: () => resolveWorktreePath
58
+ });
59
+ function resolveWorktreePath(repoRoot, meshName, branch) {
60
+ const safeBranch = branch.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
61
+ const safeMeshName = meshName.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
62
+ const parentDir = path4.dirname(repoRoot);
63
+ return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
64
+ }
65
+ async function createWorktree(opts) {
66
+ const { repoRoot, branch, baseBranch, meshName } = opts;
67
+ const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
68
+ if ((0, import_node_fs2.existsSync)(targetDir)) {
69
+ throw new Error(`Worktree target directory already exists: ${targetDir}`);
70
+ }
71
+ await (0, import_promises3.mkdir)(path4.dirname(targetDir), { recursive: true });
72
+ const args = ["worktree", "add", targetDir, "-b", branch];
73
+ if (baseBranch) {
74
+ args.push(baseBranch);
75
+ }
76
+ try {
77
+ await execFileAsync2("git", args, {
78
+ cwd: repoRoot,
79
+ encoding: "utf8",
80
+ timeout: GIT_TIMEOUT_MS,
81
+ maxBuffer: GIT_MAX_BUFFER,
82
+ windowsHide: true
83
+ });
84
+ } catch (error) {
85
+ const stderr = typeof error.stderr === "string" ? error.stderr : "";
86
+ if (/already exists/i.test(stderr)) {
87
+ throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
88
+ }
89
+ throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
90
+ }
91
+ return {
92
+ success: true,
93
+ worktreePath: targetDir,
94
+ branch
95
+ };
96
+ }
97
+ async function removeWorktree(repoRoot, worktreePath) {
98
+ if (!(0, import_node_fs2.existsSync)(worktreePath)) {
99
+ await pruneWorktrees(repoRoot);
100
+ return { success: true, removedPath: worktreePath };
101
+ }
102
+ try {
103
+ await execFileAsync2("git", ["worktree", "remove", worktreePath, "--force"], {
104
+ cwd: repoRoot,
105
+ encoding: "utf8",
106
+ timeout: GIT_TIMEOUT_MS,
107
+ maxBuffer: GIT_MAX_BUFFER,
108
+ windowsHide: true
109
+ });
110
+ } catch (error) {
111
+ const stderr = typeof error.stderr === "string" ? error.stderr : "";
112
+ throw new Error(`git worktree remove failed: ${stderr.trim() || error.message}`);
113
+ }
114
+ return { success: true, removedPath: worktreePath };
115
+ }
116
+ async function listWorktrees(repoRoot) {
117
+ const { stdout } = await execFileAsync2("git", ["worktree", "list", "--porcelain"], {
118
+ cwd: repoRoot,
119
+ encoding: "utf8",
120
+ timeout: GIT_TIMEOUT_MS,
121
+ maxBuffer: GIT_MAX_BUFFER,
122
+ windowsHide: true
123
+ });
124
+ return parseWorktreeListOutput(stdout);
125
+ }
126
+ function parseWorktreeListOutput(output) {
127
+ const entries = [];
128
+ const blocks = output.trim().split(/\n\n+/);
129
+ for (const block of blocks) {
130
+ if (!block.trim()) continue;
131
+ const lines = block.trim().split("\n");
132
+ const entry = { path: "", head: "", branch: null, bare: false };
133
+ for (const line of lines) {
134
+ if (line.startsWith("worktree ")) {
135
+ entry.path = line.slice("worktree ".length).trim();
136
+ } else if (line.startsWith("HEAD ")) {
137
+ entry.head = line.slice("HEAD ".length).trim();
138
+ } else if (line.startsWith("branch ")) {
139
+ const ref = line.slice("branch ".length).trim();
140
+ entry.branch = ref.replace(/^refs\/heads\//, "");
141
+ } else if (line === "bare") {
142
+ entry.bare = true;
143
+ }
144
+ }
145
+ if (entry.path) {
146
+ entries.push(entry);
147
+ }
148
+ }
149
+ return entries;
150
+ }
151
+ async function pruneWorktrees(repoRoot) {
152
+ try {
153
+ await execFileAsync2("git", ["worktree", "prune"], {
154
+ cwd: repoRoot,
155
+ encoding: "utf8",
156
+ timeout: GIT_TIMEOUT_MS,
157
+ windowsHide: true
158
+ });
159
+ } catch {
160
+ }
161
+ }
162
+ var path4, import_promises3, import_node_fs2, import_node_child_process2, import_node_util2, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER;
163
+ var init_git_worktree = __esm({
164
+ "src/git/git-worktree.ts"() {
165
+ "use strict";
166
+ path4 = __toESM(require("path"));
167
+ import_promises3 = require("fs/promises");
168
+ import_node_fs2 = require("fs");
169
+ import_node_child_process2 = require("child_process");
170
+ import_node_util2 = require("util");
171
+ execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
172
+ WORKTREE_DIR_NAME = ".adhdev-worktrees";
173
+ GIT_TIMEOUT_MS = 3e4;
174
+ GIT_MAX_BUFFER = 4 * 1024 * 1024;
175
+ }
176
+ });
177
+
49
178
  // src/config/config.ts
50
179
  var config_exports = {};
51
180
  __export(config_exports, {
@@ -304,10 +433,10 @@ function getMeshConfigPath() {
304
433
  return (0, import_path2.join)(getConfigDir(), "meshes.json");
305
434
  }
306
435
  function loadMeshConfig() {
307
- const path26 = getMeshConfigPath();
308
- if (!(0, import_fs2.existsSync)(path26)) return { meshes: [] };
436
+ const path27 = getMeshConfigPath();
437
+ if (!(0, import_fs2.existsSync)(path27)) return { meshes: [] };
309
438
  try {
310
- const raw = JSON.parse((0, import_fs2.readFileSync)(path26, "utf-8"));
439
+ const raw = JSON.parse((0, import_fs2.readFileSync)(path27, "utf-8"));
311
440
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
312
441
  return raw;
313
442
  } catch {
@@ -315,16 +444,16 @@ function loadMeshConfig() {
315
444
  }
316
445
  }
317
446
  function saveMeshConfig(config) {
318
- const path26 = getMeshConfigPath();
319
- (0, import_fs2.writeFileSync)(path26, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
447
+ const path27 = getMeshConfigPath();
448
+ (0, import_fs2.writeFileSync)(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
320
449
  }
321
450
  function normalizeRepoIdentity(remoteUrl) {
322
451
  let identity = remoteUrl.trim();
323
452
  if (identity.startsWith("http://") || identity.startsWith("https://")) {
324
453
  try {
325
454
  const url = new URL(identity);
326
- const path26 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
327
- return `${url.hostname}/${path26}`;
455
+ const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
456
+ return `${url.hostname}/${path27}`;
328
457
  } catch {
329
458
  }
330
459
  }
@@ -332,6 +461,18 @@ function normalizeRepoIdentity(remoteUrl) {
332
461
  if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
333
462
  return identity;
334
463
  }
464
+ function mergeMeshPolicy(base, patch) {
465
+ const policy = { ...DEFAULT_MESH_POLICY, ...base || {}, ...patch || {} };
466
+ if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
467
+ policy.dirtyWorkspaceBehavior = "warn";
468
+ }
469
+ const maxParallelTasks = Number(policy.maxParallelTasks);
470
+ policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
471
+ if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
472
+ policy.sessionCleanupOnNodeRemove = "preserve";
473
+ }
474
+ return policy;
475
+ }
335
476
  function listMeshes() {
336
477
  return loadMeshConfig().meshes;
337
478
  }
@@ -355,7 +496,7 @@ function createMesh(opts) {
355
496
  repoIdentity,
356
497
  repoRemoteUrl: opts.repoRemoteUrl,
357
498
  defaultBranch: opts.defaultBranch,
358
- policy: { ...DEFAULT_MESH_POLICY, ...opts.policy },
499
+ policy: mergeMeshPolicy(void 0, opts.policy),
359
500
  coordinator: opts.coordinator || {},
360
501
  nodes: [],
361
502
  createdAt: now,
@@ -371,7 +512,7 @@ function updateMesh(meshId, opts) {
371
512
  if (!mesh) return void 0;
372
513
  if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
373
514
  if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
374
- if (opts.policy) mesh.policy = { ...mesh.policy, ...opts.policy };
515
+ if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
375
516
  if (opts.coordinator) mesh.coordinator = opts.coordinator;
376
517
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
377
518
  saveMeshConfig(config);
@@ -399,9 +540,12 @@ function addNode(meshId, opts) {
399
540
  id: `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
400
541
  workspace: opts.workspace.trim(),
401
542
  repoRoot: opts.repoRoot,
543
+ daemonId: opts.daemonId,
402
544
  userOverrides: opts.userOverrides || {},
403
545
  policy: opts.policy || {},
404
- isLocalWorktree: opts.isLocalWorktree
546
+ isLocalWorktree: opts.isLocalWorktree,
547
+ worktreeBranch: opts.worktreeBranch,
548
+ clonedFromNodeId: opts.clonedFromNodeId
405
549
  };
406
550
  mesh.nodes.push(node);
407
551
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -431,7 +575,7 @@ function updateNode(meshId, nodeId, opts) {
431
575
  saveMeshConfig(config);
432
576
  return node;
433
577
  }
434
- var import_fs2, import_path2, import_crypto3;
578
+ var import_fs2, import_path2, import_crypto3, SESSION_CLEANUP_MODES;
435
579
  var init_mesh_config = __esm({
436
580
  "src/config/mesh-config.ts"() {
437
581
  "use strict";
@@ -440,6 +584,7 @@ var init_mesh_config = __esm({
440
584
  import_crypto3 = require("crypto");
441
585
  init_config();
442
586
  init_repo_mesh_types();
587
+ SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
443
588
  }
444
589
  });
445
590
 
@@ -449,7 +594,7 @@ __export(coordinator_prompt_exports, {
449
594
  buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
450
595
  });
451
596
  function buildCoordinatorSystemPrompt(ctx) {
452
- const { mesh, status, userInstruction } = ctx;
597
+ const { mesh, status, userInstruction, coordinatorCliType } = ctx;
453
598
  const sections = [];
454
599
  sections.push(`You are a **Repo Mesh Coordinator** \u2014 a technical team lead who orchestrates work across multiple agent sessions on a shared Git repository.
455
600
 
@@ -463,15 +608,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
463
608
  } else {
464
609
  sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
465
610
  }
466
- sections.push(buildPolicySection(mesh.policy));
611
+ sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
467
612
  sections.push(TOOLS_SECTION);
468
613
  sections.push(WORKFLOW_SECTION);
469
- sections.push(RULES_SECTION);
614
+ sections.push(buildRulesSection(coordinatorCliType));
470
615
  if (userInstruction) {
471
616
  sections.push(`## Additional Context
472
617
  ${userInstruction}`);
473
618
  }
474
- if (mesh.coordinator.systemPromptSuffix) {
619
+ if (mesh.coordinator?.systemPromptSuffix) {
475
620
  sections.push(mesh.coordinator.systemPromptSuffix);
476
621
  }
477
622
  return sections.join("\n\n");
@@ -516,10 +661,29 @@ function buildPolicySection(policy) {
516
661
  return `## Policy
517
662
  ${rules.join("\n")}`;
518
663
  }
519
- var TOOLS_SECTION, WORKFLOW_SECTION, RULES_SECTION;
664
+ function buildRulesSection(coordinatorCliType) {
665
+ const coordinatorNote = coordinatorCliType ? `
666
+ - **Coordinator runtime is not a delegation default.** This coordinator is running as \`${coordinatorCliType}\`, but delegated node sessions must follow the user's requested provider, not the coordinator's own runtime.` : "";
667
+ return `## Rules
668
+
669
+ - **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
670
+ - **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
671
+ - **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
672
+ - **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
673
+ - **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
674
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
675
+ - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
676
+ - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
677
+ - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
678
+ - **Never fabricate tool results.** Always call the actual tool; never pretend you did.
679
+ - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
680
+ - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
681
+ }
682
+ var TOOLS_SECTION, WORKFLOW_SECTION;
520
683
  var init_coordinator_prompt = __esm({
521
684
  "src/mesh/coordinator-prompt.ts"() {
522
685
  "use strict";
686
+ init_repo_mesh_types();
523
687
  TOOLS_SECTION = `## Available Tools
524
688
 
525
689
  | Tool | Purpose |
@@ -531,30 +695,23 @@ var init_coordinator_prompt = __esm({
531
695
  | \`mesh_read_chat\` | Read an agent's recent messages to check progress |
532
696
  | \`mesh_git_status\` | Check git status on a specific node |
533
697
  | \`mesh_checkpoint\` | Create a git checkpoint on a node |
534
- | \`mesh_approve\` | Approve/reject a pending agent action |`;
698
+ | \`mesh_approve\` | Approve/reject a pending agent action |
699
+ | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
700
+ | \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
535
701
  WORKFLOW_SECTION = `## Orchestration Workflow
536
702
 
537
703
  1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
538
704
  2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
539
705
  3. **Delegate** \u2014 For each task:
540
706
  a. Pick the best node (consider: health, dirty state, current workload).
541
- b. If no session exists, call \`mesh_launch_session\` to start one.
542
- c. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
707
+ b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
708
+ c. If no session exists, call \`mesh_launch_session\` to start one.
709
+ d. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
543
710
  4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
544
711
  5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
545
712
  6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
546
- 7. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
547
- RULES_SECTION = `## Rules
548
-
549
- - **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
550
- - **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
551
- - **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
552
- - **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
553
- - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
554
- - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
555
- - **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
556
- - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
557
- - **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
713
+ 7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
714
+ 8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
558
715
  }
559
716
  });
560
717
 
@@ -573,13 +730,13 @@ function getDaemonLogDir() {
573
730
  return LOG_DIR;
574
731
  }
575
732
  function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
576
- return path9.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
733
+ return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
577
734
  }
578
735
  function checkDateRotation() {
579
736
  const today = getDateStr();
580
737
  if (today !== currentDate) {
581
738
  currentDate = today;
582
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
739
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
583
740
  cleanOldLogs();
584
741
  }
585
742
  }
@@ -593,7 +750,7 @@ function cleanOldLogs() {
593
750
  const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
594
751
  if (dateMatch && dateMatch[1] < cutoffStr) {
595
752
  try {
596
- fs2.unlinkSync(path9.join(LOG_DIR, file));
753
+ fs2.unlinkSync(path10.join(LOG_DIR, file));
597
754
  } catch {
598
755
  }
599
756
  }
@@ -709,17 +866,17 @@ function installGlobalInterceptor() {
709
866
  writeToFile(`Log file: ${currentLogFile}`);
710
867
  writeToFile(`Log level: ${currentLevel}`);
711
868
  }
712
- var fs2, path9, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
869
+ var fs2, path10, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
713
870
  var init_logger = __esm({
714
871
  "src/logging/logger.ts"() {
715
872
  "use strict";
716
873
  fs2 = __toESM(require("fs"));
717
- path9 = __toESM(require("path"));
874
+ path10 = __toESM(require("path"));
718
875
  os4 = __toESM(require("os"));
719
876
  LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
720
877
  LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
721
878
  currentLevel = "info";
722
- LOG_DIR = process.platform === "win32" ? path9.join(process.env.LOCALAPPDATA || process.env.APPDATA || path9.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path9.join(os4.homedir(), "Library", "Logs", "adhdev") : path9.join(os4.homedir(), ".local", "share", "adhdev", "logs");
879
+ LOG_DIR = process.platform === "win32" ? path10.join(process.env.LOCALAPPDATA || process.env.APPDATA || path10.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path10.join(os4.homedir(), "Library", "Logs", "adhdev") : path10.join(os4.homedir(), ".local", "share", "adhdev", "logs");
723
880
  MAX_LOG_SIZE = 5 * 1024 * 1024;
724
881
  MAX_LOG_DAYS = 7;
725
882
  try {
@@ -727,16 +884,16 @@ var init_logger = __esm({
727
884
  } catch {
728
885
  }
729
886
  currentDate = getDateStr();
730
- currentLogFile = path9.join(LOG_DIR, `daemon-${currentDate}.log`);
887
+ currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
731
888
  cleanOldLogs();
732
889
  try {
733
- const oldLog = path9.join(LOG_DIR, "daemon.log");
890
+ const oldLog = path10.join(LOG_DIR, "daemon.log");
734
891
  if (fs2.existsSync(oldLog)) {
735
892
  const stat2 = fs2.statSync(oldLog);
736
893
  const oldDate = stat2.mtime.toISOString().slice(0, 10);
737
- fs2.renameSync(oldLog, path9.join(LOG_DIR, `daemon-${oldDate}.log`));
894
+ fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
738
895
  }
739
- const oldLogBackup = path9.join(LOG_DIR, "daemon.log.old");
896
+ const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
740
897
  if (fs2.existsSync(oldLogBackup)) {
741
898
  fs2.unlinkSync(oldLogBackup);
742
899
  }
@@ -768,7 +925,7 @@ var init_logger = __esm({
768
925
  }
769
926
  };
770
927
  interceptorInstalled = false;
771
- LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
928
+ LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
772
929
  }
773
930
  });
774
931
 
@@ -1236,9 +1393,9 @@ function buildCliScreenSnapshot(text) {
1236
1393
  function findBinary(name) {
1237
1394
  const trimmed = String(name || "").trim();
1238
1395
  if (!trimmed) return trimmed;
1239
- const expanded = trimmed.startsWith("~") ? path13.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1240
- if (path13.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1241
- return path13.isAbsolute(expanded) ? expanded : path13.resolve(expanded);
1396
+ const expanded = trimmed.startsWith("~") ? path14.join(os9.homedir(), trimmed.slice(1)) : trimmed;
1397
+ if (path14.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
1398
+ return path14.isAbsolute(expanded) ? expanded : path14.resolve(expanded);
1242
1399
  }
1243
1400
  const isWin = os9.platform() === "win32";
1244
1401
  try {
@@ -1254,7 +1411,7 @@ function findBinary(name) {
1254
1411
  }
1255
1412
  }
1256
1413
  function isScriptBinary(binaryPath) {
1257
- if (!path13.isAbsolute(binaryPath)) return false;
1414
+ if (!path14.isAbsolute(binaryPath)) return false;
1258
1415
  try {
1259
1416
  const fs16 = require("fs");
1260
1417
  const resolved = fs16.realpathSync(binaryPath);
@@ -1270,7 +1427,7 @@ function isScriptBinary(binaryPath) {
1270
1427
  }
1271
1428
  }
1272
1429
  function looksLikeMachOOrElf(filePath) {
1273
- if (!path13.isAbsolute(filePath)) return false;
1430
+ if (!path14.isAbsolute(filePath)) return false;
1274
1431
  try {
1275
1432
  const fs16 = require("fs");
1276
1433
  const resolved = fs16.realpathSync(filePath);
@@ -1359,12 +1516,12 @@ function normalizeCliProviderForRuntime(raw) {
1359
1516
  }
1360
1517
  };
1361
1518
  }
1362
- var os9, path13, import_child_process4, buildCliSpawnEnv;
1519
+ var os9, path14, import_child_process4, buildCliSpawnEnv;
1363
1520
  var init_provider_cli_shared = __esm({
1364
1521
  "src/cli-adapters/provider-cli-shared.ts"() {
1365
1522
  "use strict";
1366
1523
  os9 = __toESM(require("os"));
1367
- path13 = __toESM(require("path"));
1524
+ path14 = __toESM(require("path"));
1368
1525
  import_child_process4 = require("child_process");
1369
1526
  init_spawn_env();
1370
1527
  buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
@@ -1487,7 +1644,7 @@ var init_provider_cli_config = __esm({
1487
1644
 
1488
1645
  // src/cli-adapters/provider-cli-runtime.ts
1489
1646
  function resolveCliSpawnPlan(options) {
1490
- const { provider, runtimeSettings, workingDir, extraArgs } = options;
1647
+ const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
1491
1648
  const { spawn: spawnConfig } = provider;
1492
1649
  const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
1493
1650
  const binaryPath = findBinary(configuredCommand);
@@ -1495,9 +1652,9 @@ function resolveCliSpawnPlan(options) {
1495
1652
  const allArgs = [...spawnConfig.args, ...extraArgs];
1496
1653
  let shellCmd;
1497
1654
  let shellArgs;
1498
- const useShellUnix = !isWin && (!!spawnConfig.shell || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1655
+ const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
1499
1656
  const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
1500
- const useShellWin = !!spawnConfig.shell || isCmdShim || !path14.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1657
+ const useShellWin = !!spawnConfig.shell || isCmdShim || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
1501
1658
  const useShell = isWin ? useShellWin : useShellUnix;
1502
1659
  if (useShell) {
1503
1660
  shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
@@ -1511,7 +1668,7 @@ function resolveCliSpawnPlan(options) {
1511
1668
  shellCmd = binaryPath;
1512
1669
  shellArgs = allArgs;
1513
1670
  }
1514
- const env = buildCliSpawnEnv(process.env, spawnConfig.env);
1671
+ const env = buildCliSpawnEnv(process.env, { ...spawnConfig.env || {}, ...extraEnv || {} });
1515
1672
  env.TERMINAL_CWD = workingDir;
1516
1673
  return {
1517
1674
  binaryPath,
@@ -1573,12 +1730,12 @@ function respondToCliTerminalQueries(options) {
1573
1730
  }
1574
1731
  return "";
1575
1732
  }
1576
- var os10, path14, import_session_host_core2;
1733
+ var os10, path15, import_session_host_core2;
1577
1734
  var init_provider_cli_runtime = __esm({
1578
1735
  "src/cli-adapters/provider-cli-runtime.ts"() {
1579
1736
  "use strict";
1580
1737
  os10 = __toESM(require("os"));
1581
- path14 = __toESM(require("path"));
1738
+ path15 = __toESM(require("path"));
1582
1739
  import_session_host_core2 = require("@adhdev/session-host-core");
1583
1740
  init_provider_cli_shared();
1584
1741
  }
@@ -1614,8 +1771,9 @@ var init_provider_cli_adapter = __esm({
1614
1771
  init_provider_cli_runtime();
1615
1772
  init_provider_cli_shared();
1616
1773
  ProviderCliAdapter = class _ProviderCliAdapter {
1617
- constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
1774
+ constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
1618
1775
  this.extraArgs = extraArgs;
1776
+ this.extraEnv = extraEnv;
1619
1777
  this.provider = provider;
1620
1778
  this.transportFactory = transportFactory;
1621
1779
  this.cliType = provider.type;
@@ -1766,8 +1924,9 @@ var init_provider_cli_adapter = __esm({
1766
1924
  const currentSnapshot = normalizeScreenSnapshot(screenText);
1767
1925
  const lastSnapshot = this.lastScreenSnapshot;
1768
1926
  if (!lastSnapshot || lastSnapshot === currentSnapshot) return screenText;
1769
- const staleSnapshotLooksActive = /\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel/i.test(lastSnapshot);
1770
- const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:\n|\r|$)/.test(screenText) && !/\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel/i.test(screenText);
1927
+ const activeScreenPattern = /\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel|Enter to confirm\s*[·•-]\s*Esc to cancel|\b(?:MCP servers?|tool calls?)\b[^\n\r]{0,160}\brequire approval\b/i;
1928
+ const staleSnapshotLooksActive = activeScreenPattern.test(lastSnapshot);
1929
+ const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:Try\s+["“][^\n\r"”]+["”])?\s*(?:\n|\r|$)/.test(screenText) && !activeScreenPattern.test(screenText);
1771
1930
  if (staleSnapshotLooksActive && currentScreenLooksIdle) return screenText;
1772
1931
  if (currentSnapshot.length >= lastSnapshot.length) return screenText;
1773
1932
  return `${screenText}
@@ -1930,7 +2089,8 @@ ${lastSnapshot}`;
1930
2089
  provider: this.provider,
1931
2090
  runtimeSettings: this.runtimeSettings,
1932
2091
  workingDir: this.workingDir,
1933
- extraArgs: this.extraArgs
2092
+ extraArgs: this.extraArgs,
2093
+ extraEnv: this.extraEnv
1934
2094
  });
1935
2095
  LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
1936
2096
  this.resetTraceSession();
@@ -3128,9 +3288,8 @@ ${lastSnapshot}`;
3128
3288
  };
3129
3289
  this.recordTrace("submit_echo_missing", diagnostic);
3130
3290
  if (this.requirePromptEchoBeforeSubmit) {
3131
- const message = `${this.cliName} prompt echo was not observed on the PTY screen before submit`;
3132
- LOG.warn("CLI", `[${this.cliType}] ${message} elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
3133
- completion.rejectOnce(new Error(message));
3291
+ LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending guarded submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
3292
+ this.submitSendKey(state, completion);
3134
3293
  return;
3135
3294
  }
3136
3295
  LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
@@ -3177,7 +3336,14 @@ ${lastSnapshot}`;
3177
3336
  })() : null;
3178
3337
  const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
3179
3338
  if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
3180
- throw new Error(`${this.cliName} is still processing the previous prompt`);
3339
+ const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
3340
+ const parsedHasActionableModal = Boolean(
3341
+ parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
3342
+ );
3343
+ const terminalLooksIdle = this.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && !this.hasActionableApproval() && !parsedHasActionableModal;
3344
+ if (!terminalLooksIdle) {
3345
+ throw new Error(`${this.cliName} is still processing the previous prompt`);
3346
+ }
3181
3347
  }
3182
3348
  if (this.isWaitingForResponse && !allowInputDuringGeneration) {
3183
3349
  if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
@@ -3727,6 +3893,7 @@ __export(index_exports, {
3727
3893
  createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
3728
3894
  createInteractionId: () => createInteractionId,
3729
3895
  createMesh: () => createMesh,
3896
+ createWorktree: () => createWorktree,
3730
3897
  deleteMesh: () => deleteMesh,
3731
3898
  detectAllVersions: () => detectAllVersions,
3732
3899
  detectCLIs: () => detectCLIs,
@@ -3779,6 +3946,7 @@ __export(index_exports, {
3779
3946
  launchWithCdp: () => launchWithCdp,
3780
3947
  listHostedCliRuntimes: () => listHostedCliRuntimes,
3781
3948
  listMeshes: () => listMeshes,
3949
+ listWorktrees: () => listWorktrees,
3782
3950
  loadConfig: () => loadConfig,
3783
3951
  loadState: () => loadState,
3784
3952
  logCommand: () => logCommand,
@@ -3798,6 +3966,7 @@ __export(index_exports, {
3798
3966
  normalizeSessionModalFields: () => normalizeSessionModalFields,
3799
3967
  parsePorcelainV2Status: () => parsePorcelainV2Status,
3800
3968
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
3969
+ parseWorktreeListOutput: () => parseWorktreeListOutput,
3801
3970
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
3802
3971
  partitionSessionHostRecords: () => partitionSessionHostRecords,
3803
3972
  prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
@@ -3807,6 +3976,7 @@ __export(index_exports, {
3807
3976
  recordDebugTrace: () => recordDebugTrace,
3808
3977
  registerExtensionProviders: () => registerExtensionProviders,
3809
3978
  removeNode: () => removeNode,
3979
+ removeWorktree: () => removeWorktree,
3810
3980
  resetConfig: () => resetConfig,
3811
3981
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
3812
3982
  resetState: () => resetState,
@@ -3816,6 +3986,7 @@ __export(index_exports, {
3816
3986
  resolveGitRepository: () => resolveGitRepository,
3817
3987
  resolveSessionHostAppName: () => resolveSessionHostAppName,
3818
3988
  resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
3989
+ resolveWorktreePath: () => resolveWorktreePath,
3819
3990
  runAsyncBatch: () => runAsyncBatch,
3820
3991
  runGit: () => runGit,
3821
3992
  saveConfig: () => saveConfig,
@@ -4739,6 +4910,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
4739
4910
  "dirty_index_required",
4740
4911
  "conflict",
4741
4912
  "invalid_args",
4913
+ "nothing_to_commit",
4742
4914
  "git_command_failed"
4743
4915
  ]);
4744
4916
  function failure(reason, error) {
@@ -4983,7 +5155,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
4983
5155
  } catch (err) {
4984
5156
  const output = (err?.stdout || "") + (err?.stderr || "");
4985
5157
  if (/nothing to commit/i.test(output)) {
4986
- throw new GitCommandError("git_command_failed", "Nothing to commit");
5158
+ throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
5159
+ stdout: err?.stdout,
5160
+ stderr: err?.stderr
5161
+ });
4987
5162
  }
4988
5163
  throw err;
4989
5164
  }
@@ -5175,20 +5350,23 @@ var TurnSnapshotTracker = class {
5175
5350
  }
5176
5351
  };
5177
5352
 
5353
+ // src/git/index.ts
5354
+ init_git_worktree();
5355
+
5178
5356
  // src/index.ts
5179
5357
  init_config();
5180
5358
 
5181
5359
  // src/config/workspaces.ts
5182
5360
  var fs = __toESM(require("fs"));
5183
5361
  var os = __toESM(require("os"));
5184
- var path4 = __toESM(require("path"));
5362
+ var path5 = __toESM(require("path"));
5185
5363
  var import_crypto2 = require("crypto");
5186
5364
  var MAX_WORKSPACES = 50;
5187
5365
  function expandPath(p) {
5188
5366
  const t = (p || "").trim();
5189
5367
  if (!t) return "";
5190
- if (t.startsWith("~")) return path4.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5191
- return path4.resolve(t);
5368
+ if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
5369
+ return path5.resolve(t);
5192
5370
  }
5193
5371
  function validateWorkspacePath(absPath) {
5194
5372
  try {
@@ -5202,7 +5380,7 @@ function validateWorkspacePath(absPath) {
5202
5380
  }
5203
5381
  }
5204
5382
  function defaultWorkspaceLabel(absPath) {
5205
- const base = path4.basename(absPath) || absPath;
5383
+ const base = path5.basename(absPath) || absPath;
5206
5384
  return base;
5207
5385
  }
5208
5386
  function getDefaultWorkspacePath(config) {
@@ -5293,9 +5471,9 @@ function resolveIdeLaunchWorkspace(args, config) {
5293
5471
  return getDefaultWorkspacePath(config) || void 0;
5294
5472
  }
5295
5473
  function findWorkspaceByPath(config, rawPath) {
5296
- const abs = path4.resolve(expandPath(rawPath));
5474
+ const abs = path5.resolve(expandPath(rawPath));
5297
5475
  if (!abs) return void 0;
5298
- return (config.workspaces || []).find((w) => path4.resolve(expandPath(w.path)) === abs);
5476
+ return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
5299
5477
  }
5300
5478
  function addWorkspaceEntry(config, rawPath, label, options) {
5301
5479
  const abs = expandPath(rawPath);
@@ -5311,7 +5489,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
5311
5489
  const v = validateWorkspacePath(abs);
5312
5490
  if (!v.ok) return { error: v.error };
5313
5491
  const list = [...config.workspaces || []];
5314
- if (list.some((w) => path4.resolve(w.path) === abs)) {
5492
+ if (list.some((w) => path5.resolve(w.path) === abs)) {
5315
5493
  return { error: "Workspace already in list" };
5316
5494
  }
5317
5495
  if (list.length >= MAX_WORKSPACES) {
@@ -5345,7 +5523,7 @@ function setDefaultWorkspaceId(config, id) {
5345
5523
  }
5346
5524
 
5347
5525
  // src/config/recent-activity.ts
5348
- var path5 = __toESM(require("path"));
5526
+ var path6 = __toESM(require("path"));
5349
5527
 
5350
5528
  // src/providers/summary-metadata.ts
5351
5529
  function normalizeSummaryItem(item) {
@@ -5414,9 +5592,9 @@ var MAX_ACTIVITY = 30;
5414
5592
  function normalizeWorkspace(workspace) {
5415
5593
  if (!workspace) return "";
5416
5594
  try {
5417
- return path5.resolve(expandPath(workspace));
5595
+ return path6.resolve(expandPath(workspace));
5418
5596
  } catch {
5419
- return path5.resolve(workspace);
5597
+ return path6.resolve(workspace);
5420
5598
  }
5421
5599
  }
5422
5600
  function buildRecentActivityKey(entry) {
@@ -5584,14 +5762,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
5584
5762
  }
5585
5763
 
5586
5764
  // src/config/saved-sessions.ts
5587
- var path6 = __toESM(require("path"));
5765
+ var path7 = __toESM(require("path"));
5588
5766
  var MAX_SAVED_SESSIONS = 500;
5589
5767
  function normalizeWorkspace2(workspace) {
5590
5768
  if (!workspace) return "";
5591
5769
  try {
5592
- return path6.resolve(expandPath(workspace));
5770
+ return path7.resolve(expandPath(workspace));
5593
5771
  } catch {
5594
- return path6.resolve(workspace);
5772
+ return path7.resolve(workspace);
5595
5773
  }
5596
5774
  }
5597
5775
  function buildSavedProviderSessionKey(providerSessionId) {
@@ -5770,7 +5948,7 @@ function resetState() {
5770
5948
  var import_child_process = require("child_process");
5771
5949
  var import_fs4 = require("fs");
5772
5950
  var import_os2 = require("os");
5773
- var path7 = __toESM(require("path"));
5951
+ var path8 = __toESM(require("path"));
5774
5952
  var BUILTIN_IDE_DEFINITIONS = [];
5775
5953
  var registeredIDEs = /* @__PURE__ */ new Map();
5776
5954
  function registerIDEDefinition(def) {
@@ -5789,9 +5967,9 @@ function getMergedDefinitions() {
5789
5967
  function findCliCommand(command) {
5790
5968
  const trimmed = String(command || "").trim();
5791
5969
  if (!trimmed) return null;
5792
- if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5793
- const candidate = trimmed.startsWith("~") ? path7.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5794
- const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
5970
+ if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
5971
+ const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
5972
+ const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
5795
5973
  return (0, import_fs4.existsSync)(resolved) ? resolved : null;
5796
5974
  }
5797
5975
  try {
@@ -5819,7 +5997,7 @@ function getIdeVersion(cliCommand) {
5819
5997
  function checkPathExists(paths) {
5820
5998
  const home = (0, import_os2.homedir)();
5821
5999
  for (const p of paths) {
5822
- const normalized = p.startsWith("~") ? path7.join(home, p.slice(1)) : p;
6000
+ const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
5823
6001
  if (normalized.includes("*")) {
5824
6002
  const username = home.split(/[\\/]/).pop() || "";
5825
6003
  const resolved = normalized.replace("*", username);
@@ -5831,19 +6009,19 @@ function checkPathExists(paths) {
5831
6009
  return null;
5832
6010
  }
5833
6011
  async function detectIDEs(providerLoader) {
5834
- const os21 = (0, import_os2.platform)();
6012
+ const os22 = (0, import_os2.platform)();
5835
6013
  const results = [];
5836
6014
  for (const def of getMergedDefinitions()) {
5837
6015
  const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
5838
- const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os21] || []) || []);
6016
+ const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
5839
6017
  let resolvedCli = cliPath;
5840
- if (!resolvedCli && appPath && os21 === "darwin") {
6018
+ if (!resolvedCli && appPath && os22 === "darwin") {
5841
6019
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
5842
6020
  if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
5843
6021
  }
5844
- if (!resolvedCli && appPath && os21 === "win32") {
5845
- const { dirname: dirname8 } = await import("path");
5846
- const appDir = dirname8(appPath);
6022
+ if (!resolvedCli && appPath && os22 === "win32") {
6023
+ const { dirname: dirname9 } = await import("path");
6024
+ const appDir = dirname9(appPath);
5847
6025
  const candidates = [
5848
6026
  `${appDir}\\\\bin\\\\${def.cli}.cmd`,
5849
6027
  `${appDir}\\\\bin\\\\${def.cli}`,
@@ -5858,7 +6036,7 @@ async function detectIDEs(providerLoader) {
5858
6036
  }
5859
6037
  }
5860
6038
  }
5861
- const installed = os21 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
6039
+ const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
5862
6040
  const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
5863
6041
  results.push({
5864
6042
  id: def.id,
@@ -5877,7 +6055,7 @@ async function detectIDEs(providerLoader) {
5877
6055
  // src/detection/cli-detector.ts
5878
6056
  var import_child_process2 = require("child_process");
5879
6057
  var os2 = __toESM(require("os"));
5880
- var path8 = __toESM(require("path"));
6058
+ var path9 = __toESM(require("path"));
5881
6059
  var import_fs5 = require("fs");
5882
6060
  function parseVersion(raw) {
5883
6061
  const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
@@ -5890,18 +6068,18 @@ function shellQuote(value) {
5890
6068
  function expandHome(value) {
5891
6069
  const trimmed = value.trim();
5892
6070
  if (!trimmed.startsWith("~")) return trimmed;
5893
- return path8.join(os2.homedir(), trimmed.slice(1));
6071
+ return path9.join(os2.homedir(), trimmed.slice(1));
5894
6072
  }
5895
6073
  function isExplicitCommandPath(command) {
5896
6074
  const trimmed = command.trim();
5897
- return path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
6075
+ return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
5898
6076
  }
5899
6077
  function resolveCommandPath(command) {
5900
6078
  const trimmed = command.trim();
5901
6079
  if (!trimmed) return null;
5902
6080
  if (isExplicitCommandPath(trimmed)) {
5903
6081
  const expanded = expandHome(trimmed);
5904
- const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
6082
+ const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
5905
6083
  return (0, import_fs5.existsSync)(candidate) ? candidate : null;
5906
6084
  }
5907
6085
  return null;
@@ -8170,9 +8348,9 @@ ${cleanBody}`;
8170
8348
 
8171
8349
  // src/config/chat-history.ts
8172
8350
  var fs3 = __toESM(require("fs"));
8173
- var path10 = __toESM(require("path"));
8351
+ var path11 = __toESM(require("path"));
8174
8352
  var os5 = __toESM(require("os"));
8175
- var HISTORY_DIR = path10.join(os5.homedir(), ".adhdev", "history");
8353
+ var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
8176
8354
  var RETAIN_DAYS = 30;
8177
8355
  var SAVED_HISTORY_INDEX_VERSION = 1;
8178
8356
  var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -8335,7 +8513,7 @@ function extractSavedHistorySessionIdFromFile(file) {
8335
8513
  function buildSavedHistoryFileSignatureMap(dir, files) {
8336
8514
  return new Map(files.map((file) => {
8337
8515
  try {
8338
- const stat2 = fs3.statSync(path10.join(dir, file));
8516
+ const stat2 = fs3.statSync(path11.join(dir, file));
8339
8517
  return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
8340
8518
  } catch {
8341
8519
  return [file, `${file}:missing`];
@@ -8346,7 +8524,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
8346
8524
  return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
8347
8525
  }
8348
8526
  function getSavedHistoryIndexFilePath(dir) {
8349
- return path10.join(dir, SAVED_HISTORY_INDEX_FILE);
8527
+ return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
8350
8528
  }
8351
8529
  function getSavedHistoryIndexLockPath(dir) {
8352
8530
  return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
@@ -8448,7 +8626,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
8448
8626
  }
8449
8627
  for (const file of Array.from(currentEntries.keys())) {
8450
8628
  if (incomingFiles.has(file)) continue;
8451
- if (!fs3.existsSync(path10.join(dir, file))) {
8629
+ if (!fs3.existsSync(path11.join(dir, file))) {
8452
8630
  currentEntries.delete(file);
8453
8631
  }
8454
8632
  }
@@ -8474,7 +8652,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8474
8652
  const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
8475
8653
  const files = listHistoryFiles(dir);
8476
8654
  for (const file of files) {
8477
- const stat2 = fs3.statSync(path10.join(dir, file));
8655
+ const stat2 = fs3.statSync(path11.join(dir, file));
8478
8656
  if (stat2.mtimeMs > indexStat.mtimeMs) return true;
8479
8657
  }
8480
8658
  return false;
@@ -8484,14 +8662,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
8484
8662
  }
8485
8663
  function buildSavedHistoryFileSignature(dir, file) {
8486
8664
  try {
8487
- const stat2 = fs3.statSync(path10.join(dir, file));
8665
+ const stat2 = fs3.statSync(path11.join(dir, file));
8488
8666
  return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
8489
8667
  } catch {
8490
8668
  return `${file}:missing`;
8491
8669
  }
8492
8670
  }
8493
8671
  function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
8494
- const filePath = path10.join(dir, file);
8672
+ const filePath = path11.join(dir, file);
8495
8673
  const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
8496
8674
  const currentEntry = entries.get(file) || null;
8497
8675
  const nextSummary = updater(currentEntry?.summary || null);
@@ -8564,7 +8742,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
8564
8742
  function computeSavedHistoryFileSummary(dir, file) {
8565
8743
  const historySessionId = extractSavedHistorySessionIdFromFile(file);
8566
8744
  if (!historySessionId) return null;
8567
- const filePath = path10.join(dir, file);
8745
+ const filePath = path11.join(dir, file);
8568
8746
  const content = fs3.readFileSync(filePath, "utf-8");
8569
8747
  const lines = content.split("\n").filter(Boolean);
8570
8748
  let messageCount = 0;
@@ -8651,7 +8829,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
8651
8829
  const summaryBySessionId = /* @__PURE__ */ new Map();
8652
8830
  const nextPersistedEntries = /* @__PURE__ */ new Map();
8653
8831
  for (const file of files.slice().sort()) {
8654
- const filePath = path10.join(dir, file);
8832
+ const filePath = path11.join(dir, file);
8655
8833
  const signature = fileSignatures.get(file) || `${file}:missing`;
8656
8834
  const cached = savedHistoryFileSummaryCache.get(filePath);
8657
8835
  const persisted = persistedEntries.get(file);
@@ -8771,12 +8949,12 @@ var ChatHistoryWriter = class {
8771
8949
  });
8772
8950
  }
8773
8951
  if (newMessages.length === 0) return;
8774
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
8952
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8775
8953
  fs3.mkdirSync(dir, { recursive: true });
8776
8954
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8777
8955
  const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
8778
8956
  const fileName = `${filePrefix}${date}.jsonl`;
8779
- const filePath = path10.join(dir, fileName);
8957
+ const filePath = path11.join(dir, fileName);
8780
8958
  const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
8781
8959
  fs3.appendFileSync(filePath, lines, "utf-8");
8782
8960
  updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
@@ -8867,11 +9045,11 @@ var ChatHistoryWriter = class {
8867
9045
  const ws = String(workspace || "").trim();
8868
9046
  if (!id || !ws) return;
8869
9047
  try {
8870
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9048
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8871
9049
  fs3.mkdirSync(dir, { recursive: true });
8872
9050
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
8873
9051
  const fileName = `${this.sanitize(id)}_${date}.jsonl`;
8874
- const filePath = path10.join(dir, fileName);
9052
+ const filePath = path11.join(dir, fileName);
8875
9053
  const record = {
8876
9054
  ts: (/* @__PURE__ */ new Date()).toISOString(),
8877
9055
  receivedAt: Date.now(),
@@ -8917,14 +9095,14 @@ var ChatHistoryWriter = class {
8917
9095
  this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
8918
9096
  this.lastSeenCounts.delete(fromDedupKey);
8919
9097
  }
8920
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9098
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8921
9099
  if (!fs3.existsSync(dir)) return;
8922
9100
  const fromPrefix = `${this.sanitize(fromId)}_`;
8923
9101
  const toPrefix = `${this.sanitize(toId)}_`;
8924
9102
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
8925
9103
  for (const file of files) {
8926
- const sourcePath = path10.join(dir, file);
8927
- const targetPath = path10.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
9104
+ const sourcePath = path11.join(dir, file);
9105
+ const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
8928
9106
  const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
8929
9107
  const rewritten = sourceLines.map((line) => {
8930
9108
  try {
@@ -8958,13 +9136,13 @@ var ChatHistoryWriter = class {
8958
9136
  const sessionId = String(historySessionId || "").trim();
8959
9137
  if (!sessionId) return;
8960
9138
  try {
8961
- const dir = path10.join(HISTORY_DIR, this.sanitize(agentType));
9139
+ const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
8962
9140
  if (!fs3.existsSync(dir)) return;
8963
9141
  const prefix = `${this.sanitize(sessionId)}_`;
8964
9142
  const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
8965
9143
  const seen = /* @__PURE__ */ new Set();
8966
9144
  for (const file of files) {
8967
- const filePath = path10.join(dir, file);
9145
+ const filePath = path11.join(dir, file);
8968
9146
  const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
8969
9147
  const next = [];
8970
9148
  for (const line of lines) {
@@ -9018,11 +9196,11 @@ var ChatHistoryWriter = class {
9018
9196
  const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
9019
9197
  const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
9020
9198
  for (const dir of agentDirs) {
9021
- const dirPath = path10.join(HISTORY_DIR, dir.name);
9199
+ const dirPath = path11.join(HISTORY_DIR, dir.name);
9022
9200
  const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
9023
9201
  let removedAny = false;
9024
9202
  for (const file of files) {
9025
- const filePath = path10.join(dirPath, file);
9203
+ const filePath = path11.join(dirPath, file);
9026
9204
  const stat2 = fs3.statSync(filePath);
9027
9205
  if (stat2.mtimeMs < cutoff) {
9028
9206
  fs3.unlinkSync(filePath);
@@ -9072,13 +9250,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
9072
9250
  function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
9073
9251
  try {
9074
9252
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9075
- const dir = path10.join(HISTORY_DIR, sanitized);
9253
+ const dir = path11.join(HISTORY_DIR, sanitized);
9076
9254
  if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
9077
9255
  const files = listHistoryFiles(dir, historySessionId);
9078
9256
  const allMessages = [];
9079
9257
  const seen = /* @__PURE__ */ new Set();
9080
9258
  for (const file of files) {
9081
- const filePath = path10.join(dir, file);
9259
+ const filePath = path11.join(dir, file);
9082
9260
  const content = fs3.readFileSync(filePath, "utf-8");
9083
9261
  const lines = content.trim().split("\n").filter(Boolean);
9084
9262
  for (let i = 0; i < lines.length; i++) {
@@ -9102,7 +9280,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
9102
9280
  function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9103
9281
  try {
9104
9282
  const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
9105
- const dir = path10.join(HISTORY_DIR, sanitized);
9283
+ const dir = path11.join(HISTORY_DIR, sanitized);
9106
9284
  if (!fs3.existsSync(dir)) {
9107
9285
  savedHistorySessionCache.delete(sanitized);
9108
9286
  return { sessions: [], hasMore: false };
@@ -9163,11 +9341,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
9163
9341
  }
9164
9342
  function readExistingSessionStartRecord(agentType, historySessionId) {
9165
9343
  try {
9166
- const dir = path10.join(HISTORY_DIR, agentType);
9344
+ const dir = path11.join(HISTORY_DIR, agentType);
9167
9345
  if (!fs3.existsSync(dir)) return null;
9168
9346
  const files = listHistoryFiles(dir, historySessionId).sort();
9169
9347
  for (const file of files) {
9170
- const lines = fs3.readFileSync(path10.join(dir, file), "utf-8").split("\n").filter(Boolean);
9348
+ const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
9171
9349
  for (const line of lines) {
9172
9350
  try {
9173
9351
  const parsed = JSON.parse(line);
@@ -9187,16 +9365,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
9187
9365
  function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
9188
9366
  if (records.length === 0) return false;
9189
9367
  try {
9190
- const dir = path10.join(HISTORY_DIR, agentType);
9368
+ const dir = path11.join(HISTORY_DIR, agentType);
9191
9369
  fs3.mkdirSync(dir, { recursive: true });
9192
9370
  const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
9193
9371
  for (const file of fs3.readdirSync(dir)) {
9194
9372
  if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
9195
- fs3.unlinkSync(path10.join(dir, file));
9373
+ fs3.unlinkSync(path11.join(dir, file));
9196
9374
  }
9197
9375
  }
9198
9376
  const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
9199
- const filePath = path10.join(dir, `${prefix}${targetDate}.jsonl`);
9377
+ const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
9200
9378
  fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
9201
9379
  `, "utf-8");
9202
9380
  invalidatePersistedSavedHistoryIndex(agentType, dir);
@@ -11191,6 +11369,14 @@ function getActiveChatOptions(profile) {
11191
11369
  if (profile === "full") return {};
11192
11370
  return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
11193
11371
  }
11372
+ function resolveSessionStatus(activeChat, providerStatus) {
11373
+ const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
11374
+ const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
11375
+ if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
11376
+ if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
11377
+ if (topLevelStatus !== "idle") return topLevelStatus;
11378
+ return chatStatus;
11379
+ }
11194
11380
  function shouldIncludeSessionControls(profile) {
11195
11381
  return profile !== "live";
11196
11382
  }
@@ -11269,9 +11455,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11269
11455
  providerName: state.name,
11270
11456
  kind: "workspace",
11271
11457
  transport: "cdp-page",
11272
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11273
- activeModal: activeChat?.activeModal || null
11274
- }),
11458
+ status: resolveSessionStatus(activeChat, state.status),
11275
11459
  title,
11276
11460
  workspace,
11277
11461
  ...git && { git },
@@ -11306,9 +11490,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11306
11490
  providerSessionId: ext.providerSessionId,
11307
11491
  kind: "agent",
11308
11492
  transport: "cdp-webview",
11309
- status: normalizeManagedStatus(activeChat?.status || ext.status, {
11310
- activeModal: activeChat?.activeModal || null
11311
- }),
11493
+ status: resolveSessionStatus(activeChat, ext.status),
11312
11494
  title: activeChat?.title || ext.name,
11313
11495
  workspace,
11314
11496
  ...git && { git },
@@ -11358,9 +11540,7 @@ function buildCliSession(state, options) {
11358
11540
  providerSessionId: state.providerSessionId,
11359
11541
  kind: "agent",
11360
11542
  transport: "pty",
11361
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11362
- activeModal: activeChat?.activeModal || null
11363
- }),
11543
+ status: resolveSessionStatus(activeChat, state.status),
11364
11544
  title: activeChat?.title || state.name,
11365
11545
  workspace,
11366
11546
  ...git && { git },
@@ -11408,9 +11588,7 @@ function buildAcpSession(state, options) {
11408
11588
  providerName: state.name,
11409
11589
  kind: "agent",
11410
11590
  transport: "acp",
11411
- status: normalizeManagedStatus(activeChat?.status || state.status, {
11412
- activeModal: activeChat?.activeModal || null
11413
- }),
11591
+ status: resolveSessionStatus(activeChat, state.status),
11414
11592
  title: activeChat?.title || state.name,
11415
11593
  workspace,
11416
11594
  ...git && { git },
@@ -11533,7 +11711,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
11533
11711
  // src/commands/chat-commands.ts
11534
11712
  var fs4 = __toESM(require("fs"));
11535
11713
  var os6 = __toESM(require("os"));
11536
- var path11 = __toESM(require("path"));
11714
+ var path12 = __toESM(require("path"));
11537
11715
  var import_node_crypto = require("crypto");
11538
11716
 
11539
11717
  // src/providers/provider-input-support.ts
@@ -11736,6 +11914,7 @@ function buildSessionModalDeliverySignature(payload) {
11736
11914
  // src/commands/chat-commands.ts
11737
11915
  var RECENT_SEND_WINDOW_MS = 1200;
11738
11916
  var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
11917
+ var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
11739
11918
  var recentSendByTarget = /* @__PURE__ */ new Map();
11740
11919
  function getCurrentProviderType(h, fallback = "") {
11741
11920
  return h.currentSession?.providerType || h.currentProviderType || fallback;
@@ -11788,6 +11967,16 @@ function buildSendInputSignature(input) {
11788
11967
  function getSendChatInputEnvelope(args) {
11789
11968
  return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
11790
11969
  }
11970
+ function sleep(ms) {
11971
+ return new Promise((resolve16) => setTimeout(resolve16, ms));
11972
+ }
11973
+ async function waitOnceForFreshHermesCliStart(adapter, log) {
11974
+ if (adapter.cliType !== "hermes-cli") return;
11975
+ const status = typeof adapter.getStatus === "function" ? adapter.getStatus()?.status : void 0;
11976
+ if (status !== "starting") return;
11977
+ log(`Hermes CLI is still starting; waiting ${HERMES_CLI_STARTING_SEND_SETTLE_MS}ms before first send`);
11978
+ await sleep(HERMES_CLI_STARTING_SEND_SETTLE_MS);
11979
+ }
11791
11980
  function getHistorySessionId(h, args) {
11792
11981
  const explicit = typeof args?.historySessionId === "string" ? args.historySessionId.trim() : "";
11793
11982
  if (explicit) return explicit;
@@ -11896,6 +12085,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
11896
12085
  return raw;
11897
12086
  }
11898
12087
  }
12088
+ function isGeneratingLikeStatus(status) {
12089
+ return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
12090
+ }
12091
+ function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12092
+ if (!isGeneratingLikeStatus(parsedStatus)) return false;
12093
+ if (hasNonEmptyModalButtons(activeModal)) return false;
12094
+ const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
12095
+ if (adapterRawStatus !== "idle") return false;
12096
+ if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
12097
+ return true;
12098
+ }
12099
+ function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
12100
+ if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
12101
+ return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
12102
+ }
12103
+ function finalizeStreamingMessagesWhenIdle(messages, status) {
12104
+ if (status !== "idle") return messages;
12105
+ return messages.map((message) => {
12106
+ const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
12107
+ const hasStreamingMeta = meta?.streaming === true;
12108
+ if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
12109
+ return {
12110
+ ...message,
12111
+ ...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
12112
+ ...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
12113
+ };
12114
+ });
12115
+ }
11899
12116
  function buildReadChatCommandResult(payload, args) {
11900
12117
  let validatedPayload;
11901
12118
  const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
@@ -12044,7 +12261,7 @@ function buildDebugBundleText(bundle) {
12044
12261
  }
12045
12262
  function getChatDebugBundleDir() {
12046
12263
  const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
12047
- return override || path11.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12264
+ return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
12048
12265
  }
12049
12266
  function safeBundleIdSegment(value, fallback) {
12050
12267
  const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
@@ -12060,6 +12277,14 @@ function buildChatDebugBundleSummary(bundle) {
12060
12277
  const readChat = bundle.readChat && typeof bundle.readChat === "object" ? bundle.readChat : {};
12061
12278
  const cli = bundle.cli && typeof bundle.cli === "object" ? bundle.cli : null;
12062
12279
  const frontend = bundle.frontend && typeof bundle.frontend === "object" ? bundle.frontend : null;
12280
+ const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === "object" ? readChat.debugReadChat : {};
12281
+ const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === "object" ? cli.parsedStatus : null;
12282
+ const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : void 0;
12283
+ const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : void 0;
12284
+ const cliPartialResponse = typeof cli?.partialResponse === "string" ? cli.partialResponse : "";
12285
+ const readChatStatus = typeof readChat.status === "string" ? readChat.status : "";
12286
+ const cliStatus = typeof cli?.status === "string" ? cli.status : "";
12287
+ const cliParsedStatus = typeof parsedStatus?.status === "string" ? parsedStatus.status : "";
12063
12288
  return {
12064
12289
  createdAt: bundle.createdAt,
12065
12290
  targetSessionId: target.targetSessionId,
@@ -12068,8 +12293,22 @@ function buildChatDebugBundleSummary(bundle) {
12068
12293
  readChatSuccess: readChat.success,
12069
12294
  readChatStatus: readChat.status,
12070
12295
  readChatTotalMessages: readChat.totalMessages,
12296
+ readChatReturnedMessages,
12071
12297
  cliStatus: cli?.status,
12298
+ cliParsedStatus: cliParsedStatus || void 0,
12072
12299
  cliMessageCount: cli?.messageCount,
12300
+ cliParsedMessageCount,
12301
+ cliPartialResponseChars: cliPartialResponse.length,
12302
+ parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
12303
+ parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
12304
+ readChatDebug: Object.keys(debugReadChat).length ? {
12305
+ adapterStatus: debugReadChat.adapterStatus,
12306
+ parsedStatus: debugReadChat.parsedStatus,
12307
+ returnedStatus: debugReadChat.returnedStatus,
12308
+ parsedMsgCount: debugReadChat.parsedMsgCount,
12309
+ returnedMsgCount: debugReadChat.returnedMsgCount,
12310
+ shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages
12311
+ } : void 0,
12073
12312
  hasFrontendSnapshot: !!frontend
12074
12313
  };
12075
12314
  }
@@ -12077,7 +12316,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
12077
12316
  const bundleId = createChatDebugBundleId(targetSessionId);
12078
12317
  const dir = getChatDebugBundleDir();
12079
12318
  fs4.mkdirSync(dir, { recursive: true });
12080
- const savedPath = path11.join(dir, `${bundleId}.json`);
12319
+ const savedPath = path12.join(dir, `${bundleId}.json`);
12081
12320
  const json = `${JSON.stringify(bundle, null, 2)}
12082
12321
  `;
12083
12322
  fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
@@ -12307,7 +12546,7 @@ async function handleChatHistory(h, args) {
12307
12546
  }
12308
12547
  }
12309
12548
  async function handleReadChat(h, args) {
12310
- const provider = h.getProvider(args?.agentType);
12549
+ const provider = h.getProvider(args?.agentType || args?.providerType);
12311
12550
  const transport = getTargetTransport(h, provider);
12312
12551
  const historySessionId = getHistorySessionId(h, args);
12313
12552
  const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
@@ -12334,10 +12573,13 @@ async function handleReadChat(h, args) {
12334
12573
  const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
12335
12574
  const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
12336
12575
  const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
12337
- const returnedStatus = parsedRecord.status || "idle";
12338
- LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length}`);
12576
+ const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
12577
+ const runtimeMessageMerger = getTargetInstance(h, args);
12578
+ const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
12579
+ const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
12580
+ LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length} returnedMsgCount=${returnedMessages.length}`);
12339
12581
  return buildReadChatCommandResult({
12340
- messages: parsedRecord.messages,
12582
+ messages: returnedMessages,
12341
12583
  status: returnedStatus,
12342
12584
  activeModal,
12343
12585
  debugReadChat: {
@@ -12348,7 +12590,7 @@ async function handleReadChat(h, args) {
12348
12590
  returnedStatus: String(returnedStatus || ""),
12349
12591
  shouldPreferAdapterMessages: false,
12350
12592
  parsedMsgCount: parsedRecord.messages.length,
12351
- returnedMsgCount: parsedRecord.messages.length
12593
+ returnedMsgCount: returnedMessages.length
12352
12594
  },
12353
12595
  ...title ? { title } : {},
12354
12596
  ...providerSessionId ? { providerSessionId } : {},
@@ -12594,6 +12836,7 @@ async function handleSendChat(h, args) {
12594
12836
  try {
12595
12837
  assertTextOnlyInput(provider, input);
12596
12838
  if (!text) return { success: false, error: "text required for PTY send" };
12839
+ await waitOnceForFreshHermesCliStart(adapter, _log);
12597
12840
  await adapter.sendMessage(text);
12598
12841
  return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
12599
12842
  } catch (e) {
@@ -13093,9 +13336,17 @@ async function handleResolveAction(h, args) {
13093
13336
  const targetState = targetInstance?.getState?.();
13094
13337
  const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons) && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? targetState.activeChat.activeModal : null;
13095
13338
  const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons) && status.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? status.activeModal : null;
13096
- const effectiveModal = statusModal || surfacedModal;
13097
- const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" ? "waiting_approval" : status?.status;
13098
- LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
13339
+ const parsedStatus = !statusModal && !surfacedModal && typeof adapter.getScriptParsedStatus === "function" ? (() => {
13340
+ try {
13341
+ return parseMaybeJson(adapter.getScriptParsedStatus());
13342
+ } catch {
13343
+ return null;
13344
+ }
13345
+ })() : null;
13346
+ const parsedModal = parsedStatus?.status === "waiting_approval" && parsedStatus?.activeModal && Array.isArray(parsedStatus.activeModal.buttons) && parsedStatus.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? parsedStatus.activeModal : null;
13347
+ const effectiveModal = statusModal || surfacedModal || parsedModal;
13348
+ const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" || parsedStatus?.status === "waiting_approval" ? "waiting_approval" : status?.status;
13349
+ LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} parsedModal=${parsedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
13099
13350
  if (!effectiveModal) {
13100
13351
  return { success: false, error: "Not in approval state" };
13101
13352
  }
@@ -13221,7 +13472,7 @@ async function handleResolveAction(h, args) {
13221
13472
 
13222
13473
  // src/commands/cdp-commands.ts
13223
13474
  var fs5 = __toESM(require("fs"));
13224
- var path12 = __toESM(require("path"));
13475
+ var path13 = __toESM(require("path"));
13225
13476
  var os7 = __toESM(require("os"));
13226
13477
  var KEY_TO_VK = {
13227
13478
  Backspace: 8,
@@ -13478,25 +13729,25 @@ function resolveSafePath(requestedPath) {
13478
13729
  const inputPath = rawPath || ".";
13479
13730
  const home = os7.homedir();
13480
13731
  if (inputPath.startsWith("~")) {
13481
- return path12.resolve(path12.join(home, inputPath.slice(1)));
13732
+ return path13.resolve(path13.join(home, inputPath.slice(1)));
13482
13733
  }
13483
13734
  if (process.platform === "win32") {
13484
13735
  const normalized = normalizeWindowsRequestedPath(inputPath);
13485
- if (path12.win32.isAbsolute(normalized)) {
13486
- return path12.win32.normalize(normalized);
13736
+ if (path13.win32.isAbsolute(normalized)) {
13737
+ return path13.win32.normalize(normalized);
13487
13738
  }
13488
- return path12.win32.resolve(normalized);
13739
+ return path13.win32.resolve(normalized);
13489
13740
  }
13490
- if (path12.isAbsolute(inputPath)) {
13491
- return path12.normalize(inputPath);
13741
+ if (path13.isAbsolute(inputPath)) {
13742
+ return path13.normalize(inputPath);
13492
13743
  }
13493
- return path12.resolve(inputPath);
13744
+ return path13.resolve(inputPath);
13494
13745
  }
13495
13746
  function listDirectoryEntriesSafe(dirPath) {
13496
13747
  const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
13497
13748
  const files = [];
13498
13749
  for (const entry of entries) {
13499
- const entryPath = path12.join(dirPath, entry.name);
13750
+ const entryPath = path13.join(dirPath, entry.name);
13500
13751
  try {
13501
13752
  if (entry.isDirectory()) {
13502
13753
  files.push({ name: entry.name, type: "directory" });
@@ -13550,7 +13801,7 @@ async function handleFileRead(h, args) {
13550
13801
  async function handleFileWrite(h, args) {
13551
13802
  try {
13552
13803
  const filePath = resolveSafePath(args?.path);
13553
- fs5.mkdirSync(path12.dirname(filePath), { recursive: true });
13804
+ fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
13554
13805
  fs5.writeFileSync(filePath, args?.content || "", "utf-8");
13555
13806
  return { success: true, path: filePath };
13556
13807
  } catch (e) {
@@ -14334,9 +14585,11 @@ var DaemonCommandHandler = class {
14334
14585
  }
14335
14586
  const sessionLookupFailed = !!targetSessionId && !session;
14336
14587
  const managerKey = this.extractIdeType(args, sessionLookupFailed);
14337
- let providerType;
14588
+ let providerType = args?.agentType || args?.providerType;
14338
14589
  if (!sessionLookupFailed) {
14339
- providerType = session?.providerType || args?.agentType || args?.providerType || this.inferProviderType(managerKey);
14590
+ providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
14591
+ } else if (!providerType) {
14592
+ providerType = this.inferProviderType(managerKey);
14340
14593
  }
14341
14594
  return { session, managerKey, providerType, sessionLookupFailed };
14342
14595
  }
@@ -14416,7 +14669,8 @@ var DaemonCommandHandler = class {
14416
14669
  "pty_resize",
14417
14670
  "invoke_provider_script"
14418
14671
  ]);
14419
- if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
14672
+ const allowsInactiveReadChatFallback = cmd === "read_chat" && !!this._currentRoute.providerType && (typeof args?.providerSessionId === "string" && args.providerSessionId.trim().length > 0 || typeof args?.historySessionId === "string" && args.historySessionId.trim().length > 0);
14673
+ if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
14420
14674
  const result2 = {
14421
14675
  success: false,
14422
14676
  error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
@@ -14669,7 +14923,7 @@ var DaemonCommandHandler = class {
14669
14923
 
14670
14924
  // src/commands/cli-manager.ts
14671
14925
  var os13 = __toESM(require("os"));
14672
- var path16 = __toESM(require("path"));
14926
+ var path17 = __toESM(require("path"));
14673
14927
  var crypto4 = __toESM(require("crypto"));
14674
14928
  var import_fs6 = require("fs");
14675
14929
  var import_child_process6 = require("child_process");
@@ -14679,7 +14933,7 @@ init_config();
14679
14933
 
14680
14934
  // src/providers/cli-provider-instance.ts
14681
14935
  var os12 = __toESM(require("os"));
14682
- var path15 = __toESM(require("path"));
14936
+ var path16 = __toESM(require("path"));
14683
14937
  var crypto3 = __toESM(require("crypto"));
14684
14938
  var fs6 = __toESM(require("fs"));
14685
14939
  var import_node_module = require("module");
@@ -14738,7 +14992,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
14738
14992
  var CachedDatabaseSync = null;
14739
14993
  function getDatabaseSync() {
14740
14994
  if (CachedDatabaseSync) return CachedDatabaseSync;
14741
- const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path15.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14995
+ const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
14742
14996
  const sqliteModule = requireFn(`node:${"sqlite"}`);
14743
14997
  CachedDatabaseSync = sqliteModule.DatabaseSync;
14744
14998
  if (!CachedDatabaseSync) {
@@ -14791,7 +15045,7 @@ var CliProviderInstance = class {
14791
15045
  this.providerSessionId = options?.providerSessionId;
14792
15046
  this.launchMode = options?.launchMode || "new";
14793
15047
  this.onProviderSessionResolved = options?.onProviderSessionResolved;
14794
- this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
15048
+ this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
14795
15049
  this.monitor = new StatusMonitor();
14796
15050
  this.historyWriter = new ChatHistoryWriter();
14797
15051
  }
@@ -15268,7 +15522,19 @@ var CliProviderInstance = class {
15268
15522
  }
15269
15523
  }
15270
15524
  pushEvent(event) {
15271
- this.events.push(event);
15525
+ const enrichedEvent = {
15526
+ ...event,
15527
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
15528
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
15529
+ providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
15530
+ workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
15531
+ providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
15532
+ };
15533
+ if (this.context?.emitProviderEvent) {
15534
+ this.context.emitProviderEvent(enrichedEvent);
15535
+ return;
15536
+ }
15537
+ this.events.push(enrichedEvent);
15272
15538
  }
15273
15539
  flushEvents() {
15274
15540
  const events = [...this.events];
@@ -15475,12 +15741,29 @@ ${effect.notification.body || ""}`.trim();
15475
15741
  );
15476
15742
  }
15477
15743
  }
15744
+ mergeRuntimeChatMessages(parsedMessages) {
15745
+ return this.mergeConversationMessages(parsedMessages);
15746
+ }
15478
15747
  mergeConversationMessages(parsedMessages) {
15479
15748
  if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
15480
- return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
15481
- const aTime = a.message.receivedAt || a.message.timestamp || 0;
15482
- const bTime = b.message.receivedAt || b.message.timestamp || 0;
15483
- if (aTime !== bTime) return aTime - bTime;
15749
+ const parsedEntries = parsedMessages.map((message, index) => ({
15750
+ message,
15751
+ index,
15752
+ source: "parsed"
15753
+ }));
15754
+ const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
15755
+ message: entry.message,
15756
+ index: parsedMessages.length + index,
15757
+ source: "runtime"
15758
+ }));
15759
+ const getTime = (message) => {
15760
+ const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
15761
+ return Number.isFinite(value) && value > 0 ? value : 0;
15762
+ };
15763
+ return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
15764
+ const aTime = getTime(a.message);
15765
+ const bTime = getTime(b.message);
15766
+ if (aTime && bTime && aTime !== bTime) return aTime - bTime;
15484
15767
  return a.index - b.index;
15485
15768
  }).map((entry) => entry.message));
15486
15769
  }
@@ -16804,11 +17087,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16804
17087
  // src/commands/cli-manager.ts
16805
17088
  function isExplicitCommand(command) {
16806
17089
  const trimmed = command.trim();
16807
- return path16.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17090
+ return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16808
17091
  }
16809
17092
  function expandExecutable(command) {
16810
17093
  const trimmed = command.trim();
16811
- return trimmed.startsWith("~") ? path16.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17094
+ return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16812
17095
  }
16813
17096
  function commandExists(command) {
16814
17097
  const trimmed = command.trim();
@@ -16832,6 +17115,35 @@ function colorize(color, text) {
16832
17115
  const fn = chalkApi?.[color];
16833
17116
  return typeof fn === "function" ? fn(text) : text;
16834
17117
  }
17118
+ var COORDINATOR_DELEGATED_ENV_UNSETS = {
17119
+ ADHDEV_INLINE_MESH: "",
17120
+ ADHDEV_MCP_TRANSPORT: "",
17121
+ ADHDEV_MESH_ID: "",
17122
+ HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
17123
+ };
17124
+ function hasCliArg(args, flag) {
17125
+ return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
17126
+ }
17127
+ function ensureEmptyDelegatedMcpConfig(workspace) {
17128
+ const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
17129
+ (0, import_fs6.mkdirSync)(baseDir, { recursive: true });
17130
+ const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
17131
+ const filePath = path17.join(baseDir, `${workspaceHash}.json`);
17132
+ (0, import_fs6.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
17133
+ return filePath;
17134
+ }
17135
+ function buildCoordinatorDelegatedCliLaunchOptions(input) {
17136
+ const cliType = String(input.cliType || "").trim();
17137
+ const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
17138
+ const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
17139
+ if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
17140
+ cliArgs.unshift("--ignore-user-config");
17141
+ }
17142
+ if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
17143
+ cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
17144
+ }
17145
+ return { cliArgs, env };
17146
+ }
16835
17147
  function isUuid(value) {
16836
17148
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
16837
17149
  }
@@ -17002,7 +17314,7 @@ var DaemonCliManager = class {
17002
17314
  attachExisting
17003
17315
  }) || void 0;
17004
17316
  }
17005
- createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
17317
+ createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
17006
17318
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17007
17319
  const provider = this.providerLoader.getMeta(normalizedType);
17008
17320
  if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
@@ -17016,7 +17328,7 @@ var DaemonCliManager = class {
17016
17328
  providerSessionId,
17017
17329
  attachExisting
17018
17330
  );
17019
- return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
17331
+ return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
17020
17332
  }
17021
17333
  throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
17022
17334
  }
@@ -17089,7 +17401,7 @@ var DaemonCliManager = class {
17089
17401
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
17090
17402
  const trimmed = (workingDir || "").trim();
17091
17403
  if (!trimmed) throw new Error("working directory required");
17092
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path16.resolve(trimmed);
17404
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
17093
17405
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17094
17406
  const rawProvider = this.providerLoader.getByAlias(cliType);
17095
17407
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17219,6 +17531,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
17219
17531
  {
17220
17532
  providerSessionId: sessionBinding.providerSessionId,
17221
17533
  launchMode: sessionBinding.launchMode,
17534
+ extraEnv: options?.extraEnv,
17222
17535
  onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
17223
17536
  this.persistRecentActivity({
17224
17537
  kind: "cli",
@@ -17239,7 +17552,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
17239
17552
  resolvedCliArgs,
17240
17553
  key,
17241
17554
  sessionBinding.providerSessionId,
17242
- false
17555
+ false,
17556
+ options?.extraEnv
17243
17557
  );
17244
17558
  try {
17245
17559
  await adapter.spawn();
@@ -17463,12 +17777,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
17463
17777
  const dir = resolved.path;
17464
17778
  const launchSource = resolved.source;
17465
17779
  if (!cliType) throw new Error("cliType required");
17780
+ const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
17781
+ const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
17782
+ cliType,
17783
+ workspace: dir,
17784
+ cliArgs: args?.cliArgs,
17785
+ env: args?.env
17786
+ }) : null;
17466
17787
  const started = await this.startSession(
17467
17788
  cliType,
17468
17789
  dir,
17469
- args?.cliArgs,
17790
+ delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
17470
17791
  args?.initialModel,
17471
- { resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
17792
+ {
17793
+ resumeSessionId: args?.resumeSessionId,
17794
+ settingsOverride,
17795
+ extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
17796
+ }
17472
17797
  );
17473
17798
  return {
17474
17799
  success: true,
@@ -17590,11 +17915,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
17590
17915
  var import_child_process7 = require("child_process");
17591
17916
  var net = __toESM(require("net"));
17592
17917
  var os15 = __toESM(require("os"));
17593
- var path18 = __toESM(require("path"));
17918
+ var path19 = __toESM(require("path"));
17594
17919
 
17595
17920
  // src/providers/provider-loader.ts
17596
17921
  var fs7 = __toESM(require("fs"));
17597
- var path17 = __toESM(require("path"));
17922
+ var path18 = __toESM(require("path"));
17598
17923
  var os14 = __toESM(require("os"));
17599
17924
  var chokidar = __toESM(require("chokidar"));
17600
17925
  init_logger();
@@ -17918,7 +18243,7 @@ var ProviderLoader = class _ProviderLoader {
17918
18243
  try {
17919
18244
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
17920
18245
  return ["ide", "extension", "cli", "acp"].some(
17921
- (category) => fs7.existsSync(path17.join(candidate, category))
18246
+ (category) => fs7.existsSync(path18.join(candidate, category))
17922
18247
  );
17923
18248
  } catch {
17924
18249
  return false;
@@ -17926,20 +18251,20 @@ var ProviderLoader = class _ProviderLoader {
17926
18251
  }
17927
18252
  static hasProviderRootMarker(candidate) {
17928
18253
  try {
17929
- return fs7.existsSync(path17.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18254
+ return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
17930
18255
  } catch {
17931
18256
  return false;
17932
18257
  }
17933
18258
  }
17934
18259
  detectDefaultUserDir() {
17935
- const fallback = path17.join(os14.homedir(), ".adhdev", "providers");
18260
+ const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
17936
18261
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
17937
18262
  const visited = /* @__PURE__ */ new Set();
17938
18263
  for (const start of this.probeStarts) {
17939
- let current = path17.resolve(start);
18264
+ let current = path18.resolve(start);
17940
18265
  while (!visited.has(current)) {
17941
18266
  visited.add(current);
17942
- const siblingCandidate = path17.join(path17.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18267
+ const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
17943
18268
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
17944
18269
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
17945
18270
  if (envOptIn || hasMarker) {
@@ -17961,7 +18286,7 @@ var ProviderLoader = class _ProviderLoader {
17961
18286
  return { path: siblingCandidate, source };
17962
18287
  }
17963
18288
  }
17964
- const parent = path17.dirname(current);
18289
+ const parent = path18.dirname(current);
17965
18290
  if (parent === current) break;
17966
18291
  current = parent;
17967
18292
  }
@@ -17971,11 +18296,11 @@ var ProviderLoader = class _ProviderLoader {
17971
18296
  constructor(options) {
17972
18297
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
17973
18298
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
17974
- this.defaultProvidersDir = path17.join(os14.homedir(), ".adhdev", "providers");
18299
+ this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
17975
18300
  const detected = this.detectDefaultUserDir();
17976
18301
  this.userDir = detected.path;
17977
18302
  this.userDirSource = detected.source;
17978
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18303
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
17979
18304
  this.disableUpstream = false;
17980
18305
  this.applySourceConfig({
17981
18306
  userDir: options?.userDir,
@@ -18034,7 +18359,7 @@ var ProviderLoader = class _ProviderLoader {
18034
18359
  this.userDir = detected.path;
18035
18360
  this.userDirSource = detected.source;
18036
18361
  }
18037
- this.upstreamDir = path17.join(this.defaultProvidersDir, ".upstream");
18362
+ this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
18038
18363
  this.disableUpstream = this.sourceMode === "no-upstream";
18039
18364
  if (this.explicitProviderDir) {
18040
18365
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -18048,7 +18373,7 @@ var ProviderLoader = class _ProviderLoader {
18048
18373
  * Canonical provider directory shape for a given root.
18049
18374
  */
18050
18375
  getProviderDir(root, category, type) {
18051
- return path17.join(root, category, type);
18376
+ return path18.join(root, category, type);
18052
18377
  }
18053
18378
  /**
18054
18379
  * Canonical user override directory for a provider.
@@ -18075,7 +18400,7 @@ var ProviderLoader = class _ProviderLoader {
18075
18400
  resolveProviderFile(type, ...segments) {
18076
18401
  const dir = this.findProviderDirInternal(type);
18077
18402
  if (!dir) return null;
18078
- return path17.join(dir, ...segments);
18403
+ return path18.join(dir, ...segments);
18079
18404
  }
18080
18405
  /**
18081
18406
  * Load all providers (3-tier priority)
@@ -18114,7 +18439,7 @@ var ProviderLoader = class _ProviderLoader {
18114
18439
  if (!fs7.existsSync(this.upstreamDir)) return false;
18115
18440
  try {
18116
18441
  return fs7.readdirSync(this.upstreamDir).some(
18117
- (d) => fs7.statSync(path17.join(this.upstreamDir, d)).isDirectory()
18442
+ (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
18118
18443
  );
18119
18444
  } catch {
18120
18445
  return false;
@@ -18611,8 +18936,8 @@ var ProviderLoader = class _ProviderLoader {
18611
18936
  resolved._resolvedScriptDir = entry.scriptDir;
18612
18937
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18613
18938
  if (providerDir) {
18614
- const fullDir = path17.join(providerDir, entry.scriptDir);
18615
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18939
+ const fullDir = path18.join(providerDir, entry.scriptDir);
18940
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18616
18941
  }
18617
18942
  matched = true;
18618
18943
  }
@@ -18627,8 +18952,8 @@ var ProviderLoader = class _ProviderLoader {
18627
18952
  resolved._resolvedScriptDir = base.defaultScriptDir;
18628
18953
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18629
18954
  if (providerDir) {
18630
- const fullDir = path17.join(providerDir, base.defaultScriptDir);
18631
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18955
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18956
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18632
18957
  }
18633
18958
  }
18634
18959
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18645,8 +18970,8 @@ var ProviderLoader = class _ProviderLoader {
18645
18970
  resolved._resolvedScriptDir = dirOverride;
18646
18971
  resolved._resolvedScriptsSource = `versions:${range}`;
18647
18972
  if (providerDir) {
18648
- const fullDir = path17.join(providerDir, dirOverride);
18649
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18973
+ const fullDir = path18.join(providerDir, dirOverride);
18974
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18650
18975
  }
18651
18976
  }
18652
18977
  } else if (override.scripts) {
@@ -18662,8 +18987,8 @@ var ProviderLoader = class _ProviderLoader {
18662
18987
  resolved._resolvedScriptDir = base.defaultScriptDir;
18663
18988
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18664
18989
  if (providerDir) {
18665
- const fullDir = path17.join(providerDir, base.defaultScriptDir);
18666
- resolved._resolvedScriptsPath = fs7.existsSync(path17.join(fullDir, "scripts.js")) ? path17.join(fullDir, "scripts.js") : fullDir;
18990
+ const fullDir = path18.join(providerDir, base.defaultScriptDir);
18991
+ resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
18667
18992
  }
18668
18993
  }
18669
18994
  }
@@ -18695,14 +19020,14 @@ var ProviderLoader = class _ProviderLoader {
18695
19020
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18696
19021
  return null;
18697
19022
  }
18698
- const dir = path17.join(providerDir, scriptDir);
19023
+ const dir = path18.join(providerDir, scriptDir);
18699
19024
  if (!fs7.existsSync(dir)) {
18700
19025
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18701
19026
  return null;
18702
19027
  }
18703
19028
  const cached = this.scriptsCache.get(dir);
18704
19029
  if (cached) return cached;
18705
- const scriptsJs = path17.join(dir, "scripts.js");
19030
+ const scriptsJs = path18.join(dir, "scripts.js");
18706
19031
  if (fs7.existsSync(scriptsJs)) {
18707
19032
  try {
18708
19033
  delete require.cache[require.resolve(scriptsJs)];
@@ -18744,7 +19069,7 @@ var ProviderLoader = class _ProviderLoader {
18744
19069
  return;
18745
19070
  }
18746
19071
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18747
- this.log(`File changed: ${path17.basename(filePath)}, reloading...`);
19072
+ this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
18748
19073
  this.reload();
18749
19074
  }
18750
19075
  };
@@ -18799,7 +19124,7 @@ var ProviderLoader = class _ProviderLoader {
18799
19124
  }
18800
19125
  const https = require("https");
18801
19126
  const { execSync: execSync7 } = require("child_process");
18802
- const metaPath = path17.join(this.upstreamDir, _ProviderLoader.META_FILE);
19127
+ const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
18803
19128
  let prevEtag = "";
18804
19129
  let prevTimestamp = 0;
18805
19130
  try {
@@ -18859,17 +19184,17 @@ var ProviderLoader = class _ProviderLoader {
18859
19184
  return { updated: false };
18860
19185
  }
18861
19186
  this.log("Downloading latest providers from GitHub...");
18862
- const tmpTar = path17.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
18863
- const tmpExtract = path17.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
19187
+ const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19188
+ const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
18864
19189
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
18865
19190
  fs7.mkdirSync(tmpExtract, { recursive: true });
18866
19191
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
18867
19192
  const extracted = fs7.readdirSync(tmpExtract);
18868
19193
  const rootDir = extracted.find(
18869
- (d) => fs7.statSync(path17.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19194
+ (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
18870
19195
  );
18871
19196
  if (!rootDir) throw new Error("Unexpected tarball structure");
18872
- const sourceDir = path17.join(tmpExtract, rootDir);
19197
+ const sourceDir = path18.join(tmpExtract, rootDir);
18873
19198
  const backupDir = this.upstreamDir + ".bak";
18874
19199
  if (fs7.existsSync(this.upstreamDir)) {
18875
19200
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -18944,8 +19269,8 @@ var ProviderLoader = class _ProviderLoader {
18944
19269
  copyDirRecursive(src, dest) {
18945
19270
  fs7.mkdirSync(dest, { recursive: true });
18946
19271
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
18947
- const srcPath = path17.join(src, entry.name);
18948
- const destPath = path17.join(dest, entry.name);
19272
+ const srcPath = path18.join(src, entry.name);
19273
+ const destPath = path18.join(dest, entry.name);
18949
19274
  if (entry.isDirectory()) {
18950
19275
  this.copyDirRecursive(srcPath, destPath);
18951
19276
  } else {
@@ -18956,7 +19281,7 @@ var ProviderLoader = class _ProviderLoader {
18956
19281
  /** .meta.json save */
18957
19282
  writeMeta(metaPath, etag, timestamp) {
18958
19283
  try {
18959
- fs7.mkdirSync(path17.dirname(metaPath), { recursive: true });
19284
+ fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
18960
19285
  fs7.writeFileSync(metaPath, JSON.stringify({
18961
19286
  etag,
18962
19287
  timestamp,
@@ -18973,7 +19298,7 @@ var ProviderLoader = class _ProviderLoader {
18973
19298
  const scan = (d) => {
18974
19299
  try {
18975
19300
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
18976
- if (entry.isDirectory()) scan(path17.join(d, entry.name));
19301
+ if (entry.isDirectory()) scan(path18.join(d, entry.name));
18977
19302
  else if (entry.name === "provider.json") count++;
18978
19303
  }
18979
19304
  } catch {
@@ -19201,17 +19526,17 @@ var ProviderLoader = class _ProviderLoader {
19201
19526
  for (const root of searchRoots) {
19202
19527
  if (!fs7.existsSync(root)) continue;
19203
19528
  const candidate = this.getProviderDir(root, cat, type);
19204
- if (fs7.existsSync(path17.join(candidate, "provider.json"))) return candidate;
19205
- const catDir = path17.join(root, cat);
19529
+ if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19530
+ const catDir = path18.join(root, cat);
19206
19531
  if (fs7.existsSync(catDir)) {
19207
19532
  try {
19208
19533
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19209
19534
  if (!entry.isDirectory()) continue;
19210
- const jsonPath = path17.join(catDir, entry.name, "provider.json");
19535
+ const jsonPath = path18.join(catDir, entry.name, "provider.json");
19211
19536
  if (fs7.existsSync(jsonPath)) {
19212
19537
  try {
19213
19538
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19214
- if (data.type === type) return path17.join(catDir, entry.name);
19539
+ if (data.type === type) return path18.join(catDir, entry.name);
19215
19540
  } catch {
19216
19541
  }
19217
19542
  }
@@ -19228,7 +19553,7 @@ var ProviderLoader = class _ProviderLoader {
19228
19553
  * (template substitution is NOT applied here — scripts.js handles that)
19229
19554
  */
19230
19555
  buildScriptWrappersFromDir(dir) {
19231
- const scriptsJs = path17.join(dir, "scripts.js");
19556
+ const scriptsJs = path18.join(dir, "scripts.js");
19232
19557
  if (fs7.existsSync(scriptsJs)) {
19233
19558
  try {
19234
19559
  delete require.cache[require.resolve(scriptsJs)];
@@ -19242,7 +19567,7 @@ var ProviderLoader = class _ProviderLoader {
19242
19567
  for (const file of fs7.readdirSync(dir)) {
19243
19568
  if (!file.endsWith(".js")) continue;
19244
19569
  const scriptName = toCamel(file.replace(".js", ""));
19245
- const filePath = path17.join(dir, file);
19570
+ const filePath = path18.join(dir, file);
19246
19571
  result[scriptName] = (...args) => {
19247
19572
  try {
19248
19573
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19302,7 +19627,7 @@ var ProviderLoader = class _ProviderLoader {
19302
19627
  }
19303
19628
  const hasJson = entries.some((e) => e.name === "provider.json");
19304
19629
  if (hasJson) {
19305
- const jsonPath = path17.join(d, "provider.json");
19630
+ const jsonPath = path18.join(d, "provider.json");
19306
19631
  try {
19307
19632
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19308
19633
  const mod = JSON.parse(raw);
@@ -19323,7 +19648,7 @@ var ProviderLoader = class _ProviderLoader {
19323
19648
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19324
19649
  } else {
19325
19650
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19326
- const scriptsPath = path17.join(d, "scripts.js");
19651
+ const scriptsPath = path18.join(d, "scripts.js");
19327
19652
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19328
19653
  try {
19329
19654
  delete require.cache[require.resolve(scriptsPath)];
@@ -19349,7 +19674,7 @@ var ProviderLoader = class _ProviderLoader {
19349
19674
  if (!entry.isDirectory()) continue;
19350
19675
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19351
19676
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19352
- scan(path17.join(d, entry.name));
19677
+ scan(path18.join(d, entry.name));
19353
19678
  }
19354
19679
  }
19355
19680
  };
@@ -19674,8 +19999,8 @@ function detectCurrentWorkspace(ideId) {
19674
19999
  const appNameMap = getMacAppIdentifiers();
19675
20000
  const appName = appNameMap[ideId];
19676
20001
  if (appName) {
19677
- const storagePath = path18.join(
19678
- process.env.APPDATA || path18.join(os15.homedir(), "AppData", "Roaming"),
20002
+ const storagePath = path19.join(
20003
+ process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
19679
20004
  appName,
19680
20005
  "storage.json"
19681
20006
  );
@@ -19864,9 +20189,9 @@ init_logger();
19864
20189
 
19865
20190
  // src/logging/command-log.ts
19866
20191
  var fs8 = __toESM(require("fs"));
19867
- var path19 = __toESM(require("path"));
20192
+ var path20 = __toESM(require("path"));
19868
20193
  var os16 = __toESM(require("os"));
19869
- var LOG_DIR2 = process.platform === "win32" ? path19.join(process.env.LOCALAPPDATA || process.env.APPDATA || path19.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path19.join(os16.homedir(), "Library", "Logs", "adhdev") : path19.join(os16.homedir(), ".local", "share", "adhdev", "logs");
20194
+ var LOG_DIR2 = process.platform === "win32" ? path20.join(process.env.LOCALAPPDATA || process.env.APPDATA || path20.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path20.join(os16.homedir(), "Library", "Logs", "adhdev") : path20.join(os16.homedir(), ".local", "share", "adhdev", "logs");
19870
20195
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
19871
20196
  var MAX_DAYS = 7;
19872
20197
  try {
@@ -19904,13 +20229,13 @@ function getDateStr2() {
19904
20229
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
19905
20230
  }
19906
20231
  var currentDate2 = getDateStr2();
19907
- var currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20232
+ var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19908
20233
  var writeCount2 = 0;
19909
20234
  function checkRotation() {
19910
20235
  const today = getDateStr2();
19911
20236
  if (today !== currentDate2) {
19912
20237
  currentDate2 = today;
19913
- currentFile = path19.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20238
+ currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
19914
20239
  cleanOldFiles();
19915
20240
  }
19916
20241
  }
@@ -19924,7 +20249,7 @@ function cleanOldFiles() {
19924
20249
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
19925
20250
  if (dateMatch && dateMatch[1] < cutoffStr) {
19926
20251
  try {
19927
- fs8.unlinkSync(path19.join(LOG_DIR2, file));
20252
+ fs8.unlinkSync(path20.join(LOG_DIR2, file));
19928
20253
  } catch {
19929
20254
  }
19930
20255
  }
@@ -20007,14 +20332,66 @@ function getRecentCommands(count = 50) {
20007
20332
  cleanOldFiles();
20008
20333
 
20009
20334
  // src/commands/router.ts
20335
+ var yaml = __toESM(require("js-yaml"));
20010
20336
  init_logger();
20011
20337
 
20012
20338
  // src/commands/mesh-coordinator.ts
20013
- var import_node_fs2 = require("fs");
20339
+ var import_node_child_process3 = require("child_process");
20340
+ var import_node_fs3 = require("fs");
20014
20341
  var import_node_module2 = require("module");
20342
+ var os17 = __toESM(require("os"));
20015
20343
  var import_node_path = require("path");
20016
20344
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
20017
20345
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20346
+ var HERMES_CLI_TYPE = "hermes-cli";
20347
+ var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
20348
+ function isHermesProvider(provider, cliType) {
20349
+ const type = cliType?.trim() || provider?.type?.trim() || "";
20350
+ return type === HERMES_CLI_TYPE;
20351
+ }
20352
+ function resolveHermesMeshCoordinatorSetup(options) {
20353
+ const mcpServer = resolveAdhdevMcpServerLaunch({
20354
+ meshId: options.meshId,
20355
+ nodeExecutable: options.nodeExecutable,
20356
+ adhdevMcpEntryPath: options.adhdevMcpEntryPath
20357
+ });
20358
+ if (!mcpServer) {
20359
+ return {
20360
+ kind: "unsupported",
20361
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20362
+ };
20363
+ }
20364
+ const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20365
+ if (!configPath.trim()) {
20366
+ return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20367
+ }
20368
+ return {
20369
+ kind: "auto_import",
20370
+ serverName: DEFAULT_SERVER_NAME,
20371
+ configPath,
20372
+ configFormat: "hermes_config_yaml",
20373
+ mcpServer
20374
+ };
20375
+ }
20376
+ function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
20377
+ return {
20378
+ kind: "manual",
20379
+ serverName: DEFAULT_SERVER_NAME,
20380
+ configFormat: "hermes_config_yaml",
20381
+ configPathCommand: HERMES_MCP_CONFIG_PATH,
20382
+ requiresRestart: true,
20383
+ 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.",
20384
+ template: renderMeshCoordinatorTemplate(
20385
+ "mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
20386
+ {
20387
+ meshId,
20388
+ workspace,
20389
+ serverName: DEFAULT_SERVER_NAME,
20390
+ adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
20391
+ }
20392
+ )
20393
+ };
20394
+ }
20018
20395
  function resolveMeshCoordinatorSetup(options) {
20019
20396
  const { provider, meshId, workspace } = options;
20020
20397
  const config = provider?.meshCoordinator;
@@ -20024,6 +20401,9 @@ function resolveMeshCoordinatorSetup(options) {
20024
20401
  reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
20025
20402
  };
20026
20403
  }
20404
+ if (isHermesProvider(provider, options.cliType)) {
20405
+ return resolveHermesMeshCoordinatorSetup(options);
20406
+ }
20027
20407
  const mcpConfig = config.mcpConfig;
20028
20408
  if (!mcpConfig || mcpConfig.mode === "none") {
20029
20409
  return {
@@ -20033,8 +20413,8 @@ function resolveMeshCoordinatorSetup(options) {
20033
20413
  }
20034
20414
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
20035
20415
  if (mcpConfig.mode === "auto_import") {
20036
- const path26 = mcpConfig.path?.trim();
20037
- if (!path26) {
20416
+ const path27 = mcpConfig.path?.trim();
20417
+ if (!path27) {
20038
20418
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
20039
20419
  }
20040
20420
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -20045,13 +20425,13 @@ function resolveMeshCoordinatorSetup(options) {
20045
20425
  if (!mcpServer) {
20046
20426
  return {
20047
20427
  kind: "unsupported",
20048
- reason: "Could not resolve the ADHDev MCP server entrypoint without relying on a PATH bin shim"
20428
+ reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20049
20429
  };
20050
20430
  }
20051
20431
  return {
20052
20432
  kind: "auto_import",
20053
20433
  serverName,
20054
- configPath: (0, import_node_path.join)(workspace, path26),
20434
+ configPath: resolveMcpConfigPath(path27, workspace),
20055
20435
  configFormat: mcpConfig.format,
20056
20436
  mcpServer
20057
20437
  };
@@ -20085,14 +20465,85 @@ function resolveMeshCoordinatorSetup(options) {
20085
20465
  function renderMeshCoordinatorTemplate(template, values) {
20086
20466
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
20087
20467
  }
20468
+ function resolveMcpConfigPath(configPath, workspace) {
20469
+ const trimmed = configPath.trim();
20470
+ if (trimmed === "~") return os17.homedir();
20471
+ if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
20472
+ if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
20473
+ return (0, import_node_path.join)(workspace, trimmed);
20474
+ }
20088
20475
  function resolveAdhdevMcpServerLaunch(options) {
20089
20476
  const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
20090
20477
  if (!entryPath) return null;
20478
+ const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
20479
+ if (!nodeExecutable) return null;
20091
20480
  return {
20092
- command: options.nodeExecutable?.trim() || process.execPath,
20093
- args: [entryPath, "--repo-mesh", options.meshId]
20481
+ command: nodeExecutable,
20482
+ args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
20094
20483
  };
20095
20484
  }
20485
+ function resolveMcpNodeExecutable(explicitExecutable) {
20486
+ const explicit = explicitExecutable?.trim();
20487
+ if (explicit) return explicit;
20488
+ const candidates = [];
20489
+ const addCandidate = (candidate) => {
20490
+ const trimmed = candidate?.trim();
20491
+ if (!trimmed) return;
20492
+ const normalized = normalizeExistingPath(trimmed) || trimmed;
20493
+ if (!candidates.includes(normalized)) candidates.push(normalized);
20494
+ };
20495
+ addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
20496
+ addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
20497
+ addCandidate(process.env.npm_node_execpath);
20498
+ addNodeCandidatesFromPath(process.env.PATH, addCandidate);
20499
+ addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
20500
+ addCandidate("/opt/homebrew/bin/node");
20501
+ addCandidate("/usr/local/bin/node");
20502
+ addCandidate("/usr/bin/node");
20503
+ addCandidate(process.execPath);
20504
+ for (const candidate of candidates) {
20505
+ if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
20506
+ }
20507
+ return null;
20508
+ }
20509
+ function addNodeCandidatesFromPath(pathValue, addCandidate) {
20510
+ for (const entry of (pathValue || "").split(":")) {
20511
+ const dir = entry.trim();
20512
+ if (!dir) continue;
20513
+ addCandidate((0, import_node_path.join)(dir, "node"));
20514
+ }
20515
+ }
20516
+ function addNodeCandidatesFromNvm(homeDir, addCandidate) {
20517
+ const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
20518
+ try {
20519
+ const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
20520
+ for (const versionDir of versionDirs) {
20521
+ addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
20522
+ }
20523
+ } catch {
20524
+ }
20525
+ }
20526
+ function compareNodeVersionNamesDescending(a, b) {
20527
+ const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
20528
+ const left = parse(a);
20529
+ const right = parse(b);
20530
+ for (let i = 0; i < Math.max(left.length, right.length); i++) {
20531
+ const diff = (right[i] || 0) - (left[i] || 0);
20532
+ if (diff !== 0) return diff;
20533
+ }
20534
+ return b.localeCompare(a);
20535
+ }
20536
+ function nodeRuntimeSupportsWebSocket(nodeExecutable) {
20537
+ try {
20538
+ (0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
20539
+ stdio: "ignore",
20540
+ timeout: 3e3
20541
+ });
20542
+ return true;
20543
+ } catch {
20544
+ return false;
20545
+ }
20546
+ }
20096
20547
  function resolveAdhdevMcpEntryPath(explicitPath) {
20097
20548
  const explicit = explicitPath?.trim();
20098
20549
  if (explicit) return normalizeExistingPath(explicit) || explicit;
@@ -20128,15 +20579,109 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
20128
20579
  }
20129
20580
  function normalizeExistingPath(filePath) {
20130
20581
  try {
20131
- if (!(0, import_node_fs2.existsSync)(filePath)) return null;
20132
- return import_node_fs2.realpathSync.native(filePath);
20582
+ if (!(0, import_node_fs3.existsSync)(filePath)) return null;
20583
+ return import_node_fs3.realpathSync.native(filePath);
20133
20584
  } catch {
20134
20585
  return null;
20135
20586
  }
20136
20587
  }
20137
20588
 
20589
+ // src/mesh/mesh-events.ts
20590
+ init_mesh_config();
20591
+ init_logger();
20592
+ function readNonEmptyString(value) {
20593
+ return typeof value === "string" && value.trim() ? value.trim() : "";
20594
+ }
20595
+ function formatCompletionMetadata(event) {
20596
+ const parts = [
20597
+ readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
20598
+ readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
20599
+ readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
20600
+ ].filter(Boolean);
20601
+ return parts.length > 0 ? ` (${parts.join("; ")})` : "";
20602
+ }
20603
+ function buildMeshSystemMessage(args) {
20604
+ const metadata = formatCompletionMetadata(args.metadataEvent);
20605
+ if (args.event === "agent:generating_completed") {
20606
+ return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path; use mesh_read_chat once to review its final progress, but do not poll repeatedly.`;
20607
+ }
20608
+ if (args.event === "agent:waiting_approval") {
20609
+ return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
20610
+ }
20611
+ return "";
20612
+ }
20613
+ function injectMeshSystemMessage(components, args) {
20614
+ const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
20615
+ const instState = inst.getState();
20616
+ if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
20617
+ if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
20618
+ return true;
20619
+ });
20620
+ if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
20621
+ const messageText = buildMeshSystemMessage({
20622
+ event: args.event,
20623
+ nodeLabel: args.nodeLabel,
20624
+ metadataEvent: args.metadataEvent
20625
+ });
20626
+ if (!messageText) return { success: false, error: "unsupported mesh event" };
20627
+ for (const coord of coordinatorInstances) {
20628
+ const coordState = coord.getState();
20629
+ LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
20630
+ coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
20631
+ }
20632
+ return { success: true, forwarded: coordinatorInstances.length };
20633
+ }
20634
+ function handleMeshForwardEvent(components, payload) {
20635
+ const eventName = readNonEmptyString(payload.event);
20636
+ if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
20637
+ return { success: false, error: "unsupported mesh event" };
20638
+ }
20639
+ const meshId = readNonEmptyString(payload.meshId);
20640
+ if (!meshId) return { success: false, error: "meshId required" };
20641
+ const nodeId = readNonEmptyString(payload.nodeId);
20642
+ const workspace = readNonEmptyString(payload.workspace);
20643
+ const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
20644
+ return injectMeshSystemMessage(components, {
20645
+ meshId,
20646
+ nodeLabel,
20647
+ event: eventName,
20648
+ metadataEvent: {
20649
+ targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
20650
+ providerType: readNonEmptyString(payload.providerType),
20651
+ providerSessionId: readNonEmptyString(payload.providerSessionId)
20652
+ }
20653
+ });
20654
+ }
20655
+ function setupMeshEventForwarding(components) {
20656
+ components.instanceManager.onEvent((event) => {
20657
+ if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
20658
+ const instanceId = readNonEmptyString(event.instanceId);
20659
+ if (!instanceId) return;
20660
+ const sourceInstance = components.instanceManager.getInstance(instanceId);
20661
+ if (!sourceInstance || sourceInstance.category !== "cli") return;
20662
+ const state = sourceInstance.getState();
20663
+ const workspace = readNonEmptyString(state.workspace);
20664
+ if (!workspace) return;
20665
+ const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
20666
+ const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
20667
+ const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
20668
+ const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
20669
+ if (!meshId) return;
20670
+ const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
20671
+ const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
20672
+ const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
20673
+ injectMeshSystemMessage(components, {
20674
+ meshId,
20675
+ sourceInstanceId: instanceId,
20676
+ nodeLabel,
20677
+ event: event.event,
20678
+ metadataEvent: event
20679
+ });
20680
+ });
20681
+ }
20682
+
20138
20683
  // src/status/snapshot.ts
20139
- var os17 = __toESM(require("os"));
20684
+ var os18 = __toESM(require("os"));
20140
20685
  init_config();
20141
20686
  init_terminal_screen();
20142
20687
  init_logger();
@@ -20192,8 +20737,8 @@ function buildAvailableProviders(providerLoader) {
20192
20737
  }
20193
20738
  function buildMachineInfo(profile = "full") {
20194
20739
  const base = {
20195
- hostname: os17.hostname(),
20196
- platform: os17.platform()
20740
+ hostname: os18.hostname(),
20741
+ platform: os18.platform()
20197
20742
  };
20198
20743
  if (profile === "live") {
20199
20744
  return base;
@@ -20202,23 +20747,23 @@ function buildMachineInfo(profile = "full") {
20202
20747
  const memSnap2 = getHostMemorySnapshot();
20203
20748
  return {
20204
20749
  ...base,
20205
- arch: os17.arch(),
20206
- cpus: os17.cpus().length,
20750
+ arch: os18.arch(),
20751
+ cpus: os18.cpus().length,
20207
20752
  totalMem: memSnap2.totalMem,
20208
- release: os17.release()
20753
+ release: os18.release()
20209
20754
  };
20210
20755
  }
20211
20756
  const memSnap = getHostMemorySnapshot();
20212
20757
  return {
20213
20758
  ...base,
20214
- arch: os17.arch(),
20215
- cpus: os17.cpus().length,
20759
+ arch: os18.arch(),
20760
+ cpus: os18.cpus().length,
20216
20761
  totalMem: memSnap.totalMem,
20217
20762
  freeMem: memSnap.freeMem,
20218
20763
  availableMem: memSnap.availableMem,
20219
- loadavg: os17.loadavg(),
20220
- uptime: os17.uptime(),
20221
- release: os17.release()
20764
+ loadavg: os18.loadavg(),
20765
+ uptime: os18.uptime(),
20766
+ release: os18.release()
20222
20767
  };
20223
20768
  }
20224
20769
  function parseMessageTime(value) {
@@ -20452,14 +20997,14 @@ function buildStatusSnapshot(options) {
20452
20997
  var import_child_process8 = require("child_process");
20453
20998
  var import_child_process9 = require("child_process");
20454
20999
  var fs9 = __toESM(require("fs"));
20455
- var os18 = __toESM(require("os"));
20456
- var path20 = __toESM(require("path"));
21000
+ var os19 = __toESM(require("os"));
21001
+ var path21 = __toESM(require("path"));
20457
21002
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20458
21003
  function getUpgradeLogPath() {
20459
- const home = os18.homedir();
20460
- const dir = path20.join(home, ".adhdev");
21004
+ const home = os19.homedir();
21005
+ const dir = path21.join(home, ".adhdev");
20461
21006
  fs9.mkdirSync(dir, { recursive: true });
20462
- return path20.join(dir, "daemon-upgrade.log");
21007
+ return path21.join(dir, "daemon-upgrade.log");
20463
21008
  }
20464
21009
  function appendUpgradeLog(message) {
20465
21010
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20470,14 +21015,14 @@ function appendUpgradeLog(message) {
20470
21015
  }
20471
21016
  }
20472
21017
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20473
- const binDir = path20.dirname(nodeExecutable);
21018
+ const binDir = path21.dirname(nodeExecutable);
20474
21019
  if (platform10 === "win32") {
20475
- const npmCliPath = path20.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
21020
+ const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20476
21021
  if (fs9.existsSync(npmCliPath)) {
20477
21022
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20478
21023
  }
20479
21024
  for (const candidate of ["npm.exe", "npm"]) {
20480
- const candidatePath = path20.join(binDir, candidate);
21025
+ const candidatePath = path21.join(binDir, candidate);
20481
21026
  if (fs9.existsSync(candidatePath)) {
20482
21027
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20483
21028
  }
@@ -20485,7 +21030,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20485
21030
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20486
21031
  }
20487
21032
  for (const candidate of ["npm"]) {
20488
- const candidatePath = path20.join(binDir, candidate);
21033
+ const candidatePath = path21.join(binDir, candidate);
20489
21034
  if (fs9.existsSync(candidatePath)) {
20490
21035
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20491
21036
  }
@@ -20502,13 +21047,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20502
21047
  let currentDir = resolvedPath;
20503
21048
  try {
20504
21049
  if (fs9.statSync(resolvedPath).isFile()) {
20505
- currentDir = path20.dirname(resolvedPath);
21050
+ currentDir = path21.dirname(resolvedPath);
20506
21051
  }
20507
21052
  } catch {
20508
- currentDir = path20.dirname(resolvedPath);
21053
+ currentDir = path21.dirname(resolvedPath);
20509
21054
  }
20510
21055
  while (true) {
20511
- const packageJsonPath = path20.join(currentDir, "package.json");
21056
+ const packageJsonPath = path21.join(currentDir, "package.json");
20512
21057
  try {
20513
21058
  if (fs9.existsSync(packageJsonPath)) {
20514
21059
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20519,7 +21064,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20519
21064
  }
20520
21065
  } catch {
20521
21066
  }
20522
- const parentDir = path20.dirname(currentDir);
21067
+ const parentDir = path21.dirname(currentDir);
20523
21068
  if (parentDir === currentDir) {
20524
21069
  return null;
20525
21070
  }
@@ -20527,13 +21072,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20527
21072
  }
20528
21073
  }
20529
21074
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20530
- const nodeModulesDir = packageName.startsWith("@") ? path20.dirname(path20.dirname(packageRoot)) : path20.dirname(packageRoot);
20531
- if (path20.basename(nodeModulesDir) !== "node_modules") {
21075
+ const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
21076
+ if (path21.basename(nodeModulesDir) !== "node_modules") {
20532
21077
  return null;
20533
21078
  }
20534
- const maybeLibDir = path20.dirname(nodeModulesDir);
20535
- if (path20.basename(maybeLibDir) === "lib") {
20536
- return path20.dirname(maybeLibDir);
21079
+ const maybeLibDir = path21.dirname(nodeModulesDir);
21080
+ if (path21.basename(maybeLibDir) === "lib") {
21081
+ return path21.dirname(maybeLibDir);
20537
21082
  }
20538
21083
  return maybeLibDir;
20539
21084
  }
@@ -20648,7 +21193,7 @@ async function waitForPidExit(pid, timeoutMs) {
20648
21193
  }
20649
21194
  }
20650
21195
  function stopSessionHostProcesses(appName) {
20651
- const pidFile = path20.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
21196
+ const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
20652
21197
  try {
20653
21198
  if (fs9.existsSync(pidFile)) {
20654
21199
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -20665,7 +21210,7 @@ function stopSessionHostProcesses(appName) {
20665
21210
  }
20666
21211
  }
20667
21212
  function removeDaemonPidFile() {
20668
- const pidFile = path20.join(os18.homedir(), ".adhdev", "daemon.pid");
21213
+ const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
20669
21214
  try {
20670
21215
  fs9.unlinkSync(pidFile);
20671
21216
  } catch {
@@ -20676,7 +21221,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20676
21221
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20677
21222
  if (!npmRoot) return;
20678
21223
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
20679
- const binDir = process.platform === "win32" ? npmPrefix : path20.join(npmPrefix, "bin");
21224
+ const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
20680
21225
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
20681
21226
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
20682
21227
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -20684,25 +21229,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
20684
21229
  }
20685
21230
  if (pkgName.startsWith("@")) {
20686
21231
  const [scope, name] = pkgName.split("/");
20687
- const scopeDir = path20.join(npmRoot, scope);
21232
+ const scopeDir = path21.join(npmRoot, scope);
20688
21233
  if (!fs9.existsSync(scopeDir)) return;
20689
21234
  for (const entry of fs9.readdirSync(scopeDir)) {
20690
21235
  if (!entry.startsWith(`.${name}-`)) continue;
20691
- fs9.rmSync(path20.join(scopeDir, entry), { recursive: true, force: true });
20692
- appendUpgradeLog(`Removed stale scoped staging dir: ${path20.join(scopeDir, entry)}`);
21236
+ fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
21237
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
20693
21238
  }
20694
21239
  } else {
20695
21240
  for (const entry of fs9.readdirSync(npmRoot)) {
20696
21241
  if (!entry.startsWith(`.${pkgName}-`)) continue;
20697
- fs9.rmSync(path20.join(npmRoot, entry), { recursive: true, force: true });
20698
- appendUpgradeLog(`Removed stale staging dir: ${path20.join(npmRoot, entry)}`);
21242
+ fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
21243
+ appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
20699
21244
  }
20700
21245
  }
20701
21246
  if (fs9.existsSync(binDir)) {
20702
21247
  for (const entry of fs9.readdirSync(binDir)) {
20703
21248
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
20704
- fs9.rmSync(path20.join(binDir, entry), { recursive: true, force: true });
20705
- appendUpgradeLog(`Removed stale bin staging entry: ${path20.join(binDir, entry)}`);
21249
+ fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
21250
+ appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
20706
21251
  }
20707
21252
  }
20708
21253
  }
@@ -20803,6 +21348,56 @@ function normalizeReleaseChannel(value) {
20803
21348
  function resolveUpgradeChannel(args) {
20804
21349
  return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
20805
21350
  }
21351
+ function readProviderPriorityFromPolicy(policy) {
21352
+ const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
21353
+ const raw = record.providerPriority;
21354
+ if (!Array.isArray(raw)) return [];
21355
+ const seen = /* @__PURE__ */ new Set();
21356
+ return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
21357
+ if (seen.has(type)) return false;
21358
+ seen.add(type);
21359
+ return true;
21360
+ });
21361
+ }
21362
+ async function resolveProviderTypeFromPriority(args) {
21363
+ if (!args.providerPriority.length) {
21364
+ return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
21365
+ }
21366
+ const failed = [];
21367
+ for (const requestedType of args.providerPriority) {
21368
+ const normalizedType = args.providerLoader.resolveAlias(requestedType);
21369
+ if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
21370
+ failed.push(`${requestedType}: disabled`);
21371
+ continue;
21372
+ }
21373
+ const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
21374
+ args.providerLoader.setCliDetectionResults([{
21375
+ id: normalizedType,
21376
+ installed: !!detected,
21377
+ path: detected?.path
21378
+ }], false);
21379
+ args.onStatusChange?.();
21380
+ if (detected) return { providerType: normalizedType };
21381
+ failed.push(`${requestedType}: not detected`);
21382
+ }
21383
+ return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
21384
+ }
21385
+ function loadYamlModule() {
21386
+ return yaml;
21387
+ }
21388
+ function getMcpServersKey(format) {
21389
+ return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
21390
+ }
21391
+ function parseMeshCoordinatorMcpConfig(text, format) {
21392
+ if (!text.trim()) return {};
21393
+ if (format === "claude_mcp_json") return JSON.parse(text);
21394
+ const parsed = loadYamlModule().load(text);
21395
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
21396
+ }
21397
+ function serializeMeshCoordinatorMcpConfig(config, format) {
21398
+ if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
21399
+ return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
21400
+ }
20806
21401
  var CHAT_COMMANDS = [
20807
21402
  "send_chat",
20808
21403
  "new_chat",
@@ -20901,6 +21496,154 @@ var DaemonCommandRouter = class {
20901
21496
  constructor(deps) {
20902
21497
  this.deps = deps;
20903
21498
  }
21499
+ getCachedInlineMesh(meshId, inlineMesh) {
21500
+ if (inlineMesh && typeof inlineMesh === "object") {
21501
+ this.inlineMeshCache.set(meshId, inlineMesh);
21502
+ return inlineMesh;
21503
+ }
21504
+ return this.inlineMeshCache.get(meshId);
21505
+ }
21506
+ async getMeshForCommand(meshId, inlineMesh) {
21507
+ try {
21508
+ const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21509
+ const mesh = getMesh3(meshId);
21510
+ if (mesh) return { mesh, inline: false };
21511
+ } catch {
21512
+ }
21513
+ const cached = this.getCachedInlineMesh(meshId, inlineMesh);
21514
+ return cached ? { mesh: cached, inline: true } : null;
21515
+ }
21516
+ updateInlineMeshNode(meshId, mesh, node) {
21517
+ if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
21518
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
21519
+ if (idx >= 0) mesh.nodes[idx] = node;
21520
+ else mesh.nodes.push(node);
21521
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21522
+ this.inlineMeshCache.set(meshId, mesh);
21523
+ }
21524
+ removeInlineMeshNode(meshId, mesh, nodeId) {
21525
+ if (!mesh || !Array.isArray(mesh.nodes)) return false;
21526
+ const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
21527
+ if (idx === -1) return false;
21528
+ mesh.nodes.splice(idx, 1);
21529
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
21530
+ this.inlineMeshCache.set(meshId, mesh);
21531
+ return true;
21532
+ }
21533
+ normalizeMeshSessionCleanupMode(value) {
21534
+ return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
21535
+ }
21536
+ sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
21537
+ const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
21538
+ if (!sessionId) return false;
21539
+ if (sessionIds?.size) return sessionIds.has(sessionId);
21540
+ const workspace = typeof node?.workspace === "string" ? node.workspace : "";
21541
+ if (workspace && record?.workspace === workspace) return true;
21542
+ if (record?.meta?.meshNodeId === nodeId) return true;
21543
+ return false;
21544
+ }
21545
+ isCompletedHostedSession(record) {
21546
+ return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
21547
+ }
21548
+ async cleanupMeshSessions(args) {
21549
+ if (args.mode === "preserve") {
21550
+ return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
21551
+ }
21552
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
21553
+ const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
21554
+ const sessions = await this.deps.sessionHostControl.listSessions();
21555
+ const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
21556
+ const hasExplicitSessionIds = !!requestedSessionIds?.size;
21557
+ const stoppedSessionIds = [];
21558
+ const deletedSessionIds = [];
21559
+ const skippedSessionIds = [];
21560
+ const skippedLiveSessionIds = [];
21561
+ const deleteUnsupportedSessionIds = [];
21562
+ const recordsRemainSessionIds = [];
21563
+ const errors = [];
21564
+ const matchedBySurfaceKind = {
21565
+ live_runtime: 0,
21566
+ recovery_snapshot: 0,
21567
+ inactive_record: 0
21568
+ };
21569
+ for (const record of matched) {
21570
+ const surfaceKind = getSessionHostSurfaceKind(record);
21571
+ matchedBySurfaceKind[surfaceKind] += 1;
21572
+ }
21573
+ for (const record of matched) {
21574
+ const sessionId = String(record.sessionId);
21575
+ const completed = this.isCompletedHostedSession(record);
21576
+ const surfaceKind = getSessionHostSurfaceKind(record);
21577
+ const liveRuntime = surfaceKind === "live_runtime";
21578
+ if (!hasExplicitSessionIds && liveRuntime) {
21579
+ skippedSessionIds.push(sessionId);
21580
+ skippedLiveSessionIds.push(sessionId);
21581
+ continue;
21582
+ }
21583
+ try {
21584
+ if (args.mode === "stop") {
21585
+ if (!completed) {
21586
+ if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
21587
+ stoppedSessionIds.push(sessionId);
21588
+ } else {
21589
+ skippedSessionIds.push(sessionId);
21590
+ }
21591
+ continue;
21592
+ }
21593
+ if (args.mode === "delete_stopped") {
21594
+ if (completed) {
21595
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
21596
+ deletedSessionIds.push(sessionId);
21597
+ } else {
21598
+ skippedSessionIds.push(sessionId);
21599
+ }
21600
+ continue;
21601
+ }
21602
+ if (args.mode === "stop_and_delete") {
21603
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
21604
+ deletedSessionIds.push(sessionId);
21605
+ continue;
21606
+ }
21607
+ } catch (e) {
21608
+ const message = e?.message || String(e);
21609
+ if (message.includes("Unsupported session host request: delete_session") && (args.mode === "delete_stopped" || args.mode === "stop_and_delete")) {
21610
+ deleteUnsupportedSessionIds.push(sessionId);
21611
+ recordsRemainSessionIds.push(sessionId);
21612
+ if (args.mode === "stop_and_delete" && !completed) {
21613
+ try {
21614
+ await this.deps.sessionHostControl.stopSession(sessionId);
21615
+ stoppedSessionIds.push(sessionId);
21616
+ } catch (stopError) {
21617
+ errors.push({ sessionId, error: stopError?.message || String(stopError) });
21618
+ continue;
21619
+ }
21620
+ }
21621
+ skippedSessionIds.push(sessionId);
21622
+ continue;
21623
+ }
21624
+ errors.push({ sessionId, error: message });
21625
+ }
21626
+ }
21627
+ const deleteUnsupported = deleteUnsupportedSessionIds.length > 0;
21628
+ return {
21629
+ success: errors.length === 0,
21630
+ mode: args.mode,
21631
+ dryRun: args.dryRun === true,
21632
+ matchedCount: matched.length,
21633
+ matchedBySurfaceKind,
21634
+ stoppedSessionIds,
21635
+ deletedSessionIds,
21636
+ skippedSessionIds,
21637
+ skippedLiveSessionIds,
21638
+ ...deleteUnsupported ? {
21639
+ deleteUnsupported: true,
21640
+ effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
21641
+ deleteUnsupportedSessionIds,
21642
+ recordsRemainSessionIds
21643
+ } : {},
21644
+ ...errors.length ? { errors } : {}
21645
+ };
21646
+ }
20904
21647
  async traceSessionHostAction(action, args, run, summarizeResult) {
20905
21648
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
20906
21649
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -21020,6 +21763,9 @@ var DaemonCommandRouter = class {
21020
21763
  async executeDaemonCommand(cmd, args) {
21021
21764
  switch (cmd) {
21022
21765
  // ─── CLI / ACP commands ───
21766
+ case "mesh_forward_event": {
21767
+ return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
21768
+ }
21023
21769
  case "launch_cli":
21024
21770
  case "stop_cli":
21025
21771
  case "set_cli_view_mode":
@@ -21564,7 +22310,26 @@ var DaemonCommandRouter = class {
21564
22310
  if (!name) return { success: false, error: "name required" };
21565
22311
  try {
21566
22312
  const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21567
- const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
22313
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
22314
+ return { success: true, mesh };
22315
+ } catch (e) {
22316
+ return { success: false, error: e.message };
22317
+ }
22318
+ }
22319
+ case "update_mesh": {
22320
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22321
+ if (!meshId) return { success: false, error: "meshId required" };
22322
+ try {
22323
+ const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22324
+ const patch = {};
22325
+ if (typeof args?.name === "string") patch.name = args.name;
22326
+ if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
22327
+ if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
22328
+ if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
22329
+ if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
22330
+ const mesh = updateMesh2(meshId, patch);
22331
+ if (!mesh) return { success: false, error: "Mesh not found" };
22332
+ this.inlineMeshCache.set(meshId, mesh);
21568
22333
  return { success: true, mesh };
21569
22334
  } catch (e) {
21570
22335
  return { success: false, error: e.message };
@@ -21588,21 +22353,164 @@ var DaemonCommandRouter = class {
21588
22353
  if (!workspace) return { success: false, error: "workspace required" };
21589
22354
  try {
21590
22355
  const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21591
- const node = addNode3(meshId, { workspace });
22356
+ const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
22357
+ const readOnly = args?.readOnly === true;
22358
+ const policy = {
22359
+ ...readOnly ? { readOnly: true } : {},
22360
+ ...providerPriority.length ? { providerPriority } : {}
22361
+ };
22362
+ const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
21592
22363
  if (!node) return { success: false, error: "Mesh not found" };
21593
22364
  return { success: true, node };
21594
22365
  } catch (e) {
21595
22366
  return { success: false, error: e.message };
21596
22367
  }
21597
22368
  }
22369
+ case "update_mesh_node": {
22370
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22371
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22372
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22373
+ try {
22374
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22375
+ const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
22376
+ if (Array.isArray(args?.providerPriority)) {
22377
+ const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
22378
+ delete policy.provider_priority;
22379
+ if (providerPriority.length) {
22380
+ policy.providerPriority = providerPriority;
22381
+ } else {
22382
+ delete policy.providerPriority;
22383
+ }
22384
+ }
22385
+ const node = updateNode2(meshId, nodeId, { policy });
22386
+ if (!node) return { success: false, error: "Mesh node not found" };
22387
+ return { success: true, node };
22388
+ } catch (e) {
22389
+ return { success: false, error: e.message };
22390
+ }
22391
+ }
22392
+ case "cleanup_mesh_sessions": {
22393
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22394
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
22395
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
22396
+ try {
22397
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22398
+ const mesh = meshRecord?.mesh;
22399
+ if (!mesh) return { success: false, error: "Mesh not found" };
22400
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22401
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
22402
+ const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
22403
+ const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
22404
+ const result = await this.cleanupMeshSessions({
22405
+ meshId,
22406
+ nodeId,
22407
+ node,
22408
+ mode,
22409
+ sessionIds,
22410
+ dryRun: args?.dryRun === true
22411
+ });
22412
+ return result;
22413
+ } catch (e) {
22414
+ return { success: false, error: e.message };
22415
+ }
22416
+ }
21598
22417
  case "remove_mesh_node": {
21599
22418
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21600
22419
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
21601
22420
  if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
21602
22421
  try {
21603
- const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
21604
- const removed = removeNode3(meshId, nodeId);
21605
- return { success: true, removed };
22422
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22423
+ const mesh = meshRecord?.mesh;
22424
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
22425
+ const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
22426
+ args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
22427
+ );
22428
+ let sessionCleanup;
22429
+ if (node && sessionCleanupMode !== "preserve") {
22430
+ sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
22431
+ if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
22432
+ }
22433
+ if (node?.isLocalWorktree && node.workspace) {
22434
+ try {
22435
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
22436
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
22437
+ if (repoRoot) {
22438
+ const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22439
+ await removeWorktree2(repoRoot, node.workspace);
22440
+ }
22441
+ } catch (e) {
22442
+ LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
22443
+ }
22444
+ }
22445
+ let removed = false;
22446
+ if (meshRecord?.inline) {
22447
+ removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
22448
+ } else {
22449
+ const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22450
+ removed = removeNode3(meshId, nodeId);
22451
+ }
22452
+ return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
22453
+ } catch (e) {
22454
+ return { success: false, error: e.message };
22455
+ }
22456
+ }
22457
+ case "clone_mesh_node": {
22458
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
22459
+ const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
22460
+ const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
22461
+ const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
22462
+ if (!meshId) return { success: false, error: "meshId required" };
22463
+ if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
22464
+ if (!branch) return { success: false, error: "branch required" };
22465
+ try {
22466
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
22467
+ const mesh = meshRecord?.mesh;
22468
+ if (!mesh) return { success: false, error: "Mesh not found" };
22469
+ const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
22470
+ if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
22471
+ const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
22472
+ const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
22473
+ const result = await createWorktree2({
22474
+ repoRoot,
22475
+ branch,
22476
+ baseBranch,
22477
+ meshName: mesh.name
22478
+ });
22479
+ let node;
22480
+ if (meshRecord.inline) {
22481
+ const { randomUUID: randomUUID8 } = await import("crypto");
22482
+ node = {
22483
+ id: `node_${randomUUID8().replace(/-/g, "")}`,
22484
+ workspace: result.worktreePath,
22485
+ repoRoot: result.worktreePath,
22486
+ daemonId: sourceNode.daemonId,
22487
+ userOverrides: { ...sourceNode.userOverrides || {} },
22488
+ policy: { ...sourceNode.policy || {} },
22489
+ isLocalWorktree: true,
22490
+ worktreeBranch: result.branch,
22491
+ clonedFromNodeId: sourceNodeId
22492
+ };
22493
+ this.updateInlineMeshNode(meshId, mesh, node);
22494
+ } else {
22495
+ const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
22496
+ node = addNode3(meshId, {
22497
+ workspace: result.worktreePath,
22498
+ repoRoot: result.worktreePath,
22499
+ daemonId: sourceNode.daemonId,
22500
+ userOverrides: { ...sourceNode.userOverrides || {} },
22501
+ isLocalWorktree: true,
22502
+ worktreeBranch: result.branch,
22503
+ clonedFromNodeId: sourceNodeId,
22504
+ policy: { ...sourceNode.policy || {} }
22505
+ });
22506
+ if (!node) return { success: false, error: "Failed to register worktree node" };
22507
+ }
22508
+ return {
22509
+ success: true,
22510
+ node,
22511
+ worktreePath: result.worktreePath,
22512
+ branch: result.branch
22513
+ };
21606
22514
  } catch (e) {
21607
22515
  return { success: false, error: e.message };
21608
22516
  }
@@ -21610,7 +22518,7 @@ var DaemonCommandRouter = class {
21610
22518
  // ─── Mesh Coordinator Launch ───
21611
22519
  case "launch_mesh_coordinator": {
21612
22520
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
21613
- const cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "claude-cli";
22521
+ let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
21614
22522
  if (!meshId) return { success: false, error: "meshId required" };
21615
22523
  try {
21616
22524
  const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
@@ -21638,9 +22546,29 @@ var DaemonCommandRouter = class {
21638
22546
  }
21639
22547
  const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
21640
22548
  if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
22549
+ if (!cliType) {
22550
+ const resolved = await resolveProviderTypeFromPriority({
22551
+ nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
22552
+ providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
22553
+ providerLoader: this.deps.providerLoader,
22554
+ onStatusChange: this.deps.onStatusChange
22555
+ });
22556
+ if (!resolved.providerType) {
22557
+ return {
22558
+ success: false,
22559
+ code: "mesh_coordinator_provider_priority_unusable",
22560
+ error: resolved.error || "No usable provider found from node providerPriority",
22561
+ meshId,
22562
+ cliType,
22563
+ workspace
22564
+ };
22565
+ }
22566
+ cliType = resolved.providerType;
22567
+ }
21641
22568
  const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
21642
22569
  const coordinatorSetup = resolveMeshCoordinatorSetup({
21643
22570
  provider: providerMeta,
22571
+ cliType,
21644
22572
  meshId,
21645
22573
  workspace
21646
22574
  });
@@ -21665,7 +22593,8 @@ var DaemonCommandRouter = class {
21665
22593
  meshCoordinatorSetup: coordinatorSetup
21666
22594
  };
21667
22595
  }
21668
- if (coordinatorSetup.configFormat !== "claude_mcp_json") {
22596
+ const configFormat = coordinatorSetup.configFormat;
22597
+ if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
21669
22598
  return {
21670
22599
  success: false,
21671
22600
  code: "mesh_coordinator_unsupported",
@@ -21675,44 +22604,93 @@ var DaemonCommandRouter = class {
21675
22604
  workspace
21676
22605
  };
21677
22606
  }
21678
- const { existsSync: existsSync22, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3 } = await import("fs");
21679
- const mcpConfigPath = coordinatorSetup.configPath;
21680
- const hadExistingMcpConfig = existsSync22(mcpConfigPath);
21681
- let existingMcpConfig = {};
21682
- if (hadExistingMcpConfig) {
21683
- try {
21684
- existingMcpConfig = JSON.parse(readFileSync15(mcpConfigPath, "utf-8"));
21685
- copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
21686
- } catch {
21687
- }
22607
+ let systemPrompt = "";
22608
+ try {
22609
+ systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
22610
+ } catch (error) {
22611
+ const message = error?.message || String(error);
22612
+ LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
22613
+ return {
22614
+ success: false,
22615
+ code: "mesh_coordinator_prompt_failed",
22616
+ error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
22617
+ meshId,
22618
+ cliType,
22619
+ workspace
22620
+ };
21688
22621
  }
22622
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22623
+ const { dirname: dirname9 } = await import("path");
22624
+ const mcpConfigPath = coordinatorSetup.configPath;
22625
+ const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
22626
+ const returnManualFallback = (message) => ({
22627
+ success: false,
22628
+ code: "mesh_coordinator_manual_mcp_setup_required",
22629
+ error: message,
22630
+ meshId,
22631
+ cliType,
22632
+ workspace,
22633
+ meshCoordinatorSetup: hermesManualFallback
22634
+ });
21689
22635
  const mcpServerEntry = {
21690
22636
  command: coordinatorSetup.mcpServer.command,
21691
22637
  args: coordinatorSetup.mcpServer.args
21692
22638
  };
21693
22639
  if (args?.inlineMesh) {
21694
22640
  mcpServerEntry.env = {
21695
- ADHDEV_INLINE_MESH: JSON.stringify(mesh)
22641
+ ADHDEV_INLINE_MESH: JSON.stringify(mesh),
22642
+ ADHDEV_MCP_TRANSPORT: "ipc"
21696
22643
  };
21697
22644
  }
22645
+ try {
22646
+ mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
22647
+ } catch (error) {
22648
+ const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22649
+ LOG.error("MeshCoordinator", message);
22650
+ if (hermesManualFallback) return returnManualFallback(message);
22651
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
22652
+ }
22653
+ const hadExistingMcpConfig = existsSync23(mcpConfigPath);
22654
+ let existingMcpConfig = {};
22655
+ if (hadExistingMcpConfig) {
22656
+ try {
22657
+ existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
22658
+ copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
22659
+ } catch (error) {
22660
+ LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
22661
+ return {
22662
+ success: false,
22663
+ code: "mesh_coordinator_config_parse_failed",
22664
+ error: `Failed to parse existing MCP config at ${mcpConfigPath}`
22665
+ };
22666
+ }
22667
+ }
22668
+ const mcpServersKey = getMcpServersKey(configFormat);
22669
+ const existingServers = existingMcpConfig[mcpServersKey];
21698
22670
  const mcpConfig = {
21699
22671
  ...existingMcpConfig,
21700
- mcpServers: {
21701
- ...existingMcpConfig.mcpServers || {},
22672
+ [mcpServersKey]: {
22673
+ ...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
21702
22674
  [coordinatorSetup.serverName]: mcpServerEntry
21703
22675
  }
21704
22676
  };
21705
- writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
21706
- LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21707
- let systemPrompt = "";
21708
22677
  try {
21709
- systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
21710
- } catch {
21711
- systemPrompt = `You are a Repo Mesh Coordinator for "${mesh.name}". Use the adhdev-mesh MCP tools (mesh_status, mesh_list_nodes, mesh_send_task, mesh_read_chat, mesh_launch_session, etc.) to orchestrate work across ${mesh.nodes.length} node(s).`;
22678
+ writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22679
+ } catch (error) {
22680
+ const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22681
+ LOG.error("MeshCoordinator", message);
22682
+ if (hermesManualFallback) return returnManualFallback(message);
22683
+ return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
21712
22684
  }
22685
+ LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
21713
22686
  const cliArgs = [];
22687
+ const launchEnv = {};
21714
22688
  if (systemPrompt) {
21715
- cliArgs.push("--append-system-prompt", systemPrompt);
22689
+ if (configFormat === "hermes_config_yaml") {
22690
+ launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
22691
+ } else {
22692
+ cliArgs.push("--append-system-prompt", systemPrompt);
22693
+ }
21716
22694
  }
21717
22695
  if (cliType === "claude-cli") {
21718
22696
  cliArgs.push("--mcp-config", coordinatorSetup.configPath);
@@ -21721,6 +22699,7 @@ var DaemonCommandRouter = class {
21721
22699
  cliType,
21722
22700
  dir: workspace,
21723
22701
  cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
22702
+ env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
21724
22703
  settings: {
21725
22704
  meshCoordinatorFor: meshId
21726
22705
  }
@@ -21900,6 +22879,12 @@ var DaemonStatusReporter = class {
21900
22879
  if (providerType) {
21901
22880
  payload.providerType = providerType;
21902
22881
  }
22882
+ if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
22883
+ payload.providerSessionId = event.providerSessionId.trim();
22884
+ }
22885
+ if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
22886
+ payload.workspaceName = event.workspaceName.trim();
22887
+ }
21903
22888
  if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
21904
22889
  payload.duration = event.duration;
21905
22890
  }
@@ -23147,7 +24132,10 @@ var ProviderInstanceManager = class {
23147
24132
  this.instances.get(id).dispose();
23148
24133
  }
23149
24134
  this.instances.set(id, instance);
23150
- await instance.init(context);
24135
+ await instance.init({
24136
+ ...context,
24137
+ emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
24138
+ });
23151
24139
  }
23152
24140
  /**
23153
24141
  * Instance remove
@@ -23309,6 +24297,17 @@ var ProviderInstanceManager = class {
23309
24297
  onEvent(listener) {
23310
24298
  this.eventListeners.push(listener);
23311
24299
  }
24300
+ emitProviderEvent(providerType, instanceId, event) {
24301
+ const payload = {
24302
+ ...event,
24303
+ providerType,
24304
+ instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
24305
+ targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
24306
+ };
24307
+ for (const listener of this.eventListeners) {
24308
+ listener(payload);
24309
+ }
24310
+ }
23312
24311
  emitPendingEvents(providerType, state, extra = {}) {
23313
24312
  for (const event of state.pendingEvents) {
23314
24313
  for (const listener of this.eventListeners) {
@@ -23381,11 +24380,11 @@ var ProviderInstanceManager = class {
23381
24380
 
23382
24381
  // src/providers/version-archive.ts
23383
24382
  var fs11 = __toESM(require("fs"));
23384
- var path21 = __toESM(require("path"));
23385
- var os19 = __toESM(require("os"));
24383
+ var path22 = __toESM(require("path"));
24384
+ var os20 = __toESM(require("os"));
23386
24385
  var import_child_process10 = require("child_process");
23387
24386
  var import_os3 = require("os");
23388
- var ARCHIVE_PATH = path21.join(os19.homedir(), ".adhdev", "version-history.json");
24387
+ var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
23389
24388
  var MAX_ENTRIES_PER_PROVIDER = 20;
23390
24389
  var VersionArchive = class {
23391
24390
  history = {};
@@ -23432,7 +24431,7 @@ var VersionArchive = class {
23432
24431
  }
23433
24432
  save() {
23434
24433
  try {
23435
- fs11.mkdirSync(path21.dirname(ARCHIVE_PATH), { recursive: true });
24434
+ fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
23436
24435
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
23437
24436
  } catch {
23438
24437
  }
@@ -23488,8 +24487,8 @@ function getVersion(binary, versionCommand) {
23488
24487
  function checkPathExists2(paths) {
23489
24488
  for (const p of paths) {
23490
24489
  if (p.includes("*")) {
23491
- const home = os19.homedir();
23492
- const resolved = p.replace(/\*/g, home.split(path21.sep).pop() || "");
24490
+ const home = os20.homedir();
24491
+ const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
23493
24492
  if (fs11.existsSync(resolved)) return resolved;
23494
24493
  } else {
23495
24494
  if (fs11.existsSync(p)) return p;
@@ -23499,7 +24498,7 @@ function checkPathExists2(paths) {
23499
24498
  }
23500
24499
  function getMacAppVersion(appPath) {
23501
24500
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
23502
- const plistPath = path21.join(appPath, "Contents", "Info.plist");
24501
+ const plistPath = path22.join(appPath, "Contents", "Info.plist");
23503
24502
  if (!fs11.existsSync(plistPath)) return null;
23504
24503
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
23505
24504
  return raw || null;
@@ -23525,7 +24524,7 @@ async function detectAllVersions(loader, archive) {
23525
24524
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
23526
24525
  let resolvedBin = cliBin;
23527
24526
  if (!resolvedBin && appPath && currentOs === "darwin") {
23528
- const bundled = path21.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24527
+ const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
23529
24528
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
23530
24529
  }
23531
24530
  info.installed = !!(appPath || resolvedBin);
@@ -23566,7 +24565,7 @@ async function detectAllVersions(loader, archive) {
23566
24565
  // src/daemon/dev-server.ts
23567
24566
  var http2 = __toESM(require("http"));
23568
24567
  var fs15 = __toESM(require("fs"));
23569
- var path25 = __toESM(require("path"));
24568
+ var path26 = __toESM(require("path"));
23570
24569
  init_config();
23571
24570
 
23572
24571
  // src/daemon/scaffold-template.ts
@@ -23917,7 +24916,7 @@ init_logger();
23917
24916
 
23918
24917
  // src/daemon/dev-cdp-handlers.ts
23919
24918
  var fs12 = __toESM(require("fs"));
23920
- var path22 = __toESM(require("path"));
24919
+ var path23 = __toESM(require("path"));
23921
24920
  init_logger();
23922
24921
  async function handleCdpEvaluate(ctx, req, res) {
23923
24922
  const body = await ctx.readBody(req);
@@ -24096,17 +25095,17 @@ async function handleScriptHints(ctx, type, _req, res) {
24096
25095
  return;
24097
25096
  }
24098
25097
  let scriptsPath = "";
24099
- const directScripts = path22.join(dir, "scripts.js");
25098
+ const directScripts = path23.join(dir, "scripts.js");
24100
25099
  if (fs12.existsSync(directScripts)) {
24101
25100
  scriptsPath = directScripts;
24102
25101
  } else {
24103
- const scriptsDir = path22.join(dir, "scripts");
25102
+ const scriptsDir = path23.join(dir, "scripts");
24104
25103
  if (fs12.existsSync(scriptsDir)) {
24105
25104
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
24106
- return fs12.statSync(path22.join(scriptsDir, d)).isDirectory();
25105
+ return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
24107
25106
  }).sort().reverse();
24108
25107
  for (const ver of versions) {
24109
- const p = path22.join(scriptsDir, ver, "scripts.js");
25108
+ const p = path23.join(scriptsDir, ver, "scripts.js");
24110
25109
  if (fs12.existsSync(p)) {
24111
25110
  scriptsPath = p;
24112
25111
  break;
@@ -24935,7 +25934,7 @@ async function handleDomContext(ctx, type, req, res) {
24935
25934
 
24936
25935
  // src/daemon/dev-cli-debug.ts
24937
25936
  var fs13 = __toESM(require("fs"));
24938
- var path23 = __toESM(require("path"));
25937
+ var path24 = __toESM(require("path"));
24939
25938
  function slugifyFixtureName(value) {
24940
25939
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
24941
25940
  return normalized || `fixture-${Date.now()}`;
@@ -24945,11 +25944,11 @@ function getCliFixtureDir(ctx, type) {
24945
25944
  if (!providerDir) {
24946
25945
  throw new Error(`Provider directory not found for '${type}'`);
24947
25946
  }
24948
- return path23.join(providerDir, "fixtures");
25947
+ return path24.join(providerDir, "fixtures");
24949
25948
  }
24950
25949
  function readCliFixture(ctx, type, name) {
24951
25950
  const fixtureDir = getCliFixtureDir(ctx, type);
24952
- const filePath = path23.join(fixtureDir, `${name}.json`);
25951
+ const filePath = path24.join(fixtureDir, `${name}.json`);
24953
25952
  if (!fs13.existsSync(filePath)) {
24954
25953
  throw new Error(`Fixture not found: ${filePath}`);
24955
25954
  }
@@ -25117,7 +26116,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
25117
26116
  if (!adapter) return null;
25118
26117
  return { target, instance, adapter };
25119
26118
  }
25120
- function sleep(ms) {
26119
+ function sleep2(ms) {
25121
26120
  return new Promise((resolve16) => setTimeout(resolve16, ms));
25122
26121
  }
25123
26122
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
@@ -25134,7 +26133,7 @@ async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
25134
26133
  return bundle;
25135
26134
  }
25136
26135
  }
25137
- await sleep(100);
26136
+ await sleep2(100);
25138
26137
  }
25139
26138
  return getCliTargetBundle(ctx, type, instanceId);
25140
26139
  }
@@ -25190,7 +26189,7 @@ async function runCliExerciseInternal(ctx, body) {
25190
26189
  const message = String(lastLaunchError.message || "");
25191
26190
  const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
25192
26191
  if (!retryable || attempt === 2) break;
25193
- await sleep(1e3);
26192
+ await sleep2(1e3);
25194
26193
  }
25195
26194
  }
25196
26195
  if (!launched) {
@@ -25253,16 +26252,16 @@ async function runCliExerciseInternal(ctx, body) {
25253
26252
  const modal = debug?.activeModal || trace?.activeModal || null;
25254
26253
  noteStatus(status);
25255
26254
  if (resolveActiveModalIfNeeded(status, modal)) {
25256
- await sleep(150);
26255
+ await sleep2(150);
25257
26256
  continue;
25258
26257
  }
25259
26258
  const startupParseGate = !!debug?.startupParseGate;
25260
26259
  if (status === "idle" && !startupParseGate) break;
25261
- await sleep(150);
26260
+ await sleep2(150);
25262
26261
  }
25263
26262
  ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
25264
26263
  while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
25265
- await sleep(150);
26264
+ await sleep2(150);
25266
26265
  bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
25267
26266
  if (!bundle) {
25268
26267
  throw new Error("CLI instance disappeared during exercise");
@@ -25716,7 +26715,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
25716
26715
  },
25717
26716
  notes: typeof body?.notes === "string" ? body.notes : void 0
25718
26717
  };
25719
- const filePath = path23.join(fixtureDir, `${name}.json`);
26718
+ const filePath = path24.join(fixtureDir, `${name}.json`);
25720
26719
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
25721
26720
  ctx.json(res, 200, {
25722
26721
  saved: true,
@@ -25740,7 +26739,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
25740
26739
  return;
25741
26740
  }
25742
26741
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
25743
- const fullPath = path23.join(fixtureDir, file);
26742
+ const fullPath = path24.join(fixtureDir, file);
25744
26743
  try {
25745
26744
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
25746
26745
  return {
@@ -25876,8 +26875,8 @@ async function handleCliRaw(ctx, req, res) {
25876
26875
 
25877
26876
  // src/daemon/dev-auto-implement.ts
25878
26877
  var fs14 = __toESM(require("fs"));
25879
- var path24 = __toESM(require("path"));
25880
- var os20 = __toESM(require("os"));
26878
+ var path25 = __toESM(require("path"));
26879
+ var os21 = __toESM(require("os"));
25881
26880
  function getAutoImplPid(ctx) {
25882
26881
  const pid = ctx.autoImplProcess?.pid;
25883
26882
  return typeof pid === "number" && pid > 0 ? pid : null;
@@ -25926,22 +26925,22 @@ function getLatestScriptVersionDir(scriptsDir) {
25926
26925
  if (!fs14.existsSync(scriptsDir)) return null;
25927
26926
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
25928
26927
  try {
25929
- return fs14.statSync(path24.join(scriptsDir, d)).isDirectory();
26928
+ return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
25930
26929
  } catch {
25931
26930
  return false;
25932
26931
  }
25933
26932
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
25934
26933
  if (versions.length === 0) return null;
25935
- return path24.join(scriptsDir, versions[0]);
26934
+ return path25.join(scriptsDir, versions[0]);
25936
26935
  }
25937
26936
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25938
- const canonicalUserDir = path24.resolve(ctx.providerLoader.getUserProviderDir(category, type));
25939
- const desiredDir = requestedDir ? path24.resolve(requestedDir) : canonicalUserDir;
25940
- const upstreamRoot = path24.resolve(ctx.providerLoader.getUpstreamDir());
25941
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path24.sep}`)) {
26937
+ const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26938
+ const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26939
+ const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26940
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
25942
26941
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
25943
26942
  }
25944
- if (path24.basename(desiredDir) !== type) {
26943
+ if (path25.basename(desiredDir) !== type) {
25945
26944
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
25946
26945
  }
25947
26946
  const sourceDir = ctx.findProviderDir(type);
@@ -25949,11 +26948,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
25949
26948
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
25950
26949
  }
25951
26950
  if (!fs14.existsSync(desiredDir)) {
25952
- fs14.mkdirSync(path24.dirname(desiredDir), { recursive: true });
26951
+ fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
25953
26952
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
25954
26953
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
25955
26954
  }
25956
- const providerJson = path24.join(desiredDir, "provider.json");
26955
+ const providerJson = path25.join(desiredDir, "provider.json");
25957
26956
  if (!fs14.existsSync(providerJson)) {
25958
26957
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
25959
26958
  }
@@ -25964,13 +26963,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
25964
26963
  const refDir = ctx.findProviderDir(referenceType);
25965
26964
  if (!refDir || !fs14.existsSync(refDir)) return {};
25966
26965
  const referenceScripts = {};
25967
- const scriptsDir = path24.join(refDir, "scripts");
26966
+ const scriptsDir = path25.join(refDir, "scripts");
25968
26967
  const latestDir = getLatestScriptVersionDir(scriptsDir);
25969
26968
  if (!latestDir) return referenceScripts;
25970
26969
  for (const file of fs14.readdirSync(latestDir)) {
25971
26970
  if (!file.endsWith(".js")) continue;
25972
26971
  try {
25973
- referenceScripts[file] = fs14.readFileSync(path24.join(latestDir, file), "utf-8");
26972
+ referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
25974
26973
  } catch {
25975
26974
  }
25976
26975
  }
@@ -26078,9 +27077,9 @@ async function handleAutoImplement(ctx, type, req, res) {
26078
27077
  });
26079
27078
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
26080
27079
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
26081
- const tmpDir = path24.join(os20.tmpdir(), "adhdev-autoimpl");
27080
+ const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
26082
27081
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
26083
- const promptFile = path24.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
27082
+ const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26084
27083
  fs14.writeFileSync(promptFile, prompt, "utf-8");
26085
27084
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
26086
27085
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -26233,7 +27232,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26233
27232
  const interactiveFlags = ["--yolo", "--interactive", "-i"];
26234
27233
  const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
26235
27234
  let shellCmd;
26236
- const isWin = os20.platform() === "win32";
27235
+ const isWin = os21.platform() === "win32";
26237
27236
  const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
26238
27237
  const promptMode = autoImpl?.promptMode ?? "stdin";
26239
27238
  const extraArgs = autoImpl?.extraArgs ?? [];
@@ -26272,7 +27271,7 @@ async function handleAutoImplement(ctx, type, req, res) {
26272
27271
  try {
26273
27272
  const pty = require("node-pty");
26274
27273
  ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
26275
- const isWin2 = os20.platform() === "win32";
27274
+ const isWin2 = os21.platform() === "win32";
26276
27275
  child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
26277
27276
  name: "xterm-256color",
26278
27277
  cols: 120,
@@ -26512,7 +27511,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26512
27511
  setMode: "set_mode.js"
26513
27512
  };
26514
27513
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26515
- const scriptsDir = path24.join(providerDir, "scripts");
27514
+ const scriptsDir = path25.join(providerDir, "scripts");
26516
27515
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26517
27516
  if (latestScriptsDir) {
26518
27517
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26523,7 +27522,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26523
27522
  for (const file of fs14.readdirSync(latestScriptsDir)) {
26524
27523
  if (file.endsWith(".js") && targetFileNames.has(file)) {
26525
27524
  try {
26526
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27525
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26527
27526
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26528
27527
  lines.push("```javascript");
26529
27528
  lines.push(content);
@@ -26540,7 +27539,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26540
27539
  lines.push("");
26541
27540
  for (const file of refFiles) {
26542
27541
  try {
26543
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27542
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26544
27543
  lines.push(`### \`${file}\` \u{1F512}`);
26545
27544
  lines.push("```javascript");
26546
27545
  lines.push(content);
@@ -26581,10 +27580,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
26581
27580
  lines.push("");
26582
27581
  }
26583
27582
  }
26584
- const docsDir = path24.join(providerDir, "../../docs");
27583
+ const docsDir = path25.join(providerDir, "../../docs");
26585
27584
  const loadGuide = (name) => {
26586
27585
  try {
26587
- const p = path24.join(docsDir, name);
27586
+ const p = path25.join(docsDir, name);
26588
27587
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26589
27588
  } catch {
26590
27589
  }
@@ -26821,7 +27820,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26821
27820
  parseApproval: "parse_approval.js"
26822
27821
  };
26823
27822
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
26824
- const scriptsDir = path24.join(providerDir, "scripts");
27823
+ const scriptsDir = path25.join(providerDir, "scripts");
26825
27824
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
26826
27825
  if (latestScriptsDir) {
26827
27826
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -26833,7 +27832,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26833
27832
  if (!file.endsWith(".js")) continue;
26834
27833
  if (!targetFileNames.has(file)) continue;
26835
27834
  try {
26836
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27835
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26837
27836
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
26838
27837
  lines.push("```javascript");
26839
27838
  lines.push(content);
@@ -26849,7 +27848,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26849
27848
  lines.push("");
26850
27849
  for (const file of refFiles) {
26851
27850
  try {
26852
- const content = fs14.readFileSync(path24.join(latestScriptsDir, file), "utf-8");
27851
+ const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
26853
27852
  lines.push(`### \`${file}\` \u{1F512}`);
26854
27853
  lines.push("```javascript");
26855
27854
  lines.push(content);
@@ -26882,10 +27881,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
26882
27881
  lines.push("");
26883
27882
  }
26884
27883
  }
26885
- const docsDir = path24.join(providerDir, "../../docs");
27884
+ const docsDir = path25.join(providerDir, "../../docs");
26886
27885
  const loadGuide = (name) => {
26887
27886
  try {
26888
- const p = path24.join(docsDir, name);
27887
+ const p = path25.join(docsDir, name);
26889
27888
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
26890
27889
  } catch {
26891
27890
  }
@@ -27332,8 +28331,8 @@ var DevServer = class _DevServer {
27332
28331
  }
27333
28332
  getEndpointList() {
27334
28333
  return this.routes.map((r) => {
27335
- const path26 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
27336
- return `${r.method.padEnd(5)} ${path26}`;
28334
+ const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28335
+ return `${r.method.padEnd(5)} ${path27}`;
27337
28336
  });
27338
28337
  }
27339
28338
  async start(port = DEV_SERVER_PORT) {
@@ -27621,12 +28620,12 @@ var DevServer = class _DevServer {
27621
28620
  // ─── DevConsole SPA ───
27622
28621
  getConsoleDistDir() {
27623
28622
  const candidates = [
27624
- path25.resolve(__dirname, "../../web-devconsole/dist"),
27625
- path25.resolve(__dirname, "../../../web-devconsole/dist"),
27626
- path25.join(process.cwd(), "packages/web-devconsole/dist")
28623
+ path26.resolve(__dirname, "../../web-devconsole/dist"),
28624
+ path26.resolve(__dirname, "../../../web-devconsole/dist"),
28625
+ path26.join(process.cwd(), "packages/web-devconsole/dist")
27627
28626
  ];
27628
28627
  for (const dir of candidates) {
27629
- if (fs15.existsSync(path25.join(dir, "index.html"))) return dir;
28628
+ if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
27630
28629
  }
27631
28630
  return null;
27632
28631
  }
@@ -27636,7 +28635,7 @@ var DevServer = class _DevServer {
27636
28635
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
27637
28636
  return;
27638
28637
  }
27639
- const htmlPath = path25.join(distDir, "index.html");
28638
+ const htmlPath = path26.join(distDir, "index.html");
27640
28639
  try {
27641
28640
  const html = fs15.readFileSync(htmlPath, "utf-8");
27642
28641
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -27661,15 +28660,15 @@ var DevServer = class _DevServer {
27661
28660
  this.json(res, 404, { error: "Not found" });
27662
28661
  return;
27663
28662
  }
27664
- const safePath = path25.normalize(pathname).replace(/^\.\.\//, "");
27665
- const filePath = path25.join(distDir, safePath);
28663
+ const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28664
+ const filePath = path26.join(distDir, safePath);
27666
28665
  if (!filePath.startsWith(distDir)) {
27667
28666
  this.json(res, 403, { error: "Forbidden" });
27668
28667
  return;
27669
28668
  }
27670
28669
  try {
27671
28670
  const content = fs15.readFileSync(filePath);
27672
- const ext = path25.extname(filePath);
28671
+ const ext = path26.extname(filePath);
27673
28672
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
27674
28673
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
27675
28674
  res.end(content);
@@ -27782,9 +28781,9 @@ var DevServer = class _DevServer {
27782
28781
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
27783
28782
  if (entry.isDirectory()) {
27784
28783
  files.push({ path: rel, size: 0, type: "dir" });
27785
- scan(path25.join(d, entry.name), rel);
28784
+ scan(path26.join(d, entry.name), rel);
27786
28785
  } else {
27787
- const stat2 = fs15.statSync(path25.join(d, entry.name));
28786
+ const stat2 = fs15.statSync(path26.join(d, entry.name));
27788
28787
  files.push({ path: rel, size: stat2.size, type: "file" });
27789
28788
  }
27790
28789
  }
@@ -27807,7 +28806,7 @@ var DevServer = class _DevServer {
27807
28806
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27808
28807
  return;
27809
28808
  }
27810
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28809
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27811
28810
  if (!fullPath.startsWith(dir)) {
27812
28811
  this.json(res, 403, { error: "Forbidden" });
27813
28812
  return;
@@ -27832,14 +28831,14 @@ var DevServer = class _DevServer {
27832
28831
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
27833
28832
  return;
27834
28833
  }
27835
- const fullPath = path25.resolve(dir, path25.normalize(filePath));
28834
+ const fullPath = path26.resolve(dir, path26.normalize(filePath));
27836
28835
  if (!fullPath.startsWith(dir)) {
27837
28836
  this.json(res, 403, { error: "Forbidden" });
27838
28837
  return;
27839
28838
  }
27840
28839
  try {
27841
28840
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
27842
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
28841
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
27843
28842
  fs15.writeFileSync(fullPath, content, "utf-8");
27844
28843
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
27845
28844
  this.providerLoader.reload();
@@ -27856,7 +28855,7 @@ var DevServer = class _DevServer {
27856
28855
  return;
27857
28856
  }
27858
28857
  for (const name of ["scripts.js", "provider.json"]) {
27859
- const p = path25.join(dir, name);
28858
+ const p = path26.join(dir, name);
27860
28859
  if (fs15.existsSync(p)) {
27861
28860
  const source = fs15.readFileSync(p, "utf-8");
27862
28861
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -27877,8 +28876,8 @@ var DevServer = class _DevServer {
27877
28876
  this.json(res, 404, { error: `Provider not found: ${type}` });
27878
28877
  return;
27879
28878
  }
27880
- const target = fs15.existsSync(path25.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
27881
- const targetPath = path25.join(dir, target);
28879
+ const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28880
+ const targetPath = path26.join(dir, target);
27882
28881
  try {
27883
28882
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
27884
28883
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -28025,7 +29024,7 @@ var DevServer = class _DevServer {
28025
29024
  }
28026
29025
  let targetDir;
28027
29026
  targetDir = this.providerLoader.getUserProviderDir(category, type);
28028
- const jsonPath = path25.join(targetDir, "provider.json");
29027
+ const jsonPath = path26.join(targetDir, "provider.json");
28029
29028
  if (fs15.existsSync(jsonPath)) {
28030
29029
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
28031
29030
  return;
@@ -28037,8 +29036,8 @@ var DevServer = class _DevServer {
28037
29036
  const createdFiles = ["provider.json"];
28038
29037
  if (result.files) {
28039
29038
  for (const [relPath, content] of Object.entries(result.files)) {
28040
- const fullPath = path25.join(targetDir, relPath);
28041
- fs15.mkdirSync(path25.dirname(fullPath), { recursive: true });
29039
+ const fullPath = path26.join(targetDir, relPath);
29040
+ fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
28042
29041
  fs15.writeFileSync(fullPath, content, "utf-8");
28043
29042
  createdFiles.push(relPath);
28044
29043
  }
@@ -28091,22 +29090,22 @@ var DevServer = class _DevServer {
28091
29090
  if (!fs15.existsSync(scriptsDir)) return null;
28092
29091
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
28093
29092
  try {
28094
- return fs15.statSync(path25.join(scriptsDir, d)).isDirectory();
29093
+ return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
28095
29094
  } catch {
28096
29095
  return false;
28097
29096
  }
28098
29097
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
28099
29098
  if (versions.length === 0) return null;
28100
- return path25.join(scriptsDir, versions[0]);
29099
+ return path26.join(scriptsDir, versions[0]);
28101
29100
  }
28102
29101
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
28103
- const canonicalUserDir = path25.resolve(this.providerLoader.getUserProviderDir(category, type));
28104
- const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
28105
- const upstreamRoot = path25.resolve(this.providerLoader.getUpstreamDir());
28106
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
29102
+ const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
29103
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
29104
+ const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
29105
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
28107
29106
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
28108
29107
  }
28109
- if (path25.basename(desiredDir) !== type) {
29108
+ if (path26.basename(desiredDir) !== type) {
28110
29109
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
28111
29110
  }
28112
29111
  const sourceDir = this.findProviderDir(type);
@@ -28114,11 +29113,11 @@ var DevServer = class _DevServer {
28114
29113
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
28115
29114
  }
28116
29115
  if (!fs15.existsSync(desiredDir)) {
28117
- fs15.mkdirSync(path25.dirname(desiredDir), { recursive: true });
29116
+ fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
28118
29117
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
28119
29118
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
28120
29119
  }
28121
- const providerJson = path25.join(desiredDir, "provider.json");
29120
+ const providerJson = path26.join(desiredDir, "provider.json");
28122
29121
  if (!fs15.existsSync(providerJson)) {
28123
29122
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
28124
29123
  }
@@ -28154,7 +29153,7 @@ var DevServer = class _DevServer {
28154
29153
  setMode: "set_mode.js"
28155
29154
  };
28156
29155
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28157
- const scriptsDir = path25.join(providerDir, "scripts");
29156
+ const scriptsDir = path26.join(providerDir, "scripts");
28158
29157
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28159
29158
  if (latestScriptsDir) {
28160
29159
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28165,7 +29164,7 @@ var DevServer = class _DevServer {
28165
29164
  for (const file of fs15.readdirSync(latestScriptsDir)) {
28166
29165
  if (file.endsWith(".js") && targetFileNames.has(file)) {
28167
29166
  try {
28168
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29167
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28169
29168
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28170
29169
  lines.push("```javascript");
28171
29170
  lines.push(content);
@@ -28182,7 +29181,7 @@ var DevServer = class _DevServer {
28182
29181
  lines.push("");
28183
29182
  for (const file of refFiles) {
28184
29183
  try {
28185
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29184
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28186
29185
  lines.push(`### \`${file}\` \u{1F512}`);
28187
29186
  lines.push("```javascript");
28188
29187
  lines.push(content);
@@ -28223,10 +29222,10 @@ var DevServer = class _DevServer {
28223
29222
  lines.push("");
28224
29223
  }
28225
29224
  }
28226
- const docsDir = path25.join(providerDir, "../../docs");
29225
+ const docsDir = path26.join(providerDir, "../../docs");
28227
29226
  const loadGuide = (name) => {
28228
29227
  try {
28229
- const p = path25.join(docsDir, name);
29228
+ const p = path26.join(docsDir, name);
28230
29229
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28231
29230
  } catch {
28232
29231
  }
@@ -28400,7 +29399,7 @@ var DevServer = class _DevServer {
28400
29399
  parseApproval: "parse_approval.js"
28401
29400
  };
28402
29401
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
28403
- const scriptsDir = path25.join(providerDir, "scripts");
29402
+ const scriptsDir = path26.join(providerDir, "scripts");
28404
29403
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
28405
29404
  if (latestScriptsDir) {
28406
29405
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -28412,7 +29411,7 @@ var DevServer = class _DevServer {
28412
29411
  if (!file.endsWith(".js")) continue;
28413
29412
  if (!targetFileNames.has(file)) continue;
28414
29413
  try {
28415
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29414
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28416
29415
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
28417
29416
  lines.push("```javascript");
28418
29417
  lines.push(content);
@@ -28428,7 +29427,7 @@ var DevServer = class _DevServer {
28428
29427
  lines.push("");
28429
29428
  for (const file of refFiles) {
28430
29429
  try {
28431
- const content = fs15.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
29430
+ const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
28432
29431
  lines.push(`### \`${file}\` \u{1F512}`);
28433
29432
  lines.push("```javascript");
28434
29433
  lines.push(content);
@@ -28461,10 +29460,10 @@ var DevServer = class _DevServer {
28461
29460
  lines.push("");
28462
29461
  }
28463
29462
  }
28464
- const docsDir = path25.join(providerDir, "../../docs");
29463
+ const docsDir = path26.join(providerDir, "../../docs");
28465
29464
  const loadGuide = (name) => {
28466
29465
  try {
28467
- const p = path25.join(docsDir, name);
29466
+ const p = path26.join(docsDir, name);
28468
29467
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
28469
29468
  } catch {
28470
29469
  }
@@ -29464,48 +30463,6 @@ var SessionRegistry = class {
29464
30463
  // src/boot/daemon-lifecycle.ts
29465
30464
  init_logger();
29466
30465
  init_config();
29467
-
29468
- // src/mesh/mesh-events.ts
29469
- init_mesh_config();
29470
- init_logger();
29471
- function setupMeshEventForwarding(components) {
29472
- components.instanceManager.onEvent((event) => {
29473
- if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
29474
- const instanceId = event.instanceId;
29475
- if (!instanceId) return;
29476
- const sourceInstance = components.instanceManager.getInstance(instanceId);
29477
- if (!sourceInstance || sourceInstance.category !== "cli") return;
29478
- const state = sourceInstance.getState();
29479
- const workspace = state.workspace;
29480
- if (!workspace) return;
29481
- const mesh = getMeshByRepo(workspace);
29482
- if (!mesh) return;
29483
- const allInstances = components.instanceManager.getByCategory("cli");
29484
- const coordinatorInstances = allInstances.filter((inst) => {
29485
- const instState = inst.getState();
29486
- if (instState.settings?.meshCoordinatorFor !== mesh.id) return false;
29487
- if (instState.instanceId === instanceId) return false;
29488
- return true;
29489
- });
29490
- if (coordinatorInstances.length === 0) return;
29491
- const targetNode = mesh.nodes.find((n) => n.workspace === workspace);
29492
- const nodeLabel = targetNode ? `Node '${targetNode.id}'` : `Agent at ${workspace}`;
29493
- let messageText = "";
29494
- if (event.event === "agent:generating_completed") {
29495
- messageText = `[System] ${nodeLabel} has completed its task and is now idle. You may use mesh_read_chat to review its progress.`;
29496
- } else if (event.event === "agent:waiting_approval") {
29497
- messageText = `[System] ${nodeLabel} is waiting for approval to proceed. You may use mesh_read_chat and mesh_approve to handle it.`;
29498
- }
29499
- if (!messageText) return;
29500
- for (const coord of coordinatorInstances) {
29501
- const coordState = coord.getState();
29502
- LOG.info("MeshEvents", `Forwarding event from ${workspace} to coordinator ${coordState.instanceId}`);
29503
- coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
29504
- }
29505
- });
29506
- }
29507
-
29508
- // src/boot/daemon-lifecycle.ts
29509
30466
  async function initDaemonComponents(config) {
29510
30467
  installGlobalInterceptor();
29511
30468
  const appConfig = loadConfig();
@@ -29812,6 +30769,7 @@ async function shutdownDaemonComponents(components) {
29812
30769
  createGitWorkspaceMonitor,
29813
30770
  createInteractionId,
29814
30771
  createMesh,
30772
+ createWorktree,
29815
30773
  deleteMesh,
29816
30774
  detectAllVersions,
29817
30775
  detectCLIs,
@@ -29864,6 +30822,7 @@ async function shutdownDaemonComponents(components) {
29864
30822
  launchWithCdp,
29865
30823
  listHostedCliRuntimes,
29866
30824
  listMeshes,
30825
+ listWorktrees,
29867
30826
  loadConfig,
29868
30827
  loadState,
29869
30828
  logCommand,
@@ -29883,6 +30842,7 @@ async function shutdownDaemonComponents(components) {
29883
30842
  normalizeSessionModalFields,
29884
30843
  parsePorcelainV2Status,
29885
30844
  parseProviderSourceConfigUpdate,
30845
+ parseWorktreeListOutput,
29886
30846
  partitionSessionHostDiagnosticsSessions,
29887
30847
  partitionSessionHostRecords,
29888
30848
  prepareSessionChatTailUpdate,
@@ -29892,6 +30852,7 @@ async function shutdownDaemonComponents(components) {
29892
30852
  recordDebugTrace,
29893
30853
  registerExtensionProviders,
29894
30854
  removeNode,
30855
+ removeWorktree,
29895
30856
  resetConfig,
29896
30857
  resetDebugRuntimeConfig,
29897
30858
  resetState,
@@ -29901,6 +30862,7 @@ async function shutdownDaemonComponents(components) {
29901
30862
  resolveGitRepository,
29902
30863
  resolveSessionHostAppName,
29903
30864
  resolveSessionHostAppNameResolution,
30865
+ resolveWorktreePath,
29904
30866
  runAsyncBatch,
29905
30867
  runGit,
29906
30868
  saveConfig,