@adhdev/daemon-standalone 0.9.76 → 0.9.77-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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({
@@ -41293,6 +41865,8 @@ Before doing any coordinator work, confirm that the actual callable tool list in
41293
41865
  statusHistory = [];
41294
41866
  // ─── CLI Scripts (script-based parsing) ───
41295
41867
  cliScripts;
41868
+ /** Per-session opaque state object created by cliScripts.createState(), reset on stop. */
41869
+ scriptState = null;
41296
41870
  runtimeSettings = {};
41297
41871
  /** Full accumulated rendered PTY transcript for parser/readback use */
41298
41872
  accumulatedBuffer = "";
@@ -41474,6 +42048,7 @@ ${lastSnapshot}`;
41474
42048
  this.cliScripts = scripts;
41475
42049
  this.parsedStatusCache = null;
41476
42050
  this.parseErrorMessage = null;
42051
+ this.scriptState = typeof scripts.createState === "function" ? scripts.createState() : null;
41477
42052
  const scriptNames = listCliScriptNames(scripts);
41478
42053
  LOG.info("CLI", `[${this.cliType}] CLI scripts injected: [${scriptNames.join(", ")}]`);
41479
42054
  }
@@ -41591,6 +42166,7 @@ ${lastSnapshot}`;
41591
42166
  this.ready = false;
41592
42167
  this.startupParseGate = false;
41593
42168
  this.spawnAt = 0;
42169
+ this.scriptState = null;
41594
42170
  this.onStatusChange?.();
41595
42171
  });
41596
42172
  this.spawnAt = Date.now();
@@ -42364,7 +42940,7 @@ ${lastSnapshot}`;
42364
42940
  scope: this.currentTurnScope,
42365
42941
  runtimeSettings: this.runtimeSettings
42366
42942
  });
42367
- const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
42943
+ const session = this.cliScripts.parseSession(this.scriptState, { ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
42368
42944
  this.parseErrorMessage = null;
42369
42945
  return session && typeof session === "object" ? session : null;
42370
42946
  } catch (e) {
@@ -42378,7 +42954,7 @@ ${lastSnapshot}`;
42378
42954
  if (!this.cliScripts?.detectStatus) return null;
