@adhdev/daemon-core 0.9.76-rc.6 → 0.9.76-rc.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -1
- package/dist/cli-adapters/provider-cli-runtime.d.ts +1 -0
- package/dist/commands/cli-manager.d.ts +17 -4
- package/dist/commands/mesh-coordinator.d.ts +2 -0
- package/dist/commands/router.d.ts +11 -0
- package/dist/config/mesh-config.d.ts +3 -0
- package/dist/git/git-types.d.ts +1 -1
- package/dist/git/git-worktree.d.ts +64 -0
- package/dist/git/index.d.ts +2 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1690 -447
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1703 -478
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/coordinator-prompt.d.ts +1 -0
- package/dist/mesh/mesh-events.d.ts +9 -0
- package/dist/providers/chat-message-normalization.d.ts +40 -0
- package/dist/providers/cli-provider-instance.d.ts +3 -0
- package/dist/providers/provider-instance-manager.d.ts +1 -0
- package/dist/providers/provider-instance.d.ts +2 -0
- package/dist/repo-mesh-types.d.ts +27 -0
- package/dist/session-host/runtime-support.d.ts +2 -1
- package/dist/shared-types.d.ts +4 -0
- package/dist/types.d.ts +9 -0
- package/package.json +4 -5
- package/src/chat/subscription-updates.ts +3 -1
- package/src/cli-adapters/provider-cli-adapter.ts +28 -7
- package/src/cli-adapters/provider-cli-runtime.ts +3 -2
- package/src/commands/chat-commands.ts +126 -11
- package/src/commands/cli-manager.ts +78 -5
- package/src/commands/handler.ts +13 -4
- package/src/commands/mesh-coordinator.ts +148 -5
- package/src/commands/router.d.ts +1 -0
- package/src/commands/router.ts +553 -34
- package/src/config/mesh-config.ts +23 -2
- package/src/git/git-commands.ts +5 -1
- package/src/git/git-types.ts +1 -0
- package/src/git/git-worktree.ts +214 -0
- package/src/git/index.ts +14 -0
- package/src/index.ts +16 -1
- package/src/mesh/coordinator-prompt.ts +29 -14
- package/src/mesh/mesh-events.ts +109 -43
- package/src/providers/chat-message-normalization.ts +241 -0
- package/src/providers/cli-provider-instance.d.ts +2 -0
- package/src/providers/cli-provider-instance.ts +93 -8
- package/src/providers/provider-instance-manager.ts +20 -1
- package/src/providers/provider-instance.ts +2 -0
- package/src/providers/read-chat-contract.ts +8 -0
- package/src/repo-mesh-types.ts +30 -0
- package/src/session-host/runtime-support.ts +55 -7
- package/src/shared-types.ts +4 -0
- package/src/status/builders.ts +17 -12
- package/src/status/reporter.ts +6 -0
- package/src/types.ts +9 -0
package/dist/index.js
CHANGED
|
@@ -41,11 +41,140 @@ var init_repo_mesh_types = __esm({
|
|
|
41
41
|
requireApprovalForPush: true,
|
|
42
42
|
requireApprovalForDestructiveGit: true,
|
|
43
43
|
dirtyWorkspaceBehavior: "warn",
|
|
44
|
-
maxParallelTasks: 2
|
|
44
|
+
maxParallelTasks: 2,
|
|
45
|
+
sessionCleanupOnNodeRemove: "preserve"
|
|
45
46
|
};
|
|
46
47
|
}
|
|
47
48
|
});
|
|
48
49
|
|
|
50
|
+
// src/git/git-worktree.ts
|
|
51
|
+
var git_worktree_exports = {};
|
|
52
|
+
__export(git_worktree_exports, {
|
|
53
|
+
createWorktree: () => createWorktree,
|
|
54
|
+
listWorktrees: () => listWorktrees,
|
|
55
|
+
parseWorktreeListOutput: () => parseWorktreeListOutput,
|
|
56
|
+
removeWorktree: () => removeWorktree,
|
|
57
|
+
resolveWorktreePath: () => resolveWorktreePath
|
|
58
|
+
});
|
|
59
|
+
function resolveWorktreePath(repoRoot, meshName, branch) {
|
|
60
|
+
const safeBranch = branch.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
|
|
61
|
+
const safeMeshName = meshName.replace(/[/\\:*?"<>|]/g, "-").replace(/^\.+|\.+$/g, "");
|
|
62
|
+
const parentDir = path4.dirname(repoRoot);
|
|
63
|
+
return path4.join(parentDir, WORKTREE_DIR_NAME, safeMeshName, safeBranch);
|
|
64
|
+
}
|
|
65
|
+
async function createWorktree(opts) {
|
|
66
|
+
const { repoRoot, branch, baseBranch, meshName } = opts;
|
|
67
|
+
const targetDir = opts.targetDir || resolveWorktreePath(repoRoot, meshName, branch);
|
|
68
|
+
if ((0, import_node_fs2.existsSync)(targetDir)) {
|
|
69
|
+
throw new Error(`Worktree target directory already exists: ${targetDir}`);
|
|
70
|
+
}
|
|
71
|
+
await (0, import_promises3.mkdir)(path4.dirname(targetDir), { recursive: true });
|
|
72
|
+
const args = ["worktree", "add", targetDir, "-b", branch];
|
|
73
|
+
if (baseBranch) {
|
|
74
|
+
args.push(baseBranch);
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
await execFileAsync2("git", args, {
|
|
78
|
+
cwd: repoRoot,
|
|
79
|
+
encoding: "utf8",
|
|
80
|
+
timeout: GIT_TIMEOUT_MS,
|
|
81
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
82
|
+
windowsHide: true
|
|
83
|
+
});
|
|
84
|
+
} catch (error) {
|
|
85
|
+
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
86
|
+
if (/already exists/i.test(stderr)) {
|
|
87
|
+
throw new Error(`Branch '${branch}' already exists or is checked out in another worktree`);
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`git worktree add failed: ${stderr.trim() || error.message}`);
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
success: true,
|
|
93
|
+
worktreePath: targetDir,
|
|
94
|
+
branch
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async function removeWorktree(repoRoot, worktreePath) {
|
|
98
|
+
if (!(0, import_node_fs2.existsSync)(worktreePath)) {
|
|
99
|
+
await pruneWorktrees(repoRoot);
|
|
100
|
+
return { success: true, removedPath: worktreePath };
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
await execFileAsync2("git", ["worktree", "remove", worktreePath, "--force"], {
|
|
104
|
+
cwd: repoRoot,
|
|
105
|
+
encoding: "utf8",
|
|
106
|
+
timeout: GIT_TIMEOUT_MS,
|
|
107
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
108
|
+
windowsHide: true
|
|
109
|
+
});
|
|
110
|
+
} catch (error) {
|
|
111
|
+
const stderr = typeof error.stderr === "string" ? error.stderr : "";
|
|
112
|
+
throw new Error(`git worktree remove failed: ${stderr.trim() || error.message}`);
|
|
113
|
+
}
|
|
114
|
+
return { success: true, removedPath: worktreePath };
|
|
115
|
+
}
|
|
116
|
+
async function listWorktrees(repoRoot) {
|
|
117
|
+
const { stdout } = await execFileAsync2("git", ["worktree", "list", "--porcelain"], {
|
|
118
|
+
cwd: repoRoot,
|
|
119
|
+
encoding: "utf8",
|
|
120
|
+
timeout: GIT_TIMEOUT_MS,
|
|
121
|
+
maxBuffer: GIT_MAX_BUFFER,
|
|
122
|
+
windowsHide: true
|
|
123
|
+
});
|
|
124
|
+
return parseWorktreeListOutput(stdout);
|
|
125
|
+
}
|
|
126
|
+
function parseWorktreeListOutput(output) {
|
|
127
|
+
const entries = [];
|
|
128
|
+
const blocks = output.trim().split(/\n\n+/);
|
|
129
|
+
for (const block of blocks) {
|
|
130
|
+
if (!block.trim()) continue;
|
|
131
|
+
const lines = block.trim().split("\n");
|
|
132
|
+
const entry = { path: "", head: "", branch: null, bare: false };
|
|
133
|
+
for (const line of lines) {
|
|
134
|
+
if (line.startsWith("worktree ")) {
|
|
135
|
+
entry.path = line.slice("worktree ".length).trim();
|
|
136
|
+
} else if (line.startsWith("HEAD ")) {
|
|
137
|
+
entry.head = line.slice("HEAD ".length).trim();
|
|
138
|
+
} else if (line.startsWith("branch ")) {
|
|
139
|
+
const ref = line.slice("branch ".length).trim();
|
|
140
|
+
entry.branch = ref.replace(/^refs\/heads\//, "");
|
|
141
|
+
} else if (line === "bare") {
|
|
142
|
+
entry.bare = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (entry.path) {
|
|
146
|
+
entries.push(entry);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return entries;
|
|
150
|
+
}
|
|
151
|
+
async function pruneWorktrees(repoRoot) {
|
|
152
|
+
try {
|
|
153
|
+
await execFileAsync2("git", ["worktree", "prune"], {
|
|
154
|
+
cwd: repoRoot,
|
|
155
|
+
encoding: "utf8",
|
|
156
|
+
timeout: GIT_TIMEOUT_MS,
|
|
157
|
+
windowsHide: true
|
|
158
|
+
});
|
|
159
|
+
} catch {
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
var path4, import_promises3, import_node_fs2, import_node_child_process2, import_node_util2, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER;
|
|
163
|
+
var init_git_worktree = __esm({
|
|
164
|
+
"src/git/git-worktree.ts"() {
|
|
165
|
+
"use strict";
|
|
166
|
+
path4 = __toESM(require("path"));
|
|
167
|
+
import_promises3 = require("fs/promises");
|
|
168
|
+
import_node_fs2 = require("fs");
|
|
169
|
+
import_node_child_process2 = require("child_process");
|
|
170
|
+
import_node_util2 = require("util");
|
|
171
|
+
execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process2.execFile);
|
|
172
|
+
WORKTREE_DIR_NAME = ".adhdev-worktrees";
|
|
173
|
+
GIT_TIMEOUT_MS = 3e4;
|
|
174
|
+
GIT_MAX_BUFFER = 4 * 1024 * 1024;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
49
178
|
// src/config/config.ts
|
|
50
179
|
var config_exports = {};
|
|
51
180
|
__export(config_exports, {
|
|
@@ -304,10 +433,10 @@ function getMeshConfigPath() {
|
|
|
304
433
|
return (0, import_path2.join)(getConfigDir(), "meshes.json");
|
|
305
434
|
}
|
|
306
435
|
function loadMeshConfig() {
|
|
307
|
-
const
|
|
308
|
-
if (!(0, import_fs2.existsSync)(
|
|
436
|
+
const path27 = getMeshConfigPath();
|
|
437
|
+
if (!(0, import_fs2.existsSync)(path27)) return { meshes: [] };
|
|
309
438
|
try {
|
|
310
|
-
const raw = JSON.parse((0, import_fs2.readFileSync)(
|
|
439
|
+
const raw = JSON.parse((0, import_fs2.readFileSync)(path27, "utf-8"));
|
|
311
440
|
if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
|
|
312
441
|
return raw;
|
|
313
442
|
} catch {
|
|
@@ -315,16 +444,16 @@ function loadMeshConfig() {
|
|
|
315
444
|
}
|
|
316
445
|
}
|
|
317
446
|
function saveMeshConfig(config) {
|
|
318
|
-
const
|
|
319
|
-
(0, import_fs2.writeFileSync)(
|
|
447
|
+
const path27 = getMeshConfigPath();
|
|
448
|
+
(0, import_fs2.writeFileSync)(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
|
|
320
449
|
}
|
|
321
450
|
function normalizeRepoIdentity(remoteUrl) {
|
|
322
451
|
let identity = remoteUrl.trim();
|
|
323
452
|
if (identity.startsWith("http://") || identity.startsWith("https://")) {
|
|
324
453
|
try {
|
|
325
454
|
const url = new URL(identity);
|
|
326
|
-
const
|
|
327
|
-
return `${url.hostname}/${
|
|
455
|
+
const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
|
|
456
|
+
return `${url.hostname}/${path27}`;
|
|
328
457
|
} catch {
|
|
329
458
|
}
|
|
330
459
|
}
|
|
@@ -332,6 +461,18 @@ function normalizeRepoIdentity(remoteUrl) {
|
|
|
332
461
|
if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
|
|
333
462
|
return identity;
|
|
334
463
|
}
|
|
464
|
+
function mergeMeshPolicy(base, patch) {
|
|
465
|
+
const policy = { ...DEFAULT_MESH_POLICY, ...base || {}, ...patch || {} };
|
|
466
|
+
if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
|
|
467
|
+
policy.dirtyWorkspaceBehavior = "warn";
|
|
468
|
+
}
|
|
469
|
+
const maxParallelTasks = Number(policy.maxParallelTasks);
|
|
470
|
+
policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
|
|
471
|
+
if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
|
|
472
|
+
policy.sessionCleanupOnNodeRemove = "preserve";
|
|
473
|
+
}
|
|
474
|
+
return policy;
|
|
475
|
+
}
|
|
335
476
|
function listMeshes() {
|
|
336
477
|
return loadMeshConfig().meshes;
|
|
337
478
|
}
|
|
@@ -355,7 +496,7 @@ function createMesh(opts) {
|
|
|
355
496
|
repoIdentity,
|
|
356
497
|
repoRemoteUrl: opts.repoRemoteUrl,
|
|
357
498
|
defaultBranch: opts.defaultBranch,
|
|
358
|
-
policy:
|
|
499
|
+
policy: mergeMeshPolicy(void 0, opts.policy),
|
|
359
500
|
coordinator: opts.coordinator || {},
|
|
360
501
|
nodes: [],
|
|
361
502
|
createdAt: now,
|
|
@@ -371,7 +512,7 @@ function updateMesh(meshId, opts) {
|
|
|
371
512
|
if (!mesh) return void 0;
|
|
372
513
|
if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
|
|
373
514
|
if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
|
|
374
|
-
if (opts.policy) mesh.policy =
|
|
515
|
+
if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
|
|
375
516
|
if (opts.coordinator) mesh.coordinator = opts.coordinator;
|
|
376
517
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
377
518
|
saveMeshConfig(config);
|
|
@@ -399,9 +540,12 @@ function addNode(meshId, opts) {
|
|
|
399
540
|
id: `node_${(0, import_crypto3.randomUUID)().replace(/-/g, "")}`,
|
|
400
541
|
workspace: opts.workspace.trim(),
|
|
401
542
|
repoRoot: opts.repoRoot,
|
|
543
|
+
daemonId: opts.daemonId,
|
|
402
544
|
userOverrides: opts.userOverrides || {},
|
|
403
545
|
policy: opts.policy || {},
|
|
404
|
-
isLocalWorktree: opts.isLocalWorktree
|
|
546
|
+
isLocalWorktree: opts.isLocalWorktree,
|
|
547
|
+
worktreeBranch: opts.worktreeBranch,
|
|
548
|
+
clonedFromNodeId: opts.clonedFromNodeId
|
|
405
549
|
};
|
|
406
550
|
mesh.nodes.push(node);
|
|
407
551
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -431,7 +575,7 @@ function updateNode(meshId, nodeId, opts) {
|
|
|
431
575
|
saveMeshConfig(config);
|
|
432
576
|
return node;
|
|
433
577
|
}
|
|
434
|
-
var import_fs2, import_path2, import_crypto3;
|
|
578
|
+
var import_fs2, import_path2, import_crypto3, SESSION_CLEANUP_MODES;
|
|
435
579
|
var init_mesh_config = __esm({
|
|
436
580
|
"src/config/mesh-config.ts"() {
|
|
437
581
|
"use strict";
|
|
@@ -440,6 +584,7 @@ var init_mesh_config = __esm({
|
|
|
440
584
|
import_crypto3 = require("crypto");
|
|
441
585
|
init_config();
|
|
442
586
|
init_repo_mesh_types();
|
|
587
|
+
SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
|
|
443
588
|
}
|
|
444
589
|
});
|
|
445
590
|
|
|
@@ -449,7 +594,7 @@ __export(coordinator_prompt_exports, {
|
|
|
449
594
|
buildCoordinatorSystemPrompt: () => buildCoordinatorSystemPrompt
|
|
450
595
|
});
|
|
451
596
|
function buildCoordinatorSystemPrompt(ctx) {
|
|
452
|
-
const { mesh, status, userInstruction } = ctx;
|
|
597
|
+
const { mesh, status, userInstruction, coordinatorCliType } = ctx;
|
|
453
598
|
const sections = [];
|
|
454
599
|
sections.push(`You are a **Repo Mesh Coordinator** \u2014 a technical team lead who orchestrates work across multiple agent sessions on a shared Git repository.
|
|
455
600
|
|
|
@@ -463,15 +608,15 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
|
|
|
463
608
|
} else {
|
|
464
609
|
sections.push("## Nodes\nNo nodes configured yet. Ask the user to add nodes with `adhdev mesh add-node`.");
|
|
465
610
|
}
|
|
466
|
-
sections.push(buildPolicySection(mesh.policy));
|
|
611
|
+
sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
|
|
467
612
|
sections.push(TOOLS_SECTION);
|
|
468
613
|
sections.push(WORKFLOW_SECTION);
|
|
469
|
-
sections.push(
|
|
614
|
+
sections.push(buildRulesSection(coordinatorCliType));
|
|
470
615
|
if (userInstruction) {
|
|
471
616
|
sections.push(`## Additional Context
|
|
472
617
|
${userInstruction}`);
|
|
473
618
|
}
|
|
474
|
-
if (mesh.coordinator
|
|
619
|
+
if (mesh.coordinator?.systemPromptSuffix) {
|
|
475
620
|
sections.push(mesh.coordinator.systemPromptSuffix);
|
|
476
621
|
}
|
|
477
622
|
return sections.join("\n\n");
|
|
@@ -516,10 +661,29 @@ function buildPolicySection(policy) {
|
|
|
516
661
|
return `## Policy
|
|
517
662
|
${rules.join("\n")}`;
|
|
518
663
|
}
|
|
519
|
-
|
|
664
|
+
function buildRulesSection(coordinatorCliType) {
|
|
665
|
+
const coordinatorNote = coordinatorCliType ? `
|
|
666
|
+
- **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.` : "";
|
|
667
|
+
return `## Rules
|
|
668
|
+
|
|
669
|
+
- **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.
|
|
670
|
+
- **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.
|
|
671
|
+
- **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.
|
|
672
|
+
- **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.
|
|
673
|
+
- **Don't inspect code.** Treat delegated agent summaries as self-reports, not verification. Verify side effects via \`mesh_git_status\` (including related repo freshness when configured), not by reading source files.
|
|
674
|
+
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed. Never launch a duplicate session or second worker solely because \`mesh_read_chat\` has no final assistant message while the delegated session is still showing tool/terminal activity.
|
|
675
|
+
- **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
|
|
676
|
+
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
677
|
+
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
678
|
+
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.
|
|
679
|
+
- **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
|
|
680
|
+
- **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
|
|
681
|
+
}
|
|
682
|
+
var TOOLS_SECTION, WORKFLOW_SECTION;
|
|
520
683
|
var init_coordinator_prompt = __esm({
|
|
521
684
|
"src/mesh/coordinator-prompt.ts"() {
|
|
522
685
|
"use strict";
|
|
686
|
+
init_repo_mesh_types();
|
|
523
687
|
TOOLS_SECTION = `## Available Tools
|
|
524
688
|
|
|
525
689
|
| Tool | Purpose |
|
|
@@ -531,30 +695,23 @@ var init_coordinator_prompt = __esm({
|
|
|
531
695
|
| \`mesh_read_chat\` | Read an agent's recent messages to check progress |
|
|
532
696
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
533
697
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
534
|
-
| \`mesh_approve\` | Approve/reject a pending agent action
|
|
698
|
+
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
699
|
+
| \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
|
|
700
|
+
| \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
|
|
535
701
|
WORKFLOW_SECTION = `## Orchestration Workflow
|
|
536
702
|
|
|
537
703
|
1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
|
|
538
704
|
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
|
|
539
705
|
3. **Delegate** \u2014 For each task:
|
|
540
706
|
a. Pick the best node (consider: health, dirty state, current workload).
|
|
541
|
-
b. If
|
|
542
|
-
c.
|
|
543
|
-
|
|
544
|
-
|
|
707
|
+
b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
708
|
+
c. If no session exists, call \`mesh_launch_session\` to start one.
|
|
709
|
+
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.
|
|
710
|
+
4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly just because the delegated session has not produced a final assistant message yet; tool/terminal activity means work may still be in progress. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session; wait for the completion callback/status event instead unless you are debugging a real stall. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal, an explicit user status request, or a real timeout/stall. Handle approvals via \`mesh_approve\`.
|
|
711
|
+
5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
545
712
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
546
|
-
7. **
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
- **Minimize coordinator context.** The coordinator's job is routing, not implementing. Do not read source files, run commands, or analyze code directly \u2014 delegate all of that to node agents. Your context should stay lean.
|
|
550
|
-
- **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to a node. Do not do it yourself.
|
|
551
|
-
- **Front-load the task message.** When calling \`mesh_send_task\`, include everything the agent needs: what files to touch, what the problem is, what the fix should look like. The agent won't ask follow-up questions.
|
|
552
|
-
- **Don't inspect code.** Trust the agent's output. Verify via \`mesh_git_status\`, not by reading source files.
|
|
553
|
-
- **Don't over-parallelize.** Start with 1-2 concurrent tasks. Scale up if they succeed.
|
|
554
|
-
- **Handle failures gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
|
|
555
|
-
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
556
|
-
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
557
|
-
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.`;
|
|
713
|
+
7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
714
|
+
8. **Report** \u2014 Summarize what was done, what changed, and any issues.`;
|
|
558
715
|
}
|
|
559
716
|
});
|
|
560
717
|
|
|
@@ -573,13 +730,13 @@ function getDaemonLogDir() {
|
|
|
573
730
|
return LOG_DIR;
|
|
574
731
|
}
|
|
575
732
|
function getCurrentDaemonLogPath(date = /* @__PURE__ */ new Date()) {
|
|
576
|
-
return
|
|
733
|
+
return path10.join(LOG_DIR, `daemon-${date.toISOString().slice(0, 10)}.log`);
|
|
577
734
|
}
|
|
578
735
|
function checkDateRotation() {
|
|
579
736
|
const today = getDateStr();
|
|
580
737
|
if (today !== currentDate) {
|
|
581
738
|
currentDate = today;
|
|
582
|
-
currentLogFile =
|
|
739
|
+
currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
583
740
|
cleanOldLogs();
|
|
584
741
|
}
|
|
585
742
|
}
|
|
@@ -593,7 +750,7 @@ function cleanOldLogs() {
|
|
|
593
750
|
const dateMatch = file.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
594
751
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
595
752
|
try {
|
|
596
|
-
fs2.unlinkSync(
|
|
753
|
+
fs2.unlinkSync(path10.join(LOG_DIR, file));
|
|
597
754
|
} catch {
|
|
598
755
|
}
|
|
599
756
|
}
|
|
@@ -709,17 +866,17 @@ function installGlobalInterceptor() {
|
|
|
709
866
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
710
867
|
writeToFile(`Log level: ${currentLevel}`);
|
|
711
868
|
}
|
|
712
|
-
var fs2,
|
|
869
|
+
var fs2, path10, os4, LEVEL_NUM, LEVEL_LABEL, currentLevel, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
|
|
713
870
|
var init_logger = __esm({
|
|
714
871
|
"src/logging/logger.ts"() {
|
|
715
872
|
"use strict";
|
|
716
873
|
fs2 = __toESM(require("fs"));
|
|
717
|
-
|
|
874
|
+
path10 = __toESM(require("path"));
|
|
718
875
|
os4 = __toESM(require("os"));
|
|
719
876
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
720
877
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
721
878
|
currentLevel = "info";
|
|
722
|
-
LOG_DIR = process.platform === "win32" ?
|
|
879
|
+
LOG_DIR = process.platform === "win32" ? path10.join(process.env.LOCALAPPDATA || process.env.APPDATA || path10.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path10.join(os4.homedir(), "Library", "Logs", "adhdev") : path10.join(os4.homedir(), ".local", "share", "adhdev", "logs");
|
|
723
880
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
724
881
|
MAX_LOG_DAYS = 7;
|
|
725
882
|
try {
|
|
@@ -727,16 +884,16 @@ var init_logger = __esm({
|
|
|
727
884
|
} catch {
|
|
728
885
|
}
|
|
729
886
|
currentDate = getDateStr();
|
|
730
|
-
currentLogFile =
|
|
887
|
+
currentLogFile = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
731
888
|
cleanOldLogs();
|
|
732
889
|
try {
|
|
733
|
-
const oldLog =
|
|
890
|
+
const oldLog = path10.join(LOG_DIR, "daemon.log");
|
|
734
891
|
if (fs2.existsSync(oldLog)) {
|
|
735
892
|
const stat2 = fs2.statSync(oldLog);
|
|
736
893
|
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
737
|
-
fs2.renameSync(oldLog,
|
|
894
|
+
fs2.renameSync(oldLog, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
738
895
|
}
|
|
739
|
-
const oldLogBackup =
|
|
896
|
+
const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
|
|
740
897
|
if (fs2.existsSync(oldLogBackup)) {
|
|
741
898
|
fs2.unlinkSync(oldLogBackup);
|
|
742
899
|
}
|
|
@@ -768,7 +925,7 @@ var init_logger = __esm({
|
|
|
768
925
|
}
|
|
769
926
|
};
|
|
770
927
|
interceptorInstalled = false;
|
|
771
|
-
LOG_PATH =
|
|
928
|
+
LOG_PATH = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
772
929
|
}
|
|
773
930
|
});
|
|
774
931
|
|
|
@@ -1236,9 +1393,9 @@ function buildCliScreenSnapshot(text) {
|
|
|
1236
1393
|
function findBinary(name) {
|
|
1237
1394
|
const trimmed = String(name || "").trim();
|
|
1238
1395
|
if (!trimmed) return trimmed;
|
|
1239
|
-
const expanded = trimmed.startsWith("~") ?
|
|
1240
|
-
if (
|
|
1241
|
-
return
|
|
1396
|
+
const expanded = trimmed.startsWith("~") ? path14.join(os9.homedir(), trimmed.slice(1)) : trimmed;
|
|
1397
|
+
if (path14.isAbsolute(expanded) || expanded.includes("/") || expanded.includes("\\")) {
|
|
1398
|
+
return path14.isAbsolute(expanded) ? expanded : path14.resolve(expanded);
|
|
1242
1399
|
}
|
|
1243
1400
|
const isWin = os9.platform() === "win32";
|
|
1244
1401
|
try {
|
|
@@ -1254,7 +1411,7 @@ function findBinary(name) {
|
|
|
1254
1411
|
}
|
|
1255
1412
|
}
|
|
1256
1413
|
function isScriptBinary(binaryPath) {
|
|
1257
|
-
if (!
|
|
1414
|
+
if (!path14.isAbsolute(binaryPath)) return false;
|
|
1258
1415
|
try {
|
|
1259
1416
|
const fs16 = require("fs");
|
|
1260
1417
|
const resolved = fs16.realpathSync(binaryPath);
|
|
@@ -1270,7 +1427,7 @@ function isScriptBinary(binaryPath) {
|
|
|
1270
1427
|
}
|
|
1271
1428
|
}
|
|
1272
1429
|
function looksLikeMachOOrElf(filePath) {
|
|
1273
|
-
if (!
|
|
1430
|
+
if (!path14.isAbsolute(filePath)) return false;
|
|
1274
1431
|
try {
|
|
1275
1432
|
const fs16 = require("fs");
|
|
1276
1433
|
const resolved = fs16.realpathSync(filePath);
|
|
@@ -1359,12 +1516,12 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
1359
1516
|
}
|
|
1360
1517
|
};
|
|
1361
1518
|
}
|
|
1362
|
-
var os9,
|
|
1519
|
+
var os9, path14, import_child_process4, buildCliSpawnEnv;
|
|
1363
1520
|
var init_provider_cli_shared = __esm({
|
|
1364
1521
|
"src/cli-adapters/provider-cli-shared.ts"() {
|
|
1365
1522
|
"use strict";
|
|
1366
1523
|
os9 = __toESM(require("os"));
|
|
1367
|
-
|
|
1524
|
+
path14 = __toESM(require("path"));
|
|
1368
1525
|
import_child_process4 = require("child_process");
|
|
1369
1526
|
init_spawn_env();
|
|
1370
1527
|
buildCliSpawnEnv = import_session_host_core.sanitizeSpawnEnv;
|
|
@@ -1487,7 +1644,7 @@ var init_provider_cli_config = __esm({
|
|
|
1487
1644
|
|
|
1488
1645
|
// src/cli-adapters/provider-cli-runtime.ts
|
|
1489
1646
|
function resolveCliSpawnPlan(options) {
|
|
1490
|
-
const { provider, runtimeSettings, workingDir, extraArgs } = options;
|
|
1647
|
+
const { provider, runtimeSettings, workingDir, extraArgs, extraEnv } = options;
|
|
1491
1648
|
const { spawn: spawnConfig } = provider;
|
|
1492
1649
|
const configuredCommand = typeof runtimeSettings.executablePath === "string" && runtimeSettings.executablePath.trim() ? runtimeSettings.executablePath.trim() : spawnConfig.command;
|
|
1493
1650
|
const binaryPath = findBinary(configuredCommand);
|
|
@@ -1495,9 +1652,9 @@ function resolveCliSpawnPlan(options) {
|
|
|
1495
1652
|
const allArgs = [...spawnConfig.args, ...extraArgs];
|
|
1496
1653
|
let shellCmd;
|
|
1497
1654
|
let shellArgs;
|
|
1498
|
-
const useShellUnix = !isWin && (!!spawnConfig.shell || !
|
|
1655
|
+
const useShellUnix = !isWin && (!!spawnConfig.shell || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath) || !looksLikeMachOOrElf(binaryPath));
|
|
1499
1656
|
const isCmdShim = isWin && /\.(cmd|bat)$/i.test(binaryPath);
|
|
1500
|
-
const useShellWin = !!spawnConfig.shell || isCmdShim || !
|
|
1657
|
+
const useShellWin = !!spawnConfig.shell || isCmdShim || !path15.isAbsolute(binaryPath) || isScriptBinary(binaryPath);
|
|
1501
1658
|
const useShell = isWin ? useShellWin : useShellUnix;
|
|
1502
1659
|
if (useShell) {
|
|
1503
1660
|
shellCmd = isWin ? "cmd.exe" : process.env.SHELL || "/bin/zsh";
|
|
@@ -1511,7 +1668,7 @@ function resolveCliSpawnPlan(options) {
|
|
|
1511
1668
|
shellCmd = binaryPath;
|
|
1512
1669
|
shellArgs = allArgs;
|
|
1513
1670
|
}
|
|
1514
|
-
const env = buildCliSpawnEnv(process.env, spawnConfig.env);
|
|
1671
|
+
const env = buildCliSpawnEnv(process.env, { ...spawnConfig.env || {}, ...extraEnv || {} });
|
|
1515
1672
|
env.TERMINAL_CWD = workingDir;
|
|
1516
1673
|
return {
|
|
1517
1674
|
binaryPath,
|
|
@@ -1573,12 +1730,12 @@ function respondToCliTerminalQueries(options) {
|
|
|
1573
1730
|
}
|
|
1574
1731
|
return "";
|
|
1575
1732
|
}
|
|
1576
|
-
var os10,
|
|
1733
|
+
var os10, path15, import_session_host_core2;
|
|
1577
1734
|
var init_provider_cli_runtime = __esm({
|
|
1578
1735
|
"src/cli-adapters/provider-cli-runtime.ts"() {
|
|
1579
1736
|
"use strict";
|
|
1580
1737
|
os10 = __toESM(require("os"));
|
|
1581
|
-
|
|
1738
|
+
path15 = __toESM(require("path"));
|
|
1582
1739
|
import_session_host_core2 = require("@adhdev/session-host-core");
|
|
1583
1740
|
init_provider_cli_shared();
|
|
1584
1741
|
}
|
|
@@ -1614,8 +1771,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1614
1771
|
init_provider_cli_runtime();
|
|
1615
1772
|
init_provider_cli_shared();
|
|
1616
1773
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
1617
|
-
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
1774
|
+
constructor(provider, workingDir, extraArgs = [], extraEnv = {}, transportFactory = new NodePtyTransportFactory()) {
|
|
1618
1775
|
this.extraArgs = extraArgs;
|
|
1776
|
+
this.extraEnv = extraEnv;
|
|
1619
1777
|
this.provider = provider;
|
|
1620
1778
|
this.transportFactory = transportFactory;
|
|
1621
1779
|
this.cliType = provider.type;
|
|
@@ -1766,8 +1924,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
1766
1924
|
const currentSnapshot = normalizeScreenSnapshot(screenText);
|
|
1767
1925
|
const lastSnapshot = this.lastScreenSnapshot;
|
|
1768
1926
|
if (!lastSnapshot || lastSnapshot === currentSnapshot) return screenText;
|
|
1769
|
-
const
|
|
1770
|
-
const
|
|
1927
|
+
const activeScreenPattern = /\besc to (?:interrupt|stop)\b|Enter to interrupt, Ctrl\+C to cancel|Enter to confirm\s*[·•-]\s*Esc to cancel|\b(?:MCP servers?|tool calls?)\b[^\n\r]{0,160}\brequire approval\b/i;
|
|
1928
|
+
const staleSnapshotLooksActive = activeScreenPattern.test(lastSnapshot);
|
|
1929
|
+
const currentScreenLooksIdle = /(?:^|\n|\r)\s*[❯›>]\s*(?:Try\s+["“][^\n\r"”]+["”])?\s*(?:\n|\r|$)/.test(screenText) && !activeScreenPattern.test(screenText);
|
|
1771
1930
|
if (staleSnapshotLooksActive && currentScreenLooksIdle) return screenText;
|
|
1772
1931
|
if (currentSnapshot.length >= lastSnapshot.length) return screenText;
|
|
1773
1932
|
return `${screenText}
|
|
@@ -1930,7 +2089,8 @@ ${lastSnapshot}`;
|
|
|
1930
2089
|
provider: this.provider,
|
|
1931
2090
|
runtimeSettings: this.runtimeSettings,
|
|
1932
2091
|
workingDir: this.workingDir,
|
|
1933
|
-
extraArgs: this.extraArgs
|
|
2092
|
+
extraArgs: this.extraArgs,
|
|
2093
|
+
extraEnv: this.extraEnv
|
|
1934
2094
|
});
|
|
1935
2095
|
LOG.info("CLI", `[${this.cliType}] Spawning in ${this.workingDir}`);
|
|
1936
2096
|
this.resetTraceSession();
|
|
@@ -3128,9 +3288,8 @@ ${lastSnapshot}`;
|
|
|
3128
3288
|
};
|
|
3129
3289
|
this.recordTrace("submit_echo_missing", diagnostic);
|
|
3130
3290
|
if (this.requirePromptEchoBeforeSubmit) {
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
completion.rejectOnce(new Error(message));
|
|
3291
|
+
LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending guarded submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs} screen=${JSON.stringify(diagnostic.screenText).slice(0, 240)}`);
|
|
3292
|
+
this.submitSendKey(state, completion);
|
|
3134
3293
|
return;
|
|
3135
3294
|
}
|
|
3136
3295
|
LOG.warn("CLI", `[${this.cliType}] prompt echo was not observed before submit; sending submit key anyway elapsed=${elapsed}ms maxEchoWaitMs=${state.maxEchoWaitMs}`);
|
|
@@ -3177,7 +3336,14 @@ ${lastSnapshot}`;
|
|
|
3177
3336
|
})() : null;
|
|
3178
3337
|
const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
|
|
3179
3338
|
if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
|
|
3180
|
-
|
|
3339
|
+
const parsedModal = parsedStatusBeforeSend?.activeModal ?? parsedStatusBeforeSend?.modal ?? null;
|
|
3340
|
+
const parsedHasActionableModal = Boolean(
|
|
3341
|
+
parsedModal && Array.isArray(parsedModal.buttons) && parsedModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim())
|
|
3342
|
+
);
|
|
3343
|
+
const terminalLooksIdle = this.currentStatus === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle" && !this.isWaitingForResponse && !this.currentTurnScope && !this.hasActionableApproval() && !parsedHasActionableModal;
|
|
3344
|
+
if (!terminalLooksIdle) {
|
|
3345
|
+
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
3346
|
+
}
|
|
3181
3347
|
}
|
|
3182
3348
|
if (this.isWaitingForResponse && !allowInputDuringGeneration) {
|
|
3183
3349
|
if (!this.clearStaleIdleResponseGuard("send_message_guard")) {
|
|
@@ -3653,6 +3819,12 @@ __export(index_exports, {
|
|
|
3653
3819
|
AcpProviderInstance: () => AcpProviderInstance,
|
|
3654
3820
|
AgentStreamPoller: () => AgentStreamPoller,
|
|
3655
3821
|
BUILTIN_CHAT_MESSAGE_KINDS: () => BUILTIN_CHAT_MESSAGE_KINDS,
|
|
3822
|
+
CHAT_MESSAGE_ACTIVITY_SOURCES: () => CHAT_MESSAGE_ACTIVITY_SOURCES,
|
|
3823
|
+
CHAT_MESSAGE_AUDIENCES: () => CHAT_MESSAGE_AUDIENCES,
|
|
3824
|
+
CHAT_MESSAGE_INTERNAL_SOURCES: () => CHAT_MESSAGE_INTERNAL_SOURCES,
|
|
3825
|
+
CHAT_MESSAGE_SOURCES: () => CHAT_MESSAGE_SOURCES,
|
|
3826
|
+
CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES: () => CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES,
|
|
3827
|
+
CHAT_MESSAGE_VISIBILITIES: () => CHAT_MESSAGE_VISIBILITIES,
|
|
3656
3828
|
CdpDomHandlers: () => CdpDomHandlers,
|
|
3657
3829
|
CliProviderInstance: () => CliProviderInstance,
|
|
3658
3830
|
DAEMON_WS_PATH: () => DAEMON_WS_PATH,
|
|
@@ -3715,6 +3887,7 @@ __export(index_exports, {
|
|
|
3715
3887
|
buildThoughtChatMessage: () => buildThoughtChatMessage,
|
|
3716
3888
|
buildToolChatMessage: () => buildToolChatMessage,
|
|
3717
3889
|
buildUserChatMessage: () => buildUserChatMessage,
|
|
3890
|
+
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
3718
3891
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
|
|
3719
3892
|
clearDebugTrace: () => clearDebugTrace,
|
|
3720
3893
|
compareGitSnapshots: () => compareGitSnapshots,
|
|
@@ -3727,12 +3900,17 @@ __export(index_exports, {
|
|
|
3727
3900
|
createGitWorkspaceMonitor: () => createGitWorkspaceMonitor,
|
|
3728
3901
|
createInteractionId: () => createInteractionId,
|
|
3729
3902
|
createMesh: () => createMesh,
|
|
3903
|
+
createWorktree: () => createWorktree,
|
|
3730
3904
|
deleteMesh: () => deleteMesh,
|
|
3731
3905
|
detectAllVersions: () => detectAllVersions,
|
|
3732
3906
|
detectCLIs: () => detectCLIs,
|
|
3733
3907
|
detectIDEs: () => detectIDEs,
|
|
3734
3908
|
ensureSessionHostReady: () => ensureSessionHostReady,
|
|
3735
3909
|
execNpmCommandSync: () => execNpmCommandSync,
|
|
3910
|
+
filterActivityChatMessages: () => filterActivityChatMessages,
|
|
3911
|
+
filterChatMessagesByVisibility: () => filterChatMessagesByVisibility,
|
|
3912
|
+
filterInternalChatMessages: () => filterInternalChatMessages,
|
|
3913
|
+
filterUserFacingChatMessages: () => filterUserFacingChatMessages,
|
|
3736
3914
|
findCdpManager: () => findCdpManager,
|
|
3737
3915
|
flattenMessageParts: () => flattenMessageParts,
|
|
3738
3916
|
forwardAgentStreamsToIdeInstance: () => forwardAgentStreamsToIdeInstance,
|
|
@@ -3763,22 +3941,26 @@ __export(index_exports, {
|
|
|
3763
3941
|
initDaemonComponents: () => initDaemonComponents,
|
|
3764
3942
|
installExtensions: () => installExtensions,
|
|
3765
3943
|
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
3944
|
+
isActivityChatMessage: () => isActivityChatMessage,
|
|
3766
3945
|
isBuiltinChatMessageKind: () => isBuiltinChatMessageKind,
|
|
3767
3946
|
isCdpConnected: () => isCdpConnected,
|
|
3768
3947
|
isExtensionInstalled: () => isExtensionInstalled,
|
|
3769
3948
|
isGitCommandName: () => isGitCommandName,
|
|
3770
3949
|
isIdeRunning: () => isIdeRunning,
|
|
3950
|
+
isInternalChatMessage: () => isInternalChatMessage,
|
|
3771
3951
|
isManagedStatusWaiting: () => isManagedStatusWaiting,
|
|
3772
3952
|
isManagedStatusWorking: () => isManagedStatusWorking,
|
|
3773
3953
|
isPathInside: () => isPathInside,
|
|
3774
3954
|
isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
|
|
3775
3955
|
isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
|
|
3776
3956
|
isSetupComplete: () => isSetupComplete,
|
|
3957
|
+
isUserFacingChatMessage: () => isUserFacingChatMessage,
|
|
3777
3958
|
killIdeProcess: () => killIdeProcess,
|
|
3778
3959
|
launchIDE: () => launchIDE,
|
|
3779
3960
|
launchWithCdp: () => launchWithCdp,
|
|
3780
3961
|
listHostedCliRuntimes: () => listHostedCliRuntimes,
|
|
3781
3962
|
listMeshes: () => listMeshes,
|
|
3963
|
+
listWorktrees: () => listWorktrees,
|
|
3782
3964
|
loadConfig: () => loadConfig,
|
|
3783
3965
|
loadState: () => loadState,
|
|
3784
3966
|
logCommand: () => logCommand,
|
|
@@ -3798,6 +3980,7 @@ __export(index_exports, {
|
|
|
3798
3980
|
normalizeSessionModalFields: () => normalizeSessionModalFields,
|
|
3799
3981
|
parsePorcelainV2Status: () => parsePorcelainV2Status,
|
|
3800
3982
|
parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
|
|
3983
|
+
parseWorktreeListOutput: () => parseWorktreeListOutput,
|
|
3801
3984
|
partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
|
|
3802
3985
|
partitionSessionHostRecords: () => partitionSessionHostRecords,
|
|
3803
3986
|
prepareSessionChatTailUpdate: () => prepareSessionChatTailUpdate,
|
|
@@ -3807,6 +3990,7 @@ __export(index_exports, {
|
|
|
3807
3990
|
recordDebugTrace: () => recordDebugTrace,
|
|
3808
3991
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
3809
3992
|
removeNode: () => removeNode,
|
|
3993
|
+
removeWorktree: () => removeWorktree,
|
|
3810
3994
|
resetConfig: () => resetConfig,
|
|
3811
3995
|
resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
|
|
3812
3996
|
resetState: () => resetState,
|
|
@@ -3816,6 +4000,7 @@ __export(index_exports, {
|
|
|
3816
4000
|
resolveGitRepository: () => resolveGitRepository,
|
|
3817
4001
|
resolveSessionHostAppName: () => resolveSessionHostAppName,
|
|
3818
4002
|
resolveSessionHostAppNameResolution: () => resolveSessionHostAppNameResolution,
|
|
4003
|
+
resolveWorktreePath: () => resolveWorktreePath,
|
|
3819
4004
|
runAsyncBatch: () => runAsyncBatch,
|
|
3820
4005
|
runGit: () => runGit,
|
|
3821
4006
|
saveConfig: () => saveConfig,
|
|
@@ -4739,6 +4924,7 @@ var FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
|
4739
4924
|
"dirty_index_required",
|
|
4740
4925
|
"conflict",
|
|
4741
4926
|
"invalid_args",
|
|
4927
|
+
"nothing_to_commit",
|
|
4742
4928
|
"git_command_failed"
|
|
4743
4929
|
]);
|
|
4744
4930
|
function failure(reason, error) {
|
|
@@ -4983,7 +5169,10 @@ async function gitCheckpoint(workspace, message, includeUntracked) {
|
|
|
4983
5169
|
} catch (err) {
|
|
4984
5170
|
const output = (err?.stdout || "") + (err?.stderr || "");
|
|
4985
5171
|
if (/nothing to commit/i.test(output)) {
|
|
4986
|
-
throw new GitCommandError("
|
|
5172
|
+
throw new GitCommandError("nothing_to_commit", "Nothing to commit \u2014 working tree is clean.", {
|
|
5173
|
+
stdout: err?.stdout,
|
|
5174
|
+
stderr: err?.stderr
|
|
5175
|
+
});
|
|
4987
5176
|
}
|
|
4988
5177
|
throw err;
|
|
4989
5178
|
}
|
|
@@ -5175,20 +5364,23 @@ var TurnSnapshotTracker = class {
|
|
|
5175
5364
|
}
|
|
5176
5365
|
};
|
|
5177
5366
|
|
|
5367
|
+
// src/git/index.ts
|
|
5368
|
+
init_git_worktree();
|
|
5369
|
+
|
|
5178
5370
|
// src/index.ts
|
|
5179
5371
|
init_config();
|
|
5180
5372
|
|
|
5181
5373
|
// src/config/workspaces.ts
|
|
5182
5374
|
var fs = __toESM(require("fs"));
|
|
5183
5375
|
var os = __toESM(require("os"));
|
|
5184
|
-
var
|
|
5376
|
+
var path5 = __toESM(require("path"));
|
|
5185
5377
|
var import_crypto2 = require("crypto");
|
|
5186
5378
|
var MAX_WORKSPACES = 50;
|
|
5187
5379
|
function expandPath(p) {
|
|
5188
5380
|
const t = (p || "").trim();
|
|
5189
5381
|
if (!t) return "";
|
|
5190
|
-
if (t.startsWith("~")) return
|
|
5191
|
-
return
|
|
5382
|
+
if (t.startsWith("~")) return path5.join(os.homedir(), t.slice(1).replace(/^\//, ""));
|
|
5383
|
+
return path5.resolve(t);
|
|
5192
5384
|
}
|
|
5193
5385
|
function validateWorkspacePath(absPath) {
|
|
5194
5386
|
try {
|
|
@@ -5202,7 +5394,7 @@ function validateWorkspacePath(absPath) {
|
|
|
5202
5394
|
}
|
|
5203
5395
|
}
|
|
5204
5396
|
function defaultWorkspaceLabel(absPath) {
|
|
5205
|
-
const base =
|
|
5397
|
+
const base = path5.basename(absPath) || absPath;
|
|
5206
5398
|
return base;
|
|
5207
5399
|
}
|
|
5208
5400
|
function getDefaultWorkspacePath(config) {
|
|
@@ -5293,9 +5485,9 @@ function resolveIdeLaunchWorkspace(args, config) {
|
|
|
5293
5485
|
return getDefaultWorkspacePath(config) || void 0;
|
|
5294
5486
|
}
|
|
5295
5487
|
function findWorkspaceByPath(config, rawPath) {
|
|
5296
|
-
const abs =
|
|
5488
|
+
const abs = path5.resolve(expandPath(rawPath));
|
|
5297
5489
|
if (!abs) return void 0;
|
|
5298
|
-
return (config.workspaces || []).find((w) =>
|
|
5490
|
+
return (config.workspaces || []).find((w) => path5.resolve(expandPath(w.path)) === abs);
|
|
5299
5491
|
}
|
|
5300
5492
|
function addWorkspaceEntry(config, rawPath, label, options) {
|
|
5301
5493
|
const abs = expandPath(rawPath);
|
|
@@ -5311,7 +5503,7 @@ function addWorkspaceEntry(config, rawPath, label, options) {
|
|
|
5311
5503
|
const v = validateWorkspacePath(abs);
|
|
5312
5504
|
if (!v.ok) return { error: v.error };
|
|
5313
5505
|
const list = [...config.workspaces || []];
|
|
5314
|
-
if (list.some((w) =>
|
|
5506
|
+
if (list.some((w) => path5.resolve(w.path) === abs)) {
|
|
5315
5507
|
return { error: "Workspace already in list" };
|
|
5316
5508
|
}
|
|
5317
5509
|
if (list.length >= MAX_WORKSPACES) {
|
|
@@ -5345,7 +5537,7 @@ function setDefaultWorkspaceId(config, id) {
|
|
|
5345
5537
|
}
|
|
5346
5538
|
|
|
5347
5539
|
// src/config/recent-activity.ts
|
|
5348
|
-
var
|
|
5540
|
+
var path6 = __toESM(require("path"));
|
|
5349
5541
|
|
|
5350
5542
|
// src/providers/summary-metadata.ts
|
|
5351
5543
|
function normalizeSummaryItem(item) {
|
|
@@ -5414,9 +5606,9 @@ var MAX_ACTIVITY = 30;
|
|
|
5414
5606
|
function normalizeWorkspace(workspace) {
|
|
5415
5607
|
if (!workspace) return "";
|
|
5416
5608
|
try {
|
|
5417
|
-
return
|
|
5609
|
+
return path6.resolve(expandPath(workspace));
|
|
5418
5610
|
} catch {
|
|
5419
|
-
return
|
|
5611
|
+
return path6.resolve(workspace);
|
|
5420
5612
|
}
|
|
5421
5613
|
}
|
|
5422
5614
|
function buildRecentActivityKey(entry) {
|
|
@@ -5584,14 +5776,14 @@ function markSessionSeen(state, sessionId, seenAt = Date.now(), completionMarker
|
|
|
5584
5776
|
}
|
|
5585
5777
|
|
|
5586
5778
|
// src/config/saved-sessions.ts
|
|
5587
|
-
var
|
|
5779
|
+
var path7 = __toESM(require("path"));
|
|
5588
5780
|
var MAX_SAVED_SESSIONS = 500;
|
|
5589
5781
|
function normalizeWorkspace2(workspace) {
|
|
5590
5782
|
if (!workspace) return "";
|
|
5591
5783
|
try {
|
|
5592
|
-
return
|
|
5784
|
+
return path7.resolve(expandPath(workspace));
|
|
5593
5785
|
} catch {
|
|
5594
|
-
return
|
|
5786
|
+
return path7.resolve(workspace);
|
|
5595
5787
|
}
|
|
5596
5788
|
}
|
|
5597
5789
|
function buildSavedProviderSessionKey(providerSessionId) {
|
|
@@ -5770,7 +5962,7 @@ function resetState() {
|
|
|
5770
5962
|
var import_child_process = require("child_process");
|
|
5771
5963
|
var import_fs4 = require("fs");
|
|
5772
5964
|
var import_os2 = require("os");
|
|
5773
|
-
var
|
|
5965
|
+
var path8 = __toESM(require("path"));
|
|
5774
5966
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
5775
5967
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
5776
5968
|
function registerIDEDefinition(def) {
|
|
@@ -5789,9 +5981,9 @@ function getMergedDefinitions() {
|
|
|
5789
5981
|
function findCliCommand(command) {
|
|
5790
5982
|
const trimmed = String(command || "").trim();
|
|
5791
5983
|
if (!trimmed) return null;
|
|
5792
|
-
if (
|
|
5793
|
-
const candidate = trimmed.startsWith("~") ?
|
|
5794
|
-
const resolved =
|
|
5984
|
+
if (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
5985
|
+
const candidate = trimmed.startsWith("~") ? path8.join((0, import_os2.homedir)(), trimmed.slice(1)) : trimmed;
|
|
5986
|
+
const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
|
|
5795
5987
|
return (0, import_fs4.existsSync)(resolved) ? resolved : null;
|
|
5796
5988
|
}
|
|
5797
5989
|
try {
|
|
@@ -5819,7 +6011,7 @@ function getIdeVersion(cliCommand) {
|
|
|
5819
6011
|
function checkPathExists(paths) {
|
|
5820
6012
|
const home = (0, import_os2.homedir)();
|
|
5821
6013
|
for (const p of paths) {
|
|
5822
|
-
const normalized = p.startsWith("~") ?
|
|
6014
|
+
const normalized = p.startsWith("~") ? path8.join(home, p.slice(1)) : p;
|
|
5823
6015
|
if (normalized.includes("*")) {
|
|
5824
6016
|
const username = home.split(/[\\/]/).pop() || "";
|
|
5825
6017
|
const resolved = normalized.replace("*", username);
|
|
@@ -5831,19 +6023,19 @@ function checkPathExists(paths) {
|
|
|
5831
6023
|
return null;
|
|
5832
6024
|
}
|
|
5833
6025
|
async function detectIDEs(providerLoader) {
|
|
5834
|
-
const
|
|
6026
|
+
const os22 = (0, import_os2.platform)();
|
|
5835
6027
|
const results = [];
|
|
5836
6028
|
for (const def of getMergedDefinitions()) {
|
|
5837
6029
|
const cliPath = findCliCommand(providerLoader?.getIdeCliCommand(def.id, def.cli) || def.cli);
|
|
5838
|
-
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[
|
|
6030
|
+
const appPath = checkPathExists(providerLoader?.getIdePathCandidates(def.id, def.paths[os22] || []) || []);
|
|
5839
6031
|
let resolvedCli = cliPath;
|
|
5840
|
-
if (!resolvedCli && appPath &&
|
|
6032
|
+
if (!resolvedCli && appPath && os22 === "darwin") {
|
|
5841
6033
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
5842
6034
|
if ((0, import_fs4.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
5843
6035
|
}
|
|
5844
|
-
if (!resolvedCli && appPath &&
|
|
5845
|
-
const { dirname:
|
|
5846
|
-
const appDir =
|
|
6036
|
+
if (!resolvedCli && appPath && os22 === "win32") {
|
|
6037
|
+
const { dirname: dirname9 } = await import("path");
|
|
6038
|
+
const appDir = dirname9(appPath);
|
|
5847
6039
|
const candidates = [
|
|
5848
6040
|
`${appDir}\\\\bin\\\\${def.cli}.cmd`,
|
|
5849
6041
|
`${appDir}\\\\bin\\\\${def.cli}`,
|
|
@@ -5858,7 +6050,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5858
6050
|
}
|
|
5859
6051
|
}
|
|
5860
6052
|
}
|
|
5861
|
-
const installed =
|
|
6053
|
+
const installed = os22 === "darwin" ? !!(resolvedCli || appPath) : !!resolvedCli;
|
|
5862
6054
|
const version = resolvedCli ? getIdeVersion(resolvedCli) : null;
|
|
5863
6055
|
results.push({
|
|
5864
6056
|
id: def.id,
|
|
@@ -5877,7 +6069,7 @@ async function detectIDEs(providerLoader) {
|
|
|
5877
6069
|
// src/detection/cli-detector.ts
|
|
5878
6070
|
var import_child_process2 = require("child_process");
|
|
5879
6071
|
var os2 = __toESM(require("os"));
|
|
5880
|
-
var
|
|
6072
|
+
var path9 = __toESM(require("path"));
|
|
5881
6073
|
var import_fs5 = require("fs");
|
|
5882
6074
|
function parseVersion(raw) {
|
|
5883
6075
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
@@ -5890,18 +6082,18 @@ function shellQuote(value) {
|
|
|
5890
6082
|
function expandHome(value) {
|
|
5891
6083
|
const trimmed = value.trim();
|
|
5892
6084
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
5893
|
-
return
|
|
6085
|
+
return path9.join(os2.homedir(), trimmed.slice(1));
|
|
5894
6086
|
}
|
|
5895
6087
|
function isExplicitCommandPath(command) {
|
|
5896
6088
|
const trimmed = command.trim();
|
|
5897
|
-
return
|
|
6089
|
+
return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
5898
6090
|
}
|
|
5899
6091
|
function resolveCommandPath(command) {
|
|
5900
6092
|
const trimmed = command.trim();
|
|
5901
6093
|
if (!trimmed) return null;
|
|
5902
6094
|
if (isExplicitCommandPath(trimmed)) {
|
|
5903
6095
|
const expanded = expandHome(trimmed);
|
|
5904
|
-
const candidate =
|
|
6096
|
+
const candidate = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
|
|
5905
6097
|
return (0, import_fs5.existsSync)(candidate) ? candidate : null;
|
|
5906
6098
|
}
|
|
5907
6099
|
return null;
|
|
@@ -7833,6 +8025,20 @@ var StatusMonitor = class {
|
|
|
7833
8025
|
|
|
7834
8026
|
// src/providers/chat-message-normalization.ts
|
|
7835
8027
|
var BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
|
|
8028
|
+
var CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
|
|
8029
|
+
var CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
|
|
8030
|
+
var CHAT_MESSAGE_AUDIENCES = ["chat", "debug", "trace", "internal"];
|
|
8031
|
+
var CHAT_MESSAGE_SOURCES = [
|
|
8032
|
+
"assistant_text",
|
|
8033
|
+
"tool_call",
|
|
8034
|
+
"terminal_command",
|
|
8035
|
+
"runtime_activity",
|
|
8036
|
+
"runtime_status",
|
|
8037
|
+
"provider_chrome",
|
|
8038
|
+
"control"
|
|
8039
|
+
];
|
|
8040
|
+
var CHAT_MESSAGE_ACTIVITY_SOURCES = ["tool_call", "terminal_command", "runtime_activity"];
|
|
8041
|
+
var CHAT_MESSAGE_INTERNAL_SOURCES = ["runtime_status", "provider_chrome", "control"];
|
|
7836
8042
|
var KNOWN_CHAT_MESSAGE_KINDS = new Set(BUILTIN_CHAT_MESSAGE_KINDS);
|
|
7837
8043
|
var CHAT_MESSAGE_KIND_ALIASES = {
|
|
7838
8044
|
text: "standard",
|
|
@@ -7974,6 +8180,169 @@ function normalizeChatMessage(message) {
|
|
|
7974
8180
|
function normalizeChatMessages(messages) {
|
|
7975
8181
|
return (Array.isArray(messages) ? messages : []).map((message) => normalizeChatMessage(message));
|
|
7976
8182
|
}
|
|
8183
|
+
function readMessageMeta(message) {
|
|
8184
|
+
const meta = message?.meta;
|
|
8185
|
+
return meta && typeof meta === "object" && !Array.isArray(meta) ? meta : null;
|
|
8186
|
+
}
|
|
8187
|
+
function readStringField(value) {
|
|
8188
|
+
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
8189
|
+
}
|
|
8190
|
+
function readRecordField(message, meta, key) {
|
|
8191
|
+
const record = message;
|
|
8192
|
+
return record[key] ?? meta?.[key];
|
|
8193
|
+
}
|
|
8194
|
+
function readVisibilityField(message, meta) {
|
|
8195
|
+
return readStringField(readRecordField(message, meta, "visibility"));
|
|
8196
|
+
}
|
|
8197
|
+
function readTranscriptVisibilityField(message, meta) {
|
|
8198
|
+
const record = message;
|
|
8199
|
+
return readStringField(record.transcriptVisibility ?? meta?.transcriptVisibility ?? record.visibility ?? meta?.visibility);
|
|
8200
|
+
}
|
|
8201
|
+
var EXPLICIT_HIDDEN_VISIBILITIES = /* @__PURE__ */ new Set(["hidden", "debug", "internal"]);
|
|
8202
|
+
var EXPLICIT_VISIBLE_VISIBILITIES = /* @__PURE__ */ new Set(["visible", "user", "chat"]);
|
|
8203
|
+
var HIDDEN_AUDIENCES = /* @__PURE__ */ new Set(["debug", "trace", "internal"]);
|
|
8204
|
+
var ACTIVITY_SOURCE_SET = new Set(CHAT_MESSAGE_ACTIVITY_SOURCES);
|
|
8205
|
+
var INTERNAL_SOURCE_SET = new Set(CHAT_MESSAGE_INTERNAL_SOURCES);
|
|
8206
|
+
function hasBooleanMarker(message, meta, keys) {
|
|
8207
|
+
const record = message;
|
|
8208
|
+
return keys.some((key) => record[key] === true || meta?.[key] === true);
|
|
8209
|
+
}
|
|
8210
|
+
function isActivityKind(kind) {
|
|
8211
|
+
return kind === "thought" || kind === "tool" || kind === "terminal";
|
|
8212
|
+
}
|
|
8213
|
+
function isOrdinaryVisibleTurn(message, role, kind) {
|
|
8214
|
+
if (role === "user" || role === "human") return kind === "standard" || kind === "";
|
|
8215
|
+
if (role === "assistant") return kind === "standard" || kind === "";
|
|
8216
|
+
return false;
|
|
8217
|
+
}
|
|
8218
|
+
function classifyChatMessageVisibility(message) {
|
|
8219
|
+
if (!message) {
|
|
8220
|
+
return {
|
|
8221
|
+
surface: "internal",
|
|
8222
|
+
isUserFacing: false,
|
|
8223
|
+
isActivityFacing: false,
|
|
8224
|
+
isInternal: true,
|
|
8225
|
+
explicitUserFacing: false,
|
|
8226
|
+
explicitHidden: true,
|
|
8227
|
+
role: "",
|
|
8228
|
+
kind: "standard",
|
|
8229
|
+
visibility: "",
|
|
8230
|
+
transcriptVisibility: "",
|
|
8231
|
+
audience: "",
|
|
8232
|
+
source: ""
|
|
8233
|
+
};
|
|
8234
|
+
}
|
|
8235
|
+
const meta = readMessageMeta(message);
|
|
8236
|
+
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
8237
|
+
const kind = resolveChatMessageKind(message);
|
|
8238
|
+
const visibility = readVisibilityField(message, meta);
|
|
8239
|
+
const transcriptVisibility = readTranscriptVisibilityField(message, meta);
|
|
8240
|
+
const audience = readStringField(readRecordField(message, meta, "audience"));
|
|
8241
|
+
const source = readStringField(readRecordField(message, meta, "source"));
|
|
8242
|
+
const explicitHidden = EXPLICIT_HIDDEN_VISIBILITIES.has(visibility) || EXPLICIT_HIDDEN_VISIBILITIES.has(transcriptVisibility) || HIDDEN_AUDIENCES.has(audience) || hasBooleanMarker(message, meta, ["internal", "isInternal", "debug", "statusOnly", "controlOnly"]);
|
|
8243
|
+
const explicitUserFacing = EXPLICIT_VISIBLE_VISIBILITIES.has(visibility) || EXPLICIT_VISIBLE_VISIBILITIES.has(transcriptVisibility) || audience === "chat" || hasBooleanMarker(message, meta, ["userFacing"]);
|
|
8244
|
+
if (explicitHidden) {
|
|
8245
|
+
const activityLike = isActivityKind(kind) || ACTIVITY_SOURCE_SET.has(source);
|
|
8246
|
+
return {
|
|
8247
|
+
surface: activityLike ? "activity" : "internal",
|
|
8248
|
+
isUserFacing: false,
|
|
8249
|
+
isActivityFacing: activityLike,
|
|
8250
|
+
isInternal: !activityLike,
|
|
8251
|
+
explicitUserFacing,
|
|
8252
|
+
explicitHidden,
|
|
8253
|
+
role,
|
|
8254
|
+
kind,
|
|
8255
|
+
visibility,
|
|
8256
|
+
transcriptVisibility,
|
|
8257
|
+
audience,
|
|
8258
|
+
source
|
|
8259
|
+
};
|
|
8260
|
+
}
|
|
8261
|
+
if (explicitUserFacing) {
|
|
8262
|
+
return {
|
|
8263
|
+
surface: "chat",
|
|
8264
|
+
isUserFacing: true,
|
|
8265
|
+
isActivityFacing: false,
|
|
8266
|
+
isInternal: false,
|
|
8267
|
+
explicitUserFacing,
|
|
8268
|
+
explicitHidden,
|
|
8269
|
+
role,
|
|
8270
|
+
kind,
|
|
8271
|
+
visibility,
|
|
8272
|
+
transcriptVisibility,
|
|
8273
|
+
audience,
|
|
8274
|
+
source
|
|
8275
|
+
};
|
|
8276
|
+
}
|
|
8277
|
+
if (INTERNAL_SOURCE_SET.has(source) || role === "system" || kind === "system") {
|
|
8278
|
+
return {
|
|
8279
|
+
surface: "internal",
|
|
8280
|
+
isUserFacing: false,
|
|
8281
|
+
isActivityFacing: false,
|
|
8282
|
+
isInternal: true,
|
|
8283
|
+
explicitUserFacing,
|
|
8284
|
+
explicitHidden,
|
|
8285
|
+
role,
|
|
8286
|
+
kind,
|
|
8287
|
+
visibility,
|
|
8288
|
+
transcriptVisibility,
|
|
8289
|
+
audience,
|
|
8290
|
+
source
|
|
8291
|
+
};
|
|
8292
|
+
}
|
|
8293
|
+
if (ACTIVITY_SOURCE_SET.has(source) || isActivityKind(kind)) {
|
|
8294
|
+
return {
|
|
8295
|
+
surface: "activity",
|
|
8296
|
+
isUserFacing: false,
|
|
8297
|
+
isActivityFacing: true,
|
|
8298
|
+
isInternal: false,
|
|
8299
|
+
explicitUserFacing,
|
|
8300
|
+
explicitHidden,
|
|
8301
|
+
role,
|
|
8302
|
+
kind,
|
|
8303
|
+
visibility,
|
|
8304
|
+
transcriptVisibility,
|
|
8305
|
+
audience,
|
|
8306
|
+
source
|
|
8307
|
+
};
|
|
8308
|
+
}
|
|
8309
|
+
const isUserFacing = isOrdinaryVisibleTurn(message, role, kind);
|
|
8310
|
+
return {
|
|
8311
|
+
surface: isUserFacing ? "chat" : "internal",
|
|
8312
|
+
isUserFacing,
|
|
8313
|
+
isActivityFacing: false,
|
|
8314
|
+
isInternal: !isUserFacing,
|
|
8315
|
+
explicitUserFacing,
|
|
8316
|
+
explicitHidden,
|
|
8317
|
+
role,
|
|
8318
|
+
kind,
|
|
8319
|
+
visibility,
|
|
8320
|
+
transcriptVisibility,
|
|
8321
|
+
audience,
|
|
8322
|
+
source
|
|
8323
|
+
};
|
|
8324
|
+
}
|
|
8325
|
+
function isUserFacingChatMessage(message) {
|
|
8326
|
+
return classifyChatMessageVisibility(message).isUserFacing;
|
|
8327
|
+
}
|
|
8328
|
+
function isActivityChatMessage(message) {
|
|
8329
|
+
return classifyChatMessageVisibility(message).isActivityFacing;
|
|
8330
|
+
}
|
|
8331
|
+
function isInternalChatMessage(message) {
|
|
8332
|
+
return classifyChatMessageVisibility(message).isInternal;
|
|
8333
|
+
}
|
|
8334
|
+
function filterUserFacingChatMessages(messages) {
|
|
8335
|
+
return (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
|
|
8336
|
+
}
|
|
8337
|
+
function filterActivityChatMessages(messages) {
|
|
8338
|
+
return (Array.isArray(messages) ? messages : []).filter((message) => isActivityChatMessage(message));
|
|
8339
|
+
}
|
|
8340
|
+
function filterInternalChatMessages(messages) {
|
|
8341
|
+
return (Array.isArray(messages) ? messages : []).filter((message) => isInternalChatMessage(message));
|
|
8342
|
+
}
|
|
8343
|
+
function filterChatMessagesByVisibility(messages, surface) {
|
|
8344
|
+
return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
|
|
8345
|
+
}
|
|
7977
8346
|
|
|
7978
8347
|
// src/providers/control-effects.ts
|
|
7979
8348
|
function extractProviderControlValues(controls, data) {
|
|
@@ -8170,9 +8539,9 @@ ${cleanBody}`;
|
|
|
8170
8539
|
|
|
8171
8540
|
// src/config/chat-history.ts
|
|
8172
8541
|
var fs3 = __toESM(require("fs"));
|
|
8173
|
-
var
|
|
8542
|
+
var path11 = __toESM(require("path"));
|
|
8174
8543
|
var os5 = __toESM(require("os"));
|
|
8175
|
-
var HISTORY_DIR =
|
|
8544
|
+
var HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
|
|
8176
8545
|
var RETAIN_DAYS = 30;
|
|
8177
8546
|
var SAVED_HISTORY_INDEX_VERSION = 1;
|
|
8178
8547
|
var SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -8335,7 +8704,7 @@ function extractSavedHistorySessionIdFromFile(file) {
|
|
|
8335
8704
|
function buildSavedHistoryFileSignatureMap(dir, files) {
|
|
8336
8705
|
return new Map(files.map((file) => {
|
|
8337
8706
|
try {
|
|
8338
|
-
const stat2 = fs3.statSync(
|
|
8707
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8339
8708
|
return [file, `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`];
|
|
8340
8709
|
} catch {
|
|
8341
8710
|
return [file, `${file}:missing`];
|
|
@@ -8346,7 +8715,7 @@ function buildSavedHistoryCacheSignature(files, fileSignatures) {
|
|
|
8346
8715
|
return files.map((file) => fileSignatures.get(file) || `${file}:missing`).join("|");
|
|
8347
8716
|
}
|
|
8348
8717
|
function getSavedHistoryIndexFilePath(dir) {
|
|
8349
|
-
return
|
|
8718
|
+
return path11.join(dir, SAVED_HISTORY_INDEX_FILE);
|
|
8350
8719
|
}
|
|
8351
8720
|
function getSavedHistoryIndexLockPath(dir) {
|
|
8352
8721
|
return `${getSavedHistoryIndexFilePath(dir)}${SAVED_HISTORY_INDEX_LOCK_SUFFIX}`;
|
|
@@ -8448,7 +8817,7 @@ function savePersistedSavedHistoryIndex(dir, entries) {
|
|
|
8448
8817
|
}
|
|
8449
8818
|
for (const file of Array.from(currentEntries.keys())) {
|
|
8450
8819
|
if (incomingFiles.has(file)) continue;
|
|
8451
|
-
if (!fs3.existsSync(
|
|
8820
|
+
if (!fs3.existsSync(path11.join(dir, file))) {
|
|
8452
8821
|
currentEntries.delete(file);
|
|
8453
8822
|
}
|
|
8454
8823
|
}
|
|
@@ -8474,7 +8843,7 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8474
8843
|
const indexStat = fs3.statSync(getSavedHistoryIndexFilePath(dir));
|
|
8475
8844
|
const files = listHistoryFiles(dir);
|
|
8476
8845
|
for (const file of files) {
|
|
8477
|
-
const stat2 = fs3.statSync(
|
|
8846
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8478
8847
|
if (stat2.mtimeMs > indexStat.mtimeMs) return true;
|
|
8479
8848
|
}
|
|
8480
8849
|
return false;
|
|
@@ -8484,14 +8853,14 @@ function historyDirectoryHasFilesNewerThanIndex(dir) {
|
|
|
8484
8853
|
}
|
|
8485
8854
|
function buildSavedHistoryFileSignature(dir, file) {
|
|
8486
8855
|
try {
|
|
8487
|
-
const stat2 = fs3.statSync(
|
|
8856
|
+
const stat2 = fs3.statSync(path11.join(dir, file));
|
|
8488
8857
|
return `${file}:${stat2.size}:${Math.trunc(stat2.mtimeMs)}`;
|
|
8489
8858
|
} catch {
|
|
8490
8859
|
return `${file}:missing`;
|
|
8491
8860
|
}
|
|
8492
8861
|
}
|
|
8493
8862
|
function persistSavedHistoryFileSummaryEntry(agentType, dir, file, updater) {
|
|
8494
|
-
const filePath =
|
|
8863
|
+
const filePath = path11.join(dir, file);
|
|
8495
8864
|
const result = withLockedPersistedSavedHistoryIndex(dir, (entries) => {
|
|
8496
8865
|
const currentEntry = entries.get(file) || null;
|
|
8497
8866
|
const nextSummary = updater(currentEntry?.summary || null);
|
|
@@ -8564,7 +8933,7 @@ function updateSavedHistoryIndexForAppendedMessages(agentType, dir, file, histor
|
|
|
8564
8933
|
function computeSavedHistoryFileSummary(dir, file) {
|
|
8565
8934
|
const historySessionId = extractSavedHistorySessionIdFromFile(file);
|
|
8566
8935
|
if (!historySessionId) return null;
|
|
8567
|
-
const filePath =
|
|
8936
|
+
const filePath = path11.join(dir, file);
|
|
8568
8937
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
8569
8938
|
const lines = content.split("\n").filter(Boolean);
|
|
8570
8939
|
let messageCount = 0;
|
|
@@ -8651,7 +9020,7 @@ function computeSavedHistorySessionSummaries(agentType, dir, files, fileSignatur
|
|
|
8651
9020
|
const summaryBySessionId = /* @__PURE__ */ new Map();
|
|
8652
9021
|
const nextPersistedEntries = /* @__PURE__ */ new Map();
|
|
8653
9022
|
for (const file of files.slice().sort()) {
|
|
8654
|
-
const filePath =
|
|
9023
|
+
const filePath = path11.join(dir, file);
|
|
8655
9024
|
const signature = fileSignatures.get(file) || `${file}:missing`;
|
|
8656
9025
|
const cached = savedHistoryFileSummaryCache.get(filePath);
|
|
8657
9026
|
const persisted = persistedEntries.get(file);
|
|
@@ -8771,12 +9140,12 @@ var ChatHistoryWriter = class {
|
|
|
8771
9140
|
});
|
|
8772
9141
|
}
|
|
8773
9142
|
if (newMessages.length === 0) return;
|
|
8774
|
-
const dir =
|
|
9143
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8775
9144
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8776
9145
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8777
9146
|
const filePrefix = effectiveHistoryKey ? `${this.sanitize(effectiveHistoryKey)}_` : "";
|
|
8778
9147
|
const fileName = `${filePrefix}${date}.jsonl`;
|
|
8779
|
-
const filePath =
|
|
9148
|
+
const filePath = path11.join(dir, fileName);
|
|
8780
9149
|
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
8781
9150
|
fs3.appendFileSync(filePath, lines, "utf-8");
|
|
8782
9151
|
updateSavedHistoryIndexForAppendedMessages(agentType, dir, fileName, effectiveHistoryKey, newMessages);
|
|
@@ -8867,11 +9236,11 @@ var ChatHistoryWriter = class {
|
|
|
8867
9236
|
const ws = String(workspace || "").trim();
|
|
8868
9237
|
if (!id || !ws) return;
|
|
8869
9238
|
try {
|
|
8870
|
-
const dir =
|
|
9239
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8871
9240
|
fs3.mkdirSync(dir, { recursive: true });
|
|
8872
9241
|
const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
8873
9242
|
const fileName = `${this.sanitize(id)}_${date}.jsonl`;
|
|
8874
|
-
const filePath =
|
|
9243
|
+
const filePath = path11.join(dir, fileName);
|
|
8875
9244
|
const record = {
|
|
8876
9245
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8877
9246
|
receivedAt: Date.now(),
|
|
@@ -8917,14 +9286,14 @@ var ChatHistoryWriter = class {
|
|
|
8917
9286
|
this.lastSeenCounts.set(toDedupKey, Math.max(fromCount, this.lastSeenCounts.get(toDedupKey) || 0));
|
|
8918
9287
|
this.lastSeenCounts.delete(fromDedupKey);
|
|
8919
9288
|
}
|
|
8920
|
-
const dir =
|
|
9289
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8921
9290
|
if (!fs3.existsSync(dir)) return;
|
|
8922
9291
|
const fromPrefix = `${this.sanitize(fromId)}_`;
|
|
8923
9292
|
const toPrefix = `${this.sanitize(toId)}_`;
|
|
8924
9293
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(fromPrefix) && file.endsWith(".jsonl"));
|
|
8925
9294
|
for (const file of files) {
|
|
8926
|
-
const sourcePath =
|
|
8927
|
-
const targetPath =
|
|
9295
|
+
const sourcePath = path11.join(dir, file);
|
|
9296
|
+
const targetPath = path11.join(dir, `${toPrefix}${file.slice(fromPrefix.length)}`);
|
|
8928
9297
|
const sourceLines = fs3.readFileSync(sourcePath, "utf-8").split("\n").filter(Boolean);
|
|
8929
9298
|
const rewritten = sourceLines.map((line) => {
|
|
8930
9299
|
try {
|
|
@@ -8958,13 +9327,13 @@ var ChatHistoryWriter = class {
|
|
|
8958
9327
|
const sessionId = String(historySessionId || "").trim();
|
|
8959
9328
|
if (!sessionId) return;
|
|
8960
9329
|
try {
|
|
8961
|
-
const dir =
|
|
9330
|
+
const dir = path11.join(HISTORY_DIR, this.sanitize(agentType));
|
|
8962
9331
|
if (!fs3.existsSync(dir)) return;
|
|
8963
9332
|
const prefix = `${this.sanitize(sessionId)}_`;
|
|
8964
9333
|
const files = fs3.readdirSync(dir).filter((file) => file.startsWith(prefix) && file.endsWith(".jsonl")).sort();
|
|
8965
9334
|
const seen = /* @__PURE__ */ new Set();
|
|
8966
9335
|
for (const file of files) {
|
|
8967
|
-
const filePath =
|
|
9336
|
+
const filePath = path11.join(dir, file);
|
|
8968
9337
|
const lines = fs3.readFileSync(filePath, "utf-8").split("\n").filter(Boolean);
|
|
8969
9338
|
const next = [];
|
|
8970
9339
|
for (const line of lines) {
|
|
@@ -9018,11 +9387,11 @@ var ChatHistoryWriter = class {
|
|
|
9018
9387
|
const cutoff = Date.now() - RETAIN_DAYS * 24 * 60 * 60 * 1e3;
|
|
9019
9388
|
const agentDirs = fs3.readdirSync(HISTORY_DIR, { withFileTypes: true }).filter((d) => d.isDirectory());
|
|
9020
9389
|
for (const dir of agentDirs) {
|
|
9021
|
-
const dirPath =
|
|
9390
|
+
const dirPath = path11.join(HISTORY_DIR, dir.name);
|
|
9022
9391
|
const files = fs3.readdirSync(dirPath).filter((f) => f.endsWith(".jsonl") || f.endsWith(".terminal.log"));
|
|
9023
9392
|
let removedAny = false;
|
|
9024
9393
|
for (const file of files) {
|
|
9025
|
-
const filePath =
|
|
9394
|
+
const filePath = path11.join(dirPath, file);
|
|
9026
9395
|
const stat2 = fs3.statSync(filePath);
|
|
9027
9396
|
if (stat2.mtimeMs < cutoff) {
|
|
9028
9397
|
fs3.unlinkSync(filePath);
|
|
@@ -9072,13 +9441,13 @@ function pageHistoryRecords(agentType, records, offset = 0, limit = 30, excludeR
|
|
|
9072
9441
|
function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, excludeRecentCount = 0, historyBehavior) {
|
|
9073
9442
|
try {
|
|
9074
9443
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9075
|
-
const dir =
|
|
9444
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
9076
9445
|
if (!fs3.existsSync(dir)) return { messages: [], hasMore: false };
|
|
9077
9446
|
const files = listHistoryFiles(dir, historySessionId);
|
|
9078
9447
|
const allMessages = [];
|
|
9079
9448
|
const seen = /* @__PURE__ */ new Set();
|
|
9080
9449
|
for (const file of files) {
|
|
9081
|
-
const filePath =
|
|
9450
|
+
const filePath = path11.join(dir, file);
|
|
9082
9451
|
const content = fs3.readFileSync(filePath, "utf-8");
|
|
9083
9452
|
const lines = content.trim().split("\n").filter(Boolean);
|
|
9084
9453
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -9102,7 +9471,7 @@ function readChatHistory(agentType, offset = 0, limit = 30, historySessionId, ex
|
|
|
9102
9471
|
function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
9103
9472
|
try {
|
|
9104
9473
|
const sanitized = agentType.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
9105
|
-
const dir =
|
|
9474
|
+
const dir = path11.join(HISTORY_DIR, sanitized);
|
|
9106
9475
|
if (!fs3.existsSync(dir)) {
|
|
9107
9476
|
savedHistorySessionCache.delete(sanitized);
|
|
9108
9477
|
return { sessions: [], hasMore: false };
|
|
@@ -9163,11 +9532,11 @@ function listSavedHistorySessions(agentType, options = {}, historyBehavior) {
|
|
|
9163
9532
|
}
|
|
9164
9533
|
function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
9165
9534
|
try {
|
|
9166
|
-
const dir =
|
|
9535
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9167
9536
|
if (!fs3.existsSync(dir)) return null;
|
|
9168
9537
|
const files = listHistoryFiles(dir, historySessionId).sort();
|
|
9169
9538
|
for (const file of files) {
|
|
9170
|
-
const lines = fs3.readFileSync(
|
|
9539
|
+
const lines = fs3.readFileSync(path11.join(dir, file), "utf-8").split("\n").filter(Boolean);
|
|
9171
9540
|
for (const line of lines) {
|
|
9172
9541
|
try {
|
|
9173
9542
|
const parsed = JSON.parse(line);
|
|
@@ -9187,16 +9556,16 @@ function readExistingSessionStartRecord(agentType, historySessionId) {
|
|
|
9187
9556
|
function rewriteCanonicalSavedHistory(agentType, historySessionId, records) {
|
|
9188
9557
|
if (records.length === 0) return false;
|
|
9189
9558
|
try {
|
|
9190
|
-
const dir =
|
|
9559
|
+
const dir = path11.join(HISTORY_DIR, agentType);
|
|
9191
9560
|
fs3.mkdirSync(dir, { recursive: true });
|
|
9192
9561
|
const prefix = `${historySessionId.replace(/[^a-zA-Z0-9_-]/g, "_")}_`;
|
|
9193
9562
|
for (const file of fs3.readdirSync(dir)) {
|
|
9194
9563
|
if (file.startsWith(prefix) && file.endsWith(".jsonl")) {
|
|
9195
|
-
fs3.unlinkSync(
|
|
9564
|
+
fs3.unlinkSync(path11.join(dir, file));
|
|
9196
9565
|
}
|
|
9197
9566
|
}
|
|
9198
9567
|
const targetDate = new Date(records[records.length - 1].receivedAt || Date.now()).toISOString().slice(0, 10);
|
|
9199
|
-
const filePath =
|
|
9568
|
+
const filePath = path11.join(dir, `${prefix}${targetDate}.jsonl`);
|
|
9200
9569
|
fs3.writeFileSync(filePath, `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
9201
9570
|
`, "utf-8");
|
|
9202
9571
|
invalidatePersistedSavedHistoryIndex(agentType, dir);
|
|
@@ -9946,6 +10315,14 @@ function validateMessage(message, source, index) {
|
|
|
9946
10315
|
if (typeof message.senderName === "string") normalized.senderName = message.senderName;
|
|
9947
10316
|
if (typeof message._type === "string") normalized._type = message._type;
|
|
9948
10317
|
if (typeof message._sub === "string") normalized._sub = message._sub;
|
|
10318
|
+
if (typeof message.visibility === "string") normalized.visibility = message.visibility;
|
|
10319
|
+
if (typeof message.transcriptVisibility === "string") normalized.transcriptVisibility = message.transcriptVisibility;
|
|
10320
|
+
if (typeof message.audience === "string") normalized.audience = message.audience;
|
|
10321
|
+
if (typeof message.source === "string") normalized.source = message.source;
|
|
10322
|
+
if (typeof message.userFacing === "boolean") normalized.userFacing = message.userFacing;
|
|
10323
|
+
if (typeof message.internal === "boolean") normalized.internal = message.internal;
|
|
10324
|
+
if (typeof message.isInternal === "boolean") normalized.isInternal = message.isInternal;
|
|
10325
|
+
if (typeof message.debug === "boolean") normalized.debug = message.debug;
|
|
9949
10326
|
return normalized;
|
|
9950
10327
|
}
|
|
9951
10328
|
function validateModal(activeModal, status, source) {
|
|
@@ -11191,6 +11568,14 @@ function getActiveChatOptions(profile) {
|
|
|
11191
11568
|
if (profile === "full") return {};
|
|
11192
11569
|
return LIVE_STATUS_ACTIVE_CHAT_OPTIONS;
|
|
11193
11570
|
}
|
|
11571
|
+
function resolveSessionStatus(activeChat, providerStatus) {
|
|
11572
|
+
const chatStatus = normalizeManagedStatus(activeChat?.status, { activeModal: activeChat?.activeModal || null });
|
|
11573
|
+
const topLevelStatus = normalizeManagedStatus(providerStatus, { activeModal: activeChat?.activeModal || null });
|
|
11574
|
+
if (chatStatus === "waiting_approval" || topLevelStatus === "waiting_approval") return "waiting_approval";
|
|
11575
|
+
if (chatStatus === "generating" || topLevelStatus === "generating") return "generating";
|
|
11576
|
+
if (topLevelStatus !== "idle") return topLevelStatus;
|
|
11577
|
+
return chatStatus;
|
|
11578
|
+
}
|
|
11194
11579
|
function shouldIncludeSessionControls(profile) {
|
|
11195
11580
|
return profile !== "live";
|
|
11196
11581
|
}
|
|
@@ -11269,9 +11654,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
11269
11654
|
providerName: state.name,
|
|
11270
11655
|
kind: "workspace",
|
|
11271
11656
|
transport: "cdp-page",
|
|
11272
|
-
status:
|
|
11273
|
-
activeModal: activeChat?.activeModal || null
|
|
11274
|
-
}),
|
|
11657
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11275
11658
|
title,
|
|
11276
11659
|
workspace,
|
|
11277
11660
|
...git && { git },
|
|
@@ -11306,9 +11689,7 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
11306
11689
|
providerSessionId: ext.providerSessionId,
|
|
11307
11690
|
kind: "agent",
|
|
11308
11691
|
transport: "cdp-webview",
|
|
11309
|
-
status:
|
|
11310
|
-
activeModal: activeChat?.activeModal || null
|
|
11311
|
-
}),
|
|
11692
|
+
status: resolveSessionStatus(activeChat, ext.status),
|
|
11312
11693
|
title: activeChat?.title || ext.name,
|
|
11313
11694
|
workspace,
|
|
11314
11695
|
...git && { git },
|
|
@@ -11358,9 +11739,7 @@ function buildCliSession(state, options) {
|
|
|
11358
11739
|
providerSessionId: state.providerSessionId,
|
|
11359
11740
|
kind: "agent",
|
|
11360
11741
|
transport: "pty",
|
|
11361
|
-
status:
|
|
11362
|
-
activeModal: activeChat?.activeModal || null
|
|
11363
|
-
}),
|
|
11742
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11364
11743
|
title: activeChat?.title || state.name,
|
|
11365
11744
|
workspace,
|
|
11366
11745
|
...git && { git },
|
|
@@ -11408,9 +11787,7 @@ function buildAcpSession(state, options) {
|
|
|
11408
11787
|
providerName: state.name,
|
|
11409
11788
|
kind: "agent",
|
|
11410
11789
|
transport: "acp",
|
|
11411
|
-
status:
|
|
11412
|
-
activeModal: activeChat?.activeModal || null
|
|
11413
|
-
}),
|
|
11790
|
+
status: resolveSessionStatus(activeChat, state.status),
|
|
11414
11791
|
title: activeChat?.title || state.name,
|
|
11415
11792
|
workspace,
|
|
11416
11793
|
...git && { git },
|
|
@@ -11533,7 +11910,7 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
11533
11910
|
// src/commands/chat-commands.ts
|
|
11534
11911
|
var fs4 = __toESM(require("fs"));
|
|
11535
11912
|
var os6 = __toESM(require("os"));
|
|
11536
|
-
var
|
|
11913
|
+
var path12 = __toESM(require("path"));
|
|
11537
11914
|
var import_node_crypto = require("crypto");
|
|
11538
11915
|
|
|
11539
11916
|
// src/providers/provider-input-support.ts
|
|
@@ -11736,6 +12113,7 @@ function buildSessionModalDeliverySignature(payload) {
|
|
|
11736
12113
|
// src/commands/chat-commands.ts
|
|
11737
12114
|
var RECENT_SEND_WINDOW_MS = 1200;
|
|
11738
12115
|
var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
|
|
12116
|
+
var HERMES_CLI_STARTING_SEND_SETTLE_MS = 2e3;
|
|
11739
12117
|
var recentSendByTarget = /* @__PURE__ */ new Map();
|
|
11740
12118
|
function getCurrentProviderType(h, fallback = "") {
|
|
11741
12119
|
return h.currentSession?.providerType || h.currentProviderType || fallback;
|
|
@@ -11788,6 +12166,16 @@ function buildSendInputSignature(input) {
|
|
|
11788
12166
|
function getSendChatInputEnvelope(args) {
|
|
11789
12167
|
return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
|
|
11790
12168
|
}
|
|
12169
|
+
function sleep(ms) {
|
|
12170
|
+
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
12171
|
+
}
|
|
12172
|
+
async function waitOnceForFreshHermesCliStart(adapter, log) {
|
|
12173
|
+
if (adapter.cliType !== "hermes-cli") return;
|
|
12174
|
+
const status = typeof adapter.getStatus === "function" ? adapter.getStatus()?.status : void 0;
|
|
12175
|
+
if (status !== "starting") return;
|
|
12176
|
+
log(`Hermes CLI is still starting; waiting ${HERMES_CLI_STARTING_SEND_SETTLE_MS}ms before first send`);
|
|
12177
|
+
await sleep(HERMES_CLI_STARTING_SEND_SETTLE_MS);
|
|
12178
|
+
}
|
|
11791
12179
|
function getHistorySessionId(h, args) {
|
|
11792
12180
|
const explicit = typeof args?.historySessionId === "string" ? args.historySessionId.trim() : "";
|
|
11793
12181
|
if (explicit) return explicit;
|
|
@@ -11842,7 +12230,7 @@ function normalizeReadChatTailLimit(args) {
|
|
|
11842
12230
|
}
|
|
11843
12231
|
function normalizeReadChatMessages(payload) {
|
|
11844
12232
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
11845
|
-
return messages;
|
|
12233
|
+
return normalizeChatMessages(messages);
|
|
11846
12234
|
}
|
|
11847
12235
|
function deriveHistoryDedupKey(message) {
|
|
11848
12236
|
const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
|
|
@@ -11896,6 +12284,34 @@ function normalizeReadChatCommandStatus(status, activeModal) {
|
|
|
11896
12284
|
return raw;
|
|
11897
12285
|
}
|
|
11898
12286
|
}
|
|
12287
|
+
function isGeneratingLikeStatus(status) {
|
|
12288
|
+
return status === "generating" || status === "streaming" || status === "long_generating" || status === "starting";
|
|
12289
|
+
}
|
|
12290
|
+
function shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
12291
|
+
if (!isGeneratingLikeStatus(parsedStatus)) return false;
|
|
12292
|
+
if (hasNonEmptyModalButtons(activeModal)) return false;
|
|
12293
|
+
const adapterRawStatus = typeof adapterStatus?.status === "string" ? adapterStatus.status.trim() : "";
|
|
12294
|
+
if (adapterRawStatus !== "idle") return false;
|
|
12295
|
+
if (typeof adapter.isProcessing === "function" && adapter.isProcessing()) return false;
|
|
12296
|
+
return true;
|
|
12297
|
+
}
|
|
12298
|
+
function normalizeCliReadChatStatus(parsedStatus, activeModal, adapter, adapterStatus) {
|
|
12299
|
+
if (shouldTrustCliAdapterTerminalStatus(parsedStatus, activeModal, adapter, adapterStatus)) return "idle";
|
|
12300
|
+
return typeof parsedStatus === "string" && parsedStatus.trim() ? parsedStatus : "idle";
|
|
12301
|
+
}
|
|
12302
|
+
function finalizeStreamingMessagesWhenIdle(messages, status) {
|
|
12303
|
+
if (status !== "idle") return messages;
|
|
12304
|
+
return messages.map((message) => {
|
|
12305
|
+
const meta = message.meta && typeof message.meta === "object" ? message.meta : void 0;
|
|
12306
|
+
const hasStreamingMeta = meta?.streaming === true;
|
|
12307
|
+
if (message.bubbleState !== "streaming" && !hasStreamingMeta) return message;
|
|
12308
|
+
return {
|
|
12309
|
+
...message,
|
|
12310
|
+
...message.bubbleState === "streaming" ? { bubbleState: "final" } : {},
|
|
12311
|
+
...hasStreamingMeta ? { meta: { ...meta, streaming: false } } : {}
|
|
12312
|
+
};
|
|
12313
|
+
});
|
|
12314
|
+
}
|
|
11899
12315
|
function buildReadChatCommandResult(payload, args) {
|
|
11900
12316
|
let validatedPayload;
|
|
11901
12317
|
const debugReadChat = payload?.debugReadChat && typeof payload.debugReadChat === "object" ? payload.debugReadChat : void 0;
|
|
@@ -11908,13 +12324,22 @@ function buildReadChatCommandResult(payload, args) {
|
|
|
11908
12324
|
return { success: false, error: error?.message || String(error) };
|
|
11909
12325
|
}
|
|
11910
12326
|
const messages = normalizeReadChatMessages(validatedPayload);
|
|
11911
|
-
const
|
|
12327
|
+
const visibleMessages = filterUserFacingChatMessages(messages);
|
|
12328
|
+
const sync = buildFullTail(visibleMessages, normalizeReadChatTailLimit(args));
|
|
12329
|
+
const hiddenMsgCount = Math.max(0, messages.length - visibleMessages.length);
|
|
12330
|
+
const returnedDebugReadChat = debugReadChat ? {
|
|
12331
|
+
...debugReadChat,
|
|
12332
|
+
fullMsgCount: typeof debugReadChat.fullMsgCount === "number" ? debugReadChat.fullMsgCount : messages.length,
|
|
12333
|
+
visibleMsgCount: visibleMessages.length,
|
|
12334
|
+
hiddenMsgCount,
|
|
12335
|
+
returnedMsgCount: sync.messages.length
|
|
12336
|
+
} : void 0;
|
|
11912
12337
|
return {
|
|
11913
12338
|
success: true,
|
|
11914
12339
|
...validatedPayload,
|
|
11915
12340
|
messages: sync.messages,
|
|
11916
12341
|
totalMessages: sync.totalMessages,
|
|
11917
|
-
...
|
|
12342
|
+
...returnedDebugReadChat ? { debugReadChat: returnedDebugReadChat } : {}
|
|
11918
12343
|
};
|
|
11919
12344
|
}
|
|
11920
12345
|
var DEFAULT_DEBUG_SANITIZE_OPTIONS = {
|
|
@@ -12044,7 +12469,7 @@ function buildDebugBundleText(bundle) {
|
|
|
12044
12469
|
}
|
|
12045
12470
|
function getChatDebugBundleDir() {
|
|
12046
12471
|
const override = typeof process.env.ADHDEV_DEBUG_BUNDLE_DIR === "string" ? process.env.ADHDEV_DEBUG_BUNDLE_DIR.trim() : "";
|
|
12047
|
-
return override ||
|
|
12472
|
+
return override || path12.join(os6.homedir(), ".adhdev", "debug-bundles", "chat");
|
|
12048
12473
|
}
|
|
12049
12474
|
function safeBundleIdSegment(value, fallback) {
|
|
12050
12475
|
const normalized = String(value || fallback).trim().replace(/[^A-Za-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 80);
|
|
@@ -12060,6 +12485,14 @@ function buildChatDebugBundleSummary(bundle) {
|
|
|
12060
12485
|
const readChat = bundle.readChat && typeof bundle.readChat === "object" ? bundle.readChat : {};
|
|
12061
12486
|
const cli = bundle.cli && typeof bundle.cli === "object" ? bundle.cli : null;
|
|
12062
12487
|
const frontend = bundle.frontend && typeof bundle.frontend === "object" ? bundle.frontend : null;
|
|
12488
|
+
const debugReadChat = readChat.debugReadChat && typeof readChat.debugReadChat === "object" ? readChat.debugReadChat : {};
|
|
12489
|
+
const parsedStatus = cli?.parsedStatus && typeof cli.parsedStatus === "object" ? cli.parsedStatus : null;
|
|
12490
|
+
const cliParsedMessageCount = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages.length : void 0;
|
|
12491
|
+
const readChatReturnedMessages = Array.isArray(readChat.messagesTail) ? readChat.messagesTail.length : void 0;
|
|
12492
|
+
const cliPartialResponse = typeof cli?.partialResponse === "string" ? cli.partialResponse : "";
|
|
12493
|
+
const readChatStatus = typeof readChat.status === "string" ? readChat.status : "";
|
|
12494
|
+
const cliStatus = typeof cli?.status === "string" ? cli.status : "";
|
|
12495
|
+
const cliParsedStatus = typeof parsedStatus?.status === "string" ? parsedStatus.status : "";
|
|
12063
12496
|
return {
|
|
12064
12497
|
createdAt: bundle.createdAt,
|
|
12065
12498
|
targetSessionId: target.targetSessionId,
|
|
@@ -12068,8 +12501,22 @@ function buildChatDebugBundleSummary(bundle) {
|
|
|
12068
12501
|
readChatSuccess: readChat.success,
|
|
12069
12502
|
readChatStatus: readChat.status,
|
|
12070
12503
|
readChatTotalMessages: readChat.totalMessages,
|
|
12504
|
+
readChatReturnedMessages,
|
|
12071
12505
|
cliStatus: cli?.status,
|
|
12506
|
+
cliParsedStatus: cliParsedStatus || void 0,
|
|
12072
12507
|
cliMessageCount: cli?.messageCount,
|
|
12508
|
+
cliParsedMessageCount,
|
|
12509
|
+
cliPartialResponseChars: cliPartialResponse.length,
|
|
12510
|
+
parserAdapterStatusMismatch: Boolean(cliStatus && cliParsedStatus && cliStatus !== cliParsedStatus),
|
|
12511
|
+
parserReadChatStatusMismatch: Boolean(readChatStatus && cliParsedStatus && readChatStatus !== cliParsedStatus),
|
|
12512
|
+
readChatDebug: Object.keys(debugReadChat).length ? {
|
|
12513
|
+
adapterStatus: debugReadChat.adapterStatus,
|
|
12514
|
+
parsedStatus: debugReadChat.parsedStatus,
|
|
12515
|
+
returnedStatus: debugReadChat.returnedStatus,
|
|
12516
|
+
parsedMsgCount: debugReadChat.parsedMsgCount,
|
|
12517
|
+
returnedMsgCount: debugReadChat.returnedMsgCount,
|
|
12518
|
+
shouldPreferAdapterMessages: debugReadChat.shouldPreferAdapterMessages
|
|
12519
|
+
} : void 0,
|
|
12073
12520
|
hasFrontendSnapshot: !!frontend
|
|
12074
12521
|
};
|
|
12075
12522
|
}
|
|
@@ -12077,7 +12524,7 @@ function storeChatDebugBundleOnDaemon(bundle, targetSessionId) {
|
|
|
12077
12524
|
const bundleId = createChatDebugBundleId(targetSessionId);
|
|
12078
12525
|
const dir = getChatDebugBundleDir();
|
|
12079
12526
|
fs4.mkdirSync(dir, { recursive: true });
|
|
12080
|
-
const savedPath =
|
|
12527
|
+
const savedPath = path12.join(dir, `${bundleId}.json`);
|
|
12081
12528
|
const json = `${JSON.stringify(bundle, null, 2)}
|
|
12082
12529
|
`;
|
|
12083
12530
|
fs4.writeFileSync(savedPath, json, { encoding: "utf8", mode: 384 });
|
|
@@ -12307,7 +12754,7 @@ async function handleChatHistory(h, args) {
|
|
|
12307
12754
|
}
|
|
12308
12755
|
}
|
|
12309
12756
|
async function handleReadChat(h, args) {
|
|
12310
|
-
const provider = h.getProvider(args?.agentType);
|
|
12757
|
+
const provider = h.getProvider(args?.agentType || args?.providerType);
|
|
12311
12758
|
const transport = getTargetTransport(h, provider);
|
|
12312
12759
|
const historySessionId = getHistorySessionId(h, args);
|
|
12313
12760
|
const _log = (msg) => LOG.debug("Command", `[read_chat] ${msg}`);
|
|
@@ -12334,10 +12781,13 @@ async function handleReadChat(h, args) {
|
|
|
12334
12781
|
const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
|
|
12335
12782
|
const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
|
|
12336
12783
|
const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
|
|
12337
|
-
const returnedStatus = parsedRecord.status
|
|
12338
|
-
|
|
12784
|
+
const returnedStatus = normalizeCliReadChatStatus(parsedRecord.status, activeModal, adapter, adapterStatus);
|
|
12785
|
+
const runtimeMessageMerger = getTargetInstance(h, args);
|
|
12786
|
+
const parsedMessages = finalizeStreamingMessagesWhenIdle(parsedRecord.messages, returnedStatus);
|
|
12787
|
+
const returnedMessages = runtimeMessageMerger?.category === "cli" && runtimeMessageMerger.type === adapter.cliType && typeof runtimeMessageMerger.mergeRuntimeChatMessages === "function" ? runtimeMessageMerger.mergeRuntimeChatMessages(parsedMessages) : parsedMessages;
|
|
12788
|
+
LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length} returnedMsgCount=${returnedMessages.length}`);
|
|
12339
12789
|
return buildReadChatCommandResult({
|
|
12340
|
-
messages:
|
|
12790
|
+
messages: returnedMessages,
|
|
12341
12791
|
status: returnedStatus,
|
|
12342
12792
|
activeModal,
|
|
12343
12793
|
debugReadChat: {
|
|
@@ -12348,7 +12798,7 @@ async function handleReadChat(h, args) {
|
|
|
12348
12798
|
returnedStatus: String(returnedStatus || ""),
|
|
12349
12799
|
shouldPreferAdapterMessages: false,
|
|
12350
12800
|
parsedMsgCount: parsedRecord.messages.length,
|
|
12351
|
-
returnedMsgCount:
|
|
12801
|
+
returnedMsgCount: returnedMessages.length
|
|
12352
12802
|
},
|
|
12353
12803
|
...title ? { title } : {},
|
|
12354
12804
|
...providerSessionId ? { providerSessionId } : {},
|
|
@@ -12594,6 +13044,7 @@ async function handleSendChat(h, args) {
|
|
|
12594
13044
|
try {
|
|
12595
13045
|
assertTextOnlyInput(provider, input);
|
|
12596
13046
|
if (!text) return { success: false, error: "text required for PTY send" };
|
|
13047
|
+
await waitOnceForFreshHermesCliStart(adapter, _log);
|
|
12597
13048
|
await adapter.sendMessage(text);
|
|
12598
13049
|
return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
|
|
12599
13050
|
} catch (e) {
|
|
@@ -13093,9 +13544,17 @@ async function handleResolveAction(h, args) {
|
|
|
13093
13544
|
const targetState = targetInstance?.getState?.();
|
|
13094
13545
|
const surfacedModal = targetState?.activeChat?.activeModal && Array.isArray(targetState.activeChat.activeModal.buttons) && targetState.activeChat.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? targetState.activeChat.activeModal : null;
|
|
13095
13546
|
const statusModal = status?.activeModal && Array.isArray(status.activeModal.buttons) && status.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? status.activeModal : null;
|
|
13096
|
-
const
|
|
13097
|
-
|
|
13098
|
-
|
|
13547
|
+
const parsedStatus = !statusModal && !surfacedModal && typeof adapter.getScriptParsedStatus === "function" ? (() => {
|
|
13548
|
+
try {
|
|
13549
|
+
return parseMaybeJson(adapter.getScriptParsedStatus());
|
|
13550
|
+
} catch {
|
|
13551
|
+
return null;
|
|
13552
|
+
}
|
|
13553
|
+
})() : null;
|
|
13554
|
+
const parsedModal = parsedStatus?.status === "waiting_approval" && parsedStatus?.activeModal && Array.isArray(parsedStatus.activeModal.buttons) && parsedStatus.activeModal.buttons.some((candidate) => typeof candidate === "string" && candidate.trim()) ? parsedStatus.activeModal : null;
|
|
13555
|
+
const effectiveModal = statusModal || surfacedModal || parsedModal;
|
|
13556
|
+
const effectiveStatus = status?.status === "waiting_approval" || targetState?.activeChat?.status === "waiting_approval" || parsedStatus?.status === "waiting_approval" ? "waiting_approval" : status?.status;
|
|
13557
|
+
LOG.info("Command", `[resolveAction] CLI PTY gate target=${String(args?.targetSessionId || "")} rawStatus=${String(status?.status || "")} effectiveStatus=${String(effectiveStatus || "")} statusModal=${statusModal ? "yes" : "no"} surfacedModal=${surfacedModal ? "yes" : "no"} parsedModal=${parsedModal ? "yes" : "no"} instance=${targetInstance ? "yes" : "no"}`);
|
|
13099
13558
|
if (!effectiveModal) {
|
|
13100
13559
|
return { success: false, error: "Not in approval state" };
|
|
13101
13560
|
}
|
|
@@ -13221,7 +13680,7 @@ async function handleResolveAction(h, args) {
|
|
|
13221
13680
|
|
|
13222
13681
|
// src/commands/cdp-commands.ts
|
|
13223
13682
|
var fs5 = __toESM(require("fs"));
|
|
13224
|
-
var
|
|
13683
|
+
var path13 = __toESM(require("path"));
|
|
13225
13684
|
var os7 = __toESM(require("os"));
|
|
13226
13685
|
var KEY_TO_VK = {
|
|
13227
13686
|
Backspace: 8,
|
|
@@ -13478,25 +13937,25 @@ function resolveSafePath(requestedPath) {
|
|
|
13478
13937
|
const inputPath = rawPath || ".";
|
|
13479
13938
|
const home = os7.homedir();
|
|
13480
13939
|
if (inputPath.startsWith("~")) {
|
|
13481
|
-
return
|
|
13940
|
+
return path13.resolve(path13.join(home, inputPath.slice(1)));
|
|
13482
13941
|
}
|
|
13483
13942
|
if (process.platform === "win32") {
|
|
13484
13943
|
const normalized = normalizeWindowsRequestedPath(inputPath);
|
|
13485
|
-
if (
|
|
13486
|
-
return
|
|
13944
|
+
if (path13.win32.isAbsolute(normalized)) {
|
|
13945
|
+
return path13.win32.normalize(normalized);
|
|
13487
13946
|
}
|
|
13488
|
-
return
|
|
13947
|
+
return path13.win32.resolve(normalized);
|
|
13489
13948
|
}
|
|
13490
|
-
if (
|
|
13491
|
-
return
|
|
13949
|
+
if (path13.isAbsolute(inputPath)) {
|
|
13950
|
+
return path13.normalize(inputPath);
|
|
13492
13951
|
}
|
|
13493
|
-
return
|
|
13952
|
+
return path13.resolve(inputPath);
|
|
13494
13953
|
}
|
|
13495
13954
|
function listDirectoryEntriesSafe(dirPath) {
|
|
13496
13955
|
const entries = fs5.readdirSync(dirPath, { withFileTypes: true });
|
|
13497
13956
|
const files = [];
|
|
13498
13957
|
for (const entry of entries) {
|
|
13499
|
-
const entryPath =
|
|
13958
|
+
const entryPath = path13.join(dirPath, entry.name);
|
|
13500
13959
|
try {
|
|
13501
13960
|
if (entry.isDirectory()) {
|
|
13502
13961
|
files.push({ name: entry.name, type: "directory" });
|
|
@@ -13550,7 +14009,7 @@ async function handleFileRead(h, args) {
|
|
|
13550
14009
|
async function handleFileWrite(h, args) {
|
|
13551
14010
|
try {
|
|
13552
14011
|
const filePath = resolveSafePath(args?.path);
|
|
13553
|
-
fs5.mkdirSync(
|
|
14012
|
+
fs5.mkdirSync(path13.dirname(filePath), { recursive: true });
|
|
13554
14013
|
fs5.writeFileSync(filePath, args?.content || "", "utf-8");
|
|
13555
14014
|
return { success: true, path: filePath };
|
|
13556
14015
|
} catch (e) {
|
|
@@ -14334,9 +14793,11 @@ var DaemonCommandHandler = class {
|
|
|
14334
14793
|
}
|
|
14335
14794
|
const sessionLookupFailed = !!targetSessionId && !session;
|
|
14336
14795
|
const managerKey = this.extractIdeType(args, sessionLookupFailed);
|
|
14337
|
-
let providerType;
|
|
14796
|
+
let providerType = args?.agentType || args?.providerType;
|
|
14338
14797
|
if (!sessionLookupFailed) {
|
|
14339
|
-
providerType = session?.providerType ||
|
|
14798
|
+
providerType = session?.providerType || providerType || this.inferProviderType(managerKey);
|
|
14799
|
+
} else if (!providerType) {
|
|
14800
|
+
providerType = this.inferProviderType(managerKey);
|
|
14340
14801
|
}
|
|
14341
14802
|
return { session, managerKey, providerType, sessionLookupFailed };
|
|
14342
14803
|
}
|
|
@@ -14416,7 +14877,8 @@ var DaemonCommandHandler = class {
|
|
|
14416
14877
|
"pty_resize",
|
|
14417
14878
|
"invoke_provider_script"
|
|
14418
14879
|
]);
|
|
14419
|
-
|
|
14880
|
+
const allowsInactiveReadChatFallback = cmd === "read_chat" && !!this._currentRoute.providerType && (typeof args?.providerSessionId === "string" && args.providerSessionId.trim().length > 0 || typeof args?.historySessionId === "string" && args.historySessionId.trim().length > 0);
|
|
14881
|
+
if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd) && !allowsInactiveReadChatFallback) {
|
|
14420
14882
|
const result2 = {
|
|
14421
14883
|
success: false,
|
|
14422
14884
|
error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || "").trim() || "unknown"}`
|
|
@@ -14669,7 +15131,7 @@ var DaemonCommandHandler = class {
|
|
|
14669
15131
|
|
|
14670
15132
|
// src/commands/cli-manager.ts
|
|
14671
15133
|
var os13 = __toESM(require("os"));
|
|
14672
|
-
var
|
|
15134
|
+
var path17 = __toESM(require("path"));
|
|
14673
15135
|
var crypto4 = __toESM(require("crypto"));
|
|
14674
15136
|
var import_fs6 = require("fs");
|
|
14675
15137
|
var import_child_process6 = require("child_process");
|
|
@@ -14679,7 +15141,7 @@ init_config();
|
|
|
14679
15141
|
|
|
14680
15142
|
// src/providers/cli-provider-instance.ts
|
|
14681
15143
|
var os12 = __toESM(require("os"));
|
|
14682
|
-
var
|
|
15144
|
+
var path16 = __toESM(require("path"));
|
|
14683
15145
|
var crypto3 = __toESM(require("crypto"));
|
|
14684
15146
|
var fs6 = __toESM(require("fs"));
|
|
14685
15147
|
var import_node_module = require("module");
|
|
@@ -14738,7 +15200,7 @@ function buildIncrementalHistoryAppendMessages(previousMessages, currentMessages
|
|
|
14738
15200
|
var CachedDatabaseSync = null;
|
|
14739
15201
|
function getDatabaseSync() {
|
|
14740
15202
|
if (CachedDatabaseSync) return CachedDatabaseSync;
|
|
14741
|
-
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(
|
|
15203
|
+
const requireFn = typeof require === "function" ? require : (0, import_node_module.createRequire)(path16.join(process.cwd(), "__adhdev_sqlite_loader__.js"));
|
|
14742
15204
|
const sqliteModule = requireFn(`node:${"sqlite"}`);
|
|
14743
15205
|
CachedDatabaseSync = sqliteModule.DatabaseSync;
|
|
14744
15206
|
if (!CachedDatabaseSync) {
|
|
@@ -14791,7 +15253,7 @@ var CliProviderInstance = class {
|
|
|
14791
15253
|
this.providerSessionId = options?.providerSessionId;
|
|
14792
15254
|
this.launchMode = options?.launchMode || "new";
|
|
14793
15255
|
this.onProviderSessionResolved = options?.onProviderSessionResolved;
|
|
14794
|
-
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, transportFactory);
|
|
15256
|
+
this.adapter = new ProviderCliAdapter(provider, workingDir, cliArgs, options?.extraEnv || {}, transportFactory);
|
|
14795
15257
|
this.monitor = new StatusMonitor();
|
|
14796
15258
|
this.historyWriter = new ChatHistoryWriter();
|
|
14797
15259
|
}
|
|
@@ -15268,7 +15730,19 @@ var CliProviderInstance = class {
|
|
|
15268
15730
|
}
|
|
15269
15731
|
}
|
|
15270
15732
|
pushEvent(event) {
|
|
15271
|
-
|
|
15733
|
+
const enrichedEvent = {
|
|
15734
|
+
...event,
|
|
15735
|
+
instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : this.instanceId,
|
|
15736
|
+
targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : this.instanceId,
|
|
15737
|
+
providerType: typeof event.providerType === "string" && event.providerType.trim() ? event.providerType : this.type,
|
|
15738
|
+
workspaceName: typeof event.workspaceName === "string" && event.workspaceName.trim() ? event.workspaceName : this.workingDir,
|
|
15739
|
+
providerSessionId: typeof event.providerSessionId === "string" && event.providerSessionId.trim() ? event.providerSessionId : this.providerSessionId
|
|
15740
|
+
};
|
|
15741
|
+
if (this.context?.emitProviderEvent) {
|
|
15742
|
+
this.context.emitProviderEvent(enrichedEvent);
|
|
15743
|
+
return;
|
|
15744
|
+
}
|
|
15745
|
+
this.events.push(enrichedEvent);
|
|
15272
15746
|
}
|
|
15273
15747
|
flushEvents() {
|
|
15274
15748
|
const events = [...this.events];
|
|
@@ -15475,12 +15949,59 @@ ${effect.notification.body || ""}`.trim();
|
|
|
15475
15949
|
);
|
|
15476
15950
|
}
|
|
15477
15951
|
}
|
|
15952
|
+
mergeRuntimeChatMessages(parsedMessages) {
|
|
15953
|
+
return this.mergeConversationMessages(parsedMessages);
|
|
15954
|
+
}
|
|
15478
15955
|
mergeConversationMessages(parsedMessages) {
|
|
15479
15956
|
if (this.runtimeMessages.length === 0) return normalizeChatMessages(parsedMessages);
|
|
15480
|
-
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15957
|
+
const parsedEntries = parsedMessages.map((message, index) => ({
|
|
15958
|
+
message,
|
|
15959
|
+
index,
|
|
15960
|
+
source: "parsed"
|
|
15961
|
+
}));
|
|
15962
|
+
const runtimeEntries = this.runtimeMessages.map((entry, index) => ({
|
|
15963
|
+
message: entry.message,
|
|
15964
|
+
index: parsedMessages.length + index,
|
|
15965
|
+
source: "runtime",
|
|
15966
|
+
runtimeKey: entry.key
|
|
15967
|
+
}));
|
|
15968
|
+
const getTime = (message) => {
|
|
15969
|
+
const value = typeof message.receivedAt === "number" ? message.receivedAt : typeof message.timestamp === "number" ? message.timestamp : 0;
|
|
15970
|
+
return Number.isFinite(value) && value > 0 ? value : 0;
|
|
15971
|
+
};
|
|
15972
|
+
const getRole = (message) => typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
15973
|
+
const isRuntimeOverlay = (entry) => {
|
|
15974
|
+
if (entry.source !== "runtime") return false;
|
|
15975
|
+
const key = typeof entry.runtimeKey === "string" ? entry.runtimeKey.trim().toLowerCase() : "";
|
|
15976
|
+
if (key.startsWith("auto_approval:")) return true;
|
|
15977
|
+
return !isUserFacingChatMessage(entry.message);
|
|
15978
|
+
};
|
|
15979
|
+
const shouldKeepParsedBeforeUntimedRuntime = (message) => {
|
|
15980
|
+
const role = getRole(message);
|
|
15981
|
+
return role === "user" || role === "human";
|
|
15982
|
+
};
|
|
15983
|
+
const shouldKeepParsedAfterUntimedRuntime = (message) => {
|
|
15984
|
+
const role = getRole(message);
|
|
15985
|
+
if (role !== "assistant") return false;
|
|
15986
|
+
const kind = resolveChatMessageKind(message);
|
|
15987
|
+
return kind === "standard" || kind === "terminal";
|
|
15988
|
+
};
|
|
15989
|
+
return normalizeChatMessages([...parsedEntries, ...runtimeEntries].sort((a, b) => {
|
|
15990
|
+
const aTime = getTime(a.message);
|
|
15991
|
+
const bTime = getTime(b.message);
|
|
15992
|
+
if (aTime && bTime && aTime !== bTime) return aTime - bTime;
|
|
15993
|
+
if (a.source !== b.source && aTime !== bTime) {
|
|
15994
|
+
const parsedEntry = a.source === "parsed" ? a : b.source === "parsed" ? b : null;
|
|
15995
|
+
const runtimeEntry = a.source === "runtime" ? a : b.source === "runtime" ? b : null;
|
|
15996
|
+
if (parsedEntry && runtimeEntry && isRuntimeOverlay(runtimeEntry) && getTime(parsedEntry.message) === 0 && getTime(runtimeEntry.message) > 0) {
|
|
15997
|
+
if (shouldKeepParsedBeforeUntimedRuntime(parsedEntry.message)) {
|
|
15998
|
+
return a.source === "parsed" ? -1 : 1;
|
|
15999
|
+
}
|
|
16000
|
+
if (shouldKeepParsedAfterUntimedRuntime(parsedEntry.message)) {
|
|
16001
|
+
return a.source === "parsed" ? 1 : -1;
|
|
16002
|
+
}
|
|
16003
|
+
}
|
|
16004
|
+
}
|
|
15484
16005
|
return a.index - b.index;
|
|
15485
16006
|
}).map((entry) => entry.message));
|
|
15486
16007
|
}
|
|
@@ -16804,11 +17325,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
|
|
|
16804
17325
|
// src/commands/cli-manager.ts
|
|
16805
17326
|
function isExplicitCommand(command) {
|
|
16806
17327
|
const trimmed = command.trim();
|
|
16807
|
-
return
|
|
17328
|
+
return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
16808
17329
|
}
|
|
16809
17330
|
function expandExecutable(command) {
|
|
16810
17331
|
const trimmed = command.trim();
|
|
16811
|
-
return trimmed.startsWith("~") ?
|
|
17332
|
+
return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
|
|
16812
17333
|
}
|
|
16813
17334
|
function commandExists(command) {
|
|
16814
17335
|
const trimmed = command.trim();
|
|
@@ -16832,6 +17353,35 @@ function colorize(color, text) {
|
|
|
16832
17353
|
const fn = chalkApi?.[color];
|
|
16833
17354
|
return typeof fn === "function" ? fn(text) : text;
|
|
16834
17355
|
}
|
|
17356
|
+
var COORDINATOR_DELEGATED_ENV_UNSETS = {
|
|
17357
|
+
ADHDEV_INLINE_MESH: "",
|
|
17358
|
+
ADHDEV_MCP_TRANSPORT: "",
|
|
17359
|
+
ADHDEV_MESH_ID: "",
|
|
17360
|
+
HERMES_EPHEMERAL_SYSTEM_PROMPT: ""
|
|
17361
|
+
};
|
|
17362
|
+
function hasCliArg(args, flag) {
|
|
17363
|
+
return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
|
|
17364
|
+
}
|
|
17365
|
+
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
17366
|
+
const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
17367
|
+
(0, import_fs6.mkdirSync)(baseDir, { recursive: true });
|
|
17368
|
+
const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
|
|
17369
|
+
const filePath = path17.join(baseDir, `${workspaceHash}.json`);
|
|
17370
|
+
(0, import_fs6.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
17371
|
+
return filePath;
|
|
17372
|
+
}
|
|
17373
|
+
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
17374
|
+
const cliType = String(input.cliType || "").trim();
|
|
17375
|
+
const cliArgs = Array.isArray(input.cliArgs) ? [...input.cliArgs] : [];
|
|
17376
|
+
const env = { ...input.env || {}, ...COORDINATOR_DELEGATED_ENV_UNSETS };
|
|
17377
|
+
if (cliType === "hermes-cli" && !hasCliArg(cliArgs, "--ignore-user-config")) {
|
|
17378
|
+
cliArgs.unshift("--ignore-user-config");
|
|
17379
|
+
}
|
|
17380
|
+
if (cliType === "claude-cli" && !hasCliArg(cliArgs, "--mcp-config")) {
|
|
17381
|
+
cliArgs.unshift("--mcp-config", ensureEmptyDelegatedMcpConfig(input.workspace));
|
|
17382
|
+
}
|
|
17383
|
+
return { cliArgs, env };
|
|
17384
|
+
}
|
|
16835
17385
|
function isUuid(value) {
|
|
16836
17386
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
16837
17387
|
}
|
|
@@ -17002,7 +17552,7 @@ var DaemonCliManager = class {
|
|
|
17002
17552
|
attachExisting
|
|
17003
17553
|
}) || void 0;
|
|
17004
17554
|
}
|
|
17005
|
-
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false) {
|
|
17555
|
+
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
|
|
17006
17556
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
17007
17557
|
const provider = this.providerLoader.getMeta(normalizedType);
|
|
17008
17558
|
if (provider && provider.category === "cli" && provider.patterns && provider.spawn) {
|
|
@@ -17016,7 +17566,7 @@ var DaemonCliManager = class {
|
|
|
17016
17566
|
providerSessionId,
|
|
17017
17567
|
attachExisting
|
|
17018
17568
|
);
|
|
17019
|
-
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, transportFactory);
|
|
17569
|
+
return new ProviderCliAdapter(resolvedProvider, workingDir, cliArgs, extraEnv || {}, transportFactory);
|
|
17020
17570
|
}
|
|
17021
17571
|
throw new Error(`No CLI provider found for '${cliType}'. Create a provider.js in providers/cli/${cliType}/`);
|
|
17022
17572
|
}
|
|
@@ -17089,7 +17639,7 @@ var DaemonCliManager = class {
|
|
|
17089
17639
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
17090
17640
|
const trimmed = (workingDir || "").trim();
|
|
17091
17641
|
if (!trimmed) throw new Error("working directory required");
|
|
17092
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) :
|
|
17642
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
|
|
17093
17643
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
17094
17644
|
const rawProvider = this.providerLoader.getByAlias(cliType);
|
|
17095
17645
|
const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
|
|
@@ -17219,6 +17769,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17219
17769
|
{
|
|
17220
17770
|
providerSessionId: sessionBinding.providerSessionId,
|
|
17221
17771
|
launchMode: sessionBinding.launchMode,
|
|
17772
|
+
extraEnv: options?.extraEnv,
|
|
17222
17773
|
onProviderSessionResolved: ({ providerSessionId, providerName, providerType, workspace }) => {
|
|
17223
17774
|
this.persistRecentActivity({
|
|
17224
17775
|
kind: "cli",
|
|
@@ -17239,7 +17790,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17239
17790
|
resolvedCliArgs,
|
|
17240
17791
|
key,
|
|
17241
17792
|
sessionBinding.providerSessionId,
|
|
17242
|
-
false
|
|
17793
|
+
false,
|
|
17794
|
+
options?.extraEnv
|
|
17243
17795
|
);
|
|
17244
17796
|
try {
|
|
17245
17797
|
await adapter.spawn();
|
|
@@ -17463,12 +18015,23 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17463
18015
|
const dir = resolved.path;
|
|
17464
18016
|
const launchSource = resolved.source;
|
|
17465
18017
|
if (!cliType) throw new Error("cliType required");
|
|
18018
|
+
const settingsOverride = args?.settings && typeof args.settings === "object" ? args.settings : void 0;
|
|
18019
|
+
const delegatedLaunch = settingsOverride?.launchedByCoordinator === true ? buildCoordinatorDelegatedCliLaunchOptions({
|
|
18020
|
+
cliType,
|
|
18021
|
+
workspace: dir,
|
|
18022
|
+
cliArgs: args?.cliArgs,
|
|
18023
|
+
env: args?.env
|
|
18024
|
+
}) : null;
|
|
17466
18025
|
const started = await this.startSession(
|
|
17467
18026
|
cliType,
|
|
17468
18027
|
dir,
|
|
17469
|
-
args?.cliArgs,
|
|
18028
|
+
delegatedLaunch ? delegatedLaunch.cliArgs : args?.cliArgs,
|
|
17470
18029
|
args?.initialModel,
|
|
17471
|
-
{
|
|
18030
|
+
{
|
|
18031
|
+
resumeSessionId: args?.resumeSessionId,
|
|
18032
|
+
settingsOverride,
|
|
18033
|
+
extraEnv: delegatedLaunch ? delegatedLaunch.env : args?.env
|
|
18034
|
+
}
|
|
17472
18035
|
);
|
|
17473
18036
|
return {
|
|
17474
18037
|
success: true,
|
|
@@ -17590,11 +18153,11 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
17590
18153
|
var import_child_process7 = require("child_process");
|
|
17591
18154
|
var net = __toESM(require("net"));
|
|
17592
18155
|
var os15 = __toESM(require("os"));
|
|
17593
|
-
var
|
|
18156
|
+
var path19 = __toESM(require("path"));
|
|
17594
18157
|
|
|
17595
18158
|
// src/providers/provider-loader.ts
|
|
17596
18159
|
var fs7 = __toESM(require("fs"));
|
|
17597
|
-
var
|
|
18160
|
+
var path18 = __toESM(require("path"));
|
|
17598
18161
|
var os14 = __toESM(require("os"));
|
|
17599
18162
|
var chokidar = __toESM(require("chokidar"));
|
|
17600
18163
|
init_logger();
|
|
@@ -17918,7 +18481,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17918
18481
|
try {
|
|
17919
18482
|
if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
|
|
17920
18483
|
return ["ide", "extension", "cli", "acp"].some(
|
|
17921
|
-
(category) => fs7.existsSync(
|
|
18484
|
+
(category) => fs7.existsSync(path18.join(candidate, category))
|
|
17922
18485
|
);
|
|
17923
18486
|
} catch {
|
|
17924
18487
|
return false;
|
|
@@ -17926,20 +18489,20 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17926
18489
|
}
|
|
17927
18490
|
static hasProviderRootMarker(candidate) {
|
|
17928
18491
|
try {
|
|
17929
|
-
return fs7.existsSync(
|
|
18492
|
+
return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
|
|
17930
18493
|
} catch {
|
|
17931
18494
|
return false;
|
|
17932
18495
|
}
|
|
17933
18496
|
}
|
|
17934
18497
|
detectDefaultUserDir() {
|
|
17935
|
-
const fallback =
|
|
18498
|
+
const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17936
18499
|
const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
|
|
17937
18500
|
const visited = /* @__PURE__ */ new Set();
|
|
17938
18501
|
for (const start of this.probeStarts) {
|
|
17939
|
-
let current =
|
|
18502
|
+
let current = path18.resolve(start);
|
|
17940
18503
|
while (!visited.has(current)) {
|
|
17941
18504
|
visited.add(current);
|
|
17942
|
-
const siblingCandidate =
|
|
18505
|
+
const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
|
|
17943
18506
|
if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
|
|
17944
18507
|
const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
|
|
17945
18508
|
if (envOptIn || hasMarker) {
|
|
@@ -17961,7 +18524,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17961
18524
|
return { path: siblingCandidate, source };
|
|
17962
18525
|
}
|
|
17963
18526
|
}
|
|
17964
|
-
const parent =
|
|
18527
|
+
const parent = path18.dirname(current);
|
|
17965
18528
|
if (parent === current) break;
|
|
17966
18529
|
current = parent;
|
|
17967
18530
|
}
|
|
@@ -17971,11 +18534,11 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
17971
18534
|
constructor(options) {
|
|
17972
18535
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
17973
18536
|
this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
|
|
17974
|
-
this.defaultProvidersDir =
|
|
18537
|
+
this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
|
|
17975
18538
|
const detected = this.detectDefaultUserDir();
|
|
17976
18539
|
this.userDir = detected.path;
|
|
17977
18540
|
this.userDirSource = detected.source;
|
|
17978
|
-
this.upstreamDir =
|
|
18541
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
17979
18542
|
this.disableUpstream = false;
|
|
17980
18543
|
this.applySourceConfig({
|
|
17981
18544
|
userDir: options?.userDir,
|
|
@@ -18034,7 +18597,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18034
18597
|
this.userDir = detected.path;
|
|
18035
18598
|
this.userDirSource = detected.source;
|
|
18036
18599
|
}
|
|
18037
|
-
this.upstreamDir =
|
|
18600
|
+
this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
|
|
18038
18601
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
18039
18602
|
if (this.explicitProviderDir) {
|
|
18040
18603
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -18048,7 +18611,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18048
18611
|
* Canonical provider directory shape for a given root.
|
|
18049
18612
|
*/
|
|
18050
18613
|
getProviderDir(root, category, type) {
|
|
18051
|
-
return
|
|
18614
|
+
return path18.join(root, category, type);
|
|
18052
18615
|
}
|
|
18053
18616
|
/**
|
|
18054
18617
|
* Canonical user override directory for a provider.
|
|
@@ -18075,7 +18638,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18075
18638
|
resolveProviderFile(type, ...segments) {
|
|
18076
18639
|
const dir = this.findProviderDirInternal(type);
|
|
18077
18640
|
if (!dir) return null;
|
|
18078
|
-
return
|
|
18641
|
+
return path18.join(dir, ...segments);
|
|
18079
18642
|
}
|
|
18080
18643
|
/**
|
|
18081
18644
|
* Load all providers (3-tier priority)
|
|
@@ -18114,7 +18677,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18114
18677
|
if (!fs7.existsSync(this.upstreamDir)) return false;
|
|
18115
18678
|
try {
|
|
18116
18679
|
return fs7.readdirSync(this.upstreamDir).some(
|
|
18117
|
-
(d) => fs7.statSync(
|
|
18680
|
+
(d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
|
|
18118
18681
|
);
|
|
18119
18682
|
} catch {
|
|
18120
18683
|
return false;
|
|
@@ -18611,8 +19174,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18611
19174
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
18612
19175
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
18613
19176
|
if (providerDir) {
|
|
18614
|
-
const fullDir =
|
|
18615
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
19177
|
+
const fullDir = path18.join(providerDir, entry.scriptDir);
|
|
19178
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18616
19179
|
}
|
|
18617
19180
|
matched = true;
|
|
18618
19181
|
}
|
|
@@ -18627,8 +19190,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18627
19190
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18628
19191
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
18629
19192
|
if (providerDir) {
|
|
18630
|
-
const fullDir =
|
|
18631
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
19193
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
19194
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18632
19195
|
}
|
|
18633
19196
|
}
|
|
18634
19197
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -18645,8 +19208,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18645
19208
|
resolved._resolvedScriptDir = dirOverride;
|
|
18646
19209
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
18647
19210
|
if (providerDir) {
|
|
18648
|
-
const fullDir =
|
|
18649
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
19211
|
+
const fullDir = path18.join(providerDir, dirOverride);
|
|
19212
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18650
19213
|
}
|
|
18651
19214
|
}
|
|
18652
19215
|
} else if (override.scripts) {
|
|
@@ -18662,8 +19225,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18662
19225
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
18663
19226
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
18664
19227
|
if (providerDir) {
|
|
18665
|
-
const fullDir =
|
|
18666
|
-
resolved._resolvedScriptsPath = fs7.existsSync(
|
|
19228
|
+
const fullDir = path18.join(providerDir, base.defaultScriptDir);
|
|
19229
|
+
resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
|
|
18667
19230
|
}
|
|
18668
19231
|
}
|
|
18669
19232
|
}
|
|
@@ -18695,14 +19258,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18695
19258
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
18696
19259
|
return null;
|
|
18697
19260
|
}
|
|
18698
|
-
const dir =
|
|
19261
|
+
const dir = path18.join(providerDir, scriptDir);
|
|
18699
19262
|
if (!fs7.existsSync(dir)) {
|
|
18700
19263
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
18701
19264
|
return null;
|
|
18702
19265
|
}
|
|
18703
19266
|
const cached = this.scriptsCache.get(dir);
|
|
18704
19267
|
if (cached) return cached;
|
|
18705
|
-
const scriptsJs =
|
|
19268
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
18706
19269
|
if (fs7.existsSync(scriptsJs)) {
|
|
18707
19270
|
try {
|
|
18708
19271
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -18744,7 +19307,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18744
19307
|
return;
|
|
18745
19308
|
}
|
|
18746
19309
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
18747
|
-
this.log(`File changed: ${
|
|
19310
|
+
this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
|
|
18748
19311
|
this.reload();
|
|
18749
19312
|
}
|
|
18750
19313
|
};
|
|
@@ -18799,7 +19362,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18799
19362
|
}
|
|
18800
19363
|
const https = require("https");
|
|
18801
19364
|
const { execSync: execSync7 } = require("child_process");
|
|
18802
|
-
const metaPath =
|
|
19365
|
+
const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
18803
19366
|
let prevEtag = "";
|
|
18804
19367
|
let prevTimestamp = 0;
|
|
18805
19368
|
try {
|
|
@@ -18859,17 +19422,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18859
19422
|
return { updated: false };
|
|
18860
19423
|
}
|
|
18861
19424
|
this.log("Downloading latest providers from GitHub...");
|
|
18862
|
-
const tmpTar =
|
|
18863
|
-
const tmpExtract =
|
|
19425
|
+
const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
19426
|
+
const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
18864
19427
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
18865
19428
|
fs7.mkdirSync(tmpExtract, { recursive: true });
|
|
18866
19429
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
18867
19430
|
const extracted = fs7.readdirSync(tmpExtract);
|
|
18868
19431
|
const rootDir = extracted.find(
|
|
18869
|
-
(d) => fs7.statSync(
|
|
19432
|
+
(d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
18870
19433
|
);
|
|
18871
19434
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
18872
|
-
const sourceDir =
|
|
19435
|
+
const sourceDir = path18.join(tmpExtract, rootDir);
|
|
18873
19436
|
const backupDir = this.upstreamDir + ".bak";
|
|
18874
19437
|
if (fs7.existsSync(this.upstreamDir)) {
|
|
18875
19438
|
if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -18944,8 +19507,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18944
19507
|
copyDirRecursive(src, dest) {
|
|
18945
19508
|
fs7.mkdirSync(dest, { recursive: true });
|
|
18946
19509
|
for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
|
|
18947
|
-
const srcPath =
|
|
18948
|
-
const destPath =
|
|
19510
|
+
const srcPath = path18.join(src, entry.name);
|
|
19511
|
+
const destPath = path18.join(dest, entry.name);
|
|
18949
19512
|
if (entry.isDirectory()) {
|
|
18950
19513
|
this.copyDirRecursive(srcPath, destPath);
|
|
18951
19514
|
} else {
|
|
@@ -18956,7 +19519,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18956
19519
|
/** .meta.json save */
|
|
18957
19520
|
writeMeta(metaPath, etag, timestamp) {
|
|
18958
19521
|
try {
|
|
18959
|
-
fs7.mkdirSync(
|
|
19522
|
+
fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
|
|
18960
19523
|
fs7.writeFileSync(metaPath, JSON.stringify({
|
|
18961
19524
|
etag,
|
|
18962
19525
|
timestamp,
|
|
@@ -18973,7 +19536,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
18973
19536
|
const scan = (d) => {
|
|
18974
19537
|
try {
|
|
18975
19538
|
for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
|
|
18976
|
-
if (entry.isDirectory()) scan(
|
|
19539
|
+
if (entry.isDirectory()) scan(path18.join(d, entry.name));
|
|
18977
19540
|
else if (entry.name === "provider.json") count++;
|
|
18978
19541
|
}
|
|
18979
19542
|
} catch {
|
|
@@ -19201,17 +19764,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19201
19764
|
for (const root of searchRoots) {
|
|
19202
19765
|
if (!fs7.existsSync(root)) continue;
|
|
19203
19766
|
const candidate = this.getProviderDir(root, cat, type);
|
|
19204
|
-
if (fs7.existsSync(
|
|
19205
|
-
const catDir =
|
|
19767
|
+
if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
|
|
19768
|
+
const catDir = path18.join(root, cat);
|
|
19206
19769
|
if (fs7.existsSync(catDir)) {
|
|
19207
19770
|
try {
|
|
19208
19771
|
for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
|
|
19209
19772
|
if (!entry.isDirectory()) continue;
|
|
19210
|
-
const jsonPath =
|
|
19773
|
+
const jsonPath = path18.join(catDir, entry.name, "provider.json");
|
|
19211
19774
|
if (fs7.existsSync(jsonPath)) {
|
|
19212
19775
|
try {
|
|
19213
19776
|
const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
|
|
19214
|
-
if (data.type === type) return
|
|
19777
|
+
if (data.type === type) return path18.join(catDir, entry.name);
|
|
19215
19778
|
} catch {
|
|
19216
19779
|
}
|
|
19217
19780
|
}
|
|
@@ -19228,7 +19791,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19228
19791
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
19229
19792
|
*/
|
|
19230
19793
|
buildScriptWrappersFromDir(dir) {
|
|
19231
|
-
const scriptsJs =
|
|
19794
|
+
const scriptsJs = path18.join(dir, "scripts.js");
|
|
19232
19795
|
if (fs7.existsSync(scriptsJs)) {
|
|
19233
19796
|
try {
|
|
19234
19797
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -19242,7 +19805,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19242
19805
|
for (const file of fs7.readdirSync(dir)) {
|
|
19243
19806
|
if (!file.endsWith(".js")) continue;
|
|
19244
19807
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
19245
|
-
const filePath =
|
|
19808
|
+
const filePath = path18.join(dir, file);
|
|
19246
19809
|
result[scriptName] = (...args) => {
|
|
19247
19810
|
try {
|
|
19248
19811
|
let content = fs7.readFileSync(filePath, "utf-8");
|
|
@@ -19302,7 +19865,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19302
19865
|
}
|
|
19303
19866
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
19304
19867
|
if (hasJson) {
|
|
19305
|
-
const jsonPath =
|
|
19868
|
+
const jsonPath = path18.join(d, "provider.json");
|
|
19306
19869
|
try {
|
|
19307
19870
|
const raw = fs7.readFileSync(jsonPath, "utf-8");
|
|
19308
19871
|
const mod = JSON.parse(raw);
|
|
@@ -19323,7 +19886,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19323
19886
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
19324
19887
|
} else {
|
|
19325
19888
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
19326
|
-
const scriptsPath =
|
|
19889
|
+
const scriptsPath = path18.join(d, "scripts.js");
|
|
19327
19890
|
if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
|
|
19328
19891
|
try {
|
|
19329
19892
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -19349,7 +19912,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
19349
19912
|
if (!entry.isDirectory()) continue;
|
|
19350
19913
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
19351
19914
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
19352
|
-
scan(
|
|
19915
|
+
scan(path18.join(d, entry.name));
|
|
19353
19916
|
}
|
|
19354
19917
|
}
|
|
19355
19918
|
};
|
|
@@ -19674,8 +20237,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
19674
20237
|
const appNameMap = getMacAppIdentifiers();
|
|
19675
20238
|
const appName = appNameMap[ideId];
|
|
19676
20239
|
if (appName) {
|
|
19677
|
-
const storagePath =
|
|
19678
|
-
process.env.APPDATA ||
|
|
20240
|
+
const storagePath = path19.join(
|
|
20241
|
+
process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
|
|
19679
20242
|
appName,
|
|
19680
20243
|
"storage.json"
|
|
19681
20244
|
);
|
|
@@ -19864,9 +20427,9 @@ init_logger();
|
|
|
19864
20427
|
|
|
19865
20428
|
// src/logging/command-log.ts
|
|
19866
20429
|
var fs8 = __toESM(require("fs"));
|
|
19867
|
-
var
|
|
20430
|
+
var path20 = __toESM(require("path"));
|
|
19868
20431
|
var os16 = __toESM(require("os"));
|
|
19869
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
20432
|
+
var LOG_DIR2 = process.platform === "win32" ? path20.join(process.env.LOCALAPPDATA || process.env.APPDATA || path20.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path20.join(os16.homedir(), "Library", "Logs", "adhdev") : path20.join(os16.homedir(), ".local", "share", "adhdev", "logs");
|
|
19870
20433
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
19871
20434
|
var MAX_DAYS = 7;
|
|
19872
20435
|
try {
|
|
@@ -19904,13 +20467,13 @@ function getDateStr2() {
|
|
|
19904
20467
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
19905
20468
|
}
|
|
19906
20469
|
var currentDate2 = getDateStr2();
|
|
19907
|
-
var currentFile =
|
|
20470
|
+
var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19908
20471
|
var writeCount2 = 0;
|
|
19909
20472
|
function checkRotation() {
|
|
19910
20473
|
const today = getDateStr2();
|
|
19911
20474
|
if (today !== currentDate2) {
|
|
19912
20475
|
currentDate2 = today;
|
|
19913
|
-
currentFile =
|
|
20476
|
+
currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
19914
20477
|
cleanOldFiles();
|
|
19915
20478
|
}
|
|
19916
20479
|
}
|
|
@@ -19924,7 +20487,7 @@ function cleanOldFiles() {
|
|
|
19924
20487
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
19925
20488
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
19926
20489
|
try {
|
|
19927
|
-
fs8.unlinkSync(
|
|
20490
|
+
fs8.unlinkSync(path20.join(LOG_DIR2, file));
|
|
19928
20491
|
} catch {
|
|
19929
20492
|
}
|
|
19930
20493
|
}
|
|
@@ -20007,14 +20570,66 @@ function getRecentCommands(count = 50) {
|
|
|
20007
20570
|
cleanOldFiles();
|
|
20008
20571
|
|
|
20009
20572
|
// src/commands/router.ts
|
|
20573
|
+
var yaml = __toESM(require("js-yaml"));
|
|
20010
20574
|
init_logger();
|
|
20011
20575
|
|
|
20012
20576
|
// src/commands/mesh-coordinator.ts
|
|
20013
|
-
var
|
|
20577
|
+
var import_node_child_process3 = require("child_process");
|
|
20578
|
+
var import_node_fs3 = require("fs");
|
|
20014
20579
|
var import_node_module2 = require("module");
|
|
20580
|
+
var os17 = __toESM(require("os"));
|
|
20015
20581
|
var import_node_path = require("path");
|
|
20016
20582
|
var DEFAULT_SERVER_NAME = "adhdev-mesh";
|
|
20017
20583
|
var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
20584
|
+
var HERMES_CLI_TYPE = "hermes-cli";
|
|
20585
|
+
var HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
|
|
20586
|
+
function isHermesProvider(provider, cliType) {
|
|
20587
|
+
const type = cliType?.trim() || provider?.type?.trim() || "";
|
|
20588
|
+
return type === HERMES_CLI_TYPE;
|
|
20589
|
+
}
|
|
20590
|
+
function resolveHermesMeshCoordinatorSetup(options) {
|
|
20591
|
+
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
20592
|
+
meshId: options.meshId,
|
|
20593
|
+
nodeExecutable: options.nodeExecutable,
|
|
20594
|
+
adhdevMcpEntryPath: options.adhdevMcpEntryPath
|
|
20595
|
+
});
|
|
20596
|
+
if (!mcpServer) {
|
|
20597
|
+
return {
|
|
20598
|
+
kind: "unsupported",
|
|
20599
|
+
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
20600
|
+
};
|
|
20601
|
+
}
|
|
20602
|
+
const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
|
|
20603
|
+
if (!configPath.trim()) {
|
|
20604
|
+
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
|
|
20605
|
+
}
|
|
20606
|
+
return {
|
|
20607
|
+
kind: "auto_import",
|
|
20608
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20609
|
+
configPath,
|
|
20610
|
+
configFormat: "hermes_config_yaml",
|
|
20611
|
+
mcpServer
|
|
20612
|
+
};
|
|
20613
|
+
}
|
|
20614
|
+
function createHermesManualMeshCoordinatorSetup(meshId, workspace) {
|
|
20615
|
+
return {
|
|
20616
|
+
kind: "manual",
|
|
20617
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20618
|
+
configFormat: "hermes_config_yaml",
|
|
20619
|
+
configPathCommand: HERMES_MCP_CONFIG_PATH,
|
|
20620
|
+
requiresRestart: true,
|
|
20621
|
+
instructions: "Hermes CLI does not auto-import repo-local .mcp.json. Add this MCP server to Hermes config under mcp_servers, then start a fresh Hermes session.",
|
|
20622
|
+
template: renderMeshCoordinatorTemplate(
|
|
20623
|
+
"mcp_servers:\n {{serverName}}:\n command: {{adhdevMcpCommand}}\n args:\n - --repo-mesh\n - {{meshId}}\n enabled: true\n",
|
|
20624
|
+
{
|
|
20625
|
+
meshId,
|
|
20626
|
+
workspace,
|
|
20627
|
+
serverName: DEFAULT_SERVER_NAME,
|
|
20628
|
+
adhdevMcpCommand: DEFAULT_ADHDEV_MCP_COMMAND
|
|
20629
|
+
}
|
|
20630
|
+
)
|
|
20631
|
+
};
|
|
20632
|
+
}
|
|
20018
20633
|
function resolveMeshCoordinatorSetup(options) {
|
|
20019
20634
|
const { provider, meshId, workspace } = options;
|
|
20020
20635
|
const config = provider?.meshCoordinator;
|
|
@@ -20024,6 +20639,9 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20024
20639
|
reason: config?.reason || "Provider does not declare Repo Mesh coordinator support"
|
|
20025
20640
|
};
|
|
20026
20641
|
}
|
|
20642
|
+
if (isHermesProvider(provider, options.cliType)) {
|
|
20643
|
+
return resolveHermesMeshCoordinatorSetup(options);
|
|
20644
|
+
}
|
|
20027
20645
|
const mcpConfig = config.mcpConfig;
|
|
20028
20646
|
if (!mcpConfig || mcpConfig.mode === "none") {
|
|
20029
20647
|
return {
|
|
@@ -20033,8 +20651,8 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20033
20651
|
}
|
|
20034
20652
|
const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
|
|
20035
20653
|
if (mcpConfig.mode === "auto_import") {
|
|
20036
|
-
const
|
|
20037
|
-
if (!
|
|
20654
|
+
const path27 = mcpConfig.path?.trim();
|
|
20655
|
+
if (!path27) {
|
|
20038
20656
|
return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
|
|
20039
20657
|
}
|
|
20040
20658
|
const mcpServer = resolveAdhdevMcpServerLaunch({
|
|
@@ -20045,13 +20663,13 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20045
20663
|
if (!mcpServer) {
|
|
20046
20664
|
return {
|
|
20047
20665
|
kind: "unsupported",
|
|
20048
|
-
reason: "Could not resolve the ADHDev MCP server entrypoint
|
|
20666
|
+
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
20049
20667
|
};
|
|
20050
20668
|
}
|
|
20051
20669
|
return {
|
|
20052
20670
|
kind: "auto_import",
|
|
20053
20671
|
serverName,
|
|
20054
|
-
configPath: (
|
|
20672
|
+
configPath: resolveMcpConfigPath(path27, workspace),
|
|
20055
20673
|
configFormat: mcpConfig.format,
|
|
20056
20674
|
mcpServer
|
|
20057
20675
|
};
|
|
@@ -20085,14 +20703,85 @@ function resolveMeshCoordinatorSetup(options) {
|
|
|
20085
20703
|
function renderMeshCoordinatorTemplate(template, values) {
|
|
20086
20704
|
return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
|
|
20087
20705
|
}
|
|
20706
|
+
function resolveMcpConfigPath(configPath, workspace) {
|
|
20707
|
+
const trimmed = configPath.trim();
|
|
20708
|
+
if (trimmed === "~") return os17.homedir();
|
|
20709
|
+
if (trimmed.startsWith("~/")) return (0, import_node_path.join)(os17.homedir(), trimmed.slice(2));
|
|
20710
|
+
if ((0, import_node_path.isAbsolute)(trimmed)) return trimmed;
|
|
20711
|
+
return (0, import_node_path.join)(workspace, trimmed);
|
|
20712
|
+
}
|
|
20088
20713
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
20089
20714
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
20090
20715
|
if (!entryPath) return null;
|
|
20716
|
+
const nodeExecutable = resolveMcpNodeExecutable(options.nodeExecutable);
|
|
20717
|
+
if (!nodeExecutable) return null;
|
|
20091
20718
|
return {
|
|
20092
|
-
command:
|
|
20719
|
+
command: nodeExecutable,
|
|
20093
20720
|
args: [entryPath, "--mode", "ipc", "--repo-mesh", options.meshId]
|
|
20094
20721
|
};
|
|
20095
20722
|
}
|
|
20723
|
+
function resolveMcpNodeExecutable(explicitExecutable) {
|
|
20724
|
+
const explicit = explicitExecutable?.trim();
|
|
20725
|
+
if (explicit) return explicit;
|
|
20726
|
+
const candidates = [];
|
|
20727
|
+
const addCandidate = (candidate) => {
|
|
20728
|
+
const trimmed = candidate?.trim();
|
|
20729
|
+
if (!trimmed) return;
|
|
20730
|
+
const normalized = normalizeExistingPath(trimmed) || trimmed;
|
|
20731
|
+
if (!candidates.includes(normalized)) candidates.push(normalized);
|
|
20732
|
+
};
|
|
20733
|
+
addCandidate(process.env.ADHDEV_MCP_NODE_EXECUTABLE);
|
|
20734
|
+
addCandidate(process.env.ADHDEV_NODE_EXECUTABLE);
|
|
20735
|
+
addCandidate(process.env.npm_node_execpath);
|
|
20736
|
+
addNodeCandidatesFromPath(process.env.PATH, addCandidate);
|
|
20737
|
+
addNodeCandidatesFromNvm(os17.homedir(), addCandidate);
|
|
20738
|
+
addCandidate("/opt/homebrew/bin/node");
|
|
20739
|
+
addCandidate("/usr/local/bin/node");
|
|
20740
|
+
addCandidate("/usr/bin/node");
|
|
20741
|
+
addCandidate(process.execPath);
|
|
20742
|
+
for (const candidate of candidates) {
|
|
20743
|
+
if (nodeRuntimeSupportsWebSocket(candidate)) return candidate;
|
|
20744
|
+
}
|
|
20745
|
+
return null;
|
|
20746
|
+
}
|
|
20747
|
+
function addNodeCandidatesFromPath(pathValue, addCandidate) {
|
|
20748
|
+
for (const entry of (pathValue || "").split(":")) {
|
|
20749
|
+
const dir = entry.trim();
|
|
20750
|
+
if (!dir) continue;
|
|
20751
|
+
addCandidate((0, import_node_path.join)(dir, "node"));
|
|
20752
|
+
}
|
|
20753
|
+
}
|
|
20754
|
+
function addNodeCandidatesFromNvm(homeDir, addCandidate) {
|
|
20755
|
+
const versionsDir = (0, import_node_path.join)(homeDir, ".nvm", "versions", "node");
|
|
20756
|
+
try {
|
|
20757
|
+
const versionDirs = (0, import_node_fs3.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
|
|
20758
|
+
for (const versionDir of versionDirs) {
|
|
20759
|
+
addCandidate((0, import_node_path.join)(versionsDir, versionDir, "bin", "node"));
|
|
20760
|
+
}
|
|
20761
|
+
} catch {
|
|
20762
|
+
}
|
|
20763
|
+
}
|
|
20764
|
+
function compareNodeVersionNamesDescending(a, b) {
|
|
20765
|
+
const parse = (value) => value.replace(/^v/, "").split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
20766
|
+
const left = parse(a);
|
|
20767
|
+
const right = parse(b);
|
|
20768
|
+
for (let i = 0; i < Math.max(left.length, right.length); i++) {
|
|
20769
|
+
const diff = (right[i] || 0) - (left[i] || 0);
|
|
20770
|
+
if (diff !== 0) return diff;
|
|
20771
|
+
}
|
|
20772
|
+
return b.localeCompare(a);
|
|
20773
|
+
}
|
|
20774
|
+
function nodeRuntimeSupportsWebSocket(nodeExecutable) {
|
|
20775
|
+
try {
|
|
20776
|
+
(0, import_node_child_process3.execFileSync)(nodeExecutable, ["-e", "process.exit(typeof WebSocket === 'function' ? 0 : 42)"], {
|
|
20777
|
+
stdio: "ignore",
|
|
20778
|
+
timeout: 3e3
|
|
20779
|
+
});
|
|
20780
|
+
return true;
|
|
20781
|
+
} catch {
|
|
20782
|
+
return false;
|
|
20783
|
+
}
|
|
20784
|
+
}
|
|
20096
20785
|
function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
20097
20786
|
const explicit = explicitPath?.trim();
|
|
20098
20787
|
if (explicit) return normalizeExistingPath(explicit) || explicit;
|
|
@@ -20128,15 +20817,109 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
20128
20817
|
}
|
|
20129
20818
|
function normalizeExistingPath(filePath) {
|
|
20130
20819
|
try {
|
|
20131
|
-
if (!(0,
|
|
20132
|
-
return
|
|
20820
|
+
if (!(0, import_node_fs3.existsSync)(filePath)) return null;
|
|
20821
|
+
return import_node_fs3.realpathSync.native(filePath);
|
|
20133
20822
|
} catch {
|
|
20134
20823
|
return null;
|
|
20135
20824
|
}
|
|
20136
20825
|
}
|
|
20137
20826
|
|
|
20827
|
+
// src/mesh/mesh-events.ts
|
|
20828
|
+
init_mesh_config();
|
|
20829
|
+
init_logger();
|
|
20830
|
+
function readNonEmptyString(value) {
|
|
20831
|
+
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
20832
|
+
}
|
|
20833
|
+
function formatCompletionMetadata(event) {
|
|
20834
|
+
const parts = [
|
|
20835
|
+
readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
|
|
20836
|
+
readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
|
|
20837
|
+
readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
|
|
20838
|
+
].filter(Boolean);
|
|
20839
|
+
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
20840
|
+
}
|
|
20841
|
+
function buildMeshSystemMessage(args) {
|
|
20842
|
+
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
20843
|
+
if (args.event === "agent:generating_completed") {
|
|
20844
|
+
return `[System] ${args.nodeLabel} has completed its task and is now idle${metadata}. This completion came from the agent status event path; use mesh_read_chat once to review its final progress, but do not poll repeatedly.`;
|
|
20845
|
+
}
|
|
20846
|
+
if (args.event === "agent:waiting_approval") {
|
|
20847
|
+
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
20848
|
+
}
|
|
20849
|
+
return "";
|
|
20850
|
+
}
|
|
20851
|
+
function injectMeshSystemMessage(components, args) {
|
|
20852
|
+
const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
20853
|
+
const instState = inst.getState();
|
|
20854
|
+
if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
|
|
20855
|
+
if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
|
|
20856
|
+
return true;
|
|
20857
|
+
});
|
|
20858
|
+
if (coordinatorInstances.length === 0) return { success: true, forwarded: 0 };
|
|
20859
|
+
const messageText = buildMeshSystemMessage({
|
|
20860
|
+
event: args.event,
|
|
20861
|
+
nodeLabel: args.nodeLabel,
|
|
20862
|
+
metadataEvent: args.metadataEvent
|
|
20863
|
+
});
|
|
20864
|
+
if (!messageText) return { success: false, error: "unsupported mesh event" };
|
|
20865
|
+
for (const coord of coordinatorInstances) {
|
|
20866
|
+
const coordState = coord.getState();
|
|
20867
|
+
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
20868
|
+
coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
|
|
20869
|
+
}
|
|
20870
|
+
return { success: true, forwarded: coordinatorInstances.length };
|
|
20871
|
+
}
|
|
20872
|
+
function handleMeshForwardEvent(components, payload) {
|
|
20873
|
+
const eventName = readNonEmptyString(payload.event);
|
|
20874
|
+
if (eventName !== "agent:generating_completed" && eventName !== "agent:waiting_approval") {
|
|
20875
|
+
return { success: false, error: "unsupported mesh event" };
|
|
20876
|
+
}
|
|
20877
|
+
const meshId = readNonEmptyString(payload.meshId);
|
|
20878
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
20879
|
+
const nodeId = readNonEmptyString(payload.nodeId);
|
|
20880
|
+
const workspace = readNonEmptyString(payload.workspace);
|
|
20881
|
+
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
20882
|
+
return injectMeshSystemMessage(components, {
|
|
20883
|
+
meshId,
|
|
20884
|
+
nodeLabel,
|
|
20885
|
+
event: eventName,
|
|
20886
|
+
metadataEvent: {
|
|
20887
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
20888
|
+
providerType: readNonEmptyString(payload.providerType),
|
|
20889
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
20890
|
+
}
|
|
20891
|
+
});
|
|
20892
|
+
}
|
|
20893
|
+
function setupMeshEventForwarding(components) {
|
|
20894
|
+
components.instanceManager.onEvent((event) => {
|
|
20895
|
+
if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
|
|
20896
|
+
const instanceId = readNonEmptyString(event.instanceId);
|
|
20897
|
+
if (!instanceId) return;
|
|
20898
|
+
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
20899
|
+
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
20900
|
+
const state = sourceInstance.getState();
|
|
20901
|
+
const workspace = readNonEmptyString(state.workspace);
|
|
20902
|
+
if (!workspace) return;
|
|
20903
|
+
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
20904
|
+
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
20905
|
+
const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
20906
|
+
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
20907
|
+
if (!meshId) return;
|
|
20908
|
+
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
20909
|
+
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
20910
|
+
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
20911
|
+
injectMeshSystemMessage(components, {
|
|
20912
|
+
meshId,
|
|
20913
|
+
sourceInstanceId: instanceId,
|
|
20914
|
+
nodeLabel,
|
|
20915
|
+
event: event.event,
|
|
20916
|
+
metadataEvent: event
|
|
20917
|
+
});
|
|
20918
|
+
});
|
|
20919
|
+
}
|
|
20920
|
+
|
|
20138
20921
|
// src/status/snapshot.ts
|
|
20139
|
-
var
|
|
20922
|
+
var os18 = __toESM(require("os"));
|
|
20140
20923
|
init_config();
|
|
20141
20924
|
init_terminal_screen();
|
|
20142
20925
|
init_logger();
|
|
@@ -20192,8 +20975,8 @@ function buildAvailableProviders(providerLoader) {
|
|
|
20192
20975
|
}
|
|
20193
20976
|
function buildMachineInfo(profile = "full") {
|
|
20194
20977
|
const base = {
|
|
20195
|
-
hostname:
|
|
20196
|
-
platform:
|
|
20978
|
+
hostname: os18.hostname(),
|
|
20979
|
+
platform: os18.platform()
|
|
20197
20980
|
};
|
|
20198
20981
|
if (profile === "live") {
|
|
20199
20982
|
return base;
|
|
@@ -20202,23 +20985,23 @@ function buildMachineInfo(profile = "full") {
|
|
|
20202
20985
|
const memSnap2 = getHostMemorySnapshot();
|
|
20203
20986
|
return {
|
|
20204
20987
|
...base,
|
|
20205
|
-
arch:
|
|
20206
|
-
cpus:
|
|
20988
|
+
arch: os18.arch(),
|
|
20989
|
+
cpus: os18.cpus().length,
|
|
20207
20990
|
totalMem: memSnap2.totalMem,
|
|
20208
|
-
release:
|
|
20991
|
+
release: os18.release()
|
|
20209
20992
|
};
|
|
20210
20993
|
}
|
|
20211
20994
|
const memSnap = getHostMemorySnapshot();
|
|
20212
20995
|
return {
|
|
20213
20996
|
...base,
|
|
20214
|
-
arch:
|
|
20215
|
-
cpus:
|
|
20997
|
+
arch: os18.arch(),
|
|
20998
|
+
cpus: os18.cpus().length,
|
|
20216
20999
|
totalMem: memSnap.totalMem,
|
|
20217
21000
|
freeMem: memSnap.freeMem,
|
|
20218
21001
|
availableMem: memSnap.availableMem,
|
|
20219
|
-
loadavg:
|
|
20220
|
-
uptime:
|
|
20221
|
-
release:
|
|
21002
|
+
loadavg: os18.loadavg(),
|
|
21003
|
+
uptime: os18.uptime(),
|
|
21004
|
+
release: os18.release()
|
|
20222
21005
|
};
|
|
20223
21006
|
}
|
|
20224
21007
|
function parseMessageTime(value) {
|
|
@@ -20452,14 +21235,14 @@ function buildStatusSnapshot(options) {
|
|
|
20452
21235
|
var import_child_process8 = require("child_process");
|
|
20453
21236
|
var import_child_process9 = require("child_process");
|
|
20454
21237
|
var fs9 = __toESM(require("fs"));
|
|
20455
|
-
var
|
|
20456
|
-
var
|
|
21238
|
+
var os19 = __toESM(require("os"));
|
|
21239
|
+
var path21 = __toESM(require("path"));
|
|
20457
21240
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
20458
21241
|
function getUpgradeLogPath() {
|
|
20459
|
-
const home =
|
|
20460
|
-
const dir =
|
|
21242
|
+
const home = os19.homedir();
|
|
21243
|
+
const dir = path21.join(home, ".adhdev");
|
|
20461
21244
|
fs9.mkdirSync(dir, { recursive: true });
|
|
20462
|
-
return
|
|
21245
|
+
return path21.join(dir, "daemon-upgrade.log");
|
|
20463
21246
|
}
|
|
20464
21247
|
function appendUpgradeLog(message) {
|
|
20465
21248
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -20470,14 +21253,14 @@ function appendUpgradeLog(message) {
|
|
|
20470
21253
|
}
|
|
20471
21254
|
}
|
|
20472
21255
|
function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
|
|
20473
|
-
const binDir =
|
|
21256
|
+
const binDir = path21.dirname(nodeExecutable);
|
|
20474
21257
|
if (platform10 === "win32") {
|
|
20475
|
-
const npmCliPath =
|
|
21258
|
+
const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
|
|
20476
21259
|
if (fs9.existsSync(npmCliPath)) {
|
|
20477
21260
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20478
21261
|
}
|
|
20479
21262
|
for (const candidate of ["npm.exe", "npm"]) {
|
|
20480
|
-
const candidatePath =
|
|
21263
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20481
21264
|
if (fs9.existsSync(candidatePath)) {
|
|
20482
21265
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20483
21266
|
}
|
|
@@ -20485,7 +21268,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
|
|
|
20485
21268
|
return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
|
|
20486
21269
|
}
|
|
20487
21270
|
for (const candidate of ["npm"]) {
|
|
20488
|
-
const candidatePath =
|
|
21271
|
+
const candidatePath = path21.join(binDir, candidate);
|
|
20489
21272
|
if (fs9.existsSync(candidatePath)) {
|
|
20490
21273
|
return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
|
|
20491
21274
|
}
|
|
@@ -20502,13 +21285,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20502
21285
|
let currentDir = resolvedPath;
|
|
20503
21286
|
try {
|
|
20504
21287
|
if (fs9.statSync(resolvedPath).isFile()) {
|
|
20505
|
-
currentDir =
|
|
21288
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20506
21289
|
}
|
|
20507
21290
|
} catch {
|
|
20508
|
-
currentDir =
|
|
21291
|
+
currentDir = path21.dirname(resolvedPath);
|
|
20509
21292
|
}
|
|
20510
21293
|
while (true) {
|
|
20511
|
-
const packageJsonPath =
|
|
21294
|
+
const packageJsonPath = path21.join(currentDir, "package.json");
|
|
20512
21295
|
try {
|
|
20513
21296
|
if (fs9.existsSync(packageJsonPath)) {
|
|
20514
21297
|
const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -20519,7 +21302,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20519
21302
|
}
|
|
20520
21303
|
} catch {
|
|
20521
21304
|
}
|
|
20522
|
-
const parentDir =
|
|
21305
|
+
const parentDir = path21.dirname(currentDir);
|
|
20523
21306
|
if (parentDir === currentDir) {
|
|
20524
21307
|
return null;
|
|
20525
21308
|
}
|
|
@@ -20527,13 +21310,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
|
|
|
20527
21310
|
}
|
|
20528
21311
|
}
|
|
20529
21312
|
function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
|
|
20530
|
-
const nodeModulesDir = packageName.startsWith("@") ?
|
|
20531
|
-
if (
|
|
21313
|
+
const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
|
|
21314
|
+
if (path21.basename(nodeModulesDir) !== "node_modules") {
|
|
20532
21315
|
return null;
|
|
20533
21316
|
}
|
|
20534
|
-
const maybeLibDir =
|
|
20535
|
-
if (
|
|
20536
|
-
return
|
|
21317
|
+
const maybeLibDir = path21.dirname(nodeModulesDir);
|
|
21318
|
+
if (path21.basename(maybeLibDir) === "lib") {
|
|
21319
|
+
return path21.dirname(maybeLibDir);
|
|
20537
21320
|
}
|
|
20538
21321
|
return maybeLibDir;
|
|
20539
21322
|
}
|
|
@@ -20648,7 +21431,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
20648
21431
|
}
|
|
20649
21432
|
}
|
|
20650
21433
|
function stopSessionHostProcesses(appName) {
|
|
20651
|
-
const pidFile =
|
|
21434
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
20652
21435
|
try {
|
|
20653
21436
|
if (fs9.existsSync(pidFile)) {
|
|
20654
21437
|
const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -20665,7 +21448,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
20665
21448
|
}
|
|
20666
21449
|
}
|
|
20667
21450
|
function removeDaemonPidFile() {
|
|
20668
|
-
const pidFile =
|
|
21451
|
+
const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
|
|
20669
21452
|
try {
|
|
20670
21453
|
fs9.unlinkSync(pidFile);
|
|
20671
21454
|
} catch {
|
|
@@ -20676,7 +21459,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20676
21459
|
const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20677
21460
|
if (!npmRoot) return;
|
|
20678
21461
|
const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
|
|
20679
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
21462
|
+
const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
|
|
20680
21463
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
20681
21464
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
20682
21465
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -20684,25 +21467,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
|
|
|
20684
21467
|
}
|
|
20685
21468
|
if (pkgName.startsWith("@")) {
|
|
20686
21469
|
const [scope, name] = pkgName.split("/");
|
|
20687
|
-
const scopeDir =
|
|
21470
|
+
const scopeDir = path21.join(npmRoot, scope);
|
|
20688
21471
|
if (!fs9.existsSync(scopeDir)) return;
|
|
20689
21472
|
for (const entry of fs9.readdirSync(scopeDir)) {
|
|
20690
21473
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
20691
|
-
fs9.rmSync(
|
|
20692
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
21474
|
+
fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
|
|
21475
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
|
|
20693
21476
|
}
|
|
20694
21477
|
} else {
|
|
20695
21478
|
for (const entry of fs9.readdirSync(npmRoot)) {
|
|
20696
21479
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
20697
|
-
fs9.rmSync(
|
|
20698
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
21480
|
+
fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
|
|
21481
|
+
appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
|
|
20699
21482
|
}
|
|
20700
21483
|
}
|
|
20701
21484
|
if (fs9.existsSync(binDir)) {
|
|
20702
21485
|
for (const entry of fs9.readdirSync(binDir)) {
|
|
20703
21486
|
if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
20704
|
-
fs9.rmSync(
|
|
20705
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
21487
|
+
fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
|
|
21488
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
|
|
20706
21489
|
}
|
|
20707
21490
|
}
|
|
20708
21491
|
}
|
|
@@ -20803,6 +21586,56 @@ function normalizeReleaseChannel(value) {
|
|
|
20803
21586
|
function resolveUpgradeChannel(args) {
|
|
20804
21587
|
return normalizeReleaseChannel(args?.channel) || normalizeReleaseChannel(args?.updatePolicy?.channel) || normalizeReleaseChannel(args?.npmTag) || normalizeReleaseChannel(loadConfig().updateChannel) || "stable";
|
|
20805
21588
|
}
|
|
21589
|
+
function readProviderPriorityFromPolicy(policy) {
|
|
21590
|
+
const record = policy && typeof policy === "object" && !Array.isArray(policy) ? policy : {};
|
|
21591
|
+
const raw = record.providerPriority;
|
|
21592
|
+
if (!Array.isArray(raw)) return [];
|
|
21593
|
+
const seen = /* @__PURE__ */ new Set();
|
|
21594
|
+
return raw.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean).filter((type) => {
|
|
21595
|
+
if (seen.has(type)) return false;
|
|
21596
|
+
seen.add(type);
|
|
21597
|
+
return true;
|
|
21598
|
+
});
|
|
21599
|
+
}
|
|
21600
|
+
async function resolveProviderTypeFromPriority(args) {
|
|
21601
|
+
if (!args.providerPriority.length) {
|
|
21602
|
+
return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
|
|
21603
|
+
}
|
|
21604
|
+
const failed = [];
|
|
21605
|
+
for (const requestedType of args.providerPriority) {
|
|
21606
|
+
const normalizedType = args.providerLoader.resolveAlias(requestedType);
|
|
21607
|
+
if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
|
|
21608
|
+
failed.push(`${requestedType}: disabled`);
|
|
21609
|
+
continue;
|
|
21610
|
+
}
|
|
21611
|
+
const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
|
|
21612
|
+
args.providerLoader.setCliDetectionResults([{
|
|
21613
|
+
id: normalizedType,
|
|
21614
|
+
installed: !!detected,
|
|
21615
|
+
path: detected?.path
|
|
21616
|
+
}], false);
|
|
21617
|
+
args.onStatusChange?.();
|
|
21618
|
+
if (detected) return { providerType: normalizedType };
|
|
21619
|
+
failed.push(`${requestedType}: not detected`);
|
|
21620
|
+
}
|
|
21621
|
+
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join("; ")}` };
|
|
21622
|
+
}
|
|
21623
|
+
function loadYamlModule() {
|
|
21624
|
+
return yaml;
|
|
21625
|
+
}
|
|
21626
|
+
function getMcpServersKey(format) {
|
|
21627
|
+
return format === "hermes_config_yaml" ? "mcp_servers" : "mcpServers";
|
|
21628
|
+
}
|
|
21629
|
+
function parseMeshCoordinatorMcpConfig(text, format) {
|
|
21630
|
+
if (!text.trim()) return {};
|
|
21631
|
+
if (format === "claude_mcp_json") return JSON.parse(text);
|
|
21632
|
+
const parsed = loadYamlModule().load(text);
|
|
21633
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
21634
|
+
}
|
|
21635
|
+
function serializeMeshCoordinatorMcpConfig(config, format) {
|
|
21636
|
+
if (format === "claude_mcp_json") return JSON.stringify(config, null, 2);
|
|
21637
|
+
return loadYamlModule().dump(config, { noRefs: true, lineWidth: 120 });
|
|
21638
|
+
}
|
|
20806
21639
|
var CHAT_COMMANDS = [
|
|
20807
21640
|
"send_chat",
|
|
20808
21641
|
"new_chat",
|
|
@@ -20901,6 +21734,154 @@ var DaemonCommandRouter = class {
|
|
|
20901
21734
|
constructor(deps) {
|
|
20902
21735
|
this.deps = deps;
|
|
20903
21736
|
}
|
|
21737
|
+
getCachedInlineMesh(meshId, inlineMesh) {
|
|
21738
|
+
if (inlineMesh && typeof inlineMesh === "object") {
|
|
21739
|
+
this.inlineMeshCache.set(meshId, inlineMesh);
|
|
21740
|
+
return inlineMesh;
|
|
21741
|
+
}
|
|
21742
|
+
return this.inlineMeshCache.get(meshId);
|
|
21743
|
+
}
|
|
21744
|
+
async getMeshForCommand(meshId, inlineMesh) {
|
|
21745
|
+
try {
|
|
21746
|
+
const { getMesh: getMesh3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21747
|
+
const mesh = getMesh3(meshId);
|
|
21748
|
+
if (mesh) return { mesh, inline: false };
|
|
21749
|
+
} catch {
|
|
21750
|
+
}
|
|
21751
|
+
const cached = this.getCachedInlineMesh(meshId, inlineMesh);
|
|
21752
|
+
return cached ? { mesh: cached, inline: true } : null;
|
|
21753
|
+
}
|
|
21754
|
+
updateInlineMeshNode(meshId, mesh, node) {
|
|
21755
|
+
if (!mesh || !Array.isArray(mesh.nodes) || !node?.id) return;
|
|
21756
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === node.id || entry?.nodeId === node.id);
|
|
21757
|
+
if (idx >= 0) mesh.nodes[idx] = node;
|
|
21758
|
+
else mesh.nodes.push(node);
|
|
21759
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21760
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21761
|
+
}
|
|
21762
|
+
removeInlineMeshNode(meshId, mesh, nodeId) {
|
|
21763
|
+
if (!mesh || !Array.isArray(mesh.nodes)) return false;
|
|
21764
|
+
const idx = mesh.nodes.findIndex((entry) => entry?.id === nodeId || entry?.nodeId === nodeId);
|
|
21765
|
+
if (idx === -1) return false;
|
|
21766
|
+
mesh.nodes.splice(idx, 1);
|
|
21767
|
+
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
21768
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21769
|
+
return true;
|
|
21770
|
+
}
|
|
21771
|
+
normalizeMeshSessionCleanupMode(value) {
|
|
21772
|
+
return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
|
|
21773
|
+
}
|
|
21774
|
+
sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
|
|
21775
|
+
const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
|
|
21776
|
+
if (!sessionId) return false;
|
|
21777
|
+
if (sessionIds?.size) return sessionIds.has(sessionId);
|
|
21778
|
+
const workspace = typeof node?.workspace === "string" ? node.workspace : "";
|
|
21779
|
+
if (workspace && record?.workspace === workspace) return true;
|
|
21780
|
+
if (record?.meta?.meshNodeId === nodeId) return true;
|
|
21781
|
+
return false;
|
|
21782
|
+
}
|
|
21783
|
+
isCompletedHostedSession(record) {
|
|
21784
|
+
return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
|
|
21785
|
+
}
|
|
21786
|
+
async cleanupMeshSessions(args) {
|
|
21787
|
+
if (args.mode === "preserve") {
|
|
21788
|
+
return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
|
|
21789
|
+
}
|
|
21790
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
21791
|
+
const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
|
|
21792
|
+
const sessions = await this.deps.sessionHostControl.listSessions();
|
|
21793
|
+
const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
|
|
21794
|
+
const hasExplicitSessionIds = !!requestedSessionIds?.size;
|
|
21795
|
+
const stoppedSessionIds = [];
|
|
21796
|
+
const deletedSessionIds = [];
|
|
21797
|
+
const skippedSessionIds = [];
|
|
21798
|
+
const skippedLiveSessionIds = [];
|
|
21799
|
+
const deleteUnsupportedSessionIds = [];
|
|
21800
|
+
const recordsRemainSessionIds = [];
|
|
21801
|
+
const errors = [];
|
|
21802
|
+
const matchedBySurfaceKind = {
|
|
21803
|
+
live_runtime: 0,
|
|
21804
|
+
recovery_snapshot: 0,
|
|
21805
|
+
inactive_record: 0
|
|
21806
|
+
};
|
|
21807
|
+
for (const record of matched) {
|
|
21808
|
+
const surfaceKind = getSessionHostSurfaceKind(record);
|
|
21809
|
+
matchedBySurfaceKind[surfaceKind] += 1;
|
|
21810
|
+
}
|
|
21811
|
+
for (const record of matched) {
|
|
21812
|
+
const sessionId = String(record.sessionId);
|
|
21813
|
+
const completed = this.isCompletedHostedSession(record);
|
|
21814
|
+
const surfaceKind = getSessionHostSurfaceKind(record);
|
|
21815
|
+
const liveRuntime = surfaceKind === "live_runtime";
|
|
21816
|
+
if (!hasExplicitSessionIds && liveRuntime) {
|
|
21817
|
+
skippedSessionIds.push(sessionId);
|
|
21818
|
+
skippedLiveSessionIds.push(sessionId);
|
|
21819
|
+
continue;
|
|
21820
|
+
}
|
|
21821
|
+
try {
|
|
21822
|
+
if (args.mode === "stop") {
|
|
21823
|
+
if (!completed) {
|
|
21824
|
+
if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
|
|
21825
|
+
stoppedSessionIds.push(sessionId);
|
|
21826
|
+
} else {
|
|
21827
|
+
skippedSessionIds.push(sessionId);
|
|
21828
|
+
}
|
|
21829
|
+
continue;
|
|
21830
|
+
}
|
|
21831
|
+
if (args.mode === "delete_stopped") {
|
|
21832
|
+
if (completed) {
|
|
21833
|
+
if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
|
|
21834
|
+
deletedSessionIds.push(sessionId);
|
|
21835
|
+
} else {
|
|
21836
|
+
skippedSessionIds.push(sessionId);
|
|
21837
|
+
}
|
|
21838
|
+
continue;
|
|
21839
|
+
}
|
|
21840
|
+
if (args.mode === "stop_and_delete") {
|
|
21841
|
+
if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
|
|
21842
|
+
deletedSessionIds.push(sessionId);
|
|
21843
|
+
continue;
|
|
21844
|
+
}
|
|
21845
|
+
} catch (e) {
|
|
21846
|
+
const message = e?.message || String(e);
|
|
21847
|
+
if (message.includes("Unsupported session host request: delete_session") && (args.mode === "delete_stopped" || args.mode === "stop_and_delete")) {
|
|
21848
|
+
deleteUnsupportedSessionIds.push(sessionId);
|
|
21849
|
+
recordsRemainSessionIds.push(sessionId);
|
|
21850
|
+
if (args.mode === "stop_and_delete" && !completed) {
|
|
21851
|
+
try {
|
|
21852
|
+
await this.deps.sessionHostControl.stopSession(sessionId);
|
|
21853
|
+
stoppedSessionIds.push(sessionId);
|
|
21854
|
+
} catch (stopError) {
|
|
21855
|
+
errors.push({ sessionId, error: stopError?.message || String(stopError) });
|
|
21856
|
+
continue;
|
|
21857
|
+
}
|
|
21858
|
+
}
|
|
21859
|
+
skippedSessionIds.push(sessionId);
|
|
21860
|
+
continue;
|
|
21861
|
+
}
|
|
21862
|
+
errors.push({ sessionId, error: message });
|
|
21863
|
+
}
|
|
21864
|
+
}
|
|
21865
|
+
const deleteUnsupported = deleteUnsupportedSessionIds.length > 0;
|
|
21866
|
+
return {
|
|
21867
|
+
success: errors.length === 0,
|
|
21868
|
+
mode: args.mode,
|
|
21869
|
+
dryRun: args.dryRun === true,
|
|
21870
|
+
matchedCount: matched.length,
|
|
21871
|
+
matchedBySurfaceKind,
|
|
21872
|
+
stoppedSessionIds,
|
|
21873
|
+
deletedSessionIds,
|
|
21874
|
+
skippedSessionIds,
|
|
21875
|
+
skippedLiveSessionIds,
|
|
21876
|
+
...deleteUnsupported ? {
|
|
21877
|
+
deleteUnsupported: true,
|
|
21878
|
+
effectiveCleanup: args.mode === "stop_and_delete" ? "stopped_only_records_remain" : "delete_unsupported_records_remain",
|
|
21879
|
+
deleteUnsupportedSessionIds,
|
|
21880
|
+
recordsRemainSessionIds
|
|
21881
|
+
} : {},
|
|
21882
|
+
...errors.length ? { errors } : {}
|
|
21883
|
+
};
|
|
21884
|
+
}
|
|
20904
21885
|
async traceSessionHostAction(action, args, run, summarizeResult) {
|
|
20905
21886
|
const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
|
|
20906
21887
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
|
|
@@ -21020,6 +22001,9 @@ var DaemonCommandRouter = class {
|
|
|
21020
22001
|
async executeDaemonCommand(cmd, args) {
|
|
21021
22002
|
switch (cmd) {
|
|
21022
22003
|
// ─── CLI / ACP commands ───
|
|
22004
|
+
case "mesh_forward_event": {
|
|
22005
|
+
return handleMeshForwardEvent({ instanceManager: this.deps.instanceManager }, args);
|
|
22006
|
+
}
|
|
21023
22007
|
case "launch_cli":
|
|
21024
22008
|
case "stop_cli":
|
|
21025
22009
|
case "set_cli_view_mode":
|
|
@@ -21564,7 +22548,26 @@ var DaemonCommandRouter = class {
|
|
|
21564
22548
|
if (!name) return { success: false, error: "name required" };
|
|
21565
22549
|
try {
|
|
21566
22550
|
const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21567
|
-
const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
|
|
22551
|
+
const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
|
|
22552
|
+
return { success: true, mesh };
|
|
22553
|
+
} catch (e) {
|
|
22554
|
+
return { success: false, error: e.message };
|
|
22555
|
+
}
|
|
22556
|
+
}
|
|
22557
|
+
case "update_mesh": {
|
|
22558
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22559
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
22560
|
+
try {
|
|
22561
|
+
const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22562
|
+
const patch = {};
|
|
22563
|
+
if (typeof args?.name === "string") patch.name = args.name;
|
|
22564
|
+
if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
|
|
22565
|
+
if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
|
|
22566
|
+
if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
|
|
22567
|
+
if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
|
|
22568
|
+
const mesh = updateMesh2(meshId, patch);
|
|
22569
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22570
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21568
22571
|
return { success: true, mesh };
|
|
21569
22572
|
} catch (e) {
|
|
21570
22573
|
return { success: false, error: e.message };
|
|
@@ -21588,21 +22591,164 @@ var DaemonCommandRouter = class {
|
|
|
21588
22591
|
if (!workspace) return { success: false, error: "workspace required" };
|
|
21589
22592
|
try {
|
|
21590
22593
|
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21591
|
-
const
|
|
22594
|
+
const providerPriority = Array.isArray(args?.providerPriority) ? args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean) : [];
|
|
22595
|
+
const readOnly = args?.readOnly === true;
|
|
22596
|
+
const policy = {
|
|
22597
|
+
...readOnly ? { readOnly: true } : {},
|
|
22598
|
+
...providerPriority.length ? { providerPriority } : {}
|
|
22599
|
+
};
|
|
22600
|
+
const node = addNode3(meshId, { workspace, ...policy ? { policy } : {} });
|
|
21592
22601
|
if (!node) return { success: false, error: "Mesh not found" };
|
|
21593
22602
|
return { success: true, node };
|
|
21594
22603
|
} catch (e) {
|
|
21595
22604
|
return { success: false, error: e.message };
|
|
21596
22605
|
}
|
|
21597
22606
|
}
|
|
22607
|
+
case "update_mesh_node": {
|
|
22608
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22609
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
22610
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
22611
|
+
try {
|
|
22612
|
+
const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22613
|
+
const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
|
|
22614
|
+
if (Array.isArray(args?.providerPriority)) {
|
|
22615
|
+
const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
|
|
22616
|
+
delete policy.provider_priority;
|
|
22617
|
+
if (providerPriority.length) {
|
|
22618
|
+
policy.providerPriority = providerPriority;
|
|
22619
|
+
} else {
|
|
22620
|
+
delete policy.providerPriority;
|
|
22621
|
+
}
|
|
22622
|
+
}
|
|
22623
|
+
const node = updateNode2(meshId, nodeId, { policy });
|
|
22624
|
+
if (!node) return { success: false, error: "Mesh node not found" };
|
|
22625
|
+
return { success: true, node };
|
|
22626
|
+
} catch (e) {
|
|
22627
|
+
return { success: false, error: e.message };
|
|
22628
|
+
}
|
|
22629
|
+
}
|
|
22630
|
+
case "cleanup_mesh_sessions": {
|
|
22631
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22632
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
22633
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
22634
|
+
try {
|
|
22635
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22636
|
+
const mesh = meshRecord?.mesh;
|
|
22637
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22638
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
22639
|
+
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
22640
|
+
const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
|
|
22641
|
+
const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
|
|
22642
|
+
const result = await this.cleanupMeshSessions({
|
|
22643
|
+
meshId,
|
|
22644
|
+
nodeId,
|
|
22645
|
+
node,
|
|
22646
|
+
mode,
|
|
22647
|
+
sessionIds,
|
|
22648
|
+
dryRun: args?.dryRun === true
|
|
22649
|
+
});
|
|
22650
|
+
return result;
|
|
22651
|
+
} catch (e) {
|
|
22652
|
+
return { success: false, error: e.message };
|
|
22653
|
+
}
|
|
22654
|
+
}
|
|
21598
22655
|
case "remove_mesh_node": {
|
|
21599
22656
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
21600
22657
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
21601
22658
|
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
21602
22659
|
try {
|
|
21603
|
-
const
|
|
21604
|
-
const
|
|
21605
|
-
|
|
22660
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22661
|
+
const mesh = meshRecord?.mesh;
|
|
22662
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
22663
|
+
const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
|
|
22664
|
+
args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
|
|
22665
|
+
);
|
|
22666
|
+
let sessionCleanup;
|
|
22667
|
+
if (node && sessionCleanupMode !== "preserve") {
|
|
22668
|
+
sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
|
|
22669
|
+
if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
|
|
22670
|
+
}
|
|
22671
|
+
if (node?.isLocalWorktree && node.workspace) {
|
|
22672
|
+
try {
|
|
22673
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
22674
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
22675
|
+
if (repoRoot) {
|
|
22676
|
+
const { removeWorktree: removeWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
22677
|
+
await removeWorktree2(repoRoot, node.workspace);
|
|
22678
|
+
}
|
|
22679
|
+
} catch (e) {
|
|
22680
|
+
LOG.warn("MeshNode", `Worktree cleanup failed for ${nodeId}: ${e.message}`);
|
|
22681
|
+
}
|
|
22682
|
+
}
|
|
22683
|
+
let removed = false;
|
|
22684
|
+
if (meshRecord?.inline) {
|
|
22685
|
+
removed = this.removeInlineMeshNode(meshId, mesh, nodeId);
|
|
22686
|
+
} else {
|
|
22687
|
+
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22688
|
+
removed = removeNode3(meshId, nodeId);
|
|
22689
|
+
}
|
|
22690
|
+
return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
|
|
22691
|
+
} catch (e) {
|
|
22692
|
+
return { success: false, error: e.message };
|
|
22693
|
+
}
|
|
22694
|
+
}
|
|
22695
|
+
case "clone_mesh_node": {
|
|
22696
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22697
|
+
const sourceNodeId = typeof args?.sourceNodeId === "string" ? args.sourceNodeId.trim() : "";
|
|
22698
|
+
const branch = typeof args?.branch === "string" ? args.branch.trim() : "";
|
|
22699
|
+
const baseBranch = typeof args?.baseBranch === "string" ? args.baseBranch.trim() : void 0;
|
|
22700
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
22701
|
+
if (!sourceNodeId) return { success: false, error: "sourceNodeId required" };
|
|
22702
|
+
if (!branch) return { success: false, error: "branch required" };
|
|
22703
|
+
try {
|
|
22704
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22705
|
+
const mesh = meshRecord?.mesh;
|
|
22706
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22707
|
+
const sourceNode = mesh.nodes?.find((n) => n.id === sourceNodeId || n.nodeId === sourceNodeId);
|
|
22708
|
+
if (!sourceNode) return { success: false, error: `Source node '${sourceNodeId}' not found in mesh` };
|
|
22709
|
+
const repoRoot = sourceNode.repoRoot || sourceNode.workspace;
|
|
22710
|
+
const { createWorktree: createWorktree2 } = await Promise.resolve().then(() => (init_git_worktree(), git_worktree_exports));
|
|
22711
|
+
const result = await createWorktree2({
|
|
22712
|
+
repoRoot,
|
|
22713
|
+
branch,
|
|
22714
|
+
baseBranch,
|
|
22715
|
+
meshName: mesh.name
|
|
22716
|
+
});
|
|
22717
|
+
let node;
|
|
22718
|
+
if (meshRecord.inline) {
|
|
22719
|
+
const { randomUUID: randomUUID8 } = await import("crypto");
|
|
22720
|
+
node = {
|
|
22721
|
+
id: `node_${randomUUID8().replace(/-/g, "")}`,
|
|
22722
|
+
workspace: result.worktreePath,
|
|
22723
|
+
repoRoot: result.worktreePath,
|
|
22724
|
+
daemonId: sourceNode.daemonId,
|
|
22725
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
22726
|
+
policy: { ...sourceNode.policy || {} },
|
|
22727
|
+
isLocalWorktree: true,
|
|
22728
|
+
worktreeBranch: result.branch,
|
|
22729
|
+
clonedFromNodeId: sourceNodeId
|
|
22730
|
+
};
|
|
22731
|
+
this.updateInlineMeshNode(meshId, mesh, node);
|
|
22732
|
+
} else {
|
|
22733
|
+
const { addNode: addNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22734
|
+
node = addNode3(meshId, {
|
|
22735
|
+
workspace: result.worktreePath,
|
|
22736
|
+
repoRoot: result.worktreePath,
|
|
22737
|
+
daemonId: sourceNode.daemonId,
|
|
22738
|
+
userOverrides: { ...sourceNode.userOverrides || {} },
|
|
22739
|
+
isLocalWorktree: true,
|
|
22740
|
+
worktreeBranch: result.branch,
|
|
22741
|
+
clonedFromNodeId: sourceNodeId,
|
|
22742
|
+
policy: { ...sourceNode.policy || {} }
|
|
22743
|
+
});
|
|
22744
|
+
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
22745
|
+
}
|
|
22746
|
+
return {
|
|
22747
|
+
success: true,
|
|
22748
|
+
node,
|
|
22749
|
+
worktreePath: result.worktreePath,
|
|
22750
|
+
branch: result.branch
|
|
22751
|
+
};
|
|
21606
22752
|
} catch (e) {
|
|
21607
22753
|
return { success: false, error: e.message };
|
|
21608
22754
|
}
|
|
@@ -21610,7 +22756,7 @@ var DaemonCommandRouter = class {
|
|
|
21610
22756
|
// ─── Mesh Coordinator Launch ───
|
|
21611
22757
|
case "launch_mesh_coordinator": {
|
|
21612
22758
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
21613
|
-
|
|
22759
|
+
let cliType = typeof args?.cliType === "string" ? args.cliType.trim() : "";
|
|
21614
22760
|
if (!meshId) return { success: false, error: "meshId required" };
|
|
21615
22761
|
try {
|
|
21616
22762
|
const { buildCoordinatorSystemPrompt: buildCoordinatorSystemPrompt2 } = await Promise.resolve().then(() => (init_coordinator_prompt(), coordinator_prompt_exports));
|
|
@@ -21638,9 +22784,29 @@ var DaemonCommandRouter = class {
|
|
|
21638
22784
|
}
|
|
21639
22785
|
const workspace = typeof coordinatorNode.workspace === "string" ? coordinatorNode.workspace.trim() : "";
|
|
21640
22786
|
if (!workspace) return { success: false, error: "Coordinator node workspace required", meshId, cliType };
|
|
22787
|
+
if (!cliType) {
|
|
22788
|
+
const resolved = await resolveProviderTypeFromPriority({
|
|
22789
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || "coordinator"),
|
|
22790
|
+
providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
|
|
22791
|
+
providerLoader: this.deps.providerLoader,
|
|
22792
|
+
onStatusChange: this.deps.onStatusChange
|
|
22793
|
+
});
|
|
22794
|
+
if (!resolved.providerType) {
|
|
22795
|
+
return {
|
|
22796
|
+
success: false,
|
|
22797
|
+
code: "mesh_coordinator_provider_priority_unusable",
|
|
22798
|
+
error: resolved.error || "No usable provider found from node providerPriority",
|
|
22799
|
+
meshId,
|
|
22800
|
+
cliType,
|
|
22801
|
+
workspace
|
|
22802
|
+
};
|
|
22803
|
+
}
|
|
22804
|
+
cliType = resolved.providerType;
|
|
22805
|
+
}
|
|
21641
22806
|
const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
|
|
21642
22807
|
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
21643
22808
|
provider: providerMeta,
|
|
22809
|
+
cliType,
|
|
21644
22810
|
meshId,
|
|
21645
22811
|
workspace
|
|
21646
22812
|
});
|
|
@@ -21665,7 +22831,8 @@ var DaemonCommandRouter = class {
|
|
|
21665
22831
|
meshCoordinatorSetup: coordinatorSetup
|
|
21666
22832
|
};
|
|
21667
22833
|
}
|
|
21668
|
-
|
|
22834
|
+
const configFormat = coordinatorSetup.configFormat;
|
|
22835
|
+
if (configFormat !== "claude_mcp_json" && configFormat !== "hermes_config_yaml") {
|
|
21669
22836
|
return {
|
|
21670
22837
|
success: false,
|
|
21671
22838
|
code: "mesh_coordinator_unsupported",
|
|
@@ -21675,17 +22842,34 @@ var DaemonCommandRouter = class {
|
|
|
21675
22842
|
workspace
|
|
21676
22843
|
};
|
|
21677
22844
|
}
|
|
21678
|
-
|
|
21679
|
-
|
|
21680
|
-
|
|
21681
|
-
|
|
21682
|
-
|
|
21683
|
-
|
|
21684
|
-
|
|
21685
|
-
|
|
21686
|
-
|
|
21687
|
-
|
|
22845
|
+
let systemPrompt = "";
|
|
22846
|
+
try {
|
|
22847
|
+
systemPrompt = buildCoordinatorSystemPrompt2({ mesh, coordinatorCliType: cliType });
|
|
22848
|
+
} catch (error) {
|
|
22849
|
+
const message = error?.message || String(error);
|
|
22850
|
+
LOG.error("MeshCoordinator", `Failed to build coordinator prompt: ${message}`);
|
|
22851
|
+
return {
|
|
22852
|
+
success: false,
|
|
22853
|
+
code: "mesh_coordinator_prompt_failed",
|
|
22854
|
+
error: `Failed to build Repo Mesh coordinator prompt: ${message}`,
|
|
22855
|
+
meshId,
|
|
22856
|
+
cliType,
|
|
22857
|
+
workspace
|
|
22858
|
+
};
|
|
21688
22859
|
}
|
|
22860
|
+
const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
|
|
22861
|
+
const { dirname: dirname9 } = await import("path");
|
|
22862
|
+
const mcpConfigPath = coordinatorSetup.configPath;
|
|
22863
|
+
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
22864
|
+
const returnManualFallback = (message) => ({
|
|
22865
|
+
success: false,
|
|
22866
|
+
code: "mesh_coordinator_manual_mcp_setup_required",
|
|
22867
|
+
error: message,
|
|
22868
|
+
meshId,
|
|
22869
|
+
cliType,
|
|
22870
|
+
workspace,
|
|
22871
|
+
meshCoordinatorSetup: hermesManualFallback
|
|
22872
|
+
});
|
|
21689
22873
|
const mcpServerEntry = {
|
|
21690
22874
|
command: coordinatorSetup.mcpServer.command,
|
|
21691
22875
|
args: coordinatorSetup.mcpServer.args
|
|
@@ -21696,24 +22880,55 @@ var DaemonCommandRouter = class {
|
|
|
21696
22880
|
ADHDEV_MCP_TRANSPORT: "ipc"
|
|
21697
22881
|
};
|
|
21698
22882
|
}
|
|
22883
|
+
try {
|
|
22884
|
+
mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
|
|
22885
|
+
} catch (error) {
|
|
22886
|
+
const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
|
|
22887
|
+
LOG.error("MeshCoordinator", message);
|
|
22888
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
22889
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
22890
|
+
}
|
|
22891
|
+
const hadExistingMcpConfig = existsSync23(mcpConfigPath);
|
|
22892
|
+
let existingMcpConfig = {};
|
|
22893
|
+
if (hadExistingMcpConfig) {
|
|
22894
|
+
try {
|
|
22895
|
+
existingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
|
|
22896
|
+
copyFileSync3(mcpConfigPath, mcpConfigPath + ".backup");
|
|
22897
|
+
} catch (error) {
|
|
22898
|
+
LOG.error("MeshCoordinator", `Failed to parse existing MCP config ${mcpConfigPath}: ${error?.message || error}`);
|
|
22899
|
+
return {
|
|
22900
|
+
success: false,
|
|
22901
|
+
code: "mesh_coordinator_config_parse_failed",
|
|
22902
|
+
error: `Failed to parse existing MCP config at ${mcpConfigPath}`
|
|
22903
|
+
};
|
|
22904
|
+
}
|
|
22905
|
+
}
|
|
22906
|
+
const mcpServersKey = getMcpServersKey(configFormat);
|
|
22907
|
+
const existingServers = existingMcpConfig[mcpServersKey];
|
|
21699
22908
|
const mcpConfig = {
|
|
21700
22909
|
...existingMcpConfig,
|
|
21701
|
-
|
|
21702
|
-
...
|
|
22910
|
+
[mcpServersKey]: {
|
|
22911
|
+
...existingServers && typeof existingServers === "object" && !Array.isArray(existingServers) ? existingServers : {},
|
|
21703
22912
|
[coordinatorSetup.serverName]: mcpServerEntry
|
|
21704
22913
|
}
|
|
21705
22914
|
};
|
|
21706
|
-
writeFileSync12(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
21707
|
-
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21708
|
-
let systemPrompt = "";
|
|
21709
22915
|
try {
|
|
21710
|
-
|
|
21711
|
-
} catch {
|
|
21712
|
-
|
|
22916
|
+
writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
22917
|
+
} catch (error) {
|
|
22918
|
+
const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
|
|
22919
|
+
LOG.error("MeshCoordinator", message);
|
|
22920
|
+
if (hermesManualFallback) return returnManualFallback(message);
|
|
22921
|
+
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
21713
22922
|
}
|
|
22923
|
+
LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
|
|
21714
22924
|
const cliArgs = [];
|
|
22925
|
+
const launchEnv = {};
|
|
21715
22926
|
if (systemPrompt) {
|
|
21716
|
-
|
|
22927
|
+
if (configFormat === "hermes_config_yaml") {
|
|
22928
|
+
launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
|
|
22929
|
+
} else {
|
|
22930
|
+
cliArgs.push("--append-system-prompt", systemPrompt);
|
|
22931
|
+
}
|
|
21717
22932
|
}
|
|
21718
22933
|
if (cliType === "claude-cli") {
|
|
21719
22934
|
cliArgs.push("--mcp-config", coordinatorSetup.configPath);
|
|
@@ -21722,6 +22937,7 @@ var DaemonCommandRouter = class {
|
|
|
21722
22937
|
cliType,
|
|
21723
22938
|
dir: workspace,
|
|
21724
22939
|
cliArgs: cliArgs.length > 0 ? cliArgs : void 0,
|
|
22940
|
+
env: Object.keys(launchEnv).length > 0 ? launchEnv : void 0,
|
|
21725
22941
|
settings: {
|
|
21726
22942
|
meshCoordinatorFor: meshId
|
|
21727
22943
|
}
|
|
@@ -21901,6 +23117,12 @@ var DaemonStatusReporter = class {
|
|
|
21901
23117
|
if (providerType) {
|
|
21902
23118
|
payload.providerType = providerType;
|
|
21903
23119
|
}
|
|
23120
|
+
if (typeof event.providerSessionId === "string" && event.providerSessionId.trim()) {
|
|
23121
|
+
payload.providerSessionId = event.providerSessionId.trim();
|
|
23122
|
+
}
|
|
23123
|
+
if (typeof event.workspaceName === "string" && event.workspaceName.trim()) {
|
|
23124
|
+
payload.workspaceName = event.workspaceName.trim();
|
|
23125
|
+
}
|
|
21904
23126
|
if (typeof event.duration === "number" && Number.isFinite(event.duration)) {
|
|
21905
23127
|
payload.duration = event.duration;
|
|
21906
23128
|
}
|
|
@@ -22122,7 +23344,8 @@ function prepareSessionChatTailUpdate(input) {
|
|
|
22122
23344
|
update: null
|
|
22123
23345
|
};
|
|
22124
23346
|
}
|
|
22125
|
-
const
|
|
23347
|
+
const fullMessages = normalizeChatMessages(Array.isArray(result.messages) ? result.messages : []);
|
|
23348
|
+
const messages = filterUserFacingChatMessages(fullMessages);
|
|
22126
23349
|
const title = typeof result.title === "string" ? result.title : void 0;
|
|
22127
23350
|
const activeModal = normalizeChatTailActiveModal(result.activeModal);
|
|
22128
23351
|
const status = typeof result.status === "string" ? result.status : "idle";
|
|
@@ -23148,7 +24371,10 @@ var ProviderInstanceManager = class {
|
|
|
23148
24371
|
this.instances.get(id).dispose();
|
|
23149
24372
|
}
|
|
23150
24373
|
this.instances.set(id, instance);
|
|
23151
|
-
await instance.init(
|
|
24374
|
+
await instance.init({
|
|
24375
|
+
...context,
|
|
24376
|
+
emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event)
|
|
24377
|
+
});
|
|
23152
24378
|
}
|
|
23153
24379
|
/**
|
|
23154
24380
|
* Instance remove
|
|
@@ -23310,6 +24536,17 @@ var ProviderInstanceManager = class {
|
|
|
23310
24536
|
onEvent(listener) {
|
|
23311
24537
|
this.eventListeners.push(listener);
|
|
23312
24538
|
}
|
|
24539
|
+
emitProviderEvent(providerType, instanceId, event) {
|
|
24540
|
+
const payload = {
|
|
24541
|
+
...event,
|
|
24542
|
+
providerType,
|
|
24543
|
+
instanceId: typeof event.instanceId === "string" && event.instanceId.trim() ? event.instanceId : instanceId,
|
|
24544
|
+
targetSessionId: typeof event.targetSessionId === "string" && event.targetSessionId.trim() ? event.targetSessionId : instanceId
|
|
24545
|
+
};
|
|
24546
|
+
for (const listener of this.eventListeners) {
|
|
24547
|
+
listener(payload);
|
|
24548
|
+
}
|
|
24549
|
+
}
|
|
23313
24550
|
emitPendingEvents(providerType, state, extra = {}) {
|
|
23314
24551
|
for (const event of state.pendingEvents) {
|
|
23315
24552
|
for (const listener of this.eventListeners) {
|
|
@@ -23382,11 +24619,11 @@ var ProviderInstanceManager = class {
|
|
|
23382
24619
|
|
|
23383
24620
|
// src/providers/version-archive.ts
|
|
23384
24621
|
var fs11 = __toESM(require("fs"));
|
|
23385
|
-
var
|
|
23386
|
-
var
|
|
24622
|
+
var path22 = __toESM(require("path"));
|
|
24623
|
+
var os20 = __toESM(require("os"));
|
|
23387
24624
|
var import_child_process10 = require("child_process");
|
|
23388
24625
|
var import_os3 = require("os");
|
|
23389
|
-
var ARCHIVE_PATH =
|
|
24626
|
+
var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
|
|
23390
24627
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
23391
24628
|
var VersionArchive = class {
|
|
23392
24629
|
history = {};
|
|
@@ -23433,7 +24670,7 @@ var VersionArchive = class {
|
|
|
23433
24670
|
}
|
|
23434
24671
|
save() {
|
|
23435
24672
|
try {
|
|
23436
|
-
fs11.mkdirSync(
|
|
24673
|
+
fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
|
|
23437
24674
|
fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
23438
24675
|
} catch {
|
|
23439
24676
|
}
|
|
@@ -23489,8 +24726,8 @@ function getVersion(binary, versionCommand) {
|
|
|
23489
24726
|
function checkPathExists2(paths) {
|
|
23490
24727
|
for (const p of paths) {
|
|
23491
24728
|
if (p.includes("*")) {
|
|
23492
|
-
const home =
|
|
23493
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
24729
|
+
const home = os20.homedir();
|
|
24730
|
+
const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
|
|
23494
24731
|
if (fs11.existsSync(resolved)) return resolved;
|
|
23495
24732
|
} else {
|
|
23496
24733
|
if (fs11.existsSync(p)) return p;
|
|
@@ -23500,7 +24737,7 @@ function checkPathExists2(paths) {
|
|
|
23500
24737
|
}
|
|
23501
24738
|
function getMacAppVersion(appPath) {
|
|
23502
24739
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
23503
|
-
const plistPath =
|
|
24740
|
+
const plistPath = path22.join(appPath, "Contents", "Info.plist");
|
|
23504
24741
|
if (!fs11.existsSync(plistPath)) return null;
|
|
23505
24742
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
23506
24743
|
return raw || null;
|
|
@@ -23526,7 +24763,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23526
24763
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
23527
24764
|
let resolvedBin = cliBin;
|
|
23528
24765
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
23529
|
-
const bundled =
|
|
24766
|
+
const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
23530
24767
|
if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
|
|
23531
24768
|
}
|
|
23532
24769
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -23567,7 +24804,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
23567
24804
|
// src/daemon/dev-server.ts
|
|
23568
24805
|
var http2 = __toESM(require("http"));
|
|
23569
24806
|
var fs15 = __toESM(require("fs"));
|
|
23570
|
-
var
|
|
24807
|
+
var path26 = __toESM(require("path"));
|
|
23571
24808
|
init_config();
|
|
23572
24809
|
|
|
23573
24810
|
// src/daemon/scaffold-template.ts
|
|
@@ -23918,7 +25155,7 @@ init_logger();
|
|
|
23918
25155
|
|
|
23919
25156
|
// src/daemon/dev-cdp-handlers.ts
|
|
23920
25157
|
var fs12 = __toESM(require("fs"));
|
|
23921
|
-
var
|
|
25158
|
+
var path23 = __toESM(require("path"));
|
|
23922
25159
|
init_logger();
|
|
23923
25160
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
23924
25161
|
const body = await ctx.readBody(req);
|
|
@@ -24097,17 +25334,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
24097
25334
|
return;
|
|
24098
25335
|
}
|
|
24099
25336
|
let scriptsPath = "";
|
|
24100
|
-
const directScripts =
|
|
25337
|
+
const directScripts = path23.join(dir, "scripts.js");
|
|
24101
25338
|
if (fs12.existsSync(directScripts)) {
|
|
24102
25339
|
scriptsPath = directScripts;
|
|
24103
25340
|
} else {
|
|
24104
|
-
const scriptsDir =
|
|
25341
|
+
const scriptsDir = path23.join(dir, "scripts");
|
|
24105
25342
|
if (fs12.existsSync(scriptsDir)) {
|
|
24106
25343
|
const versions = fs12.readdirSync(scriptsDir).filter((d) => {
|
|
24107
|
-
return fs12.statSync(
|
|
25344
|
+
return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
|
|
24108
25345
|
}).sort().reverse();
|
|
24109
25346
|
for (const ver of versions) {
|
|
24110
|
-
const p =
|
|
25347
|
+
const p = path23.join(scriptsDir, ver, "scripts.js");
|
|
24111
25348
|
if (fs12.existsSync(p)) {
|
|
24112
25349
|
scriptsPath = p;
|
|
24113
25350
|
break;
|
|
@@ -24936,7 +26173,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
24936
26173
|
|
|
24937
26174
|
// src/daemon/dev-cli-debug.ts
|
|
24938
26175
|
var fs13 = __toESM(require("fs"));
|
|
24939
|
-
var
|
|
26176
|
+
var path24 = __toESM(require("path"));
|
|
24940
26177
|
function slugifyFixtureName(value) {
|
|
24941
26178
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
24942
26179
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -24946,11 +26183,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
24946
26183
|
if (!providerDir) {
|
|
24947
26184
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
24948
26185
|
}
|
|
24949
|
-
return
|
|
26186
|
+
return path24.join(providerDir, "fixtures");
|
|
24950
26187
|
}
|
|
24951
26188
|
function readCliFixture(ctx, type, name) {
|
|
24952
26189
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
24953
|
-
const filePath =
|
|
26190
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
24954
26191
|
if (!fs13.existsSync(filePath)) {
|
|
24955
26192
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
24956
26193
|
}
|
|
@@ -25118,7 +26355,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
|
|
|
25118
26355
|
if (!adapter) return null;
|
|
25119
26356
|
return { target, instance, adapter };
|
|
25120
26357
|
}
|
|
25121
|
-
function
|
|
26358
|
+
function sleep2(ms) {
|
|
25122
26359
|
return new Promise((resolve16) => setTimeout(resolve16, ms));
|
|
25123
26360
|
}
|
|
25124
26361
|
async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
@@ -25135,7 +26372,7 @@ async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
|
|
|
25135
26372
|
return bundle;
|
|
25136
26373
|
}
|
|
25137
26374
|
}
|
|
25138
|
-
await
|
|
26375
|
+
await sleep2(100);
|
|
25139
26376
|
}
|
|
25140
26377
|
return getCliTargetBundle(ctx, type, instanceId);
|
|
25141
26378
|
}
|
|
@@ -25191,7 +26428,7 @@ async function runCliExerciseInternal(ctx, body) {
|
|
|
25191
26428
|
const message = String(lastLaunchError.message || "");
|
|
25192
26429
|
const retryable = /ECONNREFUSED|session-host|Session host/i.test(message);
|
|
25193
26430
|
if (!retryable || attempt === 2) break;
|
|
25194
|
-
await
|
|
26431
|
+
await sleep2(1e3);
|
|
25195
26432
|
}
|
|
25196
26433
|
}
|
|
25197
26434
|
if (!launched) {
|
|
@@ -25254,16 +26491,16 @@ async function runCliExerciseInternal(ctx, body) {
|
|
|
25254
26491
|
const modal = debug?.activeModal || trace?.activeModal || null;
|
|
25255
26492
|
noteStatus(status);
|
|
25256
26493
|
if (resolveActiveModalIfNeeded(status, modal)) {
|
|
25257
|
-
await
|
|
26494
|
+
await sleep2(150);
|
|
25258
26495
|
continue;
|
|
25259
26496
|
}
|
|
25260
26497
|
const startupParseGate = !!debug?.startupParseGate;
|
|
25261
26498
|
if (status === "idle" && !startupParseGate) break;
|
|
25262
|
-
await
|
|
26499
|
+
await sleep2(150);
|
|
25263
26500
|
}
|
|
25264
26501
|
ctx.instanceManager.sendEvent(bundle.target.instanceId, "send_message", { text });
|
|
25265
26502
|
while (Date.now() - startAt < Math.max(1e3, timeoutMs)) {
|
|
25266
|
-
await
|
|
26503
|
+
await sleep2(150);
|
|
25267
26504
|
bundle = getCliTargetBundle(ctx, type, bundle.target.instanceId);
|
|
25268
26505
|
if (!bundle) {
|
|
25269
26506
|
throw new Error("CLI instance disappeared during exercise");
|
|
@@ -25717,7 +26954,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
25717
26954
|
},
|
|
25718
26955
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
25719
26956
|
};
|
|
25720
|
-
const filePath =
|
|
26957
|
+
const filePath = path24.join(fixtureDir, `${name}.json`);
|
|
25721
26958
|
fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
25722
26959
|
ctx.json(res, 200, {
|
|
25723
26960
|
saved: true,
|
|
@@ -25741,7 +26978,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
25741
26978
|
return;
|
|
25742
26979
|
}
|
|
25743
26980
|
const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
25744
|
-
const fullPath =
|
|
26981
|
+
const fullPath = path24.join(fixtureDir, file);
|
|
25745
26982
|
try {
|
|
25746
26983
|
const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
|
|
25747
26984
|
return {
|
|
@@ -25877,8 +27114,8 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
25877
27114
|
|
|
25878
27115
|
// src/daemon/dev-auto-implement.ts
|
|
25879
27116
|
var fs14 = __toESM(require("fs"));
|
|
25880
|
-
var
|
|
25881
|
-
var
|
|
27117
|
+
var path25 = __toESM(require("path"));
|
|
27118
|
+
var os21 = __toESM(require("os"));
|
|
25882
27119
|
function getAutoImplPid(ctx) {
|
|
25883
27120
|
const pid = ctx.autoImplProcess?.pid;
|
|
25884
27121
|
return typeof pid === "number" && pid > 0 ? pid : null;
|
|
@@ -25927,22 +27164,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
25927
27164
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
25928
27165
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
25929
27166
|
try {
|
|
25930
|
-
return fs14.statSync(
|
|
27167
|
+
return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
|
|
25931
27168
|
} catch {
|
|
25932
27169
|
return false;
|
|
25933
27170
|
}
|
|
25934
27171
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
25935
27172
|
if (versions.length === 0) return null;
|
|
25936
|
-
return
|
|
27173
|
+
return path25.join(scriptsDir, versions[0]);
|
|
25937
27174
|
}
|
|
25938
27175
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
25939
|
-
const canonicalUserDir =
|
|
25940
|
-
const desiredDir = requestedDir ?
|
|
25941
|
-
const upstreamRoot =
|
|
25942
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
27176
|
+
const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
27177
|
+
const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
|
|
27178
|
+
const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
|
|
27179
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
|
|
25943
27180
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
25944
27181
|
}
|
|
25945
|
-
if (
|
|
27182
|
+
if (path25.basename(desiredDir) !== type) {
|
|
25946
27183
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
25947
27184
|
}
|
|
25948
27185
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -25950,11 +27187,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
25950
27187
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
25951
27188
|
}
|
|
25952
27189
|
if (!fs14.existsSync(desiredDir)) {
|
|
25953
|
-
fs14.mkdirSync(
|
|
27190
|
+
fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
|
|
25954
27191
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
25955
27192
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
25956
27193
|
}
|
|
25957
|
-
const providerJson =
|
|
27194
|
+
const providerJson = path25.join(desiredDir, "provider.json");
|
|
25958
27195
|
if (!fs14.existsSync(providerJson)) {
|
|
25959
27196
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
25960
27197
|
}
|
|
@@ -25965,13 +27202,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
25965
27202
|
const refDir = ctx.findProviderDir(referenceType);
|
|
25966
27203
|
if (!refDir || !fs14.existsSync(refDir)) return {};
|
|
25967
27204
|
const referenceScripts = {};
|
|
25968
|
-
const scriptsDir =
|
|
27205
|
+
const scriptsDir = path25.join(refDir, "scripts");
|
|
25969
27206
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
25970
27207
|
if (!latestDir) return referenceScripts;
|
|
25971
27208
|
for (const file of fs14.readdirSync(latestDir)) {
|
|
25972
27209
|
if (!file.endsWith(".js")) continue;
|
|
25973
27210
|
try {
|
|
25974
|
-
referenceScripts[file] = fs14.readFileSync(
|
|
27211
|
+
referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
|
|
25975
27212
|
} catch {
|
|
25976
27213
|
}
|
|
25977
27214
|
}
|
|
@@ -26079,9 +27316,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26079
27316
|
});
|
|
26080
27317
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
26081
27318
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
26082
|
-
const tmpDir =
|
|
27319
|
+
const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
|
|
26083
27320
|
if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
|
|
26084
|
-
const promptFile =
|
|
27321
|
+
const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
26085
27322
|
fs14.writeFileSync(promptFile, prompt, "utf-8");
|
|
26086
27323
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
26087
27324
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -26234,7 +27471,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26234
27471
|
const interactiveFlags = ["--yolo", "--interactive", "-i"];
|
|
26235
27472
|
const baseArgs = [...spawn4.args || []].filter((a) => !interactiveFlags.includes(a));
|
|
26236
27473
|
let shellCmd;
|
|
26237
|
-
const isWin =
|
|
27474
|
+
const isWin = os21.platform() === "win32";
|
|
26238
27475
|
const escapeArg = (a) => isWin ? `"${a.replace(/"/g, '""')}"` : `'${a.replace(/'/g, "'\\''")}'`;
|
|
26239
27476
|
const promptMode = autoImpl?.promptMode ?? "stdin";
|
|
26240
27477
|
const extraArgs = autoImpl?.extraArgs ?? [];
|
|
@@ -26273,7 +27510,7 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
26273
27510
|
try {
|
|
26274
27511
|
const pty = require("node-pty");
|
|
26275
27512
|
ctx.log(`Auto-implement spawn (PTY): ${shellCmd}`);
|
|
26276
|
-
const isWin2 =
|
|
27513
|
+
const isWin2 = os21.platform() === "win32";
|
|
26277
27514
|
child = pty.spawn(isWin2 ? "cmd.exe" : process.env.SHELL || "/bin/zsh", [isWin2 ? "/c" : "-c", shellCmd], {
|
|
26278
27515
|
name: "xterm-256color",
|
|
26279
27516
|
cols: 120,
|
|
@@ -26513,7 +27750,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26513
27750
|
setMode: "set_mode.js"
|
|
26514
27751
|
};
|
|
26515
27752
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26516
|
-
const scriptsDir =
|
|
27753
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26517
27754
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26518
27755
|
if (latestScriptsDir) {
|
|
26519
27756
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26524,7 +27761,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26524
27761
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
26525
27762
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
26526
27763
|
try {
|
|
26527
|
-
const content = fs14.readFileSync(
|
|
27764
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26528
27765
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26529
27766
|
lines.push("```javascript");
|
|
26530
27767
|
lines.push(content);
|
|
@@ -26541,7 +27778,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26541
27778
|
lines.push("");
|
|
26542
27779
|
for (const file of refFiles) {
|
|
26543
27780
|
try {
|
|
26544
|
-
const content = fs14.readFileSync(
|
|
27781
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26545
27782
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26546
27783
|
lines.push("```javascript");
|
|
26547
27784
|
lines.push(content);
|
|
@@ -26582,10 +27819,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
26582
27819
|
lines.push("");
|
|
26583
27820
|
}
|
|
26584
27821
|
}
|
|
26585
|
-
const docsDir =
|
|
27822
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26586
27823
|
const loadGuide = (name) => {
|
|
26587
27824
|
try {
|
|
26588
|
-
const p =
|
|
27825
|
+
const p = path25.join(docsDir, name);
|
|
26589
27826
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26590
27827
|
} catch {
|
|
26591
27828
|
}
|
|
@@ -26822,7 +28059,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26822
28059
|
parseApproval: "parse_approval.js"
|
|
26823
28060
|
};
|
|
26824
28061
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
26825
|
-
const scriptsDir =
|
|
28062
|
+
const scriptsDir = path25.join(providerDir, "scripts");
|
|
26826
28063
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
26827
28064
|
if (latestScriptsDir) {
|
|
26828
28065
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -26834,7 +28071,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26834
28071
|
if (!file.endsWith(".js")) continue;
|
|
26835
28072
|
if (!targetFileNames.has(file)) continue;
|
|
26836
28073
|
try {
|
|
26837
|
-
const content = fs14.readFileSync(
|
|
28074
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26838
28075
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
26839
28076
|
lines.push("```javascript");
|
|
26840
28077
|
lines.push(content);
|
|
@@ -26850,7 +28087,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26850
28087
|
lines.push("");
|
|
26851
28088
|
for (const file of refFiles) {
|
|
26852
28089
|
try {
|
|
26853
|
-
const content = fs14.readFileSync(
|
|
28090
|
+
const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
|
|
26854
28091
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
26855
28092
|
lines.push("```javascript");
|
|
26856
28093
|
lines.push(content);
|
|
@@ -26883,10 +28120,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26883
28120
|
lines.push("");
|
|
26884
28121
|
}
|
|
26885
28122
|
}
|
|
26886
|
-
const docsDir =
|
|
28123
|
+
const docsDir = path25.join(providerDir, "../../docs");
|
|
26887
28124
|
const loadGuide = (name) => {
|
|
26888
28125
|
try {
|
|
26889
|
-
const p =
|
|
28126
|
+
const p = path25.join(docsDir, name);
|
|
26890
28127
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
26891
28128
|
} catch {
|
|
26892
28129
|
}
|
|
@@ -27333,8 +28570,8 @@ var DevServer = class _DevServer {
|
|
|
27333
28570
|
}
|
|
27334
28571
|
getEndpointList() {
|
|
27335
28572
|
return this.routes.map((r) => {
|
|
27336
|
-
const
|
|
27337
|
-
return `${r.method.padEnd(5)} ${
|
|
28573
|
+
const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
28574
|
+
return `${r.method.padEnd(5)} ${path27}`;
|
|
27338
28575
|
});
|
|
27339
28576
|
}
|
|
27340
28577
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -27622,12 +28859,12 @@ var DevServer = class _DevServer {
|
|
|
27622
28859
|
// ─── DevConsole SPA ───
|
|
27623
28860
|
getConsoleDistDir() {
|
|
27624
28861
|
const candidates = [
|
|
27625
|
-
|
|
27626
|
-
|
|
27627
|
-
|
|
28862
|
+
path26.resolve(__dirname, "../../web-devconsole/dist"),
|
|
28863
|
+
path26.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
28864
|
+
path26.join(process.cwd(), "packages/web-devconsole/dist")
|
|
27628
28865
|
];
|
|
27629
28866
|
for (const dir of candidates) {
|
|
27630
|
-
if (fs15.existsSync(
|
|
28867
|
+
if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
|
|
27631
28868
|
}
|
|
27632
28869
|
return null;
|
|
27633
28870
|
}
|
|
@@ -27637,7 +28874,7 @@ var DevServer = class _DevServer {
|
|
|
27637
28874
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
27638
28875
|
return;
|
|
27639
28876
|
}
|
|
27640
|
-
const htmlPath =
|
|
28877
|
+
const htmlPath = path26.join(distDir, "index.html");
|
|
27641
28878
|
try {
|
|
27642
28879
|
const html = fs15.readFileSync(htmlPath, "utf-8");
|
|
27643
28880
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -27662,15 +28899,15 @@ var DevServer = class _DevServer {
|
|
|
27662
28899
|
this.json(res, 404, { error: "Not found" });
|
|
27663
28900
|
return;
|
|
27664
28901
|
}
|
|
27665
|
-
const safePath =
|
|
27666
|
-
const filePath =
|
|
28902
|
+
const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
|
|
28903
|
+
const filePath = path26.join(distDir, safePath);
|
|
27667
28904
|
if (!filePath.startsWith(distDir)) {
|
|
27668
28905
|
this.json(res, 403, { error: "Forbidden" });
|
|
27669
28906
|
return;
|
|
27670
28907
|
}
|
|
27671
28908
|
try {
|
|
27672
28909
|
const content = fs15.readFileSync(filePath);
|
|
27673
|
-
const ext =
|
|
28910
|
+
const ext = path26.extname(filePath);
|
|
27674
28911
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
27675
28912
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
27676
28913
|
res.end(content);
|
|
@@ -27783,9 +29020,9 @@ var DevServer = class _DevServer {
|
|
|
27783
29020
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
27784
29021
|
if (entry.isDirectory()) {
|
|
27785
29022
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
27786
|
-
scan(
|
|
29023
|
+
scan(path26.join(d, entry.name), rel);
|
|
27787
29024
|
} else {
|
|
27788
|
-
const stat2 = fs15.statSync(
|
|
29025
|
+
const stat2 = fs15.statSync(path26.join(d, entry.name));
|
|
27789
29026
|
files.push({ path: rel, size: stat2.size, type: "file" });
|
|
27790
29027
|
}
|
|
27791
29028
|
}
|
|
@@ -27808,7 +29045,7 @@ var DevServer = class _DevServer {
|
|
|
27808
29045
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27809
29046
|
return;
|
|
27810
29047
|
}
|
|
27811
|
-
const fullPath =
|
|
29048
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27812
29049
|
if (!fullPath.startsWith(dir)) {
|
|
27813
29050
|
this.json(res, 403, { error: "Forbidden" });
|
|
27814
29051
|
return;
|
|
@@ -27833,14 +29070,14 @@ var DevServer = class _DevServer {
|
|
|
27833
29070
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
27834
29071
|
return;
|
|
27835
29072
|
}
|
|
27836
|
-
const fullPath =
|
|
29073
|
+
const fullPath = path26.resolve(dir, path26.normalize(filePath));
|
|
27837
29074
|
if (!fullPath.startsWith(dir)) {
|
|
27838
29075
|
this.json(res, 403, { error: "Forbidden" });
|
|
27839
29076
|
return;
|
|
27840
29077
|
}
|
|
27841
29078
|
try {
|
|
27842
29079
|
if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
|
|
27843
|
-
fs15.mkdirSync(
|
|
29080
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
27844
29081
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
27845
29082
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
27846
29083
|
this.providerLoader.reload();
|
|
@@ -27857,7 +29094,7 @@ var DevServer = class _DevServer {
|
|
|
27857
29094
|
return;
|
|
27858
29095
|
}
|
|
27859
29096
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
27860
|
-
const p =
|
|
29097
|
+
const p = path26.join(dir, name);
|
|
27861
29098
|
if (fs15.existsSync(p)) {
|
|
27862
29099
|
const source = fs15.readFileSync(p, "utf-8");
|
|
27863
29100
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -27878,8 +29115,8 @@ var DevServer = class _DevServer {
|
|
|
27878
29115
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
27879
29116
|
return;
|
|
27880
29117
|
}
|
|
27881
|
-
const target = fs15.existsSync(
|
|
27882
|
-
const targetPath =
|
|
29118
|
+
const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
29119
|
+
const targetPath = path26.join(dir, target);
|
|
27883
29120
|
try {
|
|
27884
29121
|
if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
|
|
27885
29122
|
fs15.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -28026,7 +29263,7 @@ var DevServer = class _DevServer {
|
|
|
28026
29263
|
}
|
|
28027
29264
|
let targetDir;
|
|
28028
29265
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
28029
|
-
const jsonPath =
|
|
29266
|
+
const jsonPath = path26.join(targetDir, "provider.json");
|
|
28030
29267
|
if (fs15.existsSync(jsonPath)) {
|
|
28031
29268
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
28032
29269
|
return;
|
|
@@ -28038,8 +29275,8 @@ var DevServer = class _DevServer {
|
|
|
28038
29275
|
const createdFiles = ["provider.json"];
|
|
28039
29276
|
if (result.files) {
|
|
28040
29277
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
28041
|
-
const fullPath =
|
|
28042
|
-
fs15.mkdirSync(
|
|
29278
|
+
const fullPath = path26.join(targetDir, relPath);
|
|
29279
|
+
fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
|
|
28043
29280
|
fs15.writeFileSync(fullPath, content, "utf-8");
|
|
28044
29281
|
createdFiles.push(relPath);
|
|
28045
29282
|
}
|
|
@@ -28092,22 +29329,22 @@ var DevServer = class _DevServer {
|
|
|
28092
29329
|
if (!fs15.existsSync(scriptsDir)) return null;
|
|
28093
29330
|
const versions = fs15.readdirSync(scriptsDir).filter((d) => {
|
|
28094
29331
|
try {
|
|
28095
|
-
return fs15.statSync(
|
|
29332
|
+
return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
|
|
28096
29333
|
} catch {
|
|
28097
29334
|
return false;
|
|
28098
29335
|
}
|
|
28099
29336
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
28100
29337
|
if (versions.length === 0) return null;
|
|
28101
|
-
return
|
|
29338
|
+
return path26.join(scriptsDir, versions[0]);
|
|
28102
29339
|
}
|
|
28103
29340
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
28104
|
-
const canonicalUserDir =
|
|
28105
|
-
const desiredDir = requestedDir ?
|
|
28106
|
-
const upstreamRoot =
|
|
28107
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
29341
|
+
const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
29342
|
+
const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
|
|
29343
|
+
const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
|
|
29344
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
|
|
28108
29345
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
28109
29346
|
}
|
|
28110
|
-
if (
|
|
29347
|
+
if (path26.basename(desiredDir) !== type) {
|
|
28111
29348
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
28112
29349
|
}
|
|
28113
29350
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -28115,11 +29352,11 @@ var DevServer = class _DevServer {
|
|
|
28115
29352
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
28116
29353
|
}
|
|
28117
29354
|
if (!fs15.existsSync(desiredDir)) {
|
|
28118
|
-
fs15.mkdirSync(
|
|
29355
|
+
fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
|
|
28119
29356
|
fs15.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
28120
29357
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
28121
29358
|
}
|
|
28122
|
-
const providerJson =
|
|
29359
|
+
const providerJson = path26.join(desiredDir, "provider.json");
|
|
28123
29360
|
if (!fs15.existsSync(providerJson)) {
|
|
28124
29361
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
28125
29362
|
}
|
|
@@ -28155,7 +29392,7 @@ var DevServer = class _DevServer {
|
|
|
28155
29392
|
setMode: "set_mode.js"
|
|
28156
29393
|
};
|
|
28157
29394
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28158
|
-
const scriptsDir =
|
|
29395
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28159
29396
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28160
29397
|
if (latestScriptsDir) {
|
|
28161
29398
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28166,7 +29403,7 @@ var DevServer = class _DevServer {
|
|
|
28166
29403
|
for (const file of fs15.readdirSync(latestScriptsDir)) {
|
|
28167
29404
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
28168
29405
|
try {
|
|
28169
|
-
const content = fs15.readFileSync(
|
|
29406
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28170
29407
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28171
29408
|
lines.push("```javascript");
|
|
28172
29409
|
lines.push(content);
|
|
@@ -28183,7 +29420,7 @@ var DevServer = class _DevServer {
|
|
|
28183
29420
|
lines.push("");
|
|
28184
29421
|
for (const file of refFiles) {
|
|
28185
29422
|
try {
|
|
28186
|
-
const content = fs15.readFileSync(
|
|
29423
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28187
29424
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28188
29425
|
lines.push("```javascript");
|
|
28189
29426
|
lines.push(content);
|
|
@@ -28224,10 +29461,10 @@ var DevServer = class _DevServer {
|
|
|
28224
29461
|
lines.push("");
|
|
28225
29462
|
}
|
|
28226
29463
|
}
|
|
28227
|
-
const docsDir =
|
|
29464
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28228
29465
|
const loadGuide = (name) => {
|
|
28229
29466
|
try {
|
|
28230
|
-
const p =
|
|
29467
|
+
const p = path26.join(docsDir, name);
|
|
28231
29468
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28232
29469
|
} catch {
|
|
28233
29470
|
}
|
|
@@ -28401,7 +29638,7 @@ var DevServer = class _DevServer {
|
|
|
28401
29638
|
parseApproval: "parse_approval.js"
|
|
28402
29639
|
};
|
|
28403
29640
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
28404
|
-
const scriptsDir =
|
|
29641
|
+
const scriptsDir = path26.join(providerDir, "scripts");
|
|
28405
29642
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
28406
29643
|
if (latestScriptsDir) {
|
|
28407
29644
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -28413,7 +29650,7 @@ var DevServer = class _DevServer {
|
|
|
28413
29650
|
if (!file.endsWith(".js")) continue;
|
|
28414
29651
|
if (!targetFileNames.has(file)) continue;
|
|
28415
29652
|
try {
|
|
28416
|
-
const content = fs15.readFileSync(
|
|
29653
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28417
29654
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
28418
29655
|
lines.push("```javascript");
|
|
28419
29656
|
lines.push(content);
|
|
@@ -28429,7 +29666,7 @@ var DevServer = class _DevServer {
|
|
|
28429
29666
|
lines.push("");
|
|
28430
29667
|
for (const file of refFiles) {
|
|
28431
29668
|
try {
|
|
28432
|
-
const content = fs15.readFileSync(
|
|
29669
|
+
const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
|
|
28433
29670
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
28434
29671
|
lines.push("```javascript");
|
|
28435
29672
|
lines.push(content);
|
|
@@ -28462,10 +29699,10 @@ var DevServer = class _DevServer {
|
|
|
28462
29699
|
lines.push("");
|
|
28463
29700
|
}
|
|
28464
29701
|
}
|
|
28465
|
-
const docsDir =
|
|
29702
|
+
const docsDir = path26.join(providerDir, "../../docs");
|
|
28466
29703
|
const loadGuide = (name) => {
|
|
28467
29704
|
try {
|
|
28468
|
-
const p =
|
|
29705
|
+
const p = path26.join(docsDir, name);
|
|
28469
29706
|
if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
|
|
28470
29707
|
} catch {
|
|
28471
29708
|
}
|
|
@@ -29151,29 +30388,58 @@ function resolveSessionHostAppName(options = {}) {
|
|
|
29151
30388
|
var import_session_host_core4 = require("@adhdev/session-host-core");
|
|
29152
30389
|
var STARTUP_TIMEOUT_MS = DEFAULT_SESSION_HOST_READY_TIMEOUT_MS;
|
|
29153
30390
|
var STARTUP_POLL_MS = 200;
|
|
29154
|
-
|
|
30391
|
+
var SessionHostCompatibilityError = class extends Error {
|
|
30392
|
+
constructor(message) {
|
|
30393
|
+
super(message);
|
|
30394
|
+
this.name = "SessionHostCompatibilityError";
|
|
30395
|
+
}
|
|
30396
|
+
};
|
|
30397
|
+
function getMissingRequestTypes(diagnostics, requiredRequestTypes) {
|
|
30398
|
+
const supported = new Set(diagnostics?.supportedRequestTypes || []);
|
|
30399
|
+
return requiredRequestTypes.filter((requestType) => !supported.has(requestType));
|
|
30400
|
+
}
|
|
30401
|
+
async function assertRequiredRequestTypes(client, requiredRequestTypes) {
|
|
30402
|
+
if (requiredRequestTypes.length === 0) return;
|
|
30403
|
+
const response = await client.request({
|
|
30404
|
+
type: "get_host_diagnostics",
|
|
30405
|
+
payload: { includeSessions: false }
|
|
30406
|
+
});
|
|
30407
|
+
const missing = getMissingRequestTypes(response.success ? response.result : void 0, requiredRequestTypes);
|
|
30408
|
+
if (missing.length > 0) {
|
|
30409
|
+
const detail = response.success ? "" : ` (${response.error || "capability probe failed"})`;
|
|
30410
|
+
throw new SessionHostCompatibilityError(
|
|
30411
|
+
`Session host does not support required request types: ${missing.join(", ")}${detail}`
|
|
30412
|
+
);
|
|
30413
|
+
}
|
|
30414
|
+
}
|
|
30415
|
+
async function canConnect(endpoint, requiredRequestTypes = []) {
|
|
29155
30416
|
const client = new import_session_host_core4.SessionHostClient({ endpoint });
|
|
29156
30417
|
try {
|
|
29157
30418
|
await client.connect();
|
|
29158
|
-
await client
|
|
30419
|
+
await assertRequiredRequestTypes(client, requiredRequestTypes);
|
|
29159
30420
|
return true;
|
|
29160
|
-
} catch {
|
|
30421
|
+
} catch (error) {
|
|
30422
|
+
if (error instanceof SessionHostCompatibilityError) throw error;
|
|
29161
30423
|
return false;
|
|
30424
|
+
} finally {
|
|
30425
|
+
await client.close().catch(() => {
|
|
30426
|
+
});
|
|
29162
30427
|
}
|
|
29163
30428
|
}
|
|
29164
|
-
async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
|
|
30429
|
+
async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS, requiredRequestTypes = []) {
|
|
29165
30430
|
const deadline = Date.now() + timeoutMs;
|
|
29166
30431
|
while (Date.now() < deadline) {
|
|
29167
|
-
if (await canConnect(endpoint)) return;
|
|
30432
|
+
if (await canConnect(endpoint, requiredRequestTypes)) return;
|
|
29168
30433
|
await new Promise((resolve16) => setTimeout(resolve16, STARTUP_POLL_MS));
|
|
29169
30434
|
}
|
|
29170
30435
|
throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
|
|
29171
30436
|
}
|
|
29172
30437
|
async function ensureSessionHostReady(options) {
|
|
29173
30438
|
const endpoint = (0, import_session_host_core4.getDefaultSessionHostEndpoint)(options.appName || "adhdev");
|
|
29174
|
-
|
|
30439
|
+
const requiredRequestTypes = options.requiredRequestTypes || [];
|
|
30440
|
+
if (await canConnect(endpoint, requiredRequestTypes)) return endpoint;
|
|
29175
30441
|
options.spawnHost();
|
|
29176
|
-
await waitForReady(endpoint, options.timeoutMs);
|
|
30442
|
+
await waitForReady(endpoint, options.timeoutMs, requiredRequestTypes);
|
|
29177
30443
|
return endpoint;
|
|
29178
30444
|
}
|
|
29179
30445
|
async function listHostedCliRuntimes(endpoint) {
|
|
@@ -29465,48 +30731,6 @@ var SessionRegistry = class {
|
|
|
29465
30731
|
// src/boot/daemon-lifecycle.ts
|
|
29466
30732
|
init_logger();
|
|
29467
30733
|
init_config();
|
|
29468
|
-
|
|
29469
|
-
// src/mesh/mesh-events.ts
|
|
29470
|
-
init_mesh_config();
|
|
29471
|
-
init_logger();
|
|
29472
|
-
function setupMeshEventForwarding(components) {
|
|
29473
|
-
components.instanceManager.onEvent((event) => {
|
|
29474
|
-
if (event.event !== "agent:generating_completed" && event.event !== "agent:waiting_approval") return;
|
|
29475
|
-
const instanceId = event.instanceId;
|
|
29476
|
-
if (!instanceId) return;
|
|
29477
|
-
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
29478
|
-
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
29479
|
-
const state = sourceInstance.getState();
|
|
29480
|
-
const workspace = state.workspace;
|
|
29481
|
-
if (!workspace) return;
|
|
29482
|
-
const mesh = getMeshByRepo(workspace);
|
|
29483
|
-
if (!mesh) return;
|
|
29484
|
-
const allInstances = components.instanceManager.getByCategory("cli");
|
|
29485
|
-
const coordinatorInstances = allInstances.filter((inst) => {
|
|
29486
|
-
const instState = inst.getState();
|
|
29487
|
-
if (instState.settings?.meshCoordinatorFor !== mesh.id) return false;
|
|
29488
|
-
if (instState.instanceId === instanceId) return false;
|
|
29489
|
-
return true;
|
|
29490
|
-
});
|
|
29491
|
-
if (coordinatorInstances.length === 0) return;
|
|
29492
|
-
const targetNode = mesh.nodes.find((n) => n.workspace === workspace);
|
|
29493
|
-
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : `Agent at ${workspace}`;
|
|
29494
|
-
let messageText = "";
|
|
29495
|
-
if (event.event === "agent:generating_completed") {
|
|
29496
|
-
messageText = `[System] ${nodeLabel} has completed its task and is now idle. You may use mesh_read_chat to review its progress.`;
|
|
29497
|
-
} else if (event.event === "agent:waiting_approval") {
|
|
29498
|
-
messageText = `[System] ${nodeLabel} is waiting for approval to proceed. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
29499
|
-
}
|
|
29500
|
-
if (!messageText) return;
|
|
29501
|
-
for (const coord of coordinatorInstances) {
|
|
29502
|
-
const coordState = coord.getState();
|
|
29503
|
-
LOG.info("MeshEvents", `Forwarding event from ${workspace} to coordinator ${coordState.instanceId}`);
|
|
29504
|
-
coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
|
|
29505
|
-
}
|
|
29506
|
-
});
|
|
29507
|
-
}
|
|
29508
|
-
|
|
29509
|
-
// src/boot/daemon-lifecycle.ts
|
|
29510
30734
|
async function initDaemonComponents(config) {
|
|
29511
30735
|
installGlobalInterceptor();
|
|
29512
30736
|
const appConfig = loadConfig();
|
|
@@ -29739,6 +30963,12 @@ async function shutdownDaemonComponents(components) {
|
|
|
29739
30963
|
AcpProviderInstance,
|
|
29740
30964
|
AgentStreamPoller,
|
|
29741
30965
|
BUILTIN_CHAT_MESSAGE_KINDS,
|
|
30966
|
+
CHAT_MESSAGE_ACTIVITY_SOURCES,
|
|
30967
|
+
CHAT_MESSAGE_AUDIENCES,
|
|
30968
|
+
CHAT_MESSAGE_INTERNAL_SOURCES,
|
|
30969
|
+
CHAT_MESSAGE_SOURCES,
|
|
30970
|
+
CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES,
|
|
30971
|
+
CHAT_MESSAGE_VISIBILITIES,
|
|
29742
30972
|
CdpDomHandlers,
|
|
29743
30973
|
CliProviderInstance,
|
|
29744
30974
|
DAEMON_WS_PATH,
|
|
@@ -29801,6 +31031,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29801
31031
|
buildThoughtChatMessage,
|
|
29802
31032
|
buildToolChatMessage,
|
|
29803
31033
|
buildUserChatMessage,
|
|
31034
|
+
classifyChatMessageVisibility,
|
|
29804
31035
|
classifyHotChatSessionsForSubscriptionFlush,
|
|
29805
31036
|
clearDebugTrace,
|
|
29806
31037
|
compareGitSnapshots,
|
|
@@ -29813,12 +31044,17 @@ async function shutdownDaemonComponents(components) {
|
|
|
29813
31044
|
createGitWorkspaceMonitor,
|
|
29814
31045
|
createInteractionId,
|
|
29815
31046
|
createMesh,
|
|
31047
|
+
createWorktree,
|
|
29816
31048
|
deleteMesh,
|
|
29817
31049
|
detectAllVersions,
|
|
29818
31050
|
detectCLIs,
|
|
29819
31051
|
detectIDEs,
|
|
29820
31052
|
ensureSessionHostReady,
|
|
29821
31053
|
execNpmCommandSync,
|
|
31054
|
+
filterActivityChatMessages,
|
|
31055
|
+
filterChatMessagesByVisibility,
|
|
31056
|
+
filterInternalChatMessages,
|
|
31057
|
+
filterUserFacingChatMessages,
|
|
29822
31058
|
findCdpManager,
|
|
29823
31059
|
flattenMessageParts,
|
|
29824
31060
|
forwardAgentStreamsToIdeInstance,
|
|
@@ -29849,22 +31085,26 @@ async function shutdownDaemonComponents(components) {
|
|
|
29849
31085
|
initDaemonComponents,
|
|
29850
31086
|
installExtensions,
|
|
29851
31087
|
installGlobalInterceptor,
|
|
31088
|
+
isActivityChatMessage,
|
|
29852
31089
|
isBuiltinChatMessageKind,
|
|
29853
31090
|
isCdpConnected,
|
|
29854
31091
|
isExtensionInstalled,
|
|
29855
31092
|
isGitCommandName,
|
|
29856
31093
|
isIdeRunning,
|
|
31094
|
+
isInternalChatMessage,
|
|
29857
31095
|
isManagedStatusWaiting,
|
|
29858
31096
|
isManagedStatusWorking,
|
|
29859
31097
|
isPathInside,
|
|
29860
31098
|
isSessionHostLiveRuntime,
|
|
29861
31099
|
isSessionHostRecoverySnapshot,
|
|
29862
31100
|
isSetupComplete,
|
|
31101
|
+
isUserFacingChatMessage,
|
|
29863
31102
|
killIdeProcess,
|
|
29864
31103
|
launchIDE,
|
|
29865
31104
|
launchWithCdp,
|
|
29866
31105
|
listHostedCliRuntimes,
|
|
29867
31106
|
listMeshes,
|
|
31107
|
+
listWorktrees,
|
|
29868
31108
|
loadConfig,
|
|
29869
31109
|
loadState,
|
|
29870
31110
|
logCommand,
|
|
@@ -29884,6 +31124,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29884
31124
|
normalizeSessionModalFields,
|
|
29885
31125
|
parsePorcelainV2Status,
|
|
29886
31126
|
parseProviderSourceConfigUpdate,
|
|
31127
|
+
parseWorktreeListOutput,
|
|
29887
31128
|
partitionSessionHostDiagnosticsSessions,
|
|
29888
31129
|
partitionSessionHostRecords,
|
|
29889
31130
|
prepareSessionChatTailUpdate,
|
|
@@ -29893,6 +31134,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29893
31134
|
recordDebugTrace,
|
|
29894
31135
|
registerExtensionProviders,
|
|
29895
31136
|
removeNode,
|
|
31137
|
+
removeWorktree,
|
|
29896
31138
|
resetConfig,
|
|
29897
31139
|
resetDebugRuntimeConfig,
|
|
29898
31140
|
resetState,
|
|
@@ -29902,6 +31144,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
29902
31144
|
resolveGitRepository,
|
|
29903
31145
|
resolveSessionHostAppName,
|
|
29904
31146
|
resolveSessionHostAppNameResolution,
|
|
31147
|
+
resolveWorktreePath,
|
|
29905
31148
|
runAsyncBatch,
|
|
29906
31149
|
runGit,
|
|
29907
31150
|
saveConfig,
|