@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.
@@ -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 EventEmitter2 = require("events");
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 EventEmitter2 {
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 EventEmitter2 = require("events");
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 EventEmitter2 {
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 gracefully.** If a task fails, read the chat to understand why, then retry or reassign.
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 path10.join(LOG_DIR, `daemon-${date5.toISOString().slice(0, 10)}.log`);
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 = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
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(path10.join(LOG_DIR, file2));
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, import_fs6.constants.R_OK);
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 }) => gitCheckpoint2(workspace, message, includeUntracked),
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 }) => gitPush2(workspace, remote, branch, setUpstream)
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 gitCheckpoint2(workspace, message, includeUntracked) {
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 gitPush2(workspace, remote, branch, setUpstream) {
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(os5.homedir(), t.slice(1).replace(/^\//, ""));
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: os5.homedir(), source: "home" };
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, import_crypto4.randomUUID)(),
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, import_path3.join)(getConfigDir(), "state.json");
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, import_fs7.existsSync)(statePath)) {
28673
+ if (!(0, import_fs9.existsSync)(statePath)) {
28076
28674
  return { ...DEFAULT_STATE };
28077
28675
  }
28078
28676
  try {
28079
- const raw = (0, import_fs7.readFileSync)(statePath, "utf-8");
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, import_fs7.writeFileSync)(statePath, JSON.stringify(normalized, null, 2), { encoding: "utf-8", mode: 384 });
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 (path8.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~")) {
28110
- const candidate = trimmed.startsWith("~") ? path8.join((0, import_os3.homedir)(), trimmed.slice(1)) : trimmed;
28111
- const resolved = path8.isAbsolute(candidate) ? candidate : path8.resolve(candidate);
28112
- return (0, import_fs8.existsSync)(resolved) ? resolved : null;
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("~") ? path8.join(home, p.slice(1)) : p;
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, import_fs8.existsSync)(resolved)) return resolved;
28741
+ if ((0, import_fs10.existsSync)(resolved)) return resolved;
28144
28742
  } else {
28145
- if ((0, import_fs8.existsSync)(normalized)) return normalized;
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, import_fs8.existsSync)(bundledCli)) resolvedCli = bundledCli;
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, import_fs8.existsSync)(c)) {
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 path9.join(os22.homedir(), trimmed.slice(1));
28802
+ return path10.join(os32.homedir(), trimmed.slice(1));
28205
28803
  }