42379
42955
  try {
42380
42956
  const screenText = this.terminalScreen.getText();
42381
- const status = this.cliScripts.detectStatus({
42957
+ const status = this.cliScripts.detectStatus(this.scriptState, {
42382
42958
  tail: text.slice(-500),
42383
42959
  screenText,
42384
42960
  rawBuffer: this.accumulatedRawBuffer,
@@ -42397,7 +42973,7 @@ ${lastSnapshot}`;
42397
42973
  try {
42398
42974
  const screenText = this.terminalScreen.getText();
42399
42975
  const buffer = screenText || this.accumulatedBuffer;
42400
- return this.cliScripts.parseApproval({
42976
+ return this.cliScripts.parseApproval(this.scriptState, {
42401
42977
  buffer,
42402
42978
  screenText,
42403
42979
  rawBuffer: this.accumulatedRawBuffer,
@@ -42505,7 +43081,7 @@ ${lastSnapshot}`;
42505
43081
  scope: this.currentTurnScope,
42506
43082
  runtimeSettings: this.runtimeSettings
42507
43083
  });
42508
- return await Promise.resolve(fn({
43084
+ return await Promise.resolve(fn(this.scriptState, {
42509
43085
  ...input,
42510
43086
  args: args && typeof args === "object" ? { ...args } : {}
42511
43087
  }));
@@ -43497,6 +44073,9 @@ ${lastSnapshot}`;
43497
44073
  init_mesh_config();
43498
44074
  init_coordinator_prompt();
43499
44075
  init_mesh_config();
44076
+ init_mesh_ledger();
44077
+ init_mesh_work_queue();
44078
+ init_mesh_events();
43500
44079
  init_config();
43501
44080
  DEFAULT_STATE = {
43502
44081
  recentActivity: [],
@@ -44963,7 +45542,7 @@ ${lastSnapshot}`;
44963
45542
  HIDDEN_AUDIENCES = /* @__PURE__ */ new Set(["debug", "trace", "internal"]);
44964
45543
  ACTIVITY_SOURCE_SET = new Set(CHAT_MESSAGE_ACTIVITY_SOURCES);
44965
45544
  INTERNAL_SOURCE_SET = new Set(CHAT_MESSAGE_INTERNAL_SOURCES);
44966
- HISTORY_DIR = path11.join(os52.homedir(), ".adhdev", "history");
45545
+ HISTORY_DIR = path11.join(os5.homedir(), ".adhdev", "history");
44967
45546
  RETAIN_DAYS = 30;
44968
45547
  SAVED_HISTORY_INDEX_VERSION = 1;
44969
45548
  SAVED_HISTORY_INDEX_FILE = ".saved-history-index.json";
@@ -46682,6 +47261,7 @@ ${effect.notification.body || ""}`.trim();
46682
47261
  };
46683
47262
  STATUS_MODAL_MESSAGE_LIMIT = 2 * 1024;
46684
47263
  STATUS_MODAL_BUTTON_LIMIT = 120;
47264
+ init_mesh_work_queue();
46685
47265
  VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
46686
47266
  VALID_INPUT_STRATEGIES = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
46687
47267
  TEXT_ONLY_MESSAGE_INPUT_SUPPORT = Object.freeze({
@@ -51540,16 +52120,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
51540
52120
  DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
51541
52121
  HERMES_CLI_TYPE = "hermes-cli";
51542
52122
  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
- ]);
52123
+ init_mesh_events();
51553
52124
  init_config();
51554
52125
  init_terminal_screen();
51555
52126
  init_logger();
@@ -52432,6 +53003,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
52432
53003
  return { success: false, error: e.message };
52433
53004
  }
52434
53005
  }
53006
+ case "get_mesh_ledger": {
53007
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53008
+ if (!meshId) return { success: false, error: "meshId required" };
53009
+ try {
53010
+ const { readLedgerEntries: readLedgerEntries2, getLedgerSummary: getLedgerSummary2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
53011
+ const tail = typeof args?.tail === "number" ? args.tail : 20;
53012
+ const since = typeof args?.since === "string" ? args.since : void 0;
53013
+ const kind = Array.isArray(args?.kind) ? args.kind.filter((k) => typeof k === "string") : void 0;
53014
+ const entries = readLedgerEntries2(meshId, { tail, since, kind });
53015
+ const summary = getLedgerSummary2(meshId);
53016
+ return { success: true, entries, summary };
53017
+ } catch (e) {
53018
+ return { success: false, error: e.message };
53019
+ }
53020
+ }
52435
53021
  case "add_mesh_node": {
52436
53022
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
52437
53023
  const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
@@ -52500,6 +53086,54 @@ Run 'adhdev doctor' for detailed diagnostics.`
52500
53086
  return { success: false, error: e.message };
52501
53087
  }
52502
53088
  }
53089
+ case "refine_mesh_node": {
53090
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53091
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
53092
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
53093
+ try {
53094
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
53095
+ const mesh = meshRecord?.mesh;
53096
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
53097
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
53098
+ if (!node.isLocalWorktree || !node.workspace) {
53099
+ return { success: false, error: `Refinery requires a local worktree node` };
53100
+ }
53101
+ const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
53102
+ const repoRoot = sourceNode?.repoRoot || sourceNode?.workspace;
53103
+ if (!repoRoot) return { success: false, error: "Source node repoRoot not found" };
53104
+ const { execFile: execFile3 } = await import("child_process");
53105
+ const { promisify: promisify3 } = await import("util");
53106
+ const execFileAsync3 = promisify3(execFile3);
53107
+ const { stdout: branchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: node.workspace, encoding: "utf8" });
53108
+ const branch = branchStdout.trim();
53109
+ if (!branch) return { success: false, error: "Could not determine branch of the worktree node" };
53110
+ const { stdout: baseBranchStdout } = await execFileAsync3("git", ["branch", "--show-current"], { cwd: repoRoot, encoding: "utf8" });
53111
+ const baseBranch = baseBranchStdout.trim();
53112
+ try {
53113
+ await execFileAsync3("git", ["merge", "--no-ff", branch, "-m", `Auto-merge branch '${branch}' via Refinery`], { cwd: repoRoot, encoding: "utf8" });
53114
+ } catch (e) {
53115
+ return { success: false, error: `Merge failed (conflicts?): ${e.message}` };
53116
+ }
53117
+ const removeResult = await this.execute("remove_mesh_node", {
53118
+ meshId,
53119
+ nodeId,
53120
+ sessionCleanupMode: "kill",
53121
+ inlineMesh: args?.inlineMesh
53122
+ });
53123
+ try {
53124
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
53125
+ appendLedgerEntry2(meshId, {
53126
+ kind: "node_removed",
53127
+ nodeId,
53128
+ payload: { refined: true, mergedBranch: branch, into: baseBranch }
53129
+ });
53130
+ } catch {
53131
+ }
53132
+ return { success: true, merged: true, branch, into: baseBranch, removeResult };
53133
+ } catch (e) {
53134
+ return { success: false, error: e.message };
53135
+ }
53136
+ }
52503
53137
  case "remove_mesh_node": {
52504
53138
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
52505
53139
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
@@ -52535,6 +53169,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
52535
53169
  const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
52536
53170
  removed = removeNode3(meshId, nodeId);
52537
53171
  }
53172
+ if (removed) {
53173
+ try {
53174
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
53175
+ appendLedgerEntry2(meshId, {
53176
+ kind: "node_removed",
53177
+ nodeId,
53178
+ payload: { worktree: !!node?.isLocalWorktree, sessionCleanupMode }
53179
+ });
53180
+ } catch {
53181
+ }
53182
+ }
52538
53183
  return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
52539
53184
  } catch (e) {
52540
53185
  return { success: false, error: e.message };
@@ -52564,9 +53209,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
52564
53209
  });
52565
53210
  let node;
52566
53211
  if (meshRecord.inline) {
52567
- const { randomUUID: randomUUID8 } = await import("crypto");
53212
+ const { randomUUID: randomUUID10 } = await import("crypto");
52568
53213
  node = {
52569
- id: `node_${randomUUID8().replace(/-/g, "")}`,
53214
+ id: `node_${randomUUID10().replace(/-/g, "")}`,
52570
53215
  workspace: result.worktreePath,
52571
53216
  repoRoot: result.worktreePath,
52572
53217
  daemonId: sourceNode.daemonId,
@@ -52591,6 +53236,15 @@ Run 'adhdev doctor' for detailed diagnostics.`
52591
53236
  });
52592
53237
  if (!node) return { success: false, error: "Failed to register worktree node" };
52593
53238
  }
53239
+ try {
53240
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
53241
+ appendLedgerEntry2(meshId, {
53242
+ kind: "node_cloned",
53243
+ nodeId: node.id,
53244
+ payload: { sourceNodeId, branch: result.branch, worktreePath: result.worktreePath }
53245
+ });
53246
+ } catch {
53247
+ }
52594
53248
  return {
52595
53249
  success: true,
52596
53250
  node,
@@ -52601,6 +53255,19 @@ Run 'adhdev doctor' for detailed diagnostics.`
52601
53255
  return { success: false, error: e.message };
52602
53256
  }
52603
53257
  }
53258
+ case "trigger_mesh_queue": {
53259
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53260
+ if (!meshId) return { success: false, error: "meshId required" };
53261
+ try {
53262
+ const { triggerMeshQueue: triggerMeshQueue2 } = await Promise.resolve().then(() => (init_mesh_events(), mesh_events_exports));
53263
+ if (meshId) {
53264
+ triggerMeshQueue2(this.deps, meshId);
53265
+ }
53266
+ return { success: true };
53267
+ } catch (e) {
53268
+ return { success: false, error: e.message };
53269
+ }
53270
+ }
52604
53271
  // ─── Mesh Coordinator Launch ───
52605
53272
  case "launch_mesh_coordinator": {
52606
53273
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
@@ -52705,7 +53372,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
52705
53372
  workspace
52706
53373
  };
52707
53374
  }
