@adhdev/daemon-standalone 0.9.76 → 0.9.77-rc.2
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 +894 -205
- 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 +1346 -275
- 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
|
@@ -2437,7 +2437,7 @@ var require_extension = __commonJS({
|
|
|
2437
2437
|
var require_websocket = __commonJS({
|
|
2438
2438
|
"../../node_modules/ws/lib/websocket.js"(exports2, module2) {
|
|
2439
2439
|
"use strict";
|
|
2440
|
-
var
|
|
2440
|
+
var EventEmitter3 = require("events");
|
|
2441
2441
|
var https = require("https");
|
|
2442
2442
|
var http3 = require("http");
|
|
2443
2443
|
var net3 = require("net");
|
|
@@ -2469,7 +2469,7 @@ var require_websocket = __commonJS({
|
|
|
2469
2469
|
var protocolVersions = [8, 13];
|
|
2470
2470
|
var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
|
|
2471
2471
|
var subprotocolRegex = /^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/;
|
|
2472
|
-
var WebSocket2 = class _WebSocket extends
|
|
2472
|
+
var WebSocket2 = class _WebSocket extends EventEmitter3 {
|
|
2473
2473
|
/**
|
|
2474
2474
|
* Create a new `WebSocket`.
|
|
2475
2475
|
*
|
|
@@ -3466,7 +3466,7 @@ var require_subprotocol = __commonJS({
|
|
|
3466
3466
|
var require_websocket_server = __commonJS({
|
|
3467
3467
|
"../../node_modules/ws/lib/websocket-server.js"(exports2, module2) {
|
|
3468
3468
|
"use strict";
|
|
3469
|
-
var
|
|
3469
|
+
var EventEmitter3 = require("events");
|
|
3470
3470
|
var http3 = require("http");
|
|
3471
3471
|
var { Duplex } = require("stream");
|
|
3472
3472
|
var { createHash: createHash3 } = require("crypto");
|
|
@@ -3479,7 +3479,7 @@ var require_websocket_server = __commonJS({
|
|
|
3479
3479
|
var RUNNING = 0;
|
|
3480
3480
|
var CLOSING = 1;
|
|
3481
3481
|
var CLOSED = 2;
|
|
3482
|
-
var WebSocketServer2 = class extends
|
|
3482
|
+
var WebSocketServer2 = class extends EventEmitter3 {
|
|
3483
3483
|
/**
|
|
3484
3484
|
* Create a `WebSocketServer` instance.
|
|
3485
3485
|
*
|
|
@@ -25102,6 +25102,7 @@ __export(dist_exports, {
|
|
|
25102
25102
|
TurnSnapshotTracker: () => TurnSnapshotTracker,
|
|
25103
25103
|
VersionArchive: () => VersionArchive,
|
|
25104
25104
|
addNode: () => addNode,
|
|
25105
|
+
appendLedgerEntry: () => appendLedgerEntry,
|
|
25105
25106
|
appendRecentActivity: () => appendRecentActivity,
|
|
25106
25107
|
buildAssistantChatMessage: () => buildAssistantChatMessage,
|
|
25107
25108
|
buildChatMessage: () => buildChatMessage,
|
|
@@ -25119,6 +25120,7 @@ __export(dist_exports, {
|
|
|
25119
25120
|
buildThoughtChatMessage: () => buildThoughtChatMessage,
|
|
25120
25121
|
buildToolChatMessage: () => buildToolChatMessage,
|
|
25121
25122
|
buildUserChatMessage: () => buildUserChatMessage,
|
|
25123
|
+
claimNextTask: () => claimNextTask,
|
|
25122
25124
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
25123
25125
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
|
|
25124
25126
|
clearDebugTrace: () => clearDebugTrace,
|
|
@@ -25137,6 +25139,7 @@ __export(dist_exports, {
|
|
|
25137
25139
|
detectAllVersions: () => detectAllVersions,
|
|
25138
25140
|
detectCLIs: () => detectCLIs,
|
|
25139
25141
|
detectIDEs: () => detectIDEs,
|
|
25142
|
+
enqueueTask: () => enqueueTask,
|
|
25140
25143
|
ensureSessionHostReady: () => ensureSessionHostReady,
|
|
25141
25144
|
execNpmCommandSync: () => execNpmCommandSync,
|
|
25142
25145
|
filterActivityChatMessages: () => filterActivityChatMessages,
|
|
@@ -25155,10 +25158,13 @@ __export(dist_exports, {
|
|
|
25155
25158
|
getGitFileDiff: () => getGitFileDiff,
|
|
25156
25159
|
getGitRepoStatus: () => getGitRepoStatus,
|
|
25157
25160
|
getHostMemorySnapshot: () => getHostMemorySnapshot,
|
|
25161
|
+
getLedgerDir: () => getLedgerDir,
|
|
25162
|
+
getLedgerSummary: () => getLedgerSummary,
|
|
25158
25163
|
getLogLevel: () => getLogLevel,
|
|
25159
25164
|
getMesh: () => getMesh,
|
|
25160
25165
|
getMeshByRepo: () => getMeshByRepo,
|
|
25161
25166
|
getNpmExecOptions: () => getNpmExecOptions,
|
|
25167
|
+
getQueue: () => getQueue,
|
|
25162
25168
|
getRecentActivity: () => getRecentActivity,
|
|
25163
25169
|
getRecentCommands: () => getRecentCommands,
|
|
25164
25170
|
getRecentDebugTrace: () => getRecentDebugTrace,
|
|
@@ -25166,6 +25172,7 @@ __export(dist_exports, {
|
|
|
25166
25172
|
getSavedProviderSessions: () => getSavedProviderSessions,
|
|
25167
25173
|
getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
|
|
25168
25174
|
getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
|
|
25175
|
+
getSessionRecoveryContext: () => getSessionRecoveryContext,
|
|
25169
25176
|
getWorkspaceState: () => getWorkspaceState,
|
|
25170
25177
|
handleGitCommand: () => handleGitCommand,
|
|
25171
25178
|
hasCdpManager: () => hasCdpManager,
|
|
@@ -25219,6 +25226,7 @@ __export(dist_exports, {
|
|
|
25219
25226
|
prepareSessionModalUpdate: () => prepareSessionModalUpdate,
|
|
25220
25227
|
probeCdpPort: () => probeCdpPort,
|
|
25221
25228
|
readChatHistory: () => readChatHistory,
|
|
25229
|
+
readLedgerEntries: () => readLedgerEntries,
|
|
25222
25230
|
recordDebugTrace: () => recordDebugTrace,
|
|
25223
25231
|
registerExtensionProviders: () => registerExtensionProviders,
|
|
25224
25232
|
removeNode: () => removeNode,
|
|
@@ -25247,9 +25255,12 @@ __export(dist_exports, {
|
|
|
25247
25255
|
startDaemonDevSupport: () => startDaemonDevSupport,
|
|
25248
25256
|
summarizeGitStatus: () => summarizeGitStatus,
|
|
25249
25257
|
syncMeshes: () => syncMeshes,
|
|
25258
|
+
triggerMeshQueue: () => triggerMeshQueue,
|
|
25250
25259
|
updateConfig: () => updateConfig,
|
|
25251
25260
|
updateMesh: () => updateMesh,
|
|
25252
25261
|
updateNode: () => updateNode,
|
|
25262
|
+
updateSessionTaskStatus: () => updateSessionTaskStatus,
|
|
25263
|
+
updateTaskStatus: () => updateTaskStatus,
|
|
25253
25264
|
upsertSavedProviderSession: () => upsertSavedProviderSession
|
|
25254
25265
|
});
|
|
25255
25266
|
function resolveWorktreePath(repoRoot, meshName, branch) {
|
|
@@ -25769,18 +25780,315 @@ function buildRulesSection(coordinatorCliType) {
|
|
|
25769
25780
|
return `## Rules
|
|
25770
25781
|
|
|
25771
25782
|
- **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.
|
|
25772
|
-
- **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.
|
|
25783
|
+
- **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.
|
|
25773
25784
|
- **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.
|
|
25774
|
-
- **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.
|
|
25785
|
+
- **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.
|
|
25775
25786
|
- **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.
|
|
25776
25787
|
- **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.
|
|
25777
|
-
- **Handle failures
|
|
25788
|
+
- **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.
|
|
25789
|
+
- **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.
|
|
25778
25790
|
- **Keep the user informed.** Report progress after each delegation round \u2014 one or two sentences, not a narration.
|
|
25779
25791
|
- **Respect node capabilities.** Don't send build tasks to read-only nodes. Don't push from nodes that aren't allowed to.
|
|
25780
25792
|
- **Never fabricate tool results.** Always call the actual tool; never pretend you did.
|
|
25781
25793
|
- **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
|
|
25782
25794
|
- **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
|
|
25783
25795
|
}
|
|
25796
|
+
function getLedgerDir() {
|
|
25797
|
+
const dir = (0, import_path3.join)(getConfigDir(), LEDGER_DIR_NAME);
|
|
25798
|
+
if (!(0, import_fs6.existsSync)(dir)) {
|
|
25799
|
+
(0, import_fs6.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
25800
|
+
}
|
|
25801
|
+
return dir;
|
|
25802
|
+
}
|
|
25803
|
+
function getLedgerPath(meshId) {
|
|
25804
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
25805
|
+
return (0, import_path3.join)(getLedgerDir(), `${safe}.jsonl`);
|
|
25806
|
+
}
|
|
25807
|
+
function getRotatedPath(meshId, index) {
|
|
25808
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
25809
|
+
return (0, import_path3.join)(getLedgerDir(), `${safe}.${index}.jsonl`);
|
|
25810
|
+
}
|
|
25811
|
+
function appendLedgerEntry(meshId, partial2) {
|
|
25812
|
+
const entry = {
|
|
25813
|
+
id: (0, import_crypto4.randomUUID)(),
|
|
25814
|
+
meshId,
|
|
25815
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
25816
|
+
...partial2
|
|
25817
|
+
};
|
|
25818
|
+
const filePath = getLedgerPath(meshId);
|
|
25819
|
+
if ((0, import_fs6.existsSync)(filePath)) {
|
|
25820
|
+
try {
|
|
25821
|
+
const stat22 = (0, import_fs6.statSync)(filePath);
|
|
25822
|
+
if (stat22.size >= MAX_FILE_SIZE_BYTES) {
|
|
25823
|
+
rotateLedgerFile(meshId, filePath);
|
|
25824
|
+
}
|
|
25825
|
+
} catch {
|
|
25826
|
+
}
|
|
25827
|
+
}
|
|
25828
|
+
try {
|
|
25829
|
+
const line = JSON.stringify(entry) + "\n";
|
|
25830
|
+
(0, import_fs6.appendFileSync)(filePath, line, { encoding: "utf-8", mode: 384 });
|
|
25831
|
+
meshLedgerEvents.emit("append", meshId, entry);
|
|
25832
|
+
return entry;
|
|
25833
|
+
} catch (e) {
|
|
25834
|
+
throw new Error(`Failed to append to ledger for mesh ${meshId}: ${e.message}`);
|
|
25835
|
+
}
|
|
25836
|
+
}
|
|
25837
|
+
function appendRemoteLedgerEntries(meshId, entries) {
|
|
25838
|
+
if (entries.length === 0) return;
|
|
25839
|
+
const ledgerPath = getLedgerPath(meshId);
|
|
25840
|
+
const existing = new Set(readLedgerEntries(meshId).map((e) => e.id));
|
|
25841
|
+
const newEntries = entries.filter((e) => !existing.has(e.id));
|
|
25842
|
+
if (newEntries.length === 0) return;
|
|
25843
|
+
try {
|
|
25844
|
+
const lines = newEntries.map((e) => JSON.stringify(e)).join("\n") + "\n";
|
|
25845
|
+
(0, import_fs6.appendFileSync)(ledgerPath, lines, { encoding: "utf-8", mode: 384 });
|
|
25846
|
+
} catch (e) {
|
|
25847
|
+
throw new Error(`Failed to append remote ledger entries for mesh ${meshId}: ${e.message}`);
|
|
25848
|
+
}
|
|
25849
|
+
}
|
|
25850
|
+
function readLedgerEntries(meshId, opts) {
|
|
25851
|
+
const filePath = getLedgerPath(meshId);
|
|
25852
|
+
if (!(0, import_fs6.existsSync)(filePath)) return [];
|
|
25853
|
+
let content;
|
|
25854
|
+
try {
|
|
25855
|
+
content = (0, import_fs6.readFileSync)(filePath, "utf-8");
|
|
25856
|
+
} catch {
|
|
25857
|
+
return [];
|
|
25858
|
+
}
|
|
25859
|
+
const lines = content.split("\n").filter((line) => line.trim());
|
|
25860
|
+
let entries = [];
|
|
25861
|
+
for (const line of lines) {
|
|
25862
|
+
try {
|
|
25863
|
+
const entry = JSON.parse(line);
|
|
25864
|
+
if (!entry.id || !entry.kind) continue;
|
|
25865
|
+
entries.push(entry);
|
|
25866
|
+
} catch {
|
|
25867
|
+
}
|
|
25868
|
+
}
|
|
25869
|
+
if (opts?.since) {
|
|
25870
|
+
const sinceDate = new Date(opts.since).getTime();
|
|
25871
|
+
if (!isNaN(sinceDate)) {
|
|
25872
|
+
entries = entries.filter((e) => new Date(e.timestamp).getTime() >= sinceDate);
|
|
25873
|
+
}
|
|
25874
|
+
}
|
|
25875
|
+
if (opts?.kind?.length) {
|
|
25876
|
+
const kindSet = new Set(opts.kind);
|
|
25877
|
+
entries = entries.filter((e) => kindSet.has(e.kind));
|
|
25878
|
+
}
|
|
25879
|
+
if (opts?.tail && opts.tail > 0 && entries.length > opts.tail) {
|
|
25880
|
+
entries = entries.slice(-opts.tail);
|
|
25881
|
+
}
|
|
25882
|
+
return entries;
|
|
25883
|
+
}
|
|
25884
|
+
function getLedgerSummary(meshId) {
|
|
25885
|
+
const entries = readLedgerEntries(meshId);
|
|
25886
|
+
const now = Date.now();
|
|
25887
|
+
const recentFailureCutoff = now - RECENT_FAILURE_WINDOW_MS;
|
|
25888
|
+
const summary = {
|
|
25889
|
+
meshId,
|
|
25890
|
+
totalEntries: entries.length,
|
|
25891
|
+
taskDispatched: 0,
|
|
25892
|
+
taskCompleted: 0,
|
|
25893
|
+
taskFailed: 0,
|
|
25894
|
+
taskStalled: 0,
|
|
25895
|
+
sessionLaunched: 0,
|
|
25896
|
+
checkpointCreated: 0,
|
|
25897
|
+
lastActivityAt: null,
|
|
25898
|
+
recentFailures: 0
|
|
25899
|
+
};
|
|
25900
|
+
for (const entry of entries) {
|
|
25901
|
+
switch (entry.kind) {
|
|
25902
|
+
case "task_dispatched":
|
|
25903
|
+
summary.taskDispatched++;
|
|
25904
|
+
break;
|
|
25905
|
+
case "task_completed":
|
|
25906
|
+
summary.taskCompleted++;
|
|
25907
|
+
break;
|
|
25908
|
+
case "task_failed": {
|
|
25909
|
+
summary.taskFailed++;
|
|
25910
|
+
if (new Date(entry.timestamp).getTime() >= recentFailureCutoff) {
|
|
25911
|
+
summary.recentFailures++;
|
|
25912
|
+
}
|
|
25913
|
+
break;
|
|
25914
|
+
}
|
|
25915
|
+
case "task_stalled":
|
|
25916
|
+
summary.taskStalled++;
|
|
25917
|
+
break;
|
|
25918
|
+
case "session_launched":
|
|
25919
|
+
summary.sessionLaunched++;
|
|
25920
|
+
break;
|
|
25921
|
+
case "checkpoint_created":
|
|
25922
|
+
summary.checkpointCreated++;
|
|
25923
|
+
break;
|
|
25924
|
+
}
|
|
25925
|
+
}
|
|
25926
|
+
if (entries.length > 0) {
|
|
25927
|
+
summary.lastActivityAt = entries[entries.length - 1].timestamp;
|
|
25928
|
+
}
|
|
25929
|
+
return summary;
|
|
25930
|
+
}
|
|
25931
|
+
function getSessionRecoveryContext(meshId, opts) {
|
|
25932
|
+
const maxRetries = opts.maxRetries ?? 1;
|
|
25933
|
+
const entries = readLedgerEntries(meshId);
|
|
25934
|
+
let lastDispatch = null;
|
|
25935
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
25936
|
+
const e = entries[i];
|
|
25937
|
+
if (e.kind !== "task_dispatched") continue;
|
|
25938
|
+
if (opts.sessionId && e.sessionId === opts.sessionId) {
|
|
25939
|
+
lastDispatch = e;
|
|
25940
|
+
break;
|
|
25941
|
+
}
|
|
25942
|
+
if (opts.nodeId && e.nodeId === opts.nodeId) {
|
|
25943
|
+
lastDispatch = e;
|
|
25944
|
+
break;
|
|
25945
|
+
}
|
|
25946
|
+
}
|
|
25947
|
+
const lastTaskMessage = typeof lastDispatch?.payload?.message === "string" ? lastDispatch.payload.message : null;
|
|
25948
|
+
const now = Date.now();
|
|
25949
|
+
const recentWindow = now - RECENT_FAILURE_WINDOW_MS;
|
|
25950
|
+
let consecutiveNodeFailures = 0;
|
|
25951
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
25952
|
+
const e = entries[i];
|
|
25953
|
+
if (new Date(e.timestamp).getTime() < recentWindow) break;
|
|
25954
|
+
if (opts.nodeId && e.nodeId !== opts.nodeId) continue;
|
|
25955
|
+
if (e.kind === "task_failed") {
|
|
25956
|
+
consecutiveNodeFailures++;
|
|
25957
|
+
} else if (e.kind === "task_completed" || e.kind === "task_dispatched") {
|
|
25958
|
+
break;
|
|
25959
|
+
}
|
|
25960
|
+
}
|
|
25961
|
+
let taskAttemptCount = 0;
|
|
25962
|
+
if (lastTaskMessage) {
|
|
25963
|
+
const prefix = lastTaskMessage.slice(0, 200);
|
|
25964
|
+
for (const e of entries) {
|
|
25965
|
+
if (e.kind === "task_dispatched" && typeof e.payload?.message === "string") {
|
|
25966
|
+
if (e.payload.message.startsWith(prefix)) {
|
|
25967
|
+
taskAttemptCount++;
|
|
25968
|
+
}
|
|
25969
|
+
}
|
|
25970
|
+
}
|
|
25971
|
+
}
|
|
25972
|
+
const retryRecommended = consecutiveNodeFailures <= maxRetries;
|
|
25973
|
+
let advice;
|
|
25974
|
+
if (consecutiveNodeFailures === 0) {
|
|
25975
|
+
advice = "No recent failures detected. This may be a normal stop.";
|
|
25976
|
+
} else if (retryRecommended) {
|
|
25977
|
+
const remaining = maxRetries - consecutiveNodeFailures + 1;
|
|
25978
|
+
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.`);
|
|
25979
|
+
} else {
|
|
25980
|
+
advice = `Max retries exceeded (${consecutiveNodeFailures} consecutive failures). Consider: (1) reassigning to a different node, (2) simplifying the task, or (3) escalating to the user.`;
|
|
25981
|
+
}
|
|
25982
|
+
return {
|
|
25983
|
+
lastTaskMessage,
|
|
25984
|
+
failedNodeId: opts.nodeId || null,
|
|
25985
|
+
failedSessionId: opts.sessionId || null,
|
|
25986
|
+
failedProviderType: null,
|
|
25987
|
+
// filled by caller if available
|
|
25988
|
+
consecutiveNodeFailures,
|
|
25989
|
+
taskAttemptCount,
|
|
25990
|
+
retryRecommended,
|
|
25991
|
+
advice
|
|
25992
|
+
};
|
|
25993
|
+
}
|
|
25994
|
+
function rotateLedgerFile(meshId, currentPath) {
|
|
25995
|
+
let index = 1;
|
|
25996
|
+
while ((0, import_fs6.existsSync)(getRotatedPath(meshId, index))) {
|
|
25997
|
+
index++;
|
|
25998
|
+
if (index > 10) break;
|
|
25999
|
+
}
|
|
26000
|
+
if (index > 10) index = 10;
|
|
26001
|
+
try {
|
|
26002
|
+
(0, import_fs6.renameSync)(currentPath, getRotatedPath(meshId, index));
|
|
26003
|
+
} catch {
|
|
26004
|
+
}
|
|
26005
|
+
}
|
|
26006
|
+
function getQueuePath(meshId) {
|
|
26007
|
+
const safe = meshId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
26008
|
+
return (0, import_path4.join)(getLedgerDir(), `${safe}.queue.json`);
|
|
26009
|
+
}
|
|
26010
|
+
function readQueue(meshId) {
|
|
26011
|
+
const path28 = getQueuePath(meshId);
|
|
26012
|
+
if (!(0, import_fs7.existsSync)(path28)) return [];
|
|
26013
|
+
try {
|
|
26014
|
+
const content = (0, import_fs7.readFileSync)(path28, "utf-8");
|
|
26015
|
+
return JSON.parse(content);
|
|
26016
|
+
} catch {
|
|
26017
|
+
return [];
|
|
26018
|
+
}
|
|
26019
|
+
}
|
|
26020
|
+
function writeQueue(meshId, queue) {
|
|
26021
|
+
const path28 = getQueuePath(meshId);
|
|
26022
|
+
(0, import_fs7.writeFileSync)(path28, JSON.stringify(queue, null, 2), "utf-8");
|
|
26023
|
+
}
|
|
26024
|
+
function enqueueTask(meshId, message, opts) {
|
|
26025
|
+
const queue = readQueue(meshId);
|
|
26026
|
+
const entry = {
|
|
26027
|
+
id: (0, import_crypto5.randomUUID)(),
|
|
26028
|
+
meshId,
|
|
26029
|
+
message,
|
|
26030
|
+
status: "pending",
|
|
26031
|
+
targetNodeId: opts?.targetNodeId,
|
|
26032
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
26033
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
26034
|
+
};
|
|
26035
|
+
queue.push(entry);
|
|
26036
|
+
writeQueue(meshId, queue);
|
|
26037
|
+
return entry;
|
|
26038
|
+
}
|
|
26039
|
+
function getQueue(meshId, opts) {
|
|
26040
|
+
let queue = readQueue(meshId);
|
|
26041
|
+
if (opts?.status?.length) {
|
|
26042
|
+
const statuses = new Set(opts.status);
|
|
26043
|
+
queue = queue.filter((q) => statuses.has(q.status));
|
|
26044
|
+
}
|
|
26045
|
+
return queue;
|
|
26046
|
+
}
|
|
26047
|
+
function claimNextTask(meshId, nodeId, sessionId) {
|
|
26048
|
+
const queue = readQueue(meshId);
|
|
26049
|
+
let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId);
|
|
26050
|
+
if (targetIdx === -1) {
|
|
26051
|
+
targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId);
|
|
26052
|
+
}
|
|
26053
|
+
if (targetIdx === -1) return null;
|
|
26054
|
+
const entry = queue[targetIdx];
|
|
26055
|
+
entry.status = "assigned";
|
|
26056
|
+
entry.assignedNodeId = nodeId;
|
|
26057
|
+
entry.assignedSessionId = sessionId;
|
|
26058
|
+
entry.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26059
|
+
writeQueue(meshId, queue);
|
|
26060
|
+
return entry;
|
|
26061
|
+
}
|
|
26062
|
+
function updateTaskStatus(meshId, taskId, status) {
|
|
26063
|
+
const queue = readQueue(meshId);
|
|
26064
|
+
const idx = queue.findIndex((q) => q.id === taskId);
|
|
26065
|
+
if (idx === -1) return null;
|
|
26066
|
+
queue[idx].status = status;
|
|
26067
|
+
queue[idx].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26068
|
+
writeQueue(meshId, queue);
|
|
26069
|
+
return queue[idx];
|
|
26070
|
+
}
|
|
26071
|
+
function updateSessionTaskStatus(meshId, sessionId, status) {
|
|
26072
|
+
const queue = readQueue(meshId);
|
|
26073
|
+
for (let i = queue.length - 1; i >= 0; i--) {
|
|
26074
|
+
if (queue[i].assignedSessionId === sessionId && queue[i].status === "assigned") {
|
|
26075
|
+
queue[i].status = status;
|
|
26076
|
+
queue[i].updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
26077
|
+
writeQueue(meshId, queue);
|
|
26078
|
+
return queue[i];
|
|
26079
|
+
}
|
|
26080
|
+
}
|
|
26081
|
+
return null;
|
|
26082
|
+
}
|
|
26083
|
+
function getMeshQueueStats(meshId) {
|
|
26084
|
+
const queue = readQueue(meshId);
|
|
26085
|
+
return {
|
|
26086
|
+
pending: queue.filter((q) => q.status === "pending").length,
|
|
26087
|
+
assigned: queue.filter((q) => q.status === "assigned").length,
|
|
26088
|
+
completed: queue.filter((q) => q.status === "completed").length,
|
|
26089
|
+
failed: queue.filter((q) => q.status === "failed").length
|
|
26090
|
+
};
|
|
26091
|
+
}
|
|
25784
26092
|
function setLogLevel(level) {
|
|
25785
26093
|
currentLevel = level;
|
|
25786
26094
|
daemonLog("Logger", `Log level set to: ${level}`, "info");
|
|
@@ -25795,13 +26103,13 @@ function getDaemonLogDir() {
|
|
|
25795
26103
|
return LOG_DIR;
|
|
25796
26104
|
}
|
|
25797
26105
|
function getCurrentDaemonLogPath(date5 = /* @__PURE__ */ new Date()) {
|
|
25798
|
-
return
|
|
26106
|
+
return path8.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
|
|
25799
26107
|
}
|
|
25800
26108
|
function checkDateRotation() {
|
|
25801
26109
|
const today = getDateStr();
|
|
25802
26110
|
if (today !== currentDate) {
|
|
25803
26111
|
currentDate = today;
|
|
25804
|
-
currentLogFile =
|
|
26112
|
+
currentLogFile = path8.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
25805
26113
|
cleanOldLogs();
|
|
25806
26114
|
}
|
|
25807
26115
|
}
|
|
@@ -25815,7 +26123,7 @@ function cleanOldLogs() {
|
|
|
25815
26123
|
const dateMatch = file2.match(/daemon-(\d{4}-\d{2}-\d{2})/);
|
|
25816
26124
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
25817
26125
|
try {
|
|
25818
|
-
fs2.unlinkSync(
|
|
26126
|
+
fs2.unlinkSync(path8.join(LOG_DIR, file2));
|
|
25819
26127
|
} catch {
|
|
25820
26128
|
}
|
|
25821
26129
|
}
|
|
@@ -25931,6 +26239,278 @@ function installGlobalInterceptor() {
|
|
|
25931
26239
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
25932
26240
|
writeToFile(`Log level: ${currentLevel}`);
|
|
25933
26241
|
}
|
|
26242
|
+
function drainPendingMeshCoordinatorEvents() {
|
|
26243
|
+
return pendingMeshCoordinatorEvents.splice(0);
|
|
26244
|
+
}
|
|
26245
|
+
function readNonEmptyString(value) {
|
|
26246
|
+
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
26247
|
+
}
|
|
26248
|
+
function isMeshCoordinatorEvent(eventName) {
|
|
26249
|
+
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
26250
|
+
}
|
|
26251
|
+
function formatCompletionMetadata(event) {
|
|
26252
|
+
const parts = [
|
|
26253
|
+
readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
|
|
26254
|
+
readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
|
|
26255
|
+
readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
|
|
26256
|
+
].filter(Boolean);
|
|
26257
|
+
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
26258
|
+
}
|
|
26259
|
+
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
26260
|
+
const task = claimNextTask(meshId, nodeId, sessionId);
|
|
26261
|
+
if (!task) return false;
|
|
26262
|
+
LOG.info("MeshQueue", `Node ${nodeId} (${sessionId}) pulled task ${task.id}`);
|
|
26263
|
+
components.cliManager.handleCliCommand("agent_command", {
|
|
26264
|
+
targetSessionId: sessionId,
|
|
26265
|
+
cliType: providerType,
|
|
26266
|
+
action: "send_chat",
|
|
26267
|
+
input: task.message
|
|
26268
|
+
}).catch((e) => {
|
|
26269
|
+
LOG.error("MeshQueue", `Failed to dispatch task to node ${nodeId}: ${e?.message}`);
|
|
26270
|
+
});
|
|
26271
|
+
return true;
|
|
26272
|
+
}
|
|
26273
|
+
function triggerMeshQueue(components, meshId) {
|
|
26274
|
+
const mesh = getMesh(meshId);
|
|
26275
|
+
if (!mesh) return;
|
|
26276
|
+
const cliInstances = components.instanceManager.getByCategory("cli");
|
|
26277
|
+
for (const inst of cliInstances) {
|
|
26278
|
+
const state = inst.getState();
|
|
26279
|
+
const settings = state.settings || {};
|
|
26280
|
+
const instMeshId = readNonEmptyString(settings.meshNodeFor);
|
|
26281
|
+
if (instMeshId !== meshId && !settings.launchedByCoordinator) continue;
|
|
26282
|
+
const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
|
|
26283
|
+
if (!nodeId) continue;
|
|
26284
|
+
if (state.status !== "idle" && state.status !== "stopped" && state.activeChat?.status !== "waiting_input") continue;
|
|
26285
|
+
const sessionId = state.instanceId;
|
|
26286
|
+
const providerType = state.type || readNonEmptyString(settings.providerType);
|
|
26287
|
+
if (providerType) {
|
|
26288
|
+
tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType);
|
|
26289
|
+
}
|
|
26290
|
+
}
|
|
26291
|
+
}
|
|
26292
|
+
function buildMeshSystemMessage(args) {
|
|
26293
|
+
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
26294
|
+
if (args.event === "agent:generating_completed") {
|
|
26295
|
+
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.`;
|
|
26296
|
+
}
|
|
26297
|
+
if (args.event === "agent:waiting_approval") {
|
|
26298
|
+
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
26299
|
+
}
|
|
26300
|
+
if (args.event === "agent:stopped") {
|
|
26301
|
+
const rc = args.recoveryContext;
|
|
26302
|
+
if (rc && rc.consecutiveNodeFailures > 0) {
|
|
26303
|
+
const parts = [
|
|
26304
|
+
`[System] ${args.nodeLabel} has stopped unexpectedly${metadata}.`,
|
|
26305
|
+
`
|
|
26306
|
+
|
|
26307
|
+
**Recovery Context:**`,
|
|
26308
|
+
`- Consecutive failures on this node: ${rc.consecutiveNodeFailures}`,
|
|
26309
|
+
rc.taskAttemptCount > 0 ? `- This task has been attempted ${rc.taskAttemptCount} time(s)` : "",
|
|
26310
|
+
`- Recommendation: ${rc.advice}`
|
|
26311
|
+
];
|
|
26312
|
+
if (rc.retryRecommended && rc.lastTaskMessage) {
|
|
26313
|
+
parts.push(
|
|
26314
|
+
`
|
|
26315
|
+
|
|
26316
|
+
**Original task to retry:**`,
|
|
26317
|
+
`> ${rc.lastTaskMessage.length > 300 ? rc.lastTaskMessage.slice(0, 300) + "..." : rc.lastTaskMessage}`,
|
|
26318
|
+
`
|
|
26319
|
+
To retry: call \`mesh_launch_session\` for this node, then \`mesh_send_task\` with the original task.`
|
|
26320
|
+
);
|
|
26321
|
+
} else if (!rc.retryRecommended) {
|
|
26322
|
+
parts.push(
|
|
26323
|
+
`
|
|
26324
|
+
Do NOT retry on this node. Consider reassigning to a different node or asking the user for guidance.`
|
|
26325
|
+
);
|
|
26326
|
+
}
|
|
26327
|
+
return parts.filter(Boolean).join("\n");
|
|
26328
|
+
}
|
|
26329
|
+
return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
|
|
26330
|
+
}
|
|
26331
|
+
if (args.event === "monitor:long_generating") {
|
|
26332
|
+
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.`;
|
|
26333
|
+
}
|
|
26334
|
+
return "";
|
|
26335
|
+
}
|
|
26336
|
+
function injectMeshSystemMessage(components, args) {
|
|
26337
|
+
if (args.event === "agent:generating_completed") {
|
|
26338
|
+
const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
|
|
26339
|
+
const nodeId = readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
26340
|
+
const providerType = readNonEmptyString(args.metadataEvent.providerType);
|
|
26341
|
+
if (sessionId) {
|
|
26342
|
+
updateSessionTaskStatus(args.meshId, sessionId, "completed");
|
|
26343
|
+
if (nodeId && providerType) {
|
|
26344
|
+
setTimeout(() => {
|
|
26345
|
+
tryAssignQueueTask(components, args.meshId, nodeId, sessionId, providerType);
|
|
26346
|
+
}, 500);
|
|
26347
|
+
}
|
|
26348
|
+
}
|
|
26349
|
+
} else if (args.event === "agent:stopped") {
|
|
26350
|
+
const sessionId = readNonEmptyString(args.metadataEvent.targetSessionId);
|
|
26351
|
+
if (sessionId) {
|
|
26352
|
+
updateSessionTaskStatus(args.meshId, sessionId, "failed");
|
|
26353
|
+
}
|
|
26354
|
+
}
|
|
26355
|
+
const ledgerKind = EVENT_TO_LEDGER_KIND[args.event];
|
|
26356
|
+
if (ledgerKind) {
|
|
26357
|
+
try {
|
|
26358
|
+
appendLedgerEntry(args.meshId, {
|
|
26359
|
+
kind: ledgerKind,
|
|
26360
|
+
nodeId: readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
26361
|
+
sessionId: readNonEmptyString(args.metadataEvent.targetSessionId) || void 0,
|
|
26362
|
+
providerType: readNonEmptyString(args.metadataEvent.providerType) || void 0,
|
|
26363
|
+
payload: {
|
|
26364
|
+
event: args.event,
|
|
26365
|
+
nodeLabel: args.nodeLabel,
|
|
26366
|
+
providerSessionId: readNonEmptyString(args.metadataEvent.providerSessionId) || void 0
|
|
26367
|
+
}
|
|
26368
|
+
});
|
|
26369
|
+
} catch (e) {
|
|
26370
|
+
LOG.warn("MeshLedger", `Failed to record ${ledgerKind}: ${e?.message || e}`);
|
|
26371
|
+
}
|
|
26372
|
+
}
|
|
26373
|
+
let recoveryContext = null;
|
|
26374
|
+
if (args.event === "agent:stopped") {
|
|
26375
|
+
try {
|
|
26376
|
+
const mesh = getMesh(args.meshId);
|
|
26377
|
+
const maxRetries = mesh?.policy?.maxTaskRetries ?? 1;
|
|
26378
|
+
recoveryContext = getSessionRecoveryContext(args.meshId, {
|
|
26379
|
+
sessionId: readNonEmptyString(args.metadataEvent.targetSessionId) || void 0,
|
|
26380
|
+
nodeId: readNonEmptyString(args.metadataEvent.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId) || void 0,
|
|
26381
|
+
maxRetries
|
|
26382
|
+
});
|
|
26383
|
+
recoveryContext.failedProviderType = readNonEmptyString(args.metadataEvent.providerType) || null;
|
|
26384
|
+
if (recoveryContext.retryRecommended && recoveryContext.consecutiveNodeFailures > 0) {
|
|
26385
|
+
appendLedgerEntry(args.meshId, {
|
|
26386
|
+
kind: "recovery_attempted",
|
|
26387
|
+
nodeId: recoveryContext.failedNodeId || void 0,
|
|
26388
|
+
sessionId: recoveryContext.failedSessionId || void 0,
|
|
26389
|
+
providerType: recoveryContext.failedProviderType || void 0,
|
|
26390
|
+
payload: {
|
|
26391
|
+
consecutiveFailures: recoveryContext.consecutiveNodeFailures,
|
|
26392
|
+
taskAttemptCount: recoveryContext.taskAttemptCount,
|
|
26393
|
+
retryRecommended: recoveryContext.retryRecommended,
|
|
26394
|
+
advice: recoveryContext.advice
|
|
26395
|
+
}
|
|
26396
|
+
});
|
|
26397
|
+
if (recoveryContext.lastTaskMessage && recoveryContext.failedNodeId && recoveryContext.failedProviderType) {
|
|
26398
|
+
const autoNodeId = recoveryContext.failedNodeId;
|
|
26399
|
+
try {
|
|
26400
|
+
const task = enqueueTask(args.meshId, recoveryContext.lastTaskMessage, {
|
|
26401
|
+
targetNodeId: autoNodeId
|
|
26402
|
+
});
|
|
26403
|
+
LOG.info("MeshRecovery", `Auto-requeued failed task: ${task.id} for node ${autoNodeId}`);
|
|
26404
|
+
const node = mesh?.nodes.find((n) => n.id === autoNodeId);
|
|
26405
|
+
if (node) {
|
|
26406
|
+
components.cliManager.handleCliCommand("launch_cli", {
|
|
26407
|
+
cliType: recoveryContext.failedProviderType,
|
|
26408
|
+
dir: node.workspace,
|
|
26409
|
+
settings: {
|
|
26410
|
+
meshNodeFor: args.meshId,
|
|
26411
|
+
meshNodeId: node.id,
|
|
26412
|
+
spawnedSessionVisibility: mesh?.policy?.spawnedSessionVisibility || "hidden",
|
|
26413
|
+
launchedByCoordinator: true
|
|
26414
|
+
}
|
|
26415
|
+
}).catch((e) => LOG.error("MeshRecovery", `Failed to auto-relaunch session for ${node.id}: ${e?.message}`));
|
|
26416
|
+
}
|
|
26417
|
+
} catch (e) {
|
|
26418
|
+
LOG.warn("MeshRecovery", `Failed to execute auto-recovery: ${e?.message}`);
|
|
26419
|
+
}
|
|
26420
|
+
}
|
|
26421
|
+
}
|
|
26422
|
+
LOG.info("MeshRecovery", `Recovery context for ${args.nodeLabel}: ${recoveryContext.advice}`);
|
|
26423
|
+
} catch (e) {
|
|
26424
|
+
LOG.warn("MeshRecovery", `Failed to build recovery context: ${e?.message || e}`);
|
|
26425
|
+
}
|
|
26426
|
+
}
|
|
26427
|
+
const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
26428
|
+
const instState = inst.getState();
|
|
26429
|
+
if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
|
|
26430
|
+
if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
|
|
26431
|
+
return true;
|
|
26432
|
+
});
|
|
26433
|
+
if (coordinatorInstances.length === 0) {
|
|
26434
|
+
if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
|
|
26435
|
+
pendingMeshCoordinatorEvents.push({
|
|
26436
|
+
event: args.event,
|
|
26437
|
+
meshId: args.meshId,
|
|
26438
|
+
nodeLabel: args.nodeLabel,
|
|
26439
|
+
metadataEvent: {
|
|
26440
|
+
...args.metadataEvent,
|
|
26441
|
+
...recoveryContext ? { recoveryContext } : {}
|
|
26442
|
+
},
|
|
26443
|
+
queuedAt: Date.now()
|
|
26444
|
+
});
|
|
26445
|
+
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
26446
|
+
}
|
|
26447
|
+
return { success: true, forwarded: 0 };
|
|
26448
|
+
}
|
|
26449
|
+
const messageText = buildMeshSystemMessage({
|
|
26450
|
+
event: args.event,
|
|
26451
|
+
nodeLabel: args.nodeLabel,
|
|
26452
|
+
metadataEvent: args.metadataEvent,
|
|
26453
|
+
recoveryContext
|
|
26454
|
+
});
|
|
26455
|
+
if (!messageText) return { success: false, error: "unsupported mesh event" };
|
|
26456
|
+
for (const coord of coordinatorInstances) {
|
|
26457
|
+
const coordState = coord.getState();
|
|
26458
|
+
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
26459
|
+
coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
|
|
26460
|
+
}
|
|
26461
|
+
return { success: true, forwarded: coordinatorInstances.length };
|
|
26462
|
+
}
|
|
26463
|
+
function handleMeshForwardEvent(components, payload) {
|
|
26464
|
+
const eventName = readNonEmptyString(payload.event);
|
|
26465
|
+
if (!isMeshCoordinatorEvent(eventName)) {
|
|
26466
|
+
return { success: false, error: "unsupported mesh event" };
|
|
26467
|
+
}
|
|
26468
|
+
const meshId = readNonEmptyString(payload.meshId);
|
|
26469
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
26470
|
+
const nodeId = readNonEmptyString(payload.nodeId);
|
|
26471
|
+
const workspace = readNonEmptyString(payload.workspace);
|
|
26472
|
+
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
26473
|
+
return injectMeshSystemMessage(components, {
|
|
26474
|
+
meshId,
|
|
26475
|
+
nodeLabel,
|
|
26476
|
+
event: eventName,
|
|
26477
|
+
metadataEvent: {
|
|
26478
|
+
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
26479
|
+
providerType: readNonEmptyString(payload.providerType),
|
|
26480
|
+
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
26481
|
+
}
|
|
26482
|
+
});
|
|
26483
|
+
}
|
|
26484
|
+
function setupMeshEventForwarding(components) {
|
|
26485
|
+
components.instanceManager.onEvent((event) => {
|
|
26486
|
+
if (!isMeshCoordinatorEvent(event.event)) return;
|
|
26487
|
+
const instanceId = readNonEmptyString(event.instanceId);
|
|
26488
|
+
if (!instanceId) return;
|
|
26489
|
+
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
26490
|
+
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
26491
|
+
const state = sourceInstance.getState();
|
|
26492
|
+
const workspace = readNonEmptyString(state.workspace);
|
|
26493
|
+
if (!workspace) return;
|
|
26494
|
+
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
26495
|
+
if (readNonEmptyString(settings.meshCoordinatorFor)) return;
|
|
26496
|
+
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
26497
|
+
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
26498
|
+
if (!isMeshDelegate) return;
|
|
26499
|
+
const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
26500
|
+
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
26501
|
+
if (!meshId) return;
|
|
26502
|
+
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
26503
|
+
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
26504
|
+
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
26505
|
+
injectMeshSystemMessage(components, {
|
|
26506
|
+
meshId,
|
|
26507
|
+
sourceInstanceId: instanceId,
|
|
26508
|
+
nodeLabel,
|
|
26509
|
+
event: event.event,
|
|
26510
|
+
metadataEvent: event
|
|
26511
|
+
});
|
|
26512
|
+
});
|
|
26513
|
+
}
|
|
25934
26514
|
function normalizeCategories(categories) {
|
|
25935
26515
|
if (!Array.isArray(categories)) return [];
|
|
25936
26516
|
return categories.map((category) => String(category || "").trim()).filter(Boolean);
|
|
@@ -26537,7 +27117,7 @@ async function validateWorkspace(workspace) {
|
|
|
26537
27117
|
cwd: normalizedWorkspace
|
|
26538
27118
|
});
|
|
26539
27119
|
}
|
|
26540
|
-
await (0, import_promises5.access)(normalizedWorkspace,
|
|
27120
|
+
await (0, import_promises5.access)(normalizedWorkspace, import_fs8.constants.R_OK);
|
|
26541
27121
|
} catch (error48) {
|
|
26542
27122
|
if (error48 instanceof GitCommandError) throw error48;
|
|
26543
27123
|
throw new GitCommandError("invalid_args", "Workspace must be an existing directory", {
|
|
@@ -27150,12 +27730,12 @@ function createDefaultGitCommandServices() {
|
|
|
27150
27730
|
}),
|
|
27151
27731
|
compareSnapshots: ({ beforeSnapshotId, afterSnapshotId }) => defaultSnapshotStore.compare(beforeSnapshotId, afterSnapshotId),
|
|
27152
27732
|
getLog: ({ workspace, limit, path: filePath, since, until }) => getGitLog(workspace, { limit, path: filePath, since, until }),
|
|
27153
|
-
checkpoint: async ({ workspace, message, includeUntracked = false }) =>
|
|
27733
|
+
checkpoint: async ({ workspace, message, includeUntracked = false }) => gitCheckpoint(workspace, message, includeUntracked),
|
|
27154
27734
|
stashPush: async ({ workspace, message, includeUntracked = false }) => gitStashPush(workspace, message, includeUntracked),
|
|
27155
27735
|
stashPop: async ({ workspace, stashRef }) => gitStashPop(workspace, stashRef),
|
|
27156
27736
|
checkoutFiles: async ({ workspace, paths }) => gitCheckoutFiles(workspace, paths),
|
|
27157
27737
|
getRemoteUrl: async ({ workspace, remote = "origin" }) => gitGetRemoteUrl(workspace, remote),
|
|
27158
|
-
push: async ({ workspace, remote = "origin", branch, setUpstream = false }) =>
|
|
27738
|
+
push: async ({ workspace, remote = "origin", branch, setUpstream = false }) => gitPush(workspace, remote, branch, setUpstream)
|
|
27159
27739
|
};
|
|
27160
27740
|
}
|
|
27161
27741
|
function validateWorkspace2(args) {
|
|
@@ -27350,7 +27930,7 @@ function validateMutatingMessage(value) {
|
|
|
27350
27930
|
}
|
|
27351
27931
|
return msg;
|
|
27352
27932
|
}
|
|
27353
|
-
async function
|
|
27933
|
+
async function gitCheckpoint(workspace, message, includeUntracked) {
|
|
27354
27934
|
const repo = await resolveGitRepository(workspace);
|
|
27355
27935
|
const repoRoot = repo.repoRoot;
|
|
27356
27936
|
const statusResult = await getGitRepoStatus(workspace);
|
|
@@ -27441,7 +28021,7 @@ async function gitGetRemoteUrl(workspace, remote) {
|
|
|
27441
28021
|
}
|
|
27442
28022
|
return { remoteUrl, remote };
|
|
27443
28023
|
}
|
|
27444
|
-
async function
|
|
28024
|
+
async function gitPush(workspace, remote, branch, setUpstream) {
|
|
27445
28025
|
const lastCheckedAt = Date.now();
|
|
27446
28026
|
const repo = await resolveGitRepository(workspace);
|
|
27447
28027
|
const repoRoot = repo.repoRoot;
|
|
@@ -27544,7 +28124,7 @@ function validateGitLogPath(repoRoot, filePath) {
|
|
|
27544
28124
|
function expandPath(p) {
|
|
27545
28125
|
const t = (p || "").trim();
|
|
27546
28126
|
if (!t) return "";
|
|
27547
|
-
if (t.startsWith("~")) return path5.join(
|
|
28127
|
+
if (t.startsWith("~")) return path5.join(os4.homedir(), t.slice(1).replace(/^\//, ""));
|
|
27548
28128
|
return path5.resolve(t);
|
|
27549
28129
|
}
|
|
27550
28130
|
function validateWorkspacePath(absPath) {
|
|
@@ -27617,7 +28197,7 @@ function resolveLaunchDirectory(args, config2) {
|
|
|
27617
28197
|
};
|
|
27618
28198
|
}
|
|
27619
28199
|
if (a.useHome === true) {
|
|
27620
|
-
return { ok: true, path:
|
|
28200
|
+
return { ok: true, path: os4.homedir(), source: "home" };
|
|
27621
28201
|
}
|
|
27622
28202
|
return {
|
|
27623
28203
|
ok: false,
|
|
@@ -27675,7 +28255,7 @@ function addWorkspaceEntry(config2, rawPath, label, options) {
|
|
|
27675
28255
|
return { error: `Maximum ${MAX_WORKSPACES} workspaces` };
|
|
27676
28256
|
}
|
|
27677
28257
|
const entry = {
|
|
27678
|
-
id: (0,
|
|
28258
|
+
id: (0, import_crypto6.randomUUID)(),
|
|
27679
28259
|
path: abs,
|
|
27680
28260
|
label: (label || "").trim() || defaultWorkspaceLabel(abs),
|
|
27681
28261
|
addedAt: Date.now()
|
|
@@ -28030,13 +28610,31 @@ async function syncMeshes(transport) {
|
|
|
28030
28610
|
}
|
|
28031
28611
|
}
|
|
28032
28612
|
}
|
|
28613
|
+
if (transport.syncMeshLedger) {
|
|
28614
|
+
for (const local of localMeshes) {
|
|
28615
|
+
try {
|
|
28616
|
+
await syncMeshLedger(local.id, transport);
|
|
28617
|
+
} catch (e) {
|
|
28618
|
+
result.errors.push(`Ledger sync failed for "${local.name}": ${e.message}`);
|
|
28619
|
+
}
|
|
28620
|
+
}
|
|
28621
|
+
}
|
|
28033
28622
|
return result;
|
|
28034
28623
|
}
|
|
28624
|
+
async function syncMeshLedger(meshId, transport) {
|
|
28625
|
+
if (!transport.syncMeshLedger) return;
|
|
28626
|
+
const { readLedgerEntries: readLedgerEntries2, appendRemoteLedgerEntries: appendRemoteLedgerEntries2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
28627
|
+
const localEntries = readLedgerEntries2(meshId);
|
|
28628
|
+
const res = await transport.syncMeshLedger(meshId, { newEntries: localEntries });
|
|
28629
|
+
if (res.missingEntries && res.missingEntries.length > 0) {
|
|
28630
|
+
appendRemoteLedgerEntries2(meshId, res.missingEntries);
|
|
28631
|
+
}
|
|
28632
|
+
}
|
|
28035
28633
|
function isPlainObject22(value) {
|
|
28036
28634
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
28037
28635
|
}
|
|
28038
28636
|
function getStatePath() {
|
|
28039
|
-
return (0,
|
|
28637
|
+
return (0, import_path5.join)(getConfigDir(), "state.json");
|
|
28040
28638
|
}
|
|
28041
28639
|
function normalizeState(raw) {
|
|
28042
28640
|
const parsed = isPlainObject22(raw) ? raw : {};
|
|
@@ -28072,11 +28670,11 @@ function normalizeState(raw) {
|
|
|
28072
28670
|
}
|
|
28073
28671
|
function loadState() {
|
|
28074
28672
|
const statePath = getStatePath();
|
|
28075
|
-
if (!(0,
|
|
28673
|
+
if (!(0, import_fs9.existsSync)(statePath)) {
|
|
28076
28674
|
return { ...DEFAULT_STATE };
|
|
28077
28675
|
}
|
|
28078
28676
|
try {
|
|
28079
|
-
const raw = (0,
|
|
28677
|
+
const raw = (0, import_fs9.readFileSync)(statePath, "utf-8");
|
|
28080
28678
|
return normalizeState(JSON.parse(raw));
|
|
28081
28679
|
} catch {
|
|
28082
28680
|
return { ...DEFAULT_STATE };
|
|
@@ -28085,7 +28683,7 @@ function loadState() {
|
|
|
28085
28683
|
function saveState(state) {
|
|
28086
28684
|
const statePath = getStatePath();
|
|
28087
28685
|
const normalized = normalizeState(state);
|
|
28088
|
-
(0,
|
|
28686
|
+
(0, import_fs9.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
|
|
28089
28687
|
}
|
|
28090
28688
|
function resetState() {
|
|
28091
28689
|
saveState({ ...DEFAULT_STATE });
|
|
@@ -28106,10 +28704,10 @@ function getMergedDefinitions() {
|
|
|
28106
28704
|
function findCliCommand(command) {
|
|
28107
28705
|
const trimmed = String(command || "").trim();
|
|
28108
28706
|
if (!trimmed) return null;
|
|
28109
|
-
if (
|
|
28110
|
-
const candidate = trimmed.startsWith("~") ?
|
|
28111
|
-
const resolved =
|
|
28112
|
-
return (0,
|
|
28707
|
+
if (path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
|
|
28708
|
+
const candidate = trimmed.startsWith("~") ? path9.join((0, import_os3.homedir)(), trimmed.slice(1)) : trimmed;
|
|
28709
|
+
const resolved = path9.isAbsolute(candidate) ? candidate : path9.resolve(candidate);
|
|
28710
|
+
return (0, import_fs10.existsSync)(resolved) ? resolved : null;
|
|
28113
28711
|
}
|
|
28114
28712
|
try {
|
|
28115
28713
|
const result = (0, import_child_process4.execSync)(
|
|
@@ -28136,13 +28734,13 @@ function getIdeVersion(cliCommand) {
|
|
|
28136
28734
|
function checkPathExists(paths) {
|
|
28137
28735
|
const home = (0, import_os3.homedir)();
|
|
28138
28736
|
for (const p of paths) {
|
|
28139
|
-
const normalized = p.startsWith("~") ?
|
|
28737
|
+
const normalized = p.startsWith("~") ? path9.join(home, p.slice(1)) : p;
|
|
28140
28738
|
if (normalized.includes("*")) {
|
|
28141
28739
|
const username = home.split(/[\\/]/).pop() || "";
|
|
28142
28740
|
const resolved = normalized.replace("*", username);
|
|
28143
|
-
if ((0,
|
|
28741
|
+
if ((0, import_fs10.existsSync)(resolved)) return resolved;
|
|
28144
28742
|
} else {
|
|
28145
|
-
if ((0,
|
|
28743
|
+
if ((0, import_fs10.existsSync)(normalized)) return normalized;
|
|
28146
28744
|
}
|
|
28147
28745
|
}
|
|
28148
28746
|
return null;
|
|
@@ -28156,7 +28754,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28156
28754
|
let resolvedCli = cliPath;
|
|
28157
28755
|
if (!resolvedCli && appPath && os222 === "darwin") {
|
|
28158
28756
|
const bundledCli = `${appPath}/Contents/Resources/app/bin/${def.cli}`;
|
|
28159
|
-
if ((0,
|
|
28757
|
+
if ((0, import_fs10.existsSync)(bundledCli)) resolvedCli = bundledCli;
|
|
28160
28758
|
}
|
|
28161
28759
|
if (!resolvedCli && appPath && os222 === "win32") {
|
|
28162
28760
|
const { dirname: dirname92 } = await import("path");
|
|
@@ -28169,7 +28767,7 @@ async function detectIDEs(providerLoader) {
|
|
|
28169
28767
|
`${appDir}\\\\resources\\\\app\\\\bin\\\\${def.cli}.cmd`
|
|
28170
28768
|
];
|
|
28171
28769
|
for (const c of candidates) {
|
|
28172
|
-
if ((0,
|
|
28770
|
+
if ((0, import_fs10.existsSync)(c)) {
|
|
28173
28771
|
resolvedCli = c;
|
|
28174
28772
|
break;
|
|
28175
28773
|
}
|
|
@@ -28201,19 +28799,19 @@ function shellQuote(value) {
|
|
|
28201
28799
|
function expandHome(value) {
|
|
28202
28800
|
const trimmed = value.trim();
|
|
28203
28801
|
if (!trimmed.startsWith("~")) return trimmed;
|
|
28204
|
-
return
|
|
28802
|
+
return path10.join(os32.homedir(), trimmed.slice(1));
|
|
28205
28803
|
}
|
|
28206
28804
|
function isExplicitCommandPath(command) {
|
|
28207
28805
|
const trimmed = command.trim();
|
|
28208
|
-
return
|
|
28806
|
+
return path10.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
|
|
28209
28807
|
}
|
|
28210
28808
|
function resolveCommandPath(command) {
|
|
28211
28809
|
const trimmed = command.trim();
|
|
28212
28810
|
if (!trimmed) return null;
|
|
28213
28811
|
if (isExplicitCommandPath(trimmed)) {
|
|
28214
28812
|
const expanded = expandHome(trimmed);
|
|
28215
|
-
const candidate =
|
|
28216
|
-
return (0,
|
|
28813
|
+
const candidate = path10.isAbsolute(expanded) ? expanded : path10.resolve(expanded);
|
|
28814
|
+
return (0, import_fs11.existsSync)(candidate) ? candidate : null;
|
|
28217
28815
|
}
|
|
28218
28816
|
return null;
|
|
28219
28817
|
}
|
|
@@ -28234,7 +28832,7 @@ function execAsync(cmd, timeoutMs = 5e3) {
|
|
|
28234
28832
|
});
|
|
28235
28833
|
}
|
|
28236
28834
|
async function detectCLIs(providerLoader, options) {
|
|
28237
|
-
const platform10 =
|
|
28835
|
+
const platform10 = os32.platform();
|
|
28238
28836
|
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
28239
28837
|
const includeVersion = options?.includeVersion !== false;
|
|
28240
28838
|
const cliList = providerLoader ? providerLoader.getCliDetectionList() : [];
|
|
@@ -28278,7 +28876,7 @@ async function detectCLI(cliId, providerLoader, options) {
|
|
|
28278
28876
|
const cliList = providerLoader.getCliDetectionList();
|
|
28279
28877
|
const target = cliList.find((c) => c.id === resolvedId);
|
|
28280
28878
|
if (target) {
|
|
28281
|
-
const platform10 =
|
|
28879
|
+
const platform10 = os32.platform();
|
|
28282
28880
|
const whichCmd = platform10 === "win32" ? "where" : "which";
|
|
28283
28881
|
try {
|
|
28284
28882
|
const explicitPath = resolveCommandPath(target.command);
|
|
@@ -28314,7 +28912,7 @@ async function detectCLI(cliId, providerLoader, options) {
|
|
|
28314
28912
|
return all.find((c) => c.id === resolvedId && c.installed) || null;
|
|
28315
28913
|
}
|
|
28316
28914
|
function parseDarwinAvailableBytes(totalMem) {
|
|
28317
|
-
if (
|
|
28915
|
+
if (os42.platform() !== "darwin") return null;
|
|
28318
28916
|
try {
|
|
28319
28917
|
const out = (0, import_child_process6.execSync)("vm_stat", {
|
|
28320
28918
|
encoding: "utf-8",
|
|
@@ -28345,8 +28943,8 @@ function parseDarwinAvailableBytes(totalMem) {
|
|
|
28345
28943
|
}
|
|
28346
28944
|
}
|
|
28347
28945
|
function getHostMemorySnapshot() {
|
|
28348
|
-
const totalMem =
|
|
28349
|
-
const freeMem =
|
|
28946
|
+
const totalMem = os42.totalmem();
|
|
28947
|
+
const freeMem = os42.freemem();
|
|
28350
28948
|
const darwinAvail = parseDarwinAvailableBytes(totalMem);
|
|
28351
28949
|
const availableMem = darwinAvail != null ? darwinAvail : freeMem;
|
|
28352
28950
|
return { totalMem, freeMem, availableMem };
|
|
@@ -30678,6 +31276,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
30678
31276
|
const workspace = state.workspace || null;
|
|
30679
31277
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
30680
31278
|
const title = activeChat?.title || state.name;
|
|
31279
|
+
const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
|
|
31280
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
30681
31281
|
return {
|
|
30682
31282
|
id: state.instanceId || state.type,
|
|
30683
31283
|
parentId: null,
|
|
@@ -30700,7 +31300,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
|
|
|
30700
31300
|
errorMessage: state.errorMessage,
|
|
30701
31301
|
errorReason: state.errorReason,
|
|
30702
31302
|
lastUpdated: state.lastUpdated,
|
|
30703
|
-
settings: state.settings
|
|
31303
|
+
settings: state.settings,
|
|
31304
|
+
...meshQueueStats && { meshQueueStats }
|
|
30704
31305
|
};
|
|
30705
31306
|
}
|
|
30706
31307
|
function buildExtensionAgentSession(parent, ext, options) {
|
|
@@ -30712,6 +31313,8 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
30712
31313
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
30713
31314
|
const workspace = parent.workspace || null;
|
|
30714
31315
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
31316
|
+
const meshCoordinatorFor = ext.settings?.meshCoordinatorFor;
|
|
31317
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
30715
31318
|
return {
|
|
30716
31319
|
id: ext.instanceId || `${parent.instanceId}:${ext.type}`,
|
|
30717
31320
|
parentId: parent.instanceId || parent.type,
|
|
@@ -30734,7 +31337,8 @@ function buildExtensionAgentSession(parent, ext, options) {
|
|
|
30734
31337
|
errorMessage: ext.errorMessage,
|
|
30735
31338
|
errorReason: ext.errorReason,
|
|
30736
31339
|
lastUpdated: ext.lastUpdated,
|
|
30737
|
-
settings: ext.settings
|
|
31340
|
+
settings: ext.settings,
|
|
31341
|
+
...meshQueueStats && { meshQueueStats }
|
|
30738
31342
|
};
|
|
30739
31343
|
}
|
|
30740
31344
|
function shouldIncludeExtensionSession(ext) {
|
|
@@ -30762,6 +31366,8 @@ function buildCliSession(state, options) {
|
|
|
30762
31366
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
30763
31367
|
const workspace = state.workspace || null;
|
|
30764
31368
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
31369
|
+
const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
|
|
31370
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
30765
31371
|
return {
|
|
30766
31372
|
id: state.instanceId,
|
|
30767
31373
|
parentId: null,
|
|
@@ -30800,7 +31406,8 @@ function buildCliSession(state, options) {
|
|
|
30800
31406
|
errorMessage: state.errorMessage,
|
|
30801
31407
|
errorReason: state.errorReason,
|
|
30802
31408
|
lastUpdated: state.lastUpdated,
|
|
30803
|
-
settings: state.settings
|
|
31409
|
+
settings: state.settings,
|
|
31410
|
+
...meshQueueStats && { meshQueueStats }
|
|
30804
31411
|
};
|
|
30805
31412
|
}
|
|
30806
31413
|
function buildAcpSession(state, options) {
|
|
@@ -30812,6 +31419,8 @@ function buildAcpSession(state, options) {
|
|
|
30812
31419
|
const includeSessionControls = shouldIncludeSessionControls(profile);
|
|
30813
31420
|
const workspace = state.workspace || null;
|
|
30814
31421
|
const git = getGitSummaryForWorkspace(workspace, options);
|
|
31422
|
+
const meshCoordinatorFor = state.settings?.meshCoordinatorFor;
|
|
31423
|
+
const meshQueueStats = meshCoordinatorFor ? getMeshQueueStats(meshCoordinatorFor) : void 0;
|
|
30815
31424
|
return {
|
|
30816
31425
|
id: state.instanceId,
|
|
30817
31426
|
parentId: null,
|
|
@@ -30833,7 +31442,8 @@ function buildAcpSession(state, options) {
|
|
|
30833
31442
|
errorMessage: state.errorMessage,
|
|
30834
31443
|
errorReason: state.errorReason,
|
|
30835
31444
|
lastUpdated: state.lastUpdated,
|
|
30836
|
-
settings: state.settings
|
|
31445
|
+
settings: state.settings,
|
|
31446
|
+
...meshQueueStats && { meshQueueStats }
|
|
30837
31447
|
};
|
|
30838
31448
|
}
|
|
30839
31449
|
function buildSessionEntries(allStates, cdpManagers, options = {}) {
|
|
@@ -31435,7 +32045,7 @@ function safeBundleIdSegment(value, fallback) {
|
|
|
31435
32045
|
function createChatDebugBundleId(targetSessionId) {
|
|
31436
32046
|
const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:.]/g, "").replace("T", "T").replace("Z", "Z");
|
|
31437
32047
|
const sessionSegment = safeBundleIdSegment(targetSessionId, "unknown-session");
|
|
31438
|
-
return `chat-debug-${timestamp2}-${sessionSegment}-${(0,
|
|
32048
|
+
return `chat-debug-${timestamp2}-${sessionSegment}-${(0, import_crypto7.randomUUID)().slice(0, 8)}`;
|
|
31439
32049
|
}
|
|
31440
32050
|
function buildChatDebugBundleSummary(bundle) {
|
|
31441
32051
|
const target = bundle.target && typeof bundle.target === "object" ? bundle.target : {};
|
|
@@ -33891,7 +34501,7 @@ function commandExists(command) {
|
|
|
33891
34501
|
const trimmed = command.trim();
|
|
33892
34502
|
if (!trimmed) return false;
|
|
33893
34503
|
if (isExplicitCommand(trimmed)) {
|
|
33894
|
-
return (0,
|
|
34504
|
+
return (0, import_fs12.existsSync)(expandExecutable(trimmed));
|
|
33895
34505
|
}
|
|
33896
34506
|
try {
|
|
33897
34507
|
(0, import_child_process7.execFileSync)(process.platform === "win32" ? "where" : "which", [trimmed], {
|
|
@@ -33912,10 +34522,10 @@ function hasCliArg(args, flag) {
|
|
|
33912
34522
|
}
|
|
33913
34523
|
function ensureEmptyDelegatedMcpConfig(workspace) {
|
|
33914
34524
|
const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
|
|
33915
|
-
(0,
|
|
34525
|
+
(0, import_fs12.mkdirSync)(baseDir, { recursive: true });
|
|
33916
34526
|
const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
|
|
33917
34527
|
const filePath = path18.join(baseDir, `${workspaceHash}.json`);
|
|
33918
|
-
(0,
|
|
34528
|
+
(0, import_fs12.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
|
|
33919
34529
|
return filePath;
|
|
33920
34530
|
}
|
|
33921
34531
|
function buildCoordinatorDelegatedCliLaunchOptions(input) {
|
|
@@ -34876,7 +35486,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
|
|
|
34876
35486
|
reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
|
|
34877
35487
|
};
|
|
34878
35488
|
}
|
|
34879
|
-
const configPath = (0,
|
|
35489
|
+
const configPath = (0, import_path6.join)(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
|
|
34880
35490
|
if (!configPath.trim()) {
|
|
34881
35491
|
return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
|
|
34882
35492
|
}
|
|
@@ -34982,16 +35592,16 @@ function renderMeshCoordinatorTemplate(template, values) {
|
|
|
34982
35592
|
}
|
|
34983
35593
|
function resolveHermesCoordinatorHome(meshId, workspace) {
|
|
34984
35594
|
const key = `${meshId || "mesh"}
|
|
34985
|
-
${(0,
|
|
34986
|
-
const hash2 = (0,
|
|
34987
|
-
return (0,
|
|
35595
|
+
${(0, import_path6.resolve)(workspace || os17.tmpdir())}`;
|
|
35596
|
+
const hash2 = (0, import_crypto8.createHash)("sha256").update(key).digest("hex").slice(0, 16);
|
|
35597
|
+
return (0, import_path6.join)(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash2}`);
|
|
34988
35598
|
}
|
|
34989
35599
|
function resolveMcpConfigPath(configPath, workspace) {
|
|
34990
35600
|
const trimmed = configPath.trim();
|
|
34991
35601
|
if (trimmed === "~") return os17.homedir();
|
|
34992
|
-
if (trimmed.startsWith("~/")) return (0,
|
|
34993
|
-
if ((0,
|
|
34994
|
-
return (0,
|
|
35602
|
+
if (trimmed.startsWith("~/")) return (0, import_path6.join)(os17.homedir(), trimmed.slice(2));
|
|
35603
|
+
if ((0, import_path6.isAbsolute)(trimmed)) return trimmed;
|
|
35604
|
+
return (0, import_path6.join)(workspace, trimmed);
|
|
34995
35605
|
}
|
|
34996
35606
|
function resolveAdhdevMcpServerLaunch(options) {
|
|
34997
35607
|
const entryPath = resolveAdhdevMcpEntryPath(options.adhdevMcpEntryPath);
|
|
@@ -35031,15 +35641,15 @@ function addNodeCandidatesFromPath(pathValue, addCandidate) {
|
|
|
35031
35641
|
for (const entry of (pathValue || "").split(":")) {
|
|
35032
35642
|
const dir = entry.trim();
|
|
35033
35643
|
if (!dir) continue;
|
|
35034
|
-
addCandidate((0,
|
|
35644
|
+
addCandidate((0, import_path6.join)(dir, "node"));
|
|
35035
35645
|
}
|
|
35036
35646
|
}
|
|
35037
35647
|
function addNodeCandidatesFromNvm(homeDir, addCandidate) {
|
|
35038
|
-
const versionsDir = (0,
|
|
35648
|
+
const versionsDir = (0, import_path6.join)(homeDir, ".nvm", "versions", "node");
|
|
35039
35649
|
try {
|
|
35040
|
-
const versionDirs = (0,
|
|
35650
|
+
const versionDirs = (0, import_fs13.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
|
|
35041
35651
|
for (const versionDir of versionDirs) {
|
|
35042
|
-
addCandidate((0,
|
|
35652
|
+
addCandidate((0, import_path6.join)(versionsDir, versionDir, "bin", "node"));
|
|
35043
35653
|
}
|
|
35044
35654
|
} catch {
|
|
35045
35655
|
}
|
|
@@ -35077,12 +35687,12 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
35077
35687
|
const addPackagedCandidates = (baseFile) => {
|
|
35078
35688
|
if (!baseFile) return;
|
|
35079
35689
|
const realBase = normalizeExistingPath(baseFile) || baseFile;
|
|
35080
|
-
const dir = (0,
|
|
35081
|
-
addCandidate((0,
|
|
35082
|
-
addCandidate((0,
|
|
35083
|
-
addCandidate((0,
|
|
35084
|
-
addCandidate((0,
|
|
35085
|
-
addCandidate((0,
|
|
35690
|
+
const dir = (0, import_path6.dirname)(realBase);
|
|
35691
|
+
addCandidate((0, import_path6.resolve)(dir, "../vendor/mcp-server/index.js"));
|
|
35692
|
+
addCandidate((0, import_path6.resolve)(dir, "../../vendor/mcp-server/index.js"));
|
|
35693
|
+
addCandidate((0, import_path6.resolve)(dir, "../../../vendor/mcp-server/index.js"));
|
|
35694
|
+
addCandidate((0, import_path6.resolve)(dir, "../../mcp-server/dist/index.js"));
|
|
35695
|
+
addCandidate((0, import_path6.resolve)(dir, "../../../mcp-server/dist/index.js"));
|
|
35086
35696
|
};
|
|
35087
35697
|
addPackagedCandidates(process.argv[1]);
|
|
35088
35698
|
for (const candidate of candidates) {
|
|
@@ -35090,7 +35700,7 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
35090
35700
|
if (normalized) return normalized;
|
|
35091
35701
|
}
|
|
35092
35702
|
try {
|
|
35093
|
-
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : (0,
|
|
35703
|
+
const requireBase = process.argv[1] ? normalizeExistingPath(process.argv[1]) || process.argv[1] : (0, import_path6.join)(process.cwd(), "adhdev-daemon.js");
|
|
35094
35704
|
const req = (0, import_module2.createRequire)(requireBase);
|
|
35095
35705
|
const resolvedModule = req.resolve("@adhdev/mcp-server");
|
|
35096
35706
|
return normalizeExistingPath(resolvedModule) || resolvedModule;
|
|
@@ -35100,129 +35710,12 @@ function resolveAdhdevMcpEntryPath(explicitPath) {
|
|
|
35100
35710
|
}
|
|
35101
35711
|
function normalizeExistingPath(filePath) {
|
|
35102
35712
|
try {
|
|
35103
|
-
if (!(0,
|
|
35104
|
-
return
|
|
35713
|
+
if (!(0, import_fs13.existsSync)(filePath)) return null;
|
|
35714
|
+
return import_fs13.realpathSync.native(filePath);
|
|
35105
35715
|
} catch {
|
|
35106
35716
|
return null;
|
|
35107
35717
|
}
|
|
35108
35718
|
}
|
|
35109
|
-
function drainPendingMeshCoordinatorEvents() {
|
|
35110
|
-
return pendingMeshCoordinatorEvents.splice(0);
|
|
35111
|
-
}
|
|
35112
|
-
function readNonEmptyString(value) {
|
|
35113
|
-
return typeof value === "string" && value.trim() ? value.trim() : "";
|
|
35114
|
-
}
|
|
35115
|
-
function isMeshCoordinatorEvent(eventName) {
|
|
35116
|
-
return typeof eventName === "string" && MESH_COORDINATOR_EVENTS.has(eventName);
|
|
35117
|
-
}
|
|
35118
|
-
function formatCompletionMetadata(event) {
|
|
35119
|
-
const parts = [
|
|
35120
|
-
readNonEmptyString(event.targetSessionId) ? `session_id=${readNonEmptyString(event.targetSessionId)}` : "",
|
|
35121
|
-
readNonEmptyString(event.providerType) ? `provider=${readNonEmptyString(event.providerType)}` : "",
|
|
35122
|
-
readNonEmptyString(event.providerSessionId) ? `provider_session_id=${readNonEmptyString(event.providerSessionId)}` : ""
|
|
35123
|
-
].filter(Boolean);
|
|
35124
|
-
return parts.length > 0 ? ` (${parts.join("; ")})` : "";
|
|
35125
|
-
}
|
|
35126
|
-
function buildMeshSystemMessage(args) {
|
|
35127
|
-
const metadata = formatCompletionMetadata(args.metadataEvent);
|
|
35128
|
-
if (args.event === "agent:generating_completed") {
|
|
35129
|
-
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.`;
|
|
35130
|
-
}
|
|
35131
|
-
if (args.event === "agent:waiting_approval") {
|
|
35132
|
-
return `[System] ${args.nodeLabel} is waiting for approval to proceed${metadata}. You may use mesh_read_chat and mesh_approve to handle it.`;
|
|
35133
|
-
}
|
|
35134
|
-
if (args.event === "agent:stopped") {
|
|
35135
|
-
return `[System] ${args.nodeLabel} has stopped${metadata}. Use mesh_read_chat once if you need to inspect its last output.`;
|
|
35136
|
-
}
|
|
35137
|
-
if (args.event === "monitor:long_generating") {
|
|
35138
|
-
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.`;
|
|
35139
|
-
}
|
|
35140
|
-
return "";
|
|
35141
|
-
}
|
|
35142
|
-
function injectMeshSystemMessage(components, args) {
|
|
35143
|
-
const coordinatorInstances = components.instanceManager.getByCategory("cli").filter((inst) => {
|
|
35144
|
-
const instState = inst.getState();
|
|
35145
|
-
if (instState.settings?.meshCoordinatorFor !== args.meshId) return false;
|
|
35146
|
-
if (args.sourceInstanceId && instState.instanceId === args.sourceInstanceId) return false;
|
|
35147
|
-
return true;
|
|
35148
|
-
});
|
|
35149
|
-
if (coordinatorInstances.length === 0) {
|
|
35150
|
-
if (pendingMeshCoordinatorEvents.length < MAX_PENDING_EVENTS) {
|
|
35151
|
-
pendingMeshCoordinatorEvents.push({
|
|
35152
|
-
event: args.event,
|
|
35153
|
-
meshId: args.meshId,
|
|
35154
|
-
nodeLabel: args.nodeLabel,
|
|
35155
|
-
metadataEvent: args.metadataEvent,
|
|
35156
|
-
queuedAt: Date.now()
|
|
35157
|
-
});
|
|
35158
|
-
LOG.info("MeshEvents", `Queued ${args.event} for MCP coordinator (mesh ${args.meshId})`);
|
|
35159
|
-
}
|
|
35160
|
-
return { success: true, forwarded: 0 };
|
|
35161
|
-
}
|
|
35162
|
-
const messageText = buildMeshSystemMessage({
|
|
35163
|
-
event: args.event,
|
|
35164
|
-
nodeLabel: args.nodeLabel,
|
|
35165
|
-
metadataEvent: args.metadataEvent
|
|
35166
|
-
});
|
|
35167
|
-
if (!messageText) return { success: false, error: "unsupported mesh event" };
|
|
35168
|
-
for (const coord of coordinatorInstances) {
|
|
35169
|
-
const coordState = coord.getState();
|
|
35170
|
-
LOG.info("MeshEvents", `Forwarding mesh event to coordinator ${coordState.instanceId}`);
|
|
35171
|
-
coord.onEvent("send_message", { input: { text: messageText, textFallback: messageText } });
|
|
35172
|
-
}
|
|
35173
|
-
return { success: true, forwarded: coordinatorInstances.length };
|
|
35174
|
-
}
|
|
35175
|
-
function handleMeshForwardEvent(components, payload) {
|
|
35176
|
-
const eventName = readNonEmptyString(payload.event);
|
|
35177
|
-
if (!isMeshCoordinatorEvent(eventName)) {
|
|
35178
|
-
return { success: false, error: "unsupported mesh event" };
|
|
35179
|
-
}
|
|
35180
|
-
const meshId = readNonEmptyString(payload.meshId);
|
|
35181
|
-
if (!meshId) return { success: false, error: "meshId required" };
|
|
35182
|
-
const nodeId = readNonEmptyString(payload.nodeId);
|
|
35183
|
-
const workspace = readNonEmptyString(payload.workspace);
|
|
35184
|
-
const nodeLabel = nodeId ? `Node '${nodeId}'` : workspace ? `Agent at ${workspace}` : "Remote agent";
|
|
35185
|
-
return injectMeshSystemMessage(components, {
|
|
35186
|
-
meshId,
|
|
35187
|
-
nodeLabel,
|
|
35188
|
-
event: eventName,
|
|
35189
|
-
metadataEvent: {
|
|
35190
|
-
targetSessionId: readNonEmptyString(payload.targetSessionId) || readNonEmptyString(payload.sessionId),
|
|
35191
|
-
providerType: readNonEmptyString(payload.providerType),
|
|
35192
|
-
providerSessionId: readNonEmptyString(payload.providerSessionId)
|
|
35193
|
-
}
|
|
35194
|
-
});
|
|
35195
|
-
}
|
|
35196
|
-
function setupMeshEventForwarding(components) {
|
|
35197
|
-
components.instanceManager.onEvent((event) => {
|
|
35198
|
-
if (!isMeshCoordinatorEvent(event.event)) return;
|
|
35199
|
-
const instanceId = readNonEmptyString(event.instanceId);
|
|
35200
|
-
if (!instanceId) return;
|
|
35201
|
-
const sourceInstance = components.instanceManager.getInstance(instanceId);
|
|
35202
|
-
if (!sourceInstance || sourceInstance.category !== "cli") return;
|
|
35203
|
-
const state = sourceInstance.getState();
|
|
35204
|
-
const workspace = readNonEmptyString(state.workspace);
|
|
35205
|
-
if (!workspace) return;
|
|
35206
|
-
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
35207
|
-
if (readNonEmptyString(settings.meshCoordinatorFor)) return;
|
|
35208
|
-
const meshIdFromRuntime = readNonEmptyString(settings.meshNodeFor);
|
|
35209
|
-
const isMeshDelegate = Boolean(meshIdFromRuntime || settings.launchedByCoordinator);
|
|
35210
|
-
if (!isMeshDelegate) return;
|
|
35211
|
-
const mesh = meshIdFromRuntime ? getMesh(meshIdFromRuntime) : getMeshByRepo(workspace);
|
|
35212
|
-
const meshId = meshIdFromRuntime || readNonEmptyString(mesh?.id);
|
|
35213
|
-
if (!meshId) return;
|
|
35214
|
-
const targetNode = mesh?.nodes?.find((n) => n.workspace === workspace);
|
|
35215
|
-
const runtimeNodeId = readNonEmptyString(settings.meshNodeId);
|
|
35216
|
-
const nodeLabel = targetNode ? `Node '${targetNode.id}'` : runtimeNodeId ? `Node '${runtimeNodeId}'` : `Agent at ${workspace}`;
|
|
35217
|
-
injectMeshSystemMessage(components, {
|
|
35218
|
-
meshId,
|
|
35219
|
-
sourceInstanceId: instanceId,
|
|
35220
|
-
nodeLabel,
|
|
35221
|
-
event: event.event,
|
|
35222
|
-
metadataEvent: event
|
|
35223
|
-
});
|
|
35224
|
-
});
|
|
35225
|
-
}
|
|
35226
35719
|
function buildRecentReadDebugSignature(snapshot) {
|
|
35227
35720
|
return [
|
|
35228
35721
|
snapshot.providerType,
|
|
@@ -35920,22 +36413,22 @@ function serializeMeshCoordinatorMcpConfig(config2, format) {
|
|
|
35920
36413
|
}
|
|
35921
36414
|
function resolveHermesUserHome() {
|
|
35922
36415
|
const explicitHome = process.env.HERMES_HOME?.trim();
|
|
35923
|
-
return explicitHome || (0,
|
|
36416
|
+
return explicitHome || (0, import_path7.join)((0, import_os4.homedir)(), ".hermes");
|
|
35924
36417
|
}
|
|
35925
36418
|
function loadHermesCoordinatorBaseConfig(targetConfigPath) {
|
|
35926
36419
|
const sourceHome = resolveHermesUserHome();
|
|
35927
|
-
const sourceConfigPath = (0,
|
|
36420
|
+
const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
|
|
35928
36421
|
if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
35929
|
-
if ((0,
|
|
36422
|
+
if ((0, import_path7.resolve)(sourceConfigPath) === (0, import_path7.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
|
|
35930
36423
|
const parsed = parseMeshCoordinatorMcpConfig(fs10.readFileSync(sourceConfigPath, "utf-8"), "hermes_config_yaml");
|
|
35931
36424
|
const { mcp_servers: _mcpServers, ...baseConfig } = parsed;
|
|
35932
36425
|
return { config: baseConfig, sourceHome, sourceConfigPath };
|
|
35933
36426
|
}
|
|
35934
36427
|
function copyHermesCoordinatorCredentialFiles(sourceHome, targetHome) {
|
|
35935
|
-
if ((0,
|
|
36428
|
+
if ((0, import_path7.resolve)(sourceHome) === (0, import_path7.resolve)(targetHome)) return;
|
|
35936
36429
|
for (const fileName of [".env", "auth.json"]) {
|
|
35937
|
-
const sourcePath = (0,
|
|
35938
|
-
const targetPath = (0,
|
|
36430
|
+
const sourcePath = (0, import_path7.join)(sourceHome, fileName);
|
|
36431
|
+
const targetPath = (0, import_path7.join)(targetHome, fileName);
|
|
35939
36432
|
if (!fs10.existsSync(sourcePath)) continue;
|
|
35940
36433
|
try {
|
|
35941
36434
|
fs10.copyFileSync(sourcePath, targetPath);
|
|
@@ -40420,7 +40913,7 @@ async function shutdownDaemonComponents(components) {
|
|
|
40420
40913
|
}
|
|
40421
40914
|
cdpManagers.clear();
|
|
40422
40915
|
}
|
|
40423
|
-
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, fs2,
|
|
40916
|
+
var path4, import_promises4, import_fs3, import_child_process, import_util3, import_os2, import_path, import_fs4, import_crypto2, import_fs5, import_path2, import_crypto3, import_fs6, import_path3, import_crypto4, import_events2, import_fs7, import_path4, import_crypto5, fs2, path8, os22, os8, os9, path14, import_child_process2, os10, path15, os11, import_child_process3, import_fs8, import_promises5, path, import_util4, import_promises6, path22, path32, fs, os4, path5, import_crypto6, path6, path7, import_fs9, import_path5, import_child_process4, import_fs10, import_os3, path9, import_child_process5, os32, path10, import_fs11, os42, import_child_process6, http, crypto2, fs3, path11, os5, fs4, os6, path12, import_crypto7, fs5, path13, os7, os13, path18, crypto4, import_fs12, import_child_process7, os12, path16, crypto3, fs6, import_module, path17, import_stream2, import_child_process8, import_child_process9, net2, os15, path20, fs7, path19, os14, fs8, path21, os16, import_child_process10, import_crypto8, import_fs13, import_module2, os17, import_path6, os18, import_child_process11, import_child_process12, fs9, os19, path222, import_os4, import_path7, fs10, fs11, path23, os20, import_child_process13, import_os5, http2, fs15, path27, fs12, path24, fs13, path25, fs14, path26, os21, import_child_process14, __defProp2, __getOwnPropDesc2, __getOwnPropNames2, __hasOwnProp2, __require2, __esm2, __export2, __copyProps2, __toCommonJS2, DEFAULT_MESH_POLICY, init_repo_mesh_types, git_worktree_exports, execFileAsync2, WORKTREE_DIR_NAME, GIT_TIMEOUT_MS, GIT_MAX_BUFFER, init_git_worktree, config_exports, DEFAULT_CONFIG, MACHINE_ID_PREFIX, init_config, mesh_config_exports, SESSION_CLEANUP_MODES, SPAWNED_SESSION_VISIBILITY_MODES, init_mesh_config, coordinator_prompt_exports, TOOLS_SECTION, TOOL_EXPOSURE_PREFLIGHT_SECTION, WORKFLOW_SECTION, init_coordinator_prompt, mesh_ledger_exports, LEDGER_DIR_NAME, MAX_FILE_SIZE_BYTES, RECENT_FAILURE_WINDOW_MS, meshLedgerEvents, init_mesh_ledger, init_mesh_work_queue, 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, init_logger, mesh_events_exports, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, EVENT_TO_LEDGER_KIND, init_mesh_events, NORMAL_TRACE_BUFFER_SIZE, DEV_TRACE_BUFFER_SIZE, DEFAULT_CONFIG2, currentConfig, init_debug_config, DEFAULT_BINDING_CANDIDATES, cachedBinding, cachedBindingError, GhosttyVtTerminalBackend, init_ghostty_vt_backend, TerminalCtor, XtermTerminalBackend, init_xterm_backend, DEFAULT_SCROLLBACK, loggedTerminalBackends, TerminalScreen, init_terminal_screen, init_spawn_env, cachedPty, NodePtyRuntimeTransport, NodePtyTransportFactory, init_pty_transport, TerminalTranscriptAccumulator, buildCliSpawnEnv, init_provider_cli_shared, init_provider_cli_parse, init_provider_cli_config, init_provider_cli_runtime, provider_cli_adapter_exports, ProviderCliAdapter, init_provider_cli_adapter, execFileAsync, DEFAULT_TIMEOUT_MS, DEFAULT_MAX_BUFFER, GitCommandError, DEFAULT_MAX_FILES, DEFAULT_MAX_BYTES, summarizeGitStatus, InMemoryGitSnapshotStore, DEFAULT_GIT_WORKSPACE_POLL_INTERVAL_MS, MIN_GIT_WORKSPACE_POLL_INTERVAL_MS, GitWorkspaceMonitor, GIT_COMMAND_NAMES, SNAPSHOT_REASONS, FAILURE_REASONS, defaultSnapshotStore, defaultGitCommandServices, BUSY_STATUSES, TERMINAL_STATUSES, TurnSnapshotTracker, MAX_WORKSPACES, MAX_ACTIVITY, MAX_SAVED_SESSIONS, DEFAULT_STATE, BUILTIN_IDE_DEFINITIONS, registeredIDEs, LIVE_LIFECYCLES, DEFAULT_ACTIVE_CHAT_POLL_STATUSES, DEFAULT_CHAT_TAIL_RECENT_MESSAGE_GRACE_MS, LIVE_RUNTIME_LIFECYCLES, DaemonCdpManager, CdpDomHandlers, DEFAULT_MONITOR_CONFIG, StatusMonitor, BUILTIN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_VISIBILITIES, CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES, CHAT_MESSAGE_AUDIENCES, CHAT_MESSAGE_SOURCES, CHAT_MESSAGE_ACTIVITY_SOURCES, CHAT_MESSAGE_INTERNAL_SOURCES, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES, EXPLICIT_HIDDEN_VISIBILITIES, EXPLICIT_VISIBLE_VISIBILITIES, HIDDEN_AUDIENCES, ACTIVITY_SOURCE_SET, INTERNAL_SOURCE_SET, HISTORY_DIR, RETAIN_DAYS, SAVED_HISTORY_INDEX_VERSION, SAVED_HISTORY_INDEX_FILE, SAVED_HISTORY_INDEX_LOCK_SUFFIX, SAVED_HISTORY_INDEX_LOCK_WAIT_MS, SAVED_HISTORY_INDEX_LOCK_STALE_MS, SAVED_HISTORY_INDEX_LOCK_POLL_MS, SAVED_HISTORY_ROLLUP_THRESHOLD_BYTES, savedHistorySessionCache, savedHistoryFileSummaryCache, savedHistoryBackgroundRefresh, savedHistoryRollupInFlight, ChatHistoryWriter, IDE_PROVIDER_SESSION_CAPABILITIES_BASE, EXTENSION_PROVIDER_SESSION_CAPABILITIES_BASE, ExtensionProviderInstance, VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES, DEFAULT_APPROVAL_POSITIVE_HINTS, IdeProviderInstance, DEFAULT_CDP_SCAN_INTERVAL_MS, DEFAULT_CDP_DISCOVERY_INTERVAL_MS, DEFAULT_STATUS_INITIAL_REPORT_DELAY_MS, DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS, DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS, MIN_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, DEFAULT_MACHINE_RUNTIME_SUBSCRIPTION_INTERVAL_MS, MIN_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_DIAGNOSTICS_SUBSCRIPTION_INTERVAL_MS, DEFAULT_SESSION_HOST_READY_TIMEOUT_MS, STANDALONE_CDP_SCAN_INTERVAL_MS, DaemonCdpScanner, DaemonCdpInitializer, WORKING_STATUSES, FULL_STATUS_ACTIVE_CHAT_OPTIONS, LIVE_STATUS_ACTIVE_CHAT_OPTIONS, STATUS_MODAL_MESSAGE_LIMIT, STATUS_MODAL_BUTTON_LIMIT, VALID_INPUT_MEDIA_TYPES, VALID_INPUT_STRATEGIES, TEXT_ONLY_MESSAGE_INPUT_SUPPORT, IDE_SESSION_CAPABILITIES, EXTENSION_SESSION_CAPABILITIES, PTY_SESSION_CAPABILITIES, CLI_CHAT_SESSION_CAPABILITIES, ACP_SESSION_CAPABILITIES, globalStore, RECENT_SEND_WINDOW_MS, READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS, HERMES_CLI_STARTING_SEND_SETTLE_MS, recentSendByTarget, DEFAULT_DEBUG_SANITIZE_OPTIONS, SECRET_KEY_PATTERN, KEY_TO_VK, COMMAND_DEBUG_LEVELS, DaemonCommandHandler, IMAGE_MIME_EXTENSIONS, MATERIALIZED_IMAGE_MAX_AGE_MS, MATERIALIZED_IMAGE_CLEANUP_INTERVAL_MS, lastMaterializedImageCleanupAt, CachedDatabaseSync, CliProviderInstance, AcpProviderInstance, chalkModule, chalkApi, COORDINATOR_DELEGATED_ENV_UNSETS, DaemonCliManager, VALID_CAPABILITY_MEDIA_TYPES, VALID_INPUT_STRATEGIES2, KNOWN_PROVIDER_FIELDS, VALUE_CONTROL_TYPES, ProviderLoader, _providerLoader, LOG_DIR2, MAX_FILE_SIZE, MAX_DAYS, SENSITIVE_KEYS, currentDate2, currentFile, writeCount2, SKIP_COMMANDS, DEFAULT_SERVER_NAME, DEFAULT_ADHDEV_MCP_COMMAND, HERMES_CLI_TYPE, HERMES_MCP_CONFIG_PATH, READ_DEBUG_ENABLED, recentReadDebugSignatureBySession, UPGRADE_HELPER_ENV, CHANNEL_NPM_TAG, CHANNEL_SERVER_URL, CHAT_COMMANDS, READ_DEBUG_ENABLED2, DaemonCommandRouter, DaemonStatusReporter, DEFAULT_DAEMON_PORT, DAEMON_WS_PATH, ProviderStreamAdapter, DaemonAgentStreamManager, AgentStreamPoller, ProviderInstanceManager, ARCHIVE_PATH, MAX_ENTRIES_PER_PROVIDER, VersionArchive, DEV_SERVER_PORT, DevServer, SessionHostRuntimeTransport, SessionHostPtyTransportFactory, DEFAULT_SESSION_HOST_APP_NAME, DEFAULT_STANDALONE_SESSION_HOST_APP_NAME, STARTUP_TIMEOUT_MS, STARTUP_POLL_MS, SessionHostCompatibilityError, EXTENSION_CATALOG, SessionRegistry;
|
|
40424
40917
|
var init_dist2 = __esm({
|
|
40425
40918
|
"../daemon-core/dist/index.mjs"() {
|
|
40426
40919
|
"use strict";
|
|
@@ -40436,9 +40929,16 @@ var init_dist2 = __esm({
|
|
|
40436
40929
|
import_fs5 = require("fs");
|
|
40437
40930
|
import_path2 = require("path");
|
|
40438
40931
|
import_crypto3 = require("crypto");
|
|
40932
|
+
import_fs6 = require("fs");
|
|
40933
|
+
import_path3 = require("path");
|
|
40934
|
+
import_crypto4 = require("crypto");
|
|
40935
|
+
import_events2 = require("events");
|
|
40936
|
+
import_fs7 = require("fs");
|
|
40937
|
+
import_path4 = require("path");
|
|
40938
|
+
import_crypto5 = require("crypto");
|
|
40439
40939
|
fs2 = __toESM(require("fs"), 1);
|
|
40440
|
-
|
|
40441
|
-
|
|
40940
|
+
path8 = __toESM(require("path"), 1);
|
|
40941
|
+
os22 = __toESM(require("os"), 1);
|
|
40442
40942
|
init_dist();
|
|
40443
40943
|
os8 = __toESM(require("os"), 1);
|
|
40444
40944
|
os9 = __toESM(require("os"), 1);
|
|
@@ -40449,7 +40949,7 @@ var init_dist2 = __esm({
|
|
|
40449
40949
|
init_dist();
|
|
40450
40950
|
os11 = __toESM(require("os"), 1);
|
|
40451
40951
|
import_child_process3 = require("child_process");
|
|
40452
|
-
|
|
40952
|
+
import_fs8 = require("fs");
|
|
40453
40953
|
import_promises5 = require("fs/promises");
|
|
40454
40954
|
path = __toESM(require("path"), 1);
|
|
40455
40955
|
import_util4 = require("util");
|
|
@@ -40457,40 +40957,40 @@ var init_dist2 = __esm({
|
|
|
40457
40957
|
path22 = __toESM(require("path"), 1);
|
|
40458
40958
|
path32 = __toESM(require("path"), 1);
|
|
40459
40959
|
fs = __toESM(require("fs"), 1);
|
|
40460
|
-
|
|
40960
|
+
os4 = __toESM(require("os"), 1);
|
|
40461
40961
|
path5 = __toESM(require("path"), 1);
|
|
40462
|
-
|
|
40962
|
+
import_crypto6 = require("crypto");
|
|
40463
40963
|
path6 = __toESM(require("path"), 1);
|
|
40464
40964
|
path7 = __toESM(require("path"), 1);
|
|
40465
|
-
|
|
40466
|
-
|
|
40965
|
+
import_fs9 = require("fs");
|
|
40966
|
+
import_path5 = require("path");
|
|
40467
40967
|
import_child_process4 = require("child_process");
|
|
40468
|
-
|
|
40968
|
+
import_fs10 = require("fs");
|
|
40469
40969
|
import_os3 = require("os");
|
|
40470
|
-
path8 = __toESM(require("path"), 1);
|
|
40471
|
-
import_child_process5 = require("child_process");
|
|
40472
|
-
os22 = __toESM(require("os"), 1);
|
|
40473
40970
|
path9 = __toESM(require("path"), 1);
|
|
40474
|
-
|
|
40971
|
+
import_child_process5 = require("child_process");
|
|
40475
40972
|
os32 = __toESM(require("os"), 1);
|
|
40973
|
+
path10 = __toESM(require("path"), 1);
|
|
40974
|
+
import_fs11 = require("fs");
|
|
40975
|
+
os42 = __toESM(require("os"), 1);
|
|
40476
40976
|
import_child_process6 = require("child_process");
|
|
40477
40977
|
init_wrapper();
|
|
40478
40978
|
http = __toESM(require("http"), 1);
|
|
40479
40979
|
crypto2 = __toESM(require("crypto"), 1);
|
|
40480
40980
|
fs3 = __toESM(require("fs"), 1);
|
|
40481
40981
|
path11 = __toESM(require("path"), 1);
|
|
40482
|
-
|
|
40982
|
+
os5 = __toESM(require("os"), 1);
|
|
40483
40983
|
fs4 = __toESM(require("fs"), 1);
|
|
40484
40984
|
os6 = __toESM(require("os"), 1);
|
|
40485
40985
|
path12 = __toESM(require("path"), 1);
|
|
40486
|
-
|
|
40986
|
+
import_crypto7 = require("crypto");
|
|
40487
40987
|
fs5 = __toESM(require("fs"), 1);
|
|
40488
40988
|
path13 = __toESM(require("path"), 1);
|
|
40489
40989
|
os7 = __toESM(require("os"), 1);
|
|
40490
40990
|
os13 = __toESM(require("os"), 1);
|
|
40491
40991
|
path18 = __toESM(require("path"), 1);
|
|
40492
40992
|
crypto4 = __toESM(require("crypto"), 1);
|
|
40493
|
-
|
|
40993
|
+
import_fs12 = require("fs");
|
|
40494
40994
|
import_child_process7 = require("child_process");
|
|
40495
40995
|
init_source();
|
|
40496
40996
|
os12 = __toESM(require("os"), 1);
|
|
@@ -40515,11 +41015,11 @@ var init_dist2 = __esm({
|
|
|
40515
41015
|
os16 = __toESM(require("os"), 1);
|
|
40516
41016
|
init_js_yaml();
|
|
40517
41017
|
import_child_process10 = require("child_process");
|
|
40518
|
-
|
|
40519
|
-
|
|
41018
|
+
import_crypto8 = require("crypto");
|
|
41019
|
+
import_fs13 = require("fs");
|
|
40520
41020
|
import_module2 = require("module");
|
|
40521
41021
|
os17 = __toESM(require("os"), 1);
|
|
40522
|
-
|
|
41022
|
+
import_path6 = require("path");
|
|
40523
41023
|
os18 = __toESM(require("os"), 1);
|
|
40524
41024
|
import_child_process11 = require("child_process");
|
|
40525
41025
|
import_child_process12 = require("child_process");
|
|
@@ -40527,7 +41027,7 @@ var init_dist2 = __esm({
|
|
|
40527
41027
|
os19 = __toESM(require("os"), 1);
|
|
40528
41028
|
path222 = __toESM(require("path"), 1);
|
|
40529
41029
|
import_os4 = require("os");
|
|
40530
|
-
|
|
41030
|
+
import_path7 = require("path");
|
|
40531
41031
|
fs10 = __toESM(require("fs"), 1);
|
|
40532
41032
|
fs11 = __toESM(require("fs"), 1);
|
|
40533
41033
|
path23 = __toESM(require("path"), 1);
|
|
@@ -40584,7 +41084,8 @@ var init_dist2 = __esm({
|
|
|
40584
41084
|
dirtyWorkspaceBehavior: "warn",
|
|
40585
41085
|
maxParallelTasks: 2,
|
|
40586
41086
|
spawnedSessionVisibility: "visible",
|
|
40587
|
-
sessionCleanupOnNodeRemove: "preserve"
|
|
41087
|
+
sessionCleanupOnNodeRemove: "preserve",
|
|
41088
|
+
maxTaskRetries: 1
|
|
40588
41089
|
};
|
|
40589
41090
|
}
|
|
40590
41091
|
});
|
|
@@ -40687,6 +41188,7 @@ var init_dist2 = __esm({
|
|
|
40687
41188
|
| \`mesh_launch_session\` | Start a new agent session on a node |
|
|
40688
41189
|
| \`mesh_send_task\` | Send a task (natural language) to a running agent |
|
|
40689
41190
|
| \`mesh_read_chat\` | Read an agent's recent messages to check progress |
|
|
41191
|
+
| \`mesh_task_history\` | Read the task ledger \u2014 dispatches, completions, failures. Use to understand what has been done before deciding next steps |
|
|
40690
41192
|
| \`mesh_git_status\` | Check git status on a specific node |
|
|
40691
41193
|
| \`mesh_checkpoint\` | Create a git checkpoint on a node |
|
|
40692
41194
|
| \`mesh_approve\` | Approve/reject a pending agent action |
|
|
@@ -40697,18 +41199,57 @@ var init_dist2 = __esm({
|
|
|
40697
41199
|
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\`.`;
|
|
40698
41200
|
WORKFLOW_SECTION = `## Orchestration Workflow
|
|
40699
41201
|
|
|
40700
|
-
1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
|
|
40701
|
-
2. **Plan** \u2014 Decompose the user's request into independent tasks for parallel execution, or sequential tasks when dependencies exist.
|
|
40702
|
-
3. **Delegate** \u2014
|
|
40703
|
-
a.
|
|
40704
|
-
b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
|
|
40705
|
-
c.
|
|
40706
|
-
d.
|
|
40707
|
-
4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly
|
|
41202
|
+
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.
|
|
41203
|
+
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.
|
|
41204
|
+
3. **Queue / Delegate** \u2014 The Mesh uses an autonomous pull-based Work Queue:
|
|
41205
|
+
a. **General Tasks**: Enqueue tasks using \`mesh_enqueue_task\`. Idle node agents will automatically pull tasks from the queue and begin working.
|
|
41206
|
+
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.
|
|
41207
|
+
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.
|
|
41208
|
+
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.
|
|
41209
|
+
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\`.
|
|
40708
41210
|
5. **Verify** \u2014 When a task reports completion or git work is visible, call \`mesh_git_status\` to verify changes were made.
|
|
40709
41211
|
6. **Checkpoint** \u2014 Call \`mesh_checkpoint\` to save the work.
|
|
40710
41212
|
7. **Clean up** \u2014 Remove worktree nodes via \`mesh_remove_node\` after their work is merged or no longer needed.
|
|
40711
|
-
8. **Report** \u2014 Summarize what was done, what changed, and any issues
|
|
41213
|
+
8. **Report** \u2014 Summarize what was done, what changed, and any issues.
|
|
41214
|
+
|
|
41215
|
+
## Failure Recovery
|
|
41216
|
+
|
|
41217
|
+
When a node agent stops unexpectedly, the daemon automatically enriches the system message with **Recovery Context** that includes:
|
|
41218
|
+
- The number of consecutive failures on that node
|
|
41219
|
+
- The original task message (if recorded in the ledger)
|
|
41220
|
+
- A recommendation: **retry**, **reassign**, or **escalate**
|
|
41221
|
+
|
|
41222
|
+
Follow these recovery rules:
|
|
41223
|
+
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.
|
|
41224
|
+
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.
|
|
41225
|
+
3. **If no recovery context**: The stop may be intentional (normal completion). Use \`mesh_read_chat\` once to verify, then move on.
|
|
41226
|
+
4. **Always record what happened**: After handling a failure, briefly note the outcome in your report to the user.`;
|
|
41227
|
+
}
|
|
41228
|
+
});
|
|
41229
|
+
mesh_ledger_exports = {};
|
|
41230
|
+
__export2(mesh_ledger_exports, {
|
|
41231
|
+
appendLedgerEntry: () => appendLedgerEntry,
|
|
41232
|
+
appendRemoteLedgerEntries: () => appendRemoteLedgerEntries,
|
|
41233
|
+
getLedgerDir: () => getLedgerDir,
|
|
41234
|
+
getLedgerSummary: () => getLedgerSummary,
|
|
41235
|
+
getSessionRecoveryContext: () => getSessionRecoveryContext,
|
|
41236
|
+
meshLedgerEvents: () => meshLedgerEvents,
|
|
41237
|
+
readLedgerEntries: () => readLedgerEntries
|
|
41238
|
+
});
|
|
41239
|
+
init_mesh_ledger = __esm2({
|
|
41240
|
+
"src/mesh/mesh-ledger.ts"() {
|
|
41241
|
+
"use strict";
|
|
41242
|
+
init_config();
|
|
41243
|
+
LEDGER_DIR_NAME = "mesh-ledger";
|
|
41244
|
+
MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
41245
|
+
RECENT_FAILURE_WINDOW_MS = 30 * 60 * 1e3;
|
|
41246
|
+
meshLedgerEvents = new import_events2.EventEmitter();
|
|
41247
|
+
}
|
|
41248
|
+
});
|
|
41249
|
+
init_mesh_work_queue = __esm2({
|
|
41250
|
+
"src/mesh/mesh-work-queue.ts"() {
|
|
41251
|
+
"use strict";
|
|
41252
|
+
init_mesh_ledger();
|
|
40712
41253
|
}
|
|
40713
41254
|
});
|
|
40714
41255
|
init_logger = __esm2({
|
|
@@ -40717,7 +41258,7 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
40717
41258
|
LEVEL_NUM = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
40718
41259
|
LEVEL_LABEL = { debug: "DBG", info: "INF", warn: "WRN", error: "ERR" };
|
|
40719
41260
|
currentLevel = "info";
|
|
40720
|
-
LOG_DIR = process.platform === "win32" ?
|
|
41261
|
+
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");
|
|
40721
41262
|
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
40722
41263
|
MAX_LOG_DAYS = 7;
|
|
40723
41264
|
try {
|
|
@@ -40725,16 +41266,16 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
40725
41266
|
} catch {
|
|
40726
41267
|
}
|
|
40727
41268
|
currentDate = getDateStr();
|
|
40728
|
-
currentLogFile =
|
|
41269
|
+
currentLogFile = path8.join(LOG_DIR, `daemon-${currentDate}.log`);
|
|
40729
41270
|
cleanOldLogs();
|
|
40730
41271
|
try {
|
|
40731
|
-
const oldLog =
|
|
41272
|
+
const oldLog = path8.join(LOG_DIR, "daemon.log");
|
|
40732
41273
|
if (fs2.existsSync(oldLog)) {
|
|
40733
41274
|
const stat22 = fs2.statSync(oldLog);
|
|
40734
41275
|
const oldDate = stat22.mtime.toISOString().slice(0, 10);
|
|
40735
|
-
fs2.renameSync(oldLog,
|
|
41276
|
+
fs2.renameSync(oldLog, path8.join(LOG_DIR, `daemon-${oldDate}.log`));
|
|
40736
41277
|
}
|
|
40737
|
-
const oldLogBackup =
|
|
41278
|
+
const oldLogBackup = path8.join(LOG_DIR, "daemon.log.old");
|
|
40738
41279
|
if (fs2.existsSync(oldLogBackup)) {
|
|
40739
41280
|
fs2.unlinkSync(oldLogBackup);
|
|
40740
41281
|
}
|
|
@@ -40766,7 +41307,38 @@ Before doing any coordinator work, confirm that the actual callable tool list in
|
|
|
40766
41307
|
}
|
|
40767
41308
|
};
|
|
40768
41309
|
interceptorInstalled = false;
|
|
40769
|
-
LOG_PATH =
|
|
41310
|
+
LOG_PATH = path8.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
41311
|
+
}
|
|
41312
|
+
});
|
|
41313
|
+
mesh_events_exports = {};
|
|
41314
|
+
__export2(mesh_events_exports, {
|
|
41315
|
+
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
41316
|
+
handleMeshForwardEvent: () => handleMeshForwardEvent,
|
|
41317
|
+
setupMeshEventForwarding: () => setupMeshEventForwarding,
|
|
41318
|
+
triggerMeshQueue: () => triggerMeshQueue,
|
|
41319
|
+
tryAssignQueueTask: () => tryAssignQueueTask
|
|
41320
|
+
});
|
|
41321
|
+
init_mesh_events = __esm2({
|
|
41322
|
+
"src/mesh/mesh-events.ts"() {
|
|
41323
|
+
"use strict";
|
|
41324
|
+
init_mesh_config();
|
|
41325
|
+
init_logger();
|
|
41326
|
+
init_mesh_ledger();
|
|
41327
|
+
init_mesh_work_queue();
|
|
41328
|
+
MAX_PENDING_EVENTS = 50;
|
|
41329
|
+
pendingMeshCoordinatorEvents = [];
|
|
41330
|
+
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
41331
|
+
"agent:generating_completed",
|
|
41332
|
+
"agent:waiting_approval",
|
|
41333
|
+
"agent:stopped",
|
|
41334
|
+
"monitor:long_generating"
|
|
41335
|
+
]);
|
|
41336
|
+
EVENT_TO_LEDGER_KIND = {
|
|
41337
|
+
"agent:generating_completed": "task_completed",
|
|
41338
|
+
"agent:waiting_approval": "task_approval_needed",
|
|
41339
|
+
"agent:stopped": "task_failed",
|
|
41340
|
+
"monitor:long_generating": "task_stalled"
|
|
41341
|
+
};
|
|
40770
41342
|
}
|
|
40771
41343
|
});
|
|
40772
41344
|
init_debug_config = __esm2({
|
|
@@ -43497,6 +44069,9 @@ ${lastSnapshot}`;
|
|
|
43497
44069
|
init_mesh_config();
|
|
43498
44070
|
init_coordinator_prompt();
|
|
43499
44071
|
init_mesh_config();
|
|
44072
|
+
init_mesh_ledger();
|
|
44073
|
+
init_mesh_work_queue();
|
|
44074
|
+
init_mesh_events();
|
|
43500
44075
|
init_config();
|
|
43501
44076
|
DEFAULT_STATE = {
|
|
43502
44077
|
recentActivity: [],
|
|
@@ -44963,7 +45538,7 @@ ${lastSnapshot}`;
|
|
|
44963
45538
|
HIDDEN_AUDIENCES = /* @__PURE__ */ new Set(["debug", "trace", "internal"]);
|
|
44964
45539
|
ACTIVITY_SOURCE_SET = new Set(CHAT_MESSAGE_ACTIVITY_SOURCES);
|
|
44965
45540
|
INTERNAL_SOURCE_SET = new Set(CHAT_MESSAGE_INTERNAL_SOURCES);
|
|
44966
|
-
HISTORY_DIR = path11.join(
|
|
45541
|
+
HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
|
|
44967
45542
|
RETAIN_DAYS = 30;
|
|
44968
45543
|
SAVED_HISTORY_INDEX_VERSION = 1;
|
|
44969
45544
|
SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
|
|
@@ -46682,6 +47257,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
46682
47257
|
};
|
|
46683
47258
|
STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
|
|
46684
47259
|
STATUS_MODAL_BUTTON_LIMIT = 120;
|
|
47260
|
+
init_mesh_work_queue();
|
|
46685
47261
|
VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
46686
47262
|
VALID_INPUT_STRATEGIES = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
|
|
46687
47263
|
TEXT_ONLY_MESSAGE_INPUT_SUPPORT = Object.freeze({
|
|
@@ -51540,16 +52116,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
51540
52116
|
DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
|
|
51541
52117
|
HERMES_CLI_TYPE = "hermes-cli";
|
|
51542
52118
|
HERMES_MCP_CONFIG_PATH = "~/.hermes/config.yaml";
|
|
51543
|
-
|
|
51544
|
-
init_logger();
|
|
51545
|
-
MAX_PENDING_EVENTS = 50;
|
|
51546
|
-
pendingMeshCoordinatorEvents = [];
|
|
51547
|
-
MESH_COORDINATOR_EVENTS = /* @__PURE__ */ new Set([
|
|
51548
|
-
"agent:generating_completed",
|
|
51549
|
-
"agent:waiting_approval",
|
|
51550
|
-
"agent:stopped",
|
|
51551
|
-
"monitor:long_generating"
|
|
51552
|
-
]);
|
|
52119
|
+
init_mesh_events();
|
|
51553
52120
|
init_config();
|
|
51554
52121
|
init_terminal_screen();
|
|
51555
52122
|
init_logger();
|
|
@@ -52432,6 +52999,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52432
52999
|
return { success: false, error: e.message };
|
|
52433
53000
|
}
|
|
52434
53001
|
}
|
|
53002
|
+
case "get_mesh_ledger": {
|
|
53003
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53004
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
53005
|
+
try {
|
|
53006
|
+
const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53007
|
+
const tail = typeof args?.tail === "number" ? args.tail : 20;
|
|
53008
|
+
const since = typeof args?.since === "string" ? args.since : void 0;
|
|
53009
|
+
const kind = Array.isArray(args?.kind) ? args.kind.filter((k) => typeof k === "string") : void 0;
|
|
53010
|
+
const entries = readLedgerEntries2(meshId, { tail, since, kind });
|
|
53011
|
+
const summary = getLedgerSummary2(meshId);
|
|
53012
|
+
return { success: true, entries, summary };
|
|
53013
|
+
} catch (e) {
|
|
53014
|
+
return { success: false, error: e.message };
|
|
53015
|
+
}
|
|
53016
|
+
}
|
|
52435
53017
|
case "add_mesh_node": {
|
|
52436
53018
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
52437
53019
|
const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
|
|
@@ -52500,6 +53082,54 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52500
53082
|
return { success: false, error: e.message };
|
|
52501
53083
|
}
|
|
52502
53084
|
}
|
|
53085
|
+
case "refine_mesh_node": {
|
|
53086
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53087
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
53088
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
53089
|
+
try {
|
|
53090
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
53091
|
+
const mesh = meshRecord?.mesh;
|
|
53092
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
53093
|
+
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
53094
|
+
if (!node.isLocalWorktree || !node.workspace) {
|
|
53095
|
+
return { success: false, error: `Refinery requires a local worktree node` };
|
|
53096
|
+
}
|
|
53097
|
+
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
53098
|
+
const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
|
|
53099
|
+
if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
|
|
53100
|
+
const { execFile: execFile3 } = await import("child_process");
|
|
53101
|
+
const { promisify: promisify3 } = await import("util");
|
|
53102
|
+
const execFileAsync3 = promisify3(execFile3);
|
|
53103
|
+
const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
|
|
53104
|
+
const branch = branchStdout.trim();
|
|
53105
|
+
if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
|
|
53106
|
+
const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
|
|
53107
|
+
const baseBranch = baseBranchStdout.trim();
|
|
53108
|
+
try {
|
|
53109
|
+
await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
|
|
53110
|
+
} catch (e) {
|
|
53111
|
+
return { success: false, error: `Merge failed (conflicts?): ${e.message}` };
|
|
53112
|
+
}
|
|
53113
|
+
const removeResult = await this.execute("remove_mesh_node", {
|
|
53114
|
+
meshId,
|
|
53115
|
+
nodeId,
|
|
53116
|
+
sessionCleanupMode: "kill",
|
|
53117
|
+
inlineMesh: args?.inlineMesh
|
|
53118
|
+
});
|
|
53119
|
+
try {
|
|
53120
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53121
|
+
appendLedgerEntry2(meshId, {
|
|
53122
|
+
kind: "node_removed",
|
|
53123
|
+
nodeId,
|
|
53124
|
+
payload: { refined: true, mergedBranch: branch, into: baseBranch }
|
|
53125
|
+
});
|
|
53126
|
+
} catch {
|
|
53127
|
+
}
|
|
53128
|
+
return { success: true, merged: true, branch, into: baseBranch, removeResult };
|
|
53129
|
+
} catch (e) {
|
|
53130
|
+
return { success: false, error: e.message };
|
|
53131
|
+
}
|
|
53132
|
+
}
|
|
52503
53133
|
case "remove_mesh_node": {
|
|
52504
53134
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
52505
53135
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
@@ -52535,6 +53165,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52535
53165
|
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
52536
53166
|
removed = removeNode3(meshId, nodeId);
|
|
52537
53167
|
}
|
|
53168
|
+
if (removed) {
|
|
53169
|
+
try {
|
|
53170
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53171
|
+
appendLedgerEntry2(meshId, {
|
|
53172
|
+
kind: "node_removed",
|
|
53173
|
+
nodeId,
|
|
53174
|
+
payload: { worktree: !!node?.isLocalWorktree, sessionCleanupMode }
|
|
53175
|
+
});
|
|
53176
|
+
} catch {
|
|
53177
|
+
}
|
|
53178
|
+
}
|
|
52538
53179
|
return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
|
|
52539
53180
|
} catch (e) {
|
|
52540
53181
|
return { success: false, error: e.message };
|
|
@@ -52564,9 +53205,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52564
53205
|
});
|
|
52565
53206
|
let node;
|
|
52566
53207
|
if (meshRecord.inline) {
|
|
52567
|
-
const { randomUUID:
|
|
53208
|
+
const { randomUUID: randomUUID10 } = await import("crypto");
|
|
52568
53209
|
node = {
|
|
52569
|
-
id: `node_${
|
|
53210
|
+
id: `node_${randomUUID10().replace(/-/g, "")}`,
|
|
52570
53211
|
workspace: result.worktreePath,
|
|
52571
53212
|
repoRoot: result.worktreePath,
|
|
52572
53213
|
daemonId: sourceNode.daemonId,
|
|
@@ -52591,6 +53232,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52591
53232
|
});
|
|
52592
53233
|
if (!node) return { success: false, error: "Failed to register worktree node" };
|
|
52593
53234
|
}
|
|
53235
|
+
try {
|
|
53236
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53237
|
+
appendLedgerEntry2(meshId, {
|
|
53238
|
+
kind: "node_cloned",
|
|
53239
|
+
nodeId: node.id,
|
|
53240
|
+
payload: { sourceNodeId, branch: result.branch, worktreePath: result.worktreePath }
|
|
53241
|
+
});
|
|
53242
|
+
} catch {
|
|
53243
|
+
}
|
|
52594
53244
|
return {
|
|
52595
53245
|
success: true,
|
|
52596
53246
|
node,
|
|
@@ -52601,6 +53251,19 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52601
53251
|
return { success: false, error: e.message };
|
|
52602
53252
|
}
|
|
52603
53253
|
}
|
|
53254
|
+
case "trigger_mesh_queue": {
|
|
53255
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
53256
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
53257
|
+
try {
|
|
53258
|
+
const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
|
|
53259
|
+
if (meshId) {
|
|
53260
|
+
triggerMeshQueue2(this.deps, meshId);
|
|
53261
|
+
}
|
|
53262
|
+
return { success: true };
|
|
53263
|
+
} catch (e) {
|
|
53264
|
+
return { success: false, error: e.message };
|
|
53265
|
+
}
|
|
53266
|
+
}
|
|
52604
53267
|
// ─── Mesh Coordinator Launch ───
|
|
52605
53268
|
case "launch_mesh_coordinator": {
|
|
52606
53269
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
@@ -52705,7 +53368,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52705
53368
|
workspace
|
|
52706
53369
|
};
|
|
52707
53370
|
}
|
|
52708
|
-
const { existsSync:
|
|
53371
|
+
const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
|
|
52709
53372
|
const { dirname: dirname92 } = await import("path");
|
|
52710
53373
|
const mcpConfigPath = coordinatorSetup.configPath;
|
|
52711
53374
|
const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
|
|
@@ -52739,21 +53402,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52739
53402
|
};
|
|
52740
53403
|
}
|
|
52741
53404
|
try {
|
|
52742
|
-
|
|
53405
|
+
mkdirSync17(dirname92(mcpConfigPath), { recursive: true });
|
|
52743
53406
|
} catch (error48) {
|
|
52744
53407
|
const message = `Could not prepare MCP config path for automatic setup: ${error48?.message || error48}`;
|
|
52745
53408
|
LOG.error("MeshCoordinator", message);
|
|
52746
53409
|
if (hermesManualFallback) return returnManualFallback(message);
|
|
52747
53410
|
return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
|
|
52748
53411
|
}
|
|
52749
|
-
const hadExistingMcpConfig =
|
|
53412
|
+
const hadExistingMcpConfig = existsSync25(mcpConfigPath);
|
|
52750
53413
|
let existingMcpConfig = hermesBaseConfig?.config || {};
|
|
52751
53414
|
if (hermesBaseConfig) {
|
|
52752
53415
|
copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname92(mcpConfigPath));
|
|
52753
53416
|
}
|
|
52754
53417
|
if (hadExistingMcpConfig) {
|
|
52755
53418
|
try {
|
|
52756
|
-
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(
|
|
53419
|
+
const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
|
|
52757
53420
|
existingMcpConfig = { ...existingMcpConfig, ...parsedExistingMcpConfig };
|
|
52758
53421
|
copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
|
|
52759
53422
|
} catch (error48) {
|
|
@@ -52775,7 +53438,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52775
53438
|
}
|
|
52776
53439
|
};
|
|
52777
53440
|
try {
|
|
52778
|
-
|
|
53441
|
+
writeFileSync15(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
|
|
52779
53442
|
} catch (error48) {
|
|
52780
53443
|
const message = `Could not write MCP config for automatic setup: ${error48?.message || error48}`;
|
|
52781
53444
|
LOG.error("MeshCoordinator", message);
|
|
@@ -52812,6 +53475,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
52812
53475
|
return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
|
|
52813
53476
|
}
|
|
52814
53477
|
LOG.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
|
|
53478
|
+
try {
|
|
53479
|
+
const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
|
|
53480
|
+
appendLedgerEntry2(meshId, {
|
|
53481
|
+
kind: "coordinator_started",
|
|
53482
|
+
sessionId: launchResult.sessionId || launchResult.id,
|
|
53483
|
+
providerType: cliType,
|
|
53484
|
+
payload: { workspace }
|
|
53485
|
+
});
|
|
53486
|
+
} catch {
|
|
53487
|
+
}
|
|
52815
53488
|
return {
|
|
52816
53489
|
success: true,
|
|
52817
53490
|
meshId,
|
|
@@ -56359,6 +57032,7 @@ data: ${JSON.stringify(msg.data)}
|
|
|
56359
57032
|
};
|
|
56360
57033
|
init_logger();
|
|
56361
57034
|
init_config();
|
|
57035
|
+
init_mesh_events();
|
|
56362
57036
|
}
|
|
56363
57037
|
});
|
|
56364
57038
|
|
|
@@ -56564,6 +57238,7 @@ function annotateRapidReadChatAdvisory(payload, options) {
|
|
|
56564
57238
|
}
|
|
56565
57239
|
|
|
56566
57240
|
// src/tools/mesh-tools.ts
|
|
57241
|
+
init_dist2();
|
|
56567
57242
|
var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
|
|
56568
57243
|
async function refreshMeshFromDaemon(ctx) {
|
|
56569
57244
|
if (!(ctx.transport instanceof IpcTransport)) return;
|
|
@@ -56744,9 +57419,34 @@ var MESH_LIST_NODES_TOOL = {
|
|
|
56744
57419
|
properties: {}
|
|
56745
57420
|
}
|
|
56746
57421
|
};
|
|
57422
|
+
var MESH_ENQUEUE_TASK_TOOL = {
|
|
57423
|
+
name: "mesh_enqueue_task",
|
|
57424
|
+
description: "Add a new task to the mesh work queue. Idle nodes will automatically pull and execute tasks from this queue. Use this instead of mesh_send_task when you do not need to target a specific node.",
|
|
57425
|
+
inputSchema: {
|
|
57426
|
+
type: "object",
|
|
57427
|
+
properties: {
|
|
57428
|
+
message: { type: "string", description: "The task instruction for the agent." }
|
|
57429
|
+
},
|
|
57430
|
+
required: ["message"]
|
|
57431
|
+
}
|
|
57432
|
+
};
|
|
57433
|
+
var MESH_VIEW_QUEUE_TOOL = {
|
|
57434
|
+
name: "mesh_view_queue",
|
|
57435
|
+
description: "View the current status of the mesh work queue (pending, assigned, completed, failed tasks).",
|
|
57436
|
+
inputSchema: {
|
|
57437
|
+
type: "object",
|
|
57438
|
+
properties: {
|
|
57439
|
+
status: {
|
|
57440
|
+
type: "array",
|
|
57441
|
+
items: { type: "string" },
|
|
57442
|
+
description: "Filter by task status: pending, assigned, completed, failed. Returns all if omitted."
|
|
57443
|
+
}
|
|
57444
|
+
}
|
|
57445
|
+
}
|
|
57446
|
+
};
|
|
56747
57447
|
var MESH_SEND_TASK_TOOL = {
|
|
56748
57448
|
name: "mesh_send_task",
|
|
56749
|
-
description: "
|
|
57449
|
+
description: "Legacy push-based task assignment. Enqueues a task specifically targeted at a given node. The node will pull it immediately if idle.",
|
|
56750
57450
|
inputSchema: {
|
|
56751
57451
|
type: "object",
|
|
56752
57452
|
properties: {
|
|
@@ -56886,9 +57586,33 @@ var MESH_CLEANUP_SESSIONS_TOOL = {
|
|
|
56886
57586
|
required: ["node_id", "mode"]
|
|
56887
57587
|
}
|
|
56888
57588
|
};
|
|
57589
|
+
var MESH_TASK_HISTORY_TOOL = {
|
|
57590
|
+
name: "mesh_task_history",
|
|
57591
|
+
description: "Read the task ledger for this mesh \u2014 dispatched tasks, completions, failures, checkpoints, and node lifecycle events. Use to understand what has been done before deciding next steps, to detect repeated failures, and to inform recovery decisions.",
|
|
57592
|
+
inputSchema: {
|
|
57593
|
+
type: "object",
|
|
57594
|
+
properties: {
|
|
57595
|
+
tail: { type: "number", description: "Number of recent entries to return (default: 20)." },
|
|
57596
|
+
kind: { type: "string", description: "Filter by entry kind: task_dispatched, task_completed, task_failed, task_stalled, session_launched, checkpoint_created, node_cloned, node_removed." }
|
|
57597
|
+
}
|
|
57598
|
+
}
|
|
57599
|
+
};
|
|
57600
|
+
var MESH_REFINE_NODE_TOOL = {
|
|
57601
|
+
name: "mesh_refine_node",
|
|
57602
|
+
description: "The Refinery: Automatically validate and merge a completed worktree node back into its base branch. This tool automates the validation gate and merge queue step. It will merge the node's branch into its base branch and cleanly remove the worktree node and its sessions.",
|
|
57603
|
+
inputSchema: {
|
|
57604
|
+
type: "object",
|
|
57605
|
+
properties: {
|
|
57606
|
+
node_id: { type: "string", description: "Node ID of the completed worktree node to refine and merge." }
|
|
57607
|
+
},
|
|
57608
|
+
required: ["node_id"]
|
|
57609
|
+
}
|
|
57610
|
+
};
|
|
56889
57611
|
var ALL_MESH_TOOLS = [
|
|
56890
57612
|
MESH_STATUS_TOOL,
|
|
56891
57613
|
MESH_LIST_NODES_TOOL,
|
|
57614
|
+
MESH_ENQUEUE_TASK_TOOL,
|
|
57615
|
+
MESH_VIEW_QUEUE_TOOL,
|
|
56892
57616
|
MESH_SEND_TASK_TOOL,
|
|
56893
57617
|
MESH_READ_CHAT_TOOL,
|
|
56894
57618
|
MESH_READ_DEBUG_TOOL,
|
|
@@ -56898,7 +57622,9 @@ var ALL_MESH_TOOLS = [
|
|
|
56898
57622
|
MESH_APPROVE_TOOL,
|
|
56899
57623
|
MESH_CLONE_NODE_TOOL,
|
|
56900
57624
|
MESH_REMOVE_NODE_TOOL,
|
|
56901
|
-
|
|
57625
|
+
MESH_REFINE_NODE_TOOL,
|
|
57626
|
+
MESH_CLEANUP_SESSIONS_TOOL,
|
|
57627
|
+
MESH_TASK_HISTORY_TOOL
|
|
56902
57628
|
];
|
|
56903
57629
|
async function meshStatus(ctx) {
|
|
56904
57630
|
await refreshMeshFromDaemon(ctx);
|
|
@@ -56949,6 +57675,10 @@ async function meshStatus(ctx) {
|
|
|
56949
57675
|
refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
56950
57676
|
nodes: results
|
|
56951
57677
|
};
|
|
57678
|
+
try {
|
|
57679
|
+
response.ledgerSummary = getLedgerSummary(mesh.id);
|
|
57680
|
+
} catch {
|
|
57681
|
+
}
|
|
56952
57682
|
if (ctx.transport instanceof IpcTransport) {
|
|
56953
57683
|
try {
|
|
56954
57684
|
const eventsResult = await ctx.transport.command("get_pending_mesh_events", {});
|
|
@@ -56961,6 +57691,14 @@ async function meshStatus(ctx) {
|
|
|
56961
57691
|
}
|
|
56962
57692
|
return JSON.stringify(response, null, 2);
|
|
56963
57693
|
}
|
|
57694
|
+
async function meshTaskHistory(ctx, args) {
|
|
57695
|
+
const { mesh } = ctx;
|
|
57696
|
+
const tail = typeof args.tail === "number" && args.tail > 0 ? args.tail : 20;
|
|
57697
|
+
const kind = typeof args.kind === "string" && args.kind.trim() ? [args.kind.trim()] : void 0;
|
|
57698
|
+
const entries = readLedgerEntries(mesh.id, { tail, kind });
|
|
57699
|
+
const summary = getLedgerSummary(mesh.id);
|
|
57700
|
+
return JSON.stringify({ meshId: mesh.id, entries, summary }, null, 2);
|
|
57701
|
+
}
|
|
56964
57702
|
async function meshListNodes(ctx) {
|
|
56965
57703
|
await refreshMeshFromDaemon(ctx);
|
|
56966
57704
|
const { mesh } = ctx;
|
|
@@ -56979,29 +57717,54 @@ async function meshListNodes(ctx) {
|
|
|
56979
57717
|
}))
|
|
56980
57718
|
}, null, 2);
|
|
56981
57719
|
}
|
|
57720
|
+
async function meshEnqueueTask(ctx, args) {
|
|
57721
|
+
try {
|
|
57722
|
+
const task = enqueueTask(ctx.mesh.id, args.message);
|
|
57723
|
+
if (ctx.transport instanceof IpcTransport && ctx.localDaemonId) {
|
|
57724
|
+
ctx.transport.meshCommand(ctx.localDaemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57725
|
+
});
|
|
57726
|
+
} else if (isLocalTransport(ctx.transport)) {
|
|
57727
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57728
|
+
});
|
|
57729
|
+
}
|
|
57730
|
+
return JSON.stringify({ success: true, taskId: task.id, status: task.status });
|
|
57731
|
+
} catch (e) {
|
|
57732
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
57733
|
+
}
|
|
57734
|
+
}
|
|
57735
|
+
async function meshViewQueue(ctx, args) {
|
|
57736
|
+
try {
|
|
57737
|
+
const queue = getQueue(ctx.mesh.id, { status: args.status });
|
|
57738
|
+
return JSON.stringify({ success: true, queue }, null, 2);
|
|
57739
|
+
} catch (e) {
|
|
57740
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
57741
|
+
}
|
|
57742
|
+
}
|
|
56982
57743
|
async function meshSendTask(ctx, args) {
|
|
56983
57744
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
56984
57745
|
if (node.policy?.readOnly) {
|
|
56985
57746
|
return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
|
|
56986
57747
|
}
|
|
56987
|
-
|
|
56988
|
-
|
|
56989
|
-
|
|
56990
|
-
|
|
56991
|
-
|
|
56992
|
-
|
|
56993
|
-
const payload = unwrapCommandPayload(result);
|
|
56994
|
-
if (payload?.success === false) {
|
|
56995
|
-
return JSON.stringify({
|
|
56996
|
-
success: false,
|
|
56997
|
-
nodeId: args.node_id,
|
|
56998
|
-
sessionId: args.session_id,
|
|
56999
|
-
error: payload.error || "send_chat failed"
|
|
57748
|
+
try {
|
|
57749
|
+
if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
57750
|
+
const res = await ctx.transport.meshEnqueueTask(node.daemonId, {
|
|
57751
|
+
meshId: ctx.mesh.id,
|
|
57752
|
+
message: args.message,
|
|
57753
|
+
targetNodeId: args.node_id
|
|
57000
57754
|
});
|
|
57755
|
+
return JSON.stringify(res);
|
|
57001
57756
|
}
|
|
57002
|
-
|
|
57003
|
-
|
|
57004
|
-
|
|
57757
|
+
const task = enqueueTask(ctx.mesh.id, args.message, { targetNodeId: args.node_id });
|
|
57758
|
+
if (ctx.transport instanceof IpcTransport && node.daemonId && node.daemonId !== ctx.localDaemonId) {
|
|
57759
|
+
ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57760
|
+
});
|
|
57761
|
+
} else if (isLocalTransport(ctx.transport)) {
|
|
57762
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57763
|
+
});
|
|
57764
|
+
}
|
|
57765
|
+
return JSON.stringify({ success: true, nodeId: args.node_id, taskId: task.id, status: task.status });
|
|
57766
|
+
} catch (e) {
|
|
57767
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
57005
57768
|
}
|
|
57006
57769
|
}
|
|
57007
57770
|
async function meshReadChat(ctx, args) {
|
|
@@ -57035,8 +57798,19 @@ async function meshReadChat(ctx, args) {
|
|
|
57035
57798
|
);
|
|
57036
57799
|
}
|
|
57037
57800
|
return JSON.stringify(payload, null, 2);
|
|
57801
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
57802
|
+
try {
|
|
57803
|
+
const targetId = `${node.daemonId}:session:${args.session_id}`;
|
|
57804
|
+
const res = await ctx.transport.readChat(targetId, {
|
|
57805
|
+
limit: args.tail ?? 10,
|
|
57806
|
+
sessionId: args.session_id
|
|
57807
|
+
});
|
|
57808
|
+
return JSON.stringify(res, null, 2);
|
|
57809
|
+
} catch (e) {
|
|
57810
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
57811
|
+
}
|
|
57038
57812
|
} else {
|
|
57039
|
-
return JSON.stringify({ error: "Cloud mesh read_chat
|
|
57813
|
+
return JSON.stringify({ error: "Cloud mesh read_chat requires node daemonId" });
|
|
57040
57814
|
}
|
|
57041
57815
|
}
|
|
57042
57816
|
async function meshReadDebug(ctx, args) {
|
|
@@ -57056,8 +57830,20 @@ async function meshReadDebug(ctx, args) {
|
|
|
57056
57830
|
});
|
|
57057
57831
|
const payload = unwrapCommandPayload(result);
|
|
57058
57832
|
return JSON.stringify(payload, null, 2);
|
|
57833
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
57834
|
+
try {
|
|
57835
|
+
const targetId = `${node.daemonId}:session:${args.session_id}`;
|
|
57836
|
+
const res = await ctx.transport.getChatDebugBundle(targetId, {
|
|
57837
|
+
sessionId: args.session_id,
|
|
57838
|
+
tailLimit: args.tail ?? 40,
|
|
57839
|
+
delivery: args.delivery
|
|
57840
|
+
});
|
|
57841
|
+
return JSON.stringify(res, null, 2);
|
|
57842
|
+
} catch (e) {
|
|
57843
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
57844
|
+
}
|
|
57059
57845
|
}
|
|
57060
|
-
return JSON.stringify({ error: "Cloud mesh read_debug
|
|
57846
|
+
return JSON.stringify({ error: "Cloud mesh read_debug requires node daemonId" });
|
|
57061
57847
|
}
|
|
57062
57848
|
async function meshLaunchSession(ctx, args) {
|
|
57063
57849
|
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
@@ -57106,13 +57892,70 @@ async function meshLaunchSession(ctx, args) {
|
|
|
57106
57892
|
...providerSessionId ? { providerSessionId } : {}
|
|
57107
57893
|
});
|
|
57108
57894
|
}
|
|
57895
|
+
try {
|
|
57896
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
57897
|
+
kind: "session_launched",
|
|
57898
|
+
nodeId: args.node_id,
|
|
57899
|
+
sessionId: runtimeSessionId || void 0,
|
|
57900
|
+
providerType: resolvedProviderType,
|
|
57901
|
+
payload: { providerSessionId }
|
|
57902
|
+
});
|
|
57903
|
+
} catch {
|
|
57904
|
+
}
|
|
57905
|
+
if (ctx.transport instanceof IpcTransport && node.daemonId && node.daemonId !== ctx.localDaemonId) {
|
|
57906
|
+
ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57907
|
+
});
|
|
57908
|
+
} else if (isLocalTransport(ctx.transport)) {
|
|
57909
|
+
ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
|
|
57910
|
+
});
|
|
57911
|
+
}
|
|
57109
57912
|
return JSON.stringify({
|
|
57110
57913
|
...launchPayload,
|
|
57111
57914
|
resolvedProviderType,
|
|
57112
57915
|
...providerSessionId ? { providerSessionId } : {}
|
|
57113
57916
|
}, null, 2);
|
|
57917
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
57918
|
+
let resolvedProviderType = typeof args.type === "string" && args.type.trim() ? args.type : "";
|
|
57919
|
+
if (!resolvedProviderType) {
|
|
57920
|
+
const providerPriority = readProviderPriority(node.policy);
|
|
57921
|
+
if (!providerPriority.length) {
|
|
57922
|
+
return JSON.stringify({ success: false, error: missingProviderPriorityMessage(args.node_id) });
|
|
57923
|
+
}
|
|
57924
|
+
resolvedProviderType = providerPriority[0];
|
|
57925
|
+
}
|
|
57926
|
+
const coordinatorNode = resolveCoordinatorNode(ctx);
|
|
57927
|
+
const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
|
|
57928
|
+
const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
|
|
57929
|
+
try {
|
|
57930
|
+
const res = await ctx.transport.launch(node.daemonId, {
|
|
57931
|
+
type: resolvedProviderType,
|
|
57932
|
+
dir: node.workspace,
|
|
57933
|
+
settings: {
|
|
57934
|
+
meshNodeFor: ctx.mesh.id,
|
|
57935
|
+
meshNodeId: args.node_id,
|
|
57936
|
+
spawnedSessionVisibility,
|
|
57937
|
+
...coordinatorDaemonId ? { meshCoordinatorDaemonId: coordinatorDaemonId } : {},
|
|
57938
|
+
...coordinatorNode?.id ? { meshCoordinatorNodeId: coordinatorNode.id } : {},
|
|
57939
|
+
launchedByCoordinator: true
|
|
57940
|
+
}
|
|
57941
|
+
});
|
|
57942
|
+
const runtimeSessionId = typeof res?.sessionId === "string" ? res.sessionId : typeof res?.id === "string" ? res.id : "";
|
|
57943
|
+
try {
|
|
57944
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
57945
|
+
kind: "session_launched",
|
|
57946
|
+
nodeId: args.node_id,
|
|
57947
|
+
sessionId: runtimeSessionId || void 0,
|
|
57948
|
+
providerType: resolvedProviderType,
|
|
57949
|
+
payload: {}
|
|
57950
|
+
});
|
|
57951
|
+
} catch {
|
|
57952
|
+
}
|
|
57953
|
+
return JSON.stringify({ ...res, resolvedProviderType }, null, 2);
|
|
57954
|
+
} catch (e) {
|
|
57955
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
57956
|
+
}
|
|
57114
57957
|
} else {
|
|
57115
|
-
return JSON.stringify({ error: "Cloud mesh launch_session
|
|
57958
|
+
return JSON.stringify({ error: "Cloud mesh launch_session requires node daemonId" });
|
|
57116
57959
|
}
|
|
57117
57960
|
}
|
|
57118
57961
|
async function meshGitStatus(ctx, args) {
|
|
@@ -57155,9 +57998,36 @@ async function meshCheckpoint(ctx, args) {
|
|
|
57155
57998
|
message: args.message,
|
|
57156
57999
|
includeUntracked: true
|
|
57157
58000
|
});
|
|
58001
|
+
try {
|
|
58002
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
58003
|
+
kind: "checkpoint_created",
|
|
58004
|
+
nodeId: args.node_id,
|
|
58005
|
+
payload: { message: args.message, commit: result?.checkpoint?.commit }
|
|
58006
|
+
});
|
|
58007
|
+
} catch {
|
|
58008
|
+
}
|
|
57158
58009
|
return JSON.stringify(result, null, 2);
|
|
58010
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
58011
|
+
try {
|
|
58012
|
+
const res = await ctx.transport.gitCheckpoint(node.daemonId, {
|
|
58013
|
+
workspace: node.workspace,
|
|
58014
|
+
message: args.message,
|
|
58015
|
+
includeUntracked: true
|
|
58016
|
+
});
|
|
58017
|
+
try {
|
|
58018
|
+
appendLedgerEntry(ctx.mesh.id, {
|
|
58019
|
+
kind: "checkpoint_created",
|
|
58020
|
+
nodeId: args.node_id,
|
|
58021
|
+
payload: { message: args.message, commit: res?.checkpoint?.commit }
|
|
58022
|
+
});
|
|
58023
|
+
} catch {
|
|
58024
|
+
}
|
|
58025
|
+
return JSON.stringify(res, null, 2);
|
|
58026
|
+
} catch (e) {
|
|
58027
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58028
|
+
}
|
|
57159
58029
|
} else {
|
|
57160
|
-
return JSON.stringify({ error: "Cloud mesh checkpoint
|
|
58030
|
+
return JSON.stringify({ error: "Cloud mesh checkpoint requires node daemonId" });
|
|
57161
58031
|
}
|
|
57162
58032
|
}
|
|
57163
58033
|
async function meshApprove(ctx, args) {
|
|
@@ -57174,8 +58044,16 @@ async function meshApprove(ctx, args) {
|
|
|
57174
58044
|
action: args.action === "reject" ? "reject" : "approve"
|
|
57175
58045
|
});
|
|
57176
58046
|
return JSON.stringify(result, null, 2);
|
|
58047
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
58048
|
+
try {
|
|
58049
|
+
const targetId = `${node.daemonId}:session:${args.session_id}`;
|
|
58050
|
+
const res = await ctx.transport.approve(targetId, args.action === "reject" ? "reject" : "approve");
|
|
58051
|
+
return JSON.stringify(res, null, 2);
|
|
58052
|
+
} catch (e) {
|
|
58053
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58054
|
+
}
|
|
57177
58055
|
} else {
|
|
57178
|
-
return JSON.stringify({ error: "Cloud mesh approve
|
|
58056
|
+
return JSON.stringify({ error: "Cloud mesh approve requires node daemonId" });
|
|
57179
58057
|
}
|
|
57180
58058
|
}
|
|
57181
58059
|
async function meshCloneNode(ctx, args) {
|
|
@@ -57196,8 +58074,28 @@ async function meshCloneNode(ctx, args) {
|
|
|
57196
58074
|
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57197
58075
|
}
|
|
57198
58076
|
return JSON.stringify(result, null, 2);
|
|
58077
|
+
} else if (!isLocalTransport(ctx.transport) && sourceNode.daemonId) {
|
|
58078
|
+
try {
|
|
58079
|
+
const res = await ctx.transport.meshCloneNode(sourceNode.daemonId, {
|
|
58080
|
+
meshId: ctx.mesh.id,
|
|
58081
|
+
sourceNodeId: args.source_node_id,
|
|
58082
|
+
branch: args.branch,
|
|
58083
|
+
baseBranch: args.base_branch,
|
|
58084
|
+
inlineMesh: ctx.mesh
|
|
58085
|
+
});
|
|
58086
|
+
const clonePayload = extractCloneNodePayload(res);
|
|
58087
|
+
if (clonePayload?.success && clonePayload.node?.id) {
|
|
58088
|
+
const existingIndex = ctx.mesh.nodes.findIndex((n) => n.id === clonePayload.node.id);
|
|
58089
|
+
if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
|
|
58090
|
+
else ctx.mesh.nodes.push(clonePayload.node);
|
|
58091
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58092
|
+
}
|
|
58093
|
+
return JSON.stringify(res, null, 2);
|
|
58094
|
+
} catch (e) {
|
|
58095
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58096
|
+
}
|
|
57199
58097
|
} else {
|
|
57200
|
-
return JSON.stringify({ error: "Cloud mesh clone_node
|
|
58098
|
+
return JSON.stringify({ error: "Cloud mesh clone_node requires source node daemonId" });
|
|
57201
58099
|
}
|
|
57202
58100
|
}
|
|
57203
58101
|
async function meshCleanupSessions(ctx, args) {
|
|
@@ -57212,8 +58110,22 @@ async function meshCleanupSessions(ctx, args) {
|
|
|
57212
58110
|
inlineMesh: ctx.mesh
|
|
57213
58111
|
});
|
|
57214
58112
|
return JSON.stringify(result, null, 2);
|
|
58113
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
58114
|
+
try {
|
|
58115
|
+
const res = await ctx.transport.meshCleanupSessions(node.daemonId, {
|
|
58116
|
+
meshId: ctx.mesh.id,
|
|
58117
|
+
nodeId: args.node_id,
|
|
58118
|
+
mode: args.mode,
|
|
58119
|
+
sessionIds: args.session_ids,
|
|
58120
|
+
dryRun: args.dry_run === true,
|
|
58121
|
+
inlineMesh: ctx.mesh
|
|
58122
|
+
});
|
|
58123
|
+
return JSON.stringify(res, null, 2);
|
|
58124
|
+
} catch (e) {
|
|
58125
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58126
|
+
}
|
|
57215
58127
|
} else {
|
|
57216
|
-
return JSON.stringify({ error: "Cloud mesh cleanup_sessions
|
|
58128
|
+
return JSON.stringify({ error: "Cloud mesh cleanup_sessions requires node daemonId" });
|
|
57217
58129
|
}
|
|
57218
58130
|
}
|
|
57219
58131
|
async function meshRemoveNode(ctx, args) {
|
|
@@ -57233,8 +58145,65 @@ async function meshRemoveNode(ctx, args) {
|
|
|
57233
58145
|
}
|
|
57234
58146
|
}
|
|
57235
58147
|
return JSON.stringify(result, null, 2);
|
|
58148
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
58149
|
+
try {
|
|
58150
|
+
const res = await ctx.transport.meshRemoveNode(node.daemonId, {
|
|
58151
|
+
meshId: ctx.mesh.id,
|
|
58152
|
+
nodeId: args.node_id,
|
|
58153
|
+
...args.session_cleanup_mode ? { sessionCleanupMode: args.session_cleanup_mode } : {},
|
|
58154
|
+
inlineMesh: ctx.mesh
|
|
58155
|
+
});
|
|
58156
|
+
if (res?.success && res.removed !== false) {
|
|
58157
|
+
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
58158
|
+
if (idx >= 0) {
|
|
58159
|
+
ctx.mesh.nodes.splice(idx, 1);
|
|
58160
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58161
|
+
}
|
|
58162
|
+
}
|
|
58163
|
+
return JSON.stringify(res, null, 2);
|
|
58164
|
+
} catch (e) {
|
|
58165
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58166
|
+
}
|
|
57236
58167
|
} else {
|
|
57237
|
-
return JSON.stringify({ error: "Cloud mesh remove_node
|
|
58168
|
+
return JSON.stringify({ error: "Cloud mesh remove_node requires node daemonId" });
|
|
58169
|
+
}
|
|
58170
|
+
}
|
|
58171
|
+
async function meshRefineNode(ctx, args) {
|
|
58172
|
+
const node = await findNodeWithRefresh(ctx, args.node_id);
|
|
58173
|
+
if (isLocalTransport(ctx.transport)) {
|
|
58174
|
+
const result = await commandForNode(ctx, node, "refine_mesh_node", {
|
|
58175
|
+
meshId: ctx.mesh.id,
|
|
58176
|
+
nodeId: args.node_id,
|
|
58177
|
+
inlineMesh: ctx.mesh
|
|
58178
|
+
});
|
|
58179
|
+
if (result?.success && result.removeResult?.removed !== false) {
|
|
58180
|
+
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
58181
|
+
if (idx >= 0) {
|
|
58182
|
+
ctx.mesh.nodes.splice(idx, 1);
|
|
58183
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58184
|
+
}
|
|
58185
|
+
}
|
|
58186
|
+
return JSON.stringify(result, null, 2);
|
|
58187
|
+
} else if (!isLocalTransport(ctx.transport) && node.daemonId) {
|
|
58188
|
+
try {
|
|
58189
|
+
const res = await ctx.transport.meshRefineNode(node.daemonId, {
|
|
58190
|
+
meshId: ctx.mesh.id,
|
|
58191
|
+
nodeId: args.node_id,
|
|
58192
|
+
inlineMesh: ctx.mesh
|
|
58193
|
+
});
|
|
58194
|
+
if (res?.success && res.removeResult?.removed !== false) {
|
|
58195
|
+
const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
|
|
58196
|
+
if (idx >= 0) {
|
|
58197
|
+
ctx.mesh.nodes.splice(idx, 1);
|
|
58198
|
+
ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
58199
|
+
}
|
|
58200
|
+
}
|
|
58201
|
+
return JSON.stringify(res, null, 2);
|
|
58202
|
+
} catch (e) {
|
|
58203
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
58204
|
+
}
|
|
58205
|
+
} else {
|
|
58206
|
+
return JSON.stringify({ error: "Cloud mesh refine_node requires node daemonId" });
|
|
57238
58207
|
}
|
|
57239
58208
|
}
|
|
57240
58209
|
|
|
@@ -57348,6 +58317,36 @@ var CloudTransport = class {
|
|
|
57348
58317
|
"Authorization": `Bearer ${this.apiKey}`
|
|
57349
58318
|
};
|
|
57350
58319
|
}
|
|
58320
|
+
async listRemoteMeshes() {
|
|
58321
|
+
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes`, { headers: this.headers() });
|
|
58322
|
+
if (!res.ok) throw new Error(`List remote meshes failed: ${res.status}`);
|
|
58323
|
+
return res.json();
|
|
58324
|
+
}
|
|
58325
|
+
async createRemoteMesh(data) {
|
|
58326
|
+
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes`, {
|
|
58327
|
+
method: "POST",
|
|
58328
|
+
headers: this.headers(),
|
|
58329
|
+
body: JSON.stringify(data)
|
|
58330
|
+
});
|
|
58331
|
+
if (!res.ok) throw new Error(`Create remote mesh failed: ${res.status}`);
|
|
58332
|
+
return res.json();
|
|
58333
|
+
}
|
|
58334
|
+
async deleteRemoteMesh(meshId) {
|
|
58335
|
+
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes/${encodeURIComponent(meshId)}`, {
|
|
58336
|
+
method: "DELETE",
|
|
58337
|
+
headers: this.headers()
|
|
58338
|
+
});
|
|
58339
|
+
if (!res.ok) throw new Error(`Delete remote mesh failed: ${res.status}`);
|
|
58340
|
+
}
|
|
58341
|
+
async syncMeshLedger(meshId, data) {
|
|
58342
|
+
const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes/${encodeURIComponent(meshId)}/ledger/sync`, {
|
|
58343
|
+
method: "POST",
|
|
58344
|
+
headers: this.headers(),
|
|
58345
|
+
body: JSON.stringify(data)
|
|
58346
|
+
});
|
|
58347
|
+
if (!res.ok) throw new Error(`Sync mesh ledger failed: ${res.status}`);
|
|
58348
|
+
return res.json();
|
|
58349
|
+
}
|
|
57351
58350
|
async listDaemons() {
|
|
57352
58351
|
const res = await fetch(`${this.baseUrl}/api/v1/daemons`, { headers: this.headers() });
|
|
57353
58352
|
if (!res.ok) throw new Error(`List daemons failed: ${res.status}`);
|
|
@@ -57505,6 +58504,66 @@ var CloudTransport = class {
|
|
|
57505
58504
|
if (!res.ok) throw new Error(`Git checkpoint failed: ${res.status}`);
|
|
57506
58505
|
return res.json();
|
|
57507
58506
|
}
|
|
58507
|
+
async meshCloneNode(daemonId, payload) {
|
|
58508
|
+
const res = await fetch(
|
|
58509
|
+
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/clone-node`,
|
|
58510
|
+
{
|
|
58511
|
+
method: "POST",
|
|
58512
|
+
headers: this.headers(),
|
|
58513
|
+
body: JSON.stringify(payload)
|
|
58514
|
+
}
|
|
58515
|
+
);
|
|
58516
|
+
if (!res.ok) throw new Error(`Mesh clone node failed: ${res.status}`);
|
|
58517
|
+
return res.json();
|
|
58518
|
+
}
|
|
58519
|
+
async meshRemoveNode(daemonId, payload) {
|
|
58520
|
+
const res = await fetch(
|
|
58521
|
+
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/remove-node`,
|
|
58522
|
+
{
|
|
58523
|
+
method: "POST",
|
|
58524
|
+
headers: this.headers(),
|
|
58525
|
+
body: JSON.stringify(payload)
|
|
58526
|
+
}
|
|
58527
|
+
);
|
|
58528
|
+
if (!res.ok) throw new Error(`Mesh remove node failed: ${res.status}`);
|
|
58529
|
+
return res.json();
|
|
58530
|
+
}
|
|
58531
|
+
async meshCleanupSessions(daemonId, payload) {
|
|
58532
|
+
const res = await fetch(
|
|
58533
|
+
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/cleanup-sessions`,
|
|
58534
|
+
{
|
|
58535
|
+
method: "POST",
|
|
58536
|
+
headers: this.headers(),
|
|
58537
|
+
body: JSON.stringify(payload)
|
|
58538
|
+
}
|
|
58539
|
+
);
|
|
58540
|
+
if (!res.ok) throw new Error(`Mesh cleanup sessions failed: ${res.status}`);
|
|
58541
|
+
return res.json();
|
|
58542
|
+
}
|
|
58543
|
+
async meshEnqueueTask(daemonId, payload) {
|
|
58544
|
+
const res = await fetch(
|
|
58545
|
+
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/enqueue`,
|
|
58546
|
+
{
|
|
58547
|
+
method: "POST",
|
|
58548
|
+
headers: this.headers(),
|
|
58549
|
+
body: JSON.stringify(payload)
|
|
58550
|
+
}
|
|
58551
|
+
);
|
|
58552
|
+
if (!res.ok) throw new Error(`Mesh enqueue task failed: ${res.status}`);
|
|
58553
|
+
return res.json();
|
|
58554
|
+
}
|
|
58555
|
+
async meshRefineNode(daemonId, payload) {
|
|
58556
|
+
const res = await fetch(
|
|
58557
|
+
`${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/refine-node`,
|
|
58558
|
+
{
|
|
58559
|
+
method: "POST",
|
|
58560
|
+
headers: this.headers(),
|
|
58561
|
+
body: JSON.stringify(payload)
|
|
58562
|
+
}
|
|
58563
|
+
);
|
|
58564
|
+
if (!res.ok) throw new Error(`Mesh refine node failed: ${res.status}`);
|
|
58565
|
+
return res.json();
|
|
58566
|
+
}
|
|
57508
58567
|
async ping() {
|
|
57509
58568
|
try {
|
|
57510
58569
|
await this.listDaemons();
|
|
@@ -58372,7 +59431,7 @@ var GIT_CHECKPOINT_TOOL = {
|
|
|
58372
59431
|
required: ["workspace", "message"]
|
|
58373
59432
|
}
|
|
58374
59433
|
};
|
|
58375
|
-
async function
|
|
59434
|
+
async function gitCheckpoint2(transport, args) {
|
|
58376
59435
|
const message = args.message?.trim();
|
|
58377
59436
|
if (!message) return "Error: message is required";
|
|
58378
59437
|
if (message.length > 200) return "Error: message must be 200 characters or fewer";
|
|
@@ -58432,7 +59491,7 @@ var GIT_PUSH_TOOL = {
|
|
|
58432
59491
|
required: ["workspace"]
|
|
58433
59492
|
}
|
|
58434
59493
|
};
|
|
58435
|
-
async function
|
|
59494
|
+
async function gitPush2(transport, args) {
|
|
58436
59495
|
let raw;
|
|
58437
59496
|
if (isLocalTransport(transport)) {
|
|
58438
59497
|
raw = await transport.command("git_push", {
|
|
@@ -58823,6 +59882,12 @@ async function startMcpServer(opts) {
|
|
|
58823
59882
|
case "mesh_list_nodes":
|
|
58824
59883
|
text = await meshListNodes(meshCtx);
|
|
58825
59884
|
break;
|
|
59885
|
+
case "mesh_enqueue_task":
|
|
59886
|
+
text = await meshEnqueueTask(meshCtx, a);
|
|
59887
|
+
break;
|
|
59888
|
+
case "mesh_view_queue":
|
|
59889
|
+
text = await meshViewQueue(meshCtx, a);
|
|
59890
|
+
break;
|
|
58826
59891
|
case "mesh_send_task":
|
|
58827
59892
|
text = await meshSendTask(meshCtx, a);
|
|
58828
59893
|
break;
|
|
@@ -58850,9 +59915,15 @@ async function startMcpServer(opts) {
|
|
|
58850
59915
|
case "mesh_remove_node":
|
|
58851
59916
|
text = await meshRemoveNode(meshCtx, a);
|
|
58852
59917
|
break;
|
|
59918
|
+
case "mesh_refine_node":
|
|
59919
|
+
text = await meshRefineNode(meshCtx, a);
|
|
59920
|
+
break;
|
|
58853
59921
|
case "mesh_cleanup_sessions":
|
|
58854
59922
|
text = await meshCleanupSessions(meshCtx, a);
|
|
58855
59923
|
break;
|
|
59924
|
+
case "mesh_task_history":
|
|
59925
|
+
text = await meshTaskHistory(meshCtx, a);
|
|
59926
|
+
break;
|
|
58856
59927
|
default:
|
|
58857
59928
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
58858
59929
|
}
|
|
@@ -58941,11 +60012,11 @@ async function startMcpServer(opts) {
|
|
|
58941
60012
|
return { content: [{ type: "text", text }] };
|
|
58942
60013
|
}
|
|
58943
60014
|
case "git_checkpoint": {
|
|
58944
|
-
const text = await
|
|
60015
|
+
const text = await gitCheckpoint2(transport, { workspace: a.workspace, message: a.message, include_untracked: a.include_untracked, daemon_id: a.daemon_id });
|
|
58945
60016
|
return { content: [{ type: "text", text }] };
|
|
58946
60017
|
}
|
|
58947
60018
|
case "git_push": {
|
|
58948
|
-
const text = await
|
|
60019
|
+
const text = await gitPush2(transport, { workspace: a.workspace, remote: a.remote, branch: a.branch, daemon_id: a.daemon_id });
|
|
58949
60020
|
return { content: [{ type: "text", text }] };
|
|
58950
60021
|
}
|
|
58951
60022
|
case "launch_session": {
|