adhdev 0.9.66 → 0.9.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -554,6 +554,22 @@ var init_source = __esm({
554
554
  }
555
555
  });
556
556
 
557
+ // ../../oss/packages/daemon-core/src/repo-mesh-types.ts
558
+ var DEFAULT_MESH_POLICY;
559
+ var init_repo_mesh_types = __esm({
560
+ "../../oss/packages/daemon-core/src/repo-mesh-types.ts"() {
561
+ "use strict";
562
+ DEFAULT_MESH_POLICY = {
563
+ requirePreTaskCheckpoint: false,
564
+ requirePostTaskCheckpoint: true,
565
+ requireApprovalForPush: true,
566
+ requireApprovalForDestructiveGit: true,
567
+ dirtyWorkspaceBehavior: "warn",
568
+ maxParallelTasks: 2
569
+ };
570
+ }
571
+ });
572
+
557
573
  // ../../oss/packages/daemon-core/src/git/git-executor.ts
558
574
  async function resolveGitRepository(workspace, options = {}) {
559
575
  const normalizedWorkspace = await validateWorkspace(workspace);
@@ -2682,12 +2698,326 @@ var init_saved_sessions = __esm({
2682
2698
  }
2683
2699
  });
2684
2700
 
2701
+ // ../../oss/packages/daemon-core/src/config/mesh-config.ts
2702
+ function getMeshConfigPath() {
2703
+ return (0, import_path2.join)(getConfigDir(), "meshes.json");
2704
+ }
2705
+ function loadMeshConfig() {
2706
+ const path40 = getMeshConfigPath();
2707
+ if (!(0, import_fs2.existsSync)(path40)) return { meshes: [] };
2708
+ try {
2709
+ const raw = JSON.parse((0, import_fs2.readFileSync)(path40, "utf-8"));
2710
+ if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
2711
+ return raw;
2712
+ } catch {
2713
+ return { meshes: [] };
2714
+ }
2715
+ }
2716
+ function saveMeshConfig(config2) {
2717
+ const path40 = getMeshConfigPath();
2718
+ (0, import_fs2.writeFileSync)(path40, JSON.stringify(config2, null, 2), { encoding: "utf-8", mode: 384 });
2719
+ }
2720
+ function normalizeRepoIdentity(remoteUrl) {
2721
+ let identity = remoteUrl.trim();
2722
+ if (identity.startsWith("http://") || identity.startsWith("https://")) {
2723
+ try {
2724
+ const url2 = new URL(identity);
2725
+ const path40 = url2.pathname.replace(/^\//, "").replace(/\.git$/, "");
2726
+ return `${url2.hostname}/${path40}`;
2727
+ } catch {
2728
+ }
2729
+ }
2730
+ const sshMatch = identity.match(/^(?:ssh:\/\/)?[\w.-]+@([\w.-]+)[:/]([\w.\-/]+?)(?:\.git)?$/);
2731
+ if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
2732
+ return identity;
2733
+ }
2734
+ function listMeshes() {
2735
+ return loadMeshConfig().meshes;
2736
+ }
2737
+ function getMesh(meshId) {
2738
+ return loadMeshConfig().meshes.find((m) => m.id === meshId);
2739
+ }
2740
+ function getMeshByRepo(repoIdentity) {
2741
+ return loadMeshConfig().meshes.find((m) => m.repoIdentity === repoIdentity);
2742
+ }
2743
+ function createMesh(opts) {
2744
+ const config2 = loadMeshConfig();
2745
+ if (config2.meshes.length >= 20) {
2746
+ throw new Error("Maximum 20 meshes allowed");
2747
+ }
2748
+ const repoIdentity = opts.repoIdentity || (opts.repoRemoteUrl ? normalizeRepoIdentity(opts.repoRemoteUrl) : "");
2749
+ if (!repoIdentity) throw new Error("Either repoRemoteUrl or repoIdentity is required");
2750
+ const now = (/* @__PURE__ */ new Date()).toISOString();
2751
+ const mesh = {
2752
+ id: `mesh_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
2753
+ name: opts.name.trim().slice(0, 100),
2754
+ repoIdentity,
2755
+ repoRemoteUrl: opts.repoRemoteUrl,
2756
+ defaultBranch: opts.defaultBranch,
2757
+ policy: { ...DEFAULT_MESH_POLICY, ...opts.policy },
2758
+ coordinator: opts.coordinator || {},
2759
+ nodes: [],
2760
+ createdAt: now,
2761
+ updatedAt: now
2762
+ };
2763
+ config2.meshes.push(mesh);
2764
+ saveMeshConfig(config2);
2765
+ return mesh;
2766
+ }
2767
+ function updateMesh(meshId, opts) {
2768
+ const config2 = loadMeshConfig();
2769
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2770
+ if (!mesh) return void 0;
2771
+ if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
2772
+ if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
2773
+ if (opts.policy) mesh.policy = { ...mesh.policy, ...opts.policy };
2774
+ if (opts.coordinator) mesh.coordinator = opts.coordinator;
2775
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2776
+ saveMeshConfig(config2);
2777
+ return mesh;
2778
+ }
2779
+ function deleteMesh(meshId) {
2780
+ const config2 = loadMeshConfig();
2781
+ const idx = config2.meshes.findIndex((m) => m.id === meshId);
2782
+ if (idx === -1) return false;
2783
+ config2.meshes.splice(idx, 1);
2784
+ saveMeshConfig(config2);
2785
+ return true;
2786
+ }
2787
+ function addNode(meshId, opts) {
2788
+ const config2 = loadMeshConfig();
2789
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2790
+ if (!mesh) return void 0;
2791
+ if (mesh.nodes.length >= 10) {
2792
+ throw new Error("Maximum 10 nodes per mesh");
2793
+ }
2794
+ if (mesh.nodes.some((n) => n.workspace === opts.workspace)) {
2795
+ throw new Error("This workspace is already in the mesh");
2796
+ }
2797
+ const node = {
2798
+ id: `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
2799
+ workspace: opts.workspace.trim(),
2800
+ repoRoot: opts.repoRoot,
2801
+ userOverrides: opts.userOverrides || {},
2802
+ policy: opts.policy || {},
2803
+ isLocalWorktree: opts.isLocalWorktree
2804
+ };
2805
+ mesh.nodes.push(node);
2806
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2807
+ saveMeshConfig(config2);
2808
+ return node;
2809
+ }
2810
+ function removeNode(meshId, nodeId) {
2811
+ const config2 = loadMeshConfig();
2812
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2813
+ if (!mesh) return false;
2814
+ const idx = mesh.nodes.findIndex((n) => n.id === nodeId);
2815
+ if (idx === -1) return false;
2816
+ mesh.nodes.splice(idx, 1);
2817
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2818
+ saveMeshConfig(config2);
2819
+ return true;
2820
+ }
2821
+ function updateNode(meshId, nodeId, opts) {
2822
+ const config2 = loadMeshConfig();
2823
+ const mesh = config2.meshes.find((m) => m.id === meshId);
2824
+ if (!mesh) return void 0;
2825
+ const node = mesh.nodes.find((n) => n.id === nodeId);
2826
+ if (!node) return void 0;
2827
+ if (opts.userOverrides) node.userOverrides = { ...node.userOverrides, ...opts.userOverrides };
2828
+ if (opts.policy) node.policy = { ...node.policy, ...opts.policy };
2829
+ mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
2830
+ saveMeshConfig(config2);
2831
+ return node;
2832
+ }
2833
+ var import_fs2, import_path2, import_crypto3;
2834
+ var init_mesh_config = __esm({
2835
+ "../../oss/packages/daemon-core/src/config/mesh-config.ts"() {
2836
+ "use strict";
2837
+ import_fs2 = require("fs");
2838
+ import_path2 = require("path");
2839
+ import_crypto3 = require("crypto");
2840
+ init_config();
2841
+ init_repo_mesh_types();
2842
+ }
2843
+ });
2844
+
2845
+ // ../../oss/packages/daemon-core/src/mesh/coordinator-prompt.ts
2846
+ function buildCoordinatorSystemPrompt(ctx) {
2847
+ const { mesh, status, userInstruction } = ctx;
2848
+ const sections = [];
2849
+ 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.
2850
+
2851
+ Your mesh: **${mesh.name}**
2852
+ Repository: \`${mesh.repoIdentity}\`${mesh.defaultBranch ? `
2853
+ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
2854
+ if (status?.nodes?.length) {
2855
+ sections.push(buildNodeStatusSection(status.nodes));
2856
+ } else if (mesh.nodes.length) {
2857
+ sections.push(buildNodeConfigSection(mesh));
2858
+ } else {
2859
+ sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
2860
+ }
2861
+ sections.push(buildPolicySection(mesh.policy));
2862
+ sections.push(TOOLS_SECTION);
2863
+ sections.push(WORKFLOW_SECTION);
2864
+ sections.push(RULES_SECTION);
2865
+ if (userInstruction) {
2866
+ sections.push(`## Additional Context
2867
+ ${userInstruction}`);
2868
+ }
2869
+ if (mesh.coordinator.systemPromptSuffix) {
2870
+ sections.push(mesh.coordinator.systemPromptSuffix);
2871
+ }
2872
+ return sections.join("\n\n");
2873
+ }
2874
+ function buildNodeStatusSection(nodes) {
2875
+ const lines = ["## Current Node Status", ""];
2876
+ for (const n of nodes) {
2877
+ const healthIcon = n.health === "online" ? "\u{1F7E2}" : n.health === "dirty" ? "\u{1F7E1}" : n.health === "offline" ? "\u26AB" : "\u{1F534}";
2878
+ const sessions = n.activeSessions.length > 0 ? `sessions: ${n.activeSessions.join(", ")}` : "no active sessions";
2879
+ const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : "";
2880
+ lines.push(`- ${healthIcon} **${n.machineLabel}** (${n.nodeId})`);
2881
+ lines.push(` workspace: \`${n.workspace}\` | ${branch} | ${sessions}`);
2882
+ if (n.error) lines.push(` \u26A0\uFE0F ${n.error}`);
2883
+ }
2884
+ return lines.join("\n");
2885
+ }
2886
+ function buildNodeConfigSection(mesh) {
2887
+ const lines = ["## Configured Nodes", ""];
2888
+ for (const n of mesh.nodes) {
2889
+ const labels = [];
2890
+ if (n.isLocalWorktree) labels.push("worktree");
2891
+ if (n.policy.readOnly) labels.push("read-only");
2892
+ const suffix = labels.length ? ` [${labels.join(", ")}]` : "";
2893
+ lines.push(`- **${n.workspace}** (${n.id})${suffix}`);
2894
+ }
2895
+ lines.push("", "_Use `mesh_status` to probe live health before delegating work._");
2896
+ return lines.join("\n");
2897
+ }
2898
+ function buildPolicySection(policy) {
2899
+ const rules = [];
2900
+ if (policy.requirePreTaskCheckpoint) rules.push("- Create a git checkpoint **before** starting each task");
2901
+ if (policy.requirePostTaskCheckpoint) rules.push("- Create a git checkpoint **after** each task completes");
2902
+ if (policy.requireApprovalForPush) rules.push("- **Ask for user approval** before pushing to remote");
2903
+ if (policy.requireApprovalForDestructiveGit) rules.push("- **Ask for user approval** before destructive git operations (force push, reset, etc.)");
2904
+ const dirtyBehavior = {
2905
+ block: "- **Do not** send tasks to nodes with dirty workspaces",
2906
+ warn: "- Warn the user if a node has uncommitted changes before sending a task",
2907
+ checkpoint_then_continue: "- Auto-checkpoint dirty nodes before sending tasks"
2908
+ }[policy.dirtyWorkspaceBehavior] || "";
2909
+ if (dirtyBehavior) rules.push(dirtyBehavior);
2910
+ rules.push(`- Maximum **${policy.maxParallelTasks}** tasks running in parallel`);
2911
+ return `## Policy
2912
+ ${rules.join("\n")}`;
2913
+ }
2914
+ var TOOLS_SECTION, WORKFLOW_SECTION, RULES_SECTION;
2915
+ var init_coordinator_prompt = __esm({
2916
+ "../../oss/packages/daemon-core/src/mesh/coordinator-prompt.ts"() {
2917
+ "use strict";
2918
+ TOOLS_SECTION = `## Available Tools
2919
+
2920
+ | Tool | Purpose |
2921
+ |------|---------|
2922
+ | \`mesh_status\` | Check all nodes' health, git state, and active sessions |
2923
+ | \`mesh_list_nodes\` | List nodes with workspace paths |
2924
+ | \`mesh_launch_session\` | Start a new agent session on a node |
2925
+ | \`mesh_send_task\` | Send a task (natural language) to a running agent |
2926
+ | \`mesh_read_chat\` | Read an agent's recent messages to check progress |
2927
+ | \`mesh_git_status\` | Check git status on a specific node |
2928
+ | \`mesh_checkpoint\` | Create a git checkpoint on a node |
2929
+ | \`mesh_approve\` | Approve/reject a pending agent action |`;
2930
+ WORKFLOW_SECTION = `## Orchestration Workflow
2931
+
2932
+ 1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
2933
+ 2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
2934
+ 3. **Delegate** \u2014 For each task:
2935
+ a. Pick the best node (consider: health, dirty state, current workload).
2936
+ b. If no session exists, call \`mesh_launch_session\` to start one.
2937
+ c. Call \`mesh_send_task\` with a clear, self-contained natural-language instruction.
2938
+ 4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
2939
+ 5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
2940
+ 6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
2941
+ 7. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
2942
+ RULES_SECTION = `## Rules
2943
+
2944
+ - **Be conversational.** Delegate work the way a tech lead would \u2014 clear, specific instructions in natural language.
2945
+ - **Don't inspect code.** Trust the agent's output. Verify via git diff/status, not by reading source files.
2946
+ - **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
2947
+ - **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
2948
+ - **Keep the user informed.** Report progress after each delegation round.
2949
+ - **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
2950
+ - **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
2951
+ }
2952
+ });
2953
+
2954
+ // ../../oss/packages/daemon-core/src/mesh/mesh-sync.ts
2955
+ async function syncMeshes(transport) {
2956
+ const result = { pushed: 0, pulled: 0, deleted: 0, errors: [] };
2957
+ let remoteMeshes;
2958
+ try {
2959
+ const res = await transport.listRemoteMeshes();
2960
+ remoteMeshes = res.meshes;
2961
+ } catch (e) {
2962
+ result.errors.push(`Failed to list remote meshes: ${e.message}`);
2963
+ return result;
2964
+ }
2965
+ const localMeshes = listMeshes();
2966
+ const remoteByIdentity = new Map(remoteMeshes.map((m) => [m.repo_identity, m]));
2967
+ const localByIdentity = new Map(localMeshes.map((m) => [m.repoIdentity, m]));
2968
+ for (const local of localMeshes) {
2969
+ if (!remoteByIdentity.has(local.repoIdentity)) {
2970
+ try {
2971
+ await transport.createRemoteMesh({
2972
+ name: local.name,
2973
+ repo_identity: local.repoIdentity,
2974
+ repo_remote_url: local.repoRemoteUrl,
2975
+ default_branch: local.defaultBranch,
2976
+ policy: JSON.stringify(local.policy)
2977
+ });
2978
+ result.pushed++;
2979
+ } catch (e) {
2980
+ result.errors.push(`Push failed for "${local.name}": ${e.message}`);
2981
+ }
2982
+ }
2983
+ }
2984
+ for (const remote of remoteMeshes) {
2985
+ if (!localByIdentity.has(remote.repo_identity)) {
2986
+ try {
2987
+ let policy;
2988
+ try {
2989
+ policy = JSON.parse(remote.policy);
2990
+ } catch {
2991
+ policy = void 0;
2992
+ }
2993
+ createMesh({
2994
+ name: remote.name,
2995
+ repoIdentity: remote.repo_identity,
2996
+ repoRemoteUrl: remote.repo_remote_url || void 0,
2997
+ defaultBranch: remote.default_branch || void 0,
2998
+ policy
2999
+ });
3000
+ result.pulled++;
3001
+ } catch (e) {
3002
+ result.errors.push(`Pull failed for "${remote.name}": ${e.message}`);
3003
+ }
3004
+ }
3005
+ }
3006
+ return result;
3007
+ }
3008
+ var init_mesh_sync = __esm({
3009
+ "../../oss/packages/daemon-core/src/mesh/mesh-sync.ts"() {
3010
+ "use strict";
3011
+ init_mesh_config();
3012
+ }
3013
+ });
3014
+
2685
3015
  // ../../oss/packages/daemon-core/src/config/state-store.ts
2686
3016
  function isPlainObject2(value) {
2687
3017
  return !!value && typeof value === "object" && !Array.isArray(value);
2688
3018
  }
2689
3019
  function getStatePath() {
2690
- return (0, import_path2.join)(getConfigDir(), "state.json");
3020
+ return (0, import_path3.join)(getConfigDir(), "state.json");
2691
3021
  }
2692
3022
  function normalizeState(raw) {
2693
3023
  const parsed = isPlainObject2(raw) ? raw : {};
@@ -2723,11 +3053,11 @@ function normalizeState(raw) {
2723
3053
  }
2724
3054
  function loadState() {
2725
3055
  const statePath = getStatePath();
2726
- if (!(0, import_fs2.existsSync)(statePath)) {
3056
+ if (!(0, import_fs3.existsSync)(statePath)) {
2727
3057
  return { ...DEFAULT_STATE };
2728
3058
  }
2729
3059
  try {
2730
- const raw = (0, import_fs2.readFileSync)(statePath, "utf-8");
3060
+ const raw = (0, import_fs3.readFileSync)(statePath, "utf-8");
2731
3061
  return normalizeState(JSON.parse(raw));
2732
3062
  } catch {
2733
3063
  return { ...DEFAULT_STATE };
@@ -2736,17 +3066,17 @@ function loadState() {
2736
3066
  function saveState(state) {
2737
3067
  const statePath = getStatePath();
2738
3068
  const normalized = normalizeState(state);
2739
- (0, import_fs2.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
3069
+ (0, import_fs3.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
2740
3070
  }
2741
3071
  function resetState() {
2742
3072
  saveState({ ...DEFAULT_STATE });
2743
3073
  }
2744
- var import_fs2, import_path2, DEFAULT_STATE;
3074
+ var import_fs3, import_path3, DEFAULT_STATE;
2745
3075
  var init_state_store = __esm({
2746
3076
  "../../oss/packages/daemon-core/src/config/state-store.ts"() {
2747
3077
  "use strict";
2748
- import_fs2 = require("fs");
2749
- import_path2 = require("path");
3078
+ import_fs3 = require("fs");
3079
+ import_path3 = require("path");
2750
3080
  init_config();
2751
3081
  DEFAULT_STATE = {
2752
3082
  recentActivity: [],
@@ -2779,7 +3109,7 @@ function findCliCommand(command) {
2779
3109
  if (path7.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
2780
3110
  const candidate = trimmed.startsWith("~") ? path7.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
2781
3111
  const resolved = path7.isAbsolute(candidate) ? candidate : path7.resolve(candidate);
2782
- return (0, import_fs3.existsSync)(resolved) ? resolved : null;
3112
+ return (0, import_fs4.existsSync)(resolved) ? resolved : null;
2783
3113
  }
2784
3114
  try {
2785
3115
  const result = (0, import_child_process.execSync)(
@@ -2810,9 +3140,9 @@ function checkPathExists(paths) {
2810
3140
  if (normalized.includes("*")) {
2811
3141
  const username = home.split(/[\\/]/).pop() || "";
2812
3142
  const resolved = normalized.replace("*", username);
2813
- if ((0, import_fs3.existsSync)(resolved)) return resolved;
3143
+ if ((0, import_fs4.existsSync)(resolved)) return resolved;
2814
3144
  } else {
2815
- if ((0, import_fs3.existsSync)(normalized)) return normalized;
3145
+ if ((0, import_fs4.existsSync)(normalized)) return normalized;
2816
3146
  }
2817
3147
  }
2818
3148
  return null;
@@ -2826,7 +3156,7 @@ async function detectIDEs(providerLoader) {
2826
3156
  let resolvedCli = cliPath;
2827
3157
  if (!resolvedCli && appPath && os31 === "darwin") {
2828
3158
  const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
2829
- if ((0, import_fs3.existsSync)(bundledCli)) resolvedCli = bundledCli;
3159
+ if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
2830
3160
  }
2831
3161
  if (!resolvedCli && appPath && os31 === "win32") {
2832
3162
  const { dirname: dirname11 } = await import("path");
@@ -2839,7 +3169,7 @@ async function detectIDEs(providerLoader) {
2839
3169
  `${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
2840
3170
  ];
2841
3171
  for (const c of candidates) {
2842
- if ((0, import_fs3.existsSync)(c)) {
3172
+ if ((0, import_fs4.existsSync)(c)) {
2843
3173
  resolvedCli = c;
2844
3174
  break;
2845
3175
  }
@@ -2860,12 +3190,12 @@ async function detectIDEs(providerLoader) {
2860
3190
  }
2861
3191
  return results;
2862
3192
  }
2863
- var import_child_process, import_fs3, import_os2, path7, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
3193
+ var import_child_process, import_fs4, import_os2, path7, BUILTIN_IDE_DEFINITIONS, registeredIDEs;
2864
3194
  var init_ide_detector = __esm({
2865
3195
  "../../oss/packages/daemon-core/src/detection/ide-detector.ts"() {
2866
3196
  "use strict";
2867
3197
  import_child_process = require("child_process");
2868
- import_fs3 = require("fs");
3198
+ import_fs4 = require("fs");
2869
3199
  import_os2 = require("os");
2870
3200
  path7 = __toESM(require("path"));
2871
3201
  BUILTIN_IDE_DEFINITIONS = [];
@@ -2897,7 +3227,7 @@ function resolveCommandPath(command) {
2897
3227
  if (isExplicitCommandPath(trimmed)) {
2898
3228
  const expanded = expandHome(trimmed);
2899
3229
  const candidate = path8.isAbsolute(expanded) ? expanded : path8.resolve(expanded);
2900
- return (0, import_fs4.existsSync)(candidate) ? candidate : null;
3230
+ return (0, import_fs5.existsSync)(candidate) ? candidate : null;
2901
3231
  }
2902
3232
  return null;
2903
3233
  }
@@ -2997,14 +3327,14 @@ async function detectCLI(cliId, providerLoader, options) {
2997
3327
  const all = await detectCLIs(providerLoader, options);
2998
3328
  return all.find((c) => c.id === resolvedId && c.installed) || null;
2999
3329
  }
3000
- var import_child_process2, os3, path8, import_fs4;
3330
+ var import_child_process2, os3, path8, import_fs5;
3001
3331
  var init_cli_detector = __esm({
3002
3332
  "../../oss/packages/daemon-core/src/detection/cli-detector.ts"() {
3003
3333
  "use strict";
3004
3334
  import_child_process2 = require("child_process");
3005
3335
  os3 = __toESM(require("os"));
3006
3336
  path8 = __toESM(require("path"));
3007
- import_fs4 = require("fs");
3337
+ import_fs5 = require("fs");
3008
3338
  }
3009
3339
  });
3010
3340
 
@@ -13173,16 +13503,16 @@ function ensureNodePtySpawnHelperPermissions(logFn) {
13173
13503
  } catch {
13174
13504
  }
13175
13505
  }
13176
- var import_crypto3, path13, os10, path22, net, import_crypto4, os22, path32, __require, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, SessionRingBuffer, DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS, LIVE_LIFECYCLES2, SessionHostRegistry, SessionHostClient;
13506
+ var import_crypto4, path13, os10, path22, net, import_crypto5, os22, path32, __require, DEFAULT_SESSION_RING_BUFFER_MAX_BYTES, SessionRingBuffer, DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS, LIVE_LIFECYCLES2, SessionHostRegistry, SessionHostClient;
13177
13507
  var init_dist = __esm({
13178
13508
  "../../oss/packages/session-host-core/dist/index.mjs"() {
13179
13509
  "use strict";
13180
- import_crypto3 = require("crypto");
13510
+ import_crypto4 = require("crypto");
13181
13511
  path13 = __toESM(require("path"), 1);
13182
13512
  os10 = __toESM(require("os"), 1);
13183
13513
  path22 = __toESM(require("path"), 1);
13184
13514
  net = __toESM(require("net"), 1);
13185
- import_crypto4 = require("crypto");
13515
+ import_crypto5 = require("crypto");
13186
13516
  os22 = __toESM(require("os"), 1);
13187
13517
  path32 = __toESM(require("path"), 1);
13188
13518
  __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
@@ -13258,7 +13588,7 @@ var init_dist = __esm({
13258
13588
  SessionHostRegistry = class {
13259
13589
  sessions = /* @__PURE__ */ new Map();
13260
13590
  createSession(payload) {
13261
- const sessionId = payload.sessionId || (0, import_crypto3.randomUUID)();
13591
+ const sessionId = payload.sessionId || (0, import_crypto4.randomUUID)();
13262
13592
  if (this.sessions.has(sessionId)) {
13263
13593
  throw new Error(`Session already exists: ${sessionId}`);
13264
13594
  }
@@ -13529,7 +13859,7 @@ var init_dist = __esm({
13529
13859
  async request(request) {
13530
13860
  await this.connect();
13531
13861
  if (!this.socket) throw new Error("Session host socket unavailable");
13532
- const requestId = (0, import_crypto4.randomUUID)();
13862
+ const requestId = (0, import_crypto5.randomUUID)();
13533
13863
  const envelope = {
13534
13864
  kind: "request",
13535
13865
  requestId,
@@ -34565,7 +34895,7 @@ function commandExists(command) {
34565
34895
  const trimmed = command.trim();
34566
34896
  if (!trimmed) return false;
34567
34897
  if (isExplicitCommand(trimmed)) {
34568
- return (0, import_fs5.existsSync)(expandExecutable(trimmed));
34898
+ return (0, import_fs6.existsSync)(expandExecutable(trimmed));
34569
34899
  }
34570
34900
  try {
34571
34901
  (0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
@@ -34696,14 +35026,14 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
34696
35026
  launchMode: "new"
34697
35027
  };
34698
35028
  }
34699
- var os16, path17, crypto4, import_fs5, import_child_process6, chalkModule, chalkApi, DaemonCliManager;
35029
+ var os16, path17, crypto4, import_fs6, import_child_process6, chalkModule, chalkApi, DaemonCliManager;
34700
35030
  var init_cli_manager = __esm({
34701
35031
  "../../oss/packages/daemon-core/src/commands/cli-manager.ts"() {
34702
35032
  "use strict";
34703
35033
  os16 = __toESM(require("os"));
34704
35034
  path17 = __toESM(require("path"));
34705
35035
  crypto4 = __toESM(require("crypto"));
34706
- import_fs5 = require("fs");
35036
+ import_fs6 = require("fs");
34707
35037
  import_child_process6 = require("child_process");
34708
35038
  init_source2();
34709
35039
  init_provider_cli_adapter();
@@ -38271,7 +38601,7 @@ var init_provider_loader = __esm({
38271
38601
  return { updated: false };
38272
38602
  }
38273
38603
  const https = require("https");
38274
- const { execSync: execSync8 } = require("child_process");
38604
+ const { execSync: execSync9 } = require("child_process");
38275
38605
  const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
38276
38606
  let prevEtag = "";
38277
38607
  let prevTimestamp = 0;
@@ -38336,7 +38666,7 @@ var init_provider_loader = __esm({
38336
38666
  const tmpExtract = path18.join(os17.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
38337
38667
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
38338
38668
  fs7.mkdirSync(tmpExtract, { recursive: true });
38339
- execSync8(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
38669
+ execSync9(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
38340
38670
  const extracted = fs7.readdirSync(tmpExtract);
38341
38671
  const rootDir = extracted.find(
38342
38672
  (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
@@ -49059,6 +49389,7 @@ __export(src_exports, {
49059
49389
  DEFAULT_DAEMON_PORT: () => DEFAULT_DAEMON_PORT,
49060
49390
  DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS: () => DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS,
49061
49391
  DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS,
49392
+ DEFAULT_MESH_POLICY: () => DEFAULT_MESH_POLICY,
49062
49393
  DEFAULT_SESSION_HOST_APP_NAME: () => DEFAULT_SESSION_HOST_APP_NAME,
49063
49394
  DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS: () => DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS,
49064
49395
  DEFAULT_SESSION_HOST_READY_TIMEOUT_MS: () => DEFAULT_SESSION_HOST_READY_TIMEOUT_MS,
@@ -49092,11 +49423,13 @@ __export(src_exports, {
49092
49423
  SessionHostPtyTransportFactory: () => SessionHostPtyTransportFactory,
49093
49424
  TurnSnapshotTracker: () => TurnSnapshotTracker,
49094
49425
  VersionArchive: () => VersionArchive,
49426
+ addNode: () => addNode,
49095
49427
  appendRecentActivity: () => appendRecentActivity,
49096
49428
  buildAssistantChatMessage: () => buildAssistantChatMessage,
49097
49429
  buildChatMessage: () => buildChatMessage,
49098
49430
  buildChatMessageSignature: () => buildChatMessageSignature,
49099
49431
  buildChatTailDeliverySignature: () => buildChatTailDeliverySignature,
49432
+ buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt,
49100
49433
  buildMachineInfo: () => buildMachineInfo,
49101
49434
  buildPinnedGlobalInstallCommand: () => buildPinnedGlobalInstallCommand,
49102
49435
  buildRuntimeSystemChatMessage: () => buildRuntimeSystemChatMessage,
@@ -49119,6 +49452,8 @@ __export(src_exports, {
49119
49452
  createGitSnapshotStore: () => createGitSnapshotStore,
49120
49453
  createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
49121
49454
  createInteractionId: () => createInteractionId,
49455
+ createMesh: () => createMesh,
49456
+ deleteMesh: () => deleteMesh,
49122
49457
  detectAllVersions: () => detectAllVersions,
49123
49458
  detectCLIs: () => detectCLIs,
49124
49459
  detectIDEs: () => detectIDEs,
@@ -49137,6 +49472,8 @@ __export(src_exports, {
49137
49472
  getGitRepoStatus: () => getGitRepoStatus,
49138
49473
  getHostMemorySnapshot: () => getHostMemorySnapshot,
49139
49474
  getLogLevel: () => getLogLevel,
49475
+ getMesh: () => getMesh,
49476
+ getMeshByRepo: () => getMeshByRepo,
49140
49477
  getNpmExecOptions: () => getNpmExecOptions,
49141
49478
  getRecentActivity: () => getRecentActivity,
49142
49479
  getRecentCommands: () => getRecentCommands,
@@ -49167,6 +49504,7 @@ __export(src_exports, {
49167
49504
  launchIDE: () => launchIDE,
49168
49505
  launchWithCdp: () => launchWithCdp,
49169
49506
  listHostedCliRuntimes: () => listHostedCliRuntimes,
49507
+ listMeshes: () => listMeshes,
49170
49508
  loadConfig: () => loadConfig,
49171
49509
  loadState: () => loadState,
49172
49510
  logCommand: () => logCommand,
@@ -49182,6 +49520,7 @@ __export(src_exports, {
49182
49520
  normalizeInputEnvelope: () => normalizeInputEnvelope,
49183
49521
  normalizeManagedStatus: () => normalizeManagedStatus,
49184
49522
  normalizeMessageParts: () => normalizeMessageParts,
49523
+ normalizeRepoIdentity: () => normalizeRepoIdentity,
49185
49524
  normalizeSessionModalFields: () => normalizeSessionModalFields,
49186
49525
  parsePorcelainV2Status: () => parsePorcelainV2Status,
49187
49526
  parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
@@ -49193,6 +49532,7 @@ __export(src_exports, {
49193
49532
  readChatHistory: () => readChatHistory,
49194
49533
  recordDebugTrace: () => recordDebugTrace,
49195
49534
  registerExtensionProviders: () => registerExtensionProviders,
49535
+ removeNode: () => removeNode,
49196
49536
  resetConfig: () => resetConfig,
49197
49537
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
49198
49538
  resetState: () => resetState,
@@ -49215,17 +49555,24 @@ __export(src_exports, {
49215
49555
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
49216
49556
  startDaemonDevSupport: () => startDaemonDevSupport,
49217
49557
  summarizeGitStatus: () => summarizeGitStatus,
49558
+ syncMeshes: () => syncMeshes,
49218
49559
  updateConfig: () => updateConfig,
49560
+ updateMesh: () => updateMesh,
49561
+ updateNode: () => updateNode,
49219
49562
  upsertSavedProviderSession: () => upsertSavedProviderSession
49220
49563
  });
49221
49564
  var init_src = __esm({
49222
49565
  "../../oss/packages/daemon-core/src/index.ts"() {
49223
49566
  "use strict";
49567
+ init_repo_mesh_types();
49224
49568
  init_git();
49225
49569
  init_config();
49226
49570
  init_workspaces();
49227
49571
  init_recent_activity();
49228
49572
  init_saved_sessions();
49573
+ init_mesh_config();
49574
+ init_coordinator_prompt();
49575
+ init_mesh_sync();
49229
49576
  init_state_store();
49230
49577
  init_ide_detector();
49231
49578
  init_cli_detector();
@@ -64071,7 +64418,7 @@ var require_buffer_list = __commonJS({
64071
64418
  }
64072
64419
  }, {
64073
64420
  key: "join",
64074
- value: function join34(s) {
64421
+ value: function join35(s) {
64075
64422
  if (this.length === 0) return "";
64076
64423
  var p = this.head;
64077
64424
  var ret = "" + p.data;
@@ -78130,13 +78477,13 @@ function splitStringBySpace(str) {
78130
78477
  }
78131
78478
  return pieces;
78132
78479
  }
78133
- var import_chardet, import_child_process12, import_fs6, import_node_path2, import_node_os4, import_node_crypto2, import_iconv_lite, ExternalEditor;
78480
+ var import_chardet, import_child_process12, import_fs7, import_node_path2, import_node_os4, import_node_crypto2, import_iconv_lite, ExternalEditor;
78134
78481
  var init_esm2 = __esm({
78135
78482
  "../../node_modules/@inquirer/external-editor/dist/esm/index.js"() {
78136
78483
  "use strict";
78137
78484
  import_chardet = __toESM(require_lib(), 1);
78138
78485
  import_child_process12 = require("child_process");
78139
- import_fs6 = require("fs");
78486
+ import_fs7 = require("fs");
78140
78487
  import_node_path2 = __toESM(require("path"), 1);
78141
78488
  import_node_os4 = __toESM(require("os"), 1);
78142
78489
  import_node_crypto2 = require("crypto");
@@ -78212,14 +78559,14 @@ var init_esm2 = __esm({
78212
78559
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
78213
78560
  opt.mode = this.fileOptions.mode;
78214
78561
  }
78215
- (0, import_fs6.writeFileSync)(this.tempFile, this.text, opt);
78562
+ (0, import_fs7.writeFileSync)(this.tempFile, this.text, opt);
78216
78563
  } catch (createFileError) {
78217
78564
  throw new CreateFileError(createFileError);
78218
78565
  }
78219
78566
  }
78220
78567
  readTemporaryFile() {
78221
78568
  try {
78222
- const tempFileBuffer = (0, import_fs6.readFileSync)(this.tempFile);
78569
+ const tempFileBuffer = (0, import_fs7.readFileSync)(this.tempFile);
78223
78570
  if (tempFileBuffer.length === 0) {
78224
78571
  this.text = "";
78225
78572
  } else {
@@ -78235,7 +78582,7 @@ var init_esm2 = __esm({
78235
78582
  }
78236
78583
  removeTemporaryFile() {
78237
78584
  try {
78238
- (0, import_fs6.unlinkSync)(this.tempFile);
78585
+ (0, import_fs7.unlinkSync)(this.tempFile);
78239
78586
  } catch (removeFileError) {
78240
78587
  throw new RemoveFileError(removeFileError);
78241
78588
  }
@@ -79937,25 +80284,25 @@ function resolvePackageVersion(options) {
79937
80284
  const injectedVersion = options?.injectedVersion || "unknown";
79938
80285
  const dir = options?.dirname || __dirname;
79939
80286
  const possiblePaths = [
79940
- (0, import_path3.join)(dir, "..", "..", "package.json"),
79941
- (0, import_path3.join)(dir, "..", "package.json"),
79942
- (0, import_path3.join)(dir, "package.json")
80287
+ (0, import_path4.join)(dir, "..", "..", "package.json"),
80288
+ (0, import_path4.join)(dir, "..", "package.json"),
80289
+ (0, import_path4.join)(dir, "package.json")
79943
80290
  ];
79944
80291
  for (const p of possiblePaths) {
79945
80292
  try {
79946
- const data = JSON.parse((0, import_fs7.readFileSync)(p, "utf-8"));
80293
+ const data = JSON.parse((0, import_fs8.readFileSync)(p, "utf-8"));
79947
80294
  if (data.version) return data.version;
79948
80295
  } catch {
79949
80296
  }
79950
80297
  }
79951
80298
  return injectedVersion;
79952
80299
  }
79953
- var import_fs7, import_path3;
80300
+ var import_fs8, import_path4;
79954
80301
  var init_version = __esm({
79955
80302
  "src/version.ts"() {
79956
80303
  "use strict";
79957
- import_fs7 = require("fs");
79958
- import_path3 = require("path");
80304
+ import_fs8 = require("fs");
80305
+ import_path4 = require("path");
79959
80306
  }
79960
80307
  });
79961
80308
 
@@ -81873,7 +82220,7 @@ var require_filesystem = __commonJS({
81873
82220
  var LDD_PATH = "/usr/bin/ldd";
81874
82221
  var SELF_PATH = "/proc/self/exe";
81875
82222
  var MAX_LENGTH = 2048;
81876
- var readFileSync20 = (path40) => {
82223
+ var readFileSync21 = (path40) => {
81877
82224
  const fd = fs24.openSync(path40, "r");
81878
82225
  const buffer = Buffer.alloc(MAX_LENGTH);
81879
82226
  const bytesRead = fs24.readSync(fd, buffer, 0, MAX_LENGTH, 0);
@@ -81898,7 +82245,7 @@ var require_filesystem = __commonJS({
81898
82245
  module2.exports = {
81899
82246
  LDD_PATH,
81900
82247
  SELF_PATH,
81901
- readFileSync: readFileSync20,
82248
+ readFileSync: readFileSync21,
81902
82249
  readFile: readFile2
81903
82250
  };
81904
82251
  }
@@ -81947,7 +82294,7 @@ var require_detect_libc = __commonJS({
81947
82294
  "use strict";
81948
82295
  var childProcess = require("child_process");
81949
82296
  var { isLinux: isLinux2, getReport } = require_process();
81950
- var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync20 } = require_filesystem();
82297
+ var { LDD_PATH, SELF_PATH, readFile: readFile2, readFileSync: readFileSync21 } = require_filesystem();
81951
82298
  var { interpreterPath } = require_elf();
81952
82299
  var cachedFamilyInterpreter;
81953
82300
  var cachedFamilyFilesystem;
@@ -82039,7 +82386,7 @@ var require_detect_libc = __commonJS({
82039
82386
  }
82040
82387
  cachedFamilyFilesystem = null;
82041
82388
  try {
82042
- const lddContent = readFileSync20(LDD_PATH);
82389
+ const lddContent = readFileSync21(LDD_PATH);
82043
82390
  cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
82044
82391
  } catch (e) {
82045
82392
  }
@@ -82064,7 +82411,7 @@ var require_detect_libc = __commonJS({
82064
82411
  }
82065
82412
  cachedFamilyInterpreter = null;
82066
82413
  try {
82067
- const selfContent = readFileSync20(SELF_PATH);
82414
+ const selfContent = readFileSync21(SELF_PATH);
82068
82415
  const path40 = interpreterPath(selfContent);
82069
82416
  cachedFamilyInterpreter = familyFromInterpreterPath(path40);
82070
82417
  } catch (e) {
@@ -82128,7 +82475,7 @@ var require_detect_libc = __commonJS({
82128
82475
  }
82129
82476
  cachedVersionFilesystem = null;
82130
82477
  try {
82131
- const lddContent = readFileSync20(LDD_PATH);
82478
+ const lddContent = readFileSync21(LDD_PATH);
82132
82479
  const versionMatch = lddContent.match(RE_GLIBC_VERSION);
82133
82480
  if (versionMatch) {
82134
82481
  cachedVersionFilesystem = versionMatch[1];
@@ -89392,7 +89739,7 @@ var init_adhdev_daemon = __esm({
89392
89739
  init_version();
89393
89740
  init_src();
89394
89741
  init_runtime_defaults();
89395
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.66" });
89742
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.67" });
89396
89743
  AdhdevDaemon = class _AdhdevDaemon {
89397
89744
  localHttpServer = null;
89398
89745
  localWss = null;
@@ -90884,20 +91231,20 @@ async function startDaemonFlow() {
90884
91231
  try {
90885
91232
  const { AdhdevDaemon: AdhdevDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
90886
91233
  const daemon = new AdhdevDaemon2();
90887
- const { execSync: execSync8 } = await import("child_process");
91234
+ const { execSync: execSync9 } = await import("child_process");
90888
91235
  const { getCurrentDaemonLogPath: getCurrentDaemonLogPath2 } = await Promise.resolve().then(() => (init_src(), src_exports));
90889
91236
  const logPath = getCurrentDaemonLogPath2();
90890
91237
  const os31 = await import("os");
90891
91238
  const platform12 = os31.platform();
90892
91239
  try {
90893
91240
  if (platform12 === "win32") {
90894
- execSync8("start /B adhdev daemon >NUL 2>&1", {
91241
+ execSync9("start /B adhdev daemon >NUL 2>&1", {
90895
91242
  timeout: 3e3,
90896
91243
  stdio: "ignore",
90897
91244
  shell: "cmd.exe"
90898
91245
  });
90899
91246
  } else {
90900
- execSync8("nohup adhdev daemon >/dev/null 2>&1 &", {
91247
+ execSync9("nohup adhdev daemon >/dev/null 2>&1 &", {
90901
91248
  timeout: 3e3,
90902
91249
  stdio: "ignore"
90903
91250
  });
@@ -93336,7 +93683,7 @@ async function handleTraceCommand(options) {
93336
93683
  async function runDaemonUpgrade(options, pkgVersion3) {
93337
93684
  const { isDaemonRunning: isDaemonRunning2, stopDaemon: stopDaemon2 } = await Promise.resolve().then(() => (init_adhdev_daemon(), adhdev_daemon_exports));
93338
93685
  const { stopManagedSessionHostProcess: stopManagedSessionHostProcess2 } = await Promise.resolve().then(() => (init_session_host(), session_host_exports));
93339
- const { execSync: execSync8, spawn: spawn7 } = await import("child_process");
93686
+ const { execSync: execSync9, spawn: spawn7 } = await import("child_process");
93340
93687
  const fsMod = await import("fs");
93341
93688
  const pathMod = await import("path");
93342
93689
  console.log(source_default.bold("\n \u{1F504} ADHDev Upgrade\n"));
@@ -93356,10 +93703,10 @@ async function runDaemonUpgrade(options, pkgVersion3) {
93356
93703
  while (!fsMod.existsSync(pathMod.join(gitRoot, ".git")) && gitRoot !== "/") {
93357
93704
  gitRoot = pathMod.dirname(gitRoot);
93358
93705
  }
93359
- execSync8("git pull --rebase", { cwd: gitRoot, stdio: "inherit" });
93706
+ execSync9("git pull --rebase", { cwd: gitRoot, stdio: "inherit" });
93360
93707
  console.log(source_default.cyan("\n Building..."));
93361
- execSync8("npm run build", { cwd: launcherDir, stdio: "inherit" });
93362
- execSync8("npm link", { cwd: launcherDir, stdio: "inherit" });
93708
+ execSync9("npm run build", { cwd: launcherDir, stdio: "inherit" });
93709
+ execSync9("npm link", { cwd: launcherDir, stdio: "inherit" });
93363
93710
  console.log(source_default.green("\n \u2713 Build complete"));
93364
93711
  } catch (e) {
93365
93712
  console.log(source_default.red(`
@@ -93467,7 +93814,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
93467
93814
  }
93468
93815
  });
93469
93816
  program2.command("standalone").description("\u{1F5A5}\uFE0F Start ADHDev Standalone Server (Local Dashboard & Embedded Daemon)").option("-p, --port <port>", "Local HTTP/WS server port", "3847").option("--host <host>", "Bind to specific host (use 0.0.0.0 for LAN access)").option("--no-open", "Prevent opening browser automatically").option("--token <token>", "Require token authentication").option("--dev", "Enable Dev Mode").action(async (options) => {
93470
- const { spawn: spawn7, execSync: execSync8 } = await import("child_process");
93817
+ const { spawn: spawn7, execSync: execSync9 } = await import("child_process");
93471
93818
  const { DEFAULT_STANDALONE_SESSION_HOST_APP_NAME: DEFAULT_STANDALONE_SESSION_HOST_APP_NAME2, resolveSessionHostAppNameResolution: resolveSessionHostAppNameResolution2 } = await Promise.resolve().then(() => (init_src(), src_exports));
93472
93819
  console.log(source_default.cyan("\n Starting ADHDev Standalone Server..."));
93473
93820
  const args = [];
@@ -93485,7 +93832,7 @@ function registerDaemonCommands(program2, pkgVersion3) {
93485
93832
  let bin = "npx";
93486
93833
  const npxArgs = ["-y", "@adhdev/daemon-standalone@latest", ...args];
93487
93834
  try {
93488
- execSync8("adhdev-standalone --help", { stdio: "ignore" });
93835
+ execSync9("adhdev-standalone --help", { stdio: "ignore" });
93489
93836
  bin = "adhdev-standalone";
93490
93837
  } catch {
93491
93838
  console.log(source_default.gray(" Standalone server package not found locally."));
@@ -95993,7 +96340,7 @@ var import_node_module3 = require("module");
95993
96340
  var path39 = __toESM(require("path"));
95994
96341
  init_source();
95995
96342
  function registerMcpCommands(program2) {
95996
- program2.command("mcp").description("Start an MCP server to expose IDE agents as tools (for Claude Desktop, etc.)").option("--api-key <key>", "ADHDev cloud API key (switches to cloud mode)").option("--port <n>", "Standalone daemon port (default: 3847)", "3847").option("--password <pass>", "Standalone daemon password (if set)").option("--base-url <url>", "Override cloud API base URL").addHelpText("after", `
96343
+ program2.command("mcp").description("Start an MCP server to expose IDE agents as tools (for Claude Desktop, etc.)").option("--api-key <key>", "ADHDev cloud API key (switches to cloud mode)").option("--port <n>", "Standalone daemon port (default: 3847)", "3847").option("--password <pass>", "Standalone daemon password (if set)").option("--base-url <url>", "Override cloud API base URL").option("--repo-mesh <mesh_id>", "Start in mesh mode (coordinator-scoped tools)").addHelpText("after", `
95997
96344
  Examples:
95998
96345
  adhdev mcp Local mode (requires: adhdev standalone)
95999
96346
  adhdev mcp --api-key adk_xxx Cloud mode (no local daemon needed)
@@ -96021,6 +96368,7 @@ Tools available (cloud): list_daemons, list_sessions, launch_session, stop_sess
96021
96368
  if (opts.port && opts.port !== "3847") args.push("--port", opts.port);
96022
96369
  if (opts.password) args.push("--password", opts.password);
96023
96370
  if (opts.baseUrl) args.push("--base-url", opts.baseUrl);
96371
+ if (opts.repoMesh) args.push("--repo-mesh", opts.repoMesh);
96024
96372
  const env3 = { ...process.env };
96025
96373
  if (opts.apiKey) env3.ADHDEV_API_KEY = opts.apiKey;
96026
96374
  if (opts.password) env3.ADHDEV_PASSWORD = opts.password;
@@ -96055,6 +96403,283 @@ function resolveMcpBin() {
96055
96403
  }
96056
96404
  }
96057
96405
 
96406
+ // src/cli/mesh-commands.ts
96407
+ init_source();
96408
+ var import_node_child_process4 = require("child_process");
96409
+ init_src();
96410
+ function registerMeshCommands(program2) {
96411
+ const mesh = program2.command("mesh").description("Manage Repo Meshes \u2014 repo-scoped execution environments");
96412
+ mesh.command("list").description("List all configured meshes").action(() => {
96413
+ const meshes = listMeshes();
96414
+ if (meshes.length === 0) {
96415
+ console.log(source_default.gray("No meshes configured. Create one with: adhdev mesh create <name>"));
96416
+ return;
96417
+ }
96418
+ console.log(source_default.bold(`
96419
+ Repo Meshes (${meshes.length})
96420
+ `));
96421
+ for (const m of meshes) {
96422
+ const nodeCount = m.nodes.length;
96423
+ const statusIcon = nodeCount > 0 ? source_default.green("\u25CF") : source_default.yellow("\u25CB");
96424
+ console.log(` ${statusIcon} ${source_default.bold(m.name)} ${source_default.gray(m.id)}`);
96425
+ console.log(` ${source_default.gray("repo:")} ${m.repoIdentity}`);
96426
+ console.log(` ${source_default.gray("nodes:")} ${nodeCount} ${source_default.gray("created:")} ${m.createdAt.split("T")[0]}`);
96427
+ console.log();
96428
+ }
96429
+ });
96430
+ mesh.command("create <name>").description("Create a new mesh for the current Git repository").option("--remote-url <url>", "Git remote URL (auto-detected from current directory)").option("--identity <identity>", "Repo identity override (e.g. github.com/user/repo)").option("--branch <branch>", "Default branch (e.g. main)").option("--add-current", "Also add current workspace as the first node", false).action(async (name, opts) => {
96431
+ let repoRemoteUrl = opts.remoteUrl;
96432
+ let repoIdentity = opts.identity;
96433
+ let defaultBranch = opts.branch;
96434
+ if (!repoRemoteUrl && !repoIdentity) {
96435
+ try {
96436
+ repoRemoteUrl = (0, import_node_child_process4.execSync)("git remote get-url origin", {
96437
+ encoding: "utf-8",
96438
+ stdio: ["pipe", "pipe", "pipe"]
96439
+ }).trim();
96440
+ console.log(source_default.gray(` Detected remote: ${repoRemoteUrl}`));
96441
+ } catch {
96442
+ console.error(source_default.red("\u2717 Could not detect Git remote. Use --remote-url or --identity."));
96443
+ process.exit(1);
96444
+ }
96445
+ }
96446
+ if (!defaultBranch) {
96447
+ try {
96448
+ defaultBranch = (0, import_node_child_process4.execSync)("git symbolic-ref refs/remotes/origin/HEAD", {
96449
+ encoding: "utf-8",
96450
+ stdio: ["pipe", "pipe", "pipe"]
96451
+ }).trim().replace("refs/remotes/origin/", "");
96452
+ } catch {
96453
+ try {
96454
+ defaultBranch = (0, import_node_child_process4.execSync)("git branch --show-current", {
96455
+ encoding: "utf-8",
96456
+ stdio: ["pipe", "pipe", "pipe"]
96457
+ }).trim();
96458
+ } catch {
96459
+ defaultBranch = "main";
96460
+ }
96461
+ }
96462
+ }
96463
+ try {
96464
+ const mesh2 = createMesh({
96465
+ name,
96466
+ repoRemoteUrl,
96467
+ repoIdentity,
96468
+ defaultBranch
96469
+ });
96470
+ console.log(source_default.green(`
96471
+ \u2713 Mesh created: ${source_default.bold(mesh2.name)}`));
96472
+ console.log(source_default.gray(` ID: ${mesh2.id}`));
96473
+ console.log(source_default.gray(` Repo: ${mesh2.repoIdentity}`));
96474
+ console.log(source_default.gray(` Branch: ${mesh2.defaultBranch || "auto"}`));
96475
+ if (opts.addCurrent) {
96476
+ const cwd = process.cwd();
96477
+ try {
96478
+ const node = addNode(mesh2.id, { workspace: cwd });
96479
+ if (node) {
96480
+ console.log(source_default.green(` \u2713 Added current workspace as node: ${source_default.gray(cwd)}`));
96481
+ console.log(source_default.gray(` Node ID: ${node.id}`));
96482
+ }
96483
+ } catch (e) {
96484
+ console.error(source_default.yellow(` \u26A0 Could not add current workspace: ${e.message}`));
96485
+ }
96486
+ }
96487
+ console.log();
96488
+ console.log(source_default.gray(" Next steps:"));
96489
+ console.log(source_default.gray(` adhdev mesh add-node ${mesh2.id} \u2014 Add a workspace to this mesh`));
96490
+ console.log(source_default.gray(` adhdev mcp --repo-mesh ${mesh2.id} \u2014 Start MCP server in mesh mode`));
96491
+ console.log();
96492
+ } catch (e) {
96493
+ console.error(source_default.red(`\u2717 ${e.message}`));
96494
+ process.exit(1);
96495
+ }
96496
+ });
96497
+ mesh.command("show <mesh_id>").description("Show mesh details and nodes").action((meshId) => {
96498
+ const m = getMesh(meshId);
96499
+ if (!m) {
96500
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96501
+ process.exit(1);
96502
+ }
96503
+ console.log(source_default.bold(`
96504
+ ${m.name} ${source_default.gray(m.id)}`));
96505
+ console.log(` ${source_default.gray("repo:")} ${m.repoIdentity}`);
96506
+ if (m.repoRemoteUrl) console.log(` ${source_default.gray("remote:")} ${m.repoRemoteUrl}`);
96507
+ if (m.defaultBranch) console.log(` ${source_default.gray("branch:")} ${m.defaultBranch}`);
96508
+ console.log(` ${source_default.gray("created:")} ${m.createdAt}`);
96509
+ console.log(` ${source_default.gray("updated:")} ${m.updatedAt}`);
96510
+ console.log(source_default.bold("\n Policy"));
96511
+ console.log(` ${source_default.gray("checkpoint after task:")} ${m.policy.requirePostTaskCheckpoint ? "yes" : "no"}`);
96512
+ console.log(` ${source_default.gray("push requires approval:")} ${m.policy.requireApprovalForPush ? "yes" : "no"}`);
96513
+ console.log(` ${source_default.gray("dirty workspace:")} ${m.policy.dirtyWorkspaceBehavior}`);
96514
+ console.log(` ${source_default.gray("max parallel tasks:")} ${m.policy.maxParallelTasks}`);
96515
+ console.log(source_default.bold(`
96516
+ Nodes (${m.nodes.length})`));
96517
+ if (m.nodes.length === 0) {
96518
+ console.log(source_default.gray(" No nodes. Add one with: adhdev mesh add-node " + meshId));
96519
+ } else {
96520
+ for (const n of m.nodes) {
96521
+ const label = n.isLocalWorktree ? source_default.cyan("[worktree]") : "";
96522
+ console.log(` ${source_default.gray("\u25CF")} ${n.workspace} ${label} ${source_default.gray(n.id)}`);
96523
+ if (n.policy.readOnly) console.log(` ${source_default.yellow("read-only")}`);
96524
+ if (Object.keys(n.userOverrides).length > 0) {
96525
+ console.log(` ${source_default.gray("overrides:")} ${JSON.stringify(n.userOverrides)}`);
96526
+ }
96527
+ }
96528
+ }
96529
+ console.log();
96530
+ });
96531
+ mesh.command("delete <mesh_id>").description("Delete a mesh").action((meshId) => {
96532
+ const m = getMesh(meshId);
96533
+ if (!m) {
96534
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96535
+ process.exit(1);
96536
+ }
96537
+ const ok = deleteMesh(meshId);
96538
+ if (ok) {
96539
+ console.log(source_default.green(` \u2713 Deleted mesh: ${m.name} (${meshId})`));
96540
+ } else {
96541
+ console.error(source_default.red(`\u2717 Failed to delete mesh: ${meshId}`));
96542
+ process.exit(1);
96543
+ }
96544
+ });
96545
+ mesh.command("add-node <mesh_id>").description("Add a workspace as a node to the mesh").option("--workspace <path>", "Workspace path (default: current directory)").option("--worktree", "Mark as a local Git worktree", false).option("--read-only", "Mark this node as read-only", false).action((meshId, opts) => {
96546
+ const m = getMesh(meshId);
96547
+ if (!m) {
96548
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96549
+ process.exit(1);
96550
+ }
96551
+ const workspace = opts.workspace || process.cwd();
96552
+ try {
96553
+ const node = addNode(meshId, {
96554
+ workspace,
96555
+ isLocalWorktree: opts.worktree,
96556
+ policy: opts.readOnly ? { readOnly: true } : {}
96557
+ });
96558
+ if (node) {
96559
+ console.log(source_default.green(` \u2713 Node added to ${m.name}`));
96560
+ console.log(source_default.gray(` ID: ${node.id}`));
96561
+ console.log(source_default.gray(` Workspace: ${workspace}`));
96562
+ if (opts.worktree) console.log(source_default.gray(` Type: local worktree`));
96563
+ if (opts.readOnly) console.log(source_default.gray(` Policy: read-only`));
96564
+ } else {
96565
+ console.error(source_default.red(`\u2717 Mesh not found`));
96566
+ process.exit(1);
96567
+ }
96568
+ } catch (e) {
96569
+ console.error(source_default.red(`\u2717 ${e.message}`));
96570
+ process.exit(1);
96571
+ }
96572
+ });
96573
+ mesh.command("remove-node <mesh_id> <node_id>").description("Remove a node from the mesh").action((meshId, nodeId) => {
96574
+ const ok = removeNode(meshId, nodeId);
96575
+ if (ok) {
96576
+ console.log(source_default.green(` \u2713 Node removed: ${nodeId}`));
96577
+ } else {
96578
+ console.error(source_default.red(`\u2717 Node or mesh not found`));
96579
+ process.exit(1);
96580
+ }
96581
+ });
96582
+ mesh.command("status <mesh_id>").description("Probe all mesh nodes and show health").action(async (meshId) => {
96583
+ const m = getMesh(meshId);
96584
+ if (!m) {
96585
+ console.error(source_default.red(`\u2717 Mesh not found: ${meshId}`));
96586
+ process.exit(1);
96587
+ }
96588
+ console.log(source_default.bold(`
96589
+ ${m.name} \u2014 Node Status
96590
+ `));
96591
+ if (m.nodes.length === 0) {
96592
+ console.log(source_default.gray(" No nodes configured."));
96593
+ return;
96594
+ }
96595
+ for (const node of m.nodes) {
96596
+ let gitInfo = "";
96597
+ let healthIcon = source_default.gray("?");
96598
+ let health = "unknown";
96599
+ try {
96600
+ const branch = (0, import_node_child_process4.execSync)(`git -C "${node.workspace}" branch --show-current`, {
96601
+ encoding: "utf-8",
96602
+ stdio: ["pipe", "pipe", "pipe"]
96603
+ }).trim();
96604
+ const status = (0, import_node_child_process4.execSync)(`git -C "${node.workspace}" status --porcelain`, {
96605
+ encoding: "utf-8",
96606
+ stdio: ["pipe", "pipe", "pipe"]
96607
+ }).trim();
96608
+ const isDirty = status.length > 0;
96609
+ const changedFiles = isDirty ? status.split("\n").length : 0;
96610
+ if (isDirty) {
96611
+ health = "dirty";
96612
+ healthIcon = source_default.yellow("\u25CF");
96613
+ gitInfo = `${source_default.cyan(branch)} ${source_default.yellow(`(${changedFiles} changed)`)}`;
96614
+ } else {
96615
+ health = "clean";
96616
+ healthIcon = source_default.green("\u25CF");
96617
+ gitInfo = `${source_default.cyan(branch)} ${source_default.green("clean")}`;
96618
+ }
96619
+ } catch {
96620
+ health = "error";
96621
+ healthIcon = source_default.red("\u2717");
96622
+ gitInfo = source_default.red("git probe failed");
96623
+ }
96624
+ const label = node.isLocalWorktree ? source_default.gray(" [worktree]") : "";
96625
+ console.log(` ${healthIcon} ${node.workspace}${label} ${source_default.gray(node.id.slice(0, 12))}`);
96626
+ console.log(` ${gitInfo}`);
96627
+ if (node.policy.readOnly) console.log(` ${source_default.yellow("read-only")}`);
96628
+ console.log();
96629
+ }
96630
+ });
96631
+ mesh.command("sync").description("Sync local mesh config with cloud (push/pull)").action(async () => {
96632
+ try {
96633
+ const { syncMeshes: syncMeshes2, loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_src(), src_exports));
96634
+ const config2 = loadConfig2();
96635
+ const apiKey = process.env.ADHDEV_API_KEY;
96636
+ if (!apiKey) {
96637
+ console.error(source_default.red("\u2717 No API key set. Export ADHDEV_API_KEY or use: adhdev setup"));
96638
+ process.exit(1);
96639
+ }
96640
+ const baseUrl = config2.serverUrl || "https://api.adhf.dev";
96641
+ const transport = {
96642
+ async listRemoteMeshes() {
96643
+ const res = await fetch(`${baseUrl}/api/v1/repo-meshes`, {
96644
+ headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json" }
96645
+ });
96646
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
96647
+ return res.json();
96648
+ },
96649
+ async createRemoteMesh(data) {
96650
+ const res = await fetch(`${baseUrl}/api/v1/repo-meshes`, {
96651
+ method: "POST",
96652
+ headers: { "Authorization": `Bearer ${apiKey}`, "Content-Type": "application/json" },
96653
+ body: JSON.stringify(data)
96654
+ });
96655
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
96656
+ return res.json();
96657
+ },
96658
+ async deleteRemoteMesh(meshId) {
96659
+ const res = await fetch(`${baseUrl}/api/v1/repo-meshes/${meshId}`, {
96660
+ method: "DELETE",
96661
+ headers: { "Authorization": `Bearer ${apiKey}` }
96662
+ });
96663
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
96664
+ }
96665
+ };
96666
+ console.log(source_default.gray(" Syncing with cloud..."));
96667
+ const result = await syncMeshes2(transport);
96668
+ if (result.pushed > 0) console.log(source_default.green(` \u2713 Pushed ${result.pushed} mesh${result.pushed > 1 ? "es" : ""} to cloud`));
96669
+ if (result.pulled > 0) console.log(source_default.green(` \u2713 Pulled ${result.pulled} mesh${result.pulled > 1 ? "es" : ""} from cloud`));
96670
+ if (result.pushed === 0 && result.pulled === 0 && result.errors.length === 0) {
96671
+ console.log(source_default.gray(" Already in sync."));
96672
+ }
96673
+ for (const err of result.errors) {
96674
+ console.error(source_default.yellow(` \u26A0 ${err}`));
96675
+ }
96676
+ } catch (e) {
96677
+ console.error(source_default.red(`\u2717 Sync failed: ${e.message}`));
96678
+ process.exit(1);
96679
+ }
96680
+ });
96681
+ }
96682
+
96058
96683
  // src/cli/index.ts
96059
96684
  init_version();
96060
96685
  var pkgVersion2 = resolvePackageVersion();
@@ -96075,6 +96700,7 @@ registerProviderCommands(program);
96075
96700
  registerCdpCommands(program);
96076
96701
  registerServiceCommands(program);
96077
96702
  registerMcpCommands(program);
96703
+ registerMeshCommands(program);
96078
96704
  void (async () => {
96079
96705
  const helperMode = await maybeRunDaemonUpgradeHelperFromEnv();
96080
96706
  if (helperMode) {
@@ -96102,6 +96728,8 @@ void (async () => {
96102
96728
  console.log(source_default.gray(" adhdev trace --category session_host \u2014 Inspect structured daemon trace"));
96103
96729
  console.log(source_default.gray(" adhdev service \u2014 Manage OS background auto-start service"));
96104
96730
  console.log(source_default.gray(" adhdev mcp \u2014 Start MCP server (expose agents to Claude Desktop, etc.)"));
96731
+ console.log(source_default.gray(" adhdev mesh list \u2014 List configured Repo Meshes"));
96732
+ console.log(source_default.gray(" adhdev mesh create myapp \u2014 Create a mesh for the current Git repo"));
96105
96733
  console.log(source_default.gray(" adhdev provider ... \u2014 Provider development commands"));
96106
96734
  console.log(source_default.gray(" adhdev cdp ... \u2014 CDP debugging tools"));
96107
96735
  console.log();