52708
- const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync14, copyFileSync: copyFileSync4, mkdirSync: mkdirSync16 } = await import("fs");
53375
+ const { existsSync: existsSync25, readFileSync: readFileSync17, writeFileSync: writeFileSync15, copyFileSync: copyFileSync4, mkdirSync: mkdirSync17 } = await import("fs");
52709
53376
  const { dirname: dirname92 } = await import("path");
52710
53377
  const mcpConfigPath = coordinatorSetup.configPath;
52711
53378
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -52739,21 +53406,21 @@ Run 'adhdev doctor' for detailed diagnostics.`
52739
53406
  };
52740
53407
  }
52741
53408
  try {
52742
- mkdirSync16(dirname92(mcpConfigPath), { recursive: true });
53409
+ mkdirSync17(dirname92(mcpConfigPath), { recursive: true });
52743
53410
  } catch (error48) {
52744
53411
  const message = `Could not prepare MCP config path for automatic setup: ${error48?.message || error48}`;
52745
53412
  LOG.error("MeshCoordinator", message);
52746
53413
  if (hermesManualFallback) return returnManualFallback(message);
52747
53414
  return { success: false, code: "mesh_coordinator_config_write_failed", error: message, meshId, cliType, workspace };
52748
53415
  }
52749
- const hadExistingMcpConfig = existsSync23(mcpConfigPath);
53416
+ const hadExistingMcpConfig = existsSync25(mcpConfigPath);
52750
53417
  let existingMcpConfig = hermesBaseConfig?.config || {};
52751
53418
  if (hermesBaseConfig) {
52752
53419
  copyHermesCoordinatorCredentialFiles(hermesBaseConfig.sourceHome, dirname92(mcpConfigPath));
52753
53420
  }
52754
53421
  if (hadExistingMcpConfig) {
52755
53422
  try {
52756
- const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync15(mcpConfigPath, "utf-8"), configFormat);
53423
+ const parsedExistingMcpConfig = parseMeshCoordinatorMcpConfig(readFileSync17(mcpConfigPath, "utf-8"), configFormat);
52757
53424
  existingMcpConfig = { ...existingMcpConfig, ...parsedExistingMcpConfig };
52758
53425
  copyFileSync4(mcpConfigPath, mcpConfigPath + ".backup");
52759
53426
  } catch (error48) {
@@ -52775,7 +53442,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
52775
53442
  }
52776
53443
  };
52777
53444
  try {
52778
- writeFileSync14(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
53445
+ writeFileSync15(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
52779
53446
  } catch (error48) {
52780
53447
  const message = `Could not write MCP config for automatic setup: ${error48?.message || error48}`;
52781
53448
  LOG.error("MeshCoordinator", message);
@@ -52812,6 +53479,16 @@ Run 'adhdev doctor' for detailed diagnostics.`
52812
53479
  return { success: false, error: launchResult?.error || "Failed to launch CLI session" };
52813
53480
  }
52814
53481
  LOG.info("MeshCoordinator", `Launched ${cliType} coordinator for mesh ${meshId} in ${workspace}`);
53482
+ try {
53483
+ const { appendLedgerEntry: appendLedgerEntry2 } = await Promise.resolve().then(() => (init_mesh_ledger(), mesh_ledger_exports));
53484
+ appendLedgerEntry2(meshId, {
53485
+ kind: "coordinator_started",
53486
+ sessionId: launchResult.sessionId || launchResult.id,
53487
+ providerType: cliType,
53488
+ payload: { workspace }
53489
+ });
53490
+ } catch {
53491
+ }
52815
53492
  return {
52816
53493
  success: true,
52817
53494
  meshId,
@@ -56359,6 +57036,7 @@ data: ${JSON.stringify(msg.data)}
56359
57036
  };
56360
57037
  init_logger();
56361
57038
  init_config();
57039
+ init_mesh_events();
56362
57040
  }
56363
57041
  });
56364
57042
 
@@ -56564,6 +57242,7 @@ function annotateRapidReadChatAdvisory(payload, options) {
56564
57242
  }
56565
57243
 
56566
57244
  // src/tools/mesh-tools.ts
57245
+ init_dist2();
56567
57246
  var meshSessionProviderMetadata = /* @__PURE__ */ new Map();
56568
57247
  async function refreshMeshFromDaemon(ctx) {
56569
57248
  if (!(ctx.transport instanceof IpcTransport)) return;
@@ -56744,9 +57423,34 @@ var MESH_LIST_NODES_TOOL = {
56744
57423
  properties: {}
56745
57424
  }
56746
57425
  };
