@adhdev/daemon-standalone 0.9.77-rc.30 → 0.9.77-rc.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-standalone",
3
- "version": "0.9.77-rc.30",
3
+ "version": "0.9.77-rc.31",
4
4
  "description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -26029,6 +26029,7 @@ function enqueueTask(meshId, message, opts) {
26029
26029
  message,
26030
26030
  status: "pending",
26031
26031
  targetNodeId: opts?.targetNodeId,
26032
+ targetSessionId: opts?.targetSessionId,
26032
26033
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
26033
26034
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
26034
26035
  };
@@ -26046,9 +26047,12 @@ function getQueue(meshId, opts) {
26046
26047
  }
26047
26048
  function claimNextTask(meshId, nodeId, sessionId) {
26048
26049
  const queue = readQueue(meshId);
26049
- let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId);
26050
+ let targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetSessionId === sessionId);
26050
26051
  if (targetIdx === -1) {
26051
- targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId);
26052
+ targetIdx = queue.findIndex((q) => q.status === "pending" && q.targetNodeId === nodeId && !q.targetSessionId);
26053
+ }
26054
+ if (targetIdx === -1) {
26055
+ targetIdx = queue.findIndex((q) => q.status === "pending" && !q.targetNodeId && !q.targetSessionId);
26052
26056
  }
26053
26057
  if (targetIdx === -1) return null;
26054
26058
  const entry = queue[targetIdx];
@@ -57620,7 +57624,7 @@ async function commandForNode(ctx, node, command, args = {}) {
57620
57624
  }
57621
57625
  var MESH_STATUS_TOOL = {
57622
57626
  name: "mesh_status",
57623
- description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions. Use this to decide which node to send work to.",
57627
+ description: "Get the current status of all nodes in the repo mesh \u2014 health, git state, active sessions, recovery hints, and recommended next steps. Use this to decide which node to send work to or how to recover from failures.",
57624
57628
  inputSchema: {
57625
57629
  type: "object",
57626
57630
  properties: {
@@ -57849,6 +57853,7 @@ async function meshStatus(ctx) {
57849
57853
  await refreshMeshFromDaemon(ctx);
57850
57854
  const { mesh, transport } = ctx;
57851
57855
  const results = [];
57856
+ const ledgerSummary = getLedgerSummary(mesh.id);
57852
57857
  for (const node of mesh.nodes) {
57853
57858
  const entry = {
57854
57859
  nodeId: node.id,
@@ -57882,6 +57887,33 @@ async function meshStatus(ctx) {
57882
57887
  entry.health = "degraded";
57883
57888
  entry.error = e.message;
57884
57889
  }
57890
+ const recoveryContext = getSessionRecoveryContext(mesh.id, { nodeId: node.id });
57891
+ if (recoveryContext.consecutiveNodeFailures > 0) {
57892
+ entry.recoveryHints = {
57893
+ consecutiveFailures: recoveryContext.consecutiveNodeFailures,
57894
+ lastTaskMessage: recoveryContext.lastTaskMessage,
57895
+ advice: recoveryContext.advice,
57896
+ retryRecommended: recoveryContext.retryRecommended
57897
+ };
57898
+ }
57899
+ const nextStepHints = [];
57900
+ if (entry.health === "online" && node.isLocalWorktree) {
57901
+ nextStepHints.push(`Merge worktree to base via mesh_refine_node(node_id: "${node.id}")`);
57902
+ } else if (entry.health === "dirty") {
57903
+ nextStepHints.push(`Commit changes via mesh_checkpoint(node_id: "${node.id}", message: "...")`);
57904
+ } else if (entry.health === "degraded" && entry.error?.includes("git")) {
57905
+ nextStepHints.push("Initialize git repository or check workspace path.");
57906
+ }
57907
+ if (recoveryContext.consecutiveNodeFailures > 0) {
57908
+ if (recoveryContext.retryRecommended) {
57909
+ nextStepHints.push(`Retry task on this node or launch a fresh session.`);
57910
+ } else {
57911
+ nextStepHints.push(`Consider reassigning work to a different node.`);
57912
+ }
57913
+ }
57914
+ if (nextStepHints.length > 0) {
57915
+ entry.nextStepHints = nextStepHints;
57916
+ }
57885
57917
  const relatedRepos = await collectRelatedRepoStatuses(ctx, node);
57886
57918
  if (relatedRepos.length) entry.relatedRepos = relatedRepos;
57887
57919
  results.push(entry);
@@ -57895,7 +57927,7 @@ async function meshStatus(ctx) {
57895
57927
  nodes: results
57896
57928
  };
57897
57929
  try {
57898
- response.ledgerSummary = getLedgerSummary(mesh.id);
57930
+ response.ledgerSummary = ledgerSummary;
57899
57931
  } catch {
57900
57932
  }
57901
57933
  if (ctx.transport instanceof IpcTransport) {
@@ -58020,8 +58052,11 @@ async function meshSendTask(ctx, args) {
58020
58052
  }
58021
58053
  return JSON.stringify({ ...result, nodeId: args.node_id });
58022
58054
  }
58023
- const task = enqueueTask(ctx.mesh.id, args.message, { targetNodeId: args.node_id });
58024
- if (isLocalTransport(ctx.transport)) {
58055
+ const task = enqueueTask(ctx.mesh.id, args.message, {
58056
+ targetNodeId: args.node_id,
58057
+ targetSessionId: args.session_id
58058
+ });
58059
+ if (isLocalTransport(ctx.transport) || ctx.transport instanceof IpcTransport) {
58025
58060
  ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
58026
58061
  });
58027
58062
  }