@adhdev/daemon-core 0.9.76-rc.2 → 0.9.76-rc.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/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 +6 -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-worktree.d.ts +64 -0
- package/dist/git/index.d.ts +2 -0
- package/dist/index.js +870 -361
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +897 -393
- 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/repo-mesh-types.d.ts +4 -0
- package/dist/shared-types.d.ts +18 -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 +49 -4
- package/src/commands/cli-manager.ts +13 -3
- package/src/commands/mesh-coordinator.ts +149 -6
- package/src/commands/router.ts +247 -30
- package/src/config/mesh-config.ts +6 -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/providers/cli-provider-instance.d.ts +2 -0
- package/src/providers/cli-provider-instance.ts +6 -1
- package/src/repo-mesh-types.ts +4 -0
- package/src/shared-types.ts +20 -1
- package/src/status/builders.ts +17 -12
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,
|
|
@@ -5175,20 +5326,23 @@ var TurnSnapshotTracker = class {
|
|
|
5175
5326
|
}
|
|
5176
5327
|
};
|
|
5177
5328
|
|
|
5329
|
+
// src/git/index.ts
|
|
5330
|
+
init_git_worktree();
|
|
5331
|
+
|
|
5178
5332
|
// src/index.ts
|
|
5179
5333
|
init_config();
|
|
5180
5334
|
|
|
5181
5335
|
// src/config/workspaces.ts
|
|
5182
5336
|
var fs = __toESM(require("fs"));
|
|
5183
5337
|
var os = __toESM(require("os"));
|
|
5184
|
-
var
|
|
5338
|
+
var path5 = __toESM(require("path"));
|
|
5185
5339
|
var import_crypto2 = require("crypto");
|
|
5186
5340
|
var MAX_WORKSPACES = 50;
|
|
5187
5341
|
function expandPath(p) {
|
|
5188
5342
|
const t = (p || "").trim();
|
|
5189
5343
|
if (!t) return "";
|
|
5190
|
-
if (t.startsWith("~")) return
|
|
5191
|
-
return
|
|
5344
|
+
if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
5345
|
+
return path5.resolve(t);
|
|
5192
5346
|
}
|
|
5193
5347
|
function validateWorkspacePath(absPath) {
|
|
5194
5348
|
try {
|
|
@@ -5202,7 +5356,7 @@ function validateWorkspacePath(absPath) {
|
|
|
5202
5356
|
}
|
|
5203
5357
|
}
|
|
5204
5358
|
function defaultWorkspaceLabel(absPath) {
|
|
5205
|
-
const base =
|
|
5359
|
+
const base = path5.basename(absPath) || absPath;
|
|
5206
5360
|
return base;
|
|
5207
5361
|
}
|
|
5208
5362
|
function getDefaultWorkspacePath(config) {
|
|
@@ -5293,9 +5447,9 @@ function resolveIdeLaunchWorkspace(args, config) {
|
|
|
5293
5447
|
return getDefaultWorkspacePath(config) || void 0;
|
|
5294
5448
|
}
|
|
5295
5449
|
function findWorkspaceByPath(config, rawPath) {
|
|
5296
|
-
const abs =
|
|
5450
|
+
const abs = path5.resolve(expandPath(rawPath));
|
|
5297
5451
|
if (!abs) return void 0;
|
|
5298
|
-
return (config.workspaces || []).find((w) =>
|
|
5452
|
+
return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
|
|
5299
5453
|
}
|
|
5300
5454
|
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
5301
5455
|
const abs = expandPath(rawPath);
|
|
@@ -5311,7 +5465,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
|
|
|
5311
5465
|
const v = validateWorkspacePath(abs);
|
|
5312
5466
|
if (!v.ok) return { error: v.error };
|
|
5313
5467
|
const list = [...config.workspaces || []];
|
|
5314
|
-
if (list.some((w) =>
|
|
5468
|
+
if (list.some((w) => path5.resolve(w.path) === abs)) {
|
|
5315
5469
|
return { error: "Workspace already in list" };
|
|
5316
5470
|
}
|
|
5317
5471
|
if (list.length >= MAX_WORKSPACES) {
|
|
@@ -5345,7 +5499,7 @@ function setDefaultWorkspaceId(config, id) {
|
|
|
5345
5499
|
}
|
|
5346
5500
|
|
|
5347
5501
|
// src/config/recent-activity.ts
|
|
5348
|
-
var
|
|
5502
|
+
var path6 = __toESM(require("path"));
|
|
5349
5503
|
|
|
5350
5504
|
// src/providers/summary-metadata.ts
|
|
5351
5505
|
function normalizeSummaryItem(item) {
|
|
@@ -5414,9 +5568,9 @@ var MAX_ACTIVITY = 30;
|
|
|
5414
5568
|
function normalizeWorkspace(workspace) {
|
|
5415
5569
|
if (!workspace) return "";
|
|
5416
5570
|
try {
|
|
5417
|
-
return
|
|
5571
|
+
return path6.resolve(expandPath(workspace));
|
|
5418
5572
|
} catch {
|
|
5419
|
-
return
|
|
5573
|
+
return path6.resolve(workspace);
|
|
5420
5574
|
}
|
|
5421
5575
|
}
|
|
5422
5576
|
function buildRecentActivityKey(entry) {
|
|
@@ -5584,14 +5738,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
|
|
|
5584
5738
|
}
|
|
5585
5739
|
|
|
5586
5740
|
// src/config/saved-sessions.ts
|
|
5587
|
-
var
|
|
5741
|
+
var path7 = __toESM(require("path"));
|
|
5588
5742
|
var MAX_SAVED_SESSIONS = 500;
|
|
5589
5743
|
function normalizeWorkspace2(workspace) {
|
|
5590
5744
|
if (!workspace) return "";
|
|
5591
5745
|
try {
|
|
5592
|
-
return
|
|
5746
|
+
return path7.resolve(expandPath(workspace));
|
|
5593
5747
|
} catch {
|
|
5594
|
-
return
|
|
5748
|
+
return path7.resolve(workspace);
|
|
5595
5749
|
}
|
|
5596
5750
|
}
|
|
5597
5751
|
function buildSavedProviderSessionKey(providerSessionId) {
|
|
@@ -5770,7 +5924,7 @@ function resetState() {
|
|
|
5770
5924
|
var import_child_process = require("child_process");
|
|
5771
5925
|
var import_fs4 = require("fs");
|
|
5772
5926
|
var import_os2 = require("os");
|
|
5773
|
-
var
|
|
5927
|
+
var path8 = __toESM(require("path"));
|
|
5774
5928
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
5775
5929
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
5776
5930
|
function registerIDEDefinition(def) {
|
|
@@ -5789,9 +5943,9 @@ function getMergedDefinitions() {
|
|
|
5789
5943
|
function findCliCommand(command) {
|
|
5790
5944
|
const trimmed = String(command || "").trim();
|
|
5791
5945
|
if (!trimmed) return null;
|
|
5792
|
-
if (
|
|
5793
|
-
const candidate = trimmed.startsWith("~") ?
|
|
5794
|
-
const resolved =
|
|
5946
|
+
if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
5947
|
+
const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
5948
|
+
const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
|
|
5795
5949
|
return (0, import_fs4.existsSync)(resolved) ? resolved : null;
|
|
5796
5950
|
}
|
|
5797
5951
|
try {
|
|
@@ -5819,7 +5973,7 @@ function getIdeVersion(cliCommand) {
|
|
|
5819
5973
|
function checkPathExists(paths) {
|
|
5820
5974
|
const home = (0, import_os2.homedir)();
|
|
5821
5975
|
for (const p of paths) {
|
|
5822
|
-
const normalized = p.startsWith("~") ?
|
|
5976
|
+
const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
|
|
5823
5977
|
if (normalized.includes("*")) {
|
|
5824
5978
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5825
5979
|
const resolved = normalized.replace("*", username);
|
|
@@ -5831,19 +5985,19 @@ function checkPathExists(paths) {
|
|
|
5831
5985
|
return null;
|
|
5832
5986
|
}
|
|
5833
5987
|
async function detectIDEs(providerLoader) {
|
|
5834
|
-
const
|
|
5988
|
+
const os22 = (0, import_os2.platform)();
|
|
5835
5989
|
const results = [];
|
|
5836
5990
|
for (const def of getMergedDefinitions()) {
|
|
5837
5991
|
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
5838
|
-
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[
|
|
5992
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
|
|
5839
5993
|
let resolvedCli = cliPath;
|
|
5840
|
-
if (!resolvedCli && appPath &&
|
|
5994
|
+
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
5841
5995
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
5842
5996
|
if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
5843
5997
|
}
|
|
5844
|
-
if (!resolvedCli && appPath &&
|
|
5845
|
-
const { dirname:
|
|
5846
|
-
const appDir =
|
|
5998
|
+
if (!resolvedCli && appPath && os22 === "win32") {
|
|
5999
|
+
const { dirname: dirname9 } = await import("path");
|
|
6000
|
+
const appDir = dirname9(appPath);
|
|
5847
6001
|
const candidates = [
|
|
5848
6002
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
5849
6003
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -5858,7 +6012,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5858
6012
|
}
|
|
5859
6013
|
}
|
|
5860
6014
|
}
|
|
5861
|
-
const installed =
|
|
6015
|
+
const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
5862
6016
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
5863
6017
|
results.push({
|
|
5864
6018
|
id: def.id,
|
|
@@ -5877,7 +6031,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5877
6031
|
// src/detection/cli-detector.ts
|
|
5878
6032
|
var import_child_process2 = require("child_process");
|
|
5879
6033
|
var os2 = __toESM(require("os"));
|
|
5880
|
-
var
|
|
6034
|
+
var path9 = __toESM(require("path"));
|
|
5881
6035
|
var import_fs5 = require("fs");
|
|
5882
6036
|
function parseVersion(raw) {
|
|
5883
6037
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
@@ -5890,18 +6044,18 @@ function shellQuote(value) {
|
|
|
5890
6044
|
function expandHome(value) {
|
|
5891
6045
|
const trimmed = value.trim();
|
|
5892
6046
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
5893
|
-
return
|
|
6047
|
+
return path9.join(os2.homedir(), trimmed.slice(1));
|
|
5894
6048
|
}
|
|
5895
6049
|
function isExplicitCommandPath(command) {
|
|
5896
6050
|
const trimmed = command.trim();
|
|
5897
|
-
return
|
|
6051
|
+
return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
5898
6052
|
}
|
|
5899
6053
|
function resolveCommandPath(command) {
|
|
5900
6054
|
const trimmed = command.trim();
|
|
5901
6055
|
if (!trimmed) return null;
|
|
5902
6056
|
if (isExplicitCommandPath(trimmed)) {
|
|
5903
6057
|
const expanded = expandHome(trimmed);
|
|
5904
|
-
const candidate =
|
|
6058
|
+
const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
5905
6059
|
return (0, import_fs5.existsSync)(candidate) ? candidate : null;
|
|
5906
6060
|
}
|
|
5907
6061
|
return null;
|
|
@@ -8170,9 +8324,9 @@ ${cleanBody}`;
|
|
|
8170
8324
|
|
|
8171
8325
|
// src/config/chat-history.ts
|
|
8172
8326
|
var fs3 = __toESM(require("fs"));
|
|
8173
|
-
var
|
|
8327
|
+
var path11 = __toESM(require("path"));
|
|
8174
8328
|
var os5 = __toESM(require("os"));
|
|
8175
|
-
var HISTORY_DIR =
|
|
8329
|
+
var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
|
|
8176
8330
|
var RETAIN_DAYS = 30;
|
|
8177
8331
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
8178
8332
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -8335,7 +8489,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
8335
8489
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
8336
8490
|
return new Map(files.map((file) => {
|
|
8337
8491
|
try {
|
|
8338
|
-
const stat2 = fs3.statSync(
|
|
8492
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8339
8493
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
8340
8494
|
} catch {
|
|
8341
8495
|
return [file, `${file}:missing`];
|
|
@@ -8346,7 +8500,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
8346
8500
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
8347
8501
|
}
|
|
8348
8502
|
function getSavedHistoryIndexFilePath(dir) {
|
|
8349
|
-
return
|
|
8503
|
+
return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
8350
8504
|
}
|
|
8351
8505
|
function getSavedHistoryIndexLockPath(dir) {
|
|
8352
8506
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -8448,7 +8602,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
8448
8602
|
}
|
|
8449
8603
|
for (const file of Array.from(currentEntries.keys())) {
|
|
8450
8604
|
if (incomingFiles.has(file)) continue;
|
|
8451
|
-
if (!fs3.existsSync(
|
|
8605
|
+
if (!fs3.existsSync(path11.join(dir, file))) {
|
|
8452
8606
|
currentEntries.delete(file);
|
|
8453
8607
|
}
|
|
8454
8608
|
}
|
|
@@ -8474,7 +8628,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8474
8628
|
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
8475
8629
|
const files = listHistoryFiles(dir);
|
|
8476
8630
|
for (const file of files) {
|
|
8477
|
-
const stat2 = fs3.statSync(
|
|
8631
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8478
8632
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
8479
8633
|
}
|
|
8480
8634
|
return false;
|
|
@@ -8484,14 +8638,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8484
8638
|
}
|
|
8485
8639
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
8486
8640
|
try {
|
|
8487
|
-
const stat2 = fs3.statSync(
|
|
8641
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8488
8642
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
8489
8643
|
} catch {
|
|
8490
8644
|
return `${file}:missing`;
|
|
8491
8645
|
}
|
|
8492
8646
|
}
|
|
8493
8647
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
8494
|
-
const filePath =
|
|
8648
|
+
const filePath = path11.join(dir, file);
|
|
8495
8649
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
8496
8650
|
const currentEntry = entries.get(file) || null;
|
|
8497
8651
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -8564,7 +8718,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
8564
8718
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
8565
8719
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
8566
8720
|
if (!historySessionId) return null;
|
|
8567
|
-
const filePath =
|
|
8721
|
+
const filePath = path11.join(dir, file);
|
|
8568
8722
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8569
8723
|
const lines = content.split("\n").filter(Boolean);
|
|
8570
8724
|
let messageCount = 0;
|
|
@@ -8651,7 +8805,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
8651
8805
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
8652
8806
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
8653
8807
|
for (const file of files.slice().sort()) {
|
|
8654
|
-
const filePath =
|
|
8808
|
+
const filePath = path11.join(dir, file);
|
|
8655
8809
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
8656
8810
|
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
8657
8811
|
const persisted = persistedEntries.get(file);
|
|
@@ -8771,12 +8925,12 @@ var ChatHistoryWriter = class {
|
|
|
8771
8925
|
});
|
|
8772
8926
|
}
|
|
8773
8927
|
if (newMessages.length === 0) return;
|
|
8774
|
-
const dir =
|
|
8928
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8775
8929
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8776
8930
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8777
8931
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
8778
8932
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
8779
|
-
const filePath =
|
|
8933
|
+
const filePath = path11.join(dir, fileName);
|
|
8780
8934
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
8781
8935
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
8782
8936
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -8867,11 +9021,11 @@ var ChatHistoryWriter = class {
|
|
|
8867
9021
|
const ws = String(workspace || "").trim();
|
|
8868
9022
|
if (!id || !ws) return;
|
|
8869
9023
|
try {
|
|
8870
|
-
const dir =
|
|
9024
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8871
9025
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8872
9026
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8873
9027
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
8874
|
-
const filePath =
|
|
9028
|
+
const filePath = path11.join(dir, fileName);
|
|
8875
9029
|
const record = {
|
|
8876
9030
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8877
9031
|
receivedAt: Date.now(),
|
|
@@ -8917,14 +9071,14 @@ var ChatHistoryWriter = class {
|
|
|
8917
9071
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
8918
9072
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
8919
9073
|
}
|
|
8920
|
-
const dir =
|
|
9074
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8921
9075
|
if (!fs3.existsSync(dir)) return;
|
|
8922
9076
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
8923
9077
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
8924
9078
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
8925
9079
|
for (const file of files) {
|
|
8926
|
-
const sourcePath =
|
|
8927
|
-
const targetPath =
|
|
9080
|
+
const sourcePath = path11.join(dir, file);
|
|
9081
|
+
const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
8928
9082
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
8929
9083
|
const rewritten = sourceLines.map((line) => {
|
|
8930
9084
|
try {
|
|
@@ -8958,13 +9112,13 @@ var ChatHistoryWriter = class {
|
|
|
8958
9112
|
const sessionId = String(historySessionId || "").trim();
|
|
8959
9113
|
if (!sessionId) return;
|
|
8960
9114
|
try {
|
|
8961
|
-
const dir =
|
|
9115
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8962
9116
|
if (!fs3.existsSync(dir)) return;
|
|
8963
9117
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
8964
9118
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
8965
9119
|
const seen = /* @__PURE__ */ new Set();
|
|
8966
9120
|
for (const file of files) {
|
|
8967
|
-
const filePath =
|
|
9121
|
+
const filePath = path11.join(dir, file);
|
|
8968
9122
|
const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
8969
9123
|
const next = [];
|
|
8970
9124
|
for (const line of lines) {
|
|
@@ -9018,11 +9172,11 @@ var ChatHistoryWriter = class {
|
|
|
9018
9172
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
9019
9173
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
9020
9174
|
for (const dir of agentDirs) {
|
|
9021
|
-
const dirPath =
|
|
9175
|
+
const dirPath = path11.join(HISTORY_DIR, dir.name);
|
|
9022
9176
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
9023
9177
|
let removedAny = false;
|
|
9024
9178
|
for (const file of files) {
|
|
9025
|
-
const filePath =
|
|
9179
|
+
const filePath = path11.join(dirPath, file);
|
|
9026
9180
|
const stat2 = fs3.statSync(filePath);
|
|
9027
9181
|
if (stat2.mtimeMs < cutoff) {
|
|
9028
9182
|
fs3.unlinkSync(filePath);
|
|
@@ -9072,13 +9226,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
9072
9226
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
9073
9227
|
try {
|
|
9074
9228
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9075
|
-
const dir =
|
|
9229
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
9076
9230
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
9077
9231
|
const files = listHistoryFiles(dir, historySessionId);
|
|
9078
9232
|
const allMessages = [];
|
|
9079
9233
|
const seen = /* @__PURE__ */ new Set();
|
|
9080
9234
|
for (const file of files) {
|
|
9081
|
-
const filePath =
|
|
9235
|
+
const filePath = path11.join(dir, file);
|
|
9082
9236
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
9083
9237
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
9084
9238
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -9102,7 +9256,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
9102
9256
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
9103
9257
|
try {
|
|
9104
9258
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9105
|
-
const dir =
|
|
9259
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
9106
9260
|
if (!fs3.existsSync(dir)) {
|
|
9107
9261
|
savedHistorySessionCache.delete(sanitized);
|
|
9108
9262
|
return { sessions: [], hasMore: false };
|
|
@@ -9163,11 +9317,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
9163
9317
|
}
|
|
9164
9318
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
9165
9319
|
try {
|
|
9166
|
-
const dir =
|
|
9320
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9167
9321
|
if (!fs3.existsSync(dir)) return null;
|
|
9168
9322
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
9169
9323
|
for (const file of files) {
|
|
9170
|
-
const lines = fs3.readFileSync(
|
|
9324
|
+
const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
9171
9325
|
for (const line of lines) {
|
|
9172
9326
|
try {
|
|
9173
9327
|
const parsed = JSON.parse(line);
|
|
@@ -9187,16 +9341,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
9187
9341
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
9188
9342
|
if (records.length === 0) return false;
|
|
9189
9343
|
try {
|
|
9190
|
-
const dir =
|
|
9344
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9191
9345
|
fs3.mkdirSync(dir, { recursive: true });
|
|
9192
9346
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
9193
9347
|
for (const file of fs3.readdirSync(dir)) {
|
|
9194
9348
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
9195
|
-
fs3.unlinkSync(
|
|
9349
|
+
fs3.unlinkSync(path11.join(dir, file));
|
|
9196
9350
|
}
|
|
9197
9351
|
}
|
|
9198
9352
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
9199
|
-
const filePath =
|
|
9353
|
+
const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
9200
9354
|
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
9201
9355
|
`, "utf-8");
|
|
9202
9356
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -11191,6 +11345,14 @@ function getActiveChatOptions(profile) {
|
|
|
11191
11345
|
if (profile === "full") return {};
|
|
11192
11346
|
return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
|
|
11193
11347
|
}
|
|
11348
|
+
function resolveSessionStatus(activeChat, providerStatus) {
|
|
11349
|
+
const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
|
|
11350
|
+
const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
|
|
11351
|
+
if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
|
|
11352
|
+
if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
|
|
11353
|
+
if (topLevelStatus !== "idle") return topLevelStatus;
|
|
11354
|
+
return chatStatus;
|
|
11355
|
+
}
|
|
11194
11356
|
function shouldIncludeSessionControls(profile) {
|
|
11195
11357
|
return profile !== "live";
|
|
11196
11358
|
}
|
|
@@ -11269,9 +11431,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
11269
11431
|
providerName: state.name,
|
|
11270
11432
|
kind: "workspace",
|
|
11271
11433
|
transport: "cdp-page",
|
|
11272
|
-
status:
|
|
11273
|
-
activeModal: activeChat?.activeModal || null
|
|
11274
|
-
}),
|
|
11434
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11275
11435
|
title,
|
|
11276
11436
|
workspace,
|
|
11277
11437
|
...git && { git },
|
|
@@ -11306,9 +11466,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
11306
11466
|
providerSessionId: ext.providerSessionId,
|
|
11307
11467
|
kind: "agent",
|
|
11308
11468
|
transport: "cdp-webview",
|
|
11309
|
-
status:
|
|
11310
|
-
activeModal: activeChat?.activeModal || null
|
|
11311
|
-
}),
|
|
11469
|
+
status: resolveSessionStatus(activeChat, ext.status),
|
|
11312
11470
|
title: activeChat?.title || ext.name,
|
|
11313
11471
|
workspace,
|
|
11314
11472
|
...git && { git },
|
|
@@ -11358,9 +11516,7 @@ function buildCliSession(state, options) {
|
|
|
11358
11516
|
providerSessionId: state.providerSessionId,
|
|
11359
11517
|
kind: "agent",
|
|
11360
11518
|
transport: "pty",
|
|
11361
|
-
status:
|
|
11362
|
-
activeModal: activeChat?.activeModal || null
|
|
11363
|
-
}),
|
|
11519
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11364
11520
|
title: activeChat?.title || state.name,
|
|
11365
11521
|
workspace,
|
|
11366
11522
|
...git && { git },
|
|
@@ -11408,9 +11564,7 @@ function buildAcpSession(state, options) {
|
|
|
11408
11564
|
providerName: state.name,
|
|
11409
11565
|
kind: "agent",
|
|
11410
11566
|
transport: "acp",
|
|
11411
|
-
status:
|
|
11412
|
-
activeModal: activeChat?.activeModal || null
|
|
11413
|
-
}),
|
|
11567
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11414
11568
|
title: activeChat?.title || state.name,
|
|
11415
11569
|
workspace,
|
|
11416
11570
|
...git && { git },
|
|
@@ -11533,7 +11687,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
11533
11687
|
// src/commands/chat-commands.ts
|
|
11534
11688
|
var fs4 = __toESM(require("fs"));
|
|
11535
11689
|
var os6 = __toESM(require("os"));
|
|
11536
|
-
var
|
|
11690
|
+
var path12 = __toESM(require("path"));
|
|
11537
11691
|
var import_node_crypto = require("crypto");
|
|
11538
11692
|
|
|
11539
11693
|
// src/providers/provider-input-support.ts
|
|
@@ -11896,6 +12050,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
|
|
|
11896
12050
|
return raw;
|
|
11897
12051
|
}
|
|
11898
12052
|
}
|
|
12053
|
+
function isGeneratingLikeStatus(status) {
|
|
12054
|
+
return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
|
|
12055
|
+
}
|
|
12056
|
+
function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
12057
|
+
if (!isGeneratingLikeStatus(parsedStatus)) return false;
|
|
12058
|
+
if (hasNonEmptyModalButtons(activeModal)) return false;
|
|
12059
|
+
const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
12060
|
+
if (adapterRawStatus !== "idle") return false;
|
|
12061
|
+
if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
|
|
12062
|
+
return true;
|
|
12063
|
+
}
|
|
12064
|
+
function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
12065
|
+
if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
|
|
12066
|
+
return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
|
|
12067
|
+
}
|
|
12068
|
+
function finalizeStreamingMessagesWhenIdle(messages, status) {
|
|
12069
|
+
if (status !== "idle") return messages;
|
|
12070
|
+
return messages.map((message) => {
|
|
12071
|
+
const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
|
|
12072
|
+
const hasStreamingMeta = meta?.streaming === true;
|
|
12073
|
+
if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
|
|
12074
|
+
return {
|
|
12075
|
+
...message,
|
|
12076
|
+
...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
|
|
12077
|
+
...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
|
|
12078
|
+
};
|
|
12079
|
+
});
|
|
12080
|
+
}
|
|
11899
12081
|
function buildReadChatCommandResult(payload, args) {
|
|
11900
12082
|
let validatedPayload;
|
|
11901
12083
|
const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
|
|
@@ -12044,7 +12226,7 @@ function buildDebugBundleText(bundle) {
|
|
|
12044
12226
|
}
|
|
12045
12227
|
function getChatDebugBundleDir() {
|
|
12046
12228
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
12047
|
-
return override ||
|
|
12229
|
+
return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
12048
12230
|
}
|
|
12049
12231
|
function safeBundleIdSegment(value, fallback) {
|
|
12050
12232
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -12077,7 +12259,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
12077
12259
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
12078
12260
|
const dir = getChatDebugBundleDir();
|
|
12079
12261
|
fs4.mkdirSync(dir, { recursive: true });
|
|
12080
|
-
const savedPath =
|
|
12262
|
+
const savedPath = path12.join(dir, `${bundleId}.json`);
|
|
12081
12263
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
12082
12264
|
`;
|
|
12083
12265
|
fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -12334,10 +12516,13 @@ async function handleReadChat(h, args) {
|
|
|
12334
12516
|
const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
|
|
12335
12517
|
const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
|
|
12336
12518
|
const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
|
|
12337
|
-
const returnedStatus = parsedRecord.status
|
|
12338
|
-
|
|
12519
|
+
const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
|
|
12520
|
+
const runtimeMessageMerger = getTargetInstance(h, args);
|
|
12521
|
+
const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
|
|
12522
|
+
const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
|
|
12523
|
+
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
12524
|
return buildReadChatCommandResult({
|
|
12340
|
-
messages:
|
|
12525
|
+
messages: returnedMessages,
|
|
12341
12526
|
status: returnedStatus,
|
|
12342
12527
|
activeModal,
|
|
12343
12528
|
debugReadChat: {
|
|
@@ -12348,7 +12533,7 @@ async function handleReadChat(h, args) {
|
|
|
12348
12533
|
returnedStatus: String(returnedStatus || ""),
|
|
12349
12534
|
shouldPreferAdapterMessages: false,
|
|
12350
12535
|
parsedMsgCount: parsedRecord.messages.length,
|
|
12351
|
-
returnedMsgCount:
|
|
12536
|
+
returnedMsgCount: returnedMessages.length
|
|
12352
12537
|
},
|
|
12353
12538
|
...title ? { title } : {},
|
|
12354
12539
|
...providerSessionId ? { providerSessionId } : {},
|
|
@@ -13221,7 +13406,7 @@ async function handleResolveAction(h, args) {
|
|
|
13221
13406
|
|
|
13222
13407
|
// src/commands/cdp-commands.ts
|
|
13223
13408
|
var fs5 = __toESM(require("fs"));
|
|
13224
|
-
var
|
|
13409
|
+
var path13 = __toESM(require("path"));
|
|
13225
13410
|
var os7 = __toESM(require("os"));
|
|
13226
13411
|
var KEY_TO_VK = {
|
|
13227
13412
|
Backspace: 8,
|
|
@@ -13478,25 +13663,25 @@ function resolveSafePath(requestedPath) {
|
|
|
13478
13663
|
const inputPath = rawPath || ".";
|
|
13479
13664
|
const home = os7.homedir();
|
|
13480
13665
|
if (inputPath.startsWith("~")) {
|
|
13481
|
-
return
|
|
13666
|
+
return path13.resolve(path13.join(home, inputPath.slice(1)));
|
|
13482
13667
|
}
|
|
13483
13668
|
if (process.platform === "win32") {
|
|
13484
13669
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
13485
|
-
if (
|
|
13486
|
-
return
|
|
13670
|
+
if (path13.win32.isAbsolute(normalized)) {
|
|
13671
|
+
return path13.win32.normalize(normalized);
|
|
13487
13672
|
}
|
|
13488
|
-
return
|
|
13673
|
+
return path13.win32.resolve(normalized);
|
|
13489
13674
|
}
|
|
13490
|
-
if (
|
|
13491
|
-
return
|
|
13675
|
+
if (path13.isAbsolute(inputPath)) {
|
|
13676
|
+
return path13.normalize(inputPath);
|
|
13492
13677
|
}
|
|
13493
|
-
return
|
|
13678
|
+
return path13.resolve(inputPath);
|
|
13494
13679
|
}
|
|
13495
13680
|
function listDirectoryEntriesSafe(dirPath) {
|
|
13496
13681
|
const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
|
|
13497
13682
|
const files = [];
|
|
13498
13683
|
for (const entry of entries) {
|
|
13499
|
-
const entryPath =
|
|
13684
|
+
const entryPath = path13.join(dirPath, entry.name);
|
|
13500
13685
|
try {
|
|
13501
13686
|
if (entry.isDirectory()) {
|
|
13502
13687
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -13550,7 +13735,7 @@ async function handleFileRead(h, args) {
|
|
|
13550
13735
|
async function handleFileWrite(h, args) {
|
|
13551
13736
|
try {
|
|
13552
13737
|
const filePath = resolveSafePath(args?.path);
|
|
13553
|
-
fs5.mkdirSync(
|
|
13738
|
+
fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
13554
13739
|
fs5.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
13555
13740
|
return { success: true, path: filePath };
|
|
13556
13741
|
} catch (e) {
|
|
@@ -14669,7 +14854,7 @@ var DaemonCommandHandler = class {
|
|
|
14669
14854
|
|
|
14670
14855
|
// src/commands/cli-manager.ts
|
|
14671
14856
|
var os13 = __toESM(require("os"));
|
|
14672
|
-
var
|
|
14857
|
+
var path17 = __toESM(require("path"));
|
|
14673
14858
|
var crypto4 = __toESM(require("crypto"));
|
|
14674
14859
|
var import_fs6 = require("fs");
|
|
14675
14860
|
var import_child_process6 = require("child_process");
|
|
@@ -14679,7 +14864,7 @@ init_config();
|
|
|
14679
14864
|
|
|
14680
14865
|
// src/providers/cli-provider-instance.ts
|
|
14681
14866
|
var os12 = __toESM(require("os"));
|
|
14682
|
-
var
|
|
14867
|
+
var path16 = __toESM(require("path"));
|
|
14683
14868
|
var crypto3 = __toESM(require("crypto"));
|
|
14684
14869
|
var fs6 = __toESM(require("fs"));
|
|
14685
14870
|
var import_node_module = require("module");
|
|
@@ -14738,7 +14923,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
|
|
|
14738
14923
|
var CachedDatabaseSync = null;
|
|
14739
14924
|
function getDatabaseSync() {
|
|
14740
14925
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
14741
|
-
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
14926
|
+
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
14742
14927
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
14743
14928
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
14744
14929
|
if (!CachedDatabaseSync) {
|
|
@@ -14791,7 +14976,7 @@ var CliProviderInstance = class {
|
|
|
14791
14976
|
this.providerSessionId = options?.providerSessionId;
|
|
14792
14977
|
this.launchMode = options?.launchMode || "new";
|
|
14793
14978
|
this.onProviderSessionResolved = options?.onProviderSessionResolved;
|
|
14794
|
-
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
14979
|
+
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
|
|
14795
14980
|
this.monitor = new StatusMonitor();
|
|
14796
14981
|
this.historyWriter = new ChatHistoryWriter();
|
|
14797
14982
|
}
|
|
@@ -15475,6 +15660,9 @@ ${effect.notification.body || ""}`.trim();
|
|
|
15475
15660
|
);
|
|
15476
15661
|
}
|
|
15477
15662
|
}
|
|
15663
|
+
mergeRuntimeChatMessages(parsedMessages) {
|
|
15664
|
+
return this.mergeConversationMessages(parsedMessages);
|
|
15665
|
+
}
|
|
15478
15666
|
mergeConversationMessages(parsedMessages) {
|
|
15479
15667
|
if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
|
|
15480
15668
|
return normalizeChatMessages([...parsedMessages, ...this.runtimeMessages.map((entry) => entry.message)].map((message, index) => ({ message, index })).sort((a, b) => {
|
|
@@ -16804,11 +16992,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
|
|
|
16804
16992
|
// src/commands/cli-manager.ts
|
|
16805
16993
|
function isExplicitCommand(command) {
|
|
16806
16994
|
const trimmed = command.trim();
|
|
16807
|
-
return
|
|
16995
|
+
return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
16808
16996
|
}
|
|
16809
16997
|
function expandExecutable(command) {
|
|
16810
16998
|
const trimmed = command.trim();
|
|
16811
|
-
return trimmed.startsWith("~") ?
|
|
16999
|
+
return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
|
|
16812
17000
|
}
|
|
16813
17001
|
function commandExists(command) {
|
|
16814
17002
|
const trimmed = command.trim();
|
|
@@ -17002,7 +17190,7 @@ var DaemonCliManager = class {
|
|
|
17002
17190
|
attachExisting
|
|
17003
17191
|
}) || void 0;
|
|
17004
17192
|
}
|
|
17005
|
-
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
|
|
17193
|
+
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
|
|
17006
17194
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
17007
17195
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
17008
17196
|
if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
|
|
@@ -17016,7 +17204,7 @@ var DaemonCliManager = class {
|
|
|
17016
17204
|
providerSessionId,
|
|
17017
17205
|
attachExisting
|
|
17018
17206
|
);
|
|
17019
|
-
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
|
|
17207
|
+
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
|
|
17020
17208
|
}
|
|
17021
17209
|
throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
|
|
17022
17210
|
}
|
|
@@ -17089,7 +17277,7 @@ var DaemonCliManager = class {
|
|
|
17089
17277
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
17090
17278
|
const trimmed = (workingDir || "").trim();
|
|
17091
17279
|
if (!trimmed) throw new Error("working directory required");
|
|
17092
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
17280
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
|
|
17093
17281
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
17094
17282
|
const rawProvider = this.providerLoader.getByAlias(cliType);
|
|
17095
17283
|
const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
|
|
@@ -17219,6 +17407,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17219
17407
|
{
|
|
17220
17408
|
providerSessionId: sessionBinding.providerSessionId,
|
|
17221
17409
|
launchMode: sessionBinding.launchMode,
|
|
17410
|
+
extraEnv: options?.extraEnv,
|
|
17222
17411
|
onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
|
|
17223
17412
|
this.persistRecentActivity({
|
|
17224
17413
|
kind: "cli",
|
|
@@ -17239,7 +17428,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17239
17428
|
resolvedCliArgs,
|
|
17240
17429
|
key,
|
|
17241
17430
|
sessionBinding.providerSessionId,
|
|
17242
|
-
false
|
|
17431
|
+
false,
|
|
17432
|
+
options?.extraEnv
|
|
17243
17433
|
);
|
|
17244
17434
|
try {
|
|
17245
17435
|
await adapter.spawn();
|
|
@@ -17468,7 +17658,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17468
17658
|
dir,
|
|
17469
17659
|
args?.cliArgs,
|
|
17470
17660
|
args?.initialModel,
|
|
17471
|
-
{ resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
|
|
17661
|
+
{ resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings, extraEnv: args?.env }
|
|
17472
17662
|
);
|
|
17473
17663
|
return {
|
|
17474
17664
|
success: true,
|
|
@@ -17590,11 +17780,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17590
17780
|
var import_child_process7 = require("child_process");
|
|
17591
17781
|
var net = __toESM(require("net"));
|
|
17592
17782
|
var os15 = __toESM(require("os"));
|
|
17593
|
-
var
|
|
17783
|
+
var path19 = __toESM(require("path"));
|
|
17594
17784
|
|
|
17595
17785
|
// src/providers/provider-loader.ts
|
|
17596
17786
|
var fs7 = __toESM(require("fs"));
|
|
17597
|
-
var
|
|
17787
|
+
var path18 = __toESM(require("path"));
|
|
17598
17788
|
var os14 = __toESM(require("os"));
|
|
17599
17789
|
var chokidar = __toESM(require("chokidar"));
|
|
17600
17790
|
init_logger();
|
|
@@ -17918,7 +18108,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17918
18108
|
try {
|
|
17919
18109
|
if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
|
|
17920
18110
|
return ["ide", "extension", "cli", "acp"].some(
|
|
17921
|
-
(category) => fs7.existsSync(
|
|
18111
|
+
(category) => fs7.existsSync(path18.join(candidate, category))
|
|
17922
18112
|
);
|
|
17923
18113
|
} catch {
|
|
17924
18114
|
return false;
|
|
@@ -17926,20 +18116,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17926
18116
|
}
|
|
17927
18117
|
static hasProviderRootMarker(candidate) {
|
|
17928
18118
|
try {
|
|
17929
|
-
return fs7.existsSync(
|
|
18119
|
+
return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
17930
18120
|
} catch {
|
|
17931
18121
|
return false;
|
|
17932
18122
|
}
|
|
17933
18123
|
}
|
|
17934
18124
|
detectDefaultUserDir() {
|
|
17935
|
-
const fallback =
|
|
18125
|
+
const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17936
18126
|
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
17937
18127
|
const visited = /* @__PURE__ */ new Set();
|
|
17938
18128
|
for (const start of this.probeStarts) {
|
|
17939
|
-
let current =
|
|
18129
|
+
let current = path18.resolve(start);
|
|
17940
18130
|
while (!visited.has(current)) {
|
|
17941
18131
|
visited.add(current);
|
|
17942
|
-
const siblingCandidate =
|
|
18132
|
+
const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
17943
18133
|
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
17944
18134
|
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
17945
18135
|
if (envOptIn || hasMarker) {
|
|
@@ -17961,7 +18151,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17961
18151
|
return { path: siblingCandidate, source };
|
|
17962
18152
|
}
|
|
17963
18153
|
}
|
|
17964
|
-
const parent =
|
|
18154
|
+
const parent = path18.dirname(current);
|
|
17965
18155
|
if (parent === current) break;
|
|
17966
18156
|
current = parent;
|
|
17967
18157
|
}
|
|
@@ -17971,11 +18161,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17971
18161
|
constructor(options) {
|
|
17972
18162
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
17973
18163
|
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
17974
|
-
this.defaultProvidersDir =
|
|
18164
|
+
this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17975
18165
|
const detected = this.detectDefaultUserDir();
|
|
17976
18166
|
this.userDir = detected.path;
|
|
17977
18167
|
this.userDirSource = detected.source;
|
|
17978
|
-
this.upstreamDir =
|
|
18168
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17979
18169
|
this.disableUpstream = false;
|
|
17980
18170
|
this.applySourceConfig({
|
|
17981
18171
|
userDir: options?.userDir,
|
|
@@ -18034,7 +18224,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18034
18224
|
this.userDir = detected.path;
|
|
18035
18225
|
this.userDirSource = detected.source;
|
|
18036
18226
|
}
|
|
18037
|
-
this.upstreamDir =
|
|
18227
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
18038
18228
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
18039
18229
|
if (this.explicitProviderDir) {
|
|
18040
18230
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -18048,7 +18238,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18048
18238
|
* Canonical provider directory shape for a given root.
|
|
18049
18239
|
*/
|
|
18050
18240
|
getProviderDir(root, category, type) {
|
|
18051
|
-
return
|
|
18241
|
+
return path18.join(root, category, type);
|
|
18052
18242
|
}
|
|
18053
18243
|
/**
|
|
18054
18244
|
* Canonical user override directory for a provider.
|
|
@@ -18075,7 +18265,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18075
18265
|
resolveProviderFile(type, ...segments) {
|
|
18076
18266
|
const dir = this.findProviderDirInternal(type);
|
|
18077
18267
|
if (!dir) return null;
|
|
18078
|
-
return
|
|
18268
|
+
return path18.join(dir, ...segments);
|
|
18079
18269
|
}
|
|
18080
18270
|
/**
|
|
18081
18271
|
* Load all providers (3-tier priority)
|
|
@@ -18114,7 +18304,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18114
18304
|
if (!fs7.existsSync(this.upstreamDir)) return false;
|
|
18115
18305
|
try {
|
|
18116
18306
|
return fs7.readdirSync(this.upstreamDir).some(
|
|
18117
|
-
(d) => fs7.statSync(
|
|
18307
|
+
(d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
|
|
18118
18308
|
);
|
|
18119
18309
|
} catch {
|
|
18120
18310
|
return false;
|
|
@@ -18611,8 +18801,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18611
18801
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
18612
18802
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
18613
18803
|
if (providerDir) {
|
|
18614
|
-
const fullDir =
|
|
18615
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18804
|
+
const fullDir = path18.join(providerDir, entry.scriptDir);
|
|
18805
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18616
18806
|
}
|
|
18617
18807
|
matched = true;
|
|
18618
18808
|
}
|
|
@@ -18627,8 +18817,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18627
18817
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18628
18818
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
18629
18819
|
if (providerDir) {
|
|
18630
|
-
const fullDir =
|
|
18631
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18820
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18821
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18632
18822
|
}
|
|
18633
18823
|
}
|
|
18634
18824
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -18645,8 +18835,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18645
18835
|
resolved._resolvedScriptDir = dirOverride;
|
|
18646
18836
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
18647
18837
|
if (providerDir) {
|
|
18648
|
-
const fullDir =
|
|
18649
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18838
|
+
const fullDir = path18.join(providerDir, dirOverride);
|
|
18839
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18650
18840
|
}
|
|
18651
18841
|
}
|
|
18652
18842
|
} else if (override.scripts) {
|
|
@@ -18662,8 +18852,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18662
18852
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18663
18853
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
18664
18854
|
if (providerDir) {
|
|
18665
|
-
const fullDir =
|
|
18666
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18855
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18856
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18667
18857
|
}
|
|
18668
18858
|
}
|
|
18669
18859
|
}
|
|
@@ -18695,14 +18885,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18695
18885
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
18696
18886
|
return null;
|
|
18697
18887
|
}
|
|
18698
|
-
const dir =
|
|
18888
|
+
const dir = path18.join(providerDir, scriptDir);
|
|
18699
18889
|
if (!fs7.existsSync(dir)) {
|
|
18700
18890
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
18701
18891
|
return null;
|
|
18702
18892
|
}
|
|
18703
18893
|
const cached = this.scriptsCache.get(dir);
|
|
18704
18894
|
if (cached) return cached;
|
|
18705
|
-
const scriptsJs =
|
|
18895
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
18706
18896
|
if (fs7.existsSync(scriptsJs)) {
|
|
18707
18897
|
try {
|
|
18708
18898
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -18744,7 +18934,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18744
18934
|
return;
|
|
18745
18935
|
}
|
|
18746
18936
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
18747
|
-
this.log(`File changed: ${
|
|
18937
|
+
this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
|
|
18748
18938
|
this.reload();
|
|
18749
18939
|
}
|
|
18750
18940
|
};
|
|
@@ -18799,7 +18989,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18799
18989
|
}
|
|
18800
18990
|
const https = require("https");
|
|
18801
18991
|
const { execSync: execSync7 } = require("child_process");
|
|
18802
|
-
const metaPath =
|
|
18992
|
+
const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
18803
18993
|
let prevEtag = "";
|
|
18804
18994
|
let prevTimestamp = 0;
|
|
18805
18995
|
try {
|
|
@@ -18859,17 +19049,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18859
19049
|
return { updated: false };
|
|
18860
19050
|
}
|
|
18861
19051
|
this.log("Downloading latest providers from GitHub...");
|
|
18862
|
-
const tmpTar =
|
|
18863
|
-
const tmpExtract =
|
|
19052
|
+
const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
19053
|
+
const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
18864
19054
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
18865
19055
|
fs7.mkdirSync(tmpExtract, { recursive: true });
|
|
18866
19056
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
18867
19057
|
const extracted = fs7.readdirSync(tmpExtract);
|
|
18868
19058
|
const rootDir = extracted.find(
|
|
18869
|
-
(d) => fs7.statSync(
|
|
19059
|
+
(d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
18870
19060
|
);
|
|
18871
19061
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
18872
|
-
const sourceDir =
|
|
19062
|
+
const sourceDir = path18.join(tmpExtract, rootDir);
|
|
18873
19063
|
const backupDir = this.upstreamDir + ".bak";
|
|
18874
19064
|
if (fs7.existsSync(this.upstreamDir)) {
|
|
18875
19065
|
if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -18944,8 +19134,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18944
19134
|
copyDirRecursive(src, dest) {
|
|
18945
19135
|
fs7.mkdirSync(dest, { recursive: true });
|
|
18946
19136
|
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
18947
|
-
const srcPath =
|
|
18948
|
-
const destPath =
|
|
19137
|
+
const srcPath = path18.join(src, entry.name);
|
|
19138
|
+
const destPath = path18.join(dest, entry.name);
|
|
18949
19139
|
if (entry.isDirectory()) {
|
|
18950
19140
|
this.copyDirRecursive(srcPath, destPath);
|
|
18951
19141
|
} else {
|
|
@@ -18956,7 +19146,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18956
19146
|
/** .meta.json save */
|
|
18957
19147
|
writeMeta(metaPath, etag, timestamp) {
|
|
18958
19148
|
try {
|
|
18959
|
-
fs7.mkdirSync(
|
|
19149
|
+
fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
|
|
18960
19150
|
fs7.writeFileSync(metaPath, JSON.stringify({
|
|
18961
19151
|
etag,
|
|
18962
19152
|
timestamp,
|
|
@@ -18973,7 +19163,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18973
19163
|
const scan = (d) => {
|
|
18974
19164
|
try {
|
|
18975
19165
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
18976
|
-
if (entry.isDirectory()) scan(
|
|
19166
|
+
if (entry.isDirectory()) scan(path18.join(d, entry.name));
|
|
18977
19167
|
else if (entry.name === "provider.json") count++;
|
|
18978
19168
|
}
|
|
18979
19169
|
} catch {
|
|
@@ -19201,17 +19391,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19201
19391
|
for (const root of searchRoots) {
|
|
19202
19392
|
if (!fs7.existsSync(root)) continue;
|
|
19203
19393
|
const candidate = this.getProviderDir(root, cat, type);
|
|
19204
|
-
if (fs7.existsSync(
|
|
19205
|
-
const catDir =
|
|
19394
|
+
if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
|
|
19395
|
+
const catDir = path18.join(root, cat);
|
|
19206
19396
|
if (fs7.existsSync(catDir)) {
|
|
19207
19397
|
try {
|
|
19208
19398
|
for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
|
|
19209
19399
|
if (!entry.isDirectory()) continue;
|
|
19210
|
-
const jsonPath =
|
|
19400
|
+
const jsonPath = path18.join(catDir, entry.name, "provider.json");
|
|
19211
19401
|
if (fs7.existsSync(jsonPath)) {
|
|
19212
19402
|
try {
|
|
19213
19403
|
const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
|
|
19214
|
-
if (data.type === type) return
|
|
19404
|
+
if (data.type === type) return path18.join(catDir, entry.name);
|
|
19215
19405
|
} catch {
|
|
19216
19406
|
}
|
|
19217
19407
|
}
|
|
@@ -19228,7 +19418,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19228
19418
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
19229
19419
|
*/
|
|
19230
19420
|
buildScriptWrappersFromDir(dir) {
|
|
19231
|
-
const scriptsJs =
|
|
19421
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
19232
19422
|
if (fs7.existsSync(scriptsJs)) {
|
|
19233
19423
|
try {
|
|
19234
19424
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -19242,7 +19432,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19242
19432
|
for (const file of fs7.readdirSync(dir)) {
|
|
19243
19433
|
if (!file.endsWith(".js")) continue;
|
|
19244
19434
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
19245
|
-
const filePath =
|
|
19435
|
+
const filePath = path18.join(dir, file);
|
|
19246
19436
|
result[scriptName] = (...args) => {
|
|
19247
19437
|
try {
|
|
19248
19438
|
let content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -19302,7 +19492,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19302
19492
|
}
|
|
19303
19493
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
19304
19494
|
if (hasJson) {
|
|
19305
|
-
const jsonPath =
|
|
19495
|
+
const jsonPath = path18.join(d, "provider.json");
|
|
19306
19496
|
try {
|
|
19307
19497
|
const raw = fs7.readFileSync(jsonPath, "utf-8");
|
|
19308
19498
|
const mod = JSON.parse(raw);
|
|
@@ -19323,7 +19513,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19323
19513
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
19324
19514
|
} else {
|
|
19325
19515
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
19326
|
-
const scriptsPath =
|
|
19516
|
+
const scriptsPath = path18.join(d, "scripts.js");
|
|
19327
19517
|
if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
|
|
19328
19518
|
try {
|
|
19329
19519
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -19349,7 +19539,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19349
19539
|
if (!entry.isDirectory()) continue;
|
|
19350
19540
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
19351
19541
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
19352
|
-
scan(
|
|
19542
|
+
scan(path18.join(d, entry.name));
|
|
19353
19543
|
}
|
|
19354
19544
|
}
|
|
19355
19545
|
};
|
|
@@ -19674,8 +19864,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
19674
19864
|
const appNameMap = getMacAppIdentifiers();
|
|
19675
19865
|
const appName = appNameMap[ideId];
|
|
19676
19866
|
if (appName) {
|
|
19677
|
-
const storagePath =
|
|
19678
|
-
process.env.APPDATA ||
|
|
19867
|
+
const storagePath = path19.join(
|
|
19868
|
+
process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
|
|
19679
19869
|
appName,
|
|
19680
19870
|
"storage.json"
|
|
19681
19871
|
);
|
|
@@ -19864,9 +20054,9 @@ init_logger();
|
|
|
19864
20054
|
|
|
19865
20055
|
// src/logging/command-log.ts
|
|
19866
20056
|
var fs8 = __toESM(require("fs"));
|
|
19867
|
-
var
|
|
20057
|
+
var path20 = __toESM(require("path"));
|
|
19868
20058
|
var os16 = __toESM(require("os"));
|
|
19869
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
20059
|
+
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
20060
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
19871
20061
|
var MAX_DAYS = 7;
|
|
19872
20062
|
try {
|
|
@@ -19904,13 +20094,13 @@ function getDateStr2() {
|
|
|
19904
20094
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
19905
20095
|
}
|
|
19906
20096
|
var currentDate2 = getDateStr2();
|
|
19907
|
-
var currentFile =
|
|
20097
|
+
var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19908
20098
|
var writeCount2 = 0;
|
|
19909
20099
|
function checkRotation() {
|
|
19910
20100
|
const today = getDateStr2();
|
|
19911
20101
|
if (today !== currentDate2) {
|
|
19912
20102
|
currentDate2 = today;
|
|
19913
|
-
currentFile =
|
|
20103
|
+
currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19914
20104
|
cleanOldFiles();
|
|
19915
20105
|
}
|
|
19916
20106
|
}
|
|
@@ -19924,7 +20114,7 @@ function cleanOldFiles() {
|
|
|
19924
20114
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
19925
20115
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
19926
20116
|
try {
|
|
19927
|
-
fs8.unlinkSync(
|
|
20117
|
+
fs8.unlinkSync(path20.join(LOG_DIR2, file));
|
|
19928
20118
|
} catch {
|
|
19929
20119
|
}
|
|
19930
20120
|
}
|
|
@@ -20007,14 +20197,66 @@ function getRecentCommands(count = 50) {
|
|
|
20007
20197
|
cleanOldFiles();
|
|
20008
20198
|
|
|
20009
20199
|
// src/commands/router.ts
|
|
20200
|
+
var yaml = __toESM(require("js-yaml"));
|
|
20010
20201
|
init_logger();
|
|
20011
20202
|
|
|
20012
20203
|
// src/commands/mesh-coordinator.ts
|
|
20013
|
-
var
|
|
20204
|
+
var import_node_child_process3 = require("child_process");
|
|
20205
|
+
var import_node_fs3 = require("fs");
|
|
20014
20206
|
var import_node_module2 = require("module");
|
|
20207
|
+
var os17 = __toESM(require("os"));
|
|
20015
20208
|
var import_node_path = require("path");
|
|
20016
20209
|
var DEFAULT_SERVER_NAME = "adhdev-mesh";
|
|
20017
20210
|
var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
20211
|
+
var HERMES_CLI_TYPE = "hermes-cli";
|
|
20212
|
+
var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
|
|
20213
|
+
function isHermesProvider(provider, cliType) {
|
|
20214
|
+
const type = cliType?.trim() || provider?.type?.trim() || "";
|
|
20215
|
+
return type === HERMES_CLI_TYPE;
|
|
20216
|
+
}
|
|
20217
|
+
function resolveHermesMeshCoordinatorSetup(options) {
|
|
20218
|
+
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
20219
|
+
meshId: options.meshId,
|
|
20220
|
+
nodeExecutable: options.nodeExecutable,
|
|
20221
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
20222
|
+
});
|
|
20223
|
+
if (!mcpServer) {
|
|
20224
|
+
return {
|
|
20225
|
+
kind: "unsupported",
|
|
20226
|
+
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
20227
|
+
};
|
|
20228
|
+
}
|
|
20229
|
+
const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
|
|
20230
|
+
if (!configPath.trim()) {
|
|
20231
|
+
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
|
|
20232
|
+
}
|
|
20233
|
+
return {
|
|
20234
|
+
kind: "auto_import",
|
|
20235
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20236
|
+
configPath,
|
|
20237
|
+
configFormat: "hermes_config_yaml",
|
|
20238
|
+
mcpServer
|
|
20239
|
+
};
|
|
20240
|
+
}
|
|
20241
|
+
function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
|
|
20242
|
+
return {
|
|
20243
|
+
kind: "manual",
|
|
20244
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20245
|
+
configFormat: "hermes_config_yaml",
|
|
20246
|
+
configPathCommand: HERMES_MCP_CONFIG_PATH,
|
|
20247
|
+
requiresRestart: true,
|
|
20248
|
+
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.",
|
|
20249
|
+
template: renderMeshCoordinatorTemplate(
|
|
20250
|
+
"mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
|
|
20251
|
+
{
|
|
20252
|
+
meshId,
|
|
20253
|
+
workspace,
|
|
20254
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20255
|
+
adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
|
|
20256
|
+
}
|
|
20257
|
+
)
|
|
20258
|
+
};
|
|
20259
|
+
}
|
|
20018
20260
|
function resolveMeshCoordinatorSetup(options) {
|
|
20019
20261
|
const { provider, meshId, workspace } = options;
|
|
20020
20262
|
const config = provider?.meshCoordinator;
|
|
@@ -20024,6 +20266,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20024
20266
|
reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
|
|
20025
20267
|
};
|
|
20026
20268
|
}
|
|
20269
|
+
if (isHermesProvider(provider, options.cliType)) {
|
|
20270
|
+
return resolveHermesMeshCoordinatorSetup(options);
|
|
20271
|
+
}
|
|
20027
20272
|
const mcpConfig = config.mcpConfig;
|
|
20028
20273
|
if (!mcpConfig || mcpConfig.mode === "none") {
|
|
20029
20274
|
return {
|
|
@@ -20033,8 +20278,8 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20033
20278
|
}
|
|
20034
20279
|
const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
|
|
20035
20280
|
if (mcpConfig.mode === "auto_import") {
|
|
20036
|
-
const
|
|
20037
|
-
if (!
|
|
20281
|
+
const path27 = mcpConfig.path?.trim();
|
|
20282
|
+
if (!path27) {
|
|
20038
20283
|
return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
|
|
20039
20284
|
}
|
|
20040
20285
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
@@ -20045,13 +20290,13 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20045
20290
|
if (!mcpServer) {
|
|
20046
20291
|
return {
|
|
20047
20292
|
kind: "unsupported",
|
|
20048
|
-
reason: "Could not resolve the ADHDev MCP server entrypoint
|
|
20293
|
+
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
20049
20294
|
};
|
|
20050
20295
|
}
|
|
20051
20296
|
return {
|
|
20052
20297
|
kind: "auto_import",
|
|
20053
20298
|
serverName,
|
|
20054
|
-
configPath: (
|
|
20299
|
+
configPath: resolveMcpConfigPath(path27, workspace),
|
|
20055
20300
|
configFormat: mcpConfig.format,
|
|
20056
20301
|
mcpServer
|
|
20057
20302
|
};
|
|
@@ -20085,14 +20330,85 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20085
20330
|
function renderMeshCoordinatorTemplate(template, values) {
|
|
20086
20331
|
return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
|
|
20087
20332
|
}
|
|
20333
|
+
function resolveMcpConfigPath(configPath, workspace) {
|
|
20334
|
+
const trimmed = configPath.trim();
|
|
20335
|
+
if (trimmed === "~") return os17.homedir();
|
|
20336
|
+
if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
|
|
20337
|
+
if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
|
|
20338
|
+
return (0, import_node_path.join)(workspace, trimmed);
|
|
20339
|
+
}
|
|
20088
20340
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
20089
20341
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
20090
20342
|
if (!entryPath) return null;
|
|
20343
|
+
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
20344
|
+
if (!nodeExecutable) return null;
|
|
20091
20345
|
return {
|
|
20092
|
-
command:
|
|
20093
|
-
args: [entryPath, "--repo-mesh", options.meshId]
|
|
20346
|
+
command: nodeExecutable,
|
|
20347
|
+
args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
|
|
20094
20348
|
};
|
|
20095
20349
|
}
|
|
20350
|
+
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
20351
|
+
const explicit = explicitExecutable?.trim();
|
|
20352
|
+
if (explicit) return explicit;
|
|
20353
|
+
const candidates = [];
|
|
20354
|
+
const addCandidate = (candidate) => {
|
|
20355
|
+
const trimmed = candidate?.trim();
|
|
20356
|
+
if (!trimmed) return;
|
|
20357
|
+
const normalized = normalizeExistingPath(trimmed) || trimmed;
|
|
20358
|
+
if (!candidates.includes(normalized)) candidates.push(normalized);
|
|
20359
|
+
};
|
|
20360
|
+
addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
|
|
20361
|
+
addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
|
|
20362
|
+
addCandidate(process.env.npm_node_execpath);
|
|
20363
|
+
addNodeCandidatesFromPath(process.env.PATH, addCandidate);
|
|
20364
|
+
addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
|
|
20365
|
+
addCandidate("/opt/homebrew/bin/node");
|
|
20366
|
+
addCandidate("/usr/local/bin/node");
|
|
20367
|
+
addCandidate("/usr/bin/node");
|
|
20368
|
+
addCandidate(process.execPath);
|
|
20369
|
+
for (const candidate of candidates) {
|
|
20370
|
+
if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
|
|
20371
|
+
}
|
|
20372
|
+
return null;
|
|
20373
|
+
}
|
|
20374
|
+
function addNodeCandidatesFromPath(pathValue, addCandidate) {
|
|
20375
|
+
for (const entry of (pathValue || "").split(":")) {
|
|
20376
|
+
const dir = entry.trim();
|
|
20377
|
+
if (!dir) continue;
|
|
20378
|
+
addCandidate((0, import_node_path.join)(dir, "node"));
|
|
20379
|
+
}
|
|
20380
|
+
}
|
|
20381
|
+
function addNodeCandidatesFromNvm(homeDir, addCandidate) {
|
|
20382
|
+
const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
|
|
20383
|
+
try {
|
|
20384
|
+
const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
|
|
20385
|
+
for (const versionDir of versionDirs) {
|
|
20386
|
+
addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
|
|
20387
|
+
}
|
|
20388
|
+
} catch {
|
|
20389
|
+
}
|
|
20390
|
+
}
|
|
20391
|
+
function compareNodeVersionNamesDescending(a, b) {
|
|
20392
|
+
const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
20393
|
+
const left = parse(a);
|
|
20394
|
+
const right = parse(b);
|
|
20395
|
+
for (let i = 0; i < Math.max(left.length, right.length); i++) {
|
|
20396
|
+
const diff = (right[i] || 0) - (left[i] || 0);
|
|
20397
|
+
if (diff !== 0) return diff;
|
|
20398
|
+
}
|
|
20399
|
+
return b.localeCompare(a);
|
|
20400
|
+
}
|
|
20401
|
+
function nodeRuntimeSupportsWebSocket(nodeExecutable) {
|
|
20402
|
+
try {
|
|
20403
|
+
(0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
|
|
20404
|
+
stdio: "ignore",
|
|
20405
|
+
timeout: 3e3
|
|
20406
|
+
});
|
|
20407
|
+
return true;
|
|
20408
|
+
} catch {
|
|
20409
|
+
return false;
|
|
20410
|
+
}
|
|
20411
|
+
}
|
|
20096
20412
|
function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
20097
20413
|
const explicit = explicitPath?.trim();
|
|
20098
20414
|
if (explicit) return normalizeExistingPath(explicit) || explicit;
|
|
@@ -20128,15 +20444,15 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
20128
20444
|
}
|
|
20129
20445
|
function normalizeExistingPath(filePath) {
|
|
20130
20446
|
try {
|
|
20131
|
-
if (!(0,
|
|
20132
|
-
return
|
|
20447
|
+
if (!(0, import_node_fs3.existsSync)(filePath)) return null;
|
|
20448
|
+
return import_node_fs3.realpathSync.native(filePath);
|
|
20133
20449
|
} catch {
|
|
20134
20450
|
return null;
|
|
20135
20451
|
}
|
|
20136
20452
|
}
|
|
20137
20453
|
|
|
20138
20454
|
// src/status/snapshot.ts
|
|
20139
|
-
var
|
|
20455
|
+
var os18 = __toESM(require("os"));
|
|
20140
20456
|
init_config();
|
|
20141
20457
|
init_terminal_screen();
|
|
20142
20458
|
init_logger();
|
|
@@ -20192,8 +20508,8 @@ function buildAvailableProviders(providerLoader) {
|
|
|
20192
20508
|
}
|
|
20193
20509
|
function buildMachineInfo(profile = "full") {
|
|
20194
20510
|
const base = {
|
|
20195
|
-
hostname:
|
|
20196
|
-
platform:
|
|
20511
|
+
hostname: os18.hostname(),
|
|
20512
|
+
platform: os18.platform()
|
|
20197
20513
|
};
|
|
20198
20514
|
if (profile === "live") {
|
|
20199
20515
|
return base;
|
|
@@ -20202,23 +20518,23 @@ function buildMachineInfo(profile = "full") {
|
|
|
20202
20518
|
const memSnap2 = getHostMemorySnapshot();
|
|
20203
20519
|
return {
|
|
20204
20520
|
...base,
|
|
20205
|
-
arch:
|
|
20206
|
-
cpus:
|
|
20521
|
+
arch: os18.arch(),
|
|
20522
|
+
cpus: os18.cpus().length,
|
|
20207
20523
|
totalMem: memSnap2.totalMem,
|
|
20208
|
-
release:
|
|
20524
|
+
release: os18.release()
|
|
20209
20525
|
};
|
|
20210
20526
|
}
|
|
20211
20527
|
const memSnap = getHostMemorySnapshot();
|
|
20212
20528
|
return {
|
|
20213
20529
|
...base,
|
|
20214
|
-
arch:
|
|
20215
|
-
cpus:
|
|
20530
|
+
arch: os18.arch(),
|
|
20531
|
+
cpus: os18.cpus().length,
|
|
20216
20532
|
totalMem: memSnap.totalMem,
|
|
20217
20533
|
freeMem: memSnap.freeMem,
|
|
20218
20534
|
availableMem: memSnap.availableMem,
|
|
20219
|
-
loadavg:
|
|
20220
|
-
uptime:
|
|
20221
|
-
release:
|
|
20535
|
+
loadavg: os18.loadavg(),
|
|
20536
|
+
uptime: os18.uptime(),
|
|
20537
|
+
release: os18.release()
|
|
20222
20538
|
};
|
|
20223
20539
|
}
|
|
20224
20540
|
function parseMessageTime(value) {
|
|
@@ -20452,14 +20768,14 @@ function buildStatusSnapshot(options) {
|
|
|
20452
20768
|
var import_child_process8 = require("child_process");
|
|
20453
20769
|
var import_child_process9 = require("child_process");
|
|
20454
20770
|
var fs9 = __toESM(require("fs"));
|
|
20455
|
-
var
|
|
20456
|
-
var
|
|
20771
|
+
var os19 = __toESM(require("os"));
|
|
20772
|
+
var path21 = __toESM(require("path"));
|
|
20457
20773
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
20458
20774
|
function getUpgradeLogPath() {
|
|
20459
|
-
const home =
|
|
20460
|
-
const dir =
|
|
20775
|
+
const home = os19.homedir();
|
|
20776
|
+
const dir = path21.join(home, ".adhdev");
|
|
20461
20777
|
fs9.mkdirSync(dir, { recursive: true });
|
|
20462
|
-
return
|
|
20778
|
+
return path21.join(dir, "daemon-upgrade.log");
|
|
20463
20779
|
}
|
|
20464
20780
|
function appendUpgradeLog(message) {
|
|
20465
20781
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -20470,14 +20786,14 @@ function appendUpgradeLog(message) {
|
|
|
20470
20786
|
}
|
|
20471
20787
|
}
|
|
20472
20788
|
function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
|
|
20473
|
-
const binDir =
|
|
20789
|
+
const binDir = path21.dirname(nodeExecutable);
|
|
20474
20790
|
if (platform10 === "win32") {
|
|
20475
|
-
const npmCliPath =
|
|
20791
|
+
const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
20476
20792
|
if (fs9.existsSync(npmCliPath)) {
|
|
20477
20793
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20478
20794
|
}
|
|
20479
20795
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
20480
|
-
const candidatePath =
|
|
20796
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20481
20797
|
if (fs9.existsSync(candidatePath)) {
|
|
20482
20798
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20483
20799
|
}
|
|
@@ -20485,7 +20801,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
20485
20801
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20486
20802
|
}
|
|
20487
20803
|
for (const candidate of ["npm"]) {
|
|
20488
|
-
const candidatePath =
|
|
20804
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20489
20805
|
if (fs9.existsSync(candidatePath)) {
|
|
20490
20806
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20491
20807
|
}
|
|
@@ -20502,13 +20818,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20502
20818
|
let currentDir = resolvedPath;
|
|
20503
20819
|
try {
|
|
20504
20820
|
if (fs9.statSync(resolvedPath).isFile()) {
|
|
20505
|
-
currentDir =
|
|
20821
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20506
20822
|
}
|
|
20507
20823
|
} catch {
|
|
20508
|
-
currentDir =
|
|
20824
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20509
20825
|
}
|
|
20510
20826
|
while (true) {
|
|
20511
|
-
const packageJsonPath =
|
|
20827
|
+
const packageJsonPath = path21.join(currentDir, "package.json");
|
|
20512
20828
|
try {
|
|
20513
20829
|
if (fs9.existsSync(packageJsonPath)) {
|
|
20514
20830
|
const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -20519,7 +20835,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20519
20835
|
}
|
|
20520
20836
|
} catch {
|
|
20521
20837
|
}
|
|
20522
|
-
const parentDir =
|
|
20838
|
+
const parentDir = path21.dirname(currentDir);
|
|
20523
20839
|
if (parentDir === currentDir) {
|
|
20524
20840
|
return null;
|
|
20525
20841
|
}
|
|
@@ -20527,13 +20843,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20527
20843
|
}
|
|
20528
20844
|
}
|
|
20529
20845
|
function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
|
|
20530
|
-
const nodeModulesDir = packageName.startsWith("@") ?
|
|
20531
|
-
if (
|
|
20846
|
+
const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
|
|
20847
|
+
if (path21.basename(nodeModulesDir) !== "node_modules") {
|
|
20532
20848
|
return null;
|
|
20533
20849
|
}
|
|
20534
|
-
const maybeLibDir =
|
|
20535
|
-
if (
|
|
20536
|
-
return
|
|
20850
|
+
const maybeLibDir = path21.dirname(nodeModulesDir);
|
|
20851
|
+
if (path21.basename(maybeLibDir) === "lib") {
|
|
20852
|
+
return path21.dirname(maybeLibDir);
|
|
20537
20853
|
}
|
|
20538
20854
|
return maybeLibDir;
|
|
20539
20855
|
}
|
|
@@ -20648,7 +20964,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
20648
20964
|
}
|
|
20649
20965
|
}
|
|
20650
20966
|
function stopSessionHostProcesses(appName) {
|
|
20651
|
-
const pidFile =
|
|
20967
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
20652
20968
|
try {
|
|
20653
20969
|
if (fs9.existsSync(pidFile)) {
|
|
20654
20970
|
const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -20665,7 +20981,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
20665
20981
|
}
|
|
20666
20982
|
}
|
|
20667
20983
|
function removeDaemonPidFile() {
|
|
20668
|
-
const pidFile =
|
|
20984
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
|
|
20669
20985
|
try {
|
|
20670
20986
|
fs9.unlinkSync(pidFile);
|
|
20671
20987
|
} catch {
|
|
@@ -20676,7 +20992,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20676
20992
|
const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20677
20993
|
if (!npmRoot) return;
|
|
20678
20994
|
const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20679
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
20995
|
+
const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
|
|
20680
20996
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
20681
20997
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
20682
20998
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -20684,25 +21000,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20684
21000
|
}
|
|
20685
21001
|
if (pkgName.startsWith("@")) {
|
|
20686
21002
|
const [scope, name] = pkgName.split("/");
|
|
20687
|
-
const scopeDir =
|
|
21003
|
+
const scopeDir = path21.join(npmRoot, scope);
|
|
20688
21004
|
if (!fs9.existsSync(scopeDir)) return;
|
|
20689
21005
|
for (const entry of fs9.readdirSync(scopeDir)) {
|
|
20690
21006
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
20691
|
-
fs9.rmSync(
|
|
20692
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
21007
|
+
fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
|
|
21008
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
|
|
20693
21009
|
}
|
|
20694
21010
|
} else {
|
|
20695
21011
|
for (const entry of fs9.readdirSync(npmRoot)) {
|
|
20696
21012
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
20697
|
-
fs9.rmSync(
|
|
20698
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
21013
|
+
fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
|
|
21014
|
+
appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
|
|
20699
21015
|
}
|
|
20700
21016
|
}
|
|
20701
21017
|
if (fs9.existsSync(binDir)) {
|
|
20702
21018
|
for (const entry of fs9.readdirSync(binDir)) {
|
|
20703
21019
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
20704
|
-
fs9.rmSync(
|
|
20705
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
21020
|
+
fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
|
|
21021
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
|
|
20706
21022
|
}
|
|
20707
21023
|
}
|
|
20708
21024
|
}
|
|
@@ -20789,6 +21105,10 @@ async function maybeRunDaemonUpgradeHelperFromEnv() {
|
|
|
20789
21105
|
// src/commands/router.ts
|
|
20790
21106
|
var fs10 = __toESM(require("fs"));
|
|
20791
21107
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
21108
|
+
var CHANNEL_SERVER_URL = {
|
|
21109
|
+
stable: "https://api.adhf.dev",
|
|
21110
|
+
preview: "https://api-preview.adhf.dev"
|
|
21111
|
+
};
|
|
20792
21112
|
function normalizeReleaseChannel(value) {
|
|
20793
21113
|
if (typeof value !== "string") return null;
|
|
20794
21114
|
const normalized = value.trim().toLowerCase();
|
|
@@ -20799,6 +21119,22 @@ function normalizeReleaseChannel(value) {
|
|
|
20799
21119
|
function resolveUpgradeChannel(args) {
|
|
20800
21120
|
return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
|
|
20801
21121
|
}
|
|
21122
|
+
function loadYamlModule() {
|
|
21123
|
+
return yaml;
|
|
21124
|
+
}
|
|
21125
|
+
function getMcpServersKey(format) {
|
|
21126
|
+
return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
|
|
21127
|
+
}
|
|
21128
|
+
function parseMeshCoordinatorMcpConfig(text, format) {
|
|
21129
|
+
if (!text.trim()) return {};
|
|
21130
|
+
if (format === "claude_mcp_json") return JSON.parse(text);
|
|
21131
|
+
const parsed = loadYamlModule().load(text);
|
|
21132
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
21133
|
+
}
|
|
21134
|
+
function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
21135
|
+
if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
|
|
21136
|
+
return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
|
|
21137
|
+
}
|
|
20802
21138
|
var CHAT_COMMANDS = [
|
|
20803
21139
|
"send_chat",
|
|
20804
21140
|
"new_chat",
|
|
@@ -20897,6 +21233,40 @@ var DaemonCommandRouter = class {
|
|
|
20897
21233
|
constructor(deps) {
|
|
20898
21234
|
this.deps = deps;
|
|
20899
21235
|
}
|
|
21236
|
+
getCachedInlineMesh(meshId, inlineMesh) {
|
|
21237
|
+
if (inlineMesh && typeof inlineMesh === "object") {
|
|
21238
|
+
this.inlineMeshCache.set(meshId, inlineMesh);
|
|
21239
|
+
return inlineMesh;
|
|
21240
|
+
}
|
|
21241
|
+
return this.inlineMeshCache.get(meshId);
|
|
21242
|
+
}
|
|
21243
|
+
async getMeshForCommand(meshId, inlineMesh) {
|
|
21244
|
+
try {
|
|
21245
|
+
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21246
|
+
const mesh = getMesh3(meshId);
|
|
21247
|
+
if (mesh) return { mesh, inline: false };
|
|
21248
|
+
} catch {
|
|
21249
|
+
}
|
|
21250
|
+
const cached = this.getCachedInlineMesh(meshId, inlineMesh);
|
|
21251
|
+
return cached ? { mesh: cached, inline: true } : null;
|
|
21252
|
+
}
|
|
21253
|
+
updateInlineMeshNode(meshId, mesh, node) {
|
|
21254
|
+
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
21255
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
|
|
21256
|
+
if (idx >= 0) mesh.nodes[idx] = node;
|
|
21257
|
+
else mesh.nodes.push(node);
|
|
21258
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21259
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21260
|
+
}
|
|
21261
|
+
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
21262
|
+
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
21263
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
|
|
21264
|
+
if (idx === -1) return false;
|
|
21265
|
+
mesh.nodes.splice(idx, 1);
|
|
21266
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21267
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21268
|
+
return true;
|
|
21269
|
+
}
|
|
20900
21270
|
async traceSessionHostAction(action, args, run, summarizeResult) {
|
|
20901
21271
|
const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
|
|
20902
21272
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
|
|
@@ -21485,6 +21855,7 @@ var DaemonCommandRouter = class {
|
|
|
21485
21855
|
const npmTag = CHANNEL_NPM_TAG[channel];
|
|
21486
21856
|
const latest = String(execNpmCommandSync(["view", `${pkgName}@${npmTag}`, "version"], { encoding: "utf-8", timeout: 1e4 }, npmSurface)).trim();
|
|
21487
21857
|
LOG.info("Upgrade", `Latest ${pkgName}@${npmTag}: v${latest}`);
|
|
21858
|
+
updateConfig({ updateChannel: channel, serverUrl: CHANNEL_SERVER_URL[channel] });
|
|
21488
21859
|
let currentInstalled = null;
|
|
21489
21860
|
try {
|
|
21490
21861
|
const currentJson = String(execNpmCommandSync(["ls", "-g", pkgName, "--depth=0", "--json"], {
|
|
@@ -21595,13 +21966,94 @@ var DaemonCommandRouter = class {
|
|
|
21595
21966
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
21596
21967
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
21597
21968
|
try {
|
|
21598
|
-
const
|
|
21599
|
-
const
|
|
21969
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
21970
|
+
const mesh = meshRecord?.mesh;
|
|
21971
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
21972
|
+
if (node?.isLocalWorktree && node.workspace) {
|
|
21973
|
+
try {
|
|
21974
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
21975
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
21976
|
+
if (repoRoot) {
|
|
21977
|
+
const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
21978
|
+
await removeWorktree2(repoRoot, node.workspace);
|
|
21979
|
+
}
|
|
21980
|
+
} catch (e) {
|
|
21981
|
+
LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
|
|
21982
|
+
}
|
|
21983
|
+
}
|
|
21984
|
+
let removed = false;
|
|
21985
|
+
if (meshRecord?.inline) {
|
|
21986
|
+
removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
|
|
21987
|
+
} else {
|
|
21988
|
+
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21989
|
+
removed = removeNode3(meshId, nodeId);
|
|
21990
|
+
}
|
|
21600
21991
|
return { success: true, removed };
|
|
21601
21992
|
} catch (e) {
|
|
21602
21993
|
return { success: false, error: e.message };
|
|
21603
21994
|
}
|
|
21604
21995
|
}
|
|
21996
|
+
case "clone_mesh_node": {
|
|
21997
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
21998
|
+
const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
|
|
21999
|
+
const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
|
|
22000
|
+
const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
|
|
22001
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
22002
|
+
if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
|
|
22003
|
+
if (!branch) return { success: false, error: "branch required" };
|
|
22004
|
+
try {
|
|
22005
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22006
|
+
const mesh = meshRecord?.mesh;
|
|
22007
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22008
|
+
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
22009
|
+
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
22010
|
+
const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
|
|
22011
|
+
const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
22012
|
+
const result = await createWorktree2({
|
|
22013
|
+
repoRoot,
|
|
22014
|
+
branch,
|
|
22015
|
+
baseBranch,
|
|
22016
|
+
meshName: mesh.name
|
|
22017
|
+
});
|
|
22018
|
+
let node;
|
|
22019
|
+
if (meshRecord.inline) {
|
|
22020
|
+
const { randomUUID: randomUUID8 } = await import("crypto");
|
|
22021
|
+
node = {
|
|
22022
|
+
id: `node_${randomUUID8().replace(/-/g, "")}`,
|
|
22023
|
+
workspace: result.worktreePath,
|
|
22024
|
+
repoRoot: result.worktreePath,
|
|
22025
|
+
daemonId: sourceNode.daemonId,
|
|
22026
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
22027
|
+
policy: { ...sourceNode.policy || {} },
|
|
22028
|
+
isLocalWorktree: true,
|
|
22029
|
+
worktreeBranch: result.branch,
|
|
22030
|
+
clonedFromNodeId: sourceNodeId
|
|
22031
|
+
};
|
|
22032
|
+
this.updateInlineMeshNode(meshId, mesh, node);
|
|
22033
|
+
} else {
|
|
22034
|
+
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22035
|
+
node = addNode3(meshId, {
|
|
22036
|
+
workspace: result.worktreePath,
|
|
22037
|
+
repoRoot: result.worktreePath,
|
|
22038
|
+
daemonId: sourceNode.daemonId,
|
|
22039
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
22040
|
+
isLocalWorktree: true,
|
|
22041
|
+
worktreeBranch: result.branch,
|
|
22042
|
+
clonedFromNodeId: sourceNodeId,
|
|
22043
|
+
policy: { ...sourceNode.policy || {} }
|
|
22044
|
+
});
|
|
22045
|
+
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
22046
|
+
}
|
|
22047
|
+
return {
|
|
22048
|
+
success: true,
|
|
22049
|
+
node,
|
|
22050
|
+
worktreePath: result.worktreePath,
|
|
22051
|
+
branch: result.branch
|
|
22052
|
+
};
|
|
22053
|
+
} catch (e) {
|
|
22054
|
+
return { success: false, error: e.message };
|
|
22055
|
+
}
|
|
22056
|
+
}
|
|
21605
22057
|
// ─── Mesh Coordinator Launch ───
|
|
21606
22058
|
case "launch_mesh_coordinator": {
|
|
21607
22059
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -21636,6 +22088,7 @@ var DaemonCommandRouter = class {
|
|
|
21636
22088
|
const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
|
|
21637
22089
|
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
21638
22090
|
provider: providerMeta,
|
|
22091
|
+
cliType,
|
|
21639
22092
|
meshId,
|
|
21640
22093
|
workspace
|
|
21641
22094
|
});
|
|
@@ -21660,7 +22113,8 @@ var DaemonCommandRouter = class {
|
|
|
21660
22113
|
meshCoordinatorSetup: coordinatorSetup
|
|
21661
22114
|
};
|
|
21662
22115
|
}
|
|
21663
|
-
|
|
22116
|
+
const configFormat = coordinatorSetup.configFormat;
|
|
22117
|
+
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
21664
22118
|
return {
|
|
21665
22119
|
success: false,
|
|
21666
22120
|
code: "mesh_coordinator_unsupported",
|
|
@@ -21670,44 +22124,93 @@ var DaemonCommandRouter = class {
|
|
|
21670
22124
|
workspace
|
|
21671
22125
|
};
|
|
21672
22126
|
}
|
|
21673
|
-
|
|
21674
|
-
|
|
21675
|
-
|
|
21676
|
-
|
|
21677
|
-
|
|
21678
|
-
|
|
21679
|
-
|
|
21680
|
-
|
|
21681
|
-
|
|
21682
|
-
|
|
22127
|
+
let systemPrompt = "";
|
|
22128
|
+
try {
|
|
22129
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
22130
|
+
} catch (error) {
|
|
22131
|
+
const message = error?.message || String(error);
|
|
22132
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
22133
|
+
return {
|
|
22134
|
+
success: false,
|
|
22135
|
+
code: "mesh_coordinator_prompt_failed",
|
|
22136
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
22137
|
+
meshId,
|
|
22138
|
+
cliType,
|
|
22139
|
+
workspace
|
|
22140
|
+
};
|
|
21683
22141
|
}
|
|
22142
|
+
const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3, mkdirSync: mkdirSync14 } = await import("fs");
|
|
22143
|
+
const { dirname: dirname9 } = await import("path");
|
|
22144
|
+
const mcpConfigPath = coordinatorSetup.configPath;
|
|
22145
|
+
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
22146
|
+
const returnManualFallback = (message) => ({
|
|
22147
|
+
success: false,
|
|
22148
|
+
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
22149
|
+
error: message,
|
|
22150
|
+
meshId,
|
|
22151
|
+
cliType,
|
|
22152
|
+
workspace,
|
|
22153
|
+
meshCoordinatorSetup: hermesManualFallback
|
|
22154
|
+
});
|
|
21684
22155
|
const mcpServerEntry = {
|
|
21685
22156
|
command: coordinatorSetup.mcpServer.command,
|
|
21686
22157
|
args: coordinatorSetup.mcpServer.args
|
|
21687
22158
|
};
|
|
21688
22159
|
if (args?.inlineMesh) {
|
|
21689
22160
|
mcpServerEntry.env = {
|
|
21690
|
-
ADHDEV_INLINE_MESH: JSON.stringify(mesh)
|
|
22161
|
+
ADHDEV_INLINE_MESH: JSON.stringify(mesh),
|
|
22162
|
+
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
21691
22163
|
};
|
|
21692
22164
|
}
|
|
22165
|
+
try {
|
|
22166
|
+
mkdirSync14(dirname9(mcpConfigPath), { recursive: true });
|
|
22167
|
+
} catch (error) {
|
|
22168
|
+
const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
|
|
22169
|
+
LOG.error("MeshCoordinator", message);
|
|
22170
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
22171
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
22172
|
+
}
|
|
22173
|
+
const hadExistingMcpConfig = existsSync23(mcpConfigPath);
|
|
22174
|
+
let existingMcpConfig = {};
|
|
22175
|
+
if (hadExistingMcpConfig) {
|
|
22176
|
+
try {
|
|
22177
|
+
existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
|
|
22178
|
+
copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
|
|
22179
|
+
} catch (error) {
|
|
22180
|
+
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
22181
|
+
return {
|
|
22182
|
+
success: false,
|
|
22183
|
+
code: "mesh_coordinator_config_parse_failed",
|
|
22184
|
+
error: `Failed to parse existing MCP config at ${mcpConfigPath}`
|
|
22185
|
+
};
|
|
22186
|
+
}
|
|
22187
|
+
}
|
|
22188
|
+
const mcpServersKey = getMcpServersKey(configFormat);
|
|
22189
|
+
const existingServers = existingMcpConfig[mcpServersKey];
|
|
21693
22190
|
const mcpConfig = {
|
|
21694
22191
|
...existingMcpConfig,
|
|
21695
|
-
|
|
21696
|
-
...
|
|
22192
|
+
[mcpServersKey]: {
|
|
22193
|
+
...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
|
|
21697
22194
|
[coordinatorSetup.serverName]: mcpServerEntry
|
|
21698
22195
|
}
|
|
21699
22196
|
};
|
|
21700
|
-
writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
21701
|
-
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21702
|
-
let systemPrompt = "";
|
|
21703
22197
|
try {
|
|
21704
|
-
|
|
21705
|
-
} catch {
|
|
21706
|
-
|
|
22198
|
+
writeFileSync12(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
22199
|
+
} catch (error) {
|
|
22200
|
+
const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
|
|
22201
|
+
LOG.error("MeshCoordinator", message);
|
|
22202
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
22203
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
21707
22204
|
}
|
|
22205
|
+
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21708
22206
|
const cliArgs = [];
|
|
22207
|
+
const launchEnv = {};
|
|
21709
22208
|
if (systemPrompt) {
|
|
21710
|
-
|
|
22209
|
+
if (configFormat === "hermes_config_yaml") {
|
|
22210
|
+
launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
|
|
22211
|
+
} else {
|
|
22212
|
+
cliArgs.push("--append-system-prompt", systemPrompt);
|
|
22213
|
+
}
|
|
21711
22214
|
}
|
|
21712
22215
|
if (cliType === "claude-cli") {
|
|
21713
22216
|
cliArgs.push("--mcp-config", coordinatorSetup.configPath);
|
|
@@ -21716,6 +22219,7 @@ var DaemonCommandRouter = class {
|
|
|
21716
22219
|
cliType,
|
|
21717
22220
|
dir: workspace,
|
|
21718
22221
|
cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
|
|
22222
|
+
env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
|
|
21719
22223
|
settings: {
|
|
21720
22224
|
meshCoordinatorFor: meshId
|
|
21721
22225
|
}
|
|
@@ -23376,11 +23880,11 @@ var ProviderInstanceManager = class {
|
|
|
23376
23880
|
|
|
23377
23881
|
// src/providers/version-archive.ts
|
|
23378
23882
|
var fs11 = __toESM(require("fs"));
|
|
23379
|
-
var
|
|
23380
|
-
var
|
|
23883
|
+
var path22 = __toESM(require("path"));
|
|
23884
|
+
var os20 = __toESM(require("os"));
|
|
23381
23885
|
var import_child_process10 = require("child_process");
|
|
23382
23886
|
var import_os3 = require("os");
|
|
23383
|
-
var ARCHIVE_PATH =
|
|
23887
|
+
var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
|
|
23384
23888
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
23385
23889
|
var VersionArchive = class {
|
|
23386
23890
|
history = {};
|
|
@@ -23427,7 +23931,7 @@ var VersionArchive = class {
|
|
|
23427
23931
|
}
|
|
23428
23932
|
save() {
|
|
23429
23933
|
try {
|
|
23430
|
-
fs11.mkdirSync(
|
|
23934
|
+
fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
|
|
23431
23935
|
fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
23432
23936
|
} catch {
|
|
23433
23937
|
}
|
|
@@ -23483,8 +23987,8 @@ function getVersion(binary, versionCommand) {
|
|
|
23483
23987
|
function checkPathExists2(paths) {
|
|
23484
23988
|
for (const p of paths) {
|
|
23485
23989
|
if (p.includes("*")) {
|
|
23486
|
-
const home =
|
|
23487
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
23990
|
+
const home = os20.homedir();
|
|
23991
|
+
const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
|
|
23488
23992
|
if (fs11.existsSync(resolved)) return resolved;
|
|
23489
23993
|
} else {
|
|
23490
23994
|
if (fs11.existsSync(p)) return p;
|
|
@@ -23494,7 +23998,7 @@ function checkPathExists2(paths) {
|
|
|
23494
23998
|
}
|
|
23495
23999
|
function getMacAppVersion(appPath) {
|
|
23496
24000
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
23497
|
-
const plistPath =
|
|
24001
|
+
const plistPath = path22.join(appPath, "Contents", "Info.plist");
|
|
23498
24002
|
if (!fs11.existsSync(plistPath)) return null;
|
|
23499
24003
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
23500
24004
|
return raw || null;
|
|
@@ -23520,7 +24024,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23520
24024
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
23521
24025
|
let resolvedBin = cliBin;
|
|
23522
24026
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
23523
|
-
const bundled =
|
|
24027
|
+
const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
23524
24028
|
if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
|
|
23525
24029
|
}
|
|
23526
24030
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -23561,7 +24065,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23561
24065
|
// src/daemon/dev-server.ts
|
|
23562
24066
|
var http2 = __toESM(require("http"));
|
|
23563
24067
|
var fs15 = __toESM(require("fs"));
|
|
23564
|
-
var
|
|
24068
|
+
var path26 = __toESM(require("path"));
|
|
23565
24069
|
init_config();
|
|
23566
24070
|
|
|
23567
24071
|
// src/daemon/scaffold-template.ts
|
|
@@ -23912,7 +24416,7 @@ init_logger();
|
|
|
23912
24416
|
|
|
23913
24417
|
// src/daemon/dev-cdp-handlers.ts
|
|
23914
24418
|
var fs12 = __toESM(require("fs"));
|
|
23915
|
-
var
|
|
24419
|
+
var path23 = __toESM(require("path"));
|
|
23916
24420
|
init_logger();
|
|
23917
24421
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
23918
24422
|
const body = await ctx.readBody(req);
|
|
@@ -24091,17 +24595,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
24091
24595
|
return;
|
|
24092
24596
|
}
|
|
24093
24597
|
let scriptsPath = "";
|
|
24094
|
-
const directScripts =
|
|
24598
|
+
const directScripts = path23.join(dir, "scripts.js");
|
|
24095
24599
|
if (fs12.existsSync(directScripts)) {
|
|
24096
24600
|
scriptsPath = directScripts;
|
|
24097
24601
|
} else {
|
|
24098
|
-
const scriptsDir =
|
|
24602
|
+
const scriptsDir = path23.join(dir, "scripts");
|
|
24099
24603
|
if (fs12.existsSync(scriptsDir)) {
|
|
24100
24604
|
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
24101
|
-
return fs12.statSync(
|
|
24605
|
+
return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
|
|
24102
24606
|
}).sort().reverse();
|
|
24103
24607
|
for (const ver of versions) {
|
|
24104
|
-
const p =
|
|
24608
|
+
const p = path23.join(scriptsDir, ver, "scripts.js");
|
|
24105
24609
|
if (fs12.existsSync(p)) {
|
|
24106
24610
|
scriptsPath = p;
|
|
24107
24611
|
break;
|
|
@@ -24930,7 +25434,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
24930
25434
|
|
|
24931
25435
|
// src/daemon/dev-cli-debug.ts
|
|
24932
25436
|
var fs13 = __toESM(require("fs"));
|
|
24933
|
-
var
|
|
25437
|
+
var path24 = __toESM(require("path"));
|
|
24934
25438
|
function slugifyFixtureName(value) {
|
|
24935
25439
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
24936
25440
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -24940,11 +25444,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
24940
25444
|
if (!providerDir) {
|
|
24941
25445
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
24942
25446
|
}
|
|
24943
|
-
return
|
|
25447
|
+
return path24.join(providerDir, "fixtures");
|
|
24944
25448
|
}
|
|
24945
25449
|
function readCliFixture(ctx, type, name) {
|
|
24946
25450
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
24947
|
-
const filePath =
|
|
25451
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
24948
25452
|
if (!fs13.existsSync(filePath)) {
|
|
24949
25453
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
24950
25454
|
}
|
|
@@ -25711,7 +26215,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
25711
26215
|
},
|
|
25712
26216
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
25713
26217
|
};
|
|
25714
|
-
const filePath =
|
|
26218
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
25715
26219
|
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
25716
26220
|
ctx.json(res, 200, {
|
|
25717
26221
|
saved: true,
|
|
@@ -25735,7 +26239,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
25735
26239
|
return;
|
|
25736
26240
|
}
|
|
25737
26241
|
const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
25738
|
-
const fullPath =
|
|
26242
|
+
const fullPath = path24.join(fixtureDir, file);
|
|
25739
26243
|
try {
|
|
25740
26244
|
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
25741
26245
|
return {
|
|
@@ -25871,8 +26375,8 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
25871
26375
|
|
|
25872
26376
|
// src/daemon/dev-auto-implement.ts
|
|
25873
26377
|
var fs14 = __toESM(require("fs"));
|
|
25874
|
-
var
|
|
25875
|
-
var
|
|
26378
|
+
var path25 = __toESM(require("path"));
|
|
26379
|
+
var os21 = __toESM(require("os"));
|
|
25876
26380
|
function getAutoImplPid(ctx) {
|
|
25877
26381
|
const pid = ctx.autoImplProcess?.pid;
|
|
25878
26382
|
return typeof pid === "number" && pid > 0 ? pid : null;
|
|
@@ -25921,22 +26425,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
25921
26425
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
25922
26426
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
25923
26427
|
try {
|
|
25924
|
-
return fs14.statSync(
|
|
26428
|
+
return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
|
|
25925
26429
|
} catch {
|
|
25926
26430
|
return false;
|
|
25927
26431
|
}
|
|
25928
26432
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
25929
26433
|
if (versions.length === 0) return null;
|
|
25930
|
-
return
|
|
26434
|
+
return path25.join(scriptsDir, versions[0]);
|
|
25931
26435
|
}
|
|
25932
26436
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
25933
|
-
const canonicalUserDir =
|
|
25934
|
-
const desiredDir = requestedDir ?
|
|
25935
|
-
const upstreamRoot =
|
|
25936
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
26437
|
+
const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
26438
|
+
const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
|
|
26439
|
+
const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
|
|
26440
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
|
|
25937
26441
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
25938
26442
|
}
|
|
25939
|
-
if (
|
|
26443
|
+
if (path25.basename(desiredDir) !== type) {
|
|
25940
26444
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
25941
26445
|
}
|
|
25942
26446
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -25944,11 +26448,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
25944
26448
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
25945
26449
|
}
|
|
25946
26450
|
if (!fs14.existsSync(desiredDir)) {
|
|
25947
|
-
fs14.mkdirSync(
|
|
26451
|
+
fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
|
|
25948
26452
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
25949
26453
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
25950
26454
|
}
|
|
25951
|
-
const providerJson =
|
|
26455
|
+
const providerJson = path25.join(desiredDir, "provider.json");
|
|
25952
26456
|
if (!fs14.existsSync(providerJson)) {
|
|
25953
26457
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
25954
26458
|
}
|
|
@@ -25959,13 +26463,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
25959
26463
|
const refDir = ctx.findProviderDir(referenceType);
|
|
25960
26464
|
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
25961
26465
|
const referenceScripts = {};
|
|
25962
|
-
const scriptsDir =
|
|
26466
|
+
const scriptsDir = path25.join(refDir, "scripts");
|
|
25963
26467
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
25964
26468
|
if (!latestDir) return referenceScripts;
|
|
25965
26469
|
for (const file of fs14.readdirSync(latestDir)) {
|
|
25966
26470
|
if (!file.endsWith(".js")) continue;
|
|
25967
26471
|
try {
|
|
25968
|
-
referenceScripts[file] = fs14.readFileSync(
|
|
26472
|
+
referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
|
|
25969
26473
|
} catch {
|
|
25970
26474
|
}
|
|
25971
26475
|
}
|
|
@@ -26073,9 +26577,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26073
26577
|
});
|
|
26074
26578
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
26075
26579
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
26076
|
-
const tmpDir =
|
|
26580
|
+
const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
|
|
26077
26581
|
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
26078
|
-
const promptFile =
|
|
26582
|
+
const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
26079
26583
|
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
26080
26584
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
26081
26585
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -26228,7 +26732,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26228
26732
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
26229
26733
|
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
26230
26734
|
let shellCmd;
|
|
26231
|
-
const isWin =
|
|
26735
|
+
const isWin = os21.platform() === "win32";
|
|
26232
26736
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
26233
26737
|
const promptMode = autoImpl?.promptMode ?? "stdin";
|
|
26234
26738
|
const extraArgs = autoImpl?.extraArgs ?? [];
|
|
@@ -26267,7 +26771,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26267
26771
|
try {
|
|
26268
26772
|
const pty = require("node-pty");
|
|
26269
26773
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
26270
|
-
const isWin2 =
|
|
26774
|
+
const isWin2 = os21.platform() === "win32";
|
|
26271
26775
|
child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
26272
26776
|
name: "xterm-256color",
|
|
26273
26777
|
cols: 120,
|
|
@@ -26507,7 +27011,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26507
27011
|
setMode: "set_mode.js"
|
|
26508
27012
|
};
|
|
26509
27013
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26510
|
-
const scriptsDir =
|
|
27014
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26511
27015
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26512
27016
|
if (latestScriptsDir) {
|
|
26513
27017
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26518,7 +27022,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26518
27022
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
26519
27023
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
26520
27024
|
try {
|
|
26521
|
-
const content = fs14.readFileSync(
|
|
27025
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26522
27026
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26523
27027
|
lines.push("```javascript");
|
|
26524
27028
|
lines.push(content);
|
|
@@ -26535,7 +27039,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26535
27039
|
lines.push("");
|
|
26536
27040
|
for (const file of refFiles) {
|
|
26537
27041
|
try {
|
|
26538
|
-
const content = fs14.readFileSync(
|
|
27042
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26539
27043
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26540
27044
|
lines.push("```javascript");
|
|
26541
27045
|
lines.push(content);
|
|
@@ -26576,10 +27080,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26576
27080
|
lines.push("");
|
|
26577
27081
|
}
|
|
26578
27082
|
}
|
|
26579
|
-
const docsDir =
|
|
27083
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26580
27084
|
const loadGuide = (name) => {
|
|
26581
27085
|
try {
|
|
26582
|
-
const p =
|
|
27086
|
+
const p = path25.join(docsDir, name);
|
|
26583
27087
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26584
27088
|
} catch {
|
|
26585
27089
|
}
|
|
@@ -26816,7 +27320,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26816
27320
|
parseApproval: "parse_approval.js"
|
|
26817
27321
|
};
|
|
26818
27322
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26819
|
-
const scriptsDir =
|
|
27323
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26820
27324
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26821
27325
|
if (latestScriptsDir) {
|
|
26822
27326
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26828,7 +27332,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26828
27332
|
if (!file.endsWith(".js")) continue;
|
|
26829
27333
|
if (!targetFileNames.has(file)) continue;
|
|
26830
27334
|
try {
|
|
26831
|
-
const content = fs14.readFileSync(
|
|
27335
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26832
27336
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26833
27337
|
lines.push("```javascript");
|
|
26834
27338
|
lines.push(content);
|
|
@@ -26844,7 +27348,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26844
27348
|
lines.push("");
|
|
26845
27349
|
for (const file of refFiles) {
|
|
26846
27350
|
try {
|
|
26847
|
-
const content = fs14.readFileSync(
|
|
27351
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26848
27352
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26849
27353
|
lines.push("```javascript");
|
|
26850
27354
|
lines.push(content);
|
|
@@ -26877,10 +27381,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26877
27381
|
lines.push("");
|
|
26878
27382
|
}
|
|
26879
27383
|
}
|
|
26880
|
-
const docsDir =
|
|
27384
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26881
27385
|
const loadGuide = (name) => {
|
|
26882
27386
|
try {
|
|
26883
|
-
const p =
|
|
27387
|
+
const p = path25.join(docsDir, name);
|
|
26884
27388
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26885
27389
|
} catch {
|
|
26886
27390
|
}
|
|
@@ -27327,8 +27831,8 @@ var DevServer = class _DevServer {
|
|
|
27327
27831
|
}
|
|
27328
27832
|
getEndpointList() {
|
|
27329
27833
|
return this.routes.map((r) => {
|
|
27330
|
-
const
|
|
27331
|
-
return `${r.method.padEnd(5)} ${
|
|
27834
|
+
const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
27835
|
+
return `${r.method.padEnd(5)} ${path27}`;
|
|
27332
27836
|
});
|
|
27333
27837
|
}
|
|
27334
27838
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -27616,12 +28120,12 @@ var DevServer = class _DevServer {
|
|
|
27616
28120
|
// ─── DevConsole SPA ───
|
|
27617
28121
|
getConsoleDistDir() {
|
|
27618
28122
|
const candidates = [
|
|
27619
|
-
|
|
27620
|
-
|
|
27621
|
-
|
|
28123
|
+
path26.resolve(__dirname, "../../web-devconsole/dist"),
|
|
28124
|
+
path26.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
28125
|
+
path26.join(process.cwd(), "packages/web-devconsole/dist")
|
|
27622
28126
|
];
|
|
27623
28127
|
for (const dir of candidates) {
|
|
27624
|
-
if (fs15.existsSync(
|
|
28128
|
+
if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
|
|
27625
28129
|
}
|
|
27626
28130
|
return null;
|
|
27627
28131
|
}
|
|
@@ -27631,7 +28135,7 @@ var DevServer = class _DevServer {
|
|
|
27631
28135
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
27632
28136
|
return;
|
|
27633
28137
|
}
|
|
27634
|
-
const htmlPath =
|
|
28138
|
+
const htmlPath = path26.join(distDir, "index.html");
|
|
27635
28139
|
try {
|
|
27636
28140
|
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
27637
28141
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -27656,15 +28160,15 @@ var DevServer = class _DevServer {
|
|
|
27656
28160
|
this.json(res, 404, { error: "Not found" });
|
|
27657
28161
|
return;
|
|
27658
28162
|
}
|
|
27659
|
-
const safePath =
|
|
27660
|
-
const filePath =
|
|
28163
|
+
const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
|
|
28164
|
+
const filePath = path26.join(distDir, safePath);
|
|
27661
28165
|
if (!filePath.startsWith(distDir)) {
|
|
27662
28166
|
this.json(res, 403, { error: "Forbidden" });
|
|
27663
28167
|
return;
|
|
27664
28168
|
}
|
|
27665
28169
|
try {
|
|
27666
28170
|
const content = fs15.readFileSync(filePath);
|
|
27667
|
-
const ext =
|
|
28171
|
+
const ext = path26.extname(filePath);
|
|
27668
28172
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
27669
28173
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
27670
28174
|
res.end(content);
|
|
@@ -27777,9 +28281,9 @@ var DevServer = class _DevServer {
|
|
|
27777
28281
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
27778
28282
|
if (entry.isDirectory()) {
|
|
27779
28283
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
27780
|
-
scan(
|
|
28284
|
+
scan(path26.join(d, entry.name), rel);
|
|
27781
28285
|
} else {
|
|
27782
|
-
const stat2 = fs15.statSync(
|
|
28286
|
+
const stat2 = fs15.statSync(path26.join(d, entry.name));
|
|
27783
28287
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
27784
28288
|
}
|
|
27785
28289
|
}
|
|
@@ -27802,7 +28306,7 @@ var DevServer = class _DevServer {
|
|
|
27802
28306
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27803
28307
|
return;
|
|
27804
28308
|
}
|
|
27805
|
-
const fullPath =
|
|
28309
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27806
28310
|
if (!fullPath.startsWith(dir)) {
|
|
27807
28311
|
this.json(res, 403, { error: "Forbidden" });
|
|
27808
28312
|
return;
|
|
@@ -27827,14 +28331,14 @@ var DevServer = class _DevServer {
|
|
|
27827
28331
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27828
28332
|
return;
|
|
27829
28333
|
}
|
|
27830
|
-
const fullPath =
|
|
28334
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27831
28335
|
if (!fullPath.startsWith(dir)) {
|
|
27832
28336
|
this.json(res, 403, { error: "Forbidden" });
|
|
27833
28337
|
return;
|
|
27834
28338
|
}
|
|
27835
28339
|
try {
|
|
27836
28340
|
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
27837
|
-
fs15.mkdirSync(
|
|
28341
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27838
28342
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27839
28343
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
27840
28344
|
this.providerLoader.reload();
|
|
@@ -27851,7 +28355,7 @@ var DevServer = class _DevServer {
|
|
|
27851
28355
|
return;
|
|
27852
28356
|
}
|
|
27853
28357
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
27854
|
-
const p =
|
|
28358
|
+
const p = path26.join(dir, name);
|
|
27855
28359
|
if (fs15.existsSync(p)) {
|
|
27856
28360
|
const source = fs15.readFileSync(p, "utf-8");
|
|
27857
28361
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -27872,8 +28376,8 @@ var DevServer = class _DevServer {
|
|
|
27872
28376
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
27873
28377
|
return;
|
|
27874
28378
|
}
|
|
27875
|
-
const target = fs15.existsSync(
|
|
27876
|
-
const targetPath =
|
|
28379
|
+
const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
28380
|
+
const targetPath = path26.join(dir, target);
|
|
27877
28381
|
try {
|
|
27878
28382
|
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
27879
28383
|
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -28020,7 +28524,7 @@ var DevServer = class _DevServer {
|
|
|
28020
28524
|
}
|
|
28021
28525
|
let targetDir;
|
|
28022
28526
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
28023
|
-
const jsonPath =
|
|
28527
|
+
const jsonPath = path26.join(targetDir, "provider.json");
|
|
28024
28528
|
if (fs15.existsSync(jsonPath)) {
|
|
28025
28529
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
28026
28530
|
return;
|
|
@@ -28032,8 +28536,8 @@ var DevServer = class _DevServer {
|
|
|
28032
28536
|
const createdFiles = ["provider.json"];
|
|
28033
28537
|
if (result.files) {
|
|
28034
28538
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
28035
|
-
const fullPath =
|
|
28036
|
-
fs15.mkdirSync(
|
|
28539
|
+
const fullPath = path26.join(targetDir, relPath);
|
|
28540
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
28037
28541
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
28038
28542
|
createdFiles.push(relPath);
|
|
28039
28543
|
}
|
|
@@ -28086,22 +28590,22 @@ var DevServer = class _DevServer {
|
|
|
28086
28590
|
if (!fs15.existsSync(scriptsDir)) return null;
|
|
28087
28591
|
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
28088
28592
|
try {
|
|
28089
|
-
return fs15.statSync(
|
|
28593
|
+
return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
|
|
28090
28594
|
} catch {
|
|
28091
28595
|
return false;
|
|
28092
28596
|
}
|
|
28093
28597
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
28094
28598
|
if (versions.length === 0) return null;
|
|
28095
|
-
return
|
|
28599
|
+
return path26.join(scriptsDir, versions[0]);
|
|
28096
28600
|
}
|
|
28097
28601
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
28098
|
-
const canonicalUserDir =
|
|
28099
|
-
const desiredDir = requestedDir ?
|
|
28100
|
-
const upstreamRoot =
|
|
28101
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
28602
|
+
const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
28603
|
+
const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
|
|
28604
|
+
const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
|
|
28605
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
|
|
28102
28606
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
28103
28607
|
}
|
|
28104
|
-
if (
|
|
28608
|
+
if (path26.basename(desiredDir) !== type) {
|
|
28105
28609
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
28106
28610
|
}
|
|
28107
28611
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -28109,11 +28613,11 @@ var DevServer = class _DevServer {
|
|
|
28109
28613
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
28110
28614
|
}
|
|
28111
28615
|
if (!fs15.existsSync(desiredDir)) {
|
|
28112
|
-
fs15.mkdirSync(
|
|
28616
|
+
fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
|
|
28113
28617
|
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
28114
28618
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
28115
28619
|
}
|
|
28116
|
-
const providerJson =
|
|
28620
|
+
const providerJson = path26.join(desiredDir, "provider.json");
|
|
28117
28621
|
if (!fs15.existsSync(providerJson)) {
|
|
28118
28622
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
28119
28623
|
}
|
|
@@ -28149,7 +28653,7 @@ var DevServer = class _DevServer {
|
|
|
28149
28653
|
setMode: "set_mode.js"
|
|
28150
28654
|
};
|
|
28151
28655
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28152
|
-
const scriptsDir =
|
|
28656
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28153
28657
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28154
28658
|
if (latestScriptsDir) {
|
|
28155
28659
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28160,7 +28664,7 @@ var DevServer = class _DevServer {
|
|
|
28160
28664
|
for (const file of fs15.readdirSync(latestScriptsDir)) {
|
|
28161
28665
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
28162
28666
|
try {
|
|
28163
|
-
const content = fs15.readFileSync(
|
|
28667
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28164
28668
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28165
28669
|
lines.push("```javascript");
|
|
28166
28670
|
lines.push(content);
|
|
@@ -28177,7 +28681,7 @@ var DevServer = class _DevServer {
|
|
|
28177
28681
|
lines.push("");
|
|
28178
28682
|
for (const file of refFiles) {
|
|
28179
28683
|
try {
|
|
28180
|
-
const content = fs15.readFileSync(
|
|
28684
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28181
28685
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28182
28686
|
lines.push("```javascript");
|
|
28183
28687
|
lines.push(content);
|
|
@@ -28218,10 +28722,10 @@ var DevServer = class _DevServer {
|
|
|
28218
28722
|
lines.push("");
|
|
28219
28723
|
}
|
|
28220
28724
|
}
|
|
28221
|
-
const docsDir =
|
|
28725
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28222
28726
|
const loadGuide = (name) => {
|
|
28223
28727
|
try {
|
|
28224
|
-
const p =
|
|
28728
|
+
const p = path26.join(docsDir, name);
|
|
28225
28729
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28226
28730
|
} catch {
|
|
28227
28731
|
}
|
|
@@ -28395,7 +28899,7 @@ var DevServer = class _DevServer {
|
|
|
28395
28899
|
parseApproval: "parse_approval.js"
|
|
28396
28900
|
};
|
|
28397
28901
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28398
|
-
const scriptsDir =
|
|
28902
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28399
28903
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28400
28904
|
if (latestScriptsDir) {
|
|
28401
28905
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28407,7 +28911,7 @@ var DevServer = class _DevServer {
|
|
|
28407
28911
|
if (!file.endsWith(".js")) continue;
|
|
28408
28912
|
if (!targetFileNames.has(file)) continue;
|
|
28409
28913
|
try {
|
|
28410
|
-
const content = fs15.readFileSync(
|
|
28914
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28411
28915
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28412
28916
|
lines.push("```javascript");
|
|
28413
28917
|
lines.push(content);
|
|
@@ -28423,7 +28927,7 @@ var DevServer = class _DevServer {
|
|
|
28423
28927
|
lines.push("");
|
|
28424
28928
|
for (const file of refFiles) {
|
|
28425
28929
|
try {
|
|
28426
|
-
const content = fs15.readFileSync(
|
|
28930
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28427
28931
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28428
28932
|
lines.push("```javascript");
|
|
28429
28933
|
lines.push(content);
|
|
@@ -28456,10 +28960,10 @@ var DevServer = class _DevServer {
|
|
|
28456
28960
|
lines.push("");
|
|
28457
28961
|
}
|
|
28458
28962
|
}
|
|
28459
|
-
const docsDir =
|
|
28963
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28460
28964
|
const loadGuide = (name) => {
|
|
28461
28965
|
try {
|
|
28462
|
-
const p =
|
|
28966
|
+
const p = path26.join(docsDir, name);
|
|
28463
28967
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28464
28968
|
} catch {
|
|
28465
28969
|
}
|
|
@@ -29807,6 +30311,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29807
30311
|
createGitWorkspaceMonitor,
|
|
29808
30312
|
createInteractionId,
|
|
29809
30313
|
createMesh,
|
|
30314
|
+
createWorktree,
|
|
29810
30315
|
deleteMesh,
|
|
29811
30316
|
detectAllVersions,
|
|
29812
30317
|
detectCLIs,
|
|
@@ -29859,6 +30364,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29859
30364
|
launchWithCdp,
|
|
29860
30365
|
listHostedCliRuntimes,
|
|
29861
30366
|
listMeshes,
|
|
30367
|
+
listWorktrees,
|
|
29862
30368
|
loadConfig,
|
|
29863
30369
|
loadState,
|
|
29864
30370
|
logCommand,
|
|
@@ -29878,6 +30384,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29878
30384
|
normalizeSessionModalFields,
|
|
29879
30385
|
parsePorcelainV2Status,
|
|
29880
30386
|
parseProviderSourceConfigUpdate,
|
|
30387
|
+
parseWorktreeListOutput,
|
|
29881
30388
|
partitionSessionHostDiagnosticsSessions,
|
|
29882
30389
|
partitionSessionHostRecords,
|
|
29883
30390
|
prepareSessionChatTailUpdate,
|
|
@@ -29887,6 +30394,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29887
30394
|
recordDebugTrace,
|
|
29888
30395
|
registerExtensionProviders,
|
|
29889
30396
|
removeNode,
|
|
30397
|
+
removeWorktree,
|
|
29890
30398
|
resetConfig,
|
|
29891
30399
|
resetDebugRuntimeConfig,
|
|
29892
30400
|
resetState,
|
|
@@ -29896,6 +30404,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29896
30404
|
resolveGitRepository,
|
|
29897
30405
|
resolveSessionHostAppName,
|
|
29898
30406
|
resolveSessionHostAppNameResolution,
|
|
30407
|
+
resolveWorktreePath,
|
|
29899
30408
|
runAsyncBatch,
|
|
29900
30409
|
runGit,
|
|
29901
30410
|
saveConfig,
|