57426
+ var MESH_ENQUEUE_TASK_TOOL = {
57427
+ name: "mesh_enqueue_task",
57428
+ 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.",
57429
+ inputSchema: {
57430
+ type: "object",
57431
+ properties: {
57432
+ message: { type: "string", description: "The task instruction for the agent." }
57433
+ },
57434
+ required: ["message"]
57435
+ }
57436
+ };
57437
+ var MESH_VIEW_QUEUE_TOOL = {
57438
+ name: "mesh_view_queue",
57439
+ description: "View the current status of the mesh work queue (pending, assigned, completed, failed tasks).",
57440
+ inputSchema: {
57441
+ type: "object",
57442
+ properties: {
57443
+ status: {
57444
+ type: "array",
57445
+ items: { type: "string" },
57446
+ description: "Filter by task status: pending, assigned, completed, failed. Returns all if omitted."
57447
+ }
57448
+ }
57449
+ }
57450
+ };
56747
57451
  var MESH_SEND_TASK_TOOL = {
56748
57452
  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.",
57453
+ description: "Legacy push-based task assignment. Enqueues a task specifically targeted at a given node. The node will pull it immediately if idle.",
56750
57454
  inputSchema: {
56751
57455
  type: "object",
56752
57456
  properties: {
@@ -56886,9 +57590,33 @@ var MESH_CLEANUP_SESSIONS_TOOL = {
56886
57590
  required: ["node_id", "mode"]
56887
57591
  }
56888
57592
  };
57593
+ var MESH_TASK_HISTORY_TOOL = {
57594
+ name: "mesh_task_history",
57595
+ 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.",
57596
+ inputSchema: {
57597
+ type: "object",
57598
+ properties: {
57599
+ tail: { type: "number", description: "Number of recent entries to return (default: 20)." },
57600
+ kind: { type: "string", description: "Filter by entry kind: task_dispatched, task_completed, task_failed, task_stalled, session_launched, checkpoint_created, node_cloned, node_removed." }
57601
+ }
57602
+ }
57603
+ };
57604
+ var MESH_REFINE_NODE_TOOL = {
57605
+ name: "mesh_refine_node",
57606
+ 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.",
57607
+ inputSchema: {
57608
+ type: "object",
57609
+ properties: {
57610
+ node_id: { type: "string", description: "Node ID of the completed worktree node to refine and merge." }
57611
+ },
57612
+ required: ["node_id"]
57613
+ }
57614
+ };
56889
57615
  var ALL_MESH_TOOLS = [
56890
57616
  MESH_STATUS_TOOL,
56891
57617
  MESH_LIST_NODES_TOOL,
57618
+ MESH_ENQUEUE_TASK_TOOL,
57619
+ MESH_VIEW_QUEUE_TOOL,
56892
57620
  MESH_SEND_TASK_TOOL,
56893
57621
  MESH_READ_CHAT_TOOL,
56894
57622
  MESH_READ_DEBUG_TOOL,
@@ -56898,7 +57626,9 @@ var ALL_MESH_TOOLS = [
56898
57626
  MESH_APPROVE_TOOL,
56899
57627
  MESH_CLONE_NODE_TOOL,
56900
57628
  MESH_REMOVE_NODE_TOOL,
56901
- MESH_CLEANUP_SESSIONS_TOOL
57629
+ MESH_REFINE_NODE_TOOL,
57630
+ MESH_CLEANUP_SESSIONS_TOOL,
57631
+ MESH_TASK_HISTORY_TOOL
56902
57632
  ];
56903
57633
  async function meshStatus(ctx) {
56904
57634
  await refreshMeshFromDaemon(ctx);
@@ -56949,6 +57679,10 @@ async function meshStatus(ctx) {
56949
57679
  refreshedAt: (/* @__PURE__ */ new Date()).toISOString(),
56950
57680
  nodes: results
56951
57681
  };
57682
+ try {
57683
+ response.ledgerSummary = getLedgerSummary(mesh.id);
57684
+ } catch {
57685
+ }
56952
57686
  if (ctx.transport instanceof IpcTransport) {
56953
57687
  try {
56954
57688
  const eventsResult = await ctx.transport.command("get_pending_mesh_events", {});
@@ -56961,6 +57695,14 @@ async function meshStatus(ctx) {
56961
57695
  }
56962
57696
  return JSON.stringify(response, null, 2);
56963
57697
  }
57698
+ async function meshTaskHistory(ctx, args) {
57699
+ const { mesh } = ctx;
57700
+ const tail = typeof args.tail === "number" && args.tail > 0 ? args.tail : 20;
57701
+ const kind = typeof args.kind === "string" && args.kind.trim() ? [args.kind.trim()] : void 0;
57702
+ const entries = readLedgerEntries(mesh.id, { tail, kind });
57703
+ const summary = getLedgerSummary(mesh.id);
57704
+ return JSON.stringify({ meshId: mesh.id, entries, summary }, null, 2);
57705
+ }
56964
57706
  async function meshListNodes(ctx) {
56965
57707
  await refreshMeshFromDaemon(ctx);
56966
57708
  const { mesh } = ctx;
@@ -56979,29 +57721,54 @@ async function meshListNodes(ctx) {
56979
57721
  }))
56980
57722
  }, null, 2);
56981
57723
  }
57724
+ async function meshEnqueueTask(ctx, args) {
57725
+ try {
57726
+ const task = enqueueTask(ctx.mesh.id, args.message);
57727
+ if (ctx.transport instanceof IpcTransport && ctx.localDaemonId) {
57728
+ ctx.transport.meshCommand(ctx.localDaemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
57729
+ });
57730
+ } else if (isLocalTransport(ctx.transport)) {
57731
+ ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
57732
+ });
57733
+ }
57734
+ return JSON.stringify({ success: true, taskId: task.id, status: task.status });
57735
+ } catch (e) {
57736
+ return JSON.stringify({ success: false, error: e.message });
57737
+ }
57738
+ }
57739
+ async function meshViewQueue(ctx, args) {
57740
+ try {
57741
+ const queue = getQueue(ctx.mesh.id, { status: args.status });
57742
+ return JSON.stringify({ success: true, queue }, null, 2);
57743
+ } catch (e) {
57744
+ return JSON.stringify({ success: false, error: e.message });
57745
+ }
57746
+ }
56982
57747
  async function meshSendTask(ctx, args) {
56983
57748
  const node = await findNodeWithRefresh(ctx, args.node_id);
56984
57749
  if (node.policy?.readOnly) {
56985
57750
  return JSON.stringify({ error: `Node '${args.node_id}' is read-only` });
56986
57751
  }
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"
57752
+ try {
57753
+ if (!isLocalTransport(ctx.transport) && node.daemonId) {
57754
+ const res = await ctx.transport.meshEnqueueTask(node.daemonId, {
57755
+ meshId: ctx.mesh.id,
57756
+ message: args.message,
57757
+ targetNodeId: args.node_id
57000
57758
  });
57759
+ return JSON.stringify(res);
57001
57760
  }
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" });
57761
+ const task = enqueueTask(ctx.mesh.id, args.message, { targetNodeId: args.node_id });
57762
+ if (ctx.transport instanceof IpcTransport && node.daemonId && node.daemonId !== ctx.localDaemonId) {
57763
+ ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
57764
+ });
57765
+ } else if (isLocalTransport(ctx.transport)) {
57766
+ ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
57767
+ });
57768
+ }
57769
+ return JSON.stringify({ success: true, nodeId: args.node_id, taskId: task.id, status: task.status });
57770
+ } catch (e) {
57771
+ return JSON.stringify({ success: false, error: e.message });
57005
57772
  }
