@adhdev/daemon-core 0.9.76-rc.3 → 0.9.76-rc.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -1
- package/dist/cli-adapters/provider-cli-runtime.d.ts +1 -0
- package/dist/commands/cli-manager.d.ts +17 -4
- package/dist/commands/mesh-coordinator.d.ts +2 -0
- package/dist/commands/router.d.ts +4 -0
- package/dist/config/mesh-config.d.ts +3 -0
- package/dist/git/git-types.d.ts +1 -1
- package/dist/git/git-worktree.d.ts +64 -0
- package/dist/git/index.d.ts +2 -0
- package/dist/index.js +1058 -384
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1085 -416
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +3 -0
- package/dist/providers/provider-instance-manager.d.ts +1 -0
- package/dist/providers/provider-instance.d.ts +2 -0
- package/dist/repo-mesh-types.d.ts +6 -0
- package/dist/shared-types.d.ts +22 -1
- package/package.json +3 -4
- package/src/cli-adapters/provider-cli-adapter.ts +6 -3
- package/src/cli-adapters/provider-cli-runtime.ts +3 -2
- package/src/commands/chat-commands.ts +50 -5
- package/src/commands/cli-manager.ts +78 -5
- package/src/commands/handler.ts +13 -4
- package/src/commands/mesh-coordinator.ts +149 -6
- package/src/commands/router.ts +319 -32
- package/src/config/mesh-config.ts +6 -0
- package/src/git/git-commands.ts +5 -1
- package/src/git/git-types.ts +1 -0
- package/src/git/git-worktree.ts +214 -0
- package/src/git/index.ts +14 -0
- package/src/mesh/coordinator-prompt.ts +25 -10
- package/src/mesh/mesh-events.ts +40 -17
- package/src/providers/cli-provider-instance.d.ts +2 -0
- package/src/providers/cli-provider-instance.ts +55 -7
- package/src/providers/provider-instance-manager.ts +20 -1
- package/src/providers/provider-instance.ts +2 -0
- package/src/repo-mesh-types.ts +6 -0
- package/src/shared-types.ts +24 -1
- package/src/status/builders.ts +17 -12
- package/src/status/reporter.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -46,6 +46,134 @@ var init_repo_mesh_types = __esm({
|
|
|
46
46
|
}
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
+
// src/git/git-worktree.ts
|
|
50
|
+
var git_worktree_exports = {};
|
|
51
|
+
__export(git_worktree_exports, {
|
|
52
|
+
createWorktree: () => createWorktree,
|
|
53
|
+
listWorktrees: () => listWorktrees,
|
|
54
|
+
parseWorktreeListOutput: () => parseWorktreeListOutput,
|
|
55
|
+
removeWorktree: () => removeWorktree,
|
|
56
|
+
resolveWorktreePath: () => resolveWorktreePath
|
|
57
|
+
});
|
|
58
|
+
function resolveWorktreePath(repoRoot, meshName, branch) {
|
|
59
|
+
const safeBranch = branch.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
|
|
60
|
+
const safeMeshName = meshName.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
|
|
61
|
+
const parentDir = path4.dirname(repoRoot);
|
|
62
|
+
return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
|
|
63
|
+
}
|
|
64
|
+
async function createWorktree(opts) {
|
|
65
|
+
const { repoRoot, branch, baseBranch, meshName } = opts;
|
|
66
|
+
const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
|
|
67
|
+
if ((0, import_node_fs2.existsSync)(targetDir)) {
|
|
68
|
+
throw new Error(`Worktree target directory already exists: ${targetDir}`);
|
|
69
|
+
}
|
|
70
|
+
await (0, import_promises3.mkdir)(path4.dirname(targetDir), { recursive: true });
|
|
71
|
+
const args = ["worktree", "add", targetDir, "-b", branch];
|
|
72
|
+
if (baseBranch) {
|
|
73
|
+
args.push(baseBranch);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
await execFileAsync2("git", args, {
|
|
77
|
+
cwd: repoRoot,
|
|
78
|
+
encoding: "utf8",
|
|
79
|
+
timeout: GIT_TIMEOUT_MS,
|
|
80
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
81
|
+
windowsHide: true
|
|
82
|
+
});
|
|
83
|
+
} catch (error) {
|
|
84
|
+
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
85
|
+
if (/already exists/i.test(stderr)) {
|
|
86
|
+
throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
|
|
87
|
+
}
|
|
88
|
+
throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
success: true,
|
|
92
|
+
worktreePath: targetDir,
|
|
93
|
+
branch
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function removeWorktree(repoRoot, worktreePath) {
|
|
97
|
+
if (!(0, import_node_fs2.existsSync)(worktreePath)) {
|
|
98
|
+
await pruneWorktrees(repoRoot);
|
|
99
|
+
return { success: true, removedPath: worktreePath };
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
await execFileAsync2("git", ["worktree", "remove", worktreePath, "--force"], {
|
|
103
|
+
cwd: repoRoot,
|
|
104
|
+
encoding: "utf8",
|
|
105
|
+
timeout: GIT_TIMEOUT_MS,
|
|
106
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
107
|
+
windowsHide: true
|
|
108
|
+
});
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
111
|
+
throw new Error(`git worktree remove failed: ${stderr.trim() || error.message}`);
|
|
112
|
+
}
|
|
113
|
+
return { success: true, removedPath: worktreePath };
|
|
114
|
+
}
|
|
115
|
+
async function listWorktrees(repoRoot) {
|
|
116
|
+
const { stdout } = await execFileAsync2("git", ["worktree", "list", "--porcelain"], {
|
|
117
|
+
cwd: repoRoot,
|
|
118
|
+
encoding: "utf8",
|
|
119
|
+
timeout: GIT_TIMEOUT_MS,
|
|
120
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
121
|
+
windowsHide: true
|
|
122
|
+
});
|
|
123
|
+
return parseWorktreeListOutput(stdout);
|
|
124
|
+
}
|
|
125
|
+
function parseWorktreeListOutput(output) {
|
|
126
|
+
const entries = [];
|
|
127
|
+
const blocks = output.trim().split(/\n\n+/);
|
|
128
|
+
for (const block of blocks) {
|
|
129
|
+
if (!block.trim()) continue;
|
|
130
|
+
const lines = block.trim().split("\n");
|
|
131
|
+
const entry = { path: "", head: "", branch: null, bare: false };
|
|
132
|
+
for (const line of lines) {
|
|
133
|
+
if (line.startsWith("worktree ")) {
|
|
134
|
+
entry.path = line.slice("worktree ".length).trim();
|
|
135
|
+
} else if (line.startsWith("HEAD ")) {
|
|
136
|
+
entry.head = line.slice("HEAD ".length).trim();
|
|
137
|
+
} else if (line.startsWith("branch ")) {
|
|
138
|
+
const ref = line.slice("branch ".length).trim();
|
|
139
|
+
entry.branch = ref.replace(/^refs\/heads\//, "");
|
|
140
|
+
} else if (line === "bare") {
|
|
141
|
+
entry.bare = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (entry.path) {
|
|
145
|
+
entries.push(entry);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return entries;
|
|
149
|
+
}
|
|
150
|
+
async function pruneWorktrees(repoRoot) {
|
|
151
|
+
try {
|
|
152
|
+
await execFileAsync2("git", ["worktree", "prune"], {
|
|
153
|
+
cwd: repoRoot,
|
|
154
|
+
encoding: "utf8",
|
|
155
|
+
timeout: GIT_TIMEOUT_MS,
|
|
156
|
+
windowsHide: true
|
|
157
|
+
});
|
|
158
|
+
} catch {
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
var path4, import_promises3, import_node_fs2, import_node_child_process2, import_node_util2, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER;
|
|
162
|
+
var init_git_worktree = __esm({
|
|
163
|
+
"src/git/git-worktree.ts"() {
|
|
164
|
+
"use strict";
|
|
165
|
+
path4 = __toESM(require("path"));
|
|
166
|
+
import_promises3 = require("fs/promises");
|
|
167
|
+
import_node_fs2 = require("fs");
|
|
168
|
+
import_node_child_process2 = require("child_process");
|
|
169
|
+
import_node_util2 = require("util");
|
|
170
|
+
execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
171
|
+
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
172
|
+
GIT_TIMEOUT_MS = 3e4;
|
|
173
|
+
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
49
177
|
// src/config/config.ts
|
|
50
178
|
var config_exports = {};
|
|
51
179
|
__export(config_exports, {
|
|
@@ -304,10 +432,10 @@ function getMeshConfigPath() {
|
|
|
304
432
|
return (0, import_path2.join)(getConfigDir(), "meshes.json");
|
|
305
433
|
}
|
|
306
434
|
function loadMeshConfig() {
|
|
307
|
-
const
|
|
308
|
-
if (!(0, import_fs2.existsSync)(
|
|
435
|
+
const path27 = getMeshConfigPath();
|
|
436
|
+
if (!(0, import_fs2.existsSync)(path27)) return { meshes: [] };
|
|
309
437
|
try {
|
|
310
|
-
const raw = JSON.parse((0, import_fs2.readFileSync)(
|
|
438
|
+
const raw = JSON.parse((0, import_fs2.readFileSync)(path27, "utf-8"));
|
|
311
439
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
312
440
|
return raw;
|
|
313
441
|
} catch {
|
|
@@ -315,16 +443,16 @@ function loadMeshConfig() {
|
|
|
315
443
|
}
|
|
316
444
|
}
|
|
317
445
|
function saveMeshConfig(config) {
|
|
318
|
-
const
|
|
319
|
-
(0, import_fs2.writeFileSync)(
|
|
446
|
+
const path27 = getMeshConfigPath();
|
|
447
|
+
(0, import_fs2.writeFileSync)(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
|
|
320
448
|
}
|
|
321
449
|
function normalizeRepoIdentity(remoteUrl) {
|
|
322
450
|
let identity = remoteUrl.trim();
|
|
323
451
|
if (identity.startsWith("http://") || identity.startsWith("https://")) {
|
|
324
452
|
try {
|
|
325
453
|
const url = new URL(identity);
|
|
326
|
-
const
|
|
327
|
-
return `${url.hostname}/${
|
|
454
|
+
const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
|
|
455
|
+
return `${url.hostname}/${path27}`;
|
|
328
456
|
} catch {
|
|
329
457
|
}
|
|
330
458
|
}
|
|
@@ -399,9 +527,12 @@ function addNode(meshId, opts) {
|
|
|
399
527
|
id: `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
|
|
400
528
|
workspace: opts.workspace.trim(),
|
|
401
529
|
repoRoot: opts.repoRoot,
|
|
530
|
+
daemonId: opts.daemonId,
|
|
402
531
|
userOverrides: opts.userOverrides || {},
|
|
403
532
|
policy: opts.policy || {},
|
|
404
|
-
isLocalWorktree: opts.isLocalWorktree
|
|
533
|
+
isLocalWorktree: opts.isLocalWorktree,
|
|
534
|
+
worktreeBranch: opts.worktreeBranch,
|
|
535
|
+
clonedFromNodeId: opts.clonedFromNodeId
|
|
405
536
|
};
|
|
406
537
|
mesh.nodes.push(node);
|
|
407
538
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -449,7 +580,7 @@ __export(coordinator_prompt_exports, {
|
|
|
449
580
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
|
|
450
581
|
});
|
|
451
582
|
function buildCoordinatorSystemPrompt(ctx) {
|
|
452
|
-
const { mesh, status, userInstruction } = ctx;
|
|
583
|
+
const { mesh, status, userInstruction, coordinatorCliType } = ctx;
|
|
453
584
|
const sections = [];
|
|
454
585
|
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
586
|
|
|
@@ -463,15 +594,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
463
594
|
} else {
|
|
464
595
|
sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
|
|
465
596
|
}
|
|
466
|
-
sections.push(buildPolicySection(mesh.policy));
|
|
597
|
+
sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
|
|
467
598
|
sections.push(TOOLS_SECTION);
|
|
468
599
|
sections.push(WORKFLOW_SECTION);
|
|
469
|
-
sections.push(
|
|
600
|
+
sections.push(buildRulesSection(coordinatorCliType));
|
|
470
601
|
if (userInstruction) {
|
|
471
602
|
sections.push(`## Additional Context
|
|
472
603
|
${userInstruction}`);
|
|
473
604
|
}
|
|
474
|
-
if (mesh.coordinator
|
|
605
|
+
if (mesh.coordinator?.systemPromptSuffix) {
|
|
475
606
|
sections.push(mesh.coordinator.systemPromptSuffix);
|
|
476
607
|
}
|
|
477
608
|
return sections.join("\n\n");
|
|
@@ -516,10 +647,29 @@ function buildPolicySection(policy) {
|
|
|
516
647
|
return `## Policy
|
|
517
648
|
${rules.join("\n")}`;
|
|
518
649
|
}
|
|
519
|
-
|
|
650
|
+
function buildRulesSection(coordinatorCliType) {
|
|
651
|
+
const coordinatorNote = coordinatorCliType ? `
|
|
652
|
+
- **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.` : "";
|
|
653
|
+
return `## Rules
|
|
654
|
+
|
|
655
|
+
- **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.
|
|
656
|
+
- **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.
|
|
657
|
+
- **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.
|
|
658
|
+
- **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.
|
|
659
|
+
- **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
|
|
660
|
+
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
|
|
661
|
+
- **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
|
|
662
|
+
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
663
|
+
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
664
|
+
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.
|
|
665
|
+
- **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
|
|
666
|
+
- **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
|
|
667
|
+
}
|
|
668
|
+
var TOOLS_SECTION, WORKFLOW_SECTION;
|
|
520
669
|
var init_coordinator_prompt = __esm({
|
|
521
670
|
"src/mesh/coordinator-prompt.ts"() {
|
|
522
671
|
"use strict";
|
|
672
|
+
init_repo_mesh_types();
|
|
523
673
|
TOOLS_SECTION = `## Available Tools
|
|
524
674
|
|
|
525
675
|
| Tool | Purpose |
|
|
@@ -531,30 +681,23 @@ var init_coordinator_prompt = __esm({
|
|
|
531
681
|
| \`mesh_read_chat\` | Read an agent's recent messages to check progress |
|
|
532
682
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
533
683
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
534
|
-
| \`mesh_approve\` | Approve/reject a pending agent action
|
|
684
|
+
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
685
|
+
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
686
|
+
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
|
|
535
687
|
WORKFLOW_SECTION = `## Orchestration Workflow
|
|
536
688
|
|
|
537
689
|
1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
|
|
538
690
|
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
|
|
539
691
|
3. **Delegate** \u2014 For each task:
|
|
540
692
|
a. Pick the best node (consider: health, dirty state, current workload).
|
|
541
|
-
b. If
|
|
542
|
-
c.
|
|
693
|
+
b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
694
|
+
c. If no session exists, call \`mesh_launch_session\` to start one.
|
|
695
|
+
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
696
|
4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
|
|
544
697
|
5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
|
|
545
698
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
546
|
-
7. **
|
|
547
|
-
|
|
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.`;
|
|
699
|
+
7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
700
|
+
8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
|
|
558
701
|
}
|
|
559
702
|
});
|
|
560
703
|
|
|
@@ -573,13 +716,13 @@ function getDaemonLogDir() {
|
|
|
573
716
|
return LOG_DIR;
|
|
574
717
|
}
|
|
575
718
|
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
576
|
-
return
|
|
719
|
+
return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
577
720
|
}
|
|
578
721
|
function checkDateRotation() {
|
|
579
722
|
const today = getDateStr();
|
|
580
723
|
if (today !== currentDate) {
|
|
581
724
|
currentDate = today;
|
|
582
|
-
currentLogFile =
|
|
725
|
+
currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
583
726
|
cleanOldLogs();
|
|
584
727
|
}
|
|
585
728
|
}
|
|
@@ -593,7 +736,7 @@ function cleanOldLogs() {
|
|
|
593
736
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
594
737
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
595
738
|
try {
|
|
596
|
-
fs2.unlinkSync(
|
|
739
|
+
fs2.unlinkSync(path10.join(LOG_DIR, file));
|
|
597
740
|
} catch {
|
|
598
741
|
}
|
|
599
742
|
}
|
|
@@ -709,17 +852,17 @@ function installGlobalInterceptor() {
|
|
|
709
852
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
710
853
|
writeToFile(`Log level: ${currentLevel}`);
|
|
711
854
|
}
|
|
712
|
-
var fs2,
|
|
855
|
+
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
856
|
var init_logger = __esm({
|
|
714
857
|
"src/logging/logger.ts"() {
|
|
715
858
|
"use strict";
|
|
716
859
|
fs2 = __toESM(require("fs"));
|
|
717
|
-
|
|
860
|
+
path10 = __toESM(require("path"));
|
|
718
861
|
os4 = __toESM(require("os"));
|
|
719
862
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
720
863
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
721
864
|
currentLevel = "info";
|
|
722
|
-
LOG_DIR = process.platform === "win32" ?
|
|
865
|
+
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
866
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
724
867
|
MAX_LOG_DAYS = 7;
|
|
725
868
|
try {
|
|
@@ -727,16 +870,16 @@ var init_logger = __esm({
|
|
|
727
870
|
} catch {
|
|
728
871
|
}
|
|
729
872
|
currentDate = getDateStr();
|
|
730
|
-
currentLogFile =
|
|
873
|
+
currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
731
874
|
cleanOldLogs();
|
|
732
875
|
try {
|
|
733
|
-
const oldLog =
|
|
876
|
+
const oldLog = path10.join(LOG_DIR, "daemon.log");
|
|
734
877
|
if (fs2.existsSync(oldLog)) {
|
|
735
878
|
const stat2 = fs2.statSync(oldLog);
|
|
736
879
|
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
737
|
-
fs2.renameSync(oldLog,
|
|
880
|
+
fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
738
881
|
}
|
|
739
|
-
const oldLogBackup =
|
|
882
|
+
const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
|
|
740
883
|
if (fs2.existsSync(oldLogBackup)) {
|
|
741
884
|
fs2.unlinkSync(oldLogBackup);
|
|
742
885
|
}
|
|
@@ -768,7 +911,7 @@ var init_logger = __esm({
|
|
|
768
911
|
}
|
|
769
912
|
};
|
|
770
913
|
interceptorInstalled = false;
|
|
771
|
-
LOG_PATH =
|
|
914
|
+
LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
772
915
|
}
|
|
773
916
|
});
|
|
774
917
|
|
|
@@ -1236,9 +1379,9 @@ function buildCliScreenSnapshot(text) {
|
|
|
1236
1379
|
function findBinary(name) {
|
|
1237
1380
|
const trimmed = String(name || "").trim();
|
|
1238
1381
|
if (!trimmed) return trimmed;
|
|
1239
|
-
const expanded = trimmed.startsWith("~") ?
|
|
1240
|
-
if (
|
|
1241
|
-
return
|
|
1382
|
+
const expanded = trimmed.startsWith("~") ? path14.join(os9.homedir(), trimmed.slice(1)) : trimmed;
|
|
1383
|
+
if (path14.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
1384
|
+
return path14.isAbsolute(expanded) ? expanded : path14.resolve(expanded);
|
|
1242
1385
|
}
|
|
1243
1386
|
const isWin = os9.platform() === "win32";
|
|
1244
1387
|
try {
|
|
@@ -1254,7 +1397,7 @@ function findBinary(name) {
|
|
|
1254
1397
|
}
|
|
1255
1398
|
}
|
|
1256
1399
|
function isScriptBinary(binaryPath) {
|
|
1257
|
-
if (!
|
|
1400
|
+
if (!path14.isAbsolute(binaryPath)) return false;
|
|
1258
1401
|
try {
|
|
1259
1402
|
const fs16 = require("fs");
|
|
1260
1403
|
const resolved = fs16.realpathSync(binaryPath);
|
|
@@ -1270,7 +1413,7 @@ function isScriptBinary(binaryPath) {
|
|
|
1270
1413
|
}
|
|
1271
1414
|
}
|
|
1272
1415
|
function looksLikeMachOOrElf(filePath) {
|
|
1273
|
-
if (!
|
|
1416
|
+
if (!path14.isAbsolute(filePath)) return false;
|
|
1274
1417
|
try {
|
|
1275
1418
|
const fs16 = require("fs");
|
|
1276
1419
|
const resolved = fs16.realpathSync(filePath);
|
|
@@ -1359,12 +1502,12 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
1359
1502
|
}
|
|
1360
1503
|
};
|
|
1361
1504
|
}
|
|
1362
|
-
var os9,
|
|
1505
|
+
var os9, path14, import_child_process4, buildCliSpawnEnv;
|
|
1363
1506
|
var init_provider_cli_shared = __esm({
|
|
1364
1507
|
"src/cli-adapters/provider-cli-shared.ts"() {
|
|
1365
1508
|
"use strict";
|
|
1366
1509
|
os9 = __toESM(require("os"));
|
|
1367
|
-
|
|
1510
|
+
path14 = __toESM(require("path"));
|
|
1368
1511
|
import_child_process4 = require("child_process");
|
|
1369
1512
|
init_spawn_env();
|
|
1370
1513
|
buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
|
|
@@ -1487,7 +1630,7 @@ var init_provider_cli_config = __esm({
|
|
|
1487
1630
|
|
|
1488
1631
|
// src/cli-adapters/provider-cli-runtime.ts
|
|
1489
1632
|
function resolveCliSpawnPlan(options) {
|
|
1490
|
-
const { provider, runtimeSettings, workingDir, extraArgs } = options;
|
|
1633
|
+
const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
|
|
1491
1634
|
const { spawn: spawnConfig } = provider;
|
|
1492
1635
|
const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
1493
1636
|
const binaryPath = findBinary(configuredCommand);
|
|
@@ -1495,9 +1638,9 @@ function resolveCliSpawnPlan(options) {
|
|
|
1495
1638
|
const allArgs = [...spawnConfig.args, ...extraArgs];
|
|
1496
1639
|
let shellCmd;
|
|
1497
1640
|
let shellArgs;
|
|
1498
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1641
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1499
1642
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1500
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !
|
|
1643
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1501
1644
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1502
1645
|
if (useShell) {
|
|
1503
1646
|
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
@@ -1511,7 +1654,7 @@ function resolveCliSpawnPlan(options) {
|
|
|
1511
1654
|
shellCmd = binaryPath;
|
|
1512
1655
|
shellArgs = allArgs;
|
|
1513
1656
|
}
|
|
1514
|
-
const env = buildCliSpawnEnv(process.env, spawnConfig.env);
|
|
1657
|
+
const env = buildCliSpawnEnv(process.env, { ...spawnConfig.env || {}, ...extraEnv || {} });
|
|
1515
1658
|
env.TERMINAL_CWD = workingDir;
|
|
1516
1659
|
return {
|
|
1517
1660
|
binaryPath,
|
|
@@ -1573,12 +1716,12 @@ function respondToCliTerminalQueries(options) {
|
|
|
1573
1716
|
}
|
|
1574
1717
|
return "";
|
|
1575
1718
|
}
|
|
1576
|
-
var os10,
|
|
1719
|
+
var os10, path15, import_session_host_core2;
|
|
1577
1720
|
var init_provider_cli_runtime = __esm({
|
|
1578
1721
|
"src/cli-adapters/provider-cli-runtime.ts"() {
|
|
1579
1722
|
"use strict";
|
|
1580
1723
|
os10 = __toESM(require("os"));
|
|
1581
|
-
|
|
1724
|
+
path15 = __toESM(require("path"));
|
|
1582
1725
|
import_session_host_core2 = require("@adhdev/session-host-core");
|
|
1583
1726
|
init_provider_cli_shared();
|
|
1584
1727
|
}
|
|
@@ -1614,8 +1757,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1614
1757
|
init_provider_cli_runtime();
|
|
1615
1758
|
init_provider_cli_shared();
|
|
1616
1759
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
1617
|
-
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
1760
|
+
constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
|
|
1618
1761
|
this.extraArgs = extraArgs;
|
|
1762
|
+
this.extraEnv = extraEnv;
|
|
1619
1763
|
this.provider = provider;
|
|
1620
1764
|
this.transportFactory = transportFactory;
|
|
1621
1765
|
this.cliType = provider.type;
|
|
@@ -1766,8 +1910,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1766
1910
|
const currentSnapshot = normalizeScreenSnapshot(screenText);
|
|
1767
1911
|
const lastSnapshot = this.lastScreenSnapshot;
|
|
1768
1912
|
if (!lastSnapshot || lastSnapshot === currentSnapshot) return screenText;
|
|
1769
|
-
const
|
|
1770
|
-
const
|
|
1913
|
+
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;
|
|
1914
|
+
const staleSnapshotLooksActive = activeScreenPattern.test(lastSnapshot);
|
|
1915
|
+
const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:Try\s+["“][^\n\r"”]+["”])?\s*(?:\n|\r|$)/.test(screenText) && !activeScreenPattern.test(screenText);
|
|
1771
1916
|
if (staleSnapshotLooksActive && currentScreenLooksIdle) return screenText;
|
|
1772
1917
|
if (currentSnapshot.length >= lastSnapshot.length) return screenText;
|
|
1773
1918
|
return `${screenText}
|
|
@@ -1930,7 +2075,8 @@ ${lastSnapshot}`;
|
|
|
1930
2075
|
provider: this.provider,
|
|
1931
2076
|
runtimeSettings: this.runtimeSettings,
|
|
1932
2077
|
workingDir: this.workingDir,
|
|
1933
|
-
extraArgs: this.extraArgs
|
|
2078
|
+
extraArgs: this.extraArgs,
|
|
2079
|
+
extraEnv: this.extraEnv
|
|
1934
2080
|
});
|
|
1935
2081
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1936
2082
|
this.resetTraceSession();
|
|
@@ -3727,6 +3873,7 @@ __export(index_exports, {
|
|
|
3727
3873
|
createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
|
|
3728
3874
|
createInteractionId: () => createInteractionId,
|
|
3729
3875
|
createMesh: () => createMesh,
|
|
3876
|
+
createWorktree: () => createWorktree,
|
|
3730
3877
|
deleteMesh: () => deleteMesh,
|
|
3731
3878
|
detectAllVersions: () => detectAllVersions,
|
|
3732
3879
|
detectCLIs: () => detectCLIs,
|
|
@@ -3779,6 +3926,7 @@ __export(index_exports, {
|
|
|
3779
3926
|
launchWithCdp: () => launchWithCdp,
|
|
3780
3927
|
listHostedCliRuntimes: () => listHostedCliRuntimes,
|
|
3781
3928
|
listMeshes: () => listMeshes,
|
|
3929
|
+
listWorktrees: () => listWorktrees,
|
|
3782
3930
|
loadConfig: () => loadConfig,
|
|
3783
3931
|
loadState: () => loadState,
|
|
3784
3932
|
logCommand: () => logCommand,
|
|
@@ -3798,6 +3946,7 @@ __export(index_exports, {
|
|
|
3798
3946
|
normalizeSessionModalFields: () => normalizeSessionModalFields,
|
|
3799
3947
|
parsePorcelainV2Status: () => parsePorcelainV2Status,
|
|
3800
3948
|
parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
|
|
3949
|
+
parseWorktreeListOutput: () => parseWorktreeListOutput,
|
|
3801
3950
|
partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
|
|
3802
3951
|
partitionSessionHostRecords: () => partitionSessionHostRecords,
|
|
3803
3952
|
prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
|
|
@@ -3807,6 +3956,7 @@ __export(index_exports, {
|
|
|
3807
3956
|
recordDebugTrace: () => recordDebugTrace,
|
|
3808
3957
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
3809
3958
|
removeNode: () => removeNode,
|
|
3959
|
+
removeWorktree: () => removeWorktree,
|
|
3810
3960
|
resetConfig: () => resetConfig,
|
|
3811
3961
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
3812
3962
|
resetState: () => resetState,
|
|
@@ -3816,6 +3966,7 @@ __export(index_exports, {
|
|
|
3816
3966
|
resolveGitRepository: () => resolveGitRepository,
|
|
3817
3967
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
3818
3968
|
resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
|
|
3969
|
+
resolveWorktreePath: () => resolveWorktreePath,
|
|
3819
3970
|
runAsyncBatch: () => runAsyncBatch,
|
|
3820
3971
|
runGit: () => runGit,
|
|
3821
3972
|
saveConfig: () => saveConfig,
|
|
@@ -4739,6 +4890,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
|
4739
4890
|
"dirty_index_required",
|
|
4740
4891
|
"conflict",
|
|
4741
4892
|
"invalid_args",
|
|
4893
|
+
"nothing_to_commit",
|
|
4742
4894
|
"git_command_failed"
|
|
4743
4895
|
]);
|
|
4744
4896
|
function failure(reason, error) {
|
|
@@ -4983,7 +5135,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
|
|
|
4983
5135
|
} catch (err) {
|
|
4984
5136
|
const output = (err?.stdout || "") + (err?.stderr || "");
|
|
4985
5137
|
if (/nothing to commit/i.test(output)) {
|
|
4986
|
-
throw new GitCommandError("
|
|
5138
|
+
throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
|
|
5139
|
+
stdout: err?.stdout,
|
|
5140
|
+
stderr: err?.stderr
|
|
5141
|
+
});
|
|
4987
5142
|
}
|
|
4988
5143
|
throw err;
|
|
4989
5144
|
}
|
|
@@ -5175,20 +5330,23 @@ var TurnSnapshotTracker = class {
|
|
|
5175
5330
|
}
|
|
5176
5331
|
};
|
|
5177
5332
|
|
|
5333
|
+
// src/git/index.ts
|
|
5334
|
+
init_git_worktree();
|
|
5335
|
+
|
|
5178
5336
|
// src/index.ts
|
|
5179
5337
|
init_config();
|
|
5180
5338
|
|
|
5181
5339
|
// src/config/workspaces.ts
|
|
5182
5340
|
var fs = __toESM(require("fs"));
|
|
5183
5341
|
var os = __toESM(require("os"));
|
|
5184
|
-
var
|
|
5342
|
+
var path5 = __toESM(require("path"));
|
|
5185
5343
|
var import_crypto2 = require("crypto");
|
|
5186
5344
|
var MAX_WORKSPACES = 50;
|
|
5187
5345
|
function expandPath(p) {
|
|
5188
5346
|
const t = (p || "").trim();
|
|
5189
5347
|
if (!t) return "";
|
|
5190
|
-
if (t.startsWith("~")) return
|
|
5191
|
-
return
|
|
5348
|
+
if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
5349
|
+
return path5.resolve(t);
|
|
5192
5350
|
}
|
|
5193
5351
|
function validateWorkspacePath(absPath) {
|
|
5194
5352
|
try {
|
|
@@ -5202,7 +5360,7 @@ function validateWorkspacePath(absPath) {
|
|
|
5202
5360
|
}
|
|
5203
5361
|
}
|
|
5204
5362
|
function defaultWorkspaceLabel(absPath) {
|
|
5205
|
-
const base =
|
|
5363
|
+
const base = path5.basename(absPath) || absPath;
|
|
5206
5364
|
return base;
|
|
5207
5365
|
}
|
|
5208
5366
|
function getDefaultWorkspacePath(config) {
|
|
@@ -5293,9 +5451,9 @@ function resolveIdeLaunchWorkspace(args, config) {
|
|
|
5293
5451
|
return getDefaultWorkspacePath(config) || void 0;
|
|
5294
5452
|
}
|
|
5295
5453
|
function findWorkspaceByPath(config, rawPath) {
|
|
5296
|
-
const abs =
|
|
5454
|
+
const abs = path5.resolve(expandPath(rawPath));
|
|
5297
5455
|
if (!abs) return void 0;
|
|
5298
|
-
return (config.workspaces || []).find((w) =>
|
|
5456
|
+
return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
|
|
5299
5457
|
}
|
|
5300
5458
|
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
5301
5459
|
const abs = expandPath(rawPath);
|
|
@@ -5311,7 +5469,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
|
|
|
5311
5469
|
const v = validateWorkspacePath(abs);
|
|
5312
5470
|
if (!v.ok) return { error: v.error };
|
|
5313
5471
|
const list = [...config.workspaces || []];
|
|
5314
|
-
if (list.some((w) =>
|
|
5472
|
+
if (list.some((w) => path5.resolve(w.path) === abs)) {
|
|
5315
5473
|
return { error: "Workspace already in list" };
|
|
5316
5474
|
}
|
|
5317
5475
|
if (list.length >= MAX_WORKSPACES) {
|
|
@@ -5345,7 +5503,7 @@ function setDefaultWorkspaceId(config, id) {
|
|
|
5345
5503
|
}
|
|
5346
5504
|
|
|
5347
5505
|
// src/config/recent-activity.ts
|
|
5348
|
-
var
|
|
5506
|
+
var path6 = __toESM(require("path"));
|
|
5349
5507
|
|
|
5350
5508
|
// src/providers/summary-metadata.ts
|
|
5351
5509
|
function normalizeSummaryItem(item) {
|
|
@@ -5414,9 +5572,9 @@ var MAX_ACTIVITY = 30;
|
|
|
5414
5572
|
function normalizeWorkspace(workspace) {
|
|
5415
5573
|
if (!workspace) return "";
|
|
5416
5574
|
try {
|
|
5417
|
-
return
|
|
5575
|
+
return path6.resolve(expandPath(workspace));
|
|
5418
5576
|
} catch {
|
|
5419
|
-
return
|
|
5577
|
+
return path6.resolve(workspace);
|
|
5420
5578
|
}
|
|
5421
5579
|
}
|
|
5422
5580
|
function buildRecentActivityKey(entry) {
|
|
@@ -5584,14 +5742,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
|
|
|
5584
5742
|
}
|
|
5585
5743
|
|
|
5586
5744
|
// src/config/saved-sessions.ts
|
|
5587
|
-
var
|
|
5745
|
+
var path7 = __toESM(require("path"));
|
|
5588
5746
|
var MAX_SAVED_SESSIONS = 500;
|
|
5589
5747
|
function normalizeWorkspace2(workspace) {
|
|
5590
5748
|
if (!workspace) return "";
|
|
5591
5749
|
try {
|
|
5592
|
-
return
|
|
5750
|
+
return path7.resolve(expandPath(workspace));
|
|
5593
5751
|
} catch {
|
|
5594
|
-
return
|
|
5752
|
+
return path7.resolve(workspace);
|
|
5595
5753
|
}
|
|
5596
5754
|
}
|
|
5597
5755
|
function buildSavedProviderSessionKey(providerSessionId) {
|
|
@@ -5770,7 +5928,7 @@ function resetState() {
|
|
|
5770
5928
|
var import_child_process = require("child_process");
|
|
5771
5929
|
var import_fs4 = require("fs");
|
|
5772
5930
|
var import_os2 = require("os");
|
|
5773
|
-
var
|
|
5931
|
+
var path8 = __toESM(require("path"));
|
|
5774
5932
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
5775
5933
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
5776
5934
|
function registerIDEDefinition(def) {
|
|
@@ -5789,9 +5947,9 @@ function getMergedDefinitions() {
|
|
|
5789
5947
|
function findCliCommand(command) {
|
|
5790
5948
|
const trimmed = String(command || "").trim();
|
|
5791
5949
|
if (!trimmed) return null;
|
|
5792
|
-
if (
|
|
5793
|
-
const candidate = trimmed.startsWith("~") ?
|
|
5794
|
-
const resolved =
|
|
5950
|
+
if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
5951
|
+
const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
5952
|
+
const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
|
|
5795
5953
|
return (0, import_fs4.existsSync)(resolved) ? resolved : null;
|
|
5796
5954
|
}
|
|
5797
5955
|
try {
|
|
@@ -5819,7 +5977,7 @@ function getIdeVersion(cliCommand) {
|
|
|
5819
5977
|
function checkPathExists(paths) {
|
|
5820
5978
|
const home = (0, import_os2.homedir)();
|
|
5821
5979
|
for (const p of paths) {
|
|
5822
|
-
const normalized = p.startsWith("~") ?
|
|
5980
|
+
const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
|
|
5823
5981
|
if (normalized.includes("*")) {
|
|
5824
5982
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5825
5983
|
const resolved = normalized.replace("*", username);
|
|
@@ -5831,19 +5989,19 @@ function checkPathExists(paths) {
|
|
|
5831
5989
|
return null;
|
|
5832
5990
|
}
|
|
5833
5991
|
async function detectIDEs(providerLoader) {
|
|
5834
|
-
const
|
|
5992
|
+
const os22 = (0, import_os2.platform)();
|
|
5835
5993
|
const results = [];
|
|
5836
5994
|
for (const def of getMergedDefinitions()) {
|
|
5837
5995
|
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
5838
|
-
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[
|
|
5996
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
|
|
5839
5997
|
let resolvedCli = cliPath;
|
|
5840
|
-
if (!resolvedCli && appPath &&
|
|
5998
|
+
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
5841
5999
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
5842
6000
|
if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
5843
6001
|
}
|
|
5844
|
-
if (!resolvedCli && appPath &&
|
|
5845
|
-
const { dirname:
|
|
5846
|
-
const appDir =
|
|
6002
|
+
if (!resolvedCli && appPath && os22 === "win32") {
|
|
6003
|
+
const { dirname: dirname9 } = await import("path");
|
|
6004
|
+
const appDir = dirname9(appPath);
|
|
5847
6005
|
const candidates = [
|
|
5848
6006
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
5849
6007
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -5858,7 +6016,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5858
6016
|
}
|
|
5859
6017
|
}
|
|
5860
6018
|
}
|
|
5861
|
-
const installed =
|
|
6019
|
+
const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
5862
6020
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
5863
6021
|
results.push({
|
|
5864
6022
|
id: def.id,
|
|
@@ -5877,7 +6035,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5877
6035
|
// src/detection/cli-detector.ts
|
|
5878
6036
|
var import_child_process2 = require("child_process");
|
|
5879
6037
|
var os2 = __toESM(require("os"));
|
|
5880
|
-
var
|
|
6038
|
+
var path9 = __toESM(require("path"));
|
|
5881
6039
|
var import_fs5 = require("fs");
|
|
5882
6040
|
function parseVersion(raw) {
|
|
5883
6041
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
@@ -5890,18 +6048,18 @@ function shellQuote(value) {
|
|
|
5890
6048
|
function expandHome(value) {
|
|
5891
6049
|
const trimmed = value.trim();
|
|
5892
6050
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
5893
|
-
return
|
|
6051
|
+
return path9.join(os2.homedir(), trimmed.slice(1));
|
|
5894
6052
|
}
|
|
5895
6053
|
function isExplicitCommandPath(command) {
|
|
5896
6054
|
const trimmed = command.trim();
|
|
5897
|
-
return
|
|
6055
|
+
return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
5898
6056
|
}
|
|
5899
6057
|
function resolveCommandPath(command) {
|
|
5900
6058
|
const trimmed = command.trim();
|
|
5901
6059
|
if (!trimmed) return null;
|
|
5902
6060
|
if (isExplicitCommandPath(trimmed)) {
|
|
5903
6061
|
const expanded = expandHome(trimmed);
|
|
5904
|
-
const candidate =
|
|
6062
|
+
const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
5905
6063
|
return (0, import_fs5.existsSync)(candidate) ? candidate : null;
|
|
5906
6064
|
}
|
|
5907
6065
|
return null;
|
|
@@ -8170,9 +8328,9 @@ ${cleanBody}`;
|
|
|
8170
8328
|
|
|
8171
8329
|
// src/config/chat-history.ts
|
|
8172
8330
|
var fs3 = __toESM(require("fs"));
|
|
8173
|
-
var
|
|
8331
|
+
var path11 = __toESM(require("path"));
|
|
8174
8332
|
var os5 = __toESM(require("os"));
|
|
8175
|
-
var HISTORY_DIR =
|
|
8333
|
+
var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
|
|
8176
8334
|
var RETAIN_DAYS = 30;
|
|
8177
8335
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
8178
8336
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -8335,7 +8493,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
8335
8493
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
8336
8494
|
return new Map(files.map((file) => {
|
|
8337
8495
|
try {
|
|
8338
|
-
const stat2 = fs3.statSync(
|
|
8496
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8339
8497
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
8340
8498
|
} catch {
|
|
8341
8499
|
return [file, `${file}:missing`];
|
|
@@ -8346,7 +8504,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
8346
8504
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
8347
8505
|
}
|
|
8348
8506
|
function getSavedHistoryIndexFilePath(dir) {
|
|
8349
|
-
return
|
|
8507
|
+
return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
8350
8508
|
}
|
|
8351
8509
|
function getSavedHistoryIndexLockPath(dir) {
|
|
8352
8510
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -8448,7 +8606,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
8448
8606
|
}
|
|
8449
8607
|
for (const file of Array.from(currentEntries.keys())) {
|
|
8450
8608
|
if (incomingFiles.has(file)) continue;
|
|
8451
|
-
if (!fs3.existsSync(
|
|
8609
|
+
if (!fs3.existsSync(path11.join(dir, file))) {
|
|
8452
8610
|
currentEntries.delete(file);
|
|
8453
8611
|
}
|
|
8454
8612
|
}
|
|
@@ -8474,7 +8632,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8474
8632
|
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
8475
8633
|
const files = listHistoryFiles(dir);
|
|
8476
8634
|
for (const file of files) {
|
|
8477
|
-
const stat2 = fs3.statSync(
|
|
8635
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8478
8636
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
8479
8637
|
}
|
|
8480
8638
|
return false;
|
|
@@ -8484,14 +8642,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8484
8642
|
}
|
|
8485
8643
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
8486
8644
|
try {
|
|
8487
|
-
const stat2 = fs3.statSync(
|
|
8645
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8488
8646
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
8489
8647
|
} catch {
|
|
8490
8648
|
return `${file}:missing`;
|
|
8491
8649
|
}
|
|
8492
8650
|
}
|
|
8493
8651
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
8494
|
-
const filePath =
|
|
8652
|
+
const filePath = path11.join(dir, file);
|
|
8495
8653
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
8496
8654
|
const currentEntry = entries.get(file) || null;
|
|
8497
8655
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -8564,7 +8722,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
8564
8722
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
8565
8723
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
8566
8724
|
if (!historySessionId) return null;
|
|
8567
|
-
const filePath =
|
|
8725
|
+
const filePath = path11.join(dir, file);
|
|
8568
8726
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8569
8727
|
const lines = content.split("\n").filter(Boolean);
|
|
8570
8728
|
let messageCount = 0;
|
|
@@ -8651,7 +8809,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
8651
8809
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
8652
8810
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
8653
8811
|
for (const file of files.slice().sort()) {
|
|
8654
|
-
const filePath =
|
|
8812
|
+
const filePath = path11.join(dir, file);
|
|
8655
8813
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
8656
8814
|
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
8657
8815
|
const persisted = persistedEntries.get(file);
|
|
@@ -8771,12 +8929,12 @@ var ChatHistoryWriter = class {
|
|
|
8771
8929
|
});
|
|
8772
8930
|
}
|
|
8773
8931
|
if (newMessages.length === 0) return;
|
|
8774
|
-
const dir =
|
|
8932
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8775
8933
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8776
8934
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8777
8935
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
8778
8936
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
8779
|
-
const filePath =
|
|
8937
|
+
const filePath = path11.join(dir, fileName);
|
|
8780
8938
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
8781
8939
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
8782
8940
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -8867,11 +9025,11 @@ var ChatHistoryWriter = class {
|
|
|
8867
9025
|
const ws = String(workspace || "").trim();
|
|
8868
9026
|
if (!id || !ws) return;
|
|
8869
9027
|
try {
|
|
8870
|
-
const dir =
|
|
9028
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8871
9029
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8872
9030
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8873
9031
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
8874
|
-
const filePath =
|
|
9032
|
+
const filePath = path11.join(dir, fileName);
|
|
8875
9033
|
const record = {
|
|
8876
9034
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8877
9035
|
receivedAt: Date.now(),
|
|
@@ -8917,14 +9075,14 @@ var ChatHistoryWriter = class {
|
|
|
8917
9075
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
8918
9076
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
8919
9077
|
}
|
|
8920
|
-
const dir =
|
|
9078
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8921
9079
|
if (!fs3.existsSync(dir)) return;
|
|
8922
9080
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
8923
9081
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
8924
9082
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
8925
9083
|
for (const file of files) {
|
|
8926
|
-
const sourcePath =
|
|
8927
|
-
const targetPath =
|
|
9084
|
+
const sourcePath = path11.join(dir, file);
|
|
9085
|
+
const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
8928
9086
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
8929
9087
|
const rewritten = sourceLines.map((line) => {
|
|
8930
9088
|
try {
|
|
@@ -8958,13 +9116,13 @@ var ChatHistoryWriter = class {
|
|
|
8958
9116
|
const sessionId = String(historySessionId || "").trim();
|
|
8959
9117
|
if (!sessionId) return;
|
|
8960
9118
|
try {
|
|
8961
|
-
const dir =
|
|
9119
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8962
9120
|
if (!fs3.existsSync(dir)) return;
|
|
8963
9121
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
8964
9122
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
8965
9123
|
const seen = /* @__PURE__ */ new Set();
|
|
8966
9124
|
for (const file of files) {
|
|
8967
|
-
const filePath =
|
|
9125
|
+
const filePath = path11.join(dir, file);
|
|
8968
9126
|
const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
8969
9127
|
const next = [];
|
|
8970
9128
|
for (const line of lines) {
|
|
@@ -9018,11 +9176,11 @@ var ChatHistoryWriter = class {
|
|
|
9018
9176
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
9019
9177
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
9020
9178
|
for (const dir of agentDirs) {
|
|
9021
|
-
const dirPath =
|
|
9179
|
+
const dirPath = path11.join(HISTORY_DIR, dir.name);
|
|
9022
9180
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
9023
9181
|
let removedAny = false;
|
|
9024
9182
|
for (const file of files) {
|
|
9025
|
-
const filePath =
|
|
9183
|
+
const filePath = path11.join(dirPath, file);
|
|
9026
9184
|
const stat2 = fs3.statSync(filePath);
|
|
9027
9185
|
if (stat2.mtimeMs < cutoff) {
|
|
9028
9186
|
fs3.unlinkSync(filePath);
|
|
@@ -9072,13 +9230,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
9072
9230
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
9073
9231
|
try {
|
|
9074
9232
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9075
|
-
const dir =
|
|
9233
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
9076
9234
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
9077
9235
|
const files = listHistoryFiles(dir, historySessionId);
|
|
9078
9236
|
const allMessages = [];
|
|
9079
9237
|
const seen = /* @__PURE__ */ new Set();
|
|
9080
9238
|
for (const file of files) {
|
|
9081
|
-
const filePath =
|
|
9239
|
+
const filePath = path11.join(dir, file);
|
|
9082
9240
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
9083
9241
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
9084
9242
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -9102,7 +9260,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
9102
9260
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
9103
9261
|
try {
|
|
9104
9262
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9105
|
-
const dir =
|
|
9263
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
9106
9264
|
if (!fs3.existsSync(dir)) {
|
|
9107
9265
|
savedHistorySessionCache.delete(sanitized);
|
|
9108
9266
|
return { sessions: [], hasMore: false };
|
|
@@ -9163,11 +9321,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
9163
9321
|
}
|
|
9164
9322
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
9165
9323
|
try {
|
|
9166
|
-
const dir =
|
|
9324
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9167
9325
|
if (!fs3.existsSync(dir)) return null;
|
|
9168
9326
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
9169
9327
|
for (const file of files) {
|
|
9170
|
-
const lines = fs3.readFileSync(
|
|
9328
|
+
const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
9171
9329
|
for (const line of lines) {
|
|
9172
9330
|
try {
|
|
9173
9331
|
const parsed = JSON.parse(line);
|
|
@@ -9187,16 +9345,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
9187
9345
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
9188
9346
|
if (records.length === 0) return false;
|
|
9189
9347
|
try {
|
|
9190
|
-
const dir =
|
|
9348
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9191
9349
|
fs3.mkdirSync(dir, { recursive: true });
|
|
9192
9350
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
9193
9351
|
for (const file of fs3.readdirSync(dir)) {
|
|
9194
9352
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
9195
|
-
fs3.unlinkSync(
|
|
9353
|
+
fs3.unlinkSync(path11.join(dir, file));
|
|
9196
9354
|
}
|
|
9197
9355
|
}
|
|
9198
9356
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
9199
|
-
const filePath =
|
|
9357
|
+
const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
9200
9358
|
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
9201
9359
|
`, "utf-8");
|
|
9202
9360
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -11191,6 +11349,14 @@ function getActiveChatOptions(profile) {
|
|
|
11191
11349
|
if (profile === "full") return {};
|
|
11192
11350
|
return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
|
|
11193
11351
|
}
|
|
11352
|
+
function resolveSessionStatus(activeChat, providerStatus) {
|
|
11353
|
+
const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
|
|
11354
|
+
const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
|
|
11355
|
+
if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
|
|
11356
|
+
if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
|
|
11357
|
+
if (topLevelStatus !== "idle") return topLevelStatus;
|
|
11358
|
+
return chatStatus;
|
|
11359
|
+
}
|
|
11194
11360
|
function shouldIncludeSessionControls(profile) {
|
|
11195
11361
|
return profile !== "live";
|
|
11196
11362
|
}
|
|
@@ -11269,9 +11435,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
11269
11435
|
providerName: state.name,
|
|
11270
11436
|
kind: "workspace",
|
|
11271
11437
|
transport: "cdp-page",
|
|
11272
|
-
status:
|
|
11273
|
-
activeModal: activeChat?.activeModal || null
|
|
11274
|
-
}),
|
|
11438
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11275
11439
|
title,
|
|
11276
11440
|
workspace,
|
|
11277
11441
|
...git && { git },
|
|
@@ -11306,9 +11470,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
11306
11470
|
providerSessionId: ext.providerSessionId,
|
|
11307
11471
|
kind: "agent",
|
|
11308
11472
|
transport: "cdp-webview",
|
|
11309
|
-
status:
|
|
11310
|
-
activeModal: activeChat?.activeModal || null
|
|
11311
|
-
}),
|
|
11473
|
+
status: resolveSessionStatus(activeChat, ext.status),
|
|
11312
11474
|
title: activeChat?.title || ext.name,
|
|
11313
11475
|
workspace,
|
|
11314
11476
|
...git && { git },
|
|
@@ -11358,9 +11520,7 @@ function buildCliSession(state, options) {
|
|
|
11358
11520
|
providerSessionId: state.providerSessionId,
|
|
11359
11521
|
kind: "agent",
|
|
11360
11522
|
transport: "pty",
|
|
11361
|
-
status:
|
|
11362
|
-
activeModal: activeChat?.activeModal || null
|
|
11363
|
-
}),
|
|
11523
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11364
11524
|
title: activeChat?.title || state.name,
|
|
11365
11525
|
workspace,
|
|
11366
11526
|
...git && { git },
|
|
@@ -11408,9 +11568,7 @@ function buildAcpSession(state, options) {
|
|
|
11408
11568
|
providerName: state.name,
|
|
11409
11569
|
kind: "agent",
|
|
11410
11570
|
transport: "acp",
|
|
11411
|
-
status:
|
|
11412
|
-
activeModal: activeChat?.activeModal || null
|
|
11413
|
-
}),
|
|
11571
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11414
11572
|
title: activeChat?.title || state.name,
|
|
11415
11573
|
workspace,
|
|
11416
11574
|
...git && { git },
|
|
@@ -11533,7 +11691,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
11533
11691
|
// src/commands/chat-commands.ts
|
|
11534
11692
|
var fs4 = __toESM(require("fs"));
|
|
11535
11693
|
var os6 = __toESM(require("os"));
|
|
11536
|
-
var
|
|
11694
|
+
var path12 = __toESM(require("path"));
|
|
11537
11695
|
var import_node_crypto = require("crypto");
|
|
11538
11696
|
|
|
11539
11697
|
// src/providers/provider-input-support.ts
|
|
@@ -11896,6 +12054,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
|
|
|
11896
12054
|
return raw;
|
|
11897
12055
|
}
|
|
11898
12056
|
}
|
|
12057
|
+
function isGeneratingLikeStatus(status) {
|
|
12058
|
+
return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
|
|
12059
|
+
}
|
|
12060
|
+
function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
12061
|
+
if (!isGeneratingLikeStatus(parsedStatus)) return false;
|
|
12062
|
+
if (hasNonEmptyModalButtons(activeModal)) return false;
|
|
12063
|
+
const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
12064
|
+
if (adapterRawStatus !== "idle") return false;
|
|
12065
|
+
if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
|
|
12066
|
+
return true;
|
|
12067
|
+
}
|
|
12068
|
+
function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
12069
|
+
if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
|
|
12070
|
+
return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
|
|
12071
|
+
}
|
|
12072
|
+
function finalizeStreamingMessagesWhenIdle(messages, status) {
|
|
12073
|
+
if (status !== "idle") return messages;
|
|
12074
|
+
return messages.map((message) => {
|
|
12075
|
+
const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
|
|
12076
|
+
const hasStreamingMeta = meta?.streaming === true;
|
|
12077
|
+
if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
|
|
12078
|
+
return {
|
|
12079
|
+
...message,
|
|
12080
|
+
...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
|
|
12081
|
+
...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
|
|
12082
|
+
};
|
|
12083
|
+
});
|
|
12084
|
+
}
|
|
11899
12085
|
function buildReadChatCommandResult(payload, args) {
|
|
11900
12086
|
let validatedPayload;
|
|
11901
12087
|
const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
|
|
@@ -12044,7 +12230,7 @@ function buildDebugBundleText(bundle) {
|
|
|
12044
12230
|
}
|
|
12045
12231
|
function getChatDebugBundleDir() {
|
|
12046
12232
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
12047
|
-
return override ||
|
|
12233
|
+
return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
12048
12234
|
}
|
|
12049
12235
|
function safeBundleIdSegment(value, fallback) {
|
|
12050
12236
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -12077,7 +12263,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
12077
12263
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
12078
12264
|
const dir = getChatDebugBundleDir();
|
|
12079
12265
|
fs4.mkdirSync(dir, { recursive: true });
|
|
12080
|
-
const savedPath =
|
|
12266
|
+
const savedPath = path12.join(dir, `${bundleId}.json`);
|
|
12081
12267
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
12082
12268
|
`;
|
|
12083
12269
|
fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -12307,7 +12493,7 @@ async function handleChatHistory(h, args) {
|
|
|
12307
12493
|
}
|
|
12308
12494
|
}
|
|
12309
12495
|
async function handleReadChat(h, args) {
|
|
12310
|
-
const provider = h.getProvider(args?.agentType);
|
|
12496
|
+
const provider = h.getProvider(args?.agentType || args?.providerType);
|
|
12311
12497
|
const transport = getTargetTransport(h, provider);
|
|
12312
12498
|
const historySessionId = getHistorySessionId(h, args);
|
|
12313
12499
|
const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
|
|
@@ -12334,10 +12520,13 @@ async function handleReadChat(h, args) {
|
|
|
12334
12520
|
const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
|
|
12335
12521
|
const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
|
|
12336
12522
|
const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
|
|
12337
|
-
const returnedStatus = parsedRecord.status
|
|
12338
|
-
|
|
12523
|
+
const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
|
|
12524
|
+
const runtimeMessageMerger = getTargetInstance(h, args);
|
|
12525
|
+
const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
|
|
12526
|
+
const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
|
|
12527
|
+
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
12528
|
return buildReadChatCommandResult({
|
|
12340
|
-
messages:
|
|
12529
|
+
messages: returnedMessages,
|
|
12341
12530
|
status: returnedStatus,
|
|
12342
12531
|
activeModal,
|
|
12343
12532
|
debugReadChat: {
|
|
@@ -12348,7 +12537,7 @@ async function handleReadChat(h, args) {
|
|
|
12348
12537
|
returnedStatus: String(returnedStatus || ""),
|
|
12349
12538
|
shouldPreferAdapterMessages: false,
|
|
12350
12539
|
parsedMsgCount: parsedRecord.messages.length,
|
|
12351
|
-
returnedMsgCount:
|
|
12540
|
+
returnedMsgCount: returnedMessages.length
|
|
12352
12541
|
},
|
|
12353
12542
|
...title ? { title } : {},
|
|
12354
12543
|
...providerSessionId ? { providerSessionId } : {},
|
|
@@ -13221,7 +13410,7 @@ async function handleResolveAction(h, args) {
|
|
|
13221
13410
|
|
|
13222
13411
|
// src/commands/cdp-commands.ts
|
|
13223
13412
|
var fs5 = __toESM(require("fs"));
|
|
13224
|
-
var
|
|
13413
|
+
var path13 = __toESM(require("path"));
|
|
13225
13414
|
var os7 = __toESM(require("os"));
|
|
13226
13415
|
var KEY_TO_VK = {
|
|
13227
13416
|
Backspace: 8,
|
|
@@ -13478,25 +13667,25 @@ function resolveSafePath(requestedPath) {
|
|
|
13478
13667
|
const inputPath = rawPath || ".";
|
|
13479
13668
|
const home = os7.homedir();
|
|
13480
13669
|
if (inputPath.startsWith("~")) {
|
|
13481
|
-
return
|
|
13670
|
+
return path13.resolve(path13.join(home, inputPath.slice(1)));
|
|
13482
13671
|
}
|
|
13483
13672
|
if (process.platform === "win32") {
|
|
13484
13673
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
13485
|
-
if (
|
|
13486
|
-
return
|
|
13674
|
+
if (path13.win32.isAbsolute(normalized)) {
|
|
13675
|
+
return path13.win32.normalize(normalized);
|
|
13487
13676
|
}
|
|
13488
|
-
return
|
|
13677
|
+
return path13.win32.resolve(normalized);
|
|
13489
13678
|
}
|
|
13490
|
-
if (
|
|
13491
|
-
return
|
|
13679
|
+
if (path13.isAbsolute(inputPath)) {
|
|
13680
|
+
return path13.normalize(inputPath);
|
|
13492
13681
|
}
|
|
13493
|
-
return
|
|
13682
|
+
return path13.resolve(inputPath);
|
|
13494
13683
|
}
|
|
13495
13684
|
function listDirectoryEntriesSafe(dirPath) {
|
|
13496
13685
|
const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
|
|
13497
13686
|
const files = [];
|
|
13498
13687
|
for (const entry of entries) {
|
|
13499
|
-
const entryPath =
|
|
13688
|
+
const entryPath = path13.join(dirPath, entry.name);
|
|
13500
13689
|
try {
|
|
13501
13690
|
if (entry.isDirectory()) {
|
|
13502
13691
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -13550,7 +13739,7 @@ async function handleFileRead(h, args) {
|
|
|
13550
13739
|
async function handleFileWrite(h, args) {
|
|
13551
13740
|
try {
|
|
13552
13741
|
const filePath = resolveSafePath(args?.path);
|
|
13553
|
-
fs5.mkdirSync(
|
|
13742
|
+
fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
13554
13743
|
fs5.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
13555
13744
|
return { success: true, path: filePath };
|
|
13556
13745
|
} catch (e) {
|
|
@@ -14334,9 +14523,11 @@ var DaemonCommandHandler = class {
|
|
|
14334
14523
|
}
|
|
14335
14524
|
const sessionLookupFailed = !!targetSessionId && !session;
|
|
14336
14525
|
const managerKey = this.extractIdeType(args, sessionLookupFailed);
|
|
14337
|
-
let providerType;
|
|
14526
|
+
let providerType = args?.agentType || args?.providerType;
|
|
14338
14527
|
if (!sessionLookupFailed) {
|
|
14339
|
-
providerType = session?.providerType ||
|
|
14528
|
+
providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
|
|
14529
|
+
} else if (!providerType) {
|
|
14530
|
+
providerType = this.inferProviderType(managerKey);
|
|
14340
14531
|
}
|
|
14341
14532
|
return { session, managerKey, providerType, sessionLookupFailed };
|
|
14342
14533
|
}
|
|
@@ -14416,7 +14607,8 @@ var DaemonCommandHandler = class {
|
|
|
14416
14607
|
"pty_resize",
|
|
14417
14608
|
"invoke_provider_script"
|
|
14418
14609
|
]);
|
|
14419
|
-
|
|
14610
|
+
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);
|
|
14611
|
+
if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
|
|
14420
14612
|
const result2 = {
|
|
14421
14613
|
success: false,
|
|
14422
14614
|
error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
|
|
@@ -14669,7 +14861,7 @@ var DaemonCommandHandler = class {
|
|
|
14669
14861
|
|
|
14670
14862
|
// src/commands/cli-manager.ts
|
|
14671
14863
|
var os13 = __toESM(require("os"));
|
|
14672
|
-
var
|
|
14864
|
+
var path17 = __toESM(require("path"));
|
|
14673
14865
|
var crypto4 = __toESM(require("crypto"));
|
|
14674
14866
|
var import_fs6 = require("fs");
|
|
14675
14867
|
var import_child_process6 = require("child_process");
|
|
@@ -14679,7 +14871,7 @@ init_config();
|
|
|
14679
14871
|
|
|
14680
14872
|
// src/providers/cli-provider-instance.ts
|
|
14681
14873
|
var os12 = __toESM(require("os"));
|
|
14682
|
-
var
|
|
14874
|
+
var path16 = __toESM(require("path"));
|
|
14683
14875
|
var crypto3 = __toESM(require("crypto"));
|
|
14684
14876
|
var fs6 = __toESM(require("fs"));
|
|
14685
14877
|
var import_node_module = require("module");
|
|
@@ -14738,7 +14930,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
|
|
|
14738
14930
|
var CachedDatabaseSync = null;
|
|
14739
14931
|
function getDatabaseSync() {
|
|
14740
14932
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
14741
|
-
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
14933
|
+
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
14742
14934
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
14743
14935
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
14744
14936
|
if (!CachedDatabaseSync) {
|
|
@@ -14791,7 +14983,7 @@ var CliProviderInstance = class {
|
|
|
14791
14983
|
this.providerSessionId = options?.providerSessionId;
|
|
14792
14984
|
this.launchMode = options?.launchMode || "new";
|
|
14793
14985
|
this.onProviderSessionResolved = options?.onProviderSessionResolved;
|
|
14794
|
-
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
14986
|
+
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
|
|
14795
14987
|
this.monitor = new StatusMonitor();
|
|
14796
14988
|
this.historyWriter = new ChatHistoryWriter();
|
|
14797
14989
|
}
|
|
@@ -15268,7 +15460,19 @@ var CliProviderInstance = class {
|
|
|
15268
15460
|
}
|
|
15269
15461
|
}
|
|
15270
15462
|
pushEvent(event) {
|
|
15271
|
-
|
|
15463
|
+
const enrichedEvent = {
|
|
15464
|
+
...event,
|
|
15465
|
+
instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
|
|
15466
|
+
targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
|
|
15467
|
+
providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
|
|
15468
|
+
workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
|
|
15469
|
+
providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
|
|
15470
|
+
};
|
|
15471
|
+
if (this.context?.emitProviderEvent) {
|
|
15472
|
+
this.context.emitProviderEvent(enrichedEvent);
|
|
15473
|
+
return;
|
|
15474
|
+
}
|
|
15475
|
+
this.events.push(enrichedEvent);
|
|
15272
15476
|
}
|
|
15273
15477
|
flushEvents() {
|
|
15274
15478
|
const events = [...this.events];
|
|
@@ -15475,12 +15679,31 @@ ${effect.notification.body || ""}`.trim();
|
|
|
15475
15679
|
);
|
|
15476
15680
|
}
|
|
15477
15681
|
}
|
|
15682
|
+
mergeRuntimeChatMessages(parsedMessages) {
|
|
15683
|
+
return this.mergeConversationMessages(parsedMessages);
|
|
15684
|
+
}
|
|
15478
15685
|
mergeConversationMessages(parsedMessages) {
|
|
15479
15686
|
if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15687
|
+
const parsedEntries = parsedMessages.map((message, index) => ({
|
|
15688
|
+
message,
|
|
15689
|
+
index,
|
|
15690
|
+
source: "parsed"
|
|
15691
|
+
}));
|
|
15692
|
+
const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
|
|
15693
|
+
message: entry.message,
|
|
15694
|
+
index: parsedMessages.length + index,
|
|
15695
|
+
source: "runtime"
|
|
15696
|
+
}));
|
|
15697
|
+
const getTime = (message) => {
|
|
15698
|
+
const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
|
|
15699
|
+
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
15700
|
+
};
|
|
15701
|
+
return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
|
|
15702
|
+
const aTime = getTime(a.message);
|
|
15703
|
+
const bTime = getTime(b.message);
|
|
15704
|
+
if (aTime && bTime && aTime !== bTime) return aTime - bTime;
|
|
15705
|
+
if (aTime && !bTime && a.source === "runtime" && b.source === "parsed") return -1;
|
|
15706
|
+
if (!aTime && bTime && a.source === "parsed" && b.source === "runtime") return 1;
|
|
15484
15707
|
return a.index - b.index;
|
|
15485
15708
|
}).map((entry) => entry.message));
|
|
15486
15709
|
}
|
|
@@ -16804,11 +17027,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
|
|
|
16804
17027
|
// src/commands/cli-manager.ts
|
|
16805
17028
|
function isExplicitCommand(command) {
|
|
16806
17029
|
const trimmed = command.trim();
|
|
16807
|
-
return
|
|
17030
|
+
return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
16808
17031
|
}
|
|
16809
17032
|
function expandExecutable(command) {
|
|
16810
17033
|
const trimmed = command.trim();
|
|
16811
|
-
return trimmed.startsWith("~") ?
|
|
17034
|
+
return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
|
|
16812
17035
|
}
|
|
16813
17036
|
function commandExists(command) {
|
|
16814
17037
|
const trimmed = command.trim();
|
|
@@ -16832,6 +17055,35 @@ function colorize(color, text) {
|
|
|
16832
17055
|
const fn = chalkApi?.[color];
|
|
16833
17056
|
return typeof fn === "function" ? fn(text) : text;
|
|
16834
17057
|
}
|
|
17058
|
+
var COORDINATOR_DELEGATED_ENV_UNSETS = {
|
|
17059
|
+
ADHDEV_INLINE_MESH: "",
|
|
17060
|
+
ADHDEV_MCP_TRANSPORT: "",
|
|
17061
|
+
ADHDEV_MESH_ID: "",
|
|
17062
|
+
HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
|
|
17063
|
+
};
|
|
17064
|
+
function hasCliArg(args, flag) {
|
|
17065
|
+
return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
17066
|
+
}
|
|
17067
|
+
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
17068
|
+
const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
17069
|
+
(0, import_fs6.mkdirSync)(baseDir, { recursive: true });
|
|
17070
|
+
const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
|
|
17071
|
+
const filePath = path17.join(baseDir, `${workspaceHash}.json`);
|
|
17072
|
+
(0, import_fs6.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
17073
|
+
return filePath;
|
|
17074
|
+
}
|
|
17075
|
+
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
17076
|
+
const cliType = String(input.cliType || "").trim();
|
|
17077
|
+
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
17078
|
+
const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
|
|
17079
|
+
if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
|
|
17080
|
+
cliArgs.unshift("--ignore-user-config");
|
|
17081
|
+
}
|
|
17082
|
+
if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
|
|
17083
|
+
cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
17084
|
+
}
|
|
17085
|
+
return { cliArgs, env };
|
|
17086
|
+
}
|
|
16835
17087
|
function isUuid(value) {
|
|
16836
17088
|
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
17089
|
}
|
|
@@ -17002,7 +17254,7 @@ var DaemonCliManager = class {
|
|
|
17002
17254
|
attachExisting
|
|
17003
17255
|
}) || void 0;
|
|
17004
17256
|
}
|
|
17005
|
-
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
|
|
17257
|
+
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
|
|
17006
17258
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
17007
17259
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
17008
17260
|
if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
|
|
@@ -17016,7 +17268,7 @@ var DaemonCliManager = class {
|
|
|
17016
17268
|
providerSessionId,
|
|
17017
17269
|
attachExisting
|
|
17018
17270
|
);
|
|
17019
|
-
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
|
|
17271
|
+
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
|
|
17020
17272
|
}
|
|
17021
17273
|
throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
|
|
17022
17274
|
}
|
|
@@ -17089,7 +17341,7 @@ var DaemonCliManager = class {
|
|
|
17089
17341
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
17090
17342
|
const trimmed = (workingDir || "").trim();
|
|
17091
17343
|
if (!trimmed) throw new Error("working directory required");
|
|
17092
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
17344
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
|
|
17093
17345
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
17094
17346
|
const rawProvider = this.providerLoader.getByAlias(cliType);
|
|
17095
17347
|
const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
|
|
@@ -17219,6 +17471,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17219
17471
|
{
|
|
17220
17472
|
providerSessionId: sessionBinding.providerSessionId,
|
|
17221
17473
|
launchMode: sessionBinding.launchMode,
|
|
17474
|
+
extraEnv: options?.extraEnv,
|
|
17222
17475
|
onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
|
|
17223
17476
|
this.persistRecentActivity({
|
|
17224
17477
|
kind: "cli",
|
|
@@ -17239,7 +17492,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17239
17492
|
resolvedCliArgs,
|
|
17240
17493
|
key,
|
|
17241
17494
|
sessionBinding.providerSessionId,
|
|
17242
|
-
false
|
|
17495
|
+
false,
|
|
17496
|
+
options?.extraEnv
|
|
17243
17497
|
);
|
|
17244
17498
|
try {
|
|
17245
17499
|
await adapter.spawn();
|
|
@@ -17463,12 +17717,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17463
17717
|
const dir = resolved.path;
|
|
17464
17718
|
const launchSource = resolved.source;
|
|
17465
17719
|
if (!cliType) throw new Error("cliType required");
|
|
17720
|
+
const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
17721
|
+
const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
|
|
17722
|
+
cliType,
|
|
17723
|
+
workspace: dir,
|
|
17724
|
+
cliArgs: args?.cliArgs,
|
|
17725
|
+
env: args?.env
|
|
17726
|
+
}) : null;
|
|
17466
17727
|
const started = await this.startSession(
|
|
17467
17728
|
cliType,
|
|
17468
17729
|
dir,
|
|
17469
|
-
args?.cliArgs,
|
|
17730
|
+
delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
|
|
17470
17731
|
args?.initialModel,
|
|
17471
|
-
{
|
|
17732
|
+
{
|
|
17733
|
+
resumeSessionId: args?.resumeSessionId,
|
|
17734
|
+
settingsOverride,
|
|
17735
|
+
extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
|
|
17736
|
+
}
|
|
17472
17737
|
);
|
|
17473
17738
|
return {
|
|
17474
17739
|
success: true,
|
|
@@ -17590,11 +17855,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17590
17855
|
var import_child_process7 = require("child_process");
|
|
17591
17856
|
var net = __toESM(require("net"));
|
|
17592
17857
|
var os15 = __toESM(require("os"));
|
|
17593
|
-
var
|
|
17858
|
+
var path19 = __toESM(require("path"));
|
|
17594
17859
|
|
|
17595
17860
|
// src/providers/provider-loader.ts
|
|
17596
17861
|
var fs7 = __toESM(require("fs"));
|
|
17597
|
-
var
|
|
17862
|
+
var path18 = __toESM(require("path"));
|
|
17598
17863
|
var os14 = __toESM(require("os"));
|
|
17599
17864
|
var chokidar = __toESM(require("chokidar"));
|
|
17600
17865
|
init_logger();
|
|
@@ -17918,7 +18183,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17918
18183
|
try {
|
|
17919
18184
|
if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
|
|
17920
18185
|
return ["ide", "extension", "cli", "acp"].some(
|
|
17921
|
-
(category) => fs7.existsSync(
|
|
18186
|
+
(category) => fs7.existsSync(path18.join(candidate, category))
|
|
17922
18187
|
);
|
|
17923
18188
|
} catch {
|
|
17924
18189
|
return false;
|
|
@@ -17926,20 +18191,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17926
18191
|
}
|
|
17927
18192
|
static hasProviderRootMarker(candidate) {
|
|
17928
18193
|
try {
|
|
17929
|
-
return fs7.existsSync(
|
|
18194
|
+
return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
17930
18195
|
} catch {
|
|
17931
18196
|
return false;
|
|
17932
18197
|
}
|
|
17933
18198
|
}
|
|
17934
18199
|
detectDefaultUserDir() {
|
|
17935
|
-
const fallback =
|
|
18200
|
+
const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17936
18201
|
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
17937
18202
|
const visited = /* @__PURE__ */ new Set();
|
|
17938
18203
|
for (const start of this.probeStarts) {
|
|
17939
|
-
let current =
|
|
18204
|
+
let current = path18.resolve(start);
|
|
17940
18205
|
while (!visited.has(current)) {
|
|
17941
18206
|
visited.add(current);
|
|
17942
|
-
const siblingCandidate =
|
|
18207
|
+
const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
17943
18208
|
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
17944
18209
|
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
17945
18210
|
if (envOptIn || hasMarker) {
|
|
@@ -17961,7 +18226,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17961
18226
|
return { path: siblingCandidate, source };
|
|
17962
18227
|
}
|
|
17963
18228
|
}
|
|
17964
|
-
const parent =
|
|
18229
|
+
const parent = path18.dirname(current);
|
|
17965
18230
|
if (parent === current) break;
|
|
17966
18231
|
current = parent;
|
|
17967
18232
|
}
|
|
@@ -17971,11 +18236,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17971
18236
|
constructor(options) {
|
|
17972
18237
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
17973
18238
|
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
17974
|
-
this.defaultProvidersDir =
|
|
18239
|
+
this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17975
18240
|
const detected = this.detectDefaultUserDir();
|
|
17976
18241
|
this.userDir = detected.path;
|
|
17977
18242
|
this.userDirSource = detected.source;
|
|
17978
|
-
this.upstreamDir =
|
|
18243
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17979
18244
|
this.disableUpstream = false;
|
|
17980
18245
|
this.applySourceConfig({
|
|
17981
18246
|
userDir: options?.userDir,
|
|
@@ -18034,7 +18299,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18034
18299
|
this.userDir = detected.path;
|
|
18035
18300
|
this.userDirSource = detected.source;
|
|
18036
18301
|
}
|
|
18037
|
-
this.upstreamDir =
|
|
18302
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
18038
18303
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
18039
18304
|
if (this.explicitProviderDir) {
|
|
18040
18305
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -18048,7 +18313,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18048
18313
|
* Canonical provider directory shape for a given root.
|
|
18049
18314
|
*/
|
|
18050
18315
|
getProviderDir(root, category, type) {
|
|
18051
|
-
return
|
|
18316
|
+
return path18.join(root, category, type);
|
|
18052
18317
|
}
|
|
18053
18318
|
/**
|
|
18054
18319
|
* Canonical user override directory for a provider.
|
|
@@ -18075,7 +18340,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18075
18340
|
resolveProviderFile(type, ...segments) {
|
|
18076
18341
|
const dir = this.findProviderDirInternal(type);
|
|
18077
18342
|
if (!dir) return null;
|
|
18078
|
-
return
|
|
18343
|
+
return path18.join(dir, ...segments);
|
|
18079
18344
|
}
|
|
18080
18345
|
/**
|
|
18081
18346
|
* Load all providers (3-tier priority)
|
|
@@ -18114,7 +18379,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18114
18379
|
if (!fs7.existsSync(this.upstreamDir)) return false;
|
|
18115
18380
|
try {
|
|
18116
18381
|
return fs7.readdirSync(this.upstreamDir).some(
|
|
18117
|
-
(d) => fs7.statSync(
|
|
18382
|
+
(d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
|
|
18118
18383
|
);
|
|
18119
18384
|
} catch {
|
|
18120
18385
|
return false;
|
|
@@ -18611,8 +18876,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18611
18876
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
18612
18877
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
18613
18878
|
if (providerDir) {
|
|
18614
|
-
const fullDir =
|
|
18615
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18879
|
+
const fullDir = path18.join(providerDir, entry.scriptDir);
|
|
18880
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18616
18881
|
}
|
|
18617
18882
|
matched = true;
|
|
18618
18883
|
}
|
|
@@ -18627,8 +18892,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18627
18892
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18628
18893
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
18629
18894
|
if (providerDir) {
|
|
18630
|
-
const fullDir =
|
|
18631
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18895
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18896
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18632
18897
|
}
|
|
18633
18898
|
}
|
|
18634
18899
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -18645,8 +18910,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18645
18910
|
resolved._resolvedScriptDir = dirOverride;
|
|
18646
18911
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
18647
18912
|
if (providerDir) {
|
|
18648
|
-
const fullDir =
|
|
18649
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18913
|
+
const fullDir = path18.join(providerDir, dirOverride);
|
|
18914
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18650
18915
|
}
|
|
18651
18916
|
}
|
|
18652
18917
|
} else if (override.scripts) {
|
|
@@ -18662,8 +18927,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18662
18927
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18663
18928
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
18664
18929
|
if (providerDir) {
|
|
18665
|
-
const fullDir =
|
|
18666
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18930
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18931
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18667
18932
|
}
|
|
18668
18933
|
}
|
|
18669
18934
|
}
|
|
@@ -18695,14 +18960,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18695
18960
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
18696
18961
|
return null;
|
|
18697
18962
|
}
|
|
18698
|
-
const dir =
|
|
18963
|
+
const dir = path18.join(providerDir, scriptDir);
|
|
18699
18964
|
if (!fs7.existsSync(dir)) {
|
|
18700
18965
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
18701
18966
|
return null;
|
|
18702
18967
|
}
|
|
18703
18968
|
const cached = this.scriptsCache.get(dir);
|
|
18704
18969
|
if (cached) return cached;
|
|
18705
|
-
const scriptsJs =
|
|
18970
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
18706
18971
|
if (fs7.existsSync(scriptsJs)) {
|
|
18707
18972
|
try {
|
|
18708
18973
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -18744,7 +19009,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18744
19009
|
return;
|
|
18745
19010
|
}
|
|
18746
19011
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
18747
|
-
this.log(`File changed: ${
|
|
19012
|
+
this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
|
|
18748
19013
|
this.reload();
|
|
18749
19014
|
}
|
|
18750
19015
|
};
|
|
@@ -18799,7 +19064,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18799
19064
|
}
|
|
18800
19065
|
const https = require("https");
|
|
18801
19066
|
const { execSync: execSync7 } = require("child_process");
|
|
18802
|
-
const metaPath =
|
|
19067
|
+
const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
18803
19068
|
let prevEtag = "";
|
|
18804
19069
|
let prevTimestamp = 0;
|
|
18805
19070
|
try {
|
|
@@ -18859,17 +19124,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18859
19124
|
return { updated: false };
|
|
18860
19125
|
}
|
|
18861
19126
|
this.log("Downloading latest providers from GitHub...");
|
|
18862
|
-
const tmpTar =
|
|
18863
|
-
const tmpExtract =
|
|
19127
|
+
const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
19128
|
+
const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
18864
19129
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
18865
19130
|
fs7.mkdirSync(tmpExtract, { recursive: true });
|
|
18866
19131
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
18867
19132
|
const extracted = fs7.readdirSync(tmpExtract);
|
|
18868
19133
|
const rootDir = extracted.find(
|
|
18869
|
-
(d) => fs7.statSync(
|
|
19134
|
+
(d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
18870
19135
|
);
|
|
18871
19136
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
18872
|
-
const sourceDir =
|
|
19137
|
+
const sourceDir = path18.join(tmpExtract, rootDir);
|
|
18873
19138
|
const backupDir = this.upstreamDir + ".bak";
|
|
18874
19139
|
if (fs7.existsSync(this.upstreamDir)) {
|
|
18875
19140
|
if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -18944,8 +19209,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18944
19209
|
copyDirRecursive(src, dest) {
|
|
18945
19210
|
fs7.mkdirSync(dest, { recursive: true });
|
|
18946
19211
|
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
18947
|
-
const srcPath =
|
|
18948
|
-
const destPath =
|
|
19212
|
+
const srcPath = path18.join(src, entry.name);
|
|
19213
|
+
const destPath = path18.join(dest, entry.name);
|
|
18949
19214
|
if (entry.isDirectory()) {
|
|
18950
19215
|
this.copyDirRecursive(srcPath, destPath);
|
|
18951
19216
|
} else {
|
|
@@ -18956,7 +19221,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18956
19221
|
/** .meta.json save */
|
|
18957
19222
|
writeMeta(metaPath, etag, timestamp) {
|
|
18958
19223
|
try {
|
|
18959
|
-
fs7.mkdirSync(
|
|
19224
|
+
fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
|
|
18960
19225
|
fs7.writeFileSync(metaPath, JSON.stringify({
|
|
18961
19226
|
etag,
|
|
18962
19227
|
timestamp,
|
|
@@ -18973,7 +19238,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18973
19238
|
const scan = (d) => {
|
|
18974
19239
|
try {
|
|
18975
19240
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
18976
|
-
if (entry.isDirectory()) scan(
|
|
19241
|
+
if (entry.isDirectory()) scan(path18.join(d, entry.name));
|
|
18977
19242
|
else if (entry.name === "provider.json") count++;
|
|
18978
19243
|
}
|
|
18979
19244
|
} catch {
|
|
@@ -19201,17 +19466,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19201
19466
|
for (const root of searchRoots) {
|
|
19202
19467
|
if (!fs7.existsSync(root)) continue;
|
|
19203
19468
|
const candidate = this.getProviderDir(root, cat, type);
|
|
19204
|
-
if (fs7.existsSync(
|
|
19205
|
-
const catDir =
|
|
19469
|
+
if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
|
|
19470
|
+
const catDir = path18.join(root, cat);
|
|
19206
19471
|
if (fs7.existsSync(catDir)) {
|
|
19207
19472
|
try {
|
|
19208
19473
|
for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
|
|
19209
19474
|
if (!entry.isDirectory()) continue;
|
|
19210
|
-
const jsonPath =
|
|
19475
|
+
const jsonPath = path18.join(catDir, entry.name, "provider.json");
|
|
19211
19476
|
if (fs7.existsSync(jsonPath)) {
|
|
19212
19477
|
try {
|
|
19213
19478
|
const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
|
|
19214
|
-
if (data.type === type) return
|
|
19479
|
+
if (data.type === type) return path18.join(catDir, entry.name);
|
|
19215
19480
|
} catch {
|
|
19216
19481
|
}
|
|
19217
19482
|
}
|
|
@@ -19228,7 +19493,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19228
19493
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
19229
19494
|
*/
|
|
19230
19495
|
buildScriptWrappersFromDir(dir) {
|
|
19231
|
-
const scriptsJs =
|
|
19496
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
19232
19497
|
if (fs7.existsSync(scriptsJs)) {
|
|
19233
19498
|
try {
|
|
19234
19499
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -19242,7 +19507,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19242
19507
|
for (const file of fs7.readdirSync(dir)) {
|
|
19243
19508
|
if (!file.endsWith(".js")) continue;
|
|
19244
19509
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
19245
|
-
const filePath =
|
|
19510
|
+
const filePath = path18.join(dir, file);
|
|
19246
19511
|
result[scriptName] = (...args) => {
|
|
19247
19512
|
try {
|
|
19248
19513
|
let content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -19302,7 +19567,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19302
19567
|
}
|
|
19303
19568
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
19304
19569
|
if (hasJson) {
|
|
19305
|
-
const jsonPath =
|
|
19570
|
+
const jsonPath = path18.join(d, "provider.json");
|
|
19306
19571
|
try {
|
|
19307
19572
|
const raw = fs7.readFileSync(jsonPath, "utf-8");
|
|
19308
19573
|
const mod = JSON.parse(raw);
|
|
@@ -19323,7 +19588,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19323
19588
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
19324
19589
|
} else {
|
|
19325
19590
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
19326
|
-
const scriptsPath =
|
|
19591
|
+
const scriptsPath = path18.join(d, "scripts.js");
|
|
19327
19592
|
if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
|
|
19328
19593
|
try {
|
|
19329
19594
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -19349,7 +19614,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19349
19614
|
if (!entry.isDirectory()) continue;
|
|
19350
19615
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
19351
19616
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
19352
|
-
scan(
|
|
19617
|
+
scan(path18.join(d, entry.name));
|
|
19353
19618
|
}
|
|
19354
19619
|
}
|
|
19355
19620
|
};
|
|
@@ -19674,8 +19939,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
19674
19939
|
const appNameMap = getMacAppIdentifiers();
|
|
19675
19940
|
const appName = appNameMap[ideId];
|
|
19676
19941
|
if (appName) {
|
|
19677
|
-
const storagePath =
|
|
19678
|
-
process.env.APPDATA ||
|
|
19942
|
+
const storagePath = path19.join(
|
|
19943
|
+
process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
|
|
19679
19944
|
appName,
|
|
19680
19945
|
"storage.json"
|
|
19681
19946
|
);
|
|
@@ -19864,9 +20129,9 @@ init_logger();
|
|
|
19864
20129
|
|
|
19865
20130
|
// src/logging/command-log.ts
|
|
19866
20131
|
var fs8 = __toESM(require("fs"));
|
|
19867
|
-
var
|
|
20132
|
+
var path20 = __toESM(require("path"));
|
|
19868
20133
|
var os16 = __toESM(require("os"));
|
|
19869
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
20134
|
+
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
20135
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
19871
20136
|
var MAX_DAYS = 7;
|
|
19872
20137
|
try {
|
|
@@ -19904,13 +20169,13 @@ function getDateStr2() {
|
|
|
19904
20169
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
19905
20170
|
}
|
|
19906
20171
|
var currentDate2 = getDateStr2();
|
|
19907
|
-
var currentFile =
|
|
20172
|
+
var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19908
20173
|
var writeCount2 = 0;
|
|
19909
20174
|
function checkRotation() {
|
|
19910
20175
|
const today = getDateStr2();
|
|
19911
20176
|
if (today !== currentDate2) {
|
|
19912
20177
|
currentDate2 = today;
|
|
19913
|
-
currentFile =
|
|
20178
|
+
currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19914
20179
|
cleanOldFiles();
|
|
19915
20180
|
}
|
|
19916
20181
|
}
|
|
@@ -19924,7 +20189,7 @@ function cleanOldFiles() {
|
|
|
19924
20189
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
19925
20190
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
19926
20191
|
try {
|
|
19927
|
-
fs8.unlinkSync(
|
|
20192
|
+
fs8.unlinkSync(path20.join(LOG_DIR2, file));
|
|
19928
20193
|
} catch {
|
|
19929
20194
|
}
|
|
19930
20195
|
}
|
|
@@ -20007,14 +20272,66 @@ function getRecentCommands(count = 50) {
|
|
|
20007
20272
|
cleanOldFiles();
|
|
20008
20273
|
|
|
20009
20274
|
// src/commands/router.ts
|
|
20275
|
+
var yaml = __toESM(require("js-yaml"));
|
|
20010
20276
|
init_logger();
|
|
20011
20277
|
|
|
20012
20278
|
// src/commands/mesh-coordinator.ts
|
|
20013
|
-
var
|
|
20279
|
+
var import_node_child_process3 = require("child_process");
|
|
20280
|
+
var import_node_fs3 = require("fs");
|
|
20014
20281
|
var import_node_module2 = require("module");
|
|
20282
|
+
var os17 = __toESM(require("os"));
|
|
20015
20283
|
var import_node_path = require("path");
|
|
20016
20284
|
var DEFAULT_SERVER_NAME = "adhdev-mesh";
|
|
20017
20285
|
var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
20286
|
+
var HERMES_CLI_TYPE = "hermes-cli";
|
|
20287
|
+
var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
|
|
20288
|
+
function isHermesProvider(provider, cliType) {
|
|
20289
|
+
const type = cliType?.trim() || provider?.type?.trim() || "";
|
|
20290
|
+
return type === HERMES_CLI_TYPE;
|
|
20291
|
+
}
|
|
20292
|
+
function resolveHermesMeshCoordinatorSetup(options) {
|
|
20293
|
+
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
20294
|
+
meshId: options.meshId,
|
|
20295
|
+
nodeExecutable: options.nodeExecutable,
|
|
20296
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
20297
|
+
});
|
|
20298
|
+
if (!mcpServer) {
|
|
20299
|
+
return {
|
|
20300
|
+
kind: "unsupported",
|
|
20301
|
+
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
20302
|
+
};
|
|
20303
|
+
}
|
|
20304
|
+
const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
|
|
20305
|
+
if (!configPath.trim()) {
|
|
20306
|
+
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
|
|
20307
|
+
}
|
|
20308
|
+
return {
|
|
20309
|
+
kind: "auto_import",
|
|
20310
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20311
|
+
configPath,
|
|
20312
|
+
configFormat: "hermes_config_yaml",
|
|
20313
|
+
mcpServer
|
|
20314
|
+
};
|
|
20315
|
+
}
|
|
20316
|
+
function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
|
|
20317
|
+
return {
|
|
20318
|
+
kind: "manual",
|
|
20319
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20320
|
+
configFormat: "hermes_config_yaml",
|
|
20321
|
+
configPathCommand: HERMES_MCP_CONFIG_PATH,
|
|
20322
|
+
requiresRestart: true,
|
|
20323
|
+
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.",
|
|
20324
|
+
template: renderMeshCoordinatorTemplate(
|
|
20325
|
+
"mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
|
|
20326
|
+
{
|
|
20327
|
+
meshId,
|
|
20328
|
+
workspace,
|
|
20329
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20330
|
+
adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
|
|
20331
|
+
}
|
|
20332
|
+
)
|
|
20333
|
+
};
|
|
20334
|
+
}
|
|
20018
20335
|
function resolveMeshCoordinatorSetup(options) {
|
|
20019
20336
|
const { provider, meshId, workspace } = options;
|
|
20020
20337
|
const config = provider?.meshCoordinator;
|
|
@@ -20024,6 +20341,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20024
20341
|
reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
|
|
20025
20342
|
};
|
|
20026
20343
|
}
|
|
20344
|
+
if (isHermesProvider(provider, options.cliType)) {
|
|
20345
|
+
return resolveHermesMeshCoordinatorSetup(options);
|
|
20346
|
+
}
|
|
20027
20347
|
const mcpConfig = config.mcpConfig;
|
|
20028
20348
|
if (!mcpConfig || mcpConfig.mode === "none") {
|
|
20029
20349
|
return {
|
|
@@ -20033,8 +20353,8 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20033
20353
|
}
|
|
20034
20354
|
const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
|
|
20035
20355
|
if (mcpConfig.mode === "auto_import") {
|
|
20036
|
-
const
|
|
20037
|
-
if (!
|
|
20356
|
+
const path27 = mcpConfig.path?.trim();
|
|
20357
|
+
if (!path27) {
|
|
20038
20358
|
return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
|
|
20039
20359
|
}
|
|
20040
20360
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
@@ -20045,13 +20365,13 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20045
20365
|
if (!mcpServer) {
|
|
20046
20366
|
return {
|
|
20047
20367
|
kind: "unsupported",
|
|
20048
|
-
reason: "Could not resolve the ADHDev MCP server entrypoint
|
|
20368
|
+
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
20049
20369
|
};
|
|
20050
20370
|
}
|
|
20051
20371
|
return {
|
|
20052
20372
|
kind: "auto_import",
|
|
20053
20373
|
serverName,
|
|
20054
|
-
configPath: (
|
|
20374
|
+
configPath: resolveMcpConfigPath(path27, workspace),
|
|
20055
20375
|
configFormat: mcpConfig.format,
|
|
20056
20376
|
mcpServer
|
|
20057
20377
|
};
|
|
@@ -20085,14 +20405,85 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20085
20405
|
function renderMeshCoordinatorTemplate(template, values) {
|
|
20086
20406
|
return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
|
|
20087
20407
|
}
|
|
20408
|
+
function resolveMcpConfigPath(configPath, workspace) {
|
|
20409
|
+
const trimmed = configPath.trim();
|
|
20410
|
+
if (trimmed === "~") return os17.homedir();
|
|
20411
|
+
if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
|
|
20412
|
+
if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
|
|
20413
|
+
return (0, import_node_path.join)(workspace, trimmed);
|
|
20414
|
+
}
|
|
20088
20415
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
20089
20416
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
20090
20417
|
if (!entryPath) return null;
|
|
20418
|
+
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
20419
|
+
if (!nodeExecutable) return null;
|
|
20091
20420
|
return {
|
|
20092
|
-
command:
|
|
20093
|
-
args: [entryPath, "--repo-mesh", options.meshId]
|
|
20421
|
+
command: nodeExecutable,
|
|
20422
|
+
args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
|
|
20094
20423
|
};
|
|
20095
20424
|
}
|
|
20425
|
+
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
20426
|
+
const explicit = explicitExecutable?.trim();
|
|
20427
|
+
if (explicit) return explicit;
|
|
20428
|
+
const candidates = [];
|
|
20429
|
+
const addCandidate = (candidate) => {
|
|
20430
|
+
const trimmed = candidate?.trim();
|
|
20431
|
+
if (!trimmed) return;
|
|
20432
|
+
const normalized = normalizeExistingPath(trimmed) || trimmed;
|
|
20433
|
+
if (!candidates.includes(normalized)) candidates.push(normalized);
|
|
20434
|
+
};
|
|
20435
|
+
addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
|
|
20436
|
+
addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
|
|
20437
|
+
addCandidate(process.env.npm_node_execpath);
|
|
20438
|
+
addNodeCandidatesFromPath(process.env.PATH, addCandidate);
|
|
20439
|
+
addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
|
|
20440
|
+
addCandidate("/opt/homebrew/bin/node");
|
|
20441
|
+
addCandidate("/usr/local/bin/node");
|
|
20442
|
+
addCandidate("/usr/bin/node");
|
|
20443
|
+
addCandidate(process.execPath);
|
|
20444
|
+
for (const candidate of candidates) {
|
|
20445
|
+
if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
|
|
20446
|
+
}
|
|
20447
|
+
return null;
|
|
20448
|
+
}
|
|
20449
|
+
function addNodeCandidatesFromPath(pathValue, addCandidate) {
|
|
20450
|
+
for (const entry of (pathValue || "").split(":")) {
|
|
20451
|
+
const dir = entry.trim();
|
|
20452
|
+
if (!dir) continue;
|
|
20453
|
+
addCandidate((0, import_node_path.join)(dir, "node"));
|
|
20454
|
+
}
|
|
20455
|
+
}
|
|
20456
|
+
function addNodeCandidatesFromNvm(homeDir, addCandidate) {
|
|
20457
|
+
const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
|
|
20458
|
+
try {
|
|
20459
|
+
const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
|
|
20460
|
+
for (const versionDir of versionDirs) {
|
|
20461
|
+
addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
|
|
20462
|
+
}
|
|
20463
|
+
} catch {
|
|
20464
|
+
}
|
|
20465
|
+
}
|
|
20466
|
+
function compareNodeVersionNamesDescending(a, b) {
|
|
20467
|
+
const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
20468
|
+
const left = parse(a);
|
|
20469
|
+
const right = parse(b);
|
|
20470
|
+
for (let i = 0; i < Math.max(left.length, right.length); i++) {
|
|
20471
|
+
const diff = (right[i] || 0) - (left[i] || 0);
|
|
20472
|
+
if (diff !== 0) return diff;
|
|
20473
|
+
}
|
|
20474
|
+
return b.localeCompare(a);
|
|
20475
|
+
}
|
|
20476
|
+
function nodeRuntimeSupportsWebSocket(nodeExecutable) {
|
|
20477
|
+
try {
|
|
20478
|
+
(0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
|
|
20479
|
+
stdio: "ignore",
|
|
20480
|
+
timeout: 3e3
|
|
20481
|
+
});
|
|
20482
|
+
return true;
|
|
20483
|
+
} catch {
|
|
20484
|
+
return false;
|
|
20485
|
+
}
|
|
20486
|
+
}
|
|
20096
20487
|
function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
20097
20488
|
const explicit = explicitPath?.trim();
|
|
20098
20489
|
if (explicit) return normalizeExistingPath(explicit) || explicit;
|
|
@@ -20128,15 +20519,15 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
20128
20519
|
}
|
|
20129
20520
|
function normalizeExistingPath(filePath) {
|
|
20130
20521
|
try {
|
|
20131
|
-
if (!(0,
|
|
20132
|
-
return
|
|
20522
|
+
if (!(0, import_node_fs3.existsSync)(filePath)) return null;
|
|
20523
|
+
return import_node_fs3.realpathSync.native(filePath);
|
|
20133
20524
|
} catch {
|
|
20134
20525
|
return null;
|
|
20135
20526
|
}
|
|
20136
20527
|
}
|
|
20137
20528
|
|
|
20138
20529
|
// src/status/snapshot.ts
|
|
20139
|
-
var
|
|
20530
|
+
var os18 = __toESM(require("os"));
|
|
20140
20531
|
init_config();
|
|
20141
20532
|
init_terminal_screen();
|
|
20142
20533
|
init_logger();
|
|
@@ -20192,8 +20583,8 @@ function buildAvailableProviders(providerLoader) {
|
|
|
20192
20583
|
}
|
|
20193
20584
|
function buildMachineInfo(profile = "full") {
|
|
20194
20585
|
const base = {
|
|
20195
|
-
hostname:
|
|
20196
|
-
platform:
|
|
20586
|
+
hostname: os18.hostname(),
|
|
20587
|
+
platform: os18.platform()
|
|
20197
20588
|
};
|
|
20198
20589
|
if (profile === "live") {
|
|
20199
20590
|
return base;
|
|
@@ -20202,23 +20593,23 @@ function buildMachineInfo(profile = "full") {
|
|
|
20202
20593
|
const memSnap2 = getHostMemorySnapshot();
|
|
20203
20594
|
return {
|
|
20204
20595
|
...base,
|
|
20205
|
-
arch:
|
|
20206
|
-
cpus:
|
|
20596
|
+
arch: os18.arch(),
|
|
20597
|
+
cpus: os18.cpus().length,
|
|
20207
20598
|
totalMem: memSnap2.totalMem,
|
|
20208
|
-
release:
|
|
20599
|
+
release: os18.release()
|
|
20209
20600
|
};
|
|
20210
20601
|
}
|
|
20211
20602
|
const memSnap = getHostMemorySnapshot();
|
|
20212
20603
|
return {
|
|
20213
20604
|
...base,
|
|
20214
|
-
arch:
|
|
20215
|
-
cpus:
|
|
20605
|
+
arch: os18.arch(),
|
|
20606
|
+
cpus: os18.cpus().length,
|
|
20216
20607
|
totalMem: memSnap.totalMem,
|
|
20217
20608
|
freeMem: memSnap.freeMem,
|
|
20218
20609
|
availableMem: memSnap.availableMem,
|
|
20219
|
-
loadavg:
|
|
20220
|
-
uptime:
|
|
20221
|
-
release:
|
|
20610
|
+
loadavg: os18.loadavg(),
|
|
20611
|
+
uptime: os18.uptime(),
|
|
20612
|
+
release: os18.release()
|
|
20222
20613
|
};
|
|
20223
20614
|
}
|
|
20224
20615
|
function parseMessageTime(value) {
|
|
@@ -20452,14 +20843,14 @@ function buildStatusSnapshot(options) {
|
|
|
20452
20843
|
var import_child_process8 = require("child_process");
|
|
20453
20844
|
var import_child_process9 = require("child_process");
|
|
20454
20845
|
var fs9 = __toESM(require("fs"));
|
|
20455
|
-
var
|
|
20456
|
-
var
|
|
20846
|
+
var os19 = __toESM(require("os"));
|
|
20847
|
+
var path21 = __toESM(require("path"));
|
|
20457
20848
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
20458
20849
|
function getUpgradeLogPath() {
|
|
20459
|
-
const home =
|
|
20460
|
-
const dir =
|
|
20850
|
+
const home = os19.homedir();
|
|
20851
|
+
const dir = path21.join(home, ".adhdev");
|
|
20461
20852
|
fs9.mkdirSync(dir, { recursive: true });
|
|
20462
|
-
return
|
|
20853
|
+
return path21.join(dir, "daemon-upgrade.log");
|
|
20463
20854
|
}
|
|
20464
20855
|
function appendUpgradeLog(message) {
|
|
20465
20856
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -20470,14 +20861,14 @@ function appendUpgradeLog(message) {
|
|
|
20470
20861
|
}
|
|
20471
20862
|
}
|
|
20472
20863
|
function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
|
|
20473
|
-
const binDir =
|
|
20864
|
+
const binDir = path21.dirname(nodeExecutable);
|
|
20474
20865
|
if (platform10 === "win32") {
|
|
20475
|
-
const npmCliPath =
|
|
20866
|
+
const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
20476
20867
|
if (fs9.existsSync(npmCliPath)) {
|
|
20477
20868
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20478
20869
|
}
|
|
20479
20870
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
20480
|
-
const candidatePath =
|
|
20871
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20481
20872
|
if (fs9.existsSync(candidatePath)) {
|
|
20482
20873
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20483
20874
|
}
|
|
@@ -20485,7 +20876,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
20485
20876
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20486
20877
|
}
|
|
20487
20878
|
for (const candidate of ["npm"]) {
|
|
20488
|
-
const candidatePath =
|
|
20879
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20489
20880
|
if (fs9.existsSync(candidatePath)) {
|
|
20490
20881
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20491
20882
|
}
|
|
@@ -20502,13 +20893,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20502
20893
|
let currentDir = resolvedPath;
|
|
20503
20894
|
try {
|
|
20504
20895
|
if (fs9.statSync(resolvedPath).isFile()) {
|
|
20505
|
-
currentDir =
|
|
20896
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20506
20897
|
}
|
|
20507
20898
|
} catch {
|
|
20508
|
-
currentDir =
|
|
20899
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20509
20900
|
}
|
|
20510
20901
|
while (true) {
|
|
20511
|
-
const packageJsonPath =
|
|
20902
|
+
const packageJsonPath = path21.join(currentDir, "package.json");
|
|
20512
20903
|
try {
|
|
20513
20904
|
if (fs9.existsSync(packageJsonPath)) {
|
|
20514
20905
|
const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -20519,7 +20910,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20519
20910
|
}
|
|
20520
20911
|
} catch {
|
|
20521
20912
|
}
|
|
20522
|
-
const parentDir =
|
|
20913
|
+
const parentDir = path21.dirname(currentDir);
|
|
20523
20914
|
if (parentDir === currentDir) {
|
|
20524
20915
|
return null;
|
|
20525
20916
|
}
|
|
@@ -20527,13 +20918,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20527
20918
|
}
|
|
20528
20919
|
}
|
|
20529
20920
|
function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
|
|
20530
|
-
const nodeModulesDir = packageName.startsWith("@") ?
|
|
20531
|
-
if (
|
|
20921
|
+
const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
|
|
20922
|
+
if (path21.basename(nodeModulesDir) !== "node_modules") {
|
|
20532
20923
|
return null;
|
|
20533
20924
|
}
|
|
20534
|
-
const maybeLibDir =
|
|
20535
|
-
if (
|
|
20536
|
-
return
|
|
20925
|
+
const maybeLibDir = path21.dirname(nodeModulesDir);
|
|
20926
|
+
if (path21.basename(maybeLibDir) === "lib") {
|
|
20927
|
+
return path21.dirname(maybeLibDir);
|
|
20537
20928
|
}
|
|
20538
20929
|
return maybeLibDir;
|
|
20539
20930
|
}
|
|
@@ -20648,7 +21039,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
20648
21039
|
}
|
|
20649
21040
|
}
|
|
20650
21041
|
function stopSessionHostProcesses(appName) {
|
|
20651
|
-
const pidFile =
|
|
21042
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
20652
21043
|
try {
|
|
20653
21044
|
if (fs9.existsSync(pidFile)) {
|
|
20654
21045
|
const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -20665,7 +21056,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
20665
21056
|
}
|
|
20666
21057
|
}
|
|
20667
21058
|
function removeDaemonPidFile() {
|
|
20668
|
-
const pidFile =
|
|
21059
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
|
|
20669
21060
|
try {
|
|
20670
21061
|
fs9.unlinkSync(pidFile);
|
|
20671
21062
|
} catch {
|
|
@@ -20676,7 +21067,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20676
21067
|
const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20677
21068
|
if (!npmRoot) return;
|
|
20678
21069
|
const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20679
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
21070
|
+
const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
|
|
20680
21071
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
20681
21072
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
20682
21073
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -20684,25 +21075,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20684
21075
|
}
|
|
20685
21076
|
if (pkgName.startsWith("@")) {
|
|
20686
21077
|
const [scope, name] = pkgName.split("/");
|
|
20687
|
-
const scopeDir =
|
|
21078
|
+
const scopeDir = path21.join(npmRoot, scope);
|
|
20688
21079
|
if (!fs9.existsSync(scopeDir)) return;
|
|
20689
21080
|
for (const entry of fs9.readdirSync(scopeDir)) {
|
|
20690
21081
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
20691
|
-
fs9.rmSync(
|
|
20692
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
21082
|
+
fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
|
|
21083
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
|
|
20693
21084
|
}
|
|
20694
21085
|
} else {
|
|
20695
21086
|
for (const entry of fs9.readdirSync(npmRoot)) {
|
|
20696
21087
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
20697
|
-
fs9.rmSync(
|
|
20698
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
21088
|
+
fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
|
|
21089
|
+
appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
|
|
20699
21090
|
}
|
|
20700
21091
|
}
|
|
20701
21092
|
if (fs9.existsSync(binDir)) {
|
|
20702
21093
|
for (const entry of fs9.readdirSync(binDir)) {
|
|
20703
21094
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
20704
|
-
fs9.rmSync(
|
|
20705
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
21095
|
+
fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
|
|
21096
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
|
|
20706
21097
|
}
|
|
20707
21098
|
}
|
|
20708
21099
|
}
|
|
@@ -20803,6 +21194,56 @@ function normalizeReleaseChannel(value) {
|
|
|
20803
21194
|
function resolveUpgradeChannel(args) {
|
|
20804
21195
|
return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
|
|
20805
21196
|
}
|
|
21197
|
+
function readProviderPriorityFromPolicy(policy) {
|
|
21198
|
+
const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
|
|
21199
|
+
const raw = record.providerPriority;
|
|
21200
|
+
if (!Array.isArray(raw)) return [];
|
|
21201
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21202
|
+
return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
|
|
21203
|
+
if (seen.has(type)) return false;
|
|
21204
|
+
seen.add(type);
|
|
21205
|
+
return true;
|
|
21206
|
+
});
|
|
21207
|
+
}
|
|
21208
|
+
async function resolveProviderTypeFromPriority(args) {
|
|
21209
|
+
if (!args.providerPriority.length) {
|
|
21210
|
+
return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
|
|
21211
|
+
}
|
|
21212
|
+
const failed = [];
|
|
21213
|
+
for (const requestedType of args.providerPriority) {
|
|
21214
|
+
const normalizedType = args.providerLoader.resolveAlias(requestedType);
|
|
21215
|
+
if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
|
|
21216
|
+
failed.push(`${requestedType}: disabled`);
|
|
21217
|
+
continue;
|
|
21218
|
+
}
|
|
21219
|
+
const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
|
|
21220
|
+
args.providerLoader.setCliDetectionResults([{
|
|
21221
|
+
id: normalizedType,
|
|
21222
|
+
installed: !!detected,
|
|
21223
|
+
path: detected?.path
|
|
21224
|
+
}], false);
|
|
21225
|
+
args.onStatusChange?.();
|
|
21226
|
+
if (detected) return { providerType: normalizedType };
|
|
21227
|
+
failed.push(`${requestedType}: not detected`);
|
|
21228
|
+
}
|
|
21229
|
+
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
21230
|
+
}
|
|
21231
|
+
function loadYamlModule() {
|
|
21232
|
+
return yaml;
|
|
21233
|
+
}
|
|
21234
|
+
function getMcpServersKey(format) {
|
|
21235
|
+
return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
|
|
21236
|
+
}
|
|
21237
|
+
function parseMeshCoordinatorMcpConfig(text, format) {
|
|
21238
|
+
if (!text.trim()) return {};
|
|
21239
|
+
if (format === "claude_mcp_json") return JSON.parse(text);
|
|
21240
|
+
const parsed = loadYamlModule().load(text);
|
|
21241
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
21242
|
+
}
|
|
21243
|
+
function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
21244
|
+
if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
|
|
21245
|
+
return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
|
|
21246
|
+
}
|
|
20806
21247
|
var CHAT_COMMANDS = [
|
|
20807
21248
|
"send_chat",
|
|
20808
21249
|
"new_chat",
|
|
@@ -20901,6 +21342,40 @@ var DaemonCommandRouter = class {
|
|
|
20901
21342
|
constructor(deps) {
|
|
20902
21343
|
this.deps = deps;
|
|
20903
21344
|
}
|
|
21345
|
+
getCachedInlineMesh(meshId, inlineMesh) {
|
|
21346
|
+
if (inlineMesh && typeof inlineMesh === "object") {
|
|
21347
|
+
this.inlineMeshCache.set(meshId, inlineMesh);
|
|
21348
|
+
return inlineMesh;
|
|
21349
|
+
}
|
|
21350
|
+
return this.inlineMeshCache.get(meshId);
|
|
21351
|
+
}
|
|
21352
|
+
async getMeshForCommand(meshId, inlineMesh) {
|
|
21353
|
+
try {
|
|
21354
|
+
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21355
|
+
const mesh = getMesh3(meshId);
|
|
21356
|
+
if (mesh) return { mesh, inline: false };
|
|
21357
|
+
} catch {
|
|
21358
|
+
}
|
|
21359
|
+
const cached = this.getCachedInlineMesh(meshId, inlineMesh);
|
|
21360
|
+
return cached ? { mesh: cached, inline: true } : null;
|
|
21361
|
+
}
|
|
21362
|
+
updateInlineMeshNode(meshId, mesh, node) {
|
|
21363
|
+
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
21364
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
|
|
21365
|
+
if (idx >= 0) mesh.nodes[idx] = node;
|
|
21366
|
+
else mesh.nodes.push(node);
|
|
21367
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21368
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21369
|
+
}
|
|
21370
|
+
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
21371
|
+
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
21372
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
|
|
21373
|
+
if (idx === -1) return false;
|
|
21374
|
+
mesh.nodes.splice(idx, 1);
|
|
21375
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21376
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21377
|
+
return true;
|
|
21378
|
+
}
|
|
20904
21379
|
async traceSessionHostAction(action, args, run, summarizeResult) {
|
|
20905
21380
|
const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
|
|
20906
21381
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
|
|
@@ -21588,7 +22063,13 @@ var DaemonCommandRouter = class {
|
|
|
21588
22063
|
if (!workspace) return { success: false, error: "workspace required" };
|
|
21589
22064
|
try {
|
|
21590
22065
|
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21591
|
-
const
|
|
22066
|
+
const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
|
|
22067
|
+
const readOnly = args?.readOnly === true;
|
|
22068
|
+
const policy = {
|
|
22069
|
+
...readOnly ? { readOnly: true } : {},
|
|
22070
|
+
...providerPriority.length ? { providerPriority } : {}
|
|
22071
|
+
};
|
|
22072
|
+
const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
|
|
21592
22073
|
if (!node) return { success: false, error: "Mesh not found" };
|
|
21593
22074
|
return { success: true, node };
|
|
21594
22075
|
} catch (e) {
|
|
@@ -21600,17 +22081,98 @@ var DaemonCommandRouter = class {
|
|
|
21600
22081
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
21601
22082
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
21602
22083
|
try {
|
|
21603
|
-
const
|
|
21604
|
-
const
|
|
22084
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22085
|
+
const mesh = meshRecord?.mesh;
|
|
22086
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
22087
|
+
if (node?.isLocalWorktree && node.workspace) {
|
|
22088
|
+
try {
|
|
22089
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
22090
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
22091
|
+
if (repoRoot) {
|
|
22092
|
+
const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
22093
|
+
await removeWorktree2(repoRoot, node.workspace);
|
|
22094
|
+
}
|
|
22095
|
+
} catch (e) {
|
|
22096
|
+
LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
|
|
22097
|
+
}
|
|
22098
|
+
}
|
|
22099
|
+
let removed = false;
|
|
22100
|
+
if (meshRecord?.inline) {
|
|
22101
|
+
removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
|
|
22102
|
+
} else {
|
|
22103
|
+
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22104
|
+
removed = removeNode3(meshId, nodeId);
|
|
22105
|
+
}
|
|
21605
22106
|
return { success: true, removed };
|
|
21606
22107
|
} catch (e) {
|
|
21607
22108
|
return { success: false, error: e.message };
|
|
21608
22109
|
}
|
|
21609
22110
|
}
|
|
22111
|
+
case "clone_mesh_node": {
|
|
22112
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22113
|
+
const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
|
|
22114
|
+
const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
|
|
22115
|
+
const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
|
|
22116
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
22117
|
+
if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
|
|
22118
|
+
if (!branch) return { success: false, error: "branch required" };
|
|
22119
|
+
try {
|
|
22120
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22121
|
+
const mesh = meshRecord?.mesh;
|
|
22122
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22123
|
+
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
22124
|
+
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
22125
|
+
const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
|
|
22126
|
+
const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
22127
|
+
const result = await createWorktree2({
|
|
22128
|
+
repoRoot,
|
|
22129
|
+
branch,
|
|
22130
|
+
baseBranch,
|
|
22131
|
+
meshName: mesh.name
|
|
22132
|
+
});
|
|
22133
|
+
let node;
|
|
22134
|
+
if (meshRecord.inline) {
|
|
22135
|
+
const { randomUUID: randomUUID8 } = await import("crypto");
|
|
22136
|
+
node = {
|
|
22137
|
+
id: `node_${randomUUID8().replace(/-/g, "")}`,
|
|
22138
|
+
workspace: result.worktreePath,
|
|
22139
|
+
repoRoot: result.worktreePath,
|
|
22140
|
+
daemonId: sourceNode.daemonId,
|
|
22141
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
22142
|
+
policy: { ...sourceNode.policy || {} },
|
|
22143
|
+
isLocalWorktree: true,
|
|
22144
|
+
worktreeBranch: result.branch,
|
|
22145
|
+
clonedFromNodeId: sourceNodeId
|
|
22146
|
+
};
|
|
22147
|
+
this.updateInlineMeshNode(meshId, mesh, node);
|
|
22148
|
+
} else {
|
|
22149
|
+
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22150
|
+
node = addNode3(meshId, {
|
|
22151
|
+
workspace: result.worktreePath,
|
|
22152
|
+
repoRoot: result.worktreePath,
|
|
22153
|
+
daemonId: sourceNode.daemonId,
|
|
22154
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
22155
|
+
isLocalWorktree: true,
|
|
22156
|
+
worktreeBranch: result.branch,
|
|
22157
|
+
clonedFromNodeId: sourceNodeId,
|
|
22158
|
+
policy: { ...sourceNode.policy || {} }
|
|
22159
|
+
});
|
|
22160
|
+
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
22161
|
+
}
|
|
22162
|
+
return {
|
|
22163
|
+
success: true,
|
|
22164
|
+
node,
|
|
22165
|
+
worktreePath: result.worktreePath,
|
|
22166
|
+
branch: result.branch
|
|
22167
|
+
};
|
|
22168
|
+
} catch (e) {
|
|
22169
|
+
return { success: false, error: e.message };
|
|
22170
|
+
}
|
|
22171
|
+
}
|
|
21610
22172
|
// ─── Mesh Coordinator Launch ───
|
|
21611
22173
|
case "launch_mesh_coordinator": {
|
|
21612
22174
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
21613
|
-
|
|
22175
|
+
let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
|
|
21614
22176
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
21615
22177
|
try {
|
|
21616
22178
|
const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
@@ -21638,9 +22200,29 @@ var DaemonCommandRouter = class {
|
|
|
21638
22200
|
}
|
|
21639
22201
|
const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
|
|
21640
22202
|
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
22203
|
+
if (!cliType) {
|
|
22204
|
+
const resolved = await resolveProviderTypeFromPriority({
|
|
22205
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
|
|
22206
|
+
providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
|
|
22207
|
+
providerLoader: this.deps.providerLoader,
|
|
22208
|
+
onStatusChange: this.deps.onStatusChange
|
|
22209
|
+
});
|
|
22210
|
+
if (!resolved.providerType) {
|
|
22211
|
+
return {
|
|
22212
|
+
success: false,
|
|
22213
|
+
code: "mesh_coordinator_provider_priority_unusable",
|
|
22214
|
+
error: resolved.error || "No usable provider found from node providerPriority",
|
|
22215
|
+
meshId,
|
|
22216
|
+
cliType,
|
|
22217
|
+
workspace
|
|
22218
|
+
};
|
|
22219
|
+
}
|
|
22220
|
+
cliType = resolved.providerType;
|
|
22221
|
+
}
|
|
21641
22222
|
const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
|
|
21642
22223
|
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
21643
22224
|
provider: providerMeta,
|
|
22225
|
+
cliType,
|
|
21644
22226
|
meshId,
|
|
21645
22227
|
workspace
|
|
21646
22228
|
});
|
|
@@ -21665,7 +22247,8 @@ var DaemonCommandRouter = class {
|
|
|
21665
22247
|
meshCoordinatorSetup: coordinatorSetup
|
|
21666
22248
|
};
|
|
21667
22249
|
}
|
|
21668
|
-
|
|
22250
|
+
const configFormat = coordinatorSetup.configFormat;
|
|
22251
|
+
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
21669
22252
|
return {
|
|
21670
22253
|
success: false,
|
|
21671
22254
|
code: "mesh_coordinator_unsupported",
|
|
@@ -21675,44 +22258,93 @@ var DaemonCommandRouter = class {
|
|
|
21675
22258
|
workspace
|
|
21676
22259
|
};
|
|
21677
22260
|
}
|
|
21678
|
-
|
|
21679
|
-
|
|
21680
|
-
|
|
21681
|
-
|
|
21682
|
-
|
|
21683
|
-
|
|
21684
|
-
|
|
21685
|
-
|
|
21686
|
-
|
|
21687
|
-
|
|
22261
|
+
let systemPrompt = "";
|
|
22262
|
+
try {
|
|
22263
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
22264
|
+
} catch (error) {
|
|
22265
|
+
const message = error?.message || String(error);
|
|
22266
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
22267
|
+
return {
|
|
22268
|
+
success: false,
|
|
22269
|
+
code: "mesh_coordinator_prompt_failed",
|
|
22270
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
22271
|
+
meshId,
|
|
22272
|
+
cliType,
|
|
22273
|
+
workspace
|
|
22274
|
+
};
|
|
21688
22275
|
}
|
|
22276
|
+
const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
|
|
22277
|
+
const { dirname: dirname9 } = await import("path");
|
|
22278
|
+
const mcpConfigPath = coordinatorSetup.configPath;
|
|
22279
|
+
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
22280
|
+
const returnManualFallback = (message) => ({
|
|
22281
|
+
success: false,
|
|
22282
|
+
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
22283
|
+
error: message,
|
|
22284
|
+
meshId,
|
|
22285
|
+
cliType,
|
|
22286
|
+
workspace,
|
|
22287
|
+
meshCoordinatorSetup: hermesManualFallback
|
|
22288
|
+
});
|
|
21689
22289
|
const mcpServerEntry = {
|
|
21690
22290
|
command: coordinatorSetup.mcpServer.command,
|
|
21691
22291
|
args: coordinatorSetup.mcpServer.args
|
|
21692
22292
|
};
|
|
21693
22293
|
if (args?.inlineMesh) {
|
|
21694
22294
|
mcpServerEntry.env = {
|
|
21695
|
-
ADHDEV_INLINE_MESH: JSON.stringify(mesh)
|
|
22295
|
+
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
22296
|
+
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
21696
22297
|
};
|
|
21697
22298
|
}
|
|
22299
|
+
try {
|
|
22300
|
+
mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
|
|
22301
|
+
} catch (error) {
|
|
22302
|
+
const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
|
|
22303
|
+
LOG.error("MeshCoordinator", message);
|
|
22304
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
22305
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
22306
|
+
}
|
|
22307
|
+
const hadExistingMcpConfig = existsSync23(mcpConfigPath);
|
|
22308
|
+
let existingMcpConfig = {};
|
|
22309
|
+
if (hadExistingMcpConfig) {
|
|
22310
|
+
try {
|
|
22311
|
+
existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
|
|
22312
|
+
copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
|
|
22313
|
+
} catch (error) {
|
|
22314
|
+
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
22315
|
+
return {
|
|
22316
|
+
success: false,
|
|
22317
|
+
code: "mesh_coordinator_config_parse_failed",
|
|
22318
|
+
error: `Failed to parse existing MCP config at ${mcpConfigPath}`
|
|
22319
|
+
};
|
|
22320
|
+
}
|
|
22321
|
+
}
|
|
22322
|
+
const mcpServersKey = getMcpServersKey(configFormat);
|
|
22323
|
+
const existingServers = existingMcpConfig[mcpServersKey];
|
|
21698
22324
|
const mcpConfig = {
|
|
21699
22325
|
...existingMcpConfig,
|
|
21700
|
-
|
|
21701
|
-
...
|
|
22326
|
+
[mcpServersKey]: {
|
|
22327
|
+
...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
|
|
21702
22328
|
[coordinatorSetup.serverName]: mcpServerEntry
|
|
21703
22329
|
}
|
|
21704
22330
|
};
|
|
21705
|
-
writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
21706
|
-
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21707
|
-
let systemPrompt = "";
|
|
21708
22331
|
try {
|
|
21709
|
-
|
|
21710
|
-
} catch {
|
|
21711
|
-
|
|
22332
|
+
writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
22333
|
+
} catch (error) {
|
|
22334
|
+
const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
|
|
22335
|
+
LOG.error("MeshCoordinator", message);
|
|
22336
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
22337
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
21712
22338
|
}
|
|
22339
|
+
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21713
22340
|
const cliArgs = [];
|
|
22341
|
+
const launchEnv = {};
|
|
21714
22342
|
if (systemPrompt) {
|
|
21715
|
-
|
|
22343
|
+
if (configFormat === "hermes_config_yaml") {
|
|
22344
|
+
launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
|
|
22345
|
+
} else {
|
|
22346
|
+
cliArgs.push("--append-system-prompt", systemPrompt);
|
|
22347
|
+
}
|
|
21716
22348
|
}
|
|
21717
22349
|
if (cliType === "claude-cli") {
|
|
21718
22350
|
cliArgs.push("--mcp-config", coordinatorSetup.configPath);
|
|
@@ -21721,6 +22353,7 @@ var DaemonCommandRouter = class {
|
|
|
21721
22353
|
cliType,
|
|
21722
22354
|
dir: workspace,
|
|
21723
22355
|
cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
|
|
22356
|
+
env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
|
|
21724
22357
|
settings: {
|
|
21725
22358
|
meshCoordinatorFor: meshId
|
|
21726
22359
|
}
|
|
@@ -21900,6 +22533,12 @@ var DaemonStatusReporter = class {
|
|
|
21900
22533
|
if (providerType) {
|
|
21901
22534
|
payload.providerType = providerType;
|
|
21902
22535
|
}
|
|
22536
|
+
if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
|
|
22537
|
+
payload.providerSessionId = event.providerSessionId.trim();
|
|
22538
|
+
}
|
|
22539
|
+
if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
|
|
22540
|
+
payload.workspaceName = event.workspaceName.trim();
|
|
22541
|
+
}
|
|
21903
22542
|
if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
|
|
21904
22543
|
payload.duration = event.duration;
|
|
21905
22544
|
}
|
|
@@ -23147,7 +23786,10 @@ var ProviderInstanceManager = class {
|
|
|
23147
23786
|
this.instances.get(id).dispose();
|
|
23148
23787
|
}
|
|
23149
23788
|
this.instances.set(id, instance);
|
|
23150
|
-
await instance.init(
|
|
23789
|
+
await instance.init({
|
|
23790
|
+
...context,
|
|
23791
|
+
emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
|
|
23792
|
+
});
|
|
23151
23793
|
}
|
|
23152
23794
|
/**
|
|
23153
23795
|
* Instance remove
|
|
@@ -23309,6 +23951,17 @@ var ProviderInstanceManager = class {
|
|
|
23309
23951
|
onEvent(listener) {
|
|
23310
23952
|
this.eventListeners.push(listener);
|
|
23311
23953
|
}
|
|
23954
|
+
emitProviderEvent(providerType, instanceId, event) {
|
|
23955
|
+
const payload = {
|
|
23956
|
+
...event,
|
|
23957
|
+
providerType,
|
|
23958
|
+
instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
|
|
23959
|
+
targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
|
|
23960
|
+
};
|
|
23961
|
+
for (const listener of this.eventListeners) {
|
|
23962
|
+
listener(payload);
|
|
23963
|
+
}
|
|
23964
|
+
}
|
|
23312
23965
|
emitPendingEvents(providerType, state, extra = {}) {
|
|
23313
23966
|
for (const event of state.pendingEvents) {
|
|
23314
23967
|
for (const listener of this.eventListeners) {
|
|
@@ -23381,11 +24034,11 @@ var ProviderInstanceManager = class {
|
|
|
23381
24034
|
|
|
23382
24035
|
// src/providers/version-archive.ts
|
|
23383
24036
|
var fs11 = __toESM(require("fs"));
|
|
23384
|
-
var
|
|
23385
|
-
var
|
|
24037
|
+
var path22 = __toESM(require("path"));
|
|
24038
|
+
var os20 = __toESM(require("os"));
|
|
23386
24039
|
var import_child_process10 = require("child_process");
|
|
23387
24040
|
var import_os3 = require("os");
|
|
23388
|
-
var ARCHIVE_PATH =
|
|
24041
|
+
var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
|
|
23389
24042
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
23390
24043
|
var VersionArchive = class {
|
|
23391
24044
|
history = {};
|
|
@@ -23432,7 +24085,7 @@ var VersionArchive = class {
|
|
|
23432
24085
|
}
|
|
23433
24086
|
save() {
|
|
23434
24087
|
try {
|
|
23435
|
-
fs11.mkdirSync(
|
|
24088
|
+
fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
|
|
23436
24089
|
fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
23437
24090
|
} catch {
|
|
23438
24091
|
}
|
|
@@ -23488,8 +24141,8 @@ function getVersion(binary, versionCommand) {
|
|
|
23488
24141
|
function checkPathExists2(paths) {
|
|
23489
24142
|
for (const p of paths) {
|
|
23490
24143
|
if (p.includes("*")) {
|
|
23491
|
-
const home =
|
|
23492
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
24144
|
+
const home = os20.homedir();
|
|
24145
|
+
const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
|
|
23493
24146
|
if (fs11.existsSync(resolved)) return resolved;
|
|
23494
24147
|
} else {
|
|
23495
24148
|
if (fs11.existsSync(p)) return p;
|
|
@@ -23499,7 +24152,7 @@ function checkPathExists2(paths) {
|
|
|
23499
24152
|
}
|
|
23500
24153
|
function getMacAppVersion(appPath) {
|
|
23501
24154
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
23502
|
-
const plistPath =
|
|
24155
|
+
const plistPath = path22.join(appPath, "Contents", "Info.plist");
|
|
23503
24156
|
if (!fs11.existsSync(plistPath)) return null;
|
|
23504
24157
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
23505
24158
|
return raw || null;
|
|
@@ -23525,7 +24178,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23525
24178
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
23526
24179
|
let resolvedBin = cliBin;
|
|
23527
24180
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
23528
|
-
const bundled =
|
|
24181
|
+
const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
23529
24182
|
if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
|
|
23530
24183
|
}
|
|
23531
24184
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -23566,7 +24219,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23566
24219
|
// src/daemon/dev-server.ts
|
|
23567
24220
|
var http2 = __toESM(require("http"));
|
|
23568
24221
|
var fs15 = __toESM(require("fs"));
|
|
23569
|
-
var
|
|
24222
|
+
var path26 = __toESM(require("path"));
|
|
23570
24223
|
init_config();
|
|
23571
24224
|
|
|
23572
24225
|
// src/daemon/scaffold-template.ts
|
|
@@ -23917,7 +24570,7 @@ init_logger();
|
|
|
23917
24570
|
|
|
23918
24571
|
// src/daemon/dev-cdp-handlers.ts
|
|
23919
24572
|
var fs12 = __toESM(require("fs"));
|
|
23920
|
-
var
|
|
24573
|
+
var path23 = __toESM(require("path"));
|
|
23921
24574
|
init_logger();
|
|
23922
24575
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
23923
24576
|
const body = await ctx.readBody(req);
|
|
@@ -24096,17 +24749,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
24096
24749
|
return;
|
|
24097
24750
|
}
|
|
24098
24751
|
let scriptsPath = "";
|
|
24099
|
-
const directScripts =
|
|
24752
|
+
const directScripts = path23.join(dir, "scripts.js");
|
|
24100
24753
|
if (fs12.existsSync(directScripts)) {
|
|
24101
24754
|
scriptsPath = directScripts;
|
|
24102
24755
|
} else {
|
|
24103
|
-
const scriptsDir =
|
|
24756
|
+
const scriptsDir = path23.join(dir, "scripts");
|
|
24104
24757
|
if (fs12.existsSync(scriptsDir)) {
|
|
24105
24758
|
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
24106
|
-
return fs12.statSync(
|
|
24759
|
+
return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
|
|
24107
24760
|
}).sort().reverse();
|
|
24108
24761
|
for (const ver of versions) {
|
|
24109
|
-
const p =
|
|
24762
|
+
const p = path23.join(scriptsDir, ver, "scripts.js");
|
|
24110
24763
|
if (fs12.existsSync(p)) {
|
|
24111
24764
|
scriptsPath = p;
|
|
24112
24765
|
break;
|
|
@@ -24935,7 +25588,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
24935
25588
|
|
|
24936
25589
|
// src/daemon/dev-cli-debug.ts
|
|
24937
25590
|
var fs13 = __toESM(require("fs"));
|
|
24938
|
-
var
|
|
25591
|
+
var path24 = __toESM(require("path"));
|
|
24939
25592
|
function slugifyFixtureName(value) {
|
|
24940
25593
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
24941
25594
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -24945,11 +25598,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
24945
25598
|
if (!providerDir) {
|
|
24946
25599
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
24947
25600
|
}
|
|
24948
|
-
return
|
|
25601
|
+
return path24.join(providerDir, "fixtures");
|
|
24949
25602
|
}
|
|
24950
25603
|
function readCliFixture(ctx, type, name) {
|
|
24951
25604
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
24952
|
-
const filePath =
|
|
25605
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
24953
25606
|
if (!fs13.existsSync(filePath)) {
|
|
24954
25607
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
24955
25608
|
}
|
|
@@ -25716,7 +26369,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
25716
26369
|
},
|
|
25717
26370
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
25718
26371
|
};
|
|
25719
|
-
const filePath =
|
|
26372
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
25720
26373
|
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
25721
26374
|
ctx.json(res, 200, {
|
|
25722
26375
|
saved: true,
|
|
@@ -25740,7 +26393,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
25740
26393
|
return;
|
|
25741
26394
|
}
|
|
25742
26395
|
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 =
|
|
26396
|
+
const fullPath = path24.join(fixtureDir, file);
|
|
25744
26397
|
try {
|
|
25745
26398
|
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
25746
26399
|
return {
|
|
@@ -25876,8 +26529,8 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
25876
26529
|
|
|
25877
26530
|
// src/daemon/dev-auto-implement.ts
|
|
25878
26531
|
var fs14 = __toESM(require("fs"));
|
|
25879
|
-
var
|
|
25880
|
-
var
|
|
26532
|
+
var path25 = __toESM(require("path"));
|
|
26533
|
+
var os21 = __toESM(require("os"));
|
|
25881
26534
|
function getAutoImplPid(ctx) {
|
|
25882
26535
|
const pid = ctx.autoImplProcess?.pid;
|
|
25883
26536
|
return typeof pid === "number" && pid > 0 ? pid : null;
|
|
@@ -25926,22 +26579,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
25926
26579
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
25927
26580
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
25928
26581
|
try {
|
|
25929
|
-
return fs14.statSync(
|
|
26582
|
+
return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
|
|
25930
26583
|
} catch {
|
|
25931
26584
|
return false;
|
|
25932
26585
|
}
|
|
25933
26586
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
25934
26587
|
if (versions.length === 0) return null;
|
|
25935
|
-
return
|
|
26588
|
+
return path25.join(scriptsDir, versions[0]);
|
|
25936
26589
|
}
|
|
25937
26590
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
25938
|
-
const canonicalUserDir =
|
|
25939
|
-
const desiredDir = requestedDir ?
|
|
25940
|
-
const upstreamRoot =
|
|
25941
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
26591
|
+
const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
26592
|
+
const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
|
|
26593
|
+
const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
|
|
26594
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
|
|
25942
26595
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
25943
26596
|
}
|
|
25944
|
-
if (
|
|
26597
|
+
if (path25.basename(desiredDir) !== type) {
|
|
25945
26598
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
25946
26599
|
}
|
|
25947
26600
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -25949,11 +26602,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
25949
26602
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
25950
26603
|
}
|
|
25951
26604
|
if (!fs14.existsSync(desiredDir)) {
|
|
25952
|
-
fs14.mkdirSync(
|
|
26605
|
+
fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
|
|
25953
26606
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
25954
26607
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
25955
26608
|
}
|
|
25956
|
-
const providerJson =
|
|
26609
|
+
const providerJson = path25.join(desiredDir, "provider.json");
|
|
25957
26610
|
if (!fs14.existsSync(providerJson)) {
|
|
25958
26611
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
25959
26612
|
}
|
|
@@ -25964,13 +26617,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
25964
26617
|
const refDir = ctx.findProviderDir(referenceType);
|
|
25965
26618
|
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
25966
26619
|
const referenceScripts = {};
|
|
25967
|
-
const scriptsDir =
|
|
26620
|
+
const scriptsDir = path25.join(refDir, "scripts");
|
|
25968
26621
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
25969
26622
|
if (!latestDir) return referenceScripts;
|
|
25970
26623
|
for (const file of fs14.readdirSync(latestDir)) {
|
|
25971
26624
|
if (!file.endsWith(".js")) continue;
|
|
25972
26625
|
try {
|
|
25973
|
-
referenceScripts[file] = fs14.readFileSync(
|
|
26626
|
+
referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
|
|
25974
26627
|
} catch {
|
|
25975
26628
|
}
|
|
25976
26629
|
}
|
|
@@ -26078,9 +26731,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26078
26731
|
});
|
|
26079
26732
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
26080
26733
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
26081
|
-
const tmpDir =
|
|
26734
|
+
const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
|
|
26082
26735
|
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
26083
|
-
const promptFile =
|
|
26736
|
+
const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
26084
26737
|
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
26085
26738
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
26086
26739
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -26233,7 +26886,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26233
26886
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
26234
26887
|
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
26235
26888
|
let shellCmd;
|
|
26236
|
-
const isWin =
|
|
26889
|
+
const isWin = os21.platform() === "win32";
|
|
26237
26890
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
26238
26891
|
const promptMode = autoImpl?.promptMode ?? "stdin";
|
|
26239
26892
|
const extraArgs = autoImpl?.extraArgs ?? [];
|
|
@@ -26272,7 +26925,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26272
26925
|
try {
|
|
26273
26926
|
const pty = require("node-pty");
|
|
26274
26927
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
26275
|
-
const isWin2 =
|
|
26928
|
+
const isWin2 = os21.platform() === "win32";
|
|
26276
26929
|
child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
26277
26930
|
name: "xterm-256color",
|
|
26278
26931
|
cols: 120,
|
|
@@ -26512,7 +27165,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26512
27165
|
setMode: "set_mode.js"
|
|
26513
27166
|
};
|
|
26514
27167
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26515
|
-
const scriptsDir =
|
|
27168
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26516
27169
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26517
27170
|
if (latestScriptsDir) {
|
|
26518
27171
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26523,7 +27176,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26523
27176
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
26524
27177
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
26525
27178
|
try {
|
|
26526
|
-
const content = fs14.readFileSync(
|
|
27179
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26527
27180
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26528
27181
|
lines.push("```javascript");
|
|
26529
27182
|
lines.push(content);
|
|
@@ -26540,7 +27193,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26540
27193
|
lines.push("");
|
|
26541
27194
|
for (const file of refFiles) {
|
|
26542
27195
|
try {
|
|
26543
|
-
const content = fs14.readFileSync(
|
|
27196
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26544
27197
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26545
27198
|
lines.push("```javascript");
|
|
26546
27199
|
lines.push(content);
|
|
@@ -26581,10 +27234,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26581
27234
|
lines.push("");
|
|
26582
27235
|
}
|
|
26583
27236
|
}
|
|
26584
|
-
const docsDir =
|
|
27237
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26585
27238
|
const loadGuide = (name) => {
|
|
26586
27239
|
try {
|
|
26587
|
-
const p =
|
|
27240
|
+
const p = path25.join(docsDir, name);
|
|
26588
27241
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26589
27242
|
} catch {
|
|
26590
27243
|
}
|
|
@@ -26821,7 +27474,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26821
27474
|
parseApproval: "parse_approval.js"
|
|
26822
27475
|
};
|
|
26823
27476
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26824
|
-
const scriptsDir =
|
|
27477
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26825
27478
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26826
27479
|
if (latestScriptsDir) {
|
|
26827
27480
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26833,7 +27486,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26833
27486
|
if (!file.endsWith(".js")) continue;
|
|
26834
27487
|
if (!targetFileNames.has(file)) continue;
|
|
26835
27488
|
try {
|
|
26836
|
-
const content = fs14.readFileSync(
|
|
27489
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26837
27490
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26838
27491
|
lines.push("```javascript");
|
|
26839
27492
|
lines.push(content);
|
|
@@ -26849,7 +27502,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26849
27502
|
lines.push("");
|
|
26850
27503
|
for (const file of refFiles) {
|
|
26851
27504
|
try {
|
|
26852
|
-
const content = fs14.readFileSync(
|
|
27505
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26853
27506
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26854
27507
|
lines.push("```javascript");
|
|
26855
27508
|
lines.push(content);
|
|
@@ -26882,10 +27535,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26882
27535
|
lines.push("");
|
|
26883
27536
|
}
|
|
26884
27537
|
}
|
|
26885
|
-
const docsDir =
|
|
27538
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26886
27539
|
const loadGuide = (name) => {
|
|
26887
27540
|
try {
|
|
26888
|
-
const p =
|
|
27541
|
+
const p = path25.join(docsDir, name);
|
|
26889
27542
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26890
27543
|
} catch {
|
|
26891
27544
|
}
|
|
@@ -27332,8 +27985,8 @@ var DevServer = class _DevServer {
|
|
|
27332
27985
|
}
|
|
27333
27986
|
getEndpointList() {
|
|
27334
27987
|
return this.routes.map((r) => {
|
|
27335
|
-
const
|
|
27336
|
-
return `${r.method.padEnd(5)} ${
|
|
27988
|
+
const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
27989
|
+
return `${r.method.padEnd(5)} ${path27}`;
|
|
27337
27990
|
});
|
|
27338
27991
|
}
|
|
27339
27992
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -27621,12 +28274,12 @@ var DevServer = class _DevServer {
|
|
|
27621
28274
|
// ─── DevConsole SPA ───
|
|
27622
28275
|
getConsoleDistDir() {
|
|
27623
28276
|
const candidates = [
|
|
27624
|
-
|
|
27625
|
-
|
|
27626
|
-
|
|
28277
|
+
path26.resolve(__dirname, "../../web-devconsole/dist"),
|
|
28278
|
+
path26.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
28279
|
+
path26.join(process.cwd(), "packages/web-devconsole/dist")
|
|
27627
28280
|
];
|
|
27628
28281
|
for (const dir of candidates) {
|
|
27629
|
-
if (fs15.existsSync(
|
|
28282
|
+
if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
|
|
27630
28283
|
}
|
|
27631
28284
|
return null;
|
|
27632
28285
|
}
|
|
@@ -27636,7 +28289,7 @@ var DevServer = class _DevServer {
|
|
|
27636
28289
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
27637
28290
|
return;
|
|
27638
28291
|
}
|
|
27639
|
-
const htmlPath =
|
|
28292
|
+
const htmlPath = path26.join(distDir, "index.html");
|
|
27640
28293
|
try {
|
|
27641
28294
|
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
27642
28295
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -27661,15 +28314,15 @@ var DevServer = class _DevServer {
|
|
|
27661
28314
|
this.json(res, 404, { error: "Not found" });
|
|
27662
28315
|
return;
|
|
27663
28316
|
}
|
|
27664
|
-
const safePath =
|
|
27665
|
-
const filePath =
|
|
28317
|
+
const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
|
|
28318
|
+
const filePath = path26.join(distDir, safePath);
|
|
27666
28319
|
if (!filePath.startsWith(distDir)) {
|
|
27667
28320
|
this.json(res, 403, { error: "Forbidden" });
|
|
27668
28321
|
return;
|
|
27669
28322
|
}
|
|
27670
28323
|
try {
|
|
27671
28324
|
const content = fs15.readFileSync(filePath);
|
|
27672
|
-
const ext =
|
|
28325
|
+
const ext = path26.extname(filePath);
|
|
27673
28326
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
27674
28327
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
27675
28328
|
res.end(content);
|
|
@@ -27782,9 +28435,9 @@ var DevServer = class _DevServer {
|
|
|
27782
28435
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
27783
28436
|
if (entry.isDirectory()) {
|
|
27784
28437
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
27785
|
-
scan(
|
|
28438
|
+
scan(path26.join(d, entry.name), rel);
|
|
27786
28439
|
} else {
|
|
27787
|
-
const stat2 = fs15.statSync(
|
|
28440
|
+
const stat2 = fs15.statSync(path26.join(d, entry.name));
|
|
27788
28441
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
27789
28442
|
}
|
|
27790
28443
|
}
|
|
@@ -27807,7 +28460,7 @@ var DevServer = class _DevServer {
|
|
|
27807
28460
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27808
28461
|
return;
|
|
27809
28462
|
}
|
|
27810
|
-
const fullPath =
|
|
28463
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27811
28464
|
if (!fullPath.startsWith(dir)) {
|
|
27812
28465
|
this.json(res, 403, { error: "Forbidden" });
|
|
27813
28466
|
return;
|
|
@@ -27832,14 +28485,14 @@ var DevServer = class _DevServer {
|
|
|
27832
28485
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27833
28486
|
return;
|
|
27834
28487
|
}
|
|
27835
|
-
const fullPath =
|
|
28488
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27836
28489
|
if (!fullPath.startsWith(dir)) {
|
|
27837
28490
|
this.json(res, 403, { error: "Forbidden" });
|
|
27838
28491
|
return;
|
|
27839
28492
|
}
|
|
27840
28493
|
try {
|
|
27841
28494
|
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
27842
|
-
fs15.mkdirSync(
|
|
28495
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27843
28496
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27844
28497
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
27845
28498
|
this.providerLoader.reload();
|
|
@@ -27856,7 +28509,7 @@ var DevServer = class _DevServer {
|
|
|
27856
28509
|
return;
|
|
27857
28510
|
}
|
|
27858
28511
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
27859
|
-
const p =
|
|
28512
|
+
const p = path26.join(dir, name);
|
|
27860
28513
|
if (fs15.existsSync(p)) {
|
|
27861
28514
|
const source = fs15.readFileSync(p, "utf-8");
|
|
27862
28515
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -27877,8 +28530,8 @@ var DevServer = class _DevServer {
|
|
|
27877
28530
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
27878
28531
|
return;
|
|
27879
28532
|
}
|
|
27880
|
-
const target = fs15.existsSync(
|
|
27881
|
-
const targetPath =
|
|
28533
|
+
const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
28534
|
+
const targetPath = path26.join(dir, target);
|
|
27882
28535
|
try {
|
|
27883
28536
|
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
27884
28537
|
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -28025,7 +28678,7 @@ var DevServer = class _DevServer {
|
|
|
28025
28678
|
}
|
|
28026
28679
|
let targetDir;
|
|
28027
28680
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
28028
|
-
const jsonPath =
|
|
28681
|
+
const jsonPath = path26.join(targetDir, "provider.json");
|
|
28029
28682
|
if (fs15.existsSync(jsonPath)) {
|
|
28030
28683
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
28031
28684
|
return;
|
|
@@ -28037,8 +28690,8 @@ var DevServer = class _DevServer {
|
|
|
28037
28690
|
const createdFiles = ["provider.json"];
|
|
28038
28691
|
if (result.files) {
|
|
28039
28692
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
28040
|
-
const fullPath =
|
|
28041
|
-
fs15.mkdirSync(
|
|
28693
|
+
const fullPath = path26.join(targetDir, relPath);
|
|
28694
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
28042
28695
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
28043
28696
|
createdFiles.push(relPath);
|
|
28044
28697
|
}
|
|
@@ -28091,22 +28744,22 @@ var DevServer = class _DevServer {
|
|
|
28091
28744
|
if (!fs15.existsSync(scriptsDir)) return null;
|
|
28092
28745
|
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
28093
28746
|
try {
|
|
28094
|
-
return fs15.statSync(
|
|
28747
|
+
return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
|
|
28095
28748
|
} catch {
|
|
28096
28749
|
return false;
|
|
28097
28750
|
}
|
|
28098
28751
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
28099
28752
|
if (versions.length === 0) return null;
|
|
28100
|
-
return
|
|
28753
|
+
return path26.join(scriptsDir, versions[0]);
|
|
28101
28754
|
}
|
|
28102
28755
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
28103
|
-
const canonicalUserDir =
|
|
28104
|
-
const desiredDir = requestedDir ?
|
|
28105
|
-
const upstreamRoot =
|
|
28106
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
28756
|
+
const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
28757
|
+
const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
|
|
28758
|
+
const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
|
|
28759
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
|
|
28107
28760
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
28108
28761
|
}
|
|
28109
|
-
if (
|
|
28762
|
+
if (path26.basename(desiredDir) !== type) {
|
|
28110
28763
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
28111
28764
|
}
|
|
28112
28765
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -28114,11 +28767,11 @@ var DevServer = class _DevServer {
|
|
|
28114
28767
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
28115
28768
|
}
|
|
28116
28769
|
if (!fs15.existsSync(desiredDir)) {
|
|
28117
|
-
fs15.mkdirSync(
|
|
28770
|
+
fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
|
|
28118
28771
|
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
28119
28772
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
28120
28773
|
}
|
|
28121
|
-
const providerJson =
|
|
28774
|
+
const providerJson = path26.join(desiredDir, "provider.json");
|
|
28122
28775
|
if (!fs15.existsSync(providerJson)) {
|
|
28123
28776
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
28124
28777
|
}
|
|
@@ -28154,7 +28807,7 @@ var DevServer = class _DevServer {
|
|
|
28154
28807
|
setMode: "set_mode.js"
|
|
28155
28808
|
};
|
|
28156
28809
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28157
|
-
const scriptsDir =
|
|
28810
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28158
28811
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28159
28812
|
if (latestScriptsDir) {
|
|
28160
28813
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28165,7 +28818,7 @@ var DevServer = class _DevServer {
|
|
|
28165
28818
|
for (const file of fs15.readdirSync(latestScriptsDir)) {
|
|
28166
28819
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
28167
28820
|
try {
|
|
28168
|
-
const content = fs15.readFileSync(
|
|
28821
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28169
28822
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28170
28823
|
lines.push("```javascript");
|
|
28171
28824
|
lines.push(content);
|
|
@@ -28182,7 +28835,7 @@ var DevServer = class _DevServer {
|
|
|
28182
28835
|
lines.push("");
|
|
28183
28836
|
for (const file of refFiles) {
|
|
28184
28837
|
try {
|
|
28185
|
-
const content = fs15.readFileSync(
|
|
28838
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28186
28839
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28187
28840
|
lines.push("```javascript");
|
|
28188
28841
|
lines.push(content);
|
|
@@ -28223,10 +28876,10 @@ var DevServer = class _DevServer {
|
|
|
28223
28876
|
lines.push("");
|
|
28224
28877
|
}
|
|
28225
28878
|
}
|
|
28226
|
-
const docsDir =
|
|
28879
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28227
28880
|
const loadGuide = (name) => {
|
|
28228
28881
|
try {
|
|
28229
|
-
const p =
|
|
28882
|
+
const p = path26.join(docsDir, name);
|
|
28230
28883
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28231
28884
|
} catch {
|
|
28232
28885
|
}
|
|
@@ -28400,7 +29053,7 @@ var DevServer = class _DevServer {
|
|
|
28400
29053
|
parseApproval: "parse_approval.js"
|
|
28401
29054
|
};
|
|
28402
29055
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28403
|
-
const scriptsDir =
|
|
29056
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28404
29057
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28405
29058
|
if (latestScriptsDir) {
|
|
28406
29059
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28412,7 +29065,7 @@ var DevServer = class _DevServer {
|
|
|
28412
29065
|
if (!file.endsWith(".js")) continue;
|
|
28413
29066
|
if (!targetFileNames.has(file)) continue;
|
|
28414
29067
|
try {
|
|
28415
|
-
const content = fs15.readFileSync(
|
|
29068
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28416
29069
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28417
29070
|
lines.push("```javascript");
|
|
28418
29071
|
lines.push(content);
|
|
@@ -28428,7 +29081,7 @@ var DevServer = class _DevServer {
|
|
|
28428
29081
|
lines.push("");
|
|
28429
29082
|
for (const file of refFiles) {
|
|
28430
29083
|
try {
|
|
28431
|
-
const content = fs15.readFileSync(
|
|
29084
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28432
29085
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28433
29086
|
lines.push("```javascript");
|
|
28434
29087
|
lines.push(content);
|
|
@@ -28461,10 +29114,10 @@ var DevServer = class _DevServer {
|
|
|
28461
29114
|
lines.push("");
|
|
28462
29115
|
}
|
|
28463
29116
|
}
|
|
28464
|
-
const docsDir =
|
|
29117
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28465
29118
|
const loadGuide = (name) => {
|
|
28466
29119
|
try {
|
|
28467
|
-
const p =
|
|
29120
|
+
const p = path26.join(docsDir, name);
|
|
28468
29121
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28469
29122
|
} catch {
|
|
28470
29123
|
}
|
|
@@ -29468,33 +30121,49 @@ init_config();
|
|
|
29468
30121
|
// src/mesh/mesh-events.ts
|
|
29469
30122
|
init_mesh_config();
|
|
29470
30123
|
init_logger();
|
|
30124
|
+
function readNonEmptyString(value) {
|
|
30125
|
+
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
30126
|
+
}
|
|
30127
|
+
function formatCompletionMetadata(event) {
|
|
30128
|
+
const parts = [
|
|
30129
|
+
readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
|
|
30130
|
+
readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
|
|
30131
|
+
readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
|
|
30132
|
+
].filter(Boolean);
|
|
30133
|
+
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
30134
|
+
}
|
|
29471
30135
|
function setupMeshEventForwarding(components) {
|
|
29472
30136
|
components.instanceManager.onEvent((event) => {
|
|
29473
30137
|
if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
|
|
29474
|
-
const instanceId = event.instanceId;
|
|
30138
|
+
const instanceId = readNonEmptyString(event.instanceId);
|
|
29475
30139
|
if (!instanceId) return;
|
|
29476
30140
|
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
29477
30141
|
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
29478
30142
|
const state = sourceInstance.getState();
|
|
29479
|
-
const workspace = state.workspace;
|
|
30143
|
+
const workspace = readNonEmptyString(state.workspace);
|
|
29480
30144
|
if (!workspace) return;
|
|
29481
|
-
const
|
|
29482
|
-
|
|
30145
|
+
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
30146
|
+
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
30147
|
+
const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
30148
|
+
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
30149
|
+
if (!meshId) return;
|
|
29483
30150
|
const allInstances = components.instanceManager.getByCategory("cli");
|
|
29484
30151
|
const coordinatorInstances = allInstances.filter((inst) => {
|
|
29485
30152
|
const instState = inst.getState();
|
|
29486
|
-
if (instState.settings?.meshCoordinatorFor !==
|
|
30153
|
+
if (instState.settings?.meshCoordinatorFor !== meshId) return false;
|
|
29487
30154
|
if (instState.instanceId === instanceId) return false;
|
|
29488
30155
|
return true;
|
|
29489
30156
|
});
|
|
29490
30157
|
if (coordinatorInstances.length === 0) return;
|
|
29491
|
-
const targetNode = mesh
|
|
29492
|
-
const
|
|
30158
|
+
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
30159
|
+
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
30160
|
+
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
30161
|
+
const metadata = formatCompletionMetadata(event);
|
|
29493
30162
|
let messageText = "";
|
|
29494
30163
|
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.`;
|
|
30164
|
+
messageText = `[System] ${nodeLabel} has completed its task and is now idle${metadata}. You may use mesh_read_chat to review its progress.`;
|
|
29496
30165
|
} 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.`;
|
|
30166
|
+
messageText = `[System] ${nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
29498
30167
|
}
|
|
29499
30168
|
if (!messageText) return;
|
|
29500
30169
|
for (const coord of coordinatorInstances) {
|
|
@@ -29812,6 +30481,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29812
30481
|
createGitWorkspaceMonitor,
|
|
29813
30482
|
createInteractionId,
|
|
29814
30483
|
createMesh,
|
|
30484
|
+
createWorktree,
|
|
29815
30485
|
deleteMesh,
|
|
29816
30486
|
detectAllVersions,
|
|
29817
30487
|
detectCLIs,
|
|
@@ -29864,6 +30534,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29864
30534
|
launchWithCdp,
|
|
29865
30535
|
listHostedCliRuntimes,
|
|
29866
30536
|
listMeshes,
|
|
30537
|
+
listWorktrees,
|
|
29867
30538
|
loadConfig,
|
|
29868
30539
|
loadState,
|
|
29869
30540
|
logCommand,
|
|
@@ -29883,6 +30554,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29883
30554
|
normalizeSessionModalFields,
|
|
29884
30555
|
parsePorcelainV2Status,
|
|
29885
30556
|
parseProviderSourceConfigUpdate,
|
|
30557
|
+
parseWorktreeListOutput,
|
|
29886
30558
|
partitionSessionHostDiagnosticsSessions,
|
|
29887
30559
|
partitionSessionHostRecords,
|
|
29888
30560
|
prepareSessionChatTailUpdate,
|
|
@@ -29892,6 +30564,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29892
30564
|
recordDebugTrace,
|
|
29893
30565
|
registerExtensionProviders,
|
|
29894
30566
|
removeNode,
|
|
30567
|
+
removeWorktree,
|
|
29895
30568
|
resetConfig,
|
|
29896
30569
|
resetDebugRuntimeConfig,
|
|
29897
30570
|
resetState,
|
|
@@ -29901,6 +30574,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29901
30574
|
resolveGitRepository,
|
|
29902
30575
|
resolveSessionHostAppName,
|
|
29903
30576
|
resolveSessionHostAppNameResolution,
|
|
30577
|
+
resolveWorktreePath,
|
|
29904
30578
|
runAsyncBatch,
|
|
29905
30579
|
runGit,
|
|
29906
30580
|
saveConfig,
|