@adhdev/daemon-standalone 0.9.76 → 0.9.77-rc.10
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/index.js +902 -209
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/public/assets/{index-B_uT3-ej.js → index-6WEc6L46.js} +19 -19
- package/public/index.html +1 -1
- package/vendor/mcp-server/index.js +1354 -279
- package/vendor/mcp-server/index.js.map +1 -1
- package/vendor/session-host-daemon/index.js +0 -0
- package/vendor/session-host-daemon/index.mjs +0 -0
package/dist/index.js
CHANGED
|
@@ -31227,7 +31227,8 @@ var require_dist2 = __commonJS({
|
|
|
31227
31227
|
dirtyWorkspaceBehavior: "warn",
|
|
31228
31228
|
maxParallelTasks: 2,
|
|
31229
31229
|
spawnedSessionVisibility: "visible",
|
|
31230
|
-
sessionCleanupOnNodeRemove: "preserve"
|
|
31230
|
+
sessionCleanupOnNodeRemove: "preserve",
|
|
31231
|
+
maxTaskRetries: 1
|
|
31231
31232
|
};
|
|
31232
31233
|
}
|
|
31233
31234
|
});
|
|
@@ -31866,12 +31867,13 @@ ${rules.join("\n")}`;
|
|
|
31866
31867
|
return `## Rules
|
|
31867
31868
|
|
|
31868
31869
|
- **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.
|
|
31869
|
-
- **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.
|
|
31870
|
+
- **Delegate analysis too.** If you need to understand a bug or explore the codebase, send that investigation as a task to the queue or a node. Do not do it yourself.
|
|
31870
31871
|
- **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.
|
|
31871
|
-
- **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.
|
|
31872
|
+
- **Front-load the task message.** When calling \`mesh_enqueue_task\` or \`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.
|
|
31872
31873
|
- **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.
|
|
31873
31874
|
- **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.
|
|
31874
|
-
- **Handle failures
|
|
31875
|
+
- **Handle failures with context.** If a task fails, check \`mesh_task_history\` first to see if this task was attempted before and how it failed. Read the chat to understand why, then decide: retry on the same node, reassign to a different node, or escalate to the user.
|
|
31876
|
+
- **Check history before starting.** At the beginning of a coordination session, call \`mesh_task_history\` to understand what was previously delegated and its outcomes. This prevents duplicate work and informs recovery decisions.
|
|
31875
31877
|
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
31876
31878
|
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
31877
31879
|
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.
|
|
@@ -31894,6 +31896,7 @@ ${rules.join("\n")}`;
|
|
|
31894
31896
|
| \`mesh_launch_session\` | Start a new agent session on a node |
|
|
31895
31897
|
| \`mesh_send_task\` | Send a task (natural language) to a running agent |
|
|
31896
31898
|
| \`mesh_read_chat\` | Read an agent's recent messages to check progress |
|
|
31899
|
+
| \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
31897
31900
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
31898
31901
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
31899
31902
|
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
@@ -31904,18 +31907,371 @@ ${rules.join("\n")}`;
|
|
|
31904
31907
|
Before doing any coordinator work, confirm that the actual callable tool list includes \`mesh_status\` and the other \`mesh_*\` tools from the table above. If this Repo Mesh coordinator prompt is present but the callable \`mesh_*\` tools are missing, the MCP server/tool manifest is stale or not injected yet. Do not substitute terminal/file/git tools, do not inspect or edit the repository directly, and do not continue as a non-mesh local coding agent. Stop immediately and tell the user to run \`/reload-mcp\` or start a fresh coordinator session so ADHDev can reconnect \`adhdev-mesh\`.`;
|
|
31905
31908
|
WORKFLOW_SECTION = `## Orchestration Workflow
|
|
31906
31909
|
|
|
31907
|
-
1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
|
|
31908
|
-
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
|
|
31909
|
-
3. **Delegate** \u2014
|
|
31910
|
-
a.
|
|
31911
|
-
b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
31912
|
-
c.
|
|
31913
|
-
d.
|
|
31914
|
-
4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly
|
|
31910
|
+
1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available. Check \`mesh_task_history\` to understand what has already been done in this mesh \u2014 previous delegations, completions, and failures.
|
|
31911
|
+
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist. If \`mesh_task_history\` shows a recent failure for a task, decide whether to retry or reassign.
|
|
31912
|
+
3. **Queue / Delegate** \u2014 The Mesh uses an autonomous pull-based Work Queue:
|
|
31913
|
+
a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
|
|
31914
|
+
b. **Node Preparation**: Call \`mesh_launch_session\` to ensure enough agent sessions are active to handle the queue. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
31915
|
+
c. **Targeted Tasks**: Use \`mesh_send_task\` only when you need to bypass the queue and force a specific node to execute a task immediately.
|
|
31916
|
+
d. Always provide 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.
|
|
31917
|
+
4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly. Use \`mesh_view_queue\` to see the status of all pending, assigned, completed, and failed tasks. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal. Handle approvals via \`mesh_approve\`.
|
|
31915
31918
|
5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
31916
31919
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
31917
31920
|
7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
31918
|
-
8. **Report** \u2014 Summarize what was done, what changed, and any issues
|
|
31921
|
+
8. **Report** \u2014 Summarize what was done, what changed, and any issues.
|
|
31922
|
+
|
|
31923
|
+
## Failure Recovery
|
|
31924
|
+
|
|
31925
|
+
When a node agent stops unexpectedly, the daemon automatically enriches the system message with **Recovery Context** that includes:
|
|
31926
|
+
- The number of consecutive failures on that node
|
|
31927
|
+
- The original task message (if recorded in the ledger)
|
|
31928
|
+
- A recommendation: **retry**, **reassign**, or **escalate**
|
|
31929
|
+
|
|
31930
|
+
Follow these recovery rules:
|
|
31931
|
+
1. **If "Retry recommended"**: Re-launch the session on the same node (\`mesh_launch_session\`), then resend the original task (\`mesh_send_task\`). The system message includes the original task text.
|
|
31932
|
+
2. **If "Max retries exceeded"**: Do NOT retry on the same node. Either reassign the task to a different node, or inform the user that the task requires manual intervention.
|
|
31933
|
+
3. **If no recovery context**: The stop may be intentional (normal completion). Use \`mesh_read_chat\` once to verify, then move on.
|
|
31934
|
+
4. **Always record what happened**: After handling a failure, briefly note the outcome in your report to the user.`;
|
|
31935
|
+
}
|
|
31936
|
+
});
|
|
31937
|
+
var mesh_ledger_exports = {};
|
|
31938
|
+
__export2(mesh_ledger_exports, {
|
|
31939
|
+
appendLedgerEntry: () => appendLedgerEntry,
|
|
31940
|
+
appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
|
|
31941
|
+
getLedgerDir: () => getLedgerDir,
|
|
31942
|
+
getLedgerSummary: () => getLedgerSummary,
|
|
31943
|
+
getSessionRecoveryContext: () => getSessionRecoveryContext,
|
|
31944
|
+
meshLedgerEvents: () => meshLedgerEvents,
|
|
31945
|
+
readLedgerEntries: () => readLedgerEntries
|
|
31946
|
+
});
|
|
31947
|
+
function getLedgerDir() {
|
|
31948
|
+
const dir = (0, import_path3.join)(getConfigDir(), LEDGER_DIR_NAME);
|
|
31949
|
+
if (!(0, import_fs3.existsSync)(dir)) {
|
|
31950
|
+
(0, import_fs3.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
31951
|
+
}
|
|
31952
|
+
return dir;
|
|
31953
|
+
}
|
|
31954
|
+
function getLedgerPath(meshId) {
|
|
31955
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
31956
|
+
return (0, import_path3.join)(getLedgerDir(), `${safe}.jsonl`);
|
|
31957
|
+
}
|
|
31958
|
+
function getRotatedPath(meshId, index) {
|
|
31959
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
31960
|
+
return (0, import_path3.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
|
|
31961
|
+
}
|
|
31962
|
+
function appendLedgerEntry(meshId, partial2) {
|
|
31963
|
+
const entry = {
|
|
31964
|
+
id: (0, import_crypto4.randomUUID)(),
|
|
31965
|
+
meshId,
|
|
31966
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31967
|
+
...partial2
|
|
31968
|
+
};
|
|
31969
|
+
const filePath = getLedgerPath(meshId);
|
|
31970
|
+
if ((0, import_fs3.existsSync)(filePath)) {
|
|
31971
|
+
try {
|
|
31972
|
+
const stat2 = (0, import_fs3.statSync)(filePath);
|
|
31973
|
+
if (stat2.size >= MAX_FILE_SIZE_BYTES) {
|
|
31974
|
+
rotateLedgerFile(meshId, filePath);
|
|
31975
|
+
}
|
|
31976
|
+
} catch {
|
|
31977
|
+
}
|
|
31978
|
+
}
|
|
31979
|
+
try {
|
|
31980
|
+
const line = JSON.stringify(entry) + "\n";
|
|
31981
|
+
(0, import_fs3.appendFileSync)(filePath, line, { encoding: "utf-8", mode: 384 });
|
|
31982
|
+
meshLedgerEvents.emit("append", meshId, entry);
|
|
31983
|
+
return entry;
|
|
31984
|
+
} catch (e) {
|
|
31985
|
+
throw new Error(`Failed to append to ledger for mesh ${meshId}: ${e.message}`);
|
|
31986
|
+
}
|
|
31987
|
+
}
|
|
31988
|
+
function appendRemoteLedgerEntries(meshId, entries) {
|
|
31989
|
+
if (entries.length === 0) return;
|
|
31990
|
+
const ledgerPath = getLedgerPath(meshId);
|
|
31991
|
+
const existing = new Set(readLedgerEntries(meshId).map((e) => e.id));
|
|
31992
|
+
const newEntries = entries.filter((e) => !existing.has(e.id));
|
|
31993
|
+
if (newEntries.length === 0) return;
|
|
31994
|
+
try {
|
|
31995
|
+
const lines = newEntries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
31996
|
+
(0, import_fs3.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
|
|
31997
|
+
} catch (e) {
|
|
31998
|
+
throw new Error(`Failed to append remote ledger entries for mesh ${meshId}: ${e.message}`);
|
|
31999
|
+
}
|
|
32000
|
+
}
|
|
32001
|
+
function readLedgerEntries(meshId, opts) {
|
|
32002
|
+
const filePath = getLedgerPath(meshId);
|
|
32003
|
+
if (!(0, import_fs3.existsSync)(filePath)) return [];
|
|
32004
|
+
let content;
|
|
32005
|
+
try {
|
|
32006
|
+
content = (0, import_fs3.readFileSync)(filePath, "utf-8");
|
|
32007
|
+
} catch {
|
|
32008
|
+
return [];
|
|
32009
|
+
}
|
|
32010
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
32011
|
+
let entries = [];
|
|
32012
|
+
for (const line of lines) {
|
|
32013
|
+
try {
|
|
32014
|
+
const entry = JSON.parse(line);
|
|
32015
|
+
if (!entry.id || !entry.kind) continue;
|
|
32016
|
+
entries.push(entry);
|
|
32017
|
+
} catch {
|
|
32018
|
+
}
|
|
32019
|
+
}
|
|
32020
|
+
if (opts?.since) {
|
|
32021
|
+
const sinceDate = new Date(opts.since).getTime();
|
|
32022
|
+
if (!isNaN(sinceDate)) {
|
|
32023
|
+
entries = entries.filter((e) => new Date(e.timestamp).getTime() >= sinceDate);
|
|
32024
|
+
}
|
|
32025
|
+
}
|
|
32026
|
+
if (opts?.kind?.length) {
|
|
32027
|
+
const kindSet = new Set(opts.kind);
|
|
32028
|
+
entries = entries.filter((e) => kindSet.has(e.kind));
|
|
32029
|
+
}
|
|
32030
|
+
if (opts?.tail && opts.tail > 0 && entries.length > opts.tail) {
|
|
32031
|
+
entries = entries.slice(-opts.tail);
|
|
32032
|
+
}
|
|
32033
|
+
return entries;
|
|
32034
|
+
}
|
|
32035
|
+
function getLedgerSummary(meshId) {
|
|
32036
|
+
const entries = readLedgerEntries(meshId);
|
|
32037
|
+
const now = Date.now();
|
|
32038
|
+
const recentFailureCutoff = now - RECENT_FAILURE_WINDOW_MS;
|
|
32039
|
+
const summary = {
|
|
32040
|
+
meshId,
|
|
32041
|
+
totalEntries: entries.length,
|
|
32042
|
+
taskDispatched: 0,
|
|
32043
|
+
taskCompleted: 0,
|
|
32044
|
+
taskFailed: 0,
|
|
32045
|
+
taskStalled: 0,
|
|
32046
|
+
sessionLaunched: 0,
|
|
32047
|
+
checkpointCreated: 0,
|
|
32048
|
+
lastActivityAt: null,
|
|
32049
|
+
recentFailures: 0
|
|
32050
|
+
};
|
|
32051
|
+
for (const entry of entries) {
|
|
32052
|
+
switch (entry.kind) {
|
|
32053
|
+
case "task_dispatched":
|
|
32054
|
+
summary.taskDispatched++;
|
|
32055
|
+
break;
|
|
32056
|
+
case "task_completed":
|
|
32057
|
+
summary.taskCompleted++;
|
|
32058
|
+
break;
|
|
32059
|
+
case "task_failed": {
|
|
32060
|
+
summary.taskFailed++;
|
|
32061
|
+
if (new Date(entry.timestamp).getTime() >= recentFailureCutoff) {
|
|
32062
|
+
summary.recentFailures++;
|
|
32063
|
+
}
|
|
32064
|
+
break;
|
|
32065
|
+
}
|
|
32066
|
+
case "task_stalled":
|
|
32067
|
+
summary.taskStalled++;
|
|
32068
|
+
break;
|
|
32069
|
+
case "session_launched":
|
|
32070
|
+
summary.sessionLaunched++;
|
|
32071
|
+
break;
|
|
32072
|
+
case "checkpoint_created":
|
|
32073
|
+
summary.checkpointCreated++;
|
|
32074
|
+
break;
|
|
32075
|
+
}
|
|
32076
|
+
}
|
|
32077
|
+
if (entries.length > 0) {
|
|
32078
|
+
summary.lastActivityAt = entries[entries.length - 1].timestamp;
|
|
32079
|
+
}
|
|
32080
|
+
return summary;
|
|
32081
|
+
}
|
|
32082
|
+
function getSessionRecoveryContext(meshId, opts) {
|
|
32083
|
+
const maxRetries = opts.maxRetries ?? 1;
|
|
32084
|
+
const entries = readLedgerEntries(meshId);
|
|
32085
|
+
let lastDispatch = null;
|
|
32086
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
32087
|
+
const e = entries[i];
|
|
32088
|
+
if (e.kind !== "task_dispatched") continue;
|
|
32089
|
+
if (opts.sessionId && e.sessionId === opts.sessionId) {
|
|
32090
|
+
lastDispatch = e;
|
|
32091
|
+
break;
|
|
32092
|
+
}
|
|
32093
|
+
if (opts.nodeId && e.nodeId === opts.nodeId) {
|
|
32094
|
+
lastDispatch = e;
|
|
32095
|
+
break;
|
|
32096
|
+
}
|
|
32097
|
+
}
|
|
32098
|
+
const lastTaskMessage = typeof lastDispatch?.payload?.message === "string" ? lastDispatch.payload.message : null;
|
|
32099
|
+
const now = Date.now();
|
|
32100
|
+
const recentWindow = now - RECENT_FAILURE_WINDOW_MS;
|
|
32101
|
+
let consecutiveNodeFailures = 0;
|
|
32102
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
32103
|
+
const e = entries[i];
|
|
32104
|
+
if (new Date(e.timestamp).getTime() < recentWindow) break;
|
|
32105
|
+
if (opts.nodeId && e.nodeId !== opts.nodeId) continue;
|
|
32106
|
+
if (e.kind === "task_failed") {
|
|
32107
|
+
consecutiveNodeFailures++;
|
|
32108
|
+
} else if (e.kind === "task_completed" || e.kind === "task_dispatched") {
|
|
32109
|
+
break;
|
|
32110
|
+
}
|
|
32111
|
+
}
|
|
32112
|
+
let taskAttemptCount = 0;
|
|
32113
|
+
if (lastTaskMessage) {
|
|
32114
|
+
const prefix = lastTaskMessage.slice(0, 200);
|
|
32115
|
+
for (const e of entries) {
|
|
32116
|
+
if (e.kind === "task_dispatched" && typeof e.payload?.message === "string") {
|
|
32117
|
+
if (e.payload.message.startsWith(prefix)) {
|
|
32118
|
+
taskAttemptCount++;
|
|
32119
|
+
}
|
|
32120
|
+
}
|
|
32121
|
+
}
|
|
32122
|
+
}
|
|
32123
|
+
const retryRecommended = consecutiveNodeFailures <= maxRetries;
|
|
32124
|
+
let advice;
|
|
32125
|
+
if (consecutiveNodeFailures === 0) {
|
|
32126
|
+
advice = "No recent failures detected. This may be a normal stop.";
|
|
32127
|
+
} else if (retryRecommended) {
|
|
32128
|
+
const remaining = maxRetries - consecutiveNodeFailures + 1;
|
|
32129
|
+
advice = `Retry recommended (${consecutiveNodeFailures}/${maxRetries + 1} attempts used, ${remaining} remaining). ` + (lastTaskMessage ? `Re-launch the session and resend the original task.` : `Re-launch the session. Original task message not found in ledger.`);
|
|
32130
|
+
} else {
|
|
32131
|
+
advice = `Max retries exceeded (${consecutiveNodeFailures} consecutive failures). Consider: (1) reassigning to a different node, (2) simplifying the task, or (3) escalating to the user.`;
|
|
32132
|
+
}
|
|
32133
|
+
return {
|
|
32134
|
+
lastTaskMessage,
|
|
32135
|
+
failedNodeId: opts.nodeId || null,
|
|
32136
|
+
failedSessionId: opts.sessionId || null,
|
|
32137
|
+
failedProviderType: null,
|
|
32138
|
+
// filled by caller if available
|
|
32139
|
+
consecutiveNodeFailures,
|
|
32140
|
+
taskAttemptCount,
|
|
32141
|
+
retryRecommended,
|
|
32142
|
+
advice
|
|
32143
|
+
};
|
|
32144
|
+
}
|
|
32145
|
+
function rotateLedgerFile(meshId, currentPath) {
|
|
32146
|
+
let index = 1;
|
|
32147
|
+
while ((0, import_fs3.existsSync)(getRotatedPath(meshId, index))) {
|
|
32148
|
+
index++;
|
|
32149
|
+
if (index > 10) break;
|
|
32150
|
+
}
|
|
32151
|
+
if (index > 10) index = 10;
|
|
32152
|
+
try {
|
|
32153
|
+
(0, import_fs3.renameSync)(currentPath, getRotatedPath(meshId, index));
|
|
32154
|
+
} catch {
|
|
32155
|
+
}
|
|
32156
|
+
}
|
|
32157
|
+
var import_fs3;
|
|
32158
|
+
var import_path3;
|
|
32159
|
+
var import_crypto4;
|
|
32160
|
+
var import_events;
|
|
32161
|
+
var LEDGER_DIR_NAME;
|
|
32162
|
+
var MAX_FILE_SIZE_BYTES;
|
|
32163
|
+
var RECENT_FAILURE_WINDOW_MS;
|
|
32164
|
+
var meshLedgerEvents;
|
|
32165
|
+
var init_mesh_ledger = __esm2({
|
|
32166
|
+
"src/mesh/mesh-ledger.ts"() {
|
|
32167
|
+
"use strict";
|
|
32168
|
+
import_fs3 = require("fs");
|
|
32169
|
+
import_path3 = require("path");
|
|
32170
|
+
import_crypto4 = require("crypto");
|
|
32171
|
+
init_config();
|
|
32172
|
+
import_events = require("events");
|
|
32173
|
+
LEDGER_DIR_NAME = "mesh-ledger";
|
|
32174
|
+
MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
32175
|
+
RECENT_FAILURE_WINDOW_MS = 30 * 60 * 1e3;
|
|
32176
|
+
meshLedgerEvents = new import_events.EventEmitter();
|
|
32177
|
+
}
|
|
32178
|
+
});
|
|
32179
|
+
function getQueuePath(meshId) {
|
|
32180
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
32181
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
|
|
32182
|
+
}
|
|
32183
|
+
function readQueue(meshId) {
|
|
32184
|
+
const path28 = getQueuePath(meshId);
|
|
32185
|
+
if (!(0, import_fs4.existsSync)(path28)) return [];
|
|
32186
|
+
try {
|
|
32187
|
+
const content = (0, import_fs4.readFileSync)(path28, "utf-8");
|
|
32188
|
+
return JSON.parse(content);
|
|
32189
|
+
} catch {
|
|
32190
|
+
return [];
|
|
32191
|
+
}
|
|
32192
|
+
}
|
|
32193
|
+
function writeQueue(meshId, queue) {
|
|
32194
|
+
const path28 = getQueuePath(meshId);
|
|
32195
|
+
(0, import_fs4.writeFileSync)(path28, JSON.stringify(queue, null, 2), "utf-8");
|
|
32196
|
+
}
|
|
32197
|
+
function enqueueTask(meshId, message, opts) {
|
|
32198
|
+
const queue = readQueue(meshId);
|
|
32199
|
+
const entry = {
|
|
32200
|
+
id: (0, import_crypto5.randomUUID)(),
|
|
32201
|
+
meshId,
|
|
32202
|
+
message,
|
|
32203
|
+
status: "pending",
|
|
32204
|
+
targetNodeId: opts?.targetNodeId,
|
|
32205
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32206
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
32207
|
+
};
|
|
32208
|
+
queue.push(entry);
|
|
32209
|
+
writeQueue(meshId, queue);
|
|
32210
|
+
return entry;
|
|
32211
|
+
}
|
|
32212
|
+
function getQueue(meshId, opts) {
|
|
32213
|
+
let queue = readQueue(meshId);
|
|
32214
|
+
if (opts?.status?.length) {
|
|
32215
|
+
const statuses = new Set(opts.status);
|
|
32216
|
+
queue = queue.filter((q2) => statuses.has(q2.status));
|
|
32217
|
+
}
|
|
32218
|
+
return queue;
|
|
32219
|
+
}
|
|
32220
|
+
function claimNextTask(meshId, nodeId, sessionId) {
|
|
32221
|
+
const queue = readQueue(meshId);
|
|
32222
|
+
let targetIdx = queue.findIndex((q2) => q2.status === "pending" && q2.targetNodeId === nodeId);
|
|
32223
|
+
if (targetIdx === -1) {
|
|
32224
|
+
targetIdx = queue.findIndex((q2) => q2.status === "pending" && !q2.targetNodeId);
|
|
32225
|
+
}
|
|
32226
|
+
if (targetIdx === -1) return null;
|
|
32227
|
+
const entry = queue[targetIdx];
|
|
32228
|
+
entry.status = "assigned";
|
|
32229
|
+
entry.assignedNodeId = nodeId;
|
|
32230
|
+
entry.assignedSessionId = sessionId;
|
|
32231
|
+
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
32232
|
+
writeQueue(meshId, queue);
|
|
32233
|
+
return entry;
|
|
32234
|
+
}
|
|
32235
|
+
function updateTaskStatus(meshId, taskId, status) {
|
|
32236
|
+
const queue = readQueue(meshId);
|
|
32237
|
+
const idx = queue.findIndex((q2) => q2.id === taskId);
|
|
32238
|
+
if (idx === -1) return null;
|
|
32239
|
+
queue[idx].status = status;
|
|
32240
|
+
queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
32241
|
+
writeQueue(meshId, queue);
|
|
32242
|
+
return queue[idx];
|
|
32243
|
+
}
|
|
32244
|
+
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
32245
|
+
const queue = readQueue(meshId);
|
|
32246
|
+
for (let i = queue.length - 1; i >= 0; i--) {
|
|
32247
|
+
if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
|
|
32248
|
+
queue[i].status = status;
|
|
32249
|
+
queue[i].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
32250
|
+
writeQueue(meshId, queue);
|
|
32251
|
+
return queue[i];
|
|
32252
|
+
}
|
|
32253
|
+
}
|
|
32254
|
+
return null;
|
|
32255
|
+
}
|
|
32256
|
+
function getMeshQueueStats(meshId) {
|
|
32257
|
+
const queue = readQueue(meshId);
|
|
32258
|
+
return {
|
|
32259
|
+
pending: queue.filter((q2) => q2.status === "pending").length,
|
|
32260
|
+
assigned: queue.filter((q2) => q2.status === "assigned").length,
|
|
32261
|
+
completed: queue.filter((q2) => q2.status === "completed").length,
|
|
32262
|
+
failed: queue.filter((q2) => q2.status === "failed").length
|
|
32263
|
+
};
|
|
32264
|
+
}
|
|
32265
|
+
var import_fs4;
|
|
32266
|
+
var import_path4;
|
|
32267
|
+
var import_crypto5;
|
|
32268
|
+
var init_mesh_work_queue = __esm2({
|
|
32269
|
+
"src/mesh/mesh-work-queue.ts"() {
|
|
32270
|
+
"use strict";
|
|
32271
|
+
import_fs4 = require("fs");
|
|
32272
|
+
import_path4 = require("path");
|
|
32273
|
+
import_crypto5 = require("crypto");
|
|
32274
|
+
init_mesh_ledger();
|
|
31919
32275
|
}
|
|
31920
32276
|
});
|
|
31921
32277
|
function setLogLevel(level) {
|
|
@@ -31932,13 +32288,13 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
31932
32288
|
return LOG_DIR;
|
|
31933
32289
|
}
|
|
31934
32290
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
31935
|
-
return
|
|
32291
|
+
return path8.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
31936
32292
|
}
|
|
31937
32293
|
function checkDateRotation() {
|
|
31938
32294
|
const today = getDateStr();
|
|
31939
32295
|
if (today !== currentDate) {
|
|
31940
32296
|
currentDate = today;
|
|
31941
|
-
currentLogFile =
|
|
32297
|
+
currentLogFile = path8.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
31942
32298
|
cleanOldLogs();
|
|
31943
32299
|
}
|
|
31944
32300
|
}
|
|
@@ -31952,7 +32308,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
31952
32308
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
31953
32309
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
31954
32310
|
try {
|
|
31955
|
-
fs22.unlinkSync(
|
|
32311
|
+
fs22.unlinkSync(path8.join(LOG_DIR, file2));
|
|
31956
32312
|
} catch {
|
|
31957
32313
|
}
|
|
31958
32314
|
}
|
|
@@ -32069,8 +32425,8 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
32069
32425
|
writeToFile(`Log level: ${currentLevel}`);
|
|
32070
32426
|
}
|
|
32071
32427
|
var fs22;
|
|
32072
|
-
var
|
|
32073
|
-
var
|
|
32428
|
+
var path8;
|
|
32429
|
+
var os22;
|
|
32074
32430
|
var LEVEL_NUM;
|
|
32075
32431
|
var LEVEL_LABEL;
|
|
32076
32432
|
var currentLevel;
|
|
@@ -32092,12 +32448,12 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
32092
32448
|
"src/logging/logger.ts"() {
|
|
32093
32449
|
"use strict";
|
|
32094
32450
|
fs22 = __toESM2(require("fs"));
|
|
32095
|
-
|
|
32096
|
-
|
|
32451
|
+
path8 = __toESM2(require("path"));
|
|
32452
|
+
os22 = __toESM2(require("os"));
|
|
32097
32453
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
32098
32454
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
32099
32455
|
currentLevel = "info";
|
|
32100
|
-
LOG_DIR = process.platform === "win32" ?
|
|
32456
|
+
LOG_DIR = process.platform === "win32" ? path8.join(process.env.LOCALAPPDATA || process.env.APPDATA || path8.join(os22.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path8.join(os22.homedir(), "Library", "Logs", "adhdev") : path8.join(os22.homedir(), ".local", "share", "adhdev", "logs");
|
|
32101
32457
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
32102
32458
|
MAX_LOG_DAYS = 7;
|
|
32103
32459
|
try {
|
|
@@ -32105,16 +32461,16 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
32105
32461
|
} catch {
|
|
32106
32462
|
}
|
|
32107
32463
|
currentDate = getDateStr();
|
|
32108
|
-
currentLogFile =
|
|
32464
|
+
currentLogFile = path8.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
32109
32465
|
cleanOldLogs();
|
|
32110
32466
|
try {
|
|
32111
|
-
const oldLog =
|
|
32467
|
+
const oldLog = path8.join(LOG_DIR, "daemon.log");
|
|
32112
32468
|
if (fs22.existsSync(oldLog)) {
|
|
32113
32469
|
const stat2 = fs22.statSync(oldLog);
|
|
32114
32470
|
const oldDate = stat2.mtime.toISOString().slice(0, 10);
|
|
32115
|
-
fs22.renameSync(oldLog,
|
|
32471
|
+
fs22.renameSync(oldLog, path8.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
32116
32472
|
}
|
|
32117
|
-
const oldLogBackup =
|
|
32473
|
+
const oldLogBackup = path8.join(LOG_DIR, "daemon.log.old");
|
|
32118
32474
|
if (fs22.existsSync(oldLogBackup)) {
|
|
32119
32475
|
fs22.unlinkSync(oldLogBackup);
|
|
32120
32476
|
}
|
|
@@ -32146,7 +32502,314 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
32146
32502
|
}
|
|
32147
32503
|
};
|
|
32148
32504
|
interceptorInstalled = false;
|
|
32149
|
-
LOG_PATH =
|
|
32505
|
+
LOG_PATH = path8.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
32506
|
+
}
|
|
32507
|
+
});
|
|
32508
|
+
var mesh_events_exports = {};
|
|
32509
|
+
__export2(mesh_events_exports, {
|
|
32510
|
+
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
32511
|
+
handleMeshForwardEvent: () => handleMeshForwardEvent,
|
|
32512
|
+
setupMeshEventForwarding: () => setupMeshEventForwarding,
|
|
32513
|
+
triggerMeshQueue: () => triggerMeshQueue,
|
|
32514
|
+
tryAssignQueueTask: () => tryAssignQueueTask
|
|
32515
|
+
});
|
|
32516
|
+
function drainPendingMeshCoordinatorEvents() {
|
|
32517
|
+
return pendingMeshCoordinatorEvents.splice(0);
|
|
32518
|
+
}
|
|
32519
|
+
function readNonEmptyString(value) {
|
|
32520
|
+
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
32521
|
+
}
|
|
32522
|
+
function isMeshCoordinatorEvent(eventName) {
|
|
32523
|
+
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
32524
|
+
}
|
|
32525
|
+
function formatCompletionMetadata(event) {
|
|
32526
|
+
const parts = [
|
|
32527
|
+
readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
|
|
32528
|
+
readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
|
|
32529
|
+
readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
|
|
32530
|
+
].filter(Boolean);
|
|
32531
|
+
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
32532
|
+
}
|
|
32533
|
+
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
32534
|
+
const task = claimNextTask(meshId, nodeId, sessionId);
|
|
32535
|
+
if (!task) return false;
|
|
32536
|
+
LOG2.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
|
|
32537
|
+
components.cliManager.handleCliCommand("agent_command", {
|
|
32538
|
+
targetSessionId: sessionId,
|
|
32539
|
+
cliType: providerType,
|
|
32540
|
+
action: "send_chat",
|
|
32541
|
+
input: task.message
|
|
32542
|
+
}).catch((e) => {
|
|
32543
|
+
LOG2.error("MeshQueue", `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
|
|
32544
|
+
});
|
|
32545
|
+
return true;
|
|
32546
|
+
}
|
|
32547
|
+
function triggerMeshQueue(components, meshId) {
|
|
32548
|
+
const mesh = getMesh(meshId);
|
|
32549
|
+
if (!mesh) return;
|
|
32550
|
+
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
32551
|
+
for (const inst of cliInstances) {
|
|
32552
|
+
const state = inst.getState();
|
|
32553
|
+
const settings = state.settings || {};
|
|
32554
|
+
const instMeshId = readNonEmptyString(settings.meshNodeFor);
|
|
32555
|
+
if (instMeshId !== meshId && !settings.launchedByCoordinator) continue;
|
|
32556
|
+
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
32557
|
+
if (!nodeId) continue;
|
|
32558
|
+
if (state.status !== "idle" && state.status !== "stopped" && state.activeChat?.status !== "waiting_input") continue;
|
|
32559
|
+
const sessionId = state.instanceId;
|
|
32560
|
+
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
32561
|
+
if (providerType) {
|
|
32562
|
+
tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
|
|
32563
|
+
}
|
|
32564
|
+
}
|
|
32565
|
+
}
|
|
32566
|
+
function buildMeshSystemMessage(args) {
|
|
32567
|
+
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
32568
|
+
if (args.event === "agent:generating_completed") {
|
|
32569
|
+
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.`;
|
|
32570
|
+
}
|
|
32571
|
+
if (args.event === "agent:waiting_approval") {
|
|
32572
|
+
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
32573
|
+
}
|
|
32574
|
+
if (args.event === "agent:stopped") {
|
|
32575
|
+
const rc = args.recoveryContext;
|
|
32576
|
+
if (rc && rc.consecutiveNodeFailures > 0) {
|
|
32577
|
+
const parts = [
|
|
32578
|
+
`[System] ${args.nodeLabel} has stopped unexpectedly${metadata}.`,
|
|
32579
|
+
`
|
|
32580
|
+
|
|
32581
|
+
**Recovery Context:**`,
|
|
32582
|
+
`- Consecutive failures on this node: ${rc.consecutiveNodeFailures}`,
|
|
32583
|
+
rc.taskAttemptCount > 0 ? `- This task has been attempted ${rc.taskAttemptCount} time(s)` : "",
|
|
32584
|
+
`- Recommendation: ${rc.advice}`
|
|
32585
|
+
];
|
|
32586
|
+
if (rc.retryRecommended && rc.lastTaskMessage) {
|
|
32587
|
+
parts.push(
|
|
32588
|
+
`
|
|
32589
|
+
|
|
32590
|
+
**Original task to retry:**`,
|
|
32591
|
+
`> ${rc.lastTaskMessage.length > 300 ? rc.lastTaskMessage.slice(0, 300) + "..." : rc.lastTaskMessage}`,
|
|
32592
|
+
`
|
|
32593
|
+
To retry: call \`mesh_launch_session\` for this node, then \`mesh_send_task\` with the original task.`
|
|
32594
|
+
);
|
|
32595
|
+
} else if (!rc.retryRecommended) {
|
|
32596
|
+
parts.push(
|
|
32597
|
+
`
|
|
32598
|
+
Do NOT retry on this node. Consider reassigning to a different node or asking the user for guidance.`
|
|
32599
|
+
);
|
|
32600
|
+
}
|
|
32601
|
+
return parts.filter(Boolean).join("\n");
|
|
32602
|
+
}
|
|
32603
|
+
return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
|
|
32604
|
+
}
|
|
32605
|
+
if (args.event === "monitor:long_generating") {
|
|
32606
|
+
return `[System] ${args.nodeLabel} has been generating for a long time${metadata}. Use mesh_read_chat once for a status check, but do not poll repeatedly.`;
|
|
32607
|
+
}
|
|
32608
|
+
return "";
|
|
32609
|
+
}
|
|
32610
|
+
function injectMeshSystemMessage(components, args) {
|
|
32611
|
+
if (args.event === "agent:generating_completed") {
|
|
32612
|
+
const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
|
|
32613
|
+
const nodeId = readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
32614
|
+
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
32615
|
+
if (sessionId) {
|
|
32616
|
+
updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
32617
|
+
if (nodeId && providerType) {
|
|
32618
|
+
setTimeout(() => {
|
|
32619
|
+
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
32620
|
+
}, 500);
|
|
32621
|
+
}
|
|
32622
|
+
}
|
|
32623
|
+
} else if (args.event === "agent:stopped") {
|
|
32624
|
+
const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
|
|
32625
|
+
if (sessionId) {
|
|
32626
|
+
updateSessionTaskStatus(args.meshId, sessionId, "failed");
|
|
32627
|
+
}
|
|
32628
|
+
}
|
|
32629
|
+
const ledgerKind = EVENT_TO_LEDGER_KIND[args.event];
|
|
32630
|
+
if (ledgerKind) {
|
|
32631
|
+
try {
|
|
32632
|
+
appendLedgerEntry(args.meshId, {
|
|
32633
|
+
kind: ledgerKind,
|
|
32634
|
+
nodeId: readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
32635
|
+
sessionId: readNonEmptyString(args.metadataEvent.targetSessionId) || void 0,
|
|
32636
|
+
providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
|
|
32637
|
+
payload: {
|
|
32638
|
+
event: args.event,
|
|
32639
|
+
nodeLabel: args.nodeLabel,
|
|
32640
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0
|
|
32641
|
+
}
|
|
32642
|
+
});
|
|
32643
|
+
} catch (e) {
|
|
32644
|
+
LOG2.warn("MeshLedger", `Failed to record ${ledgerKind}: ${e?.message || e}`);
|
|
32645
|
+
}
|
|
32646
|
+
}
|
|
32647
|
+
let recoveryContext = null;
|
|
32648
|
+
if (args.event === "agent:stopped") {
|
|
32649
|
+
try {
|
|
32650
|
+
const mesh = getMesh(args.meshId);
|
|
32651
|
+
const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
|
|
32652
|
+
recoveryContext = getSessionRecoveryContext(args.meshId, {
|
|
32653
|
+
sessionId: readNonEmptyString(args.metadataEvent.targetSessionId) || void 0,
|
|
32654
|
+
nodeId: readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
32655
|
+
maxRetries
|
|
32656
|
+
});
|
|
32657
|
+
recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
|
|
32658
|
+
if (recoveryContext.retryRecommended && recoveryContext.consecutiveNodeFailures > 0) {
|
|
32659
|
+
appendLedgerEntry(args.meshId, {
|
|
32660
|
+
kind: "recovery_attempted",
|
|
32661
|
+
nodeId: recoveryContext.failedNodeId || void 0,
|
|
32662
|
+
sessionId: recoveryContext.failedSessionId || void 0,
|
|
32663
|
+
providerType: recoveryContext.failedProviderType || void 0,
|
|
32664
|
+
payload: {
|
|
32665
|
+
consecutiveFailures: recoveryContext.consecutiveNodeFailures,
|
|
32666
|
+
taskAttemptCount: recoveryContext.taskAttemptCount,
|
|
32667
|
+
retryRecommended: recoveryContext.retryRecommended,
|
|
32668
|
+
advice: recoveryContext.advice
|
|
32669
|
+
}
|
|
32670
|
+
});
|
|
32671
|
+
if (recoveryContext.lastTaskMessage && recoveryContext.failedNodeId && recoveryContext.failedProviderType) {
|
|
32672
|
+
const autoNodeId = recoveryContext.failedNodeId;
|
|
32673
|
+
try {
|
|
32674
|
+
const task = enqueueTask(args.meshId, recoveryContext.lastTaskMessage, {
|
|
32675
|
+
targetNodeId: autoNodeId
|
|
32676
|
+
});
|
|
32677
|
+
LOG2.info("MeshRecovery", `Auto-requeued failed task: ${task.id} for node ${autoNodeId}`);
|
|
32678
|
+
const node = mesh?.nodes.find((n) => n.id === autoNodeId);
|
|
32679
|
+
if (node) {
|
|
32680
|
+
components.cliManager.handleCliCommand("launch_cli", {
|
|
32681
|
+
cliType: recoveryContext.failedProviderType,
|
|
32682
|
+
dir: node.workspace,
|
|
32683
|
+
settings: {
|
|
32684
|
+
meshNodeFor: args.meshId,
|
|
32685
|
+
meshNodeId: node.id,
|
|
32686
|
+
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
32687
|
+
launchedByCoordinator: true
|
|
32688
|
+
}
|
|
32689
|
+
}).catch((e) => LOG2.error("MeshRecovery", `Failed to auto-relaunch session for ${node.id}: ${e?.message}`));
|
|
32690
|
+
}
|
|
32691
|
+
} catch (e) {
|
|
32692
|
+
LOG2.warn("MeshRecovery", `Failed to execute auto-recovery: ${e?.message}`);
|
|
32693
|
+
}
|
|
32694
|
+
}
|
|
32695
|
+
}
|
|
32696
|
+
LOG2.info("MeshRecovery", `Recovery context for ${args.nodeLabel}: ${recoveryContext.advice}`);
|
|
32697
|
+
} catch (e) {
|
|
32698
|
+
LOG2.warn("MeshRecovery", `Failed to build recovery context: ${e?.message || e}`);
|
|
32699
|
+
}
|
|
32700
|
+
}
|
|
32701
|
+
const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
32702
|
+
const instState = inst.getState();
|
|
32703
|
+
if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
|
|
32704
|
+
if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
|
|
32705
|
+
return true;
|
|
32706
|
+
});
|
|
32707
|
+
if (coordinatorInstances.length === 0) {
|
|
32708
|
+
if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
|
|
32709
|
+
pendingMeshCoordinatorEvents.push({
|
|
32710
|
+
event: args.event,
|
|
32711
|
+
meshId: args.meshId,
|
|
32712
|
+
nodeLabel: args.nodeLabel,
|
|
32713
|
+
metadataEvent: {
|
|
32714
|
+
...args.metadataEvent,
|
|
32715
|
+
...recoveryContext ? { recoveryContext } : {}
|
|
32716
|
+
},
|
|
32717
|
+
queuedAt: Date.now()
|
|
32718
|
+
});
|
|
32719
|
+
LOG2.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
32720
|
+
}
|
|
32721
|
+
return { success: true, forwarded: 0 };
|
|
32722
|
+
}
|
|
32723
|
+
const messageText = buildMeshSystemMessage({
|
|
32724
|
+
event: args.event,
|
|
32725
|
+
nodeLabel: args.nodeLabel,
|
|
32726
|
+
metadataEvent: args.metadataEvent,
|
|
32727
|
+
recoveryContext
|
|
32728
|
+
});
|
|
32729
|
+
if (!messageText) return { success: false, error: "unsupported mesh event" };
|
|
32730
|
+
for (const coord of coordinatorInstances) {
|
|
32731
|
+
const coordState = coord.getState();
|
|
32732
|
+
LOG2.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
32733
|
+
coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
|
|
32734
|
+
}
|
|
32735
|
+
return { success: true, forwarded: coordinatorInstances.length };
|
|
32736
|
+
}
|
|
32737
|
+
function handleMeshForwardEvent(components, payload) {
|
|
32738
|
+
const eventName = readNonEmptyString(payload.event);
|
|
32739
|
+
if (!isMeshCoordinatorEvent(eventName)) {
|
|
32740
|
+
return { success: false, error: "unsupported mesh event" };
|
|
32741
|
+
}
|
|
32742
|
+
const meshId = readNonEmptyString(payload.meshId);
|
|
32743
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
32744
|
+
const nodeId = readNonEmptyString(payload.nodeId);
|
|
32745
|
+
const workspace = readNonEmptyString(payload.workspace);
|
|
32746
|
+
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
32747
|
+
return injectMeshSystemMessage(components, {
|
|
32748
|
+
meshId,
|
|
32749
|
+
nodeLabel,
|
|
32750
|
+
event: eventName,
|
|
32751
|
+
metadataEvent: {
|
|
32752
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
32753
|
+
providerType: readNonEmptyString(payload.providerType),
|
|
32754
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
32755
|
+
}
|
|
32756
|
+
});
|
|
32757
|
+
}
|
|
32758
|
+
function setupMeshEventForwarding(components) {
|
|
32759
|
+
components.instanceManager.onEvent((event) => {
|
|
32760
|
+
if (!isMeshCoordinatorEvent(event.event)) return;
|
|
32761
|
+
const instanceId = readNonEmptyString(event.instanceId);
|
|
32762
|
+
if (!instanceId) return;
|
|
32763
|
+
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
32764
|
+
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
32765
|
+
const state = sourceInstance.getState();
|
|
32766
|
+
const workspace = readNonEmptyString(state.workspace);
|
|
32767
|
+
if (!workspace) return;
|
|
32768
|
+
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
32769
|
+
if (readNonEmptyString(settings.meshCoordinatorFor)) return;
|
|
32770
|
+
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
32771
|
+
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
32772
|
+
if (!isMeshDelegate) return;
|
|
32773
|
+
const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
32774
|
+
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
32775
|
+
if (!meshId) return;
|
|
32776
|
+
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
32777
|
+
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
32778
|
+
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
32779
|
+
injectMeshSystemMessage(components, {
|
|
32780
|
+
meshId,
|
|
32781
|
+
sourceInstanceId: instanceId,
|
|
32782
|
+
nodeLabel,
|
|
32783
|
+
event: event.event,
|
|
32784
|
+
metadataEvent: event
|
|
32785
|
+
});
|
|
32786
|
+
});
|
|
32787
|
+
}
|
|
32788
|
+
var MAX_PENDING_EVENTS;
|
|
32789
|
+
var pendingMeshCoordinatorEvents;
|
|
32790
|
+
var MESH_COORDINATOR_EVENTS;
|
|
32791
|
+
var EVENT_TO_LEDGER_KIND;
|
|
32792
|
+
var init_mesh_events = __esm2({
|
|
32793
|
+
"src/mesh/mesh-events.ts"() {
|
|
32794
|
+
"use strict";
|
|
32795
|
+
init_mesh_config();
|
|
32796
|
+
init_logger();
|
|
32797
|
+
init_mesh_ledger();
|
|
32798
|
+
init_mesh_work_queue();
|
|
32799
|
+
MAX_PENDING_EVENTS = 50;
|
|
32800
|
+
pendingMeshCoordinatorEvents = [];
|
|
32801
|
+
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
32802
|
+
"agent:generating_completed",
|
|
32803
|
+
"agent:waiting_approval",
|
|
32804
|
+
"agent:stopped",
|
|
32805
|
+
"monitor:long_generating"
|
|
32806
|
+
]);
|
|
32807
|
+
EVENT_TO_LEDGER_KIND = {
|
|
32808
|
+
"agent:generating_completed": "task_completed",
|
|
32809
|
+
"agent:waiting_approval": "task_approval_needed",
|
|
32810
|
+
"agent:stopped": "task_failed",
|
|
32811
|
+
"monitor:long_generating": "task_stalled"
|
|
32812
|
+
};
|
|
32150
32813
|
}
|
|
32151
32814
|
});
|
|
32152
32815
|
function normalizeCategories(categories) {
|
|
@@ -33251,6 +33914,8 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
33251
33914
|
statusHistory = [];
|
|
33252
33915
|
// ─── CLI Scripts (script-based parsing) ───
|
|
33253
33916
|
cliScripts;
|
|
33917
|
+
/** Per-session opaque state object created by cliScripts.createState(), reset on stop. */
|
|
33918
|
+
scriptState = null;
|
|
33254
33919
|
runtimeSettings = {};
|
|
33255
33920
|
/** Full accumulated rendered PTY transcript for parser/readback use */
|
|
33256
33921
|
accumulatedBuffer = "";
|
|
@@ -33432,6 +34097,7 @@ ${lastSnapshot}`;
|
|
|
33432
34097
|
this.cliScripts = scripts;
|
|
33433
34098
|
this.parsedStatusCache = null;
|
|
33434
34099
|
this.parseErrorMessage = null;
|
|
34100
|
+
this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
|
|
33435
34101
|
const scriptNames = listCliScriptNames(scripts);
|
|
33436
34102
|
LOG2.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
|
|
33437
34103
|
}
|
|
@@ -33549,6 +34215,7 @@ ${lastSnapshot}`;
|
|
|
33549
34215
|
this.ready = false;
|
|
33550
34216
|
this.startupParseGate = false;
|
|
33551
34217
|
this.spawnAt = 0;
|
|
34218
|
+
this.scriptState = null;
|
|
33552
34219
|
this.onStatusChange?.();
|
|
33553
34220
|
});
|
|
33554
34221
|
this.spawnAt = Date.now();
|
|
@@ -34322,7 +34989,7 @@ ${lastSnapshot}`;
|
|
|
34322
34989
|
scope: this.currentTurnScope,
|
|
34323
34990
|
runtimeSettings: this.runtimeSettings
|
|
34324
34991
|
});
|
|
34325
|
-
const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
34992
|
+
const session = this.cliScripts.parseSession(this.scriptState, { ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
34326
34993
|
this.parseErrorMessage = null;
|
|
34327
34994
|
return session && typeof session === "object" ? session : null;
|
|
34328
34995
|
} catch (e) {
|
|
@@ -34336,7 +35003,7 @@ ${lastSnapshot}`;
|
|
|
34336
35003
|
if (!this.cliScripts?.detectStatus) return null;
|
|
34337
35004
|
try {
|
|
34338
35005
|
const screenText = this.terminalScreen.getText();
|
|
34339
|
-
const status = this.cliScripts.detectStatus({
|
|
35006
|
+
const status = this.cliScripts.detectStatus(this.scriptState, {
|
|
34340
35007
|
tail: text.slice(-500),
|
|
34341
35008
|
screenText,
|
|
34342
35009
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -34355,7 +35022,7 @@ ${lastSnapshot}`;
|
|
|
34355
35022
|
try {
|
|
34356
35023
|
const screenText = this.terminalScreen.getText();
|
|
34357
35024
|
const buffer = screenText || this.accumulatedBuffer;
|
|
34358
|
-
return this.cliScripts.parseApproval({
|
|
35025
|
+
return this.cliScripts.parseApproval(this.scriptState, {
|
|
34359
35026
|
buffer,
|
|
34360
35027
|
screenText,
|
|
34361
35028
|
rawBuffer: this.accumulatedRawBuffer,
|
|
@@ -34463,7 +35130,7 @@ ${lastSnapshot}`;
|
|
|
34463
35130
|
scope: this.currentTurnScope,
|
|
34464
35131
|
runtimeSettings: this.runtimeSettings
|
|
34465
35132
|
});
|
|
34466
|
-
return await Promise.resolve(fn2({
|
|
35133
|
+
return await Promise.resolve(fn2(this.scriptState, {
|
|
34467
35134
|
...input,
|
|
34468
35135
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
34469
35136
|
}));
|
|
@@ -35254,6 +35921,7 @@ ${lastSnapshot}`;
|
|
|
35254
35921
|
TurnSnapshotTracker: () => TurnSnapshotTracker,
|
|
35255
35922
|
VersionArchive: () => VersionArchive,
|
|
35256
35923
|
addNode: () => addNode,
|
|
35924
|
+
appendLedgerEntry: () => appendLedgerEntry,
|
|
35257
35925
|
appendRecentActivity: () => appendRecentActivity,
|
|
35258
35926
|
buildAssistantChatMessage: () => buildAssistantChatMessage,
|
|
35259
35927
|
buildChatMessage: () => buildChatMessage,
|
|
@@ -35271,6 +35939,7 @@ ${lastSnapshot}`;
|
|
|
35271
35939
|
buildThoughtChatMessage: () => buildThoughtChatMessage,
|
|
35272
35940
|
buildToolChatMessage: () => buildToolChatMessage,
|
|
35273
35941
|
buildUserChatMessage: () => buildUserChatMessage,
|
|
35942
|
+
claimNextTask: () => claimNextTask,
|
|
35274
35943
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
35275
35944
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush2,
|
|
35276
35945
|
clearDebugTrace: () => clearDebugTrace,
|
|
@@ -35289,6 +35958,7 @@ ${lastSnapshot}`;
|
|
|
35289
35958
|
detectAllVersions: () => detectAllVersions,
|
|
35290
35959
|
detectCLIs: () => detectCLIs,
|
|
35291
35960
|
detectIDEs: () => detectIDEs,
|
|
35961
|
+
enqueueTask: () => enqueueTask,
|
|
35292
35962
|
ensureSessionHostReady: () => ensureSessionHostReady2,
|
|
35293
35963
|
execNpmCommandSync: () => execNpmCommandSync,
|
|
35294
35964
|
filterActivityChatMessages: () => filterActivityChatMessages,
|
|
@@ -35307,10 +35977,13 @@ ${lastSnapshot}`;
|
|
|
35307
35977
|
getGitFileDiff: () => getGitFileDiff,
|
|
35308
35978
|
getGitRepoStatus: () => getGitRepoStatus,
|
|
35309
35979
|
getHostMemorySnapshot: () => getHostMemorySnapshot,
|
|
35980
|
+
getLedgerDir: () => getLedgerDir,
|
|
35981
|
+
getLedgerSummary: () => getLedgerSummary,
|
|
35310
35982
|
getLogLevel: () => getLogLevel,
|
|
35311
35983
|
getMesh: () => getMesh,
|
|
35312
35984
|
getMeshByRepo: () => getMeshByRepo,
|
|
35313
35985
|
getNpmExecOptions: () => getNpmExecOptions,
|
|
35986
|
+
getQueue: () => getQueue,
|
|
35314
35987
|
getRecentActivity: () => getRecentActivity,
|
|
35315
35988
|
getRecentCommands: () => getRecentCommands,
|
|
35316
35989
|
getRecentDebugTrace: () => getRecentDebugTrace,
|
|
@@ -35318,6 +35991,7 @@ ${lastSnapshot}`;
|
|
|
35318
35991
|
getSavedProviderSessions: () => getSavedProviderSessions,
|
|
35319
35992
|
getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
|
|
35320
35993
|
getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
|
|
35994
|
+
getSessionRecoveryContext: () => getSessionRecoveryContext,
|
|
35321
35995
|
getWorkspaceState: () => getWorkspaceState2,
|
|
35322
35996
|
handleGitCommand: () => handleGitCommand,
|
|
35323
35997
|
hasCdpManager: () => hasCdpManager,
|
|
@@ -35371,6 +36045,7 @@ ${lastSnapshot}`;
|
|
|
35371
36045
|
prepareSessionModalUpdate: () => prepareSessionModalUpdate2,
|
|
35372
36046
|
probeCdpPort: () => probeCdpPort,
|
|
35373
36047
|
readChatHistory: () => readChatHistory,
|
|
36048
|
+
readLedgerEntries: () => readLedgerEntries,
|
|
35374
36049
|
recordDebugTrace: () => recordDebugTrace,
|
|
35375
36050
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
35376
36051
|
removeNode: () => removeNode,
|
|
@@ -35399,9 +36074,12 @@ ${lastSnapshot}`;
|
|
|
35399
36074
|
startDaemonDevSupport: () => startDaemonDevSupport2,
|
|
35400
36075
|
summarizeGitStatus: () => summarizeGitStatus,
|
|
35401
36076
|
syncMeshes: () => syncMeshes,
|
|
36077
|
+
triggerMeshQueue: () => triggerMeshQueue,
|
|
35402
36078
|
updateConfig: () => updateConfig,
|
|
35403
36079
|
updateMesh: () => updateMesh,
|
|
35404
36080
|
updateNode: () => updateNode,
|
|
36081
|
+
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
36082
|
+
updateTaskStatus: () => updateTaskStatus,
|
|
35405
36083
|
upsertSavedProviderSession: () => upsertSavedProviderSession
|
|
35406
36084
|
});
|
|
35407
36085
|
module2.exports = __toCommonJS2(index_exports);
|
|
@@ -37234,10 +37912,31 @@ ${lastSnapshot}`;
|
|
|
37234
37912
|
}
|
|
37235
37913
|
}
|
|
37236
37914
|
}
|
|
37915
|
+
if (transport.syncMeshLedger) {
|
|
37916
|
+
for (const local of localMeshes) {
|
|
37917
|
+
try {
|
|
37918
|
+
await syncMeshLedger(local.id, transport);
|
|
37919
|
+
} catch (e) {
|
|
37920
|
+
result.errors.push(`Ledger sync failed for "${local.name}": ${e.message}`);
|
|
37921
|
+
}
|
|
37922
|
+
}
|
|
37923
|
+
}
|
|
37237
37924
|
return result;
|
|
37238
37925
|
}
|
|
37239
|
-
|
|
37240
|
-
|
|
37926
|
+
async function syncMeshLedger(meshId, transport) {
|
|
37927
|
+
if (!transport.syncMeshLedger) return;
|
|
37928
|
+
const { readLedgerEntries: readLedgerEntries2, appendRemoteLedgerEntries: appendRemoteLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
37929
|
+
const localEntries = readLedgerEntries2(meshId);
|
|
37930
|
+
const res = await transport.syncMeshLedger(meshId, { newEntries: localEntries });
|
|
37931
|
+
if (res.missingEntries && res.missingEntries.length > 0) {
|
|
37932
|
+
appendRemoteLedgerEntries2(meshId, res.missingEntries);
|
|
37933
|
+
}
|
|
37934
|
+
}
|
|
37935
|
+
init_mesh_ledger();
|
|
37936
|
+
init_mesh_work_queue();
|
|
37937
|
+
init_mesh_events();
|
|
37938
|
+
var import_fs5 = require("fs");
|
|
37939
|
+
var import_path5 = require("path");
|
|
37241
37940
|
init_config();
|
|
37242
37941
|
var DEFAULT_STATE = {
|
|
37243
37942
|
recentActivity: [],
|
|
@@ -37251,7 +37950,7 @@ ${lastSnapshot}`;
|
|
|
37251
37950
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
37252
37951
|
}
|
|
37253
37952
|
function getStatePath() {
|
|
37254
|
-
return (0,
|
|
37953
|
+
return (0, import_path5.join)(getConfigDir(), "state.json");
|
|
37255
37954
|
}
|
|
37256
37955
|
function normalizeState(raw) {
|
|
37257
37956
|
const parsed = isPlainObject22(raw) ? raw : {};
|
|
@@ -37287,11 +37986,11 @@ ${lastSnapshot}`;
|
|
|
37287
37986
|
}
|
|
37288
37987
|
function loadState() {
|
|
37289
37988
|
const statePath = getStatePath();
|
|
37290
|
-
if (!(0,
|
|
37989
|
+
if (!(0, import_fs5.existsSync)(statePath)) {
|
|
37291
37990
|
return { ...DEFAULT_STATE };
|
|
37292
37991
|
}
|
|
37293
37992
|
try {
|
|
37294
|
-
const raw = (0,
|
|
37993
|
+
const raw = (0, import_fs5.readFileSync)(statePath, "utf-8");
|
|
37295
37994
|
return normalizeState(JSON.parse(raw));
|
|
37296
37995
|
} catch {
|
|
37297
37996
|
return { ...DEFAULT_STATE };
|
|
@@ -37300,15 +37999,15 @@ ${lastSnapshot}`;
|
|
|
37300
37999
|
function saveState(state) {
|
|
37301
38000
|
const statePath = getStatePath();
|
|
37302
38001
|
const normalized = normalizeState(state);
|
|
37303
|
-
(0,
|
|
38002
|
+
(0, import_fs5.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
37304
38003
|
}
|
|
37305
38004
|
function resetState() {
|
|
37306
38005
|
saveState({ ...DEFAULT_STATE });
|
|
37307
38006
|
}
|
|
37308
38007
|
var import_child_process = require("child_process");
|
|
37309
|
-
var
|
|
38008
|
+
var import_fs6 = require("fs");
|
|
37310
38009
|
var import_os22 = require("os");
|
|
37311
|
-
var
|
|
38010
|
+
var path9 = __toESM2(require("path"));
|
|
37312
38011
|
var BUILTIN_IDE_DEFINITIONS = [];
|
|
37313
38012
|
var registeredIDEs = /* @__PURE__ */ new Map();
|
|
37314
38013
|
function registerIDEDefinition(def) {
|
|
@@ -37327,10 +38026,10 @@ ${lastSnapshot}`;
|
|
|
37327
38026
|
function findCliCommand(command) {
|
|
37328
38027
|
const trimmed = String(command || "").trim();
|
|
37329
38028
|
if (!trimmed) return null;
|
|
37330
|
-
if (
|
|
37331
|
-
const candidate = trimmed.startsWith("~") ?
|
|
37332
|
-
const resolved =
|
|
37333
|
-
return (0,
|
|
38029
|
+
if (path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
38030
|
+
const candidate = trimmed.startsWith("~") ? path9.join((0, import_os22.homedir)(), trimmed.slice(1)) : trimmed;
|
|
38031
|
+
const resolved = path9.isAbsolute(candidate) ? candidate : path9.resolve(candidate);
|
|
38032
|
+
return (0, import_fs6.existsSync)(resolved) ? resolved : null;
|
|
37334
38033
|
}
|
|
37335
38034
|
try {
|
|
37336
38035
|
const result = (0, import_child_process.execSync)(
|
|
@@ -37357,13 +38056,13 @@ ${lastSnapshot}`;
|
|
|
37357
38056
|
function checkPathExists(paths) {
|
|
37358
38057
|
const home = (0, import_os22.homedir)();
|
|
37359
38058
|
for (const p of paths) {
|
|
37360
|
-
const normalized = p.startsWith("~") ?
|
|
38059
|
+
const normalized = p.startsWith("~") ? path9.join(home, p.slice(1)) : p;
|
|
37361
38060
|
if (normalized.includes("*")) {
|
|
37362
38061
|
const username = home.split(/[\\/]/).pop() || "";
|
|
37363
38062
|
const resolved = normalized.replace("*", username);
|
|
37364
|
-
if ((0,
|
|
38063
|
+
if ((0, import_fs6.existsSync)(resolved)) return resolved;
|
|
37365
38064
|
} else {
|
|
37366
|
-
if ((0,
|
|
38065
|
+
if ((0, import_fs6.existsSync)(normalized)) return normalized;
|
|
37367
38066
|
}
|
|
37368
38067
|
}
|
|
37369
38068
|
return null;
|
|
@@ -37377,7 +38076,7 @@ ${lastSnapshot}`;
|
|
|
37377
38076
|
let resolvedCli = cliPath;
|
|
37378
38077
|
if (!resolvedCli && appPath && os222 === "darwin") {
|
|
37379
38078
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
37380
|
-
if ((0,
|
|
38079
|
+
if ((0, import_fs6.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
37381
38080
|
}
|
|
37382
38081
|
if (!resolvedCli && appPath && os222 === "win32") {
|
|
37383
38082
|
const { dirname: dirname9 } = await import("path");
|
|
@@ -37390,7 +38089,7 @@ ${lastSnapshot}`;
|
|
|
37390
38089
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
37391
38090
|
];
|
|
37392
38091
|
for (const c of candidates) {
|
|
37393
|
-
if ((0,
|
|
38092
|
+
if ((0, import_fs6.existsSync)(c)) {
|
|
37394
38093
|
resolvedCli = c;
|
|
37395
38094
|
break;
|
|
37396
38095
|
}
|
|
@@ -37412,9 +38111,9 @@ ${lastSnapshot}`;
|
|
|
37412
38111
|
return results;
|
|
37413
38112
|
}
|
|
37414
38113
|
var import_child_process2 = require("child_process");
|
|
37415
|
-
var
|
|
37416
|
-
var
|
|
37417
|
-
var
|
|
38114
|
+
var os32 = __toESM2(require("os"));
|
|
38115
|
+
var path10 = __toESM2(require("path"));
|
|
38116
|
+
var import_fs7 = require("fs");
|
|
37418
38117
|
function parseVersion(raw) {
|
|
37419
38118
|
const match = raw.match(/v?(\d+\.\d+(?:\.\d+)?(?:-[a-zA-Z0-9.]+)?)/);
|
|
37420
38119
|
return match ? match[1] : raw.split("\n")[0].slice(0, 100);
|
|
@@ -37426,19 +38125,19 @@ ${lastSnapshot}`;
|
|
|
37426
38125
|
function expandHome(value) {
|
|
37427
38126
|
const trimmed = value.trim();
|
|
37428
38127
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
37429
|
-
return
|
|
38128
|
+
return path10.join(os32.homedir(), trimmed.slice(1));
|
|
37430
38129
|
}
|
|
37431
38130
|
function isExplicitCommandPath(command) {
|
|
37432
38131
|
const trimmed = command.trim();
|
|
37433
|
-
return
|
|
38132
|
+
return path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
37434
38133
|
}
|
|
37435
38134
|
function resolveCommandPath(command) {
|
|
37436
38135
|
const trimmed = command.trim();
|
|
37437
38136
|
if (!trimmed) return null;
|
|
37438
38137
|
if (isExplicitCommandPath(trimmed)) {
|
|
37439
38138
|
const expanded = expandHome(trimmed);
|
|
37440
|
-
const candidate =
|
|
37441
|
-
return (0,
|
|
38139
|
+
const candidate = path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
|
|
38140
|
+
return (0, import_fs7.existsSync)(candidate) ? candidate : null;
|
|
37442
38141
|
}
|
|
37443
38142
|
return null;
|
|
37444
38143
|
}
|
|
@@ -37459,7 +38158,7 @@ ${lastSnapshot}`;
|
|
|
37459
38158
|
});
|
|
37460
38159
|
}
|
|
37461
38160
|
async function detectCLIs(providerLoader, options) {
|
|
37462
|
-
const platform10 =
|
|
38161
|
+
const platform10 = os32.platform();
|
|
37463
38162
|
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
37464
38163
|
const includeVersion = options?.includeVersion !== false;
|
|
37465
38164
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
@@ -37503,7 +38202,7 @@ ${lastSnapshot}`;
|
|
|
37503
38202
|
const cliList = providerLoader.getCliDetectionList();
|
|
37504
38203
|
const target = cliList.find((c) => c.id === resolvedId);
|
|
37505
38204
|
if (target) {
|
|
37506
|
-
const platform10 =
|
|
38205
|
+
const platform10 = os32.platform();
|
|
37507
38206
|
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
37508
38207
|
try {
|
|
37509
38208
|
const explicitPath = resolveCommandPath(target.command);
|
|
@@ -37538,10 +38237,10 @@ ${lastSnapshot}`;
|
|
|
37538
38237
|
const all = await detectCLIs(providerLoader, options);
|
|
37539
38238
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
37540
38239
|
}
|
|
37541
|
-
var
|
|
38240
|
+
var os42 = __toESM2(require("os"));
|
|
37542
38241
|
var import_child_process3 = require("child_process");
|
|
37543
38242
|
function parseDarwinAvailableBytes(totalMem) {
|
|
37544
|
-
if (
|
|
38243
|
+
if (os42.platform() !== "darwin") return null;
|
|
37545
38244
|
try {
|
|
37546
38245
|
const out = (0, import_child_process3.execSync)("vm_stat", {
|
|
37547
38246
|
encoding: "utf-8",
|
|
@@ -37572,8 +38271,8 @@ ${lastSnapshot}`;
|
|
|
37572
38271
|
}
|
|
37573
38272
|
}
|
|
37574
38273
|
function getHostMemorySnapshot() {
|
|
37575
|
-
const totalMem =
|
|
37576
|
-
const freeMem =
|
|
38274
|
+
const totalMem = os42.totalmem();
|
|
38275
|
+
const freeMem = os42.freemem();
|
|
37577
38276
|
const darwinAvail = parseDarwinAvailableBytes(totalMem);
|
|
37578
38277
|
const availableMem = darwinAvail != null ? darwinAvail : freeMem;
|
|
37579
38278
|
return { totalMem, freeMem, availableMem };
|
|
@@ -42894,6 +43593,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
42894
43593
|
}
|
|
42895
43594
|
return normalized;
|
|
42896
43595
|
}
|
|
43596
|
+
init_mesh_work_queue();
|
|
42897
43597
|
var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
42898
43598
|
var VALID_INPUT_STRATEGIES = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
|
|
42899
43599
|
var TEXT_ONLY_MESSAGE_INPUT_SUPPORT = Object.freeze({
|
|
@@ -43116,6 +43816,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43116
43816
|
const workspace = state.workspace || null;
|
|
43117
43817
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
43118
43818
|
const title = activeChat?.title || state.name;
|
|
43819
|
+
const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
|
|
43820
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
43119
43821
|
return {
|
|
43120
43822
|
id: state.instanceId || state.type,
|
|
43121
43823
|
parentId: null,
|
|
@@ -43138,7 +43840,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43138
43840
|
errorMessage: state.errorMessage,
|
|
43139
43841
|
errorReason: state.errorReason,
|
|
43140
43842
|
lastUpdated: state.lastUpdated,
|
|
43141
|
-
settings: state.settings
|
|
43843
|
+
settings: state.settings,
|
|
43844
|
+
...meshQueueStats && { meshQueueStats }
|
|
43142
43845
|
};
|
|
43143
43846
|
}
|
|
43144
43847
|
function buildExtensionAgentSession(parent, ext, options) {
|
|
@@ -43150,6 +43853,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43150
43853
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
43151
43854
|
const workspace = parent.workspace || null;
|
|
43152
43855
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
43856
|
+
const meshCoordinatorFor = ext.settings?.meshCoordinatorFor;
|
|
43857
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
43153
43858
|
return {
|
|
43154
43859
|
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
43155
43860
|
parentId: parent.instanceId || parent.type,
|
|
@@ -43172,7 +43877,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43172
43877
|
errorMessage: ext.errorMessage,
|
|
43173
43878
|
errorReason: ext.errorReason,
|
|
43174
43879
|
lastUpdated: ext.lastUpdated,
|
|
43175
|
-
settings: ext.settings
|
|
43880
|
+
settings: ext.settings,
|
|
43881
|
+
...meshQueueStats && { meshQueueStats }
|
|
43176
43882
|
};
|
|
43177
43883
|
}
|
|
43178
43884
|
function shouldIncludeExtensionSession(ext) {
|
|
@@ -43200,6 +43906,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43200
43906
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
43201
43907
|
const workspace = state.workspace || null;
|
|
43202
43908
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
43909
|
+
const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
|
|
43910
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
43203
43911
|
return {
|
|
43204
43912
|
id: state.instanceId,
|
|
43205
43913
|
parentId: null,
|
|
@@ -43238,7 +43946,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43238
43946
|
errorMessage: state.errorMessage,
|
|
43239
43947
|
errorReason: state.errorReason,
|
|
43240
43948
|
lastUpdated: state.lastUpdated,
|
|
43241
|
-
settings: state.settings
|
|
43949
|
+
settings: state.settings,
|
|
43950
|
+
...meshQueueStats && { meshQueueStats }
|
|
43242
43951
|
};
|
|
43243
43952
|
}
|
|
43244
43953
|
function buildAcpSession(state, options) {
|
|
@@ -43250,6 +43959,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43250
43959
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
43251
43960
|
const workspace = state.workspace || null;
|
|
43252
43961
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
43962
|
+
const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
|
|
43963
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
43253
43964
|
return {
|
|
43254
43965
|
id: state.instanceId,
|
|
43255
43966
|
parentId: null,
|
|
@@ -43271,7 +43982,8 @@ ${effect.notification.body || ""}`.trim();
|
|
|
43271
43982
|
errorMessage: state.errorMessage,
|
|
43272
43983
|
errorReason: state.errorReason,
|
|
43273
43984
|
lastUpdated: state.lastUpdated,
|
|
43274
|
-
settings: state.settings
|
|
43985
|
+
settings: state.settings,
|
|
43986
|
+
...meshQueueStats && { meshQueueStats }
|
|
43275
43987
|
};
|
|
43276
43988
|
}
|
|
43277
43989
|
function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
@@ -46542,7 +47254,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
46542
47254
|
var os13 = __toESM2(require("os"));
|
|
46543
47255
|
var path18 = __toESM2(require("path"));
|
|
46544
47256
|
var crypto4 = __toESM2(require("crypto"));
|
|
46545
|
-
var
|
|
47257
|
+
var import_fs8 = require("fs");
|
|
46546
47258
|
var import_child_process6 = require("child_process");
|
|
46547
47259
|
var import_chalk = __toESM2((init_source(), __toCommonJS(source_exports)));
|
|
46548
47260
|
init_provider_cli_adapter();
|
|
@@ -48906,7 +49618,7 @@ ${rawInput}` : rawInput;
|
|
|
48906
49618
|
const trimmed = command.trim();
|
|
48907
49619
|
if (!trimmed) return false;
|
|
48908
49620
|
if (isExplicitCommand(trimmed)) {
|
|
48909
|
-
return (0,
|
|
49621
|
+
return (0, import_fs8.existsSync)(expandExecutable(trimmed));
|
|
48910
49622
|
}
|
|
48911
49623
|
try {
|
|
48912
49624
|
(0, import_child_process6.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -48935,10 +49647,10 @@ ${rawInput}` : rawInput;
|
|
|
48935
49647
|
}
|
|
48936
49648
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
48937
49649
|
const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
48938
|
-
(0,
|
|
49650
|
+
(0, import_fs8.mkdirSync)(baseDir, { recursive: true });
|
|
48939
49651
|
const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
|
|
48940
49652
|
const filePath = path18.join(baseDir, `${workspaceHash}.json`);
|
|
48941
|
-
(0,
|
|
49653
|
+
(0, import_fs8.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
48942
49654
|
return filePath;
|
|
48943
49655
|
}
|
|
48944
49656
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
@@ -52411,133 +53123,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
52411
53123
|
return null;
|
|
52412
53124
|
}
|
|
52413
53125
|
}
|
|
52414
|
-
|
|
52415
|
-
init_logger();
|
|
52416
|
-
var MAX_PENDING_EVENTS = 50;
|
|
52417
|
-
var pendingMeshCoordinatorEvents = [];
|
|
52418
|
-
function drainPendingMeshCoordinatorEvents() {
|
|
52419
|
-
return pendingMeshCoordinatorEvents.splice(0);
|
|
52420
|
-
}
|
|
52421
|
-
function readNonEmptyString(value) {
|
|
52422
|
-
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
52423
|
-
}
|
|
52424
|
-
var MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
52425
|
-
"agent:generating_completed",
|
|
52426
|
-
"agent:waiting_approval",
|
|
52427
|
-
"agent:stopped",
|
|
52428
|
-
"monitor:long_generating"
|
|
52429
|
-
]);
|
|
52430
|
-
function isMeshCoordinatorEvent(eventName) {
|
|
52431
|
-
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
52432
|
-
}
|
|
52433
|
-
function formatCompletionMetadata(event) {
|
|
52434
|
-
const parts = [
|
|
52435
|
-
readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
|
|
52436
|
-
readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
|
|
52437
|
-
readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
|
|
52438
|
-
].filter(Boolean);
|
|
52439
|
-
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
52440
|
-
}
|
|
52441
|
-
function buildMeshSystemMessage(args) {
|
|
52442
|
-
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
52443
|
-
if (args.event === "agent:generating_completed") {
|
|
52444
|
-
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.`;
|
|
52445
|
-
}
|
|
52446
|
-
if (args.event === "agent:waiting_approval") {
|
|
52447
|
-
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
52448
|
-
}
|
|
52449
|
-
if (args.event === "agent:stopped") {
|
|
52450
|
-
return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
|
|
52451
|
-
}
|
|
52452
|
-
if (args.event === "monitor:long_generating") {
|
|
52453
|
-
return `[System] ${args.nodeLabel} has been generating for a long time${metadata}. Use mesh_read_chat once for a status check, but do not poll repeatedly.`;
|
|
52454
|
-
}
|
|
52455
|
-
return "";
|
|
52456
|
-
}
|
|
52457
|
-
function injectMeshSystemMessage(components, args) {
|
|
52458
|
-
const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
52459
|
-
const instState = inst.getState();
|
|
52460
|
-
if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
|
|
52461
|
-
if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
|
|
52462
|
-
return true;
|
|
52463
|
-
});
|
|
52464
|
-
if (coordinatorInstances.length === 0) {
|
|
52465
|
-
if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
|
|
52466
|
-
pendingMeshCoordinatorEvents.push({
|
|
52467
|
-
event: args.event,
|
|
52468
|
-
meshId: args.meshId,
|
|
52469
|
-
nodeLabel: args.nodeLabel,
|
|
52470
|
-
metadataEvent: args.metadataEvent,
|
|
52471
|
-
queuedAt: Date.now()
|
|
52472
|
-
});
|
|
52473
|
-
LOG2.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
52474
|
-
}
|
|
52475
|
-
return { success: true, forwarded: 0 };
|
|
52476
|
-
}
|
|
52477
|
-
const messageText = buildMeshSystemMessage({
|
|
52478
|
-
event: args.event,
|
|
52479
|
-
nodeLabel: args.nodeLabel,
|
|
52480
|
-
metadataEvent: args.metadataEvent
|
|
52481
|
-
});
|
|
52482
|
-
if (!messageText) return { success: false, error: "unsupported mesh event" };
|
|
52483
|
-
for (const coord of coordinatorInstances) {
|
|
52484
|
-
const coordState = coord.getState();
|
|
52485
|
-
LOG2.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
52486
|
-
coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
|
|
52487
|
-
}
|
|
52488
|
-
return { success: true, forwarded: coordinatorInstances.length };
|
|
52489
|
-
}
|
|
52490
|
-
function handleMeshForwardEvent(components, payload) {
|
|
52491
|
-
const eventName = readNonEmptyString(payload.event);
|
|
52492
|
-
if (!isMeshCoordinatorEvent(eventName)) {
|
|
52493
|
-
return { success: false, error: "unsupported mesh event" };
|
|
52494
|
-
}
|
|
52495
|
-
const meshId = readNonEmptyString(payload.meshId);
|
|
52496
|
-
if (!meshId) return { success: false, error: "meshId required" };
|
|
52497
|
-
const nodeId = readNonEmptyString(payload.nodeId);
|
|
52498
|
-
const workspace = readNonEmptyString(payload.workspace);
|
|
52499
|
-
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
52500
|
-
return injectMeshSystemMessage(components, {
|
|
52501
|
-
meshId,
|
|
52502
|
-
nodeLabel,
|
|
52503
|
-
event: eventName,
|
|
52504
|
-
metadataEvent: {
|
|
52505
|
-
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
52506
|
-
providerType: readNonEmptyString(payload.providerType),
|
|
52507
|
-
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
52508
|
-
}
|
|
52509
|
-
});
|
|
52510
|
-
}
|
|
52511
|
-
function setupMeshEventForwarding(components) {
|
|
52512
|
-
components.instanceManager.onEvent((event) => {
|
|
52513
|
-
if (!isMeshCoordinatorEvent(event.event)) return;
|
|
52514
|
-
const instanceId = readNonEmptyString(event.instanceId);
|
|
52515
|
-
if (!instanceId) return;
|
|
52516
|
-
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
52517
|
-
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
52518
|
-
const state = sourceInstance.getState();
|
|
52519
|
-
const workspace = readNonEmptyString(state.workspace);
|
|
52520
|
-
if (!workspace) return;
|
|
52521
|
-
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
52522
|
-
if (readNonEmptyString(settings.meshCoordinatorFor)) return;
|
|
52523
|
-
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
52524
|
-
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
52525
|
-
if (!isMeshDelegate) return;
|
|
52526
|
-
const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
52527
|
-
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
52528
|
-
if (!meshId) return;
|
|
52529
|
-
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
52530
|
-
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
52531
|
-
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
52532
|
-
injectMeshSystemMessage(components, {
|
|
52533
|
-
meshId,
|
|
52534
|
-
sourceInstanceId: instanceId,
|
|
52535
|
-
nodeLabel,
|
|
52536
|
-
event: event.event,
|
|
52537
|
-
metadataEvent: event
|
|
52538
|
-
});
|
|
52539
|
-
});
|
|
52540
|
-
}
|
|
53126
|
+
init_mesh_events();
|
|
52541
53127
|
var os18 = __toESM2(require("os"));
|
|
52542
53128
|
init_config();
|
|
52543
53129
|
init_terminal_screen();
|
|
@@ -53186,7 +53772,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
53186
53772
|
}
|
|
53187
53773
|
}
|
|
53188
53774
|
var import_os3 = require("os");
|
|
53189
|
-
var
|
|
53775
|
+
var import_path6 = require("path");
|
|
53190
53776
|
var fs10 = __toESM2(require("fs"));
|
|
53191
53777
|
var CHANNEL_NPM_TAG = { stable: "latest", preview: "next" };
|
|
53192
53778
|
var CHANNEL_SERVER_URL = {
|
|
@@ -53255,22 +53841,22 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
53255
53841
|
}
|
|
53256
53842
|
function resolveHermesUserHome() {
|
|
53257
53843
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
53258
|
-
return explicitHome || (0,
|
|
53844
|
+
return explicitHome || (0, import_path6.join)((0, import_os3.homedir)(), ".hermes");
|
|
53259
53845
|
}
|
|
53260
53846
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
53261
53847
|
const sourceHome = resolveHermesUserHome();
|
|
53262
|
-
const sourceConfigPath = (0,
|
|
53848
|
+
const sourceConfigPath = (0, import_path6.join)(sourceHome, "config.yaml");
|
|
53263
53849
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
53264
|
-
if ((0,
|
|
53850
|
+
if ((0, import_path6.resolve)(sourceConfigPath) === (0, import_path6.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
53265
53851
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
53266
53852
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
53267
53853
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
53268
53854
|
}
|
|
53269
53855
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
53270
|
-
if ((0,
|
|
53856
|
+
if ((0, import_path6.resolve)(sourceHome) === (0, import_path6.resolve)(targetHome)) return;
|
|
53271
53857
|
for (const fileName of [".env", "auth.json"]) {
|
|
53272
|
-
const sourcePath = (0,
|
|
53273
|
-
const targetPath = (0,
|
|
53858
|
+
const sourcePath = (0, import_path6.join)(sourceHome, fileName);
|
|
53859
|
+
const targetPath = (0, import_path6.join)(targetHome, fileName);
|
|
53274
53860
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
53275
53861
|
try {
|
|
53276
53862
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -54231,6 +54817,21 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54231
54817
|
return { success: false, error: e.message };
|
|
54232
54818
|
}
|
|
54233
54819
|
}
|
|
54820
|
+
case "get_mesh_ledger": {
|
|
54821
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
54822
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
54823
|
+
try {
|
|
54824
|
+
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
54825
|
+
const tail = typeof args?.tail === "number" ? args.tail : 20;
|
|
54826
|
+
const since = typeof args?.since === "string" ? args.since : void 0;
|
|
54827
|
+
const kind = Array.isArray(args?.kind) ? args.kind.filter((k) => typeof k === "string") : void 0;
|
|
54828
|
+
const entries = readLedgerEntries2(meshId, { tail, since, kind });
|
|
54829
|
+
const summary = getLedgerSummary2(meshId);
|
|
54830
|
+
return { success: true, entries, summary };
|
|
54831
|
+
} catch (e) {
|
|
54832
|
+
return { success: false, error: e.message };
|
|
54833
|
+
}
|
|
54834
|
+
}
|
|
54234
54835
|
case "add_mesh_node": {
|
|
54235
54836
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
54236
54837
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -54299,6 +54900,54 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54299
54900
|
return { success: false, error: e.message };
|
|
54300
54901
|
}
|
|
54301
54902
|
}
|
|
54903
|
+
case "refine_mesh_node": {
|
|
54904
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
54905
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
54906
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
54907
|
+
try {
|
|
54908
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
54909
|
+
const mesh = meshRecord?.mesh;
|
|
54910
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
54911
|
+
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
54912
|
+
if (!node.isLocalWorktree || !node.workspace) {
|
|
54913
|
+
return { success: false, error: `Refinery requires a local worktree node` };
|
|
54914
|
+
}
|
|
54915
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
54916
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
54917
|
+
if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
|
|
54918
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
54919
|
+
const { promisify: promisify3 } = await import("util");
|
|
54920
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
54921
|
+
const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
|
|
54922
|
+
const branch = branchStdout.trim();
|
|
54923
|
+
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
54924
|
+
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
54925
|
+
const baseBranch = baseBranchStdout.trim();
|
|
54926
|
+
try {
|
|
54927
|
+
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
54928
|
+
} catch (e) {
|
|
54929
|
+
return { success: false, error: `Merge failed (conflicts?): ${e.message}` };
|
|
54930
|
+
}
|
|
54931
|
+
const removeResult = await this.execute("remove_mesh_node", {
|
|
54932
|
+
meshId,
|
|
54933
|
+
nodeId,
|
|
54934
|
+
sessionCleanupMode: "kill",
|
|
54935
|
+
inlineMesh: args?.inlineMesh
|
|
54936
|
+
});
|
|
54937
|
+
try {
|
|
54938
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
54939
|
+
appendLedgerEntry2(meshId, {
|
|
54940
|
+
kind: "node_removed",
|
|
54941
|
+
nodeId,
|
|
54942
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch }
|
|
54943
|
+
});
|
|
54944
|
+
} catch {
|
|
54945
|
+
}
|
|
54946
|
+
return { success: true, merged: true, branch, into: baseBranch, removeResult };
|
|
54947
|
+
} catch (e) {
|
|
54948
|
+
return { success: false, error: e.message };
|
|
54949
|
+
}
|
|
54950
|
+
}
|
|
54302
54951
|
case "remove_mesh_node": {
|
|
54303
54952
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
54304
54953
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
@@ -54334,6 +54983,17 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54334
54983
|
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
54335
54984
|
removed = removeNode3(meshId, nodeId);
|
|
54336
54985
|
}
|
|
54986
|
+
if (removed) {
|
|
54987
|
+
try {
|
|
54988
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
54989
|
+
appendLedgerEntry2(meshId, {
|
|
54990
|
+
kind: "node_removed",
|
|
54991
|
+
nodeId,
|
|
54992
|
+
payload: { worktree: !!node?.isLocalWorktree, sessionCleanupMode }
|
|
54993
|
+
});
|
|
54994
|
+
} catch {
|
|
54995
|
+
}
|
|
54996
|
+
}
|
|
54337
54997
|
return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
|
|
54338
54998
|
} catch (e) {
|
|
54339
54999
|
return { success: false, error: e.message };
|
|
@@ -54363,9 +55023,9 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54363
55023
|
});
|
|
54364
55024
|
let node;
|
|
54365
55025
|
if (meshRecord.inline) {
|
|
54366
|
-
const { randomUUID:
|
|
55026
|
+
const { randomUUID: randomUUID10 } = await import("crypto");
|
|
54367
55027
|
node = {
|
|
54368
|
-
id: `node_${
|
|
55028
|
+
id: `node_${randomUUID10().replace(/-/g, "")}`,
|
|
54369
55029
|
workspace: result.worktreePath,
|
|
54370
55030
|
repoRoot: result.worktreePath,
|
|
54371
55031
|
daemonId: sourceNode.daemonId,
|
|
@@ -54390,6 +55050,15 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54390
55050
|
});
|
|
54391
55051
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
54392
55052
|
}
|
|
55053
|
+
try {
|
|
55054
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
55055
|
+
appendLedgerEntry2(meshId, {
|
|
55056
|
+
kind: "node_cloned",
|
|
55057
|
+
nodeId: node.id,
|
|
55058
|
+
payload: { sourceNodeId, branch: result.branch, worktreePath: result.worktreePath }
|
|
55059
|
+
});
|
|
55060
|
+
} catch {
|
|
55061
|
+
}
|
|
54393
55062
|
return {
|
|
54394
55063
|
success: true,
|
|
54395
55064
|
node,
|
|
@@ -54400,6 +55069,19 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54400
55069
|
return { success: false, error: e.message };
|
|
54401
55070
|
}
|
|
54402
55071
|
}
|
|
55072
|
+
case "trigger_mesh_queue": {
|
|
55073
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
55074
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
55075
|
+
try {
|
|
55076
|
+
const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
|
|
55077
|
+
if (meshId) {
|
|
55078
|
+
triggerMeshQueue2(this.deps, meshId);
|
|
55079
|
+
}
|
|
55080
|
+
return { success: true };
|
|
55081
|
+
} catch (e) {
|
|
55082
|
+
return { success: false, error: e.message };
|
|
55083
|
+
}
|
|
55084
|
+
}
|
|
54403
55085
|
// ─── Mesh Coordinator Launch ───
|
|
54404
55086
|
case "launch_mesh_coordinator": {
|
|
54405
55087
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -54504,7 +55186,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54504
55186
|
workspace
|
|
54505
55187
|
};
|
|
54506
55188
|
}
|
|
54507
|
-
const { existsSync:
|
|
55189
|
+
const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
|
|
54508
55190
|
const { dirname: dirname9 } = await import("path");
|
|
54509
55191
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
54510
55192
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -54538,21 +55220,21 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54538
55220
|
};
|
|
54539
55221
|
}
|
|
54540
55222
|
try {
|
|
54541
|
-
|
|
55223
|
+
mkdirSync17(dirname9(mcpConfigPath), { recursive: true });
|
|
54542
55224
|
} catch (error48) {
|
|
54543
55225
|
const message = `Could not prepare MCP config path for automatic setup: ${error48?.message || error48}`;
|
|
54544
55226
|
LOG2.error("MeshCoordinator", message);
|
|
54545
55227
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
54546
55228
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
54547
55229
|
}
|
|
54548
|
-
const hadExistingMcpConfig =
|
|
55230
|
+
const hadExistingMcpConfig = existsSync25(mcpConfigPath);
|
|
54549
55231
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
54550
55232
|
if (hermesBaseConfig) {
|
|
54551
55233
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname9(mcpConfigPath));
|
|
54552
55234
|
}
|
|
54553
55235
|
if (hadExistingMcpConfig) {
|
|
54554
55236
|
try {
|
|
54555
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
55237
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
|
|
54556
55238
|
existingMcpConfig = { ...existingMcpConfig, ...parsedExistingMcpConfig };
|
|
54557
55239
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
54558
55240
|
} catch (error48) {
|
|
@@ -54574,7 +55256,7 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54574
55256
|
}
|
|
54575
55257
|
};
|
|
54576
55258
|
try {
|
|
54577
|
-
|
|
55259
|
+
writeFileSync15(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
54578
55260
|
} catch (error48) {
|
|
54579
55261
|
const message = `Could not write MCP config for automatic setup: ${error48?.message || error48}`;
|
|
54580
55262
|
LOG2.error("MeshCoordinator", message);
|
|
@@ -54611,6 +55293,16 @@ ${(0, import_node_path.resolve)(workspace || os17.tmpdir())}`;
|
|
|
54611
55293
|
return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
|
|
54612
55294
|
}
|
|
54613
55295
|
LOG2.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
|
|
55296
|
+
try {
|
|
55297
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
55298
|
+
appendLedgerEntry2(meshId, {
|
|
55299
|
+
kind: "coordinator_started",
|
|
55300
|
+
sessionId: launchResult.sessionId || launchResult.id,
|
|
55301
|
+
providerType: cliType,
|
|
55302
|
+
payload: { workspace }
|
|
55303
|
+
});
|
|
55304
|
+
} catch {
|
|
55305
|
+
}
|
|
54614
55306
|
return {
|
|
54615
55307
|
success: true,
|
|
54616
55308
|
meshId,
|
|
@@ -62344,6 +63036,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
62344
63036
|
};
|
|
62345
63037
|
init_logger();
|
|
62346
63038
|
init_config();
|
|
63039
|
+
init_mesh_events();
|
|
62347
63040
|
async function initDaemonComponents2(config2) {
|
|
62348
63041
|
installGlobalInterceptor();
|
|
62349
63042
|
const appConfig = loadConfig2();
|