57006
57773
  }
57007
57774
  async function meshReadChat(ctx, args) {
@@ -57035,8 +57802,19 @@ async function meshReadChat(ctx, args) {
57035
57802
  );
57036
57803
  }
57037
57804
  return JSON.stringify(payload, null, 2);
57805
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
57806
+ try {
57807
+ const targetId = `${node.daemonId}:session:${args.session_id}`;
57808
+ const res = await ctx.transport.readChat(targetId, {
57809
+ limit: args.tail ?? 10,
57810
+ sessionId: args.session_id
57811
+ });
57812
+ return JSON.stringify(res, null, 2);
57813
+ } catch (e) {
57814
+ return JSON.stringify({ success: false, error: e.message });
57815
+ }
57038
57816
  } else {
57039
- return JSON.stringify({ error: "Cloud mesh read_chat not yet implemented" });
57817
+ return JSON.stringify({ error: "Cloud mesh read_chat requires node daemonId" });
57040
57818
  }
57041
57819
  }
57042
57820
  async function meshReadDebug(ctx, args) {
@@ -57056,8 +57834,20 @@ async function meshReadDebug(ctx, args) {
57056
57834
  });
57057
57835
  const payload = unwrapCommandPayload(result);
57058
57836
  return JSON.stringify(payload, null, 2);
57837
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
57838
+ try {
57839
+ const targetId = `${node.daemonId}:session:${args.session_id}`;
57840
+ const res = await ctx.transport.getChatDebugBundle(targetId, {
57841
+ sessionId: args.session_id,
57842
+ tailLimit: args.tail ?? 40,
57843
+ delivery: args.delivery
57844
+ });
57845
+ return JSON.stringify(res, null, 2);
57846
+ } catch (e) {
57847
+ return JSON.stringify({ success: false, error: e.message });
57848
+ }
57059
57849
  }
57060
- return JSON.stringify({ error: "Cloud mesh read_debug not yet implemented" });
57850
+ return JSON.stringify({ error: "Cloud mesh read_debug requires node daemonId" });
57061
57851
  }
57062
57852
  async function meshLaunchSession(ctx, args) {
57063
57853
  const node = await findNodeWithRefresh(ctx, args.node_id);
@@ -57106,13 +57896,70 @@ async function meshLaunchSession(ctx, args) {
57106
57896
  ...providerSessionId ? { providerSessionId } : {}
57107
57897
  });
57108
57898
  }
57899
+ try {
57900
+ appendLedgerEntry(ctx.mesh.id, {
57901
+ kind: "session_launched",
57902
+ nodeId: args.node_id,
57903
+ sessionId: runtimeSessionId || void 0,
57904
+ providerType: resolvedProviderType,
57905
+ payload: { providerSessionId }
57906
+ });
57907
+ } catch {
57908
+ }
57909
+ if (ctx.transport instanceof IpcTransport && node.daemonId && node.daemonId !== ctx.localDaemonId) {
57910
+ ctx.transport.meshCommand(node.daemonId, "trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
57911
+ });
57912
+ } else if (isLocalTransport(ctx.transport)) {
57913
+ ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
57914
+ });
57915
+ }
57109
57916
  return JSON.stringify({
57110
57917
  ...launchPayload,
57111
57918
  resolvedProviderType,
57112
57919
  ...providerSessionId ? { providerSessionId } : {}
57113
57920
  }, null, 2);
