@adhdev/daemon-core 0.9.76-rc.10 → 0.9.76-rc.12
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/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 +660 -334
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +680 -359
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +1 -0
- package/dist/providers/cli-provider-instance.d.ts +1 -0
- package/dist/repo-mesh-types.d.ts +4 -0
- package/package.json +3 -1
- package/src/cli-adapters/provider-cli-adapter.ts +2 -0
- package/src/cli-adapters/provider-cli-runtime.ts +3 -2
- package/src/commands/cli-manager.ts +13 -3
- package/src/commands/mesh-coordinator.ts +11 -2
- package/src/commands/router.ts +205 -23
- 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.ts +2 -1
- package/src/repo-mesh-types.ts +4 -0
package/dist/index.mjs
CHANGED
|
@@ -41,6 +41,134 @@ var init_repo_mesh_types = __esm({
|
|
|
41
41
|
}
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
+
// src/git/git-worktree.ts
|
|
45
|
+
var git_worktree_exports = {};
|
|
46
|
+
__export(git_worktree_exports, {
|
|
47
|
+
createWorktree: () => createWorktree,
|
|
48
|
+
listWorktrees: () => listWorktrees,
|
|
49
|
+
parseWorktreeListOutput: () => parseWorktreeListOutput,
|
|
50
|
+
removeWorktree: () => removeWorktree,
|
|
51
|
+
resolveWorktreePath: () => resolveWorktreePath
|
|
52
|
+
});
|
|
53
|
+
import * as path4 from "path";
|
|
54
|
+
import { mkdir } from "fs/promises";
|
|
55
|
+
import { existsSync } from "fs";
|
|
56
|
+
import { execFile as execFile2 } from "child_process";
|
|
57
|
+
import { promisify as promisify2 } from "util";
|
|
58
|
+
function resolveWorktreePath(repoRoot, meshName, branch) {
|
|
59
|
+
const safeBranch = branch.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
|
|
60
|
+
const safeMeshName = meshName.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
|
|
61
|
+
const parentDir = path4.dirname(repoRoot);
|
|
62
|
+
return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
|
|
63
|
+
}
|
|
64
|
+
async function createWorktree(opts) {
|
|
65
|
+
const { repoRoot, branch, baseBranch, meshName } = opts;
|
|
66
|
+
const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
|
|
67
|
+
if (existsSync(targetDir)) {
|
|
68
|
+
throw new Error(`Worktree target directory already exists: ${targetDir}`);
|
|
69
|
+
}
|
|
70
|
+
await mkdir(path4.dirname(targetDir), { recursive: true });
|
|
71
|
+
const args = ["worktree", "add", targetDir, "-b", branch];
|
|
72
|
+
if (baseBranch) {
|
|
73
|
+
args.push(baseBranch);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
await execFileAsync2("git", args, {
|
|
77
|
+
cwd: repoRoot,
|
|
78
|
+
encoding: "utf8",
|
|
79
|
+
timeout: GIT_TIMEOUT_MS,
|
|
80
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
81
|
+
windowsHide: true
|
|
82
|
+
});
|
|
83
|
+
} catch (error) {
|
|
84
|
+
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
85
|
+
if (/already exists/i.test(stderr)) {
|
|
86
|
+
throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
|
|
87
|
+
}
|
|
88
|
+
throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
success: true,
|
|
92
|
+
worktreePath: targetDir,
|
|
93
|
+
branch
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function removeWorktree(repoRoot, worktreePath) {
|
|
97
|
+
if (!existsSync(worktreePath)) {
|
|
98
|
+
await pruneWorktrees(repoRoot);
|
|
99
|
+
return { success: true, removedPath: worktreePath };
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
await execFileAsync2("git", ["worktree", "remove", worktreePath, "--force"], {
|
|
103
|
+
cwd: repoRoot,
|
|
104
|
+
encoding: "utf8",
|
|
105
|
+
timeout: GIT_TIMEOUT_MS,
|
|
106
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
107
|
+
windowsHide: true
|
|
108
|
+
});
|
|
109
|
+
} catch (error) {
|
|
110
|
+
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
111
|
+
throw new Error(`git worktree remove failed: ${stderr.trim() || error.message}`);
|
|
112
|
+
}
|
|
113
|
+
return { success: true, removedPath: worktreePath };
|
|
114
|
+
}
|
|
115
|
+
async function listWorktrees(repoRoot) {
|
|
116
|
+
const { stdout } = await execFileAsync2("git", ["worktree", "list", "--porcelain"], {
|
|
117
|
+
cwd: repoRoot,
|
|
118
|
+
encoding: "utf8",
|
|
119
|
+
timeout: GIT_TIMEOUT_MS,
|
|
120
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
121
|
+
windowsHide: true
|
|
122
|
+
});
|
|
123
|
+
return parseWorktreeListOutput(stdout);
|
|
124
|
+
}
|
|
125
|
+
function parseWorktreeListOutput(output) {
|
|
126
|
+
const entries = [];
|
|
127
|
+
const blocks = output.trim().split(/\n\n+/);
|
|
128
|
+
for (const block of blocks) {
|
|
129
|
+
if (!block.trim()) continue;
|
|
130
|
+
const lines = block.trim().split("\n");
|
|
131
|
+
const entry = { path: "", head: "", branch: null, bare: false };
|
|
132
|
+
for (const line of lines) {
|
|
133
|
+
if (line.startsWith("worktree ")) {
|
|
134
|
+
entry.path = line.slice("worktree ".length).trim();
|
|
135
|
+
} else if (line.startsWith("HEAD ")) {
|
|
136
|
+
entry.head = line.slice("HEAD ".length).trim();
|
|
137
|
+
} else if (line.startsWith("branch ")) {
|
|
138
|
+
const ref = line.slice("branch ".length).trim();
|
|
139
|
+
entry.branch = ref.replace(/^refs\/heads\//, "");
|
|
140
|
+
} else if (line === "bare") {
|
|
141
|
+
entry.bare = true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (entry.path) {
|
|
145
|
+
entries.push(entry);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return entries;
|
|
149
|
+
}
|
|
150
|
+
async function pruneWorktrees(repoRoot) {
|
|
151
|
+
try {
|
|
152
|
+
await execFileAsync2("git", ["worktree", "prune"], {
|
|
153
|
+
cwd: repoRoot,
|
|
154
|
+
encoding: "utf8",
|
|
155
|
+
timeout: GIT_TIMEOUT_MS,
|
|
156
|
+
windowsHide: true
|
|
157
|
+
});
|
|
158
|
+
} catch {
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
var execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER;
|
|
162
|
+
var init_git_worktree = __esm({
|
|
163
|
+
"src/git/git-worktree.ts"() {
|
|
164
|
+
"use strict";
|
|
165
|
+
execFileAsync2 = promisify2(execFile2);
|
|
166
|
+
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
167
|
+
GIT_TIMEOUT_MS = 3e4;
|
|
168
|
+
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
44
172
|
// src/config/config.ts
|
|
45
173
|
var config_exports = {};
|
|
46
174
|
__export(config_exports, {
|
|
@@ -56,8 +184,8 @@ __export(config_exports, {
|
|
|
56
184
|
updateConfig: () => updateConfig
|
|
57
185
|
});
|
|
58
186
|
import { homedir } from "os";
|
|
59
|
-
import { join } from "path";
|
|
60
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
187
|
+
import { join as join2 } from "path";
|
|
188
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
|
|
61
189
|
import { randomUUID } from "crypto";
|
|
62
190
|
function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
|
|
63
191
|
if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
|
|
@@ -151,18 +279,18 @@ function ensureMachineId(config) {
|
|
|
151
279
|
};
|
|
152
280
|
}
|
|
153
281
|
function getConfigDir() {
|
|
154
|
-
const dir =
|
|
155
|
-
if (!
|
|
282
|
+
const dir = join2(homedir(), ".adhdev");
|
|
283
|
+
if (!existsSync2(dir)) {
|
|
156
284
|
mkdirSync(dir, { recursive: true });
|
|
157
285
|
}
|
|
158
286
|
return dir;
|
|
159
287
|
}
|
|
160
288
|
function getConfigPath() {
|
|
161
|
-
return
|
|
289
|
+
return join2(getConfigDir(), "config.json");
|
|
162
290
|
}
|
|
163
291
|
function migrateStateToStateFile(raw) {
|
|
164
|
-
const statePath =
|
|
165
|
-
if (
|
|
292
|
+
const statePath = join2(getConfigDir(), "state.json");
|
|
293
|
+
if (existsSync2(statePath)) return;
|
|
166
294
|
const recentActivity = Array.isArray(raw.recentActivity) ? raw.recentActivity : [];
|
|
167
295
|
const savedProviderSessions = Array.isArray(raw.savedProviderSessions) ? raw.savedProviderSessions : [];
|
|
168
296
|
const legacySessionReads = isPlainObject(raw.recentSessionReads) ? raw.recentSessionReads : {};
|
|
@@ -186,7 +314,7 @@ function migrateStateToStateFile(raw) {
|
|
|
186
314
|
}
|
|
187
315
|
function loadConfig() {
|
|
188
316
|
const configPath = getConfigPath();
|
|
189
|
-
if (!
|
|
317
|
+
if (!existsSync2(configPath)) {
|
|
190
318
|
const initialized = ensureMachineId({ ...DEFAULT_CONFIG });
|
|
191
319
|
try {
|
|
192
320
|
saveConfig(initialized.config);
|
|
@@ -217,7 +345,7 @@ function saveConfig(config) {
|
|
|
217
345
|
const configPath = getConfigPath();
|
|
218
346
|
const dir = getConfigDir();
|
|
219
347
|
const normalized = normalizeConfig(config);
|
|
220
|
-
if (!
|
|
348
|
+
if (!existsSync2(dir)) {
|
|
221
349
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
222
350
|
}
|
|
223
351
|
writeFileSync(configPath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
@@ -295,17 +423,17 @@ __export(mesh_config_exports, {
|
|
|
295
423
|
updateMesh: () => updateMesh,
|
|
296
424
|
updateNode: () => updateNode
|
|
297
425
|
});
|
|
298
|
-
import { existsSync as
|
|
299
|
-
import { join as
|
|
426
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
427
|
+
import { join as join4 } from "path";
|
|
300
428
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
301
429
|
function getMeshConfigPath() {
|
|
302
|
-
return
|
|
430
|
+
return join4(getConfigDir(), "meshes.json");
|
|
303
431
|
}
|
|
304
432
|
function loadMeshConfig() {
|
|
305
|
-
const
|
|
306
|
-
if (!
|
|
433
|
+
const path27 = getMeshConfigPath();
|
|
434
|
+
if (!existsSync4(path27)) return { meshes: [] };
|
|
307
435
|
try {
|
|
308
|
-
const raw = JSON.parse(readFileSync2(
|
|
436
|
+
const raw = JSON.parse(readFileSync2(path27, "utf-8"));
|
|
309
437
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
310
438
|
return raw;
|
|
311
439
|
} catch {
|
|
@@ -313,16 +441,16 @@ function loadMeshConfig() {
|
|
|
313
441
|
}
|
|
314
442
|
}
|
|
315
443
|
function saveMeshConfig(config) {
|
|
316
|
-
const
|
|
317
|
-
writeFileSync2(
|
|
444
|
+
const path27 = getMeshConfigPath();
|
|
445
|
+
writeFileSync2(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
|
|
318
446
|
}
|
|
319
447
|
function normalizeRepoIdentity(remoteUrl) {
|
|
320
448
|
let identity = remoteUrl.trim();
|
|
321
449
|
if (identity.startsWith("http://") || identity.startsWith("https://")) {
|
|
322
450
|
try {
|
|
323
451
|
const url = new URL(identity);
|
|
324
|
-
const
|
|
325
|
-
return `${url.hostname}/${
|
|
452
|
+
const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
|
|
453
|
+
return `${url.hostname}/${path27}`;
|
|
326
454
|
} catch {
|
|
327
455
|
}
|
|
328
456
|
}
|
|
@@ -397,9 +525,12 @@ function addNode(meshId, opts) {
|
|
|
397
525
|
id: `node_${randomUUID3().replace(/-/g, "")}`,
|
|
398
526
|
workspace: opts.workspace.trim(),
|
|
399
527
|
repoRoot: opts.repoRoot,
|
|
528
|
+
daemonId: opts.daemonId,
|
|
400
529
|
userOverrides: opts.userOverrides || {},
|
|
401
530
|
policy: opts.policy || {},
|
|
402
|
-
isLocalWorktree: opts.isLocalWorktree
|
|
531
|
+
isLocalWorktree: opts.isLocalWorktree,
|
|
532
|
+
worktreeBranch: opts.worktreeBranch,
|
|
533
|
+
clonedFromNodeId: opts.clonedFromNodeId
|
|
403
534
|
};
|
|
404
535
|
mesh.nodes.push(node);
|
|
405
536
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -443,7 +574,7 @@ __export(coordinator_prompt_exports, {
|
|
|
443
574
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
|
|
444
575
|
});
|
|
445
576
|
function buildCoordinatorSystemPrompt(ctx) {
|
|
446
|
-
const { mesh, status, userInstruction } = ctx;
|
|
577
|
+
const { mesh, status, userInstruction, coordinatorCliType } = ctx;
|
|
447
578
|
const sections = [];
|
|
448
579
|
sections.push(`You are a **Repo Mesh Coordinator** \u2014 a technical team lead who orchestrates work across multiple agent sessions on a shared Git repository.
|
|
449
580
|
|
|
@@ -457,15 +588,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
457
588
|
} else {
|
|
458
589
|
sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
|
|
459
590
|
}
|
|
460
|
-
sections.push(buildPolicySection(mesh.policy));
|
|
591
|
+
sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
|
|
461
592
|
sections.push(TOOLS_SECTION);
|
|
462
593
|
sections.push(WORKFLOW_SECTION);
|
|
463
|
-
sections.push(
|
|
594
|
+
sections.push(buildRulesSection(coordinatorCliType));
|
|
464
595
|
if (userInstruction) {
|
|
465
596
|
sections.push(`## Additional Context
|
|
466
597
|
${userInstruction}`);
|
|
467
598
|
}
|
|
468
|
-
if (mesh.coordinator
|
|
599
|
+
if (mesh.coordinator?.systemPromptSuffix) {
|
|
469
600
|
sections.push(mesh.coordinator.systemPromptSuffix);
|
|
470
601
|
}
|
|
471
602
|
return sections.join("\n\n");
|
|
@@ -510,10 +641,29 @@ function buildPolicySection(policy) {
|
|
|
510
641
|
return `## Policy
|
|
511
642
|
${rules.join("\n")}`;
|
|
512
643
|
}
|
|
513
|
-
|
|
644
|
+
function buildRulesSection(coordinatorCliType) {
|
|
645
|
+
const coordinatorNote = coordinatorCliType ? `
|
|
646
|
+
- **Coordinator runtime is not a delegation default.** This coordinator is running as \`${coordinatorCliType}\`, but delegated node sessions must follow the user's requested provider, not the coordinator's own runtime.` : "";
|
|
647
|
+
return `## Rules
|
|
648
|
+
|
|
649
|
+
- **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
|
|
650
|
+
- **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
|
|
651
|
+
- **Respect explicit provider requests.** If the user names an agent/provider, pass the matching provider type to \`mesh_launch_session\`: Hermes \u2192 \`hermes-cli\`, Claude Code/Claude \u2192 \`claude-cli\`, Codex \u2192 \`codex-cli\`, Gemini \u2192 \`gemini-cli\`. Never substitute \`claude-cli\` just because the coordinator itself is Claude Code.
|
|
652
|
+
- **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
|
|
653
|
+
- **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
|
|
654
|
+
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
|
|
655
|
+
- **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
|
|
656
|
+
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
657
|
+
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
658
|
+
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.
|
|
659
|
+
- **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
|
|
660
|
+
- **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
|
|
661
|
+
}
|
|
662
|
+
var TOOLS_SECTION, WORKFLOW_SECTION;
|
|
514
663
|
var init_coordinator_prompt = __esm({
|
|
515
664
|
"src/mesh/coordinator-prompt.ts"() {
|
|
516
665
|
"use strict";
|
|
666
|
+
init_repo_mesh_types();
|
|
517
667
|
TOOLS_SECTION = `## Available Tools
|
|
518
668
|
|
|
519
669
|
| Tool | Purpose |
|
|
@@ -525,36 +675,29 @@ var init_coordinator_prompt = __esm({
|
|
|
525
675
|
| \`mesh_read_chat\` | Read an agent's recent messages to check progress |
|
|
526
676
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
527
677
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
528
|
-
| \`mesh_approve\` | Approve/reject a pending agent action
|
|
678
|
+
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
679
|
+
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
680
|
+
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
|
|
529
681
|
WORKFLOW_SECTION = `## Orchestration Workflow
|
|
530
682
|
|
|
531
683
|
1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
|
|
532
684
|
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
|
|
533
685
|
3. **Delegate** \u2014 For each task:
|
|
534
686
|
a. Pick the best node (consider: health, dirty state, current workload).
|
|
535
|
-
b. If
|
|
536
|
-
c.
|
|
687
|
+
b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
688
|
+
c. If no session exists, call \`mesh_launch_session\` to start one.
|
|
689
|
+
d. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
|
|
537
690
|
4. **Monitor** \u2014 Periodically call \`mesh_read_chat\` to check progress. Handle approvals via \`mesh_approve\`.
|
|
538
691
|
5. **Verify** \u2014 When a task reports completion, call \`mesh_git_status\` to verify changes were made.
|
|
539
692
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
540
|
-
7. **
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
- **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
|
|
544
|
-
- **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
|
|
545
|
-
- **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
|
|
546
|
-
- **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
|
|
547
|
-
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
|
|
548
|
-
- **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
|
|
549
|
-
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
550
|
-
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
551
|
-
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
|
|
693
|
+
7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
694
|
+
8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
|
|
552
695
|
}
|
|
553
696
|
});
|
|
554
697
|
|
|
555
698
|
// src/logging/logger.ts
|
|
556
699
|
import * as fs2 from "fs";
|
|
557
|
-
import * as
|
|
700
|
+
import * as path10 from "path";
|
|
558
701
|
import * as os4 from "os";
|
|
559
702
|
function setLogLevel(level) {
|
|
560
703
|
currentLevel = level;
|
|
@@ -570,13 +713,13 @@ function getDaemonLogDir() {
|
|
|
570
713
|
return LOG_DIR;
|
|
571
714
|
}
|
|
572
715
|
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
573
|
-
return
|
|
716
|
+
return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
574
717
|
}
|
|
575
718
|
function checkDateRotation() {
|
|
576
719
|
const today = getDateStr();
|
|
577
720
|
if (today !== currentDate) {
|
|
578
721
|
currentDate = today;
|
|
579
|
-
currentLogFile =
|
|
722
|
+
currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
580
723
|
cleanOldLogs();
|
|
581
724
|
}
|
|
582
725
|
}
|
|
@@ -590,7 +733,7 @@ function cleanOldLogs() {
|
|
|
590
733
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
591
734
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
592
735
|
try {
|
|
593
|
-
fs2.unlinkSync(
|
|
736
|
+
fs2.unlinkSync(path10.join(LOG_DIR, file));
|
|
594
737
|
} catch {
|
|
595
738
|
}
|
|
596
739
|
}
|
|
@@ -713,7 +856,7 @@ var init_logger = __esm({
|
|
|
713
856
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
714
857
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
715
858
|
currentLevel = "info";
|
|
716
|
-
LOG_DIR = process.platform === "win32" ?
|
|
859
|
+
LOG_DIR = process.platform === "win32" ? path10.join(process.env.LOCALAPPDATA || process.env.APPDATA || path10.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path10.join(os4.homedir(), "Library", "Logs", "adhdev") : path10.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
717
860
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
718
861
|
MAX_LOG_DAYS = 7;
|
|
719
862
|
try {
|
|
@@ -721,16 +864,16 @@ var init_logger = __esm({
|
|
|
721
864
|
} catch {
|
|
722
865
|
}
|
|
723
866
|
currentDate = getDateStr();
|
|
724
|
-
currentLogFile =
|
|
867
|
+
currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
725
868
|
cleanOldLogs();
|
|
726
869
|
try {
|
|
727
|
-
const oldLog =
|
|
870
|
+
const oldLog = path10.join(LOG_DIR, "daemon.log");
|
|
728
871
|
if (fs2.existsSync(oldLog)) {
|
|
729
872
|
const stat2 = fs2.statSync(oldLog);
|
|
730
873
|
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
731
|
-
fs2.renameSync(oldLog,
|
|
874
|
+
fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
732
875
|
}
|
|
733
|
-
const oldLogBackup =
|
|
876
|
+
const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
|
|
734
877
|
if (fs2.existsSync(oldLogBackup)) {
|
|
735
878
|
fs2.unlinkSync(oldLogBackup);
|
|
736
879
|
}
|
|
@@ -762,7 +905,7 @@ var init_logger = __esm({
|
|
|
762
905
|
}
|
|
763
906
|
};
|
|
764
907
|
interceptorInstalled = false;
|
|
765
|
-
LOG_PATH =
|
|
908
|
+
LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
766
909
|
}
|
|
767
910
|
});
|
|
768
911
|
|
|
@@ -1171,7 +1314,7 @@ var init_pty_transport = __esm({
|
|
|
1171
1314
|
|
|
1172
1315
|
// src/cli-adapters/provider-cli-shared.ts
|
|
1173
1316
|
import * as os9 from "os";
|
|
1174
|
-
import * as
|
|
1317
|
+
import * as path14 from "path";
|
|
1175
1318
|
import { execSync as execSync3 } from "child_process";
|
|
1176
1319
|
function stripAnsi(str) {
|
|
1177
1320
|
return str.replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][\s\S]*?\x1B\\/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/ +/g, " ");
|
|
@@ -1236,9 +1379,9 @@ function buildCliScreenSnapshot(text) {
|
|
|
1236
1379
|
function findBinary(name) {
|
|
1237
1380
|
const trimmed = String(name || "").trim();
|
|
1238
1381
|
if (!trimmed) return trimmed;
|
|
1239
|
-
const expanded = trimmed.startsWith("~") ?
|
|
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);
|
|
@@ -1484,10 +1627,10 @@ var init_provider_cli_config = __esm({
|
|
|
1484
1627
|
|
|
1485
1628
|
// src/cli-adapters/provider-cli-runtime.ts
|
|
1486
1629
|
import * as os10 from "os";
|
|
1487
|
-
import * as
|
|
1630
|
+
import * as path15 from "path";
|
|
1488
1631
|
import { DEFAULT_SESSION_HOST_COLS, DEFAULT_SESSION_HOST_ROWS } from "@adhdev/session-host-core";
|
|
1489
1632
|
function resolveCliSpawnPlan(options) {
|
|
1490
|
-
const { provider, runtimeSettings, workingDir, extraArgs } = options;
|
|
1633
|
+
const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
|
|
1491
1634
|
const { spawn: spawnConfig } = provider;
|
|
1492
1635
|
const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
1493
1636
|
const binaryPath = findBinary(configuredCommand);
|
|
@@ -1495,9 +1638,9 @@ function resolveCliSpawnPlan(options) {
|
|
|
1495
1638
|
const allArgs = [...spawnConfig.args, ...extraArgs];
|
|
1496
1639
|
let shellCmd;
|
|
1497
1640
|
let shellArgs;
|
|
1498
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
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,
|
|
@@ -1610,8 +1753,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1610
1753
|
init_provider_cli_runtime();
|
|
1611
1754
|
init_provider_cli_shared();
|
|
1612
1755
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
1613
|
-
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
1756
|
+
constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
|
|
1614
1757
|
this.extraArgs = extraArgs;
|
|
1758
|
+
this.extraEnv = extraEnv;
|
|
1615
1759
|
this.provider = provider;
|
|
1616
1760
|
this.transportFactory = transportFactory;
|
|
1617
1761
|
this.cliType = provider.type;
|
|
@@ -1927,7 +2071,8 @@ ${lastSnapshot}`;
|
|
|
1927
2071
|
provider: this.provider,
|
|
1928
2072
|
runtimeSettings: this.runtimeSettings,
|
|
1929
2073
|
workingDir: this.workingDir,
|
|
1930
|
-
extraArgs: this.extraArgs
|
|
2074
|
+
extraArgs: this.extraArgs,
|
|
2075
|
+
extraEnv: this.extraEnv
|
|
1931
2076
|
});
|
|
1932
2077
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1933
2078
|
this.resetTraceSession();
|
|
@@ -4984,20 +5129,23 @@ var TurnSnapshotTracker = class {
|
|
|
4984
5129
|
}
|
|
4985
5130
|
};
|
|
4986
5131
|
|
|
5132
|
+
// src/git/index.ts
|
|
5133
|
+
init_git_worktree();
|
|
5134
|
+
|
|
4987
5135
|
// src/index.ts
|
|
4988
5136
|
init_config();
|
|
4989
5137
|
|
|
4990
5138
|
// src/config/workspaces.ts
|
|
4991
5139
|
import * as fs from "fs";
|
|
4992
5140
|
import * as os from "os";
|
|
4993
|
-
import * as
|
|
5141
|
+
import * as path5 from "path";
|
|
4994
5142
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4995
5143
|
var MAX_WORKSPACES = 50;
|
|
4996
5144
|
function expandPath(p) {
|
|
4997
5145
|
const t = (p || "").trim();
|
|
4998
5146
|
if (!t) return "";
|
|
4999
|
-
if (t.startsWith("~")) return
|
|
5000
|
-
return
|
|
5147
|
+
if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
5148
|
+
return path5.resolve(t);
|
|
5001
5149
|
}
|
|
5002
5150
|
function validateWorkspacePath(absPath) {
|
|
5003
5151
|
try {
|
|
@@ -5011,7 +5159,7 @@ function validateWorkspacePath(absPath) {
|
|
|
5011
5159
|
}
|
|
5012
5160
|
}
|
|
5013
5161
|
function defaultWorkspaceLabel(absPath) {
|
|
5014
|
-
const base =
|
|
5162
|
+
const base = path5.basename(absPath) || absPath;
|
|
5015
5163
|
return base;
|
|
5016
5164
|
}
|
|
5017
5165
|
function getDefaultWorkspacePath(config) {
|
|
@@ -5102,9 +5250,9 @@ function resolveIdeLaunchWorkspace(args, config) {
|
|
|
5102
5250
|
return getDefaultWorkspacePath(config) || void 0;
|
|
5103
5251
|
}
|
|
5104
5252
|
function findWorkspaceByPath(config, rawPath) {
|
|
5105
|
-
const abs =
|
|
5253
|
+
const abs = path5.resolve(expandPath(rawPath));
|
|
5106
5254
|
if (!abs) return void 0;
|
|
5107
|
-
return (config.workspaces || []).find((w) =>
|
|
5255
|
+
return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
|
|
5108
5256
|
}
|
|
5109
5257
|
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
5110
5258
|
const abs = expandPath(rawPath);
|
|
@@ -5120,7 +5268,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
|
|
|
5120
5268
|
const v = validateWorkspacePath(abs);
|
|
5121
5269
|
if (!v.ok) return { error: v.error };
|
|
5122
5270
|
const list = [...config.workspaces || []];
|
|
5123
|
-
if (list.some((w) =>
|
|
5271
|
+
if (list.some((w) => path5.resolve(w.path) === abs)) {
|
|
5124
5272
|
return { error: "Workspace already in list" };
|
|
5125
5273
|
}
|
|
5126
5274
|
if (list.length >= MAX_WORKSPACES) {
|
|
@@ -5154,7 +5302,7 @@ function setDefaultWorkspaceId(config, id) {
|
|
|
5154
5302
|
}
|
|
5155
5303
|
|
|
5156
5304
|
// src/config/recent-activity.ts
|
|
5157
|
-
import * as
|
|
5305
|
+
import * as path6 from "path";
|
|
5158
5306
|
|
|
5159
5307
|
// src/providers/summary-metadata.ts
|
|
5160
5308
|
function normalizeSummaryItem(item) {
|
|
@@ -5223,9 +5371,9 @@ var MAX_ACTIVITY = 30;
|
|
|
5223
5371
|
function normalizeWorkspace(workspace) {
|
|
5224
5372
|
if (!workspace) return "";
|
|
5225
5373
|
try {
|
|
5226
|
-
return
|
|
5374
|
+
return path6.resolve(expandPath(workspace));
|
|
5227
5375
|
} catch {
|
|
5228
|
-
return
|
|
5376
|
+
return path6.resolve(workspace);
|
|
5229
5377
|
}
|
|
5230
5378
|
}
|
|
5231
5379
|
function buildRecentActivityKey(entry) {
|
|
@@ -5393,14 +5541,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
|
|
|
5393
5541
|
}
|
|
5394
5542
|
|
|
5395
5543
|
// src/config/saved-sessions.ts
|
|
5396
|
-
import * as
|
|
5544
|
+
import * as path7 from "path";
|
|
5397
5545
|
var MAX_SAVED_SESSIONS = 500;
|
|
5398
5546
|
function normalizeWorkspace2(workspace) {
|
|
5399
5547
|
if (!workspace) return "";
|
|
5400
5548
|
try {
|
|
5401
|
-
return
|
|
5549
|
+
return path7.resolve(expandPath(workspace));
|
|
5402
5550
|
} catch {
|
|
5403
|
-
return
|
|
5551
|
+
return path7.resolve(workspace);
|
|
5404
5552
|
}
|
|
5405
5553
|
}
|
|
5406
5554
|
function buildSavedProviderSessionKey(providerSessionId) {
|
|
@@ -5506,8 +5654,8 @@ async function syncMeshes(transport) {
|
|
|
5506
5654
|
|
|
5507
5655
|
// src/config/state-store.ts
|
|
5508
5656
|
init_config();
|
|
5509
|
-
import { existsSync as
|
|
5510
|
-
import { join as
|
|
5657
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5658
|
+
import { join as join5 } from "path";
|
|
5511
5659
|
var DEFAULT_STATE = {
|
|
5512
5660
|
recentActivity: [],
|
|
5513
5661
|
savedProviderSessions: [],
|
|
@@ -5520,7 +5668,7 @@ function isPlainObject2(value) {
|
|
|
5520
5668
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5521
5669
|
}
|
|
5522
5670
|
function getStatePath() {
|
|
5523
|
-
return
|
|
5671
|
+
return join5(getConfigDir(), "state.json");
|
|
5524
5672
|
}
|
|
5525
5673
|
function normalizeState(raw) {
|
|
5526
5674
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -5556,7 +5704,7 @@ function normalizeState(raw) {
|
|
|
5556
5704
|
}
|
|
5557
5705
|
function loadState() {
|
|
5558
5706
|
const statePath = getStatePath();
|
|
5559
|
-
if (!
|
|
5707
|
+
if (!existsSync5(statePath)) {
|
|
5560
5708
|
return { ...DEFAULT_STATE };
|
|
5561
5709
|
}
|
|
5562
5710
|
try {
|
|
@@ -5577,9 +5725,9 @@ function resetState() {
|
|
|
5577
5725
|
|
|
5578
5726
|
// src/detection/ide-detector.ts
|
|
5579
5727
|
import { execSync } from "child_process";
|
|
5580
|
-
import { existsSync as
|
|
5728
|
+
import { existsSync as existsSync6 } from "fs";
|
|
5581
5729
|
import { platform, homedir as homedir3 } from "os";
|
|
5582
|
-
import * as
|
|
5730
|
+
import * as path8 from "path";
|
|
5583
5731
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
5584
5732
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
5585
5733
|
function registerIDEDefinition(def) {
|
|
@@ -5598,10 +5746,10 @@ function getMergedDefinitions() {
|
|
|
5598
5746
|
function findCliCommand(command) {
|
|
5599
5747
|
const trimmed = String(command || "").trim();
|
|
5600
5748
|
if (!trimmed) return null;
|
|
5601
|
-
if (
|
|
5602
|
-
const candidate = trimmed.startsWith("~") ?
|
|
5603
|
-
const resolved =
|
|
5604
|
-
return
|
|
5749
|
+
if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
5750
|
+
const candidate = trimmed.startsWith("~") ? path8.join(homedir3(), trimmed.slice(1)) : trimmed;
|
|
5751
|
+
const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
|
|
5752
|
+
return existsSync6(resolved) ? resolved : null;
|
|
5605
5753
|
}
|
|
5606
5754
|
try {
|
|
5607
5755
|
const result = execSync(
|
|
@@ -5628,31 +5776,31 @@ function getIdeVersion(cliCommand) {
|
|
|
5628
5776
|
function checkPathExists(paths) {
|
|
5629
5777
|
const home = homedir3();
|
|
5630
5778
|
for (const p of paths) {
|
|
5631
|
-
const normalized = p.startsWith("~") ?
|
|
5779
|
+
const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
|
|
5632
5780
|
if (normalized.includes("*")) {
|
|
5633
5781
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5634
5782
|
const resolved = normalized.replace("*", username);
|
|
5635
|
-
if (
|
|
5783
|
+
if (existsSync6(resolved)) return resolved;
|
|
5636
5784
|
} else {
|
|
5637
|
-
if (
|
|
5785
|
+
if (existsSync6(normalized)) return normalized;
|
|
5638
5786
|
}
|
|
5639
5787
|
}
|
|
5640
5788
|
return null;
|
|
5641
5789
|
}
|
|
5642
5790
|
async function detectIDEs(providerLoader) {
|
|
5643
|
-
const
|
|
5791
|
+
const os22 = platform();
|
|
5644
5792
|
const results = [];
|
|
5645
5793
|
for (const def of getMergedDefinitions()) {
|
|
5646
5794
|
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
5647
|
-
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[
|
|
5795
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
|
|
5648
5796
|
let resolvedCli = cliPath;
|
|
5649
|
-
if (!resolvedCli && appPath &&
|
|
5797
|
+
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
5650
5798
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
5651
|
-
if (
|
|
5799
|
+
if (existsSync6(bundledCli)) resolvedCli = bundledCli;
|
|
5652
5800
|
}
|
|
5653
|
-
if (!resolvedCli && appPath &&
|
|
5654
|
-
const { dirname:
|
|
5655
|
-
const appDir =
|
|
5801
|
+
if (!resolvedCli && appPath && os22 === "win32") {
|
|
5802
|
+
const { dirname: dirname9 } = await import("path");
|
|
5803
|
+
const appDir = dirname9(appPath);
|
|
5656
5804
|
const candidates = [
|
|
5657
5805
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
5658
5806
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -5661,13 +5809,13 @@ async function detectIDEs(providerLoader) {
|
|
|
5661
5809
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
5662
5810
|
];
|
|
5663
5811
|
for (const c of candidates) {
|
|
5664
|
-
if (
|
|
5812
|
+
if (existsSync6(c)) {
|
|
5665
5813
|
resolvedCli = c;
|
|
5666
5814
|
break;
|
|
5667
5815
|
}
|
|
5668
5816
|
}
|
|
5669
5817
|
}
|
|
5670
|
-
const installed =
|
|
5818
|
+
const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
5671
5819
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
5672
5820
|
results.push({
|
|
5673
5821
|
id: def.id,
|
|
@@ -5686,8 +5834,8 @@ async function detectIDEs(providerLoader) {
|
|
|
5686
5834
|
// src/detection/cli-detector.ts
|
|
5687
5835
|
import { exec } from "child_process";
|
|
5688
5836
|
import * as os2 from "os";
|
|
5689
|
-
import * as
|
|
5690
|
-
import { existsSync as
|
|
5837
|
+
import * as path9 from "path";
|
|
5838
|
+
import { existsSync as existsSync7 } from "fs";
|
|
5691
5839
|
function parseVersion(raw) {
|
|
5692
5840
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
5693
5841
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
@@ -5699,19 +5847,19 @@ function shellQuote(value) {
|
|
|
5699
5847
|
function expandHome(value) {
|
|
5700
5848
|
const trimmed = value.trim();
|
|
5701
5849
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
5702
|
-
return
|
|
5850
|
+
return path9.join(os2.homedir(), trimmed.slice(1));
|
|
5703
5851
|
}
|
|
5704
5852
|
function isExplicitCommandPath(command) {
|
|
5705
5853
|
const trimmed = command.trim();
|
|
5706
|
-
return
|
|
5854
|
+
return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
5707
5855
|
}
|
|
5708
5856
|
function resolveCommandPath(command) {
|
|
5709
5857
|
const trimmed = command.trim();
|
|
5710
5858
|
if (!trimmed) return null;
|
|
5711
5859
|
if (isExplicitCommandPath(trimmed)) {
|
|
5712
5860
|
const expanded = expandHome(trimmed);
|
|
5713
|
-
const candidate =
|
|
5714
|
-
return
|
|
5861
|
+
const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
5862
|
+
return existsSync7(candidate) ? candidate : null;
|
|
5715
5863
|
}
|
|
5716
5864
|
return null;
|
|
5717
5865
|
}
|
|
@@ -7979,9 +8127,9 @@ ${cleanBody}`;
|
|
|
7979
8127
|
|
|
7980
8128
|
// src/config/chat-history.ts
|
|
7981
8129
|
import * as fs3 from "fs";
|
|
7982
|
-
import * as
|
|
8130
|
+
import * as path11 from "path";
|
|
7983
8131
|
import * as os5 from "os";
|
|
7984
|
-
var HISTORY_DIR =
|
|
8132
|
+
var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
|
|
7985
8133
|
var RETAIN_DAYS = 30;
|
|
7986
8134
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
7987
8135
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -8144,7 +8292,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
8144
8292
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
8145
8293
|
return new Map(files.map((file) => {
|
|
8146
8294
|
try {
|
|
8147
|
-
const stat2 = fs3.statSync(
|
|
8295
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8148
8296
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
8149
8297
|
} catch {
|
|
8150
8298
|
return [file, `${file}:missing`];
|
|
@@ -8155,7 +8303,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
8155
8303
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
8156
8304
|
}
|
|
8157
8305
|
function getSavedHistoryIndexFilePath(dir) {
|
|
8158
|
-
return
|
|
8306
|
+
return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
8159
8307
|
}
|
|
8160
8308
|
function getSavedHistoryIndexLockPath(dir) {
|
|
8161
8309
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -8257,7 +8405,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
8257
8405
|
}
|
|
8258
8406
|
for (const file of Array.from(currentEntries.keys())) {
|
|
8259
8407
|
if (incomingFiles.has(file)) continue;
|
|
8260
|
-
if (!fs3.existsSync(
|
|
8408
|
+
if (!fs3.existsSync(path11.join(dir, file))) {
|
|
8261
8409
|
currentEntries.delete(file);
|
|
8262
8410
|
}
|
|
8263
8411
|
}
|
|
@@ -8283,7 +8431,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8283
8431
|
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
8284
8432
|
const files = listHistoryFiles(dir);
|
|
8285
8433
|
for (const file of files) {
|
|
8286
|
-
const stat2 = fs3.statSync(
|
|
8434
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8287
8435
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
8288
8436
|
}
|
|
8289
8437
|
return false;
|
|
@@ -8293,14 +8441,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8293
8441
|
}
|
|
8294
8442
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
8295
8443
|
try {
|
|
8296
|
-
const stat2 = fs3.statSync(
|
|
8444
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8297
8445
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
8298
8446
|
} catch {
|
|
8299
8447
|
return `${file}:missing`;
|
|
8300
8448
|
}
|
|
8301
8449
|
}
|
|
8302
8450
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
8303
|
-
const filePath =
|
|
8451
|
+
const filePath = path11.join(dir, file);
|
|
8304
8452
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
8305
8453
|
const currentEntry = entries.get(file) || null;
|
|
8306
8454
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -8373,7 +8521,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
8373
8521
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
8374
8522
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
8375
8523
|
if (!historySessionId) return null;
|
|
8376
|
-
const filePath =
|
|
8524
|
+
const filePath = path11.join(dir, file);
|
|
8377
8525
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8378
8526
|
const lines = content.split("\n").filter(Boolean);
|
|
8379
8527
|
let messageCount = 0;
|
|
@@ -8460,7 +8608,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
8460
8608
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
8461
8609
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
8462
8610
|
for (const file of files.slice().sort()) {
|
|
8463
|
-
const filePath =
|
|
8611
|
+
const filePath = path11.join(dir, file);
|
|
8464
8612
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
8465
8613
|
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
8466
8614
|
const persisted = persistedEntries.get(file);
|
|
@@ -8580,12 +8728,12 @@ var ChatHistoryWriter = class {
|
|
|
8580
8728
|
});
|
|
8581
8729
|
}
|
|
8582
8730
|
if (newMessages.length === 0) return;
|
|
8583
|
-
const dir =
|
|
8731
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8584
8732
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8585
8733
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8586
8734
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
8587
8735
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
8588
|
-
const filePath =
|
|
8736
|
+
const filePath = path11.join(dir, fileName);
|
|
8589
8737
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
8590
8738
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
8591
8739
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -8676,11 +8824,11 @@ var ChatHistoryWriter = class {
|
|
|
8676
8824
|
const ws = String(workspace || "").trim();
|
|
8677
8825
|
if (!id || !ws) return;
|
|
8678
8826
|
try {
|
|
8679
|
-
const dir =
|
|
8827
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8680
8828
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8681
8829
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8682
8830
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
8683
|
-
const filePath =
|
|
8831
|
+
const filePath = path11.join(dir, fileName);
|
|
8684
8832
|
const record = {
|
|
8685
8833
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8686
8834
|
receivedAt: Date.now(),
|
|
@@ -8726,14 +8874,14 @@ var ChatHistoryWriter = class {
|
|
|
8726
8874
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
8727
8875
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
8728
8876
|
}
|
|
8729
|
-
const dir =
|
|
8877
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8730
8878
|
if (!fs3.existsSync(dir)) return;
|
|
8731
8879
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
8732
8880
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
8733
8881
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
8734
8882
|
for (const file of files) {
|
|
8735
|
-
const sourcePath =
|
|
8736
|
-
const targetPath =
|
|
8883
|
+
const sourcePath = path11.join(dir, file);
|
|
8884
|
+
const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
8737
8885
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
8738
8886
|
const rewritten = sourceLines.map((line) => {
|
|
8739
8887
|
try {
|
|
@@ -8767,13 +8915,13 @@ var ChatHistoryWriter = class {
|
|
|
8767
8915
|
const sessionId = String(historySessionId || "").trim();
|
|
8768
8916
|
if (!sessionId) return;
|
|
8769
8917
|
try {
|
|
8770
|
-
const dir =
|
|
8918
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8771
8919
|
if (!fs3.existsSync(dir)) return;
|
|
8772
8920
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
8773
8921
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
8774
8922
|
const seen = /* @__PURE__ */ new Set();
|
|
8775
8923
|
for (const file of files) {
|
|
8776
|
-
const filePath =
|
|
8924
|
+
const filePath = path11.join(dir, file);
|
|
8777
8925
|
const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
8778
8926
|
const next = [];
|
|
8779
8927
|
for (const line of lines) {
|
|
@@ -8827,11 +8975,11 @@ var ChatHistoryWriter = class {
|
|
|
8827
8975
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
8828
8976
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
8829
8977
|
for (const dir of agentDirs) {
|
|
8830
|
-
const dirPath =
|
|
8978
|
+
const dirPath = path11.join(HISTORY_DIR, dir.name);
|
|
8831
8979
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
8832
8980
|
let removedAny = false;
|
|
8833
8981
|
for (const file of files) {
|
|
8834
|
-
const filePath =
|
|
8982
|
+
const filePath = path11.join(dirPath, file);
|
|
8835
8983
|
const stat2 = fs3.statSync(filePath);
|
|
8836
8984
|
if (stat2.mtimeMs < cutoff) {
|
|
8837
8985
|
fs3.unlinkSync(filePath);
|
|
@@ -8881,13 +9029,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
8881
9029
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
8882
9030
|
try {
|
|
8883
9031
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8884
|
-
const dir =
|
|
9032
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
8885
9033
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
8886
9034
|
const files = listHistoryFiles(dir, historySessionId);
|
|
8887
9035
|
const allMessages = [];
|
|
8888
9036
|
const seen = /* @__PURE__ */ new Set();
|
|
8889
9037
|
for (const file of files) {
|
|
8890
|
-
const filePath =
|
|
9038
|
+
const filePath = path11.join(dir, file);
|
|
8891
9039
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8892
9040
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
8893
9041
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -8911,7 +9059,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
8911
9059
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
8912
9060
|
try {
|
|
8913
9061
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8914
|
-
const dir =
|
|
9062
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
8915
9063
|
if (!fs3.existsSync(dir)) {
|
|
8916
9064
|
savedHistorySessionCache.delete(sanitized);
|
|
8917
9065
|
return { sessions: [], hasMore: false };
|
|
@@ -8972,11 +9120,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
8972
9120
|
}
|
|
8973
9121
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
8974
9122
|
try {
|
|
8975
|
-
const dir =
|
|
9123
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
8976
9124
|
if (!fs3.existsSync(dir)) return null;
|
|
8977
9125
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
8978
9126
|
for (const file of files) {
|
|
8979
|
-
const lines = fs3.readFileSync(
|
|
9127
|
+
const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
8980
9128
|
for (const line of lines) {
|
|
8981
9129
|
try {
|
|
8982
9130
|
const parsed = JSON.parse(line);
|
|
@@ -8996,16 +9144,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
8996
9144
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
8997
9145
|
if (records.length === 0) return false;
|
|
8998
9146
|
try {
|
|
8999
|
-
const dir =
|
|
9147
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9000
9148
|
fs3.mkdirSync(dir, { recursive: true });
|
|
9001
9149
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
9002
9150
|
for (const file of fs3.readdirSync(dir)) {
|
|
9003
9151
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
9004
|
-
fs3.unlinkSync(
|
|
9152
|
+
fs3.unlinkSync(path11.join(dir, file));
|
|
9005
9153
|
}
|
|
9006
9154
|
}
|
|
9007
9155
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
9008
|
-
const filePath =
|
|
9156
|
+
const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
9009
9157
|
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
9010
9158
|
`, "utf-8");
|
|
9011
9159
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -11342,7 +11490,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
11342
11490
|
// src/commands/chat-commands.ts
|
|
11343
11491
|
import * as fs4 from "fs";
|
|
11344
11492
|
import * as os6 from "os";
|
|
11345
|
-
import * as
|
|
11493
|
+
import * as path12 from "path";
|
|
11346
11494
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
11347
11495
|
|
|
11348
11496
|
// src/providers/provider-input-support.ts
|
|
@@ -11853,7 +12001,7 @@ function buildDebugBundleText(bundle) {
|
|
|
11853
12001
|
}
|
|
11854
12002
|
function getChatDebugBundleDir() {
|
|
11855
12003
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
11856
|
-
return override ||
|
|
12004
|
+
return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
11857
12005
|
}
|
|
11858
12006
|
function safeBundleIdSegment(value, fallback) {
|
|
11859
12007
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -11886,7 +12034,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
11886
12034
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
11887
12035
|
const dir = getChatDebugBundleDir();
|
|
11888
12036
|
fs4.mkdirSync(dir, { recursive: true });
|
|
11889
|
-
const savedPath =
|
|
12037
|
+
const savedPath = path12.join(dir, `${bundleId}.json`);
|
|
11890
12038
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
11891
12039
|
`;
|
|
11892
12040
|
fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -13030,7 +13178,7 @@ async function handleResolveAction(h, args) {
|
|
|
13030
13178
|
|
|
13031
13179
|
// src/commands/cdp-commands.ts
|
|
13032
13180
|
import * as fs5 from "fs";
|
|
13033
|
-
import * as
|
|
13181
|
+
import * as path13 from "path";
|
|
13034
13182
|
import * as os7 from "os";
|
|
13035
13183
|
var KEY_TO_VK = {
|
|
13036
13184
|
Backspace: 8,
|
|
@@ -13287,25 +13435,25 @@ function resolveSafePath(requestedPath) {
|
|
|
13287
13435
|
const inputPath = rawPath || ".";
|
|
13288
13436
|
const home = os7.homedir();
|
|
13289
13437
|
if (inputPath.startsWith("~")) {
|
|
13290
|
-
return
|
|
13438
|
+
return path13.resolve(path13.join(home, inputPath.slice(1)));
|
|
13291
13439
|
}
|
|
13292
13440
|
if (process.platform === "win32") {
|
|
13293
13441
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
13294
|
-
if (
|
|
13295
|
-
return
|
|
13442
|
+
if (path13.win32.isAbsolute(normalized)) {
|
|
13443
|
+
return path13.win32.normalize(normalized);
|
|
13296
13444
|
}
|
|
13297
|
-
return
|
|
13445
|
+
return path13.win32.resolve(normalized);
|
|
13298
13446
|
}
|
|
13299
|
-
if (
|
|
13300
|
-
return
|
|
13447
|
+
if (path13.isAbsolute(inputPath)) {
|
|
13448
|
+
return path13.normalize(inputPath);
|
|
13301
13449
|
}
|
|
13302
|
-
return
|
|
13450
|
+
return path13.resolve(inputPath);
|
|
13303
13451
|
}
|
|
13304
13452
|
function listDirectoryEntriesSafe(dirPath) {
|
|
13305
13453
|
const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
|
|
13306
13454
|
const files = [];
|
|
13307
13455
|
for (const entry of entries) {
|
|
13308
|
-
const entryPath =
|
|
13456
|
+
const entryPath = path13.join(dirPath, entry.name);
|
|
13309
13457
|
try {
|
|
13310
13458
|
if (entry.isDirectory()) {
|
|
13311
13459
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -13359,7 +13507,7 @@ async function handleFileRead(h, args) {
|
|
|
13359
13507
|
async function handleFileWrite(h, args) {
|
|
13360
13508
|
try {
|
|
13361
13509
|
const filePath = resolveSafePath(args?.path);
|
|
13362
|
-
fs5.mkdirSync(
|
|
13510
|
+
fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
13363
13511
|
fs5.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
13364
13512
|
return { success: true, path: filePath };
|
|
13365
13513
|
} catch (e) {
|
|
@@ -14479,16 +14627,16 @@ var DaemonCommandHandler = class {
|
|
|
14479
14627
|
// src/commands/cli-manager.ts
|
|
14480
14628
|
init_provider_cli_adapter();
|
|
14481
14629
|
import * as os13 from "os";
|
|
14482
|
-
import * as
|
|
14630
|
+
import * as path17 from "path";
|
|
14483
14631
|
import * as crypto4 from "crypto";
|
|
14484
|
-
import { existsSync as
|
|
14632
|
+
import { existsSync as existsSync12 } from "fs";
|
|
14485
14633
|
import { execFileSync } from "child_process";
|
|
14486
14634
|
import chalk from "chalk";
|
|
14487
14635
|
init_config();
|
|
14488
14636
|
|
|
14489
14637
|
// src/providers/cli-provider-instance.ts
|
|
14490
14638
|
import * as os12 from "os";
|
|
14491
|
-
import * as
|
|
14639
|
+
import * as path16 from "path";
|
|
14492
14640
|
import * as crypto3 from "crypto";
|
|
14493
14641
|
import * as fs6 from "fs";
|
|
14494
14642
|
import { createRequire } from "module";
|
|
@@ -14547,7 +14695,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
|
|
|
14547
14695
|
var CachedDatabaseSync = null;
|
|
14548
14696
|
function getDatabaseSync() {
|
|
14549
14697
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
14550
|
-
const requireFn = typeof __require === "function" ? __require : createRequire(
|
|
14698
|
+
const requireFn = typeof __require === "function" ? __require : createRequire(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
14551
14699
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
14552
14700
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
14553
14701
|
if (!CachedDatabaseSync) {
|
|
@@ -14600,7 +14748,7 @@ var CliProviderInstance = class {
|
|
|
14600
14748
|
this.providerSessionId = options?.providerSessionId;
|
|
14601
14749
|
this.launchMode = options?.launchMode || "new";
|
|
14602
14750
|
this.onProviderSessionResolved = options?.onProviderSessionResolved;
|
|
14603
|
-
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
14751
|
+
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
|
|
14604
14752
|
this.monitor = new StatusMonitor();
|
|
14605
14753
|
this.historyWriter = new ChatHistoryWriter();
|
|
14606
14754
|
}
|
|
@@ -16618,17 +16766,17 @@ function shouldRestoreHostedRuntime(record, managerTag) {
|
|
|
16618
16766
|
// src/commands/cli-manager.ts
|
|
16619
16767
|
function isExplicitCommand(command) {
|
|
16620
16768
|
const trimmed = command.trim();
|
|
16621
|
-
return
|
|
16769
|
+
return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
16622
16770
|
}
|
|
16623
16771
|
function expandExecutable(command) {
|
|
16624
16772
|
const trimmed = command.trim();
|
|
16625
|
-
return trimmed.startsWith("~") ?
|
|
16773
|
+
return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
|
|
16626
16774
|
}
|
|
16627
16775
|
function commandExists(command) {
|
|
16628
16776
|
const trimmed = command.trim();
|
|
16629
16777
|
if (!trimmed) return false;
|
|
16630
16778
|
if (isExplicitCommand(trimmed)) {
|
|
16631
|
-
return
|
|
16779
|
+
return existsSync12(expandExecutable(trimmed));
|
|
16632
16780
|
}
|
|
16633
16781
|
try {
|
|
16634
16782
|
execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -16816,7 +16964,7 @@ var DaemonCliManager = class {
|
|
|
16816
16964
|
attachExisting
|
|
16817
16965
|
}) || void 0;
|
|
16818
16966
|
}
|
|
16819
|
-
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
|
|
16967
|
+
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
|
|
16820
16968
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
16821
16969
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
16822
16970
|
if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
|
|
@@ -16830,7 +16978,7 @@ var DaemonCliManager = class {
|
|
|
16830
16978
|
providerSessionId,
|
|
16831
16979
|
attachExisting
|
|
16832
16980
|
);
|
|
16833
|
-
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
|
|
16981
|
+
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
|
|
16834
16982
|
}
|
|
16835
16983
|
throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
|
|
16836
16984
|
}
|
|
@@ -16903,7 +17051,7 @@ var DaemonCliManager = class {
|
|
|
16903
17051
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
16904
17052
|
const trimmed = (workingDir || "").trim();
|
|
16905
17053
|
if (!trimmed) throw new Error("working directory required");
|
|
16906
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
17054
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
|
|
16907
17055
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
16908
17056
|
const rawProvider = this.providerLoader.getByAlias(cliType);
|
|
16909
17057
|
const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
|
|
@@ -17033,6 +17181,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17033
17181
|
{
|
|
17034
17182
|
providerSessionId: sessionBinding.providerSessionId,
|
|
17035
17183
|
launchMode: sessionBinding.launchMode,
|
|
17184
|
+
extraEnv: options?.extraEnv,
|
|
17036
17185
|
onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
|
|
17037
17186
|
this.persistRecentActivity({
|
|
17038
17187
|
kind: "cli",
|
|
@@ -17053,7 +17202,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17053
17202
|
resolvedCliArgs,
|
|
17054
17203
|
key,
|
|
17055
17204
|
sessionBinding.providerSessionId,
|
|
17056
|
-
false
|
|
17205
|
+
false,
|
|
17206
|
+
options?.extraEnv
|
|
17057
17207
|
);
|
|
17058
17208
|
try {
|
|
17059
17209
|
await adapter.spawn();
|
|
@@ -17282,7 +17432,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17282
17432
|
dir,
|
|
17283
17433
|
args?.cliArgs,
|
|
17284
17434
|
args?.initialModel,
|
|
17285
|
-
{ resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings }
|
|
17435
|
+
{ resumeSessionId: args?.resumeSessionId, settingsOverride: args?.settings, extraEnv: args?.env }
|
|
17286
17436
|
);
|
|
17287
17437
|
return {
|
|
17288
17438
|
success: true,
|
|
@@ -17404,11 +17554,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17404
17554
|
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
17405
17555
|
import * as net from "net";
|
|
17406
17556
|
import * as os15 from "os";
|
|
17407
|
-
import * as
|
|
17557
|
+
import * as path19 from "path";
|
|
17408
17558
|
|
|
17409
17559
|
// src/providers/provider-loader.ts
|
|
17410
17560
|
import * as fs7 from "fs";
|
|
17411
|
-
import * as
|
|
17561
|
+
import * as path18 from "path";
|
|
17412
17562
|
import * as os14 from "os";
|
|
17413
17563
|
import * as chokidar from "chokidar";
|
|
17414
17564
|
init_logger();
|
|
@@ -17732,7 +17882,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17732
17882
|
try {
|
|
17733
17883
|
if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
|
|
17734
17884
|
return ["ide", "extension", "cli", "acp"].some(
|
|
17735
|
-
(category) => fs7.existsSync(
|
|
17885
|
+
(category) => fs7.existsSync(path18.join(candidate, category))
|
|
17736
17886
|
);
|
|
17737
17887
|
} catch {
|
|
17738
17888
|
return false;
|
|
@@ -17740,20 +17890,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17740
17890
|
}
|
|
17741
17891
|
static hasProviderRootMarker(candidate) {
|
|
17742
17892
|
try {
|
|
17743
|
-
return fs7.existsSync(
|
|
17893
|
+
return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
17744
17894
|
} catch {
|
|
17745
17895
|
return false;
|
|
17746
17896
|
}
|
|
17747
17897
|
}
|
|
17748
17898
|
detectDefaultUserDir() {
|
|
17749
|
-
const fallback =
|
|
17899
|
+
const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17750
17900
|
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
17751
17901
|
const visited = /* @__PURE__ */ new Set();
|
|
17752
17902
|
for (const start of this.probeStarts) {
|
|
17753
|
-
let current =
|
|
17903
|
+
let current = path18.resolve(start);
|
|
17754
17904
|
while (!visited.has(current)) {
|
|
17755
17905
|
visited.add(current);
|
|
17756
|
-
const siblingCandidate =
|
|
17906
|
+
const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
17757
17907
|
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
17758
17908
|
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
17759
17909
|
if (envOptIn || hasMarker) {
|
|
@@ -17775,7 +17925,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17775
17925
|
return { path: siblingCandidate, source };
|
|
17776
17926
|
}
|
|
17777
17927
|
}
|
|
17778
|
-
const parent =
|
|
17928
|
+
const parent = path18.dirname(current);
|
|
17779
17929
|
if (parent === current) break;
|
|
17780
17930
|
current = parent;
|
|
17781
17931
|
}
|
|
@@ -17785,11 +17935,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17785
17935
|
constructor(options) {
|
|
17786
17936
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
17787
17937
|
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
17788
|
-
this.defaultProvidersDir =
|
|
17938
|
+
this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17789
17939
|
const detected = this.detectDefaultUserDir();
|
|
17790
17940
|
this.userDir = detected.path;
|
|
17791
17941
|
this.userDirSource = detected.source;
|
|
17792
|
-
this.upstreamDir =
|
|
17942
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17793
17943
|
this.disableUpstream = false;
|
|
17794
17944
|
this.applySourceConfig({
|
|
17795
17945
|
userDir: options?.userDir,
|
|
@@ -17848,7 +17998,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17848
17998
|
this.userDir = detected.path;
|
|
17849
17999
|
this.userDirSource = detected.source;
|
|
17850
18000
|
}
|
|
17851
|
-
this.upstreamDir =
|
|
18001
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17852
18002
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
17853
18003
|
if (this.explicitProviderDir) {
|
|
17854
18004
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -17862,7 +18012,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17862
18012
|
* Canonical provider directory shape for a given root.
|
|
17863
18013
|
*/
|
|
17864
18014
|
getProviderDir(root, category, type) {
|
|
17865
|
-
return
|
|
18015
|
+
return path18.join(root, category, type);
|
|
17866
18016
|
}
|
|
17867
18017
|
/**
|
|
17868
18018
|
* Canonical user override directory for a provider.
|
|
@@ -17889,7 +18039,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17889
18039
|
resolveProviderFile(type, ...segments) {
|
|
17890
18040
|
const dir = this.findProviderDirInternal(type);
|
|
17891
18041
|
if (!dir) return null;
|
|
17892
|
-
return
|
|
18042
|
+
return path18.join(dir, ...segments);
|
|
17893
18043
|
}
|
|
17894
18044
|
/**
|
|
17895
18045
|
* Load all providers (3-tier priority)
|
|
@@ -17928,7 +18078,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17928
18078
|
if (!fs7.existsSync(this.upstreamDir)) return false;
|
|
17929
18079
|
try {
|
|
17930
18080
|
return fs7.readdirSync(this.upstreamDir).some(
|
|
17931
|
-
(d) => fs7.statSync(
|
|
18081
|
+
(d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
|
|
17932
18082
|
);
|
|
17933
18083
|
} catch {
|
|
17934
18084
|
return false;
|
|
@@ -18425,8 +18575,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18425
18575
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
18426
18576
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
18427
18577
|
if (providerDir) {
|
|
18428
|
-
const fullDir =
|
|
18429
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18578
|
+
const fullDir = path18.join(providerDir, entry.scriptDir);
|
|
18579
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18430
18580
|
}
|
|
18431
18581
|
matched = true;
|
|
18432
18582
|
}
|
|
@@ -18441,8 +18591,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18441
18591
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18442
18592
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
18443
18593
|
if (providerDir) {
|
|
18444
|
-
const fullDir =
|
|
18445
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18594
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18595
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18446
18596
|
}
|
|
18447
18597
|
}
|
|
18448
18598
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -18459,8 +18609,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18459
18609
|
resolved._resolvedScriptDir = dirOverride;
|
|
18460
18610
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
18461
18611
|
if (providerDir) {
|
|
18462
|
-
const fullDir =
|
|
18463
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18612
|
+
const fullDir = path18.join(providerDir, dirOverride);
|
|
18613
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18464
18614
|
}
|
|
18465
18615
|
}
|
|
18466
18616
|
} else if (override.scripts) {
|
|
@@ -18476,8 +18626,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18476
18626
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18477
18627
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
18478
18628
|
if (providerDir) {
|
|
18479
|
-
const fullDir =
|
|
18480
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18629
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18630
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18481
18631
|
}
|
|
18482
18632
|
}
|
|
18483
18633
|
}
|
|
@@ -18509,14 +18659,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18509
18659
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
18510
18660
|
return null;
|
|
18511
18661
|
}
|
|
18512
|
-
const dir =
|
|
18662
|
+
const dir = path18.join(providerDir, scriptDir);
|
|
18513
18663
|
if (!fs7.existsSync(dir)) {
|
|
18514
18664
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
18515
18665
|
return null;
|
|
18516
18666
|
}
|
|
18517
18667
|
const cached = this.scriptsCache.get(dir);
|
|
18518
18668
|
if (cached) return cached;
|
|
18519
|
-
const scriptsJs =
|
|
18669
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
18520
18670
|
if (fs7.existsSync(scriptsJs)) {
|
|
18521
18671
|
try {
|
|
18522
18672
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -18558,7 +18708,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18558
18708
|
return;
|
|
18559
18709
|
}
|
|
18560
18710
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
18561
|
-
this.log(`File changed: ${
|
|
18711
|
+
this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
|
|
18562
18712
|
this.reload();
|
|
18563
18713
|
}
|
|
18564
18714
|
};
|
|
@@ -18613,7 +18763,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18613
18763
|
}
|
|
18614
18764
|
const https = __require("https");
|
|
18615
18765
|
const { execSync: execSync7 } = __require("child_process");
|
|
18616
|
-
const metaPath =
|
|
18766
|
+
const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
18617
18767
|
let prevEtag = "";
|
|
18618
18768
|
let prevTimestamp = 0;
|
|
18619
18769
|
try {
|
|
@@ -18673,17 +18823,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18673
18823
|
return { updated: false };
|
|
18674
18824
|
}
|
|
18675
18825
|
this.log("Downloading latest providers from GitHub...");
|
|
18676
|
-
const tmpTar =
|
|
18677
|
-
const tmpExtract =
|
|
18826
|
+
const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
18827
|
+
const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
18678
18828
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
18679
18829
|
fs7.mkdirSync(tmpExtract, { recursive: true });
|
|
18680
18830
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
18681
18831
|
const extracted = fs7.readdirSync(tmpExtract);
|
|
18682
18832
|
const rootDir = extracted.find(
|
|
18683
|
-
(d) => fs7.statSync(
|
|
18833
|
+
(d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
18684
18834
|
);
|
|
18685
18835
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
18686
|
-
const sourceDir =
|
|
18836
|
+
const sourceDir = path18.join(tmpExtract, rootDir);
|
|
18687
18837
|
const backupDir = this.upstreamDir + ".bak";
|
|
18688
18838
|
if (fs7.existsSync(this.upstreamDir)) {
|
|
18689
18839
|
if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -18758,8 +18908,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18758
18908
|
copyDirRecursive(src, dest) {
|
|
18759
18909
|
fs7.mkdirSync(dest, { recursive: true });
|
|
18760
18910
|
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
18761
|
-
const srcPath =
|
|
18762
|
-
const destPath =
|
|
18911
|
+
const srcPath = path18.join(src, entry.name);
|
|
18912
|
+
const destPath = path18.join(dest, entry.name);
|
|
18763
18913
|
if (entry.isDirectory()) {
|
|
18764
18914
|
this.copyDirRecursive(srcPath, destPath);
|
|
18765
18915
|
} else {
|
|
@@ -18770,7 +18920,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18770
18920
|
/** .meta.json save */
|
|
18771
18921
|
writeMeta(metaPath, etag, timestamp) {
|
|
18772
18922
|
try {
|
|
18773
|
-
fs7.mkdirSync(
|
|
18923
|
+
fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
|
|
18774
18924
|
fs7.writeFileSync(metaPath, JSON.stringify({
|
|
18775
18925
|
etag,
|
|
18776
18926
|
timestamp,
|
|
@@ -18787,7 +18937,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18787
18937
|
const scan = (d) => {
|
|
18788
18938
|
try {
|
|
18789
18939
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
18790
|
-
if (entry.isDirectory()) scan(
|
|
18940
|
+
if (entry.isDirectory()) scan(path18.join(d, entry.name));
|
|
18791
18941
|
else if (entry.name === "provider.json") count++;
|
|
18792
18942
|
}
|
|
18793
18943
|
} catch {
|
|
@@ -19015,17 +19165,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19015
19165
|
for (const root of searchRoots) {
|
|
19016
19166
|
if (!fs7.existsSync(root)) continue;
|
|
19017
19167
|
const candidate = this.getProviderDir(root, cat, type);
|
|
19018
|
-
if (fs7.existsSync(
|
|
19019
|
-
const catDir =
|
|
19168
|
+
if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
|
|
19169
|
+
const catDir = path18.join(root, cat);
|
|
19020
19170
|
if (fs7.existsSync(catDir)) {
|
|
19021
19171
|
try {
|
|
19022
19172
|
for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
|
|
19023
19173
|
if (!entry.isDirectory()) continue;
|
|
19024
|
-
const jsonPath =
|
|
19174
|
+
const jsonPath = path18.join(catDir, entry.name, "provider.json");
|
|
19025
19175
|
if (fs7.existsSync(jsonPath)) {
|
|
19026
19176
|
try {
|
|
19027
19177
|
const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
|
|
19028
|
-
if (data.type === type) return
|
|
19178
|
+
if (data.type === type) return path18.join(catDir, entry.name);
|
|
19029
19179
|
} catch {
|
|
19030
19180
|
}
|
|
19031
19181
|
}
|
|
@@ -19042,7 +19192,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19042
19192
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
19043
19193
|
*/
|
|
19044
19194
|
buildScriptWrappersFromDir(dir) {
|
|
19045
|
-
const scriptsJs =
|
|
19195
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
19046
19196
|
if (fs7.existsSync(scriptsJs)) {
|
|
19047
19197
|
try {
|
|
19048
19198
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -19056,7 +19206,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19056
19206
|
for (const file of fs7.readdirSync(dir)) {
|
|
19057
19207
|
if (!file.endsWith(".js")) continue;
|
|
19058
19208
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
19059
|
-
const filePath =
|
|
19209
|
+
const filePath = path18.join(dir, file);
|
|
19060
19210
|
result[scriptName] = (...args) => {
|
|
19061
19211
|
try {
|
|
19062
19212
|
let content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -19116,7 +19266,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19116
19266
|
}
|
|
19117
19267
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
19118
19268
|
if (hasJson) {
|
|
19119
|
-
const jsonPath =
|
|
19269
|
+
const jsonPath = path18.join(d, "provider.json");
|
|
19120
19270
|
try {
|
|
19121
19271
|
const raw = fs7.readFileSync(jsonPath, "utf-8");
|
|
19122
19272
|
const mod = JSON.parse(raw);
|
|
@@ -19137,7 +19287,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19137
19287
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
19138
19288
|
} else {
|
|
19139
19289
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
19140
|
-
const scriptsPath =
|
|
19290
|
+
const scriptsPath = path18.join(d, "scripts.js");
|
|
19141
19291
|
if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
|
|
19142
19292
|
try {
|
|
19143
19293
|
delete __require.cache[__require.resolve(scriptsPath)];
|
|
@@ -19163,7 +19313,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19163
19313
|
if (!entry.isDirectory()) continue;
|
|
19164
19314
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
19165
19315
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
19166
|
-
scan(
|
|
19316
|
+
scan(path18.join(d, entry.name));
|
|
19167
19317
|
}
|
|
19168
19318
|
}
|
|
19169
19319
|
};
|
|
@@ -19488,8 +19638,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
19488
19638
|
const appNameMap = getMacAppIdentifiers();
|
|
19489
19639
|
const appName = appNameMap[ideId];
|
|
19490
19640
|
if (appName) {
|
|
19491
|
-
const storagePath =
|
|
19492
|
-
process.env.APPDATA ||
|
|
19641
|
+
const storagePath = path19.join(
|
|
19642
|
+
process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
|
|
19493
19643
|
appName,
|
|
19494
19644
|
"storage.json"
|
|
19495
19645
|
);
|
|
@@ -19678,9 +19828,9 @@ init_logger();
|
|
|
19678
19828
|
|
|
19679
19829
|
// src/logging/command-log.ts
|
|
19680
19830
|
import * as fs8 from "fs";
|
|
19681
|
-
import * as
|
|
19831
|
+
import * as path20 from "path";
|
|
19682
19832
|
import * as os16 from "os";
|
|
19683
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
19833
|
+
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");
|
|
19684
19834
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
19685
19835
|
var MAX_DAYS = 7;
|
|
19686
19836
|
try {
|
|
@@ -19718,13 +19868,13 @@ function getDateStr2() {
|
|
|
19718
19868
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
19719
19869
|
}
|
|
19720
19870
|
var currentDate2 = getDateStr2();
|
|
19721
|
-
var currentFile =
|
|
19871
|
+
var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19722
19872
|
var writeCount2 = 0;
|
|
19723
19873
|
function checkRotation() {
|
|
19724
19874
|
const today = getDateStr2();
|
|
19725
19875
|
if (today !== currentDate2) {
|
|
19726
19876
|
currentDate2 = today;
|
|
19727
|
-
currentFile =
|
|
19877
|
+
currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19728
19878
|
cleanOldFiles();
|
|
19729
19879
|
}
|
|
19730
19880
|
}
|
|
@@ -19738,7 +19888,7 @@ function cleanOldFiles() {
|
|
|
19738
19888
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
19739
19889
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
19740
19890
|
try {
|
|
19741
|
-
fs8.unlinkSync(
|
|
19891
|
+
fs8.unlinkSync(path20.join(LOG_DIR2, file));
|
|
19742
19892
|
} catch {
|
|
19743
19893
|
}
|
|
19744
19894
|
}
|
|
@@ -19822,11 +19972,13 @@ cleanOldFiles();
|
|
|
19822
19972
|
|
|
19823
19973
|
// src/commands/router.ts
|
|
19824
19974
|
init_logger();
|
|
19975
|
+
import * as yaml from "js-yaml";
|
|
19825
19976
|
|
|
19826
19977
|
// src/commands/mesh-coordinator.ts
|
|
19827
|
-
import { existsSync as
|
|
19978
|
+
import { existsSync as existsSync15, realpathSync as realpathSync2 } from "fs";
|
|
19828
19979
|
import { createRequire as createRequire2 } from "module";
|
|
19829
|
-
import
|
|
19980
|
+
import * as os17 from "os";
|
|
19981
|
+
import { dirname as dirname4, isAbsolute as isAbsolute10, join as join18, resolve as resolve13 } from "path";
|
|
19830
19982
|
var DEFAULT_SERVER_NAME = "adhdev-mesh";
|
|
19831
19983
|
var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
19832
19984
|
function resolveMeshCoordinatorSetup(options) {
|
|
@@ -19847,8 +19999,8 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
19847
19999
|
}
|
|
19848
20000
|
const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
|
|
19849
20001
|
if (mcpConfig.mode === "auto_import") {
|
|
19850
|
-
const
|
|
19851
|
-
if (!
|
|
20002
|
+
const path27 = mcpConfig.path?.trim();
|
|
20003
|
+
if (!path27) {
|
|
19852
20004
|
return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
|
|
19853
20005
|
}
|
|
19854
20006
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
@@ -19865,7 +20017,7 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
19865
20017
|
return {
|
|
19866
20018
|
kind: "auto_import",
|
|
19867
20019
|
serverName,
|
|
19868
|
-
configPath:
|
|
20020
|
+
configPath: resolveMcpConfigPath(path27, workspace),
|
|
19869
20021
|
configFormat: mcpConfig.format,
|
|
19870
20022
|
mcpServer
|
|
19871
20023
|
};
|
|
@@ -19899,6 +20051,13 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
19899
20051
|
function renderMeshCoordinatorTemplate(template, values) {
|
|
19900
20052
|
return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
|
|
19901
20053
|
}
|
|
20054
|
+
function resolveMcpConfigPath(configPath, workspace) {
|
|
20055
|
+
const trimmed = configPath.trim();
|
|
20056
|
+
if (trimmed === "~") return os17.homedir();
|
|
20057
|
+
if (trimmed.startsWith("~/")) return join18(os17.homedir(), trimmed.slice(2));
|
|
20058
|
+
if (isAbsolute10(trimmed)) return trimmed;
|
|
20059
|
+
return join18(workspace, trimmed);
|
|
20060
|
+
}
|
|
19902
20061
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
19903
20062
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
19904
20063
|
if (!entryPath) return null;
|
|
@@ -19919,7 +20078,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
19919
20078
|
const addPackagedCandidates = (baseFile) => {
|
|
19920
20079
|
if (!baseFile) return;
|
|
19921
20080
|
const realBase = normalizeExistingPath(baseFile) || baseFile;
|
|
19922
|
-
const dir =
|
|
20081
|
+
const dir = dirname4(realBase);
|
|
19923
20082
|
addCandidate(resolve13(dir, "../vendor/mcp-server/index.js"));
|
|
19924
20083
|
addCandidate(resolve13(dir, "../../vendor/mcp-server/index.js"));
|
|
19925
20084
|
addCandidate(resolve13(dir, "../../../vendor/mcp-server/index.js"));
|
|
@@ -19932,7 +20091,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
19932
20091
|
if (normalized) return normalized;
|
|
19933
20092
|
}
|
|
19934
20093
|
try {
|
|
19935
|
-
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] :
|
|
20094
|
+
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join18(process.cwd(), "adhdev-daemon.js");
|
|
19936
20095
|
const req = createRequire2(requireBase);
|
|
19937
20096
|
const resolvedModule = req.resolve("@adhdev/mcp-server");
|
|
19938
20097
|
return normalizeExistingPath(resolvedModule) || resolvedModule;
|
|
@@ -19942,7 +20101,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
19942
20101
|
}
|
|
19943
20102
|
function normalizeExistingPath(filePath) {
|
|
19944
20103
|
try {
|
|
19945
|
-
if (!
|
|
20104
|
+
if (!existsSync15(filePath)) return null;
|
|
19946
20105
|
return realpathSync2.native(filePath);
|
|
19947
20106
|
} catch {
|
|
19948
20107
|
return null;
|
|
@@ -19951,7 +20110,7 @@ function normalizeExistingPath(filePath) {
|
|
|
19951
20110
|
|
|
19952
20111
|
// src/status/snapshot.ts
|
|
19953
20112
|
init_config();
|
|
19954
|
-
import * as
|
|
20113
|
+
import * as os18 from "os";
|
|
19955
20114
|
init_terminal_screen();
|
|
19956
20115
|
init_logger();
|
|
19957
20116
|
var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
|
|
@@ -20006,8 +20165,8 @@ function buildAvailableProviders(providerLoader) {
|
|
|
20006
20165
|
}
|
|
20007
20166
|
function buildMachineInfo(profile = "full") {
|
|
20008
20167
|
const base = {
|
|
20009
|
-
hostname:
|
|
20010
|
-
platform:
|
|
20168
|
+
hostname: os18.hostname(),
|
|
20169
|
+
platform: os18.platform()
|
|
20011
20170
|
};
|
|
20012
20171
|
if (profile === "live") {
|
|
20013
20172
|
return base;
|
|
@@ -20016,23 +20175,23 @@ function buildMachineInfo(profile = "full") {
|
|
|
20016
20175
|
const memSnap2 = getHostMemorySnapshot();
|
|
20017
20176
|
return {
|
|
20018
20177
|
...base,
|
|
20019
|
-
arch:
|
|
20020
|
-
cpus:
|
|
20178
|
+
arch: os18.arch(),
|
|
20179
|
+
cpus: os18.cpus().length,
|
|
20021
20180
|
totalMem: memSnap2.totalMem,
|
|
20022
|
-
release:
|
|
20181
|
+
release: os18.release()
|
|
20023
20182
|
};
|
|
20024
20183
|
}
|
|
20025
20184
|
const memSnap = getHostMemorySnapshot();
|
|
20026
20185
|
return {
|
|
20027
20186
|
...base,
|
|
20028
|
-
arch:
|
|
20029
|
-
cpus:
|
|
20187
|
+
arch: os18.arch(),
|
|
20188
|
+
cpus: os18.cpus().length,
|
|
20030
20189
|
totalMem: memSnap.totalMem,
|
|
20031
20190
|
freeMem: memSnap.freeMem,
|
|
20032
20191
|
availableMem: memSnap.availableMem,
|
|
20033
|
-
loadavg:
|
|
20034
|
-
uptime:
|
|
20035
|
-
release:
|
|
20192
|
+
loadavg: os18.loadavg(),
|
|
20193
|
+
uptime: os18.uptime(),
|
|
20194
|
+
release: os18.release()
|
|
20036
20195
|
};
|
|
20037
20196
|
}
|
|
20038
20197
|
function parseMessageTime(value) {
|
|
@@ -20266,14 +20425,14 @@ function buildStatusSnapshot(options) {
|
|
|
20266
20425
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
20267
20426
|
import { spawn as spawn3 } from "child_process";
|
|
20268
20427
|
import * as fs9 from "fs";
|
|
20269
|
-
import * as
|
|
20270
|
-
import * as
|
|
20428
|
+
import * as os19 from "os";
|
|
20429
|
+
import * as path21 from "path";
|
|
20271
20430
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
20272
20431
|
function getUpgradeLogPath() {
|
|
20273
|
-
const home =
|
|
20274
|
-
const dir =
|
|
20432
|
+
const home = os19.homedir();
|
|
20433
|
+
const dir = path21.join(home, ".adhdev");
|
|
20275
20434
|
fs9.mkdirSync(dir, { recursive: true });
|
|
20276
|
-
return
|
|
20435
|
+
return path21.join(dir, "daemon-upgrade.log");
|
|
20277
20436
|
}
|
|
20278
20437
|
function appendUpgradeLog(message) {
|
|
20279
20438
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -20284,14 +20443,14 @@ function appendUpgradeLog(message) {
|
|
|
20284
20443
|
}
|
|
20285
20444
|
}
|
|
20286
20445
|
function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
|
|
20287
|
-
const binDir =
|
|
20446
|
+
const binDir = path21.dirname(nodeExecutable);
|
|
20288
20447
|
if (platform10 === "win32") {
|
|
20289
|
-
const npmCliPath =
|
|
20448
|
+
const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
20290
20449
|
if (fs9.existsSync(npmCliPath)) {
|
|
20291
20450
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20292
20451
|
}
|
|
20293
20452
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
20294
|
-
const candidatePath =
|
|
20453
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20295
20454
|
if (fs9.existsSync(candidatePath)) {
|
|
20296
20455
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20297
20456
|
}
|
|
@@ -20299,7 +20458,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
20299
20458
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20300
20459
|
}
|
|
20301
20460
|
for (const candidate of ["npm"]) {
|
|
20302
|
-
const candidatePath =
|
|
20461
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20303
20462
|
if (fs9.existsSync(candidatePath)) {
|
|
20304
20463
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20305
20464
|
}
|
|
@@ -20316,13 +20475,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20316
20475
|
let currentDir = resolvedPath;
|
|
20317
20476
|
try {
|
|
20318
20477
|
if (fs9.statSync(resolvedPath).isFile()) {
|
|
20319
|
-
currentDir =
|
|
20478
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20320
20479
|
}
|
|
20321
20480
|
} catch {
|
|
20322
|
-
currentDir =
|
|
20481
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20323
20482
|
}
|
|
20324
20483
|
while (true) {
|
|
20325
|
-
const packageJsonPath =
|
|
20484
|
+
const packageJsonPath = path21.join(currentDir, "package.json");
|
|
20326
20485
|
try {
|
|
20327
20486
|
if (fs9.existsSync(packageJsonPath)) {
|
|
20328
20487
|
const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -20333,7 +20492,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20333
20492
|
}
|
|
20334
20493
|
} catch {
|
|
20335
20494
|
}
|
|
20336
|
-
const parentDir =
|
|
20495
|
+
const parentDir = path21.dirname(currentDir);
|
|
20337
20496
|
if (parentDir === currentDir) {
|
|
20338
20497
|
return null;
|
|
20339
20498
|
}
|
|
@@ -20341,13 +20500,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20341
20500
|
}
|
|
20342
20501
|
}
|
|
20343
20502
|
function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
|
|
20344
|
-
const nodeModulesDir = packageName.startsWith("@") ?
|
|
20345
|
-
if (
|
|
20503
|
+
const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
|
|
20504
|
+
if (path21.basename(nodeModulesDir) !== "node_modules") {
|
|
20346
20505
|
return null;
|
|
20347
20506
|
}
|
|
20348
|
-
const maybeLibDir =
|
|
20349
|
-
if (
|
|
20350
|
-
return
|
|
20507
|
+
const maybeLibDir = path21.dirname(nodeModulesDir);
|
|
20508
|
+
if (path21.basename(maybeLibDir) === "lib") {
|
|
20509
|
+
return path21.dirname(maybeLibDir);
|
|
20351
20510
|
}
|
|
20352
20511
|
return maybeLibDir;
|
|
20353
20512
|
}
|
|
@@ -20462,7 +20621,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
20462
20621
|
}
|
|
20463
20622
|
}
|
|
20464
20623
|
function stopSessionHostProcesses(appName) {
|
|
20465
|
-
const pidFile =
|
|
20624
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
20466
20625
|
try {
|
|
20467
20626
|
if (fs9.existsSync(pidFile)) {
|
|
20468
20627
|
const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -20479,7 +20638,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
20479
20638
|
}
|
|
20480
20639
|
}
|
|
20481
20640
|
function removeDaemonPidFile() {
|
|
20482
|
-
const pidFile =
|
|
20641
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
|
|
20483
20642
|
try {
|
|
20484
20643
|
fs9.unlinkSync(pidFile);
|
|
20485
20644
|
} catch {
|
|
@@ -20490,7 +20649,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20490
20649
|
const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20491
20650
|
if (!npmRoot) return;
|
|
20492
20651
|
const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20493
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
20652
|
+
const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
|
|
20494
20653
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
20495
20654
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
20496
20655
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -20498,25 +20657,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20498
20657
|
}
|
|
20499
20658
|
if (pkgName.startsWith("@")) {
|
|
20500
20659
|
const [scope, name] = pkgName.split("/");
|
|
20501
|
-
const scopeDir =
|
|
20660
|
+
const scopeDir = path21.join(npmRoot, scope);
|
|
20502
20661
|
if (!fs9.existsSync(scopeDir)) return;
|
|
20503
20662
|
for (const entry of fs9.readdirSync(scopeDir)) {
|
|
20504
20663
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
20505
|
-
fs9.rmSync(
|
|
20506
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
20664
|
+
fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
|
|
20665
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
|
|
20507
20666
|
}
|
|
20508
20667
|
} else {
|
|
20509
20668
|
for (const entry of fs9.readdirSync(npmRoot)) {
|
|
20510
20669
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
20511
|
-
fs9.rmSync(
|
|
20512
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
20670
|
+
fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
|
|
20671
|
+
appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
|
|
20513
20672
|
}
|
|
20514
20673
|
}
|
|
20515
20674
|
if (fs9.existsSync(binDir)) {
|
|
20516
20675
|
for (const entry of fs9.readdirSync(binDir)) {
|
|
20517
20676
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
20518
|
-
fs9.rmSync(
|
|
20519
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
20677
|
+
fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
|
|
20678
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
|
|
20520
20679
|
}
|
|
20521
20680
|
}
|
|
20522
20681
|
}
|
|
@@ -20617,6 +20776,22 @@ function normalizeReleaseChannel(value) {
|
|
|
20617
20776
|
function resolveUpgradeChannel(args) {
|
|
20618
20777
|
return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
|
|
20619
20778
|
}
|
|
20779
|
+
function loadYamlModule() {
|
|
20780
|
+
return yaml;
|
|
20781
|
+
}
|
|
20782
|
+
function getMcpServersKey(format) {
|
|
20783
|
+
return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
|
|
20784
|
+
}
|
|
20785
|
+
function parseMeshCoordinatorMcpConfig(text, format) {
|
|
20786
|
+
if (!text.trim()) return {};
|
|
20787
|
+
if (format === "claude_mcp_json") return JSON.parse(text);
|
|
20788
|
+
const parsed = loadYamlModule().load(text);
|
|
20789
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
20790
|
+
}
|
|
20791
|
+
function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
20792
|
+
if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
|
|
20793
|
+
return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
|
|
20794
|
+
}
|
|
20620
20795
|
var CHAT_COMMANDS = [
|
|
20621
20796
|
"send_chat",
|
|
20622
20797
|
"new_chat",
|
|
@@ -20715,6 +20890,40 @@ var DaemonCommandRouter = class {
|
|
|
20715
20890
|
constructor(deps) {
|
|
20716
20891
|
this.deps = deps;
|
|
20717
20892
|
}
|
|
20893
|
+
getCachedInlineMesh(meshId, inlineMesh) {
|
|
20894
|
+
if (inlineMesh && typeof inlineMesh === "object") {
|
|
20895
|
+
this.inlineMeshCache.set(meshId, inlineMesh);
|
|
20896
|
+
return inlineMesh;
|
|
20897
|
+
}
|
|
20898
|
+
return this.inlineMeshCache.get(meshId);
|
|
20899
|
+
}
|
|
20900
|
+
async getMeshForCommand(meshId, inlineMesh) {
|
|
20901
|
+
try {
|
|
20902
|
+
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
20903
|
+
const mesh = getMesh3(meshId);
|
|
20904
|
+
if (mesh) return { mesh, inline: false };
|
|
20905
|
+
} catch {
|
|
20906
|
+
}
|
|
20907
|
+
const cached = this.getCachedInlineMesh(meshId, inlineMesh);
|
|
20908
|
+
return cached ? { mesh: cached, inline: true } : null;
|
|
20909
|
+
}
|
|
20910
|
+
updateInlineMeshNode(meshId, mesh, node) {
|
|
20911
|
+
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
20912
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
|
|
20913
|
+
if (idx >= 0) mesh.nodes[idx] = node;
|
|
20914
|
+
else mesh.nodes.push(node);
|
|
20915
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20916
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
20917
|
+
}
|
|
20918
|
+
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
20919
|
+
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
20920
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
|
|
20921
|
+
if (idx === -1) return false;
|
|
20922
|
+
mesh.nodes.splice(idx, 1);
|
|
20923
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20924
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
20925
|
+
return true;
|
|
20926
|
+
}
|
|
20718
20927
|
async traceSessionHostAction(action, args, run, summarizeResult) {
|
|
20719
20928
|
const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
|
|
20720
20929
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
|
|
@@ -21414,13 +21623,94 @@ var DaemonCommandRouter = class {
|
|
|
21414
21623
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
21415
21624
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
21416
21625
|
try {
|
|
21417
|
-
const
|
|
21418
|
-
const
|
|
21626
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
21627
|
+
const mesh = meshRecord?.mesh;
|
|
21628
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
21629
|
+
if (node?.isLocalWorktree && node.workspace) {
|
|
21630
|
+
try {
|
|
21631
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
21632
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
21633
|
+
if (repoRoot) {
|
|
21634
|
+
const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
21635
|
+
await removeWorktree2(repoRoot, node.workspace);
|
|
21636
|
+
}
|
|
21637
|
+
} catch (e) {
|
|
21638
|
+
LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
|
|
21639
|
+
}
|
|
21640
|
+
}
|
|
21641
|
+
let removed = false;
|
|
21642
|
+
if (meshRecord?.inline) {
|
|
21643
|
+
removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
|
|
21644
|
+
} else {
|
|
21645
|
+
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21646
|
+
removed = removeNode3(meshId, nodeId);
|
|
21647
|
+
}
|
|
21419
21648
|
return { success: true, removed };
|
|
21420
21649
|
} catch (e) {
|
|
21421
21650
|
return { success: false, error: e.message };
|
|
21422
21651
|
}
|
|
21423
21652
|
}
|
|
21653
|
+
case "clone_mesh_node": {
|
|
21654
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
21655
|
+
const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
|
|
21656
|
+
const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
|
|
21657
|
+
const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
|
|
21658
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
21659
|
+
if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
|
|
21660
|
+
if (!branch) return { success: false, error: "branch required" };
|
|
21661
|
+
try {
|
|
21662
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
21663
|
+
const mesh = meshRecord?.mesh;
|
|
21664
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
21665
|
+
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
21666
|
+
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
21667
|
+
const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
|
|
21668
|
+
const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
21669
|
+
const result = await createWorktree2({
|
|
21670
|
+
repoRoot,
|
|
21671
|
+
branch,
|
|
21672
|
+
baseBranch,
|
|
21673
|
+
meshName: mesh.name
|
|
21674
|
+
});
|
|
21675
|
+
let node;
|
|
21676
|
+
if (meshRecord.inline) {
|
|
21677
|
+
const { randomUUID: randomUUID8 } = await import("crypto");
|
|
21678
|
+
node = {
|
|
21679
|
+
id: `node_${randomUUID8().replace(/-/g, "")}`,
|
|
21680
|
+
workspace: result.worktreePath,
|
|
21681
|
+
repoRoot: result.worktreePath,
|
|
21682
|
+
daemonId: sourceNode.daemonId,
|
|
21683
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
21684
|
+
policy: { ...sourceNode.policy || {} },
|
|
21685
|
+
isLocalWorktree: true,
|
|
21686
|
+
worktreeBranch: result.branch,
|
|
21687
|
+
clonedFromNodeId: sourceNodeId
|
|
21688
|
+
};
|
|
21689
|
+
this.updateInlineMeshNode(meshId, mesh, node);
|
|
21690
|
+
} else {
|
|
21691
|
+
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21692
|
+
node = addNode3(meshId, {
|
|
21693
|
+
workspace: result.worktreePath,
|
|
21694
|
+
repoRoot: result.worktreePath,
|
|
21695
|
+
daemonId: sourceNode.daemonId,
|
|
21696
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
21697
|
+
isLocalWorktree: true,
|
|
21698
|
+
worktreeBranch: result.branch,
|
|
21699
|
+
clonedFromNodeId: sourceNodeId,
|
|
21700
|
+
policy: { ...sourceNode.policy || {} }
|
|
21701
|
+
});
|
|
21702
|
+
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
21703
|
+
}
|
|
21704
|
+
return {
|
|
21705
|
+
success: true,
|
|
21706
|
+
node,
|
|
21707
|
+
worktreePath: result.worktreePath,
|
|
21708
|
+
branch: result.branch
|
|
21709
|
+
};
|
|
21710
|
+
} catch (e) {
|
|
21711
|
+
return { success: false, error: e.message };
|
|
21712
|
+
}
|
|
21713
|
+
}
|
|
21424
21714
|
// ─── Mesh Coordinator Launch ───
|
|
21425
21715
|
case "launch_mesh_coordinator": {
|
|
21426
21716
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -21479,7 +21769,8 @@ var DaemonCommandRouter = class {
|
|
|
21479
21769
|
meshCoordinatorSetup: coordinatorSetup
|
|
21480
21770
|
};
|
|
21481
21771
|
}
|
|
21482
|
-
|
|
21772
|
+
const configFormat = coordinatorSetup.configFormat;
|
|
21773
|
+
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
21483
21774
|
return {
|
|
21484
21775
|
success: false,
|
|
21485
21776
|
code: "mesh_coordinator_unsupported",
|
|
@@ -21489,15 +21780,38 @@ var DaemonCommandRouter = class {
|
|
|
21489
21780
|
workspace
|
|
21490
21781
|
};
|
|
21491
21782
|
}
|
|
21492
|
-
|
|
21783
|
+
let systemPrompt = "";
|
|
21784
|
+
try {
|
|
21785
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
21786
|
+
} catch (error) {
|
|
21787
|
+
const message = error?.message || String(error);
|
|
21788
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
21789
|
+
return {
|
|
21790
|
+
success: false,
|
|
21791
|
+
code: "mesh_coordinator_prompt_failed",
|
|
21792
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
21793
|
+
meshId,
|
|
21794
|
+
cliType,
|
|
21795
|
+
workspace
|
|
21796
|
+
};
|
|
21797
|
+
}
|
|
21798
|
+
const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3, mkdirSync: mkdirSync14 } = await import("fs");
|
|
21799
|
+
const { dirname: dirname9 } = await import("path");
|
|
21493
21800
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
21494
|
-
|
|
21801
|
+
mkdirSync14(dirname9(mcpConfigPath), { recursive: true });
|
|
21802
|
+
const hadExistingMcpConfig = existsSync23(mcpConfigPath);
|
|
21495
21803
|
let existingMcpConfig = {};
|
|
21496
21804
|
if (hadExistingMcpConfig) {
|
|
21497
21805
|
try {
|
|
21498
|
-
existingMcpConfig =
|
|
21806
|
+
existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
|
|
21499
21807
|
copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
|
|
21500
|
-
} catch {
|
|
21808
|
+
} catch (error) {
|
|
21809
|
+
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
21810
|
+
return {
|
|
21811
|
+
success: false,
|
|
21812
|
+
code: "mesh_coordinator_config_parse_failed",
|
|
21813
|
+
error: `Failed to parse existing MCP config at ${mcpConfigPath}`
|
|
21814
|
+
};
|
|
21501
21815
|
}
|
|
21502
21816
|
}
|
|
21503
21817
|
const mcpServerEntry = {
|
|
@@ -21510,24 +21824,25 @@ var DaemonCommandRouter = class {
|
|
|
21510
21824
|
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
21511
21825
|
};
|
|
21512
21826
|
}
|
|
21827
|
+
const mcpServersKey = getMcpServersKey(configFormat);
|
|
21828
|
+
const existingServers = existingMcpConfig[mcpServersKey];
|
|
21513
21829
|
const mcpConfig = {
|
|
21514
21830
|
...existingMcpConfig,
|
|
21515
|
-
|
|
21516
|
-
...
|
|
21831
|
+
[mcpServersKey]: {
|
|
21832
|
+
...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
|
|
21517
21833
|
[coordinatorSetup.serverName]: mcpServerEntry
|
|
21518
21834
|
}
|
|
21519
21835
|
};
|
|
21520
|
-
writeFileSync12(mcpConfigPath,
|
|
21836
|
+
writeFileSync12(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
21521
21837
|
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21522
|
-
let systemPrompt = "";
|
|
21523
|
-
try {
|
|
21524
|
-
systemPrompt = buildCoordinatorSystemPrompt2({ mesh });
|
|
21525
|
-
} catch {
|
|
21526
|
-
systemPrompt = `You are a Repo Mesh Coordinator for "${mesh.name}". Use the adhdev-mesh MCP tools (mesh_status, mesh_list_nodes, mesh_send_task, mesh_read_chat, mesh_launch_session, etc.) to orchestrate work across ${mesh.nodes.length} node(s).`;
|
|
21527
|
-
}
|
|
21528
21838
|
const cliArgs = [];
|
|
21839
|
+
const launchEnv = {};
|
|
21529
21840
|
if (systemPrompt) {
|
|
21530
|
-
|
|
21841
|
+
if (configFormat === "hermes_config_yaml") {
|
|
21842
|
+
launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
|
|
21843
|
+
} else {
|
|
21844
|
+
cliArgs.push("--append-system-prompt", systemPrompt);
|
|
21845
|
+
}
|
|
21531
21846
|
}
|
|
21532
21847
|
if (cliType === "claude-cli") {
|
|
21533
21848
|
cliArgs.push("--mcp-config", coordinatorSetup.configPath);
|
|
@@ -21536,6 +21851,7 @@ var DaemonCommandRouter = class {
|
|
|
21536
21851
|
cliType,
|
|
21537
21852
|
dir: workspace,
|
|
21538
21853
|
cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
|
|
21854
|
+
env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
|
|
21539
21855
|
settings: {
|
|
21540
21856
|
meshCoordinatorFor: meshId
|
|
21541
21857
|
}
|
|
@@ -23196,11 +23512,11 @@ var ProviderInstanceManager = class {
|
|
|
23196
23512
|
|
|
23197
23513
|
// src/providers/version-archive.ts
|
|
23198
23514
|
import * as fs11 from "fs";
|
|
23199
|
-
import * as
|
|
23200
|
-
import * as
|
|
23515
|
+
import * as path22 from "path";
|
|
23516
|
+
import * as os20 from "os";
|
|
23201
23517
|
import { execSync as execSync5 } from "child_process";
|
|
23202
23518
|
import { platform as platform8 } from "os";
|
|
23203
|
-
var ARCHIVE_PATH =
|
|
23519
|
+
var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
|
|
23204
23520
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
23205
23521
|
var VersionArchive = class {
|
|
23206
23522
|
history = {};
|
|
@@ -23247,7 +23563,7 @@ var VersionArchive = class {
|
|
|
23247
23563
|
}
|
|
23248
23564
|
save() {
|
|
23249
23565
|
try {
|
|
23250
|
-
fs11.mkdirSync(
|
|
23566
|
+
fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
|
|
23251
23567
|
fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
23252
23568
|
} catch {
|
|
23253
23569
|
}
|
|
@@ -23303,8 +23619,8 @@ function getVersion(binary, versionCommand) {
|
|
|
23303
23619
|
function checkPathExists2(paths) {
|
|
23304
23620
|
for (const p of paths) {
|
|
23305
23621
|
if (p.includes("*")) {
|
|
23306
|
-
const home =
|
|
23307
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
23622
|
+
const home = os20.homedir();
|
|
23623
|
+
const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
|
|
23308
23624
|
if (fs11.existsSync(resolved)) return resolved;
|
|
23309
23625
|
} else {
|
|
23310
23626
|
if (fs11.existsSync(p)) return p;
|
|
@@ -23314,7 +23630,7 @@ function checkPathExists2(paths) {
|
|
|
23314
23630
|
}
|
|
23315
23631
|
function getMacAppVersion(appPath) {
|
|
23316
23632
|
if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
23317
|
-
const plistPath =
|
|
23633
|
+
const plistPath = path22.join(appPath, "Contents", "Info.plist");
|
|
23318
23634
|
if (!fs11.existsSync(plistPath)) return null;
|
|
23319
23635
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
23320
23636
|
return raw || null;
|
|
@@ -23340,7 +23656,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23340
23656
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
23341
23657
|
let resolvedBin = cliBin;
|
|
23342
23658
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
23343
|
-
const bundled =
|
|
23659
|
+
const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
23344
23660
|
if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
|
|
23345
23661
|
}
|
|
23346
23662
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -23381,7 +23697,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23381
23697
|
// src/daemon/dev-server.ts
|
|
23382
23698
|
import * as http2 from "http";
|
|
23383
23699
|
import * as fs15 from "fs";
|
|
23384
|
-
import * as
|
|
23700
|
+
import * as path26 from "path";
|
|
23385
23701
|
init_config();
|
|
23386
23702
|
|
|
23387
23703
|
// src/daemon/scaffold-template.ts
|
|
@@ -23733,7 +24049,7 @@ init_logger();
|
|
|
23733
24049
|
// src/daemon/dev-cdp-handlers.ts
|
|
23734
24050
|
init_logger();
|
|
23735
24051
|
import * as fs12 from "fs";
|
|
23736
|
-
import * as
|
|
24052
|
+
import * as path23 from "path";
|
|
23737
24053
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
23738
24054
|
const body = await ctx.readBody(req);
|
|
23739
24055
|
const { expression, timeout, ideType } = body;
|
|
@@ -23911,17 +24227,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
23911
24227
|
return;
|
|
23912
24228
|
}
|
|
23913
24229
|
let scriptsPath = "";
|
|
23914
|
-
const directScripts =
|
|
24230
|
+
const directScripts = path23.join(dir, "scripts.js");
|
|
23915
24231
|
if (fs12.existsSync(directScripts)) {
|
|
23916
24232
|
scriptsPath = directScripts;
|
|
23917
24233
|
} else {
|
|
23918
|
-
const scriptsDir =
|
|
24234
|
+
const scriptsDir = path23.join(dir, "scripts");
|
|
23919
24235
|
if (fs12.existsSync(scriptsDir)) {
|
|
23920
24236
|
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
23921
|
-
return fs12.statSync(
|
|
24237
|
+
return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
|
|
23922
24238
|
}).sort().reverse();
|
|
23923
24239
|
for (const ver of versions) {
|
|
23924
|
-
const p =
|
|
24240
|
+
const p = path23.join(scriptsDir, ver, "scripts.js");
|
|
23925
24241
|
if (fs12.existsSync(p)) {
|
|
23926
24242
|
scriptsPath = p;
|
|
23927
24243
|
break;
|
|
@@ -24750,7 +25066,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
24750
25066
|
|
|
24751
25067
|
// src/daemon/dev-cli-debug.ts
|
|
24752
25068
|
import * as fs13 from "fs";
|
|
24753
|
-
import * as
|
|
25069
|
+
import * as path24 from "path";
|
|
24754
25070
|
function slugifyFixtureName(value) {
|
|
24755
25071
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
24756
25072
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -24760,11 +25076,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
24760
25076
|
if (!providerDir) {
|
|
24761
25077
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
24762
25078
|
}
|
|
24763
|
-
return
|
|
25079
|
+
return path24.join(providerDir, "fixtures");
|
|
24764
25080
|
}
|
|
24765
25081
|
function readCliFixture(ctx, type, name) {
|
|
24766
25082
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
24767
|
-
const filePath =
|
|
25083
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
24768
25084
|
if (!fs13.existsSync(filePath)) {
|
|
24769
25085
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
24770
25086
|
}
|
|
@@ -25531,7 +25847,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
25531
25847
|
},
|
|
25532
25848
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
25533
25849
|
};
|
|
25534
|
-
const filePath =
|
|
25850
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
25535
25851
|
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
25536
25852
|
ctx.json(res, 200, {
|
|
25537
25853
|
saved: true,
|
|
@@ -25555,7 +25871,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
25555
25871
|
return;
|
|
25556
25872
|
}
|
|
25557
25873
|
const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
25558
|
-
const fullPath =
|
|
25874
|
+
const fullPath = path24.join(fixtureDir, file);
|
|
25559
25875
|
try {
|
|
25560
25876
|
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
25561
25877
|
return {
|
|
@@ -25691,8 +26007,8 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
25691
26007
|
|
|
25692
26008
|
// src/daemon/dev-auto-implement.ts
|
|
25693
26009
|
import * as fs14 from "fs";
|
|
25694
|
-
import * as
|
|
25695
|
-
import * as
|
|
26010
|
+
import * as path25 from "path";
|
|
26011
|
+
import * as os21 from "os";
|
|
25696
26012
|
function getAutoImplPid(ctx) {
|
|
25697
26013
|
const pid = ctx.autoImplProcess?.pid;
|
|
25698
26014
|
return typeof pid === "number" && pid > 0 ? pid : null;
|
|
@@ -25741,22 +26057,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
25741
26057
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
25742
26058
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
25743
26059
|
try {
|
|
25744
|
-
return fs14.statSync(
|
|
26060
|
+
return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
|
|
25745
26061
|
} catch {
|
|
25746
26062
|
return false;
|
|
25747
26063
|
}
|
|
25748
26064
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
25749
26065
|
if (versions.length === 0) return null;
|
|
25750
|
-
return
|
|
26066
|
+
return path25.join(scriptsDir, versions[0]);
|
|
25751
26067
|
}
|
|
25752
26068
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
25753
|
-
const canonicalUserDir =
|
|
25754
|
-
const desiredDir = requestedDir ?
|
|
25755
|
-
const upstreamRoot =
|
|
25756
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
26069
|
+
const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
26070
|
+
const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
|
|
26071
|
+
const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
|
|
26072
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
|
|
25757
26073
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
25758
26074
|
}
|
|
25759
|
-
if (
|
|
26075
|
+
if (path25.basename(desiredDir) !== type) {
|
|
25760
26076
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
25761
26077
|
}
|
|
25762
26078
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -25764,11 +26080,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
25764
26080
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
25765
26081
|
}
|
|
25766
26082
|
if (!fs14.existsSync(desiredDir)) {
|
|
25767
|
-
fs14.mkdirSync(
|
|
26083
|
+
fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
|
|
25768
26084
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
25769
26085
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
25770
26086
|
}
|
|
25771
|
-
const providerJson =
|
|
26087
|
+
const providerJson = path25.join(desiredDir, "provider.json");
|
|
25772
26088
|
if (!fs14.existsSync(providerJson)) {
|
|
25773
26089
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
25774
26090
|
}
|
|
@@ -25779,13 +26095,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
25779
26095
|
const refDir = ctx.findProviderDir(referenceType);
|
|
25780
26096
|
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
25781
26097
|
const referenceScripts = {};
|
|
25782
|
-
const scriptsDir =
|
|
26098
|
+
const scriptsDir = path25.join(refDir, "scripts");
|
|
25783
26099
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
25784
26100
|
if (!latestDir) return referenceScripts;
|
|
25785
26101
|
for (const file of fs14.readdirSync(latestDir)) {
|
|
25786
26102
|
if (!file.endsWith(".js")) continue;
|
|
25787
26103
|
try {
|
|
25788
|
-
referenceScripts[file] = fs14.readFileSync(
|
|
26104
|
+
referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
|
|
25789
26105
|
} catch {
|
|
25790
26106
|
}
|
|
25791
26107
|
}
|
|
@@ -25893,9 +26209,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
25893
26209
|
});
|
|
25894
26210
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
25895
26211
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
25896
|
-
const tmpDir =
|
|
26212
|
+
const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
|
|
25897
26213
|
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
25898
|
-
const promptFile =
|
|
26214
|
+
const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
25899
26215
|
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
25900
26216
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
25901
26217
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -26048,7 +26364,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26048
26364
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
26049
26365
|
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
26050
26366
|
let shellCmd;
|
|
26051
|
-
const isWin =
|
|
26367
|
+
const isWin = os21.platform() === "win32";
|
|
26052
26368
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
26053
26369
|
const promptMode = autoImpl?.promptMode ?? "stdin";
|
|
26054
26370
|
const extraArgs = autoImpl?.extraArgs ?? [];
|
|
@@ -26087,7 +26403,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26087
26403
|
try {
|
|
26088
26404
|
const pty = __require("node-pty");
|
|
26089
26405
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
26090
|
-
const isWin2 =
|
|
26406
|
+
const isWin2 = os21.platform() === "win32";
|
|
26091
26407
|
child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
26092
26408
|
name: "xterm-256color",
|
|
26093
26409
|
cols: 120,
|
|
@@ -26327,7 +26643,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26327
26643
|
setMode: "set_mode.js"
|
|
26328
26644
|
};
|
|
26329
26645
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26330
|
-
const scriptsDir =
|
|
26646
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26331
26647
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26332
26648
|
if (latestScriptsDir) {
|
|
26333
26649
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26338,7 +26654,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26338
26654
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
26339
26655
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
26340
26656
|
try {
|
|
26341
|
-
const content = fs14.readFileSync(
|
|
26657
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26342
26658
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26343
26659
|
lines.push("```javascript");
|
|
26344
26660
|
lines.push(content);
|
|
@@ -26355,7 +26671,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26355
26671
|
lines.push("");
|
|
26356
26672
|
for (const file of refFiles) {
|
|
26357
26673
|
try {
|
|
26358
|
-
const content = fs14.readFileSync(
|
|
26674
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26359
26675
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26360
26676
|
lines.push("```javascript");
|
|
26361
26677
|
lines.push(content);
|
|
@@ -26396,10 +26712,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26396
26712
|
lines.push("");
|
|
26397
26713
|
}
|
|
26398
26714
|
}
|
|
26399
|
-
const docsDir =
|
|
26715
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26400
26716
|
const loadGuide = (name) => {
|
|
26401
26717
|
try {
|
|
26402
|
-
const p =
|
|
26718
|
+
const p = path25.join(docsDir, name);
|
|
26403
26719
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26404
26720
|
} catch {
|
|
26405
26721
|
}
|
|
@@ -26636,7 +26952,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26636
26952
|
parseApproval: "parse_approval.js"
|
|
26637
26953
|
};
|
|
26638
26954
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26639
|
-
const scriptsDir =
|
|
26955
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26640
26956
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26641
26957
|
if (latestScriptsDir) {
|
|
26642
26958
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26648,7 +26964,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26648
26964
|
if (!file.endsWith(".js")) continue;
|
|
26649
26965
|
if (!targetFileNames.has(file)) continue;
|
|
26650
26966
|
try {
|
|
26651
|
-
const content = fs14.readFileSync(
|
|
26967
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26652
26968
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26653
26969
|
lines.push("```javascript");
|
|
26654
26970
|
lines.push(content);
|
|
@@ -26664,7 +26980,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26664
26980
|
lines.push("");
|
|
26665
26981
|
for (const file of refFiles) {
|
|
26666
26982
|
try {
|
|
26667
|
-
const content = fs14.readFileSync(
|
|
26983
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26668
26984
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26669
26985
|
lines.push("```javascript");
|
|
26670
26986
|
lines.push(content);
|
|
@@ -26697,10 +27013,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26697
27013
|
lines.push("");
|
|
26698
27014
|
}
|
|
26699
27015
|
}
|
|
26700
|
-
const docsDir =
|
|
27016
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26701
27017
|
const loadGuide = (name) => {
|
|
26702
27018
|
try {
|
|
26703
|
-
const p =
|
|
27019
|
+
const p = path25.join(docsDir, name);
|
|
26704
27020
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26705
27021
|
} catch {
|
|
26706
27022
|
}
|
|
@@ -27147,8 +27463,8 @@ var DevServer = class _DevServer {
|
|
|
27147
27463
|
}
|
|
27148
27464
|
getEndpointList() {
|
|
27149
27465
|
return this.routes.map((r) => {
|
|
27150
|
-
const
|
|
27151
|
-
return `${r.method.padEnd(5)} ${
|
|
27466
|
+
const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
27467
|
+
return `${r.method.padEnd(5)} ${path27}`;
|
|
27152
27468
|
});
|
|
27153
27469
|
}
|
|
27154
27470
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -27436,12 +27752,12 @@ var DevServer = class _DevServer {
|
|
|
27436
27752
|
// ─── DevConsole SPA ───
|
|
27437
27753
|
getConsoleDistDir() {
|
|
27438
27754
|
const candidates = [
|
|
27439
|
-
|
|
27440
|
-
|
|
27441
|
-
|
|
27755
|
+
path26.resolve(__dirname, "../../web-devconsole/dist"),
|
|
27756
|
+
path26.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
27757
|
+
path26.join(process.cwd(), "packages/web-devconsole/dist")
|
|
27442
27758
|
];
|
|
27443
27759
|
for (const dir of candidates) {
|
|
27444
|
-
if (fs15.existsSync(
|
|
27760
|
+
if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
|
|
27445
27761
|
}
|
|
27446
27762
|
return null;
|
|
27447
27763
|
}
|
|
@@ -27451,7 +27767,7 @@ var DevServer = class _DevServer {
|
|
|
27451
27767
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
27452
27768
|
return;
|
|
27453
27769
|
}
|
|
27454
|
-
const htmlPath =
|
|
27770
|
+
const htmlPath = path26.join(distDir, "index.html");
|
|
27455
27771
|
try {
|
|
27456
27772
|
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
27457
27773
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -27476,15 +27792,15 @@ var DevServer = class _DevServer {
|
|
|
27476
27792
|
this.json(res, 404, { error: "Not found" });
|
|
27477
27793
|
return;
|
|
27478
27794
|
}
|
|
27479
|
-
const safePath =
|
|
27480
|
-
const filePath =
|
|
27795
|
+
const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
|
|
27796
|
+
const filePath = path26.join(distDir, safePath);
|
|
27481
27797
|
if (!filePath.startsWith(distDir)) {
|
|
27482
27798
|
this.json(res, 403, { error: "Forbidden" });
|
|
27483
27799
|
return;
|
|
27484
27800
|
}
|
|
27485
27801
|
try {
|
|
27486
27802
|
const content = fs15.readFileSync(filePath);
|
|
27487
|
-
const ext =
|
|
27803
|
+
const ext = path26.extname(filePath);
|
|
27488
27804
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
27489
27805
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
27490
27806
|
res.end(content);
|
|
@@ -27597,9 +27913,9 @@ var DevServer = class _DevServer {
|
|
|
27597
27913
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
27598
27914
|
if (entry.isDirectory()) {
|
|
27599
27915
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
27600
|
-
scan(
|
|
27916
|
+
scan(path26.join(d, entry.name), rel);
|
|
27601
27917
|
} else {
|
|
27602
|
-
const stat2 = fs15.statSync(
|
|
27918
|
+
const stat2 = fs15.statSync(path26.join(d, entry.name));
|
|
27603
27919
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
27604
27920
|
}
|
|
27605
27921
|
}
|
|
@@ -27622,7 +27938,7 @@ var DevServer = class _DevServer {
|
|
|
27622
27938
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27623
27939
|
return;
|
|
27624
27940
|
}
|
|
27625
|
-
const fullPath =
|
|
27941
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27626
27942
|
if (!fullPath.startsWith(dir)) {
|
|
27627
27943
|
this.json(res, 403, { error: "Forbidden" });
|
|
27628
27944
|
return;
|
|
@@ -27647,14 +27963,14 @@ var DevServer = class _DevServer {
|
|
|
27647
27963
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27648
27964
|
return;
|
|
27649
27965
|
}
|
|
27650
|
-
const fullPath =
|
|
27966
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27651
27967
|
if (!fullPath.startsWith(dir)) {
|
|
27652
27968
|
this.json(res, 403, { error: "Forbidden" });
|
|
27653
27969
|
return;
|
|
27654
27970
|
}
|
|
27655
27971
|
try {
|
|
27656
27972
|
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
27657
|
-
fs15.mkdirSync(
|
|
27973
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27658
27974
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27659
27975
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
27660
27976
|
this.providerLoader.reload();
|
|
@@ -27671,7 +27987,7 @@ var DevServer = class _DevServer {
|
|
|
27671
27987
|
return;
|
|
27672
27988
|
}
|
|
27673
27989
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
27674
|
-
const p =
|
|
27990
|
+
const p = path26.join(dir, name);
|
|
27675
27991
|
if (fs15.existsSync(p)) {
|
|
27676
27992
|
const source = fs15.readFileSync(p, "utf-8");
|
|
27677
27993
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -27692,8 +28008,8 @@ var DevServer = class _DevServer {
|
|
|
27692
28008
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
27693
28009
|
return;
|
|
27694
28010
|
}
|
|
27695
|
-
const target = fs15.existsSync(
|
|
27696
|
-
const targetPath =
|
|
28011
|
+
const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
28012
|
+
const targetPath = path26.join(dir, target);
|
|
27697
28013
|
try {
|
|
27698
28014
|
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
27699
28015
|
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -27840,7 +28156,7 @@ var DevServer = class _DevServer {
|
|
|
27840
28156
|
}
|
|
27841
28157
|
let targetDir;
|
|
27842
28158
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
27843
|
-
const jsonPath =
|
|
28159
|
+
const jsonPath = path26.join(targetDir, "provider.json");
|
|
27844
28160
|
if (fs15.existsSync(jsonPath)) {
|
|
27845
28161
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
27846
28162
|
return;
|
|
@@ -27852,8 +28168,8 @@ var DevServer = class _DevServer {
|
|
|
27852
28168
|
const createdFiles = ["provider.json"];
|
|
27853
28169
|
if (result.files) {
|
|
27854
28170
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
27855
|
-
const fullPath =
|
|
27856
|
-
fs15.mkdirSync(
|
|
28171
|
+
const fullPath = path26.join(targetDir, relPath);
|
|
28172
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27857
28173
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27858
28174
|
createdFiles.push(relPath);
|
|
27859
28175
|
}
|
|
@@ -27906,22 +28222,22 @@ var DevServer = class _DevServer {
|
|
|
27906
28222
|
if (!fs15.existsSync(scriptsDir)) return null;
|
|
27907
28223
|
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
27908
28224
|
try {
|
|
27909
|
-
return fs15.statSync(
|
|
28225
|
+
return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
|
|
27910
28226
|
} catch {
|
|
27911
28227
|
return false;
|
|
27912
28228
|
}
|
|
27913
28229
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
27914
28230
|
if (versions.length === 0) return null;
|
|
27915
|
-
return
|
|
28231
|
+
return path26.join(scriptsDir, versions[0]);
|
|
27916
28232
|
}
|
|
27917
28233
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
27918
|
-
const canonicalUserDir =
|
|
27919
|
-
const desiredDir = requestedDir ?
|
|
27920
|
-
const upstreamRoot =
|
|
27921
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
28234
|
+
const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
28235
|
+
const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
|
|
28236
|
+
const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
|
|
28237
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
|
|
27922
28238
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
27923
28239
|
}
|
|
27924
|
-
if (
|
|
28240
|
+
if (path26.basename(desiredDir) !== type) {
|
|
27925
28241
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
27926
28242
|
}
|
|
27927
28243
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -27929,11 +28245,11 @@ var DevServer = class _DevServer {
|
|
|
27929
28245
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
27930
28246
|
}
|
|
27931
28247
|
if (!fs15.existsSync(desiredDir)) {
|
|
27932
|
-
fs15.mkdirSync(
|
|
28248
|
+
fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
|
|
27933
28249
|
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
27934
28250
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
27935
28251
|
}
|
|
27936
|
-
const providerJson =
|
|
28252
|
+
const providerJson = path26.join(desiredDir, "provider.json");
|
|
27937
28253
|
if (!fs15.existsSync(providerJson)) {
|
|
27938
28254
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
27939
28255
|
}
|
|
@@ -27969,7 +28285,7 @@ var DevServer = class _DevServer {
|
|
|
27969
28285
|
setMode: "set_mode.js"
|
|
27970
28286
|
};
|
|
27971
28287
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
27972
|
-
const scriptsDir =
|
|
28288
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
27973
28289
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
27974
28290
|
if (latestScriptsDir) {
|
|
27975
28291
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -27980,7 +28296,7 @@ var DevServer = class _DevServer {
|
|
|
27980
28296
|
for (const file of fs15.readdirSync(latestScriptsDir)) {
|
|
27981
28297
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
27982
28298
|
try {
|
|
27983
|
-
const content = fs15.readFileSync(
|
|
28299
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
27984
28300
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
27985
28301
|
lines.push("```javascript");
|
|
27986
28302
|
lines.push(content);
|
|
@@ -27997,7 +28313,7 @@ var DevServer = class _DevServer {
|
|
|
27997
28313
|
lines.push("");
|
|
27998
28314
|
for (const file of refFiles) {
|
|
27999
28315
|
try {
|
|
28000
|
-
const content = fs15.readFileSync(
|
|
28316
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28001
28317
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28002
28318
|
lines.push("```javascript");
|
|
28003
28319
|
lines.push(content);
|
|
@@ -28038,10 +28354,10 @@ var DevServer = class _DevServer {
|
|
|
28038
28354
|
lines.push("");
|
|
28039
28355
|
}
|
|
28040
28356
|
}
|
|
28041
|
-
const docsDir =
|
|
28357
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28042
28358
|
const loadGuide = (name) => {
|
|
28043
28359
|
try {
|
|
28044
|
-
const p =
|
|
28360
|
+
const p = path26.join(docsDir, name);
|
|
28045
28361
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28046
28362
|
} catch {
|
|
28047
28363
|
}
|
|
@@ -28215,7 +28531,7 @@ var DevServer = class _DevServer {
|
|
|
28215
28531
|
parseApproval: "parse_approval.js"
|
|
28216
28532
|
};
|
|
28217
28533
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28218
|
-
const scriptsDir =
|
|
28534
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28219
28535
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28220
28536
|
if (latestScriptsDir) {
|
|
28221
28537
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28227,7 +28543,7 @@ var DevServer = class _DevServer {
|
|
|
28227
28543
|
if (!file.endsWith(".js")) continue;
|
|
28228
28544
|
if (!targetFileNames.has(file)) continue;
|
|
28229
28545
|
try {
|
|
28230
|
-
const content = fs15.readFileSync(
|
|
28546
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28231
28547
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28232
28548
|
lines.push("```javascript");
|
|
28233
28549
|
lines.push(content);
|
|
@@ -28243,7 +28559,7 @@ var DevServer = class _DevServer {
|
|
|
28243
28559
|
lines.push("");
|
|
28244
28560
|
for (const file of refFiles) {
|
|
28245
28561
|
try {
|
|
28246
|
-
const content = fs15.readFileSync(
|
|
28562
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28247
28563
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28248
28564
|
lines.push("```javascript");
|
|
28249
28565
|
lines.push(content);
|
|
@@ -28276,10 +28592,10 @@ var DevServer = class _DevServer {
|
|
|
28276
28592
|
lines.push("");
|
|
28277
28593
|
}
|
|
28278
28594
|
}
|
|
28279
|
-
const docsDir =
|
|
28595
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28280
28596
|
const loadGuide = (name) => {
|
|
28281
28597
|
try {
|
|
28282
|
-
const p =
|
|
28598
|
+
const p = path26.join(docsDir, name);
|
|
28283
28599
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28284
28600
|
} catch {
|
|
28285
28601
|
}
|
|
@@ -29631,6 +29947,7 @@ export {
|
|
|
29631
29947
|
createGitWorkspaceMonitor,
|
|
29632
29948
|
createInteractionId,
|
|
29633
29949
|
createMesh,
|
|
29950
|
+
createWorktree,
|
|
29634
29951
|
deleteMesh,
|
|
29635
29952
|
detectAllVersions,
|
|
29636
29953
|
detectCLIs,
|
|
@@ -29683,6 +30000,7 @@ export {
|
|
|
29683
30000
|
launchWithCdp,
|
|
29684
30001
|
listHostedCliRuntimes,
|
|
29685
30002
|
listMeshes,
|
|
30003
|
+
listWorktrees,
|
|
29686
30004
|
loadConfig,
|
|
29687
30005
|
loadState,
|
|
29688
30006
|
logCommand,
|
|
@@ -29702,6 +30020,7 @@ export {
|
|
|
29702
30020
|
normalizeSessionModalFields,
|
|
29703
30021
|
parsePorcelainV2Status,
|
|
29704
30022
|
parseProviderSourceConfigUpdate,
|
|
30023
|
+
parseWorktreeListOutput,
|
|
29705
30024
|
partitionSessionHostDiagnosticsSessions,
|
|
29706
30025
|
partitionSessionHostRecords,
|
|
29707
30026
|
prepareSessionChatTailUpdate,
|
|
@@ -29711,6 +30030,7 @@ export {
|
|
|
29711
30030
|
recordDebugTrace,
|
|
29712
30031
|
registerExtensionProviders,
|
|
29713
30032
|
removeNode,
|
|
30033
|
+
removeWorktree,
|
|
29714
30034
|
resetConfig,
|
|
29715
30035
|
resetDebugRuntimeConfig,
|
|
29716
30036
|
resetState,
|
|
@@ -29720,6 +30040,7 @@ export {
|
|
|
29720
30040
|
resolveGitRepository,
|
|
29721
30041
|
resolveSessionHostAppName,
|
|
29722
30042
|
resolveSessionHostAppNameResolution,
|
|
30043
|
+
resolveWorktreePath,
|
|
29723
30044
|
runAsyncBatch,
|
|
29724
30045
|
runGit,
|
|
29725
30046
|
saveConfig,
|