@adhdev/daemon-core 0.9.76-rc.10 → 0.9.76-rc.11
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/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 +575 -295
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +595 -320
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +1 -0
- package/dist/repo-mesh-types.d.ts +4 -0
- package/package.json +1 -1
- package/src/commands/router.ts +151 -10
- 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/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,7 +1627,7 @@ 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
1633
|
const { provider, runtimeSettings, workingDir, extraArgs } = options;
|
|
@@ -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";
|
|
@@ -4984,20 +5127,23 @@ var TurnSnapshotTracker = class {
|
|
|
4984
5127
|
}
|
|
4985
5128
|
};
|
|
4986
5129
|
|
|
5130
|
+
// src/git/index.ts
|
|
5131
|
+
init_git_worktree();
|
|
5132
|
+
|
|
4987
5133
|
// src/index.ts
|
|
4988
5134
|
init_config();
|
|
4989
5135
|
|
|
4990
5136
|
// src/config/workspaces.ts
|
|
4991
5137
|
import * as fs from "fs";
|
|
4992
5138
|
import * as os from "os";
|
|
4993
|
-
import * as
|
|
5139
|
+
import * as path5 from "path";
|
|
4994
5140
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4995
5141
|
var MAX_WORKSPACES = 50;
|
|
4996
5142
|
function expandPath(p) {
|
|
4997
5143
|
const t = (p || "").trim();
|
|
4998
5144
|
if (!t) return "";
|
|
4999
|
-
if (t.startsWith("~")) return
|
|
5000
|
-
return
|
|
5145
|
+
if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
5146
|
+
return path5.resolve(t);
|
|
5001
5147
|
}
|
|
5002
5148
|
function validateWorkspacePath(absPath) {
|
|
5003
5149
|
try {
|
|
@@ -5011,7 +5157,7 @@ function validateWorkspacePath(absPath) {
|
|
|
5011
5157
|
}
|
|
5012
5158
|
}
|
|
5013
5159
|
function defaultWorkspaceLabel(absPath) {
|
|
5014
|
-
const base =
|
|
5160
|
+
const base = path5.basename(absPath) || absPath;
|
|
5015
5161
|
return base;
|
|
5016
5162
|
}
|
|
5017
5163
|
function getDefaultWorkspacePath(config) {
|
|
@@ -5102,9 +5248,9 @@ function resolveIdeLaunchWorkspace(args, config) {
|
|
|
5102
5248
|
return getDefaultWorkspacePath(config) || void 0;
|
|
5103
5249
|
}
|
|
5104
5250
|
function findWorkspaceByPath(config, rawPath) {
|
|
5105
|
-
const abs =
|
|
5251
|
+
const abs = path5.resolve(expandPath(rawPath));
|
|
5106
5252
|
if (!abs) return void 0;
|
|
5107
|
-
return (config.workspaces || []).find((w) =>
|
|
5253
|
+
return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
|
|
5108
5254
|
}
|
|
5109
5255
|
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
5110
5256
|
const abs = expandPath(rawPath);
|
|
@@ -5120,7 +5266,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
|
|
|
5120
5266
|
const v = validateWorkspacePath(abs);
|
|
5121
5267
|
if (!v.ok) return { error: v.error };
|
|
5122
5268
|
const list = [...config.workspaces || []];
|
|
5123
|
-
if (list.some((w) =>
|
|
5269
|
+
if (list.some((w) => path5.resolve(w.path) === abs)) {
|
|
5124
5270
|
return { error: "Workspace already in list" };
|
|
5125
5271
|
}
|
|
5126
5272
|
if (list.length >= MAX_WORKSPACES) {
|
|
@@ -5154,7 +5300,7 @@ function setDefaultWorkspaceId(config, id) {
|
|
|
5154
5300
|
}
|
|
5155
5301
|
|
|
5156
5302
|
// src/config/recent-activity.ts
|
|
5157
|
-
import * as
|
|
5303
|
+
import * as path6 from "path";
|
|
5158
5304
|
|
|
5159
5305
|
// src/providers/summary-metadata.ts
|
|
5160
5306
|
function normalizeSummaryItem(item) {
|
|
@@ -5223,9 +5369,9 @@ var MAX_ACTIVITY = 30;
|
|
|
5223
5369
|
function normalizeWorkspace(workspace) {
|
|
5224
5370
|
if (!workspace) return "";
|
|
5225
5371
|
try {
|
|
5226
|
-
return
|
|
5372
|
+
return path6.resolve(expandPath(workspace));
|
|
5227
5373
|
} catch {
|
|
5228
|
-
return
|
|
5374
|
+
return path6.resolve(workspace);
|
|
5229
5375
|
}
|
|
5230
5376
|
}
|
|
5231
5377
|
function buildRecentActivityKey(entry) {
|
|
@@ -5393,14 +5539,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
|
|
|
5393
5539
|
}
|
|
5394
5540
|
|
|
5395
5541
|
// src/config/saved-sessions.ts
|
|
5396
|
-
import * as
|
|
5542
|
+
import * as path7 from "path";
|
|
5397
5543
|
var MAX_SAVED_SESSIONS = 500;
|
|
5398
5544
|
function normalizeWorkspace2(workspace) {
|
|
5399
5545
|
if (!workspace) return "";
|
|
5400
5546
|
try {
|
|
5401
|
-
return
|
|
5547
|
+
return path7.resolve(expandPath(workspace));
|
|
5402
5548
|
} catch {
|
|
5403
|
-
return
|
|
5549
|
+
return path7.resolve(workspace);
|
|
5404
5550
|
}
|
|
5405
5551
|
}
|
|
5406
5552
|
function buildSavedProviderSessionKey(providerSessionId) {
|
|
@@ -5506,8 +5652,8 @@ async function syncMeshes(transport) {
|
|
|
5506
5652
|
|
|
5507
5653
|
// src/config/state-store.ts
|
|
5508
5654
|
init_config();
|
|
5509
|
-
import { existsSync as
|
|
5510
|
-
import { join as
|
|
5655
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
5656
|
+
import { join as join5 } from "path";
|
|
5511
5657
|
var DEFAULT_STATE = {
|
|
5512
5658
|
recentActivity: [],
|
|
5513
5659
|
savedProviderSessions: [],
|
|
@@ -5520,7 +5666,7 @@ function isPlainObject2(value) {
|
|
|
5520
5666
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
5521
5667
|
}
|
|
5522
5668
|
function getStatePath() {
|
|
5523
|
-
return
|
|
5669
|
+
return join5(getConfigDir(), "state.json");
|
|
5524
5670
|
}
|
|
5525
5671
|
function normalizeState(raw) {
|
|
5526
5672
|
const parsed = isPlainObject2(raw) ? raw : {};
|
|
@@ -5556,7 +5702,7 @@ function normalizeState(raw) {
|
|
|
5556
5702
|
}
|
|
5557
5703
|
function loadState() {
|
|
5558
5704
|
const statePath = getStatePath();
|
|
5559
|
-
if (!
|
|
5705
|
+
if (!existsSync5(statePath)) {
|
|
5560
5706
|
return { ...DEFAULT_STATE };
|
|
5561
5707
|
}
|
|
5562
5708
|
try {
|
|
@@ -5577,9 +5723,9 @@ function resetState() {
|
|
|
5577
5723
|
|
|
5578
5724
|
// src/detection/ide-detector.ts
|
|
5579
5725
|
import { execSync } from "child_process";
|
|
5580
|
-
import { existsSync as
|
|
5726
|
+
import { existsSync as existsSync6 } from "fs";
|
|
5581
5727
|
import { platform, homedir as homedir3 } from "os";
|
|
5582
|
-
import * as
|
|
5728
|
+
import * as path8 from "path";
|
|
5583
5729
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
5584
5730
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
5585
5731
|
function registerIDEDefinition(def) {
|
|
@@ -5598,10 +5744,10 @@ function getMergedDefinitions() {
|
|
|
5598
5744
|
function findCliCommand(command) {
|
|
5599
5745
|
const trimmed = String(command || "").trim();
|
|
5600
5746
|
if (!trimmed) return null;
|
|
5601
|
-
if (
|
|
5602
|
-
const candidate = trimmed.startsWith("~") ?
|
|
5603
|
-
const resolved =
|
|
5604
|
-
return
|
|
5747
|
+
if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
5748
|
+
const candidate = trimmed.startsWith("~") ? path8.join(homedir3(), trimmed.slice(1)) : trimmed;
|
|
5749
|
+
const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
|
|
5750
|
+
return existsSync6(resolved) ? resolved : null;
|
|
5605
5751
|
}
|
|
5606
5752
|
try {
|
|
5607
5753
|
const result = execSync(
|
|
@@ -5628,13 +5774,13 @@ function getIdeVersion(cliCommand) {
|
|
|
5628
5774
|
function checkPathExists(paths) {
|
|
5629
5775
|
const home = homedir3();
|
|
5630
5776
|
for (const p of paths) {
|
|
5631
|
-
const normalized = p.startsWith("~") ?
|
|
5777
|
+
const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
|
|
5632
5778
|
if (normalized.includes("*")) {
|
|
5633
5779
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5634
5780
|
const resolved = normalized.replace("*", username);
|
|
5635
|
-
if (
|
|
5781
|
+
if (existsSync6(resolved)) return resolved;
|
|
5636
5782
|
} else {
|
|
5637
|
-
if (
|
|
5783
|
+
if (existsSync6(normalized)) return normalized;
|
|
5638
5784
|
}
|
|
5639
5785
|
}
|
|
5640
5786
|
return null;
|
|
@@ -5648,11 +5794,11 @@ async function detectIDEs(providerLoader) {
|
|
|
5648
5794
|
let resolvedCli = cliPath;
|
|
5649
5795
|
if (!resolvedCli && appPath && os21 === "darwin") {
|
|
5650
5796
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
5651
|
-
if (
|
|
5797
|
+
if (existsSync6(bundledCli)) resolvedCli = bundledCli;
|
|
5652
5798
|
}
|
|
5653
5799
|
if (!resolvedCli && appPath && os21 === "win32") {
|
|
5654
|
-
const { dirname:
|
|
5655
|
-
const appDir =
|
|
5800
|
+
const { dirname: dirname9 } = await import("path");
|
|
5801
|
+
const appDir = dirname9(appPath);
|
|
5656
5802
|
const candidates = [
|
|
5657
5803
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
5658
5804
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -5661,7 +5807,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5661
5807
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
5662
5808
|
];
|
|
5663
5809
|
for (const c of candidates) {
|
|
5664
|
-
if (
|
|
5810
|
+
if (existsSync6(c)) {
|
|
5665
5811
|
resolvedCli = c;
|
|
5666
5812
|
break;
|
|
5667
5813
|
}
|
|
@@ -5686,8 +5832,8 @@ async function detectIDEs(providerLoader) {
|
|
|
5686
5832
|
// src/detection/cli-detector.ts
|
|
5687
5833
|
import { exec } from "child_process";
|
|
5688
5834
|
import * as os2 from "os";
|
|
5689
|
-
import * as
|
|
5690
|
-
import { existsSync as
|
|
5835
|
+
import * as path9 from "path";
|
|
5836
|
+
import { existsSync as existsSync7 } from "fs";
|
|
5691
5837
|
function parseVersion(raw) {
|
|
5692
5838
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
5693
5839
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
@@ -5699,19 +5845,19 @@ function shellQuote(value) {
|
|
|
5699
5845
|
function expandHome(value) {
|
|
5700
5846
|
const trimmed = value.trim();
|
|
5701
5847
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
5702
|
-
return
|
|
5848
|
+
return path9.join(os2.homedir(), trimmed.slice(1));
|
|
5703
5849
|
}
|
|
5704
5850
|
function isExplicitCommandPath(command) {
|
|
5705
5851
|
const trimmed = command.trim();
|
|
5706
|
-
return
|
|
5852
|
+
return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
5707
5853
|
}
|
|
5708
5854
|
function resolveCommandPath(command) {
|
|
5709
5855
|
const trimmed = command.trim();
|
|
5710
5856
|
if (!trimmed) return null;
|
|
5711
5857
|
if (isExplicitCommandPath(trimmed)) {
|
|
5712
5858
|
const expanded = expandHome(trimmed);
|
|
5713
|
-
const candidate =
|
|
5714
|
-
return
|
|
5859
|
+
const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
5860
|
+
return existsSync7(candidate) ? candidate : null;
|
|
5715
5861
|
}
|
|
5716
5862
|
return null;
|
|
5717
5863
|
}
|
|
@@ -7979,9 +8125,9 @@ ${cleanBody}`;
|
|
|
7979
8125
|
|
|
7980
8126
|
// src/config/chat-history.ts
|
|
7981
8127
|
import * as fs3 from "fs";
|
|
7982
|
-
import * as
|
|
8128
|
+
import * as path11 from "path";
|
|
7983
8129
|
import * as os5 from "os";
|
|
7984
|
-
var HISTORY_DIR =
|
|
8130
|
+
var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
|
|
7985
8131
|
var RETAIN_DAYS = 30;
|
|
7986
8132
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
7987
8133
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -8144,7 +8290,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
8144
8290
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
8145
8291
|
return new Map(files.map((file) => {
|
|
8146
8292
|
try {
|
|
8147
|
-
const stat2 = fs3.statSync(
|
|
8293
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8148
8294
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
8149
8295
|
} catch {
|
|
8150
8296
|
return [file, `${file}:missing`];
|
|
@@ -8155,7 +8301,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
8155
8301
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
8156
8302
|
}
|
|
8157
8303
|
function getSavedHistoryIndexFilePath(dir) {
|
|
8158
|
-
return
|
|
8304
|
+
return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
8159
8305
|
}
|
|
8160
8306
|
function getSavedHistoryIndexLockPath(dir) {
|
|
8161
8307
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -8257,7 +8403,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
8257
8403
|
}
|
|
8258
8404
|
for (const file of Array.from(currentEntries.keys())) {
|
|
8259
8405
|
if (incomingFiles.has(file)) continue;
|
|
8260
|
-
if (!fs3.existsSync(
|
|
8406
|
+
if (!fs3.existsSync(path11.join(dir, file))) {
|
|
8261
8407
|
currentEntries.delete(file);
|
|
8262
8408
|
}
|
|
8263
8409
|
}
|
|
@@ -8283,7 +8429,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8283
8429
|
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
8284
8430
|
const files = listHistoryFiles(dir);
|
|
8285
8431
|
for (const file of files) {
|
|
8286
|
-
const stat2 = fs3.statSync(
|
|
8432
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8287
8433
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
8288
8434
|
}
|
|
8289
8435
|
return false;
|
|
@@ -8293,14 +8439,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8293
8439
|
}
|
|
8294
8440
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
8295
8441
|
try {
|
|
8296
|
-
const stat2 = fs3.statSync(
|
|
8442
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8297
8443
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
8298
8444
|
} catch {
|
|
8299
8445
|
return `${file}:missing`;
|
|
8300
8446
|
}
|
|
8301
8447
|
}
|
|
8302
8448
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
8303
|
-
const filePath =
|
|
8449
|
+
const filePath = path11.join(dir, file);
|
|
8304
8450
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
8305
8451
|
const currentEntry = entries.get(file) || null;
|
|
8306
8452
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -8373,7 +8519,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
8373
8519
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
8374
8520
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
8375
8521
|
if (!historySessionId) return null;
|
|
8376
|
-
const filePath =
|
|
8522
|
+
const filePath = path11.join(dir, file);
|
|
8377
8523
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8378
8524
|
const lines = content.split("\n").filter(Boolean);
|
|
8379
8525
|
let messageCount = 0;
|
|
@@ -8460,7 +8606,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
8460
8606
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
8461
8607
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
8462
8608
|
for (const file of files.slice().sort()) {
|
|
8463
|
-
const filePath =
|
|
8609
|
+
const filePath = path11.join(dir, file);
|
|
8464
8610
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
8465
8611
|
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
8466
8612
|
const persisted = persistedEntries.get(file);
|
|
@@ -8580,12 +8726,12 @@ var ChatHistoryWriter = class {
|
|
|
8580
8726
|
});
|
|
8581
8727
|
}
|
|
8582
8728
|
if (newMessages.length === 0) return;
|
|
8583
|
-
const dir =
|
|
8729
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8584
8730
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8585
8731
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8586
8732
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
8587
8733
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
8588
|
-
const filePath =
|
|
8734
|
+
const filePath = path11.join(dir, fileName);
|
|
8589
8735
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
8590
8736
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
8591
8737
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -8676,11 +8822,11 @@ var ChatHistoryWriter = class {
|
|
|
8676
8822
|
const ws = String(workspace || "").trim();
|
|
8677
8823
|
if (!id || !ws) return;
|
|
8678
8824
|
try {
|
|
8679
|
-
const dir =
|
|
8825
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8680
8826
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8681
8827
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8682
8828
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
8683
|
-
const filePath =
|
|
8829
|
+
const filePath = path11.join(dir, fileName);
|
|
8684
8830
|
const record = {
|
|
8685
8831
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8686
8832
|
receivedAt: Date.now(),
|
|
@@ -8726,14 +8872,14 @@ var ChatHistoryWriter = class {
|
|
|
8726
8872
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
8727
8873
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
8728
8874
|
}
|
|
8729
|
-
const dir =
|
|
8875
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8730
8876
|
if (!fs3.existsSync(dir)) return;
|
|
8731
8877
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
8732
8878
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
8733
8879
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
8734
8880
|
for (const file of files) {
|
|
8735
|
-
const sourcePath =
|
|
8736
|
-
const targetPath =
|
|
8881
|
+
const sourcePath = path11.join(dir, file);
|
|
8882
|
+
const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
8737
8883
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
8738
8884
|
const rewritten = sourceLines.map((line) => {
|
|
8739
8885
|
try {
|
|
@@ -8767,13 +8913,13 @@ var ChatHistoryWriter = class {
|
|
|
8767
8913
|
const sessionId = String(historySessionId || "").trim();
|
|
8768
8914
|
if (!sessionId) return;
|
|
8769
8915
|
try {
|
|
8770
|
-
const dir =
|
|
8916
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8771
8917
|
if (!fs3.existsSync(dir)) return;
|
|
8772
8918
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
8773
8919
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
8774
8920
|
const seen = /* @__PURE__ */ new Set();
|
|
8775
8921
|
for (const file of files) {
|
|
8776
|
-
const filePath =
|
|
8922
|
+
const filePath = path11.join(dir, file);
|
|
8777
8923
|
const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
8778
8924
|
const next = [];
|
|
8779
8925
|
for (const line of lines) {
|
|
@@ -8827,11 +8973,11 @@ var ChatHistoryWriter = class {
|
|
|
8827
8973
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
8828
8974
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
8829
8975
|
for (const dir of agentDirs) {
|
|
8830
|
-
const dirPath =
|
|
8976
|
+
const dirPath = path11.join(HISTORY_DIR, dir.name);
|
|
8831
8977
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
8832
8978
|
let removedAny = false;
|
|
8833
8979
|
for (const file of files) {
|
|
8834
|
-
const filePath =
|
|
8980
|
+
const filePath = path11.join(dirPath, file);
|
|
8835
8981
|
const stat2 = fs3.statSync(filePath);
|
|
8836
8982
|
if (stat2.mtimeMs < cutoff) {
|
|
8837
8983
|
fs3.unlinkSync(filePath);
|
|
@@ -8881,13 +9027,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
8881
9027
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
8882
9028
|
try {
|
|
8883
9029
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8884
|
-
const dir =
|
|
9030
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
8885
9031
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
8886
9032
|
const files = listHistoryFiles(dir, historySessionId);
|
|
8887
9033
|
const allMessages = [];
|
|
8888
9034
|
const seen = /* @__PURE__ */ new Set();
|
|
8889
9035
|
for (const file of files) {
|
|
8890
|
-
const filePath =
|
|
9036
|
+
const filePath = path11.join(dir, file);
|
|
8891
9037
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8892
9038
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
8893
9039
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -8911,7 +9057,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
8911
9057
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
8912
9058
|
try {
|
|
8913
9059
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
8914
|
-
const dir =
|
|
9060
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
8915
9061
|
if (!fs3.existsSync(dir)) {
|
|
8916
9062
|
savedHistorySessionCache.delete(sanitized);
|
|
8917
9063
|
return { sessions: [], hasMore: false };
|
|
@@ -8972,11 +9118,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
8972
9118
|
}
|
|
8973
9119
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
8974
9120
|
try {
|
|
8975
|
-
const dir =
|
|
9121
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
8976
9122
|
if (!fs3.existsSync(dir)) return null;
|
|
8977
9123
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
8978
9124
|
for (const file of files) {
|
|
8979
|
-
const lines = fs3.readFileSync(
|
|
9125
|
+
const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
8980
9126
|
for (const line of lines) {
|
|
8981
9127
|
try {
|
|
8982
9128
|
const parsed = JSON.parse(line);
|
|
@@ -8996,16 +9142,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
8996
9142
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
8997
9143
|
if (records.length === 0) return false;
|
|
8998
9144
|
try {
|
|
8999
|
-
const dir =
|
|
9145
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9000
9146
|
fs3.mkdirSync(dir, { recursive: true });
|
|
9001
9147
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
9002
9148
|
for (const file of fs3.readdirSync(dir)) {
|
|
9003
9149
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
9004
|
-
fs3.unlinkSync(
|
|
9150
|
+
fs3.unlinkSync(path11.join(dir, file));
|
|
9005
9151
|
}
|
|
9006
9152
|
}
|
|
9007
9153
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
9008
|
-
const filePath =
|
|
9154
|
+
const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
9009
9155
|
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
9010
9156
|
`, "utf-8");
|
|
9011
9157
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -11342,7 +11488,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
11342
11488
|
// src/commands/chat-commands.ts
|
|
11343
11489
|
import * as fs4 from "fs";
|
|
11344
11490
|
import * as os6 from "os";
|
|
11345
|
-
import * as
|
|
11491
|
+
import * as path12 from "path";
|
|
11346
11492
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
11347
11493
|
|
|
11348
11494
|
// src/providers/provider-input-support.ts
|
|
@@ -11853,7 +11999,7 @@ function buildDebugBundleText(bundle) {
|
|
|
11853
11999
|
}
|
|
11854
12000
|
function getChatDebugBundleDir() {
|
|
11855
12001
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
11856
|
-
return override ||
|
|
12002
|
+
return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
11857
12003
|
}
|
|
11858
12004
|
function safeBundleIdSegment(value, fallback) {
|
|
11859
12005
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -11886,7 +12032,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
11886
12032
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
11887
12033
|
const dir = getChatDebugBundleDir();
|
|
11888
12034
|
fs4.mkdirSync(dir, { recursive: true });
|
|
11889
|
-
const savedPath =
|
|
12035
|
+
const savedPath = path12.join(dir, `${bundleId}.json`);
|
|
11890
12036
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
11891
12037
|
`;
|
|
11892
12038
|
fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -13030,7 +13176,7 @@ async function handleResolveAction(h, args) {
|
|
|
13030
13176
|
|
|
13031
13177
|
// src/commands/cdp-commands.ts
|
|
13032
13178
|
import * as fs5 from "fs";
|
|
13033
|
-
import * as
|
|
13179
|
+
import * as path13 from "path";
|
|
13034
13180
|
import * as os7 from "os";
|
|
13035
13181
|
var KEY_TO_VK = {
|
|
13036
13182
|
Backspace: 8,
|
|
@@ -13287,25 +13433,25 @@ function resolveSafePath(requestedPath) {
|
|
|
13287
13433
|
const inputPath = rawPath || ".";
|
|
13288
13434
|
const home = os7.homedir();
|
|
13289
13435
|
if (inputPath.startsWith("~")) {
|
|
13290
|
-
return
|
|
13436
|
+
return path13.resolve(path13.join(home, inputPath.slice(1)));
|
|
13291
13437
|
}
|
|
13292
13438
|
if (process.platform === "win32") {
|
|
13293
13439
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
13294
|
-
if (
|
|
13295
|
-
return
|
|
13440
|
+
if (path13.win32.isAbsolute(normalized)) {
|
|
13441
|
+
return path13.win32.normalize(normalized);
|
|
13296
13442
|
}
|
|
13297
|
-
return
|
|
13443
|
+
return path13.win32.resolve(normalized);
|
|
13298
13444
|
}
|
|
13299
|
-
if (
|
|
13300
|
-
return
|
|
13445
|
+
if (path13.isAbsolute(inputPath)) {
|
|
13446
|
+
return path13.normalize(inputPath);
|
|
13301
13447
|
}
|
|
13302
|
-
return
|
|
13448
|
+
return path13.resolve(inputPath);
|
|
13303
13449
|
}
|
|
13304
13450
|
function listDirectoryEntriesSafe(dirPath) {
|
|
13305
13451
|
const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
|
|
13306
13452
|
const files = [];
|
|
13307
13453
|
for (const entry of entries) {
|
|
13308
|
-
const entryPath =
|
|
13454
|
+
const entryPath = path13.join(dirPath, entry.name);
|
|
13309
13455
|
try {
|
|
13310
13456
|
if (entry.isDirectory()) {
|
|
13311
13457
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -13359,7 +13505,7 @@ async function handleFileRead(h, args) {
|
|
|
13359
13505
|
async function handleFileWrite(h, args) {
|
|
13360
13506
|
try {
|
|
13361
13507
|
const filePath = resolveSafePath(args?.path);
|
|
13362
|
-
fs5.mkdirSync(
|
|
13508
|
+
fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
13363
13509
|
fs5.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
13364
13510
|
return { success: true, path: filePath };
|
|
13365
13511
|
} catch (e) {
|
|
@@ -14479,16 +14625,16 @@ var DaemonCommandHandler = class {
|
|
|
14479
14625
|
// src/commands/cli-manager.ts
|
|
14480
14626
|
init_provider_cli_adapter();
|
|
14481
14627
|
import * as os13 from "os";
|
|
14482
|
-
import * as
|
|
14628
|
+
import * as path17 from "path";
|
|
14483
14629
|
import * as crypto4 from "crypto";
|
|
14484
|
-
import { existsSync as
|
|
14630
|
+
import { existsSync as existsSync12 } from "fs";
|
|
14485
14631
|
import { execFileSync } from "child_process";
|
|
14486
14632
|
import chalk from "chalk";
|
|
14487
14633
|
init_config();
|
|
14488
14634
|
|
|
14489
14635
|
// src/providers/cli-provider-instance.ts
|
|
14490
14636
|
import * as os12 from "os";
|
|
14491
|
-
import * as
|
|
14637
|
+
import * as path16 from "path";
|
|
14492
14638
|
import * as crypto3 from "crypto";
|
|
14493
14639
|
import * as fs6 from "fs";
|
|
14494
14640
|
import { createRequire } from "module";
|
|
@@ -14547,7 +14693,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
|
|
|
14547
14693
|
var CachedDatabaseSync = null;
|
|
14548
14694
|
function getDatabaseSync() {
|
|
14549
14695
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
14550
|
-
const requireFn = typeof __require === "function" ? __require : createRequire(
|
|
14696
|
+
const requireFn = typeof __require === "function" ? __require : createRequire(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
14551
14697
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
14552
14698
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
14553
14699
|
if (!CachedDatabaseSync) {
|
|
@@ -16618,17 +16764,17 @@ function shouldRestoreHostedRuntime(record, managerTag) {
|
|
|
16618
16764
|
// src/commands/cli-manager.ts
|
|
16619
16765
|
function isExplicitCommand(command) {
|
|
16620
16766
|
const trimmed = command.trim();
|
|
16621
|
-
return
|
|
16767
|
+
return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
16622
16768
|
}
|
|
16623
16769
|
function expandExecutable(command) {
|
|
16624
16770
|
const trimmed = command.trim();
|
|
16625
|
-
return trimmed.startsWith("~") ?
|
|
16771
|
+
return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
|
|
16626
16772
|
}
|
|
16627
16773
|
function commandExists(command) {
|
|
16628
16774
|
const trimmed = command.trim();
|
|
16629
16775
|
if (!trimmed) return false;
|
|
16630
16776
|
if (isExplicitCommand(trimmed)) {
|
|
16631
|
-
return
|
|
16777
|
+
return existsSync12(expandExecutable(trimmed));
|
|
16632
16778
|
}
|
|
16633
16779
|
try {
|
|
16634
16780
|
execFileSync(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -16903,7 +17049,7 @@ var DaemonCliManager = class {
|
|
|
16903
17049
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
16904
17050
|
const trimmed = (workingDir || "").trim();
|
|
16905
17051
|
if (!trimmed) throw new Error("working directory required");
|
|
16906
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
17052
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
|
|
16907
17053
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
16908
17054
|
const rawProvider = this.providerLoader.getByAlias(cliType);
|
|
16909
17055
|
const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
|
|
@@ -17404,11 +17550,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17404
17550
|
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
17405
17551
|
import * as net from "net";
|
|
17406
17552
|
import * as os15 from "os";
|
|
17407
|
-
import * as
|
|
17553
|
+
import * as path19 from "path";
|
|
17408
17554
|
|
|
17409
17555
|
// src/providers/provider-loader.ts
|
|
17410
17556
|
import * as fs7 from "fs";
|
|
17411
|
-
import * as
|
|
17557
|
+
import * as path18 from "path";
|
|
17412
17558
|
import * as os14 from "os";
|
|
17413
17559
|
import * as chokidar from "chokidar";
|
|
17414
17560
|
init_logger();
|
|
@@ -17732,7 +17878,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17732
17878
|
try {
|
|
17733
17879
|
if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
|
|
17734
17880
|
return ["ide", "extension", "cli", "acp"].some(
|
|
17735
|
-
(category) => fs7.existsSync(
|
|
17881
|
+
(category) => fs7.existsSync(path18.join(candidate, category))
|
|
17736
17882
|
);
|
|
17737
17883
|
} catch {
|
|
17738
17884
|
return false;
|
|
@@ -17740,20 +17886,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17740
17886
|
}
|
|
17741
17887
|
static hasProviderRootMarker(candidate) {
|
|
17742
17888
|
try {
|
|
17743
|
-
return fs7.existsSync(
|
|
17889
|
+
return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
17744
17890
|
} catch {
|
|
17745
17891
|
return false;
|
|
17746
17892
|
}
|
|
17747
17893
|
}
|
|
17748
17894
|
detectDefaultUserDir() {
|
|
17749
|
-
const fallback =
|
|
17895
|
+
const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17750
17896
|
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
17751
17897
|
const visited = /* @__PURE__ */ new Set();
|
|
17752
17898
|
for (const start of this.probeStarts) {
|
|
17753
|
-
let current =
|
|
17899
|
+
let current = path18.resolve(start);
|
|
17754
17900
|
while (!visited.has(current)) {
|
|
17755
17901
|
visited.add(current);
|
|
17756
|
-
const siblingCandidate =
|
|
17902
|
+
const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
17757
17903
|
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
17758
17904
|
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
17759
17905
|
if (envOptIn || hasMarker) {
|
|
@@ -17775,7 +17921,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17775
17921
|
return { path: siblingCandidate, source };
|
|
17776
17922
|
}
|
|
17777
17923
|
}
|
|
17778
|
-
const parent =
|
|
17924
|
+
const parent = path18.dirname(current);
|
|
17779
17925
|
if (parent === current) break;
|
|
17780
17926
|
current = parent;
|
|
17781
17927
|
}
|
|
@@ -17785,11 +17931,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17785
17931
|
constructor(options) {
|
|
17786
17932
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
17787
17933
|
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
17788
|
-
this.defaultProvidersDir =
|
|
17934
|
+
this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17789
17935
|
const detected = this.detectDefaultUserDir();
|
|
17790
17936
|
this.userDir = detected.path;
|
|
17791
17937
|
this.userDirSource = detected.source;
|
|
17792
|
-
this.upstreamDir =
|
|
17938
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17793
17939
|
this.disableUpstream = false;
|
|
17794
17940
|
this.applySourceConfig({
|
|
17795
17941
|
userDir: options?.userDir,
|
|
@@ -17848,7 +17994,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17848
17994
|
this.userDir = detected.path;
|
|
17849
17995
|
this.userDirSource = detected.source;
|
|
17850
17996
|
}
|
|
17851
|
-
this.upstreamDir =
|
|
17997
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17852
17998
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
17853
17999
|
if (this.explicitProviderDir) {
|
|
17854
18000
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -17862,7 +18008,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17862
18008
|
* Canonical provider directory shape for a given root.
|
|
17863
18009
|
*/
|
|
17864
18010
|
getProviderDir(root, category, type) {
|
|
17865
|
-
return
|
|
18011
|
+
return path18.join(root, category, type);
|
|
17866
18012
|
}
|
|
17867
18013
|
/**
|
|
17868
18014
|
* Canonical user override directory for a provider.
|
|
@@ -17889,7 +18035,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17889
18035
|
resolveProviderFile(type, ...segments) {
|
|
17890
18036
|
const dir = this.findProviderDirInternal(type);
|
|
17891
18037
|
if (!dir) return null;
|
|
17892
|
-
return
|
|
18038
|
+
return path18.join(dir, ...segments);
|
|
17893
18039
|
}
|
|
17894
18040
|
/**
|
|
17895
18041
|
* Load all providers (3-tier priority)
|
|
@@ -17928,7 +18074,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17928
18074
|
if (!fs7.existsSync(this.upstreamDir)) return false;
|
|
17929
18075
|
try {
|
|
17930
18076
|
return fs7.readdirSync(this.upstreamDir).some(
|
|
17931
|
-
(d) => fs7.statSync(
|
|
18077
|
+
(d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
|
|
17932
18078
|
);
|
|
17933
18079
|
} catch {
|
|
17934
18080
|
return false;
|
|
@@ -18425,8 +18571,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18425
18571
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
18426
18572
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
18427
18573
|
if (providerDir) {
|
|
18428
|
-
const fullDir =
|
|
18429
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18574
|
+
const fullDir = path18.join(providerDir, entry.scriptDir);
|
|
18575
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18430
18576
|
}
|
|
18431
18577
|
matched = true;
|
|
18432
18578
|
}
|
|
@@ -18441,8 +18587,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18441
18587
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18442
18588
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
18443
18589
|
if (providerDir) {
|
|
18444
|
-
const fullDir =
|
|
18445
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18590
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18591
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18446
18592
|
}
|
|
18447
18593
|
}
|
|
18448
18594
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -18459,8 +18605,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18459
18605
|
resolved._resolvedScriptDir = dirOverride;
|
|
18460
18606
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
18461
18607
|
if (providerDir) {
|
|
18462
|
-
const fullDir =
|
|
18463
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18608
|
+
const fullDir = path18.join(providerDir, dirOverride);
|
|
18609
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18464
18610
|
}
|
|
18465
18611
|
}
|
|
18466
18612
|
} else if (override.scripts) {
|
|
@@ -18476,8 +18622,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18476
18622
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18477
18623
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
18478
18624
|
if (providerDir) {
|
|
18479
|
-
const fullDir =
|
|
18480
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
18625
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
18626
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18481
18627
|
}
|
|
18482
18628
|
}
|
|
18483
18629
|
}
|
|
@@ -18509,14 +18655,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18509
18655
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
18510
18656
|
return null;
|
|
18511
18657
|
}
|
|
18512
|
-
const dir =
|
|
18658
|
+
const dir = path18.join(providerDir, scriptDir);
|
|
18513
18659
|
if (!fs7.existsSync(dir)) {
|
|
18514
18660
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
18515
18661
|
return null;
|
|
18516
18662
|
}
|
|
18517
18663
|
const cached = this.scriptsCache.get(dir);
|
|
18518
18664
|
if (cached) return cached;
|
|
18519
|
-
const scriptsJs =
|
|
18665
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
18520
18666
|
if (fs7.existsSync(scriptsJs)) {
|
|
18521
18667
|
try {
|
|
18522
18668
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -18558,7 +18704,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18558
18704
|
return;
|
|
18559
18705
|
}
|
|
18560
18706
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
18561
|
-
this.log(`File changed: ${
|
|
18707
|
+
this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
|
|
18562
18708
|
this.reload();
|
|
18563
18709
|
}
|
|
18564
18710
|
};
|
|
@@ -18613,7 +18759,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18613
18759
|
}
|
|
18614
18760
|
const https = __require("https");
|
|
18615
18761
|
const { execSync: execSync7 } = __require("child_process");
|
|
18616
|
-
const metaPath =
|
|
18762
|
+
const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
18617
18763
|
let prevEtag = "";
|
|
18618
18764
|
let prevTimestamp = 0;
|
|
18619
18765
|
try {
|
|
@@ -18673,17 +18819,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18673
18819
|
return { updated: false };
|
|
18674
18820
|
}
|
|
18675
18821
|
this.log("Downloading latest providers from GitHub...");
|
|
18676
|
-
const tmpTar =
|
|
18677
|
-
const tmpExtract =
|
|
18822
|
+
const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
18823
|
+
const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
18678
18824
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
18679
18825
|
fs7.mkdirSync(tmpExtract, { recursive: true });
|
|
18680
18826
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
18681
18827
|
const extracted = fs7.readdirSync(tmpExtract);
|
|
18682
18828
|
const rootDir = extracted.find(
|
|
18683
|
-
(d) => fs7.statSync(
|
|
18829
|
+
(d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
18684
18830
|
);
|
|
18685
18831
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
18686
|
-
const sourceDir =
|
|
18832
|
+
const sourceDir = path18.join(tmpExtract, rootDir);
|
|
18687
18833
|
const backupDir = this.upstreamDir + ".bak";
|
|
18688
18834
|
if (fs7.existsSync(this.upstreamDir)) {
|
|
18689
18835
|
if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -18758,8 +18904,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18758
18904
|
copyDirRecursive(src, dest) {
|
|
18759
18905
|
fs7.mkdirSync(dest, { recursive: true });
|
|
18760
18906
|
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
18761
|
-
const srcPath =
|
|
18762
|
-
const destPath =
|
|
18907
|
+
const srcPath = path18.join(src, entry.name);
|
|
18908
|
+
const destPath = path18.join(dest, entry.name);
|
|
18763
18909
|
if (entry.isDirectory()) {
|
|
18764
18910
|
this.copyDirRecursive(srcPath, destPath);
|
|
18765
18911
|
} else {
|
|
@@ -18770,7 +18916,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18770
18916
|
/** .meta.json save */
|
|
18771
18917
|
writeMeta(metaPath, etag, timestamp) {
|
|
18772
18918
|
try {
|
|
18773
|
-
fs7.mkdirSync(
|
|
18919
|
+
fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
|
|
18774
18920
|
fs7.writeFileSync(metaPath, JSON.stringify({
|
|
18775
18921
|
etag,
|
|
18776
18922
|
timestamp,
|
|
@@ -18787,7 +18933,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18787
18933
|
const scan = (d) => {
|
|
18788
18934
|
try {
|
|
18789
18935
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
18790
|
-
if (entry.isDirectory()) scan(
|
|
18936
|
+
if (entry.isDirectory()) scan(path18.join(d, entry.name));
|
|
18791
18937
|
else if (entry.name === "provider.json") count++;
|
|
18792
18938
|
}
|
|
18793
18939
|
} catch {
|
|
@@ -19015,17 +19161,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19015
19161
|
for (const root of searchRoots) {
|
|
19016
19162
|
if (!fs7.existsSync(root)) continue;
|
|
19017
19163
|
const candidate = this.getProviderDir(root, cat, type);
|
|
19018
|
-
if (fs7.existsSync(
|
|
19019
|
-
const catDir =
|
|
19164
|
+
if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
|
|
19165
|
+
const catDir = path18.join(root, cat);
|
|
19020
19166
|
if (fs7.existsSync(catDir)) {
|
|
19021
19167
|
try {
|
|
19022
19168
|
for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
|
|
19023
19169
|
if (!entry.isDirectory()) continue;
|
|
19024
|
-
const jsonPath =
|
|
19170
|
+
const jsonPath = path18.join(catDir, entry.name, "provider.json");
|
|
19025
19171
|
if (fs7.existsSync(jsonPath)) {
|
|
19026
19172
|
try {
|
|
19027
19173
|
const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
|
|
19028
|
-
if (data.type === type) return
|
|
19174
|
+
if (data.type === type) return path18.join(catDir, entry.name);
|
|
19029
19175
|
} catch {
|
|
19030
19176
|
}
|
|
19031
19177
|
}
|
|
@@ -19042,7 +19188,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19042
19188
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
19043
19189
|
*/
|
|
19044
19190
|
buildScriptWrappersFromDir(dir) {
|
|
19045
|
-
const scriptsJs =
|
|
19191
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
19046
19192
|
if (fs7.existsSync(scriptsJs)) {
|
|
19047
19193
|
try {
|
|
19048
19194
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -19056,7 +19202,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19056
19202
|
for (const file of fs7.readdirSync(dir)) {
|
|
19057
19203
|
if (!file.endsWith(".js")) continue;
|
|
19058
19204
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
19059
|
-
const filePath =
|
|
19205
|
+
const filePath = path18.join(dir, file);
|
|
19060
19206
|
result[scriptName] = (...args) => {
|
|
19061
19207
|
try {
|
|
19062
19208
|
let content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -19116,7 +19262,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19116
19262
|
}
|
|
19117
19263
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
19118
19264
|
if (hasJson) {
|
|
19119
|
-
const jsonPath =
|
|
19265
|
+
const jsonPath = path18.join(d, "provider.json");
|
|
19120
19266
|
try {
|
|
19121
19267
|
const raw = fs7.readFileSync(jsonPath, "utf-8");
|
|
19122
19268
|
const mod = JSON.parse(raw);
|
|
@@ -19137,7 +19283,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19137
19283
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
19138
19284
|
} else {
|
|
19139
19285
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
19140
|
-
const scriptsPath =
|
|
19286
|
+
const scriptsPath = path18.join(d, "scripts.js");
|
|
19141
19287
|
if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
|
|
19142
19288
|
try {
|
|
19143
19289
|
delete __require.cache[__require.resolve(scriptsPath)];
|
|
@@ -19163,7 +19309,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19163
19309
|
if (!entry.isDirectory()) continue;
|
|
19164
19310
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
19165
19311
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
19166
|
-
scan(
|
|
19312
|
+
scan(path18.join(d, entry.name));
|
|
19167
19313
|
}
|
|
19168
19314
|
}
|
|
19169
19315
|
};
|
|
@@ -19488,8 +19634,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
19488
19634
|
const appNameMap = getMacAppIdentifiers();
|
|
19489
19635
|
const appName = appNameMap[ideId];
|
|
19490
19636
|
if (appName) {
|
|
19491
|
-
const storagePath =
|
|
19492
|
-
process.env.APPDATA ||
|
|
19637
|
+
const storagePath = path19.join(
|
|
19638
|
+
process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
|
|
19493
19639
|
appName,
|
|
19494
19640
|
"storage.json"
|
|
19495
19641
|
);
|
|
@@ -19678,9 +19824,9 @@ init_logger();
|
|
|
19678
19824
|
|
|
19679
19825
|
// src/logging/command-log.ts
|
|
19680
19826
|
import * as fs8 from "fs";
|
|
19681
|
-
import * as
|
|
19827
|
+
import * as path20 from "path";
|
|
19682
19828
|
import * as os16 from "os";
|
|
19683
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
19829
|
+
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
19830
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
19685
19831
|
var MAX_DAYS = 7;
|
|
19686
19832
|
try {
|
|
@@ -19718,13 +19864,13 @@ function getDateStr2() {
|
|
|
19718
19864
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
19719
19865
|
}
|
|
19720
19866
|
var currentDate2 = getDateStr2();
|
|
19721
|
-
var currentFile =
|
|
19867
|
+
var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19722
19868
|
var writeCount2 = 0;
|
|
19723
19869
|
function checkRotation() {
|
|
19724
19870
|
const today = getDateStr2();
|
|
19725
19871
|
if (today !== currentDate2) {
|
|
19726
19872
|
currentDate2 = today;
|
|
19727
|
-
currentFile =
|
|
19873
|
+
currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19728
19874
|
cleanOldFiles();
|
|
19729
19875
|
}
|
|
19730
19876
|
}
|
|
@@ -19738,7 +19884,7 @@ function cleanOldFiles() {
|
|
|
19738
19884
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
19739
19885
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
19740
19886
|
try {
|
|
19741
|
-
fs8.unlinkSync(
|
|
19887
|
+
fs8.unlinkSync(path20.join(LOG_DIR2, file));
|
|
19742
19888
|
} catch {
|
|
19743
19889
|
}
|
|
19744
19890
|
}
|
|
@@ -19824,9 +19970,9 @@ cleanOldFiles();
|
|
|
19824
19970
|
init_logger();
|
|
19825
19971
|
|
|
19826
19972
|
// src/commands/mesh-coordinator.ts
|
|
19827
|
-
import { existsSync as
|
|
19973
|
+
import { existsSync as existsSync15, realpathSync as realpathSync2 } from "fs";
|
|
19828
19974
|
import { createRequire as createRequire2 } from "module";
|
|
19829
|
-
import { dirname as
|
|
19975
|
+
import { dirname as dirname4, join as join18, resolve as resolve13 } from "path";
|
|
19830
19976
|
var DEFAULT_SERVER_NAME = "adhdev-mesh";
|
|
19831
19977
|
var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
19832
19978
|
function resolveMeshCoordinatorSetup(options) {
|
|
@@ -19847,8 +19993,8 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
19847
19993
|
}
|
|
19848
19994
|
const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
|
|
19849
19995
|
if (mcpConfig.mode === "auto_import") {
|
|
19850
|
-
const
|
|
19851
|
-
if (!
|
|
19996
|
+
const path27 = mcpConfig.path?.trim();
|
|
19997
|
+
if (!path27) {
|
|
19852
19998
|
return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
|
|
19853
19999
|
}
|
|
19854
20000
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
@@ -19865,7 +20011,7 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
19865
20011
|
return {
|
|
19866
20012
|
kind: "auto_import",
|
|
19867
20013
|
serverName,
|
|
19868
|
-
configPath:
|
|
20014
|
+
configPath: join18(workspace, path27),
|
|
19869
20015
|
configFormat: mcpConfig.format,
|
|
19870
20016
|
mcpServer
|
|
19871
20017
|
};
|
|
@@ -19919,7 +20065,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
19919
20065
|
const addPackagedCandidates = (baseFile) => {
|
|
19920
20066
|
if (!baseFile) return;
|
|
19921
20067
|
const realBase = normalizeExistingPath(baseFile) || baseFile;
|
|
19922
|
-
const dir =
|
|
20068
|
+
const dir = dirname4(realBase);
|
|
19923
20069
|
addCandidate(resolve13(dir, "../vendor/mcp-server/index.js"));
|
|
19924
20070
|
addCandidate(resolve13(dir, "../../vendor/mcp-server/index.js"));
|
|
19925
20071
|
addCandidate(resolve13(dir, "../../../vendor/mcp-server/index.js"));
|
|
@@ -19932,7 +20078,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
19932
20078
|
if (normalized) return normalized;
|
|
19933
20079
|
}
|
|
19934
20080
|
try {
|
|
19935
|
-
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] :
|
|
20081
|
+
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : join18(process.cwd(), "adhdev-daemon.js");
|
|
19936
20082
|
const req = createRequire2(requireBase);
|
|
19937
20083
|
const resolvedModule = req.resolve("@adhdev/mcp-server");
|
|
19938
20084
|
return normalizeExistingPath(resolvedModule) || resolvedModule;
|
|
@@ -19942,7 +20088,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
19942
20088
|
}
|
|
19943
20089
|
function normalizeExistingPath(filePath) {
|
|
19944
20090
|
try {
|
|
19945
|
-
if (!
|
|
20091
|
+
if (!existsSync15(filePath)) return null;
|
|
19946
20092
|
return realpathSync2.native(filePath);
|
|
19947
20093
|
} catch {
|
|
19948
20094
|
return null;
|
|
@@ -20267,13 +20413,13 @@ import { execFileSync as execFileSync2 } from "child_process";
|
|
|
20267
20413
|
import { spawn as spawn3 } from "child_process";
|
|
20268
20414
|
import * as fs9 from "fs";
|
|
20269
20415
|
import * as os18 from "os";
|
|
20270
|
-
import * as
|
|
20416
|
+
import * as path21 from "path";
|
|
20271
20417
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
20272
20418
|
function getUpgradeLogPath() {
|
|
20273
20419
|
const home = os18.homedir();
|
|
20274
|
-
const dir =
|
|
20420
|
+
const dir = path21.join(home, ".adhdev");
|
|
20275
20421
|
fs9.mkdirSync(dir, { recursive: true });
|
|
20276
|
-
return
|
|
20422
|
+
return path21.join(dir, "daemon-upgrade.log");
|
|
20277
20423
|
}
|
|
20278
20424
|
function appendUpgradeLog(message) {
|
|
20279
20425
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -20284,14 +20430,14 @@ function appendUpgradeLog(message) {
|
|
|
20284
20430
|
}
|
|
20285
20431
|
}
|
|
20286
20432
|
function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
|
|
20287
|
-
const binDir =
|
|
20433
|
+
const binDir = path21.dirname(nodeExecutable);
|
|
20288
20434
|
if (platform10 === "win32") {
|
|
20289
|
-
const npmCliPath =
|
|
20435
|
+
const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
20290
20436
|
if (fs9.existsSync(npmCliPath)) {
|
|
20291
20437
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20292
20438
|
}
|
|
20293
20439
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
20294
|
-
const candidatePath =
|
|
20440
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20295
20441
|
if (fs9.existsSync(candidatePath)) {
|
|
20296
20442
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20297
20443
|
}
|
|
@@ -20299,7 +20445,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
20299
20445
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20300
20446
|
}
|
|
20301
20447
|
for (const candidate of ["npm"]) {
|
|
20302
|
-
const candidatePath =
|
|
20448
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20303
20449
|
if (fs9.existsSync(candidatePath)) {
|
|
20304
20450
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20305
20451
|
}
|
|
@@ -20316,13 +20462,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20316
20462
|
let currentDir = resolvedPath;
|
|
20317
20463
|
try {
|
|
20318
20464
|
if (fs9.statSync(resolvedPath).isFile()) {
|
|
20319
|
-
currentDir =
|
|
20465
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20320
20466
|
}
|
|
20321
20467
|
} catch {
|
|
20322
|
-
currentDir =
|
|
20468
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20323
20469
|
}
|
|
20324
20470
|
while (true) {
|
|
20325
|
-
const packageJsonPath =
|
|
20471
|
+
const packageJsonPath = path21.join(currentDir, "package.json");
|
|
20326
20472
|
try {
|
|
20327
20473
|
if (fs9.existsSync(packageJsonPath)) {
|
|
20328
20474
|
const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -20333,7 +20479,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20333
20479
|
}
|
|
20334
20480
|
} catch {
|
|
20335
20481
|
}
|
|
20336
|
-
const parentDir =
|
|
20482
|
+
const parentDir = path21.dirname(currentDir);
|
|
20337
20483
|
if (parentDir === currentDir) {
|
|
20338
20484
|
return null;
|
|
20339
20485
|
}
|
|
@@ -20341,13 +20487,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20341
20487
|
}
|
|
20342
20488
|
}
|
|
20343
20489
|
function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
|
|
20344
|
-
const nodeModulesDir = packageName.startsWith("@") ?
|
|
20345
|
-
if (
|
|
20490
|
+
const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
|
|
20491
|
+
if (path21.basename(nodeModulesDir) !== "node_modules") {
|
|
20346
20492
|
return null;
|
|
20347
20493
|
}
|
|
20348
|
-
const maybeLibDir =
|
|
20349
|
-
if (
|
|
20350
|
-
return
|
|
20494
|
+
const maybeLibDir = path21.dirname(nodeModulesDir);
|
|
20495
|
+
if (path21.basename(maybeLibDir) === "lib") {
|
|
20496
|
+
return path21.dirname(maybeLibDir);
|
|
20351
20497
|
}
|
|
20352
20498
|
return maybeLibDir;
|
|
20353
20499
|
}
|
|
@@ -20462,7 +20608,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
20462
20608
|
}
|
|
20463
20609
|
}
|
|
20464
20610
|
function stopSessionHostProcesses(appName) {
|
|
20465
|
-
const pidFile =
|
|
20611
|
+
const pidFile = path21.join(os18.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
20466
20612
|
try {
|
|
20467
20613
|
if (fs9.existsSync(pidFile)) {
|
|
20468
20614
|
const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -20479,7 +20625,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
20479
20625
|
}
|
|
20480
20626
|
}
|
|
20481
20627
|
function removeDaemonPidFile() {
|
|
20482
|
-
const pidFile =
|
|
20628
|
+
const pidFile = path21.join(os18.homedir(), ".adhdev", "daemon.pid");
|
|
20483
20629
|
try {
|
|
20484
20630
|
fs9.unlinkSync(pidFile);
|
|
20485
20631
|
} catch {
|
|
@@ -20490,7 +20636,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20490
20636
|
const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20491
20637
|
if (!npmRoot) return;
|
|
20492
20638
|
const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20493
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
20639
|
+
const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
|
|
20494
20640
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
20495
20641
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
20496
20642
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -20498,25 +20644,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20498
20644
|
}
|
|
20499
20645
|
if (pkgName.startsWith("@")) {
|
|
20500
20646
|
const [scope, name] = pkgName.split("/");
|
|
20501
|
-
const scopeDir =
|
|
20647
|
+
const scopeDir = path21.join(npmRoot, scope);
|
|
20502
20648
|
if (!fs9.existsSync(scopeDir)) return;
|
|
20503
20649
|
for (const entry of fs9.readdirSync(scopeDir)) {
|
|
20504
20650
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
20505
|
-
fs9.rmSync(
|
|
20506
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
20651
|
+
fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
|
|
20652
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
|
|
20507
20653
|
}
|
|
20508
20654
|
} else {
|
|
20509
20655
|
for (const entry of fs9.readdirSync(npmRoot)) {
|
|
20510
20656
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
20511
|
-
fs9.rmSync(
|
|
20512
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
20657
|
+
fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
|
|
20658
|
+
appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
|
|
20513
20659
|
}
|
|
20514
20660
|
}
|
|
20515
20661
|
if (fs9.existsSync(binDir)) {
|
|
20516
20662
|
for (const entry of fs9.readdirSync(binDir)) {
|
|
20517
20663
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
20518
|
-
fs9.rmSync(
|
|
20519
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
20664
|
+
fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
|
|
20665
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
|
|
20520
20666
|
}
|
|
20521
20667
|
}
|
|
20522
20668
|
}
|
|
@@ -20715,6 +20861,40 @@ var DaemonCommandRouter = class {
|
|
|
20715
20861
|
constructor(deps) {
|
|
20716
20862
|
this.deps = deps;
|
|
20717
20863
|
}
|
|
20864
|
+
getCachedInlineMesh(meshId, inlineMesh) {
|
|
20865
|
+
if (inlineMesh && typeof inlineMesh === "object") {
|
|
20866
|
+
this.inlineMeshCache.set(meshId, inlineMesh);
|
|
20867
|
+
return inlineMesh;
|
|
20868
|
+
}
|
|
20869
|
+
return this.inlineMeshCache.get(meshId);
|
|
20870
|
+
}
|
|
20871
|
+
async getMeshForCommand(meshId, inlineMesh) {
|
|
20872
|
+
try {
|
|
20873
|
+
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
20874
|
+
const mesh = getMesh3(meshId);
|
|
20875
|
+
if (mesh) return { mesh, inline: false };
|
|
20876
|
+
} catch {
|
|
20877
|
+
}
|
|
20878
|
+
const cached = this.getCachedInlineMesh(meshId, inlineMesh);
|
|
20879
|
+
return cached ? { mesh: cached, inline: true } : null;
|
|
20880
|
+
}
|
|
20881
|
+
updateInlineMeshNode(meshId, mesh, node) {
|
|
20882
|
+
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
20883
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
|
|
20884
|
+
if (idx >= 0) mesh.nodes[idx] = node;
|
|
20885
|
+
else mesh.nodes.push(node);
|
|
20886
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20887
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
20888
|
+
}
|
|
20889
|
+
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
20890
|
+
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
20891
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
|
|
20892
|
+
if (idx === -1) return false;
|
|
20893
|
+
mesh.nodes.splice(idx, 1);
|
|
20894
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
20895
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
20896
|
+
return true;
|
|
20897
|
+
}
|
|
20718
20898
|
async traceSessionHostAction(action, args, run, summarizeResult) {
|
|
20719
20899
|
const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
|
|
20720
20900
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
|
|
@@ -21414,13 +21594,94 @@ var DaemonCommandRouter = class {
|
|
|
21414
21594
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
21415
21595
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
21416
21596
|
try {
|
|
21417
|
-
const
|
|
21418
|
-
const
|
|
21597
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
21598
|
+
const mesh = meshRecord?.mesh;
|
|
21599
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
21600
|
+
if (node?.isLocalWorktree && node.workspace) {
|
|
21601
|
+
try {
|
|
21602
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
21603
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
21604
|
+
if (repoRoot) {
|
|
21605
|
+
const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
21606
|
+
await removeWorktree2(repoRoot, node.workspace);
|
|
21607
|
+
}
|
|
21608
|
+
} catch (e) {
|
|
21609
|
+
LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
|
|
21610
|
+
}
|
|
21611
|
+
}
|
|
21612
|
+
let removed = false;
|
|
21613
|
+
if (meshRecord?.inline) {
|
|
21614
|
+
removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
|
|
21615
|
+
} else {
|
|
21616
|
+
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21617
|
+
removed = removeNode3(meshId, nodeId);
|
|
21618
|
+
}
|
|
21419
21619
|
return { success: true, removed };
|
|
21420
21620
|
} catch (e) {
|
|
21421
21621
|
return { success: false, error: e.message };
|
|
21422
21622
|
}
|
|
21423
21623
|
}
|
|
21624
|
+
case "clone_mesh_node": {
|
|
21625
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
21626
|
+
const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
|
|
21627
|
+
const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
|
|
21628
|
+
const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
|
|
21629
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
21630
|
+
if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
|
|
21631
|
+
if (!branch) return { success: false, error: "branch required" };
|
|
21632
|
+
try {
|
|
21633
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
21634
|
+
const mesh = meshRecord?.mesh;
|
|
21635
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
21636
|
+
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
21637
|
+
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
21638
|
+
const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
|
|
21639
|
+
const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
21640
|
+
const result = await createWorktree2({
|
|
21641
|
+
repoRoot,
|
|
21642
|
+
branch,
|
|
21643
|
+
baseBranch,
|
|
21644
|
+
meshName: mesh.name
|
|
21645
|
+
});
|
|
21646
|
+
let node;
|
|
21647
|
+
if (meshRecord.inline) {
|
|
21648
|
+
const { randomUUID: randomUUID8 } = await import("crypto");
|
|
21649
|
+
node = {
|
|
21650
|
+
id: `node_${randomUUID8().replace(/-/g, "")}`,
|
|
21651
|
+
workspace: result.worktreePath,
|
|
21652
|
+
repoRoot: result.worktreePath,
|
|
21653
|
+
daemonId: sourceNode.daemonId,
|
|
21654
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
21655
|
+
policy: { ...sourceNode.policy || {} },
|
|
21656
|
+
isLocalWorktree: true,
|
|
21657
|
+
worktreeBranch: result.branch,
|
|
21658
|
+
clonedFromNodeId: sourceNodeId
|
|
21659
|
+
};
|
|
21660
|
+
this.updateInlineMeshNode(meshId, mesh, node);
|
|
21661
|
+
} else {
|
|
21662
|
+
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21663
|
+
node = addNode3(meshId, {
|
|
21664
|
+
workspace: result.worktreePath,
|
|
21665
|
+
repoRoot: result.worktreePath,
|
|
21666
|
+
daemonId: sourceNode.daemonId,
|
|
21667
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
21668
|
+
isLocalWorktree: true,
|
|
21669
|
+
worktreeBranch: result.branch,
|
|
21670
|
+
clonedFromNodeId: sourceNodeId,
|
|
21671
|
+
policy: { ...sourceNode.policy || {} }
|
|
21672
|
+
});
|
|
21673
|
+
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
21674
|
+
}
|
|
21675
|
+
return {
|
|
21676
|
+
success: true,
|
|
21677
|
+
node,
|
|
21678
|
+
worktreePath: result.worktreePath,
|
|
21679
|
+
branch: result.branch
|
|
21680
|
+
};
|
|
21681
|
+
} catch (e) {
|
|
21682
|
+
return { success: false, error: e.message };
|
|
21683
|
+
}
|
|
21684
|
+
}
|
|
21424
21685
|
// ─── Mesh Coordinator Launch ───
|
|
21425
21686
|
case "launch_mesh_coordinator": {
|
|
21426
21687
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -21489,9 +21750,24 @@ var DaemonCommandRouter = class {
|
|
|
21489
21750
|
workspace
|
|
21490
21751
|
};
|
|
21491
21752
|
}
|
|
21492
|
-
|
|
21753
|
+
let systemPrompt = "";
|
|
21754
|
+
try {
|
|
21755
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
21756
|
+
} catch (error) {
|
|
21757
|
+
const message = error?.message || String(error);
|
|
21758
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
21759
|
+
return {
|
|
21760
|
+
success: false,
|
|
21761
|
+
code: "mesh_coordinator_prompt_failed",
|
|
21762
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
21763
|
+
meshId,
|
|
21764
|
+
cliType,
|
|
21765
|
+
workspace
|
|
21766
|
+
};
|
|
21767
|
+
}
|
|
21768
|
+
const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync12, copyFileSync: copyFileSync3 } = await import("fs");
|
|
21493
21769
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
21494
|
-
const hadExistingMcpConfig =
|
|
21770
|
+
const hadExistingMcpConfig = existsSync23(mcpConfigPath);
|
|
21495
21771
|
let existingMcpConfig = {};
|
|
21496
21772
|
if (hadExistingMcpConfig) {
|
|
21497
21773
|
try {
|
|
@@ -21519,12 +21795,6 @@ var DaemonCommandRouter = class {
|
|
|
21519
21795
|
};
|
|
21520
21796
|
writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
21521
21797
|
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
21798
|
const cliArgs = [];
|
|
21529
21799
|
if (systemPrompt) {
|
|
21530
21800
|
cliArgs.push("--append-system-prompt", systemPrompt);
|
|
@@ -23196,11 +23466,11 @@ var ProviderInstanceManager = class {
|
|
|
23196
23466
|
|
|
23197
23467
|
// src/providers/version-archive.ts
|
|
23198
23468
|
import * as fs11 from "fs";
|
|
23199
|
-
import * as
|
|
23469
|
+
import * as path22 from "path";
|
|
23200
23470
|
import * as os19 from "os";
|
|
23201
23471
|
import { execSync as execSync5 } from "child_process";
|
|
23202
23472
|
import { platform as platform8 } from "os";
|
|
23203
|
-
var ARCHIVE_PATH =
|
|
23473
|
+
var ARCHIVE_PATH = path22.join(os19.homedir(), ".adhdev", "version-history.json");
|
|
23204
23474
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
23205
23475
|
var VersionArchive = class {
|
|
23206
23476
|
history = {};
|
|
@@ -23247,7 +23517,7 @@ var VersionArchive = class {
|
|
|
23247
23517
|
}
|
|
23248
23518
|
save() {
|
|
23249
23519
|
try {
|
|
23250
|
-
fs11.mkdirSync(
|
|
23520
|
+
fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
|
|
23251
23521
|
fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
23252
23522
|
} catch {
|
|
23253
23523
|
}
|
|
@@ -23304,7 +23574,7 @@ function checkPathExists2(paths) {
|
|
|
23304
23574
|
for (const p of paths) {
|
|
23305
23575
|
if (p.includes("*")) {
|
|
23306
23576
|
const home = os19.homedir();
|
|
23307
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
23577
|
+
const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
|
|
23308
23578
|
if (fs11.existsSync(resolved)) return resolved;
|
|
23309
23579
|
} else {
|
|
23310
23580
|
if (fs11.existsSync(p)) return p;
|
|
@@ -23314,7 +23584,7 @@ function checkPathExists2(paths) {
|
|
|
23314
23584
|
}
|
|
23315
23585
|
function getMacAppVersion(appPath) {
|
|
23316
23586
|
if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
23317
|
-
const plistPath =
|
|
23587
|
+
const plistPath = path22.join(appPath, "Contents", "Info.plist");
|
|
23318
23588
|
if (!fs11.existsSync(plistPath)) return null;
|
|
23319
23589
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
23320
23590
|
return raw || null;
|
|
@@ -23340,7 +23610,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23340
23610
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
23341
23611
|
let resolvedBin = cliBin;
|
|
23342
23612
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
23343
|
-
const bundled =
|
|
23613
|
+
const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
23344
23614
|
if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
|
|
23345
23615
|
}
|
|
23346
23616
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -23381,7 +23651,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23381
23651
|
// src/daemon/dev-server.ts
|
|
23382
23652
|
import * as http2 from "http";
|
|
23383
23653
|
import * as fs15 from "fs";
|
|
23384
|
-
import * as
|
|
23654
|
+
import * as path26 from "path";
|
|
23385
23655
|
init_config();
|
|
23386
23656
|
|
|
23387
23657
|
// src/daemon/scaffold-template.ts
|
|
@@ -23733,7 +24003,7 @@ init_logger();
|
|
|
23733
24003
|
// src/daemon/dev-cdp-handlers.ts
|
|
23734
24004
|
init_logger();
|
|
23735
24005
|
import * as fs12 from "fs";
|
|
23736
|
-
import * as
|
|
24006
|
+
import * as path23 from "path";
|
|
23737
24007
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
23738
24008
|
const body = await ctx.readBody(req);
|
|
23739
24009
|
const { expression, timeout, ideType } = body;
|
|
@@ -23911,17 +24181,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
23911
24181
|
return;
|
|
23912
24182
|
}
|
|
23913
24183
|
let scriptsPath = "";
|
|
23914
|
-
const directScripts =
|
|
24184
|
+
const directScripts = path23.join(dir, "scripts.js");
|
|
23915
24185
|
if (fs12.existsSync(directScripts)) {
|
|
23916
24186
|
scriptsPath = directScripts;
|
|
23917
24187
|
} else {
|
|
23918
|
-
const scriptsDir =
|
|
24188
|
+
const scriptsDir = path23.join(dir, "scripts");
|
|
23919
24189
|
if (fs12.existsSync(scriptsDir)) {
|
|
23920
24190
|
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
23921
|
-
return fs12.statSync(
|
|
24191
|
+
return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
|
|
23922
24192
|
}).sort().reverse();
|
|
23923
24193
|
for (const ver of versions) {
|
|
23924
|
-
const p =
|
|
24194
|
+
const p = path23.join(scriptsDir, ver, "scripts.js");
|
|
23925
24195
|
if (fs12.existsSync(p)) {
|
|
23926
24196
|
scriptsPath = p;
|
|
23927
24197
|
break;
|
|
@@ -24750,7 +25020,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
24750
25020
|
|
|
24751
25021
|
// src/daemon/dev-cli-debug.ts
|
|
24752
25022
|
import * as fs13 from "fs";
|
|
24753
|
-
import * as
|
|
25023
|
+
import * as path24 from "path";
|
|
24754
25024
|
function slugifyFixtureName(value) {
|
|
24755
25025
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
24756
25026
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -24760,11 +25030,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
24760
25030
|
if (!providerDir) {
|
|
24761
25031
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
24762
25032
|
}
|
|
24763
|
-
return
|
|
25033
|
+
return path24.join(providerDir, "fixtures");
|
|
24764
25034
|
}
|
|
24765
25035
|
function readCliFixture(ctx, type, name) {
|
|
24766
25036
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
24767
|
-
const filePath =
|
|
25037
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
24768
25038
|
if (!fs13.existsSync(filePath)) {
|
|
24769
25039
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
24770
25040
|
}
|
|
@@ -25531,7 +25801,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
25531
25801
|
},
|
|
25532
25802
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
25533
25803
|
};
|
|
25534
|
-
const filePath =
|
|
25804
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
25535
25805
|
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
25536
25806
|
ctx.json(res, 200, {
|
|
25537
25807
|
saved: true,
|
|
@@ -25555,7 +25825,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
25555
25825
|
return;
|
|
25556
25826
|
}
|
|
25557
25827
|
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 =
|
|
25828
|
+
const fullPath = path24.join(fixtureDir, file);
|
|
25559
25829
|
try {
|
|
25560
25830
|
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
25561
25831
|
return {
|
|
@@ -25691,7 +25961,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
25691
25961
|
|
|
25692
25962
|
// src/daemon/dev-auto-implement.ts
|
|
25693
25963
|
import * as fs14 from "fs";
|
|
25694
|
-
import * as
|
|
25964
|
+
import * as path25 from "path";
|
|
25695
25965
|
import * as os20 from "os";
|
|
25696
25966
|
function getAutoImplPid(ctx) {
|
|
25697
25967
|
const pid = ctx.autoImplProcess?.pid;
|
|
@@ -25741,22 +26011,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
25741
26011
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
25742
26012
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
25743
26013
|
try {
|
|
25744
|
-
return fs14.statSync(
|
|
26014
|
+
return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
|
|
25745
26015
|
} catch {
|
|
25746
26016
|
return false;
|
|
25747
26017
|
}
|
|
25748
26018
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
25749
26019
|
if (versions.length === 0) return null;
|
|
25750
|
-
return
|
|
26020
|
+
return path25.join(scriptsDir, versions[0]);
|
|
25751
26021
|
}
|
|
25752
26022
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
25753
|
-
const canonicalUserDir =
|
|
25754
|
-
const desiredDir = requestedDir ?
|
|
25755
|
-
const upstreamRoot =
|
|
25756
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
26023
|
+
const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
26024
|
+
const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
|
|
26025
|
+
const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
|
|
26026
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
|
|
25757
26027
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
25758
26028
|
}
|
|
25759
|
-
if (
|
|
26029
|
+
if (path25.basename(desiredDir) !== type) {
|
|
25760
26030
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
25761
26031
|
}
|
|
25762
26032
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -25764,11 +26034,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
25764
26034
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
25765
26035
|
}
|
|
25766
26036
|
if (!fs14.existsSync(desiredDir)) {
|
|
25767
|
-
fs14.mkdirSync(
|
|
26037
|
+
fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
|
|
25768
26038
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
25769
26039
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
25770
26040
|
}
|
|
25771
|
-
const providerJson =
|
|
26041
|
+
const providerJson = path25.join(desiredDir, "provider.json");
|
|
25772
26042
|
if (!fs14.existsSync(providerJson)) {
|
|
25773
26043
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
25774
26044
|
}
|
|
@@ -25779,13 +26049,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
25779
26049
|
const refDir = ctx.findProviderDir(referenceType);
|
|
25780
26050
|
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
25781
26051
|
const referenceScripts = {};
|
|
25782
|
-
const scriptsDir =
|
|
26052
|
+
const scriptsDir = path25.join(refDir, "scripts");
|
|
25783
26053
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
25784
26054
|
if (!latestDir) return referenceScripts;
|
|
25785
26055
|
for (const file of fs14.readdirSync(latestDir)) {
|
|
25786
26056
|
if (!file.endsWith(".js")) continue;
|
|
25787
26057
|
try {
|
|
25788
|
-
referenceScripts[file] = fs14.readFileSync(
|
|
26058
|
+
referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
|
|
25789
26059
|
} catch {
|
|
25790
26060
|
}
|
|
25791
26061
|
}
|
|
@@ -25893,9 +26163,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
25893
26163
|
});
|
|
25894
26164
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
25895
26165
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
25896
|
-
const tmpDir =
|
|
26166
|
+
const tmpDir = path25.join(os20.tmpdir(), "adhdev-autoimpl");
|
|
25897
26167
|
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
25898
|
-
const promptFile =
|
|
26168
|
+
const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
25899
26169
|
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
25900
26170
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
25901
26171
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -26327,7 +26597,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26327
26597
|
setMode: "set_mode.js"
|
|
26328
26598
|
};
|
|
26329
26599
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26330
|
-
const scriptsDir =
|
|
26600
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26331
26601
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26332
26602
|
if (latestScriptsDir) {
|
|
26333
26603
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26338,7 +26608,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26338
26608
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
26339
26609
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
26340
26610
|
try {
|
|
26341
|
-
const content = fs14.readFileSync(
|
|
26611
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26342
26612
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26343
26613
|
lines.push("```javascript");
|
|
26344
26614
|
lines.push(content);
|
|
@@ -26355,7 +26625,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26355
26625
|
lines.push("");
|
|
26356
26626
|
for (const file of refFiles) {
|
|
26357
26627
|
try {
|
|
26358
|
-
const content = fs14.readFileSync(
|
|
26628
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26359
26629
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26360
26630
|
lines.push("```javascript");
|
|
26361
26631
|
lines.push(content);
|
|
@@ -26396,10 +26666,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26396
26666
|
lines.push("");
|
|
26397
26667
|
}
|
|
26398
26668
|
}
|
|
26399
|
-
const docsDir =
|
|
26669
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26400
26670
|
const loadGuide = (name) => {
|
|
26401
26671
|
try {
|
|
26402
|
-
const p =
|
|
26672
|
+
const p = path25.join(docsDir, name);
|
|
26403
26673
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26404
26674
|
} catch {
|
|
26405
26675
|
}
|
|
@@ -26636,7 +26906,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26636
26906
|
parseApproval: "parse_approval.js"
|
|
26637
26907
|
};
|
|
26638
26908
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26639
|
-
const scriptsDir =
|
|
26909
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26640
26910
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26641
26911
|
if (latestScriptsDir) {
|
|
26642
26912
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26648,7 +26918,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26648
26918
|
if (!file.endsWith(".js")) continue;
|
|
26649
26919
|
if (!targetFileNames.has(file)) continue;
|
|
26650
26920
|
try {
|
|
26651
|
-
const content = fs14.readFileSync(
|
|
26921
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26652
26922
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26653
26923
|
lines.push("```javascript");
|
|
26654
26924
|
lines.push(content);
|
|
@@ -26664,7 +26934,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26664
26934
|
lines.push("");
|
|
26665
26935
|
for (const file of refFiles) {
|
|
26666
26936
|
try {
|
|
26667
|
-
const content = fs14.readFileSync(
|
|
26937
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26668
26938
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26669
26939
|
lines.push("```javascript");
|
|
26670
26940
|
lines.push(content);
|
|
@@ -26697,10 +26967,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26697
26967
|
lines.push("");
|
|
26698
26968
|
}
|
|
26699
26969
|
}
|
|
26700
|
-
const docsDir =
|
|
26970
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26701
26971
|
const loadGuide = (name) => {
|
|
26702
26972
|
try {
|
|
26703
|
-
const p =
|
|
26973
|
+
const p = path25.join(docsDir, name);
|
|
26704
26974
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26705
26975
|
} catch {
|
|
26706
26976
|
}
|
|
@@ -27147,8 +27417,8 @@ var DevServer = class _DevServer {
|
|
|
27147
27417
|
}
|
|
27148
27418
|
getEndpointList() {
|
|
27149
27419
|
return this.routes.map((r) => {
|
|
27150
|
-
const
|
|
27151
|
-
return `${r.method.padEnd(5)} ${
|
|
27420
|
+
const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
27421
|
+
return `${r.method.padEnd(5)} ${path27}`;
|
|
27152
27422
|
});
|
|
27153
27423
|
}
|
|
27154
27424
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -27436,12 +27706,12 @@ var DevServer = class _DevServer {
|
|
|
27436
27706
|
// ─── DevConsole SPA ───
|
|
27437
27707
|
getConsoleDistDir() {
|
|
27438
27708
|
const candidates = [
|
|
27439
|
-
|
|
27440
|
-
|
|
27441
|
-
|
|
27709
|
+
path26.resolve(__dirname, "../../web-devconsole/dist"),
|
|
27710
|
+
path26.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
27711
|
+
path26.join(process.cwd(), "packages/web-devconsole/dist")
|
|
27442
27712
|
];
|
|
27443
27713
|
for (const dir of candidates) {
|
|
27444
|
-
if (fs15.existsSync(
|
|
27714
|
+
if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
|
|
27445
27715
|
}
|
|
27446
27716
|
return null;
|
|
27447
27717
|
}
|
|
@@ -27451,7 +27721,7 @@ var DevServer = class _DevServer {
|
|
|
27451
27721
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
27452
27722
|
return;
|
|
27453
27723
|
}
|
|
27454
|
-
const htmlPath =
|
|
27724
|
+
const htmlPath = path26.join(distDir, "index.html");
|
|
27455
27725
|
try {
|
|
27456
27726
|
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
27457
27727
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -27476,15 +27746,15 @@ var DevServer = class _DevServer {
|
|
|
27476
27746
|
this.json(res, 404, { error: "Not found" });
|
|
27477
27747
|
return;
|
|
27478
27748
|
}
|
|
27479
|
-
const safePath =
|
|
27480
|
-
const filePath =
|
|
27749
|
+
const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
|
|
27750
|
+
const filePath = path26.join(distDir, safePath);
|
|
27481
27751
|
if (!filePath.startsWith(distDir)) {
|
|
27482
27752
|
this.json(res, 403, { error: "Forbidden" });
|
|
27483
27753
|
return;
|
|
27484
27754
|
}
|
|
27485
27755
|
try {
|
|
27486
27756
|
const content = fs15.readFileSync(filePath);
|
|
27487
|
-
const ext =
|
|
27757
|
+
const ext = path26.extname(filePath);
|
|
27488
27758
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
27489
27759
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
27490
27760
|
res.end(content);
|
|
@@ -27597,9 +27867,9 @@ var DevServer = class _DevServer {
|
|
|
27597
27867
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
27598
27868
|
if (entry.isDirectory()) {
|
|
27599
27869
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
27600
|
-
scan(
|
|
27870
|
+
scan(path26.join(d, entry.name), rel);
|
|
27601
27871
|
} else {
|
|
27602
|
-
const stat2 = fs15.statSync(
|
|
27872
|
+
const stat2 = fs15.statSync(path26.join(d, entry.name));
|
|
27603
27873
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
27604
27874
|
}
|
|
27605
27875
|
}
|
|
@@ -27622,7 +27892,7 @@ var DevServer = class _DevServer {
|
|
|
27622
27892
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27623
27893
|
return;
|
|
27624
27894
|
}
|
|
27625
|
-
const fullPath =
|
|
27895
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27626
27896
|
if (!fullPath.startsWith(dir)) {
|
|
27627
27897
|
this.json(res, 403, { error: "Forbidden" });
|
|
27628
27898
|
return;
|
|
@@ -27647,14 +27917,14 @@ var DevServer = class _DevServer {
|
|
|
27647
27917
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27648
27918
|
return;
|
|
27649
27919
|
}
|
|
27650
|
-
const fullPath =
|
|
27920
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27651
27921
|
if (!fullPath.startsWith(dir)) {
|
|
27652
27922
|
this.json(res, 403, { error: "Forbidden" });
|
|
27653
27923
|
return;
|
|
27654
27924
|
}
|
|
27655
27925
|
try {
|
|
27656
27926
|
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
27657
|
-
fs15.mkdirSync(
|
|
27927
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27658
27928
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27659
27929
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
27660
27930
|
this.providerLoader.reload();
|
|
@@ -27671,7 +27941,7 @@ var DevServer = class _DevServer {
|
|
|
27671
27941
|
return;
|
|
27672
27942
|
}
|
|
27673
27943
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
27674
|
-
const p =
|
|
27944
|
+
const p = path26.join(dir, name);
|
|
27675
27945
|
if (fs15.existsSync(p)) {
|
|
27676
27946
|
const source = fs15.readFileSync(p, "utf-8");
|
|
27677
27947
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -27692,8 +27962,8 @@ var DevServer = class _DevServer {
|
|
|
27692
27962
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
27693
27963
|
return;
|
|
27694
27964
|
}
|
|
27695
|
-
const target = fs15.existsSync(
|
|
27696
|
-
const targetPath =
|
|
27965
|
+
const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
27966
|
+
const targetPath = path26.join(dir, target);
|
|
27697
27967
|
try {
|
|
27698
27968
|
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
27699
27969
|
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -27840,7 +28110,7 @@ var DevServer = class _DevServer {
|
|
|
27840
28110
|
}
|
|
27841
28111
|
let targetDir;
|
|
27842
28112
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
27843
|
-
const jsonPath =
|
|
28113
|
+
const jsonPath = path26.join(targetDir, "provider.json");
|
|
27844
28114
|
if (fs15.existsSync(jsonPath)) {
|
|
27845
28115
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
27846
28116
|
return;
|
|
@@ -27852,8 +28122,8 @@ var DevServer = class _DevServer {
|
|
|
27852
28122
|
const createdFiles = ["provider.json"];
|
|
27853
28123
|
if (result.files) {
|
|
27854
28124
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
27855
|
-
const fullPath =
|
|
27856
|
-
fs15.mkdirSync(
|
|
28125
|
+
const fullPath = path26.join(targetDir, relPath);
|
|
28126
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27857
28127
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27858
28128
|
createdFiles.push(relPath);
|
|
27859
28129
|
}
|
|
@@ -27906,22 +28176,22 @@ var DevServer = class _DevServer {
|
|
|
27906
28176
|
if (!fs15.existsSync(scriptsDir)) return null;
|
|
27907
28177
|
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
27908
28178
|
try {
|
|
27909
|
-
return fs15.statSync(
|
|
28179
|
+
return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
|
|
27910
28180
|
} catch {
|
|
27911
28181
|
return false;
|
|
27912
28182
|
}
|
|
27913
28183
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
27914
28184
|
if (versions.length === 0) return null;
|
|
27915
|
-
return
|
|
28185
|
+
return path26.join(scriptsDir, versions[0]);
|
|
27916
28186
|
}
|
|
27917
28187
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
27918
|
-
const canonicalUserDir =
|
|
27919
|
-
const desiredDir = requestedDir ?
|
|
27920
|
-
const upstreamRoot =
|
|
27921
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
28188
|
+
const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
28189
|
+
const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
|
|
28190
|
+
const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
|
|
28191
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
|
|
27922
28192
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
27923
28193
|
}
|
|
27924
|
-
if (
|
|
28194
|
+
if (path26.basename(desiredDir) !== type) {
|
|
27925
28195
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
27926
28196
|
}
|
|
27927
28197
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -27929,11 +28199,11 @@ var DevServer = class _DevServer {
|
|
|
27929
28199
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
27930
28200
|
}
|
|
27931
28201
|
if (!fs15.existsSync(desiredDir)) {
|
|
27932
|
-
fs15.mkdirSync(
|
|
28202
|
+
fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
|
|
27933
28203
|
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
27934
28204
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
27935
28205
|
}
|
|
27936
|
-
const providerJson =
|
|
28206
|
+
const providerJson = path26.join(desiredDir, "provider.json");
|
|
27937
28207
|
if (!fs15.existsSync(providerJson)) {
|
|
27938
28208
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
27939
28209
|
}
|
|
@@ -27969,7 +28239,7 @@ var DevServer = class _DevServer {
|
|
|
27969
28239
|
setMode: "set_mode.js"
|
|
27970
28240
|
};
|
|
27971
28241
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
27972
|
-
const scriptsDir =
|
|
28242
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
27973
28243
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
27974
28244
|
if (latestScriptsDir) {
|
|
27975
28245
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -27980,7 +28250,7 @@ var DevServer = class _DevServer {
|
|
|
27980
28250
|
for (const file of fs15.readdirSync(latestScriptsDir)) {
|
|
27981
28251
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
27982
28252
|
try {
|
|
27983
|
-
const content = fs15.readFileSync(
|
|
28253
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
27984
28254
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
27985
28255
|
lines.push("```javascript");
|
|
27986
28256
|
lines.push(content);
|
|
@@ -27997,7 +28267,7 @@ var DevServer = class _DevServer {
|
|
|
27997
28267
|
lines.push("");
|
|
27998
28268
|
for (const file of refFiles) {
|
|
27999
28269
|
try {
|
|
28000
|
-
const content = fs15.readFileSync(
|
|
28270
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28001
28271
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28002
28272
|
lines.push("```javascript");
|
|
28003
28273
|
lines.push(content);
|
|
@@ -28038,10 +28308,10 @@ var DevServer = class _DevServer {
|
|
|
28038
28308
|
lines.push("");
|
|
28039
28309
|
}
|
|
28040
28310
|
}
|
|
28041
|
-
const docsDir =
|
|
28311
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28042
28312
|
const loadGuide = (name) => {
|
|
28043
28313
|
try {
|
|
28044
|
-
const p =
|
|
28314
|
+
const p = path26.join(docsDir, name);
|
|
28045
28315
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28046
28316
|
} catch {
|
|
28047
28317
|
}
|
|
@@ -28215,7 +28485,7 @@ var DevServer = class _DevServer {
|
|
|
28215
28485
|
parseApproval: "parse_approval.js"
|
|
28216
28486
|
};
|
|
28217
28487
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28218
|
-
const scriptsDir =
|
|
28488
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28219
28489
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28220
28490
|
if (latestScriptsDir) {
|
|
28221
28491
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28227,7 +28497,7 @@ var DevServer = class _DevServer {
|
|
|
28227
28497
|
if (!file.endsWith(".js")) continue;
|
|
28228
28498
|
if (!targetFileNames.has(file)) continue;
|
|
28229
28499
|
try {
|
|
28230
|
-
const content = fs15.readFileSync(
|
|
28500
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28231
28501
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28232
28502
|
lines.push("```javascript");
|
|
28233
28503
|
lines.push(content);
|
|
@@ -28243,7 +28513,7 @@ var DevServer = class _DevServer {
|
|
|
28243
28513
|
lines.push("");
|
|
28244
28514
|
for (const file of refFiles) {
|
|
28245
28515
|
try {
|
|
28246
|
-
const content = fs15.readFileSync(
|
|
28516
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28247
28517
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28248
28518
|
lines.push("```javascript");
|
|
28249
28519
|
lines.push(content);
|
|
@@ -28276,10 +28546,10 @@ var DevServer = class _DevServer {
|
|
|
28276
28546
|
lines.push("");
|
|
28277
28547
|
}
|
|
28278
28548
|
}
|
|
28279
|
-
const docsDir =
|
|
28549
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28280
28550
|
const loadGuide = (name) => {
|
|
28281
28551
|
try {
|
|
28282
|
-
const p =
|
|
28552
|
+
const p = path26.join(docsDir, name);
|
|
28283
28553
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28284
28554
|
} catch {
|
|
28285
28555
|
}
|
|
@@ -29631,6 +29901,7 @@ export {
|
|
|
29631
29901
|
createGitWorkspaceMonitor,
|
|
29632
29902
|
createInteractionId,
|
|
29633
29903
|
createMesh,
|
|
29904
|
+
createWorktree,
|
|
29634
29905
|
deleteMesh,
|
|
29635
29906
|
detectAllVersions,
|
|
29636
29907
|
detectCLIs,
|
|
@@ -29683,6 +29954,7 @@ export {
|
|
|
29683
29954
|
launchWithCdp,
|
|
29684
29955
|
listHostedCliRuntimes,
|
|
29685
29956
|
listMeshes,
|
|
29957
|
+
listWorktrees,
|
|
29686
29958
|
loadConfig,
|
|
29687
29959
|
loadState,
|
|
29688
29960
|
logCommand,
|
|
@@ -29702,6 +29974,7 @@ export {
|
|
|
29702
29974
|
normalizeSessionModalFields,
|
|
29703
29975
|
parsePorcelainV2Status,
|
|
29704
29976
|
parseProviderSourceConfigUpdate,
|
|
29977
|
+
parseWorktreeListOutput,
|
|
29705
29978
|
partitionSessionHostDiagnosticsSessions,
|
|
29706
29979
|
partitionSessionHostRecords,
|
|
29707
29980
|
prepareSessionChatTailUpdate,
|
|
@@ -29711,6 +29984,7 @@ export {
|
|
|
29711
29984
|
recordDebugTrace,
|
|
29712
29985
|
registerExtensionProviders,
|
|
29713
29986
|
removeNode,
|
|
29987
|
+
removeWorktree,
|
|
29714
29988
|
resetConfig,
|
|
29715
29989
|
resetDebugRuntimeConfig,
|
|
29716
29990
|
resetState,
|
|
@@ -29720,6 +29994,7 @@ export {
|
|
|
29720
29994
|
resolveGitRepository,
|
|
29721
29995
|
resolveSessionHostAppName,
|
|
29722
29996
|
resolveSessionHostAppNameResolution,
|
|
29997
|
+
resolveWorktreePath,
|
|
29723
29998
|
runAsyncBatch,
|
|
29724
29999
|
runGit,
|
|
29725
30000
|
saveConfig,
|