57921
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
57922
+ let resolvedProviderType = typeof args.type === "string" && args.type.trim() ? args.type : "";
57923
+ if (!resolvedProviderType) {
57924
+ const providerPriority = readProviderPriority(node.policy);
57925
+ if (!providerPriority.length) {
57926
+ return JSON.stringify({ success: false, error: missingProviderPriorityMessage(args.node_id) });
57927
+ }
57928
+ resolvedProviderType = providerPriority[0];
57929
+ }
57930
+ const coordinatorNode = resolveCoordinatorNode(ctx);
57931
+ const coordinatorDaemonId = coordinatorNode?.daemonId || ctx.localDaemonId;
57932
+ const spawnedSessionVisibility = readSpawnedSessionVisibility(ctx.mesh.policy);
57933
+ try {
57934
+ const res = await ctx.transport.launch(node.daemonId, {
57935
+ type: resolvedProviderType,
57936
+ dir: node.workspace,
57937
+ settings: {
57938
+ meshNodeFor: ctx.mesh.id,
57939
+ meshNodeId: args.node_id,
57940
+ spawnedSessionVisibility,
57941
+ ...coordinatorDaemonId ? { meshCoordinatorDaemonId: coordinatorDaemonId } : {},
57942
+ ...coordinatorNode?.id ? { meshCoordinatorNodeId: coordinatorNode.id } : {},
57943
+ launchedByCoordinator: true
57944
+ }
57945
+ });
57946
+ const runtimeSessionId = typeof res?.sessionId === "string" ? res.sessionId : typeof res?.id === "string" ? res.id : "";
57947
+ try {
57948
+ appendLedgerEntry(ctx.mesh.id, {
57949
+ kind: "session_launched",
57950
+ nodeId: args.node_id,
57951
+ sessionId: runtimeSessionId || void 0,
57952
+ providerType: resolvedProviderType,
57953
+ payload: {}
57954
+ });
57955
+ } catch {
57956
+ }
57957
+ return JSON.stringify({ ...res, resolvedProviderType }, null, 2);
57958
+ } catch (e) {
57959
+ return JSON.stringify({ success: false, error: e.message });
57960
+ }
57114
57961
  } else {
57115
- return JSON.stringify({ error: "Cloud mesh launch_session not yet implemented" });
57962
+ return JSON.stringify({ error: "Cloud mesh launch_session requires node daemonId" });
57116
57963
  }
57117
57964
  }
57118
57965
  async function meshGitStatus(ctx, args) {
@@ -57155,9 +58002,36 @@ async function meshCheckpoint(ctx, args) {
57155
58002
  message: args.message,
57156
58003
  includeUntracked: true
57157
58004
  });
58005
+ try {
58006
+ appendLedgerEntry(ctx.mesh.id, {
58007
+ kind: "checkpoint_created",
58008
+ nodeId: args.node_id,
58009
+ payload: { message: args.message, commit: result?.checkpoint?.commit }
58010
+ });
58011
+ } catch {
58012
+ }
57158
58013
  return JSON.stringify(result, null, 2);
58014
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
58015
+ try {
58016
+ const res = await ctx.transport.gitCheckpoint(node.daemonId, {
58017
+ workspace: node.workspace,
58018
+ message: args.message,
58019
+ includeUntracked: true
58020
+ });
58021
+ try {
58022
+ appendLedgerEntry(ctx.mesh.id, {
58023
+ kind: "checkpoint_created",
58024
+ nodeId: args.node_id,
58025
+ payload: { message: args.message, commit: res?.checkpoint?.commit }
58026
+ });
58027
+ } catch {
58028
+ }
58029
+ return JSON.stringify(res, null, 2);
58030
+ } catch (e) {
58031
+ return JSON.stringify({ success: false, error: e.message });
58032
+ }
57159
58033
  } else {
57160
- return JSON.stringify({ error: "Cloud mesh checkpoint not yet implemented" });
58034
+ return JSON.stringify({ error: "Cloud mesh checkpoint requires node daemonId" });
57161
58035
  }
57162
58036
  }
57163
58037
  async function meshApprove(ctx, args) {
@@ -57174,8 +58048,16 @@ async function meshApprove(ctx, args) {
57174
58048
  action: args.action === "reject" ? "reject" : "approve"
57175
58049
  });
57176
58050
  return JSON.stringify(result, null, 2);
58051
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
58052
+ try {
58053
+ const targetId = `${node.daemonId}:session:${args.session_id}`;
58054
+ const res = await ctx.transport.approve(targetId, args.action === "reject" ? "reject" : "approve");
58055
+ return JSON.stringify(res, null, 2);
58056
+ } catch (e) {
58057
+ return JSON.stringify({ success: false, error: e.message });
58058
+ }
57177
58059
  } else {
57178
- return JSON.stringify({ error: "Cloud mesh approve not yet implemented" });
58060
+ return JSON.stringify({ error: "Cloud mesh approve requires node daemonId" });
57179
58061
  }
57180
58062
  }
57181
58063
  async function meshCloneNode(ctx, args) {
@@ -57196,8 +58078,28 @@ async function meshCloneNode(ctx, args) {
57196
58078
  ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
57197
58079
  }
57198
58080
  return JSON.stringify(result, null, 2);
58081
+ } else if (!isLocalTransport(ctx.transport) && sourceNode.daemonId) {
58082
+ try {
58083
+ const res = await ctx.transport.meshCloneNode(sourceNode.daemonId, {
58084
+ meshId: ctx.mesh.id,
58085
+ sourceNodeId: args.source_node_id,
58086
+ branch: args.branch,
58087
+ baseBranch: args.base_branch,
58088
+ inlineMesh: ctx.mesh
58089
+ });
58090
+ const clonePayload = extractCloneNodePayload(res);
58091
+ if (clonePayload?.success && clonePayload.node?.id) {
58092
+ const existingIndex = ctx.mesh.nodes.findIndex((n) => n.id === clonePayload.node.id);
58093
+ if (existingIndex >= 0) ctx.mesh.nodes[existingIndex] = clonePayload.node;
58094
+ else ctx.mesh.nodes.push(clonePayload.node);
58095
+ ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
58096
+ }
58097
+ return JSON.stringify(res, null, 2);
58098
+ } catch (e) {
58099
+ return JSON.stringify({ success: false, error: e.message });
58100
+ }
57199
58101
  } else {
57200
- return JSON.stringify({ error: "Cloud mesh clone_node not yet implemented" });
58102
+ return JSON.stringify({ error: "Cloud mesh clone_node requires source node daemonId" });
57201
58103
  }
57202
58104
  }
57203
58105
  async function meshCleanupSessions(ctx, args) {
@@ -57212,8 +58114,22 @@ async function meshCleanupSessions(ctx, args) {
57212
58114
  inlineMesh: ctx.mesh
57213
58115
  });
57214
58116
  return JSON.stringify(result, null, 2);