28206
28804
  function isExplicitCommandPath(command) {
28207
28805
  const trimmed = command.trim();
28208
- return path9.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
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 = path9.isAbsolute(expanded) ? expanded : path9.resolve(expanded);
28216
- return (0, import_fs9.existsSync)(candidate) ? candidate : null;
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 = os22.platform();
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 = os22.platform();
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 (os32.platform() !== "darwin") return null;
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 = os32.totalmem();
28349
- const freeMem = os32.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, import_crypto5.randomUUID)().slice(0, 8)}`;
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, import_fs10.existsSync)(expandExecutable(trimmed));
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, import_fs10.mkdirSync)(baseDir, { recursive: true });
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, import_fs10.writeFileSync)(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
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, import_path4.join)(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
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, import_path4.resolve)(workspace || os17.tmpdir())}`;
34986
- const hash2 = (0, import_crypto6.createHash)("sha256").update(key).digest("hex").slice(0, 16);
34987
- return (0, import_path4.join)(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash2}`);
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, import_path4.join)(os17.homedir(), trimmed.slice(2));
34993
- if ((0, import_path4.isAbsolute)(trimmed)) return trimmed;
34994
- return (0, import_path4.join)(workspace, trimmed);
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, import_path4.join)(dir, "node"));
35644
+ addCandidate((0, import_path6.join)(dir, "node"));
35035
35645
  }
35036
35646
  }
35037
35647
  function addNodeCandidatesFromNvm(homeDir, addCandidate) {
35038
- const versionsDir = (0, import_path4.join)(homeDir, ".nvm", "versions", "node");
35648
+ const versionsDir = (0, import_path6.join)(homeDir, ".nvm", "versions", "node");
35039
35649
  try {
35040
- const versionDirs = (0, import_fs11.readdirSync)(versionsDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(compareNodeVersionNamesDescending);
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, import_path4.join)(versionsDir, versionDir, "bin", "node"));
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, import_path4.dirname)(realBase);
35081
- addCandidate((0, import_path4.resolve)(dir, "../vendor/mcp-server/index.js"));
35082
- addCandidate((0, import_path4.resolve)(dir, "../../vendor/mcp-server/index.js"));
35083
- addCandidate((0, import_path4.resolve)(dir, "../../../vendor/mcp-server/index.js"));
35084
- addCandidate((0, import_path4.resolve)(dir, "../../mcp-server/dist/index.js"));
35085
- addCandidate((0, import_path4.resolve)(dir, "../../../mcp-server/dist/index.js"));
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, import_path4.join)(process.cwd(), "adhdev-daemon.js");
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, import_fs11.existsSync)(filePath)) return null;
35104
- return import_fs11.realpathSync.native(filePath);
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, import_path5.join)((0, import_os4.homedir)(), ".hermes");
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, import_path5.join)(sourceHome, "config.yaml");
36420
+ const sourceConfigPath = (0, import_path7.join)(sourceHome, "config.yaml");
35928
36421
  if (!fs10.existsSync(sourceConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
35929
- if ((0, import_path5.resolve)(sourceConfigPath) === (0, import_path5.resolve)(targetConfigPath)) return { config: {}, sourceHome, sourceConfigPath };
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, import_path5.resolve)(sourceHome) === (0, import_path5.resolve)(targetHome)) return;
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, import_path5.join)(sourceHome, fileName);
35938
- const targetPath = (0, import_path5.join)(targetHome, fileName);
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, path10, os4, os8, os9, path14, import_child_process2, os10, path15, os11, import_child_process3, import_fs6, import_promises5, path, import_util4, import_promises6, path22, path32, fs, os5, path5, import_crypto4, path6, path7, import_fs7, import_path3, import_child_process4, import_fs8, import_os3, path8, import_child_process5, os22, path9, import_fs9, os32, import_child_process6, http, crypto2, fs3, path11, os52, fs4, os6, path12, import_crypto5, fs5, path13, os7, os13, path18, crypto4, import_fs10, 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_crypto6, import_fs11, import_module2, os17, import_path4, os18, import_child_process11, import_child_process12, fs9, os19, path222, import_os4, import_path5, 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, 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, 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, MAX_PENDING_EVENTS, pendingMeshCoordinatorEvents, MESH_COORDINATOR_EVENTS, 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;
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
- path10 = __toESM(require("path"), 1);
40441
- os4 = __toESM(require("os"), 1);
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
- import_fs6 = require("fs");
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
- os5 = __toESM(require("os"), 1);
40960
+ os4 = __toESM(require("os"), 1);
40461
40961
  path5 = __toESM(require("path"), 1);
40462
- import_crypto4 = require("crypto");
40962
+ import_crypto6 = require("crypto");
40463
40963
  path6 = __toESM(require("path"), 1);
40464
40964
  path7 = __toESM(require("path"), 1);
40465
- import_fs7 = require("fs");
40466
- import_path3 = require("path");
40965
+ import_fs9 = require("fs");
40966
+ import_path5 = require("path");
40467
40967
  import_child_process4 = require("child_process");
40468
- import_fs8 = require("fs");
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
- import_fs9 = require("fs");
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
- os52 = __toESM(require("os"), 1);
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
- import_crypto5 = require("crypto");
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
- import_fs10 = require("fs");
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
- import_crypto6 = require("crypto");
40519
- import_fs11 = require("fs");
41018
+ import_crypto8 = require("crypto");
41019
+ import_fs13 = require("fs");
40520
41020
  import_module2 = require("module");
40521
41021
  os17 = __toESM(require("os"), 1);
40522
- import_path4 = require("path");
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
- import_path5 = require("path");
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 For each task:
40703
- a. Pick the best node (consider: health, dirty state, current workload).
40704
- b. If you need branch isolation for parallel work, call \`mesh_clone_node\` to create a worktree node first.
40705
- c. If no session exists, call \`mesh_launch_session\` to start one.
40706
- d. Call \`mesh_send_task\` with a **complete, self-contained** instruction that includes all context the agent needs (file paths, line numbers, what to change, why). Do not send partial instructions expecting future follow-up.
40707
- 4. **Monitor** \u2014 Prefer event-driven completion/status notifications. Do **not** poll \`mesh_read_chat\` repeatedly just because the delegated session has not produced a final assistant message yet; tool/terminal activity means work may still be in progress. Do not call \`mesh_read_chat\` again within a few seconds for the same generating session; wait for the completion callback/status event instead unless you are debugging a real stall. Use at most one compact \`mesh_read_chat\` check after a completion/approval signal, an explicit user status request, or a real timeout/stall. Handle approvals via \`mesh_approve\`.
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" ? path10.join(process.env.LOCALAPPDATA || process.env.APPDATA || path10.join(os4.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path10.join(os4.homedir(), "Library", "Logs", "adhdev") : path10.join(os4.homedir(), ".local", "share", "adhdev", "logs");
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 = path10.join(LOG_DIR, `daemon-${currentDate}.log`);
41269
+ currentLogFile = path8.join(LOG_DIR, `daemon-${currentDate}.log`);
40729
41270
  cleanOldLogs();
40730
41271
  try {
40731
- const oldLog = path10.join(LOG_DIR, "daemon.log");
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, path10.join(LOG_DIR, `daemon-${oldDate}.log`));
41276
+ fs2.renameSync(oldLog, path8.join(LOG_DIR, `daemon-${oldDate}.log`));
40736
41277
  }
40737
- const oldLogBackup = path10.join(LOG_DIR, "daemon.log.old");
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 = path10.join(LOG_DIR, `daemon-${getDateStr()}.log`);
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(os52.homedir(), ".adhdev", "history");
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
- init_mesh_config();
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: randomUUID8 } = await import("crypto");
53208
+ const { randomUUID: randomUUID10 } = await import("crypto");
52568
53209
  node = {
52569
- id: `node_${randomUUID8().replace(/-/g, "")}`,
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: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync14, copyFileSync: copyFileSync4, mkdirSync: mkdirSync16 } = await import("fs");
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
- mkdirSync16(dirname92(mcpConfigPath), { recursive: true });
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 = existsSync23(mcpConfigPath);
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(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
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
- writeFileSync14(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
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: "Send a natural-language task to an agent session on a mesh node. The agent will execute the task autonomously.",
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
- MESH_CLEANUP_SESSIONS_TOOL
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
- if (isLocalTransport(ctx.transport)) {
56988
- const result = await commandForNode(ctx, node, "send_chat", {
56989
- message: args.message,
56990
- sessionId: args.session_id,
56991
- targetSessionId: args.session_id
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
- return JSON.stringify({ success: true, nodeId: args.node_id, sessionId: args.session_id });
57003
- } else {
57004
- return JSON.stringify({ error: "Cloud mesh send_task not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 not yet implemented" });
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 gitCheckpoint(transport, args) {
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 gitPush(transport, args) {
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 gitCheckpoint(transport, { workspace: a.workspace, message: a.message, include_untracked: a.include_untracked, daemon_id: a.daemon_id });
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 gitPush(transport, { workspace: a.workspace, remote: a.remote, branch: a.branch, daemon_id: a.daemon_id });
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": {