58117
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
58118
+ try {
58119
+ const res = await ctx.transport.meshCleanupSessions(node.daemonId, {
58120
+ meshId: ctx.mesh.id,
58121
+ nodeId: args.node_id,
58122
+ mode: args.mode,
58123
+ sessionIds: args.session_ids,
58124
+ dryRun: args.dry_run === true,
58125
+ inlineMesh: ctx.mesh
58126
+ });
58127
+ return JSON.stringify(res, null, 2);
58128
+ } catch (e) {
58129
+ return JSON.stringify({ success: false, error: e.message });
58130
+ }
57215
58131
  } else {
57216
- return JSON.stringify({ error: "Cloud mesh cleanup_sessions not yet implemented" });
58132
+ return JSON.stringify({ error: "Cloud mesh cleanup_sessions requires node daemonId" });
57217
58133
  }
57218
58134
  }
57219
58135
  async function meshRemoveNode(ctx, args) {
@@ -57233,8 +58149,65 @@ async function meshRemoveNode(ctx, args) {
57233
58149
  }
57234
58150
  }
57235
58151
  return JSON.stringify(result, null, 2);
58152
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
58153
+ try {
58154
+ const res = await ctx.transport.meshRemoveNode(node.daemonId, {
58155
+ meshId: ctx.mesh.id,
58156
+ nodeId: args.node_id,
58157
+ ...args.session_cleanup_mode ? { sessionCleanupMode: args.session_cleanup_mode } : {},
58158
+ inlineMesh: ctx.mesh
58159
+ });
58160
+ if (res?.success && res.removed !== false) {
58161
+ const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
58162
+ if (idx >= 0) {
58163
+ ctx.mesh.nodes.splice(idx, 1);
58164
+ ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
58165
+ }
58166
+ }
58167
+ return JSON.stringify(res, null, 2);
58168
+ } catch (e) {
58169
+ return JSON.stringify({ success: false, error: e.message });
58170
+ }
57236
58171
  } else {
57237
- return JSON.stringify({ error: "Cloud mesh remove_node not yet implemented" });
58172
+ return JSON.stringify({ error: "Cloud mesh remove_node requires node daemonId" });
58173
+ }
58174
+ }
58175
+ async function meshRefineNode(ctx, args) {
58176
+ const node = await findNodeWithRefresh(ctx, args.node_id);
58177
+ if (isLocalTransport(ctx.transport)) {
58178
+ const result = await commandForNode(ctx, node, "refine_mesh_node", {
58179
+ meshId: ctx.mesh.id,
58180
+ nodeId: args.node_id,
58181
+ inlineMesh: ctx.mesh
58182
+ });
58183
+ if (result?.success && result.removeResult?.removed !== false) {
58184
+ const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
58185
+ if (idx >= 0) {
58186
+ ctx.mesh.nodes.splice(idx, 1);
58187
+ ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
58188
+ }
58189
+ }
58190
+ return JSON.stringify(result, null, 2);
58191
+ } else if (!isLocalTransport(ctx.transport) && node.daemonId) {
58192
+ try {
58193
+ const res = await ctx.transport.meshRefineNode(node.daemonId, {
58194
+ meshId: ctx.mesh.id,
58195
+ nodeId: args.node_id,
58196
+ inlineMesh: ctx.mesh
58197
+ });
58198
+ if (res?.success && res.removeResult?.removed !== false) {
58199
+ const idx = ctx.mesh.nodes.findIndex((n) => n.id === args.node_id);
58200
+ if (idx >= 0) {
58201
+ ctx.mesh.nodes.splice(idx, 1);
58202
+ ctx.mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
58203
+ }
58204
+ }
58205
+ return JSON.stringify(res, null, 2);
58206
+ } catch (e) {
58207
+ return JSON.stringify({ success: false, error: e.message });
58208
+ }
58209
+ } else {
58210
+ return JSON.stringify({ error: "Cloud mesh refine_node requires node daemonId" });
57238
58211
  }
57239
58212
  }
57240
58213
 
@@ -57348,6 +58321,36 @@ var CloudTransport = class {
57348
58321
  "Authorization": `Bearer ${this.apiKey}`
57349
58322
  };
57350
58323
  }
58324
+ async listRemoteMeshes() {
58325
+ const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes`, { headers: this.headers() });
58326
+ if (!res.ok) throw new Error(`List remote meshes failed: ${res.status}`);
58327
+ return res.json();
58328
+ }
58329
+ async createRemoteMesh(data) {
58330
+ const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes`, {
58331
+ method: "POST",
58332
+ headers: this.headers(),
58333
+ body: JSON.stringify(data)
58334
+ });
58335
+ if (!res.ok) throw new Error(`Create remote mesh failed: ${res.status}`);
58336
+ return res.json();
58337
+ }
58338
+ async deleteRemoteMesh(meshId) {
58339
+ const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes/${encodeURIComponent(meshId)}`, {
58340
+ method: "DELETE",
58341
+ headers: this.headers()
58342
+ });
58343
+ if (!res.ok) throw new Error(`Delete remote mesh failed: ${res.status}`);
58344
+ }
58345
+ async syncMeshLedger(meshId, data) {
58346
+ const res = await fetch(`${this.baseUrl}/api/v1/repo-meshes/${encodeURIComponent(meshId)}/ledger/sync`, {
58347
+ method: "POST",
58348
+ headers: this.headers(),
58349
+ body: JSON.stringify(data)
58350
+ });
58351
+ if (!res.ok) throw new Error(`Sync mesh ledger failed: ${res.status}`);
58352
+ return res.json();
58353
+ }
57351
58354
  async listDaemons() {
57352
58355
  const res = await fetch(`${this.baseUrl}/api/v1/daemons`, { headers: this.headers() });
57353
58356
  if (!res.ok) throw new Error(`List daemons failed: ${res.status}`);
@@ -57505,6 +58508,66 @@ var CloudTransport = class {
57505
58508
  if (!res.ok) throw new Error(`Git checkpoint failed: ${res.status}`);
57506
58509
  return res.json();
57507
58510
  }
58511
+ async meshCloneNode(daemonId, payload) {
58512
+ const res = await fetch(
58513
+ `${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/clone-node`,
58514
+ {
58515
+ method: "POST",
58516
+ headers: this.headers(),
58517
+ body: JSON.stringify(payload)
58518
+ }
58519
+ );
58520
+ if (!res.ok) throw new Error(`Mesh clone node failed: ${res.status}`);
58521
+ return res.json();
58522
+ }
58523
+ async meshRemoveNode(daemonId, payload) {
58524
+ const res = await fetch(
58525
+ `${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/remove-node`,
58526
+ {
58527
+ method: "POST",
58528
+ headers: this.headers(),
58529
+ body: JSON.stringify(payload)
58530
+ }
58531
+ );
58532
+ if (!res.ok) throw new Error(`Mesh remove node failed: ${res.status}`);
58533
+ return res.json();
58534
+ }
58535
+ async meshCleanupSessions(daemonId, payload) {
58536
+ const res = await fetch(
58537
+ `${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/cleanup-sessions`,
58538
+ {
58539
+ method: "POST",
58540
+ headers: this.headers(),
58541
+ body: JSON.stringify(payload)
58542
+ }
58543
+ );
58544
+ if (!res.ok) throw new Error(`Mesh cleanup sessions failed: ${res.status}`);
58545
+ return res.json();
58546
+ }
58547
+ async meshEnqueueTask(daemonId, payload) {
58548
+ const res = await fetch(
58549
+ `${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/enqueue`,
58550
+ {
58551
+ method: "POST",
58552
+ headers: this.headers(),
58553
+ body: JSON.stringify(payload)
58554
+ }
58555
+ );
58556
+ if (!res.ok) throw new Error(`Mesh enqueue task failed: ${res.status}`);
58557
+ return res.json();
58558
+ }
58559
+ async meshRefineNode(daemonId, payload) {
58560
+ const res = await fetch(
58561
+ `${this.baseUrl}/api/v1/shortcuts/${encodeURIComponent(daemonId)}/mesh/refine-node`,
58562
+ {
58563
+ method: "POST",
58564
+ headers: this.headers(),
58565
+ body: JSON.stringify(payload)
58566
+ }
58567
+ );
58568
+ if (!res.ok) throw new Error(`Mesh refine node failed: ${res.status}`);
58569
+ return res.json();
58570
+ }
57508
58571
  async ping() {
57509
58572
  try {
57510
58573
  await this.listDaemons();
@@ -58372,7 +59435,7 @@ var GIT_CHECKPOINT_TOOL = {
58372
59435
  required: ["workspace", "message"]
58373
59436
  }
58374
59437
  };
58375
- async function gitCheckpoint(transport, args) {
59438
+ async function gitCheckpoint2(transport, args) {
58376
59439
  const message = args.message?.trim();
58377
59440
  if (!message) return "Error: message is required";
58378
59441
  if (message.length > 200) return "Error: message must be 200 characters or fewer";
@@ -58432,7 +59495,7 @@ var GIT_PUSH_TOOL = {
58432
59495
  required: ["workspace"]
58433
59496
  }
58434
59497
  };
58435
- async function gitPush(transport, args) {
59498
+ async function gitPush2(transport, args) {
58436
59499
  let raw;
58437
59500
  if (isLocalTransport(transport)) {
58438
59501
  raw = await transport.command("git_push", {
@@ -58823,6 +59886,12 @@ async function startMcpServer(opts) {
58823
59886
  case "mesh_list_nodes":
58824
59887
  text = await meshListNodes(meshCtx);
58825
59888
  break;
59889
+ case "mesh_enqueue_task":
59890
+ text = await meshEnqueueTask(meshCtx, a);
59891
+ break;
59892
+ case "mesh_view_queue":
59893
+ text = await meshViewQueue(meshCtx, a);
59894
+ break;
58826
59895
  case "mesh_send_task":
58827
59896
  text = await meshSendTask(meshCtx, a);
58828
59897
  break;
@@ -58850,9 +59919,15 @@ async function startMcpServer(opts) {
58850
59919
  case "mesh_remove_node":
58851
59920
  text = await meshRemoveNode(meshCtx, a);
58852
59921
  break;
59922
+ case "mesh_refine_node":
59923
+ text = await meshRefineNode(meshCtx, a);
59924
+ break;
58853
59925
  case "mesh_cleanup_sessions":
58854
59926
  text = await meshCleanupSessions(meshCtx, a);
58855
59927
  break;
59928
+ case "mesh_task_history":
59929
+ text = await meshTaskHistory(meshCtx, a);
59930
+ break;
58856
59931
  default:
58857
59932
  return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
58858
59933
  }
@@ -58941,11 +60016,11 @@ async function startMcpServer(opts) {
58941
60016
  return { content: [{ type: "text", text }] };
58942
60017
  }
58943
60018
  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 });
60019
+ const text = await gitCheckpoint2(transport, { workspace: a.workspace, message: a.message, include_untracked: a.include_untracked, daemon_id: a.daemon_id });
58945
60020
  return { content: [{ type: "text", text }] };
58946
60021
  }
58947
60022
  case "git_push": {
58948
- const text = await gitPush(transport, { workspace: a.workspace, remote: a.remote, branch: a.branch, daemon_id: a.daemon_id });
60023
+ const text = await gitPush2(transport, { workspace: a.workspace, remote: a.remote, branch: a.branch, daemon_id: a.daemon_id });
58949
60024
  return { content: [{ type: "text", text }] };
58950
60025
  }
58951
60026
  case "launch_session": {