@adhdev/daemon-standalone 0.9.77-rc.32 → 0.9.77-rc.34

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.32",
3
+ "version": "0.9.77-rc.34",
4
4
  "description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -25120,6 +25120,7 @@ __export(dist_exports, {
25120
25120
  buildThoughtChatMessage: () => buildThoughtChatMessage,
25121
25121
  buildToolChatMessage: () => buildToolChatMessage,
25122
25122
  buildUserChatMessage: () => buildUserChatMessage,
25123
+ cancelTask: () => cancelTask,
25123
25124
  claimNextTask: () => claimNextTask,
25124
25125
  classifyChatMessageVisibility: () => classifyChatMessageVisibility,
25125
25126
  classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush,
@@ -25231,6 +25232,7 @@ __export(dist_exports, {
25231
25232
  registerExtensionProviders: () => registerExtensionProviders,
25232
25233
  removeNode: () => removeNode,
25233
25234
  removeWorktree: () => removeWorktree,
25235
+ requeueTask: () => requeueTask,
25234
25236
  resetConfig: () => resetConfig,
25235
25237
  resetDebugRuntimeConfig: () => resetDebugRuntimeConfig,
25236
25238
  resetState: () => resetState,
@@ -26074,6 +26076,40 @@ function updateTaskStatus(meshId, taskId, status) {
26074
26076
  writeQueue(meshId, queue);
26075
26077
  return queue[idx];
26076
26078
  }
26079
+ function cancelTask(meshId, taskId, opts) {
26080
+ const queue = readQueue(meshId);
26081
+ const idx = queue.findIndex((q) => q.id === taskId);
26082
+ if (idx === -1) return null;
26083
+ const now = (/* @__PURE__ */ new Date()).toISOString();
26084
+ queue[idx].status = "cancelled";
26085
+ queue[idx].updatedAt = now;
26086
+ queue[idx].cancelledAt = now;
26087
+ if (opts?.reason) queue[idx].cancelReason = opts.reason;
26088
+ writeQueue(meshId, queue);
26089
+ return queue[idx];
26090
+ }
26091
+ function requeueTask(meshId, taskId, opts) {
26092
+ const queue = readQueue(meshId);
26093
+ const idx = queue.findIndex((q) => q.id === taskId);
26094
+ if (idx === -1) return null;
26095
+ const entry = queue[idx];
26096
+ const now = (/* @__PURE__ */ new Date()).toISOString();
26097
+ entry.status = "pending";
26098
+ delete entry.assignedNodeId;
26099
+ delete entry.assignedSessionId;
26100
+ delete entry.cancelledAt;
26101
+ delete entry.cancelReason;
26102
+ if (opts?.clearTargetNode) delete entry.targetNodeId;
26103
+ if (typeof opts?.targetNodeId === "string") entry.targetNodeId = opts.targetNodeId;
26104
+ if (opts?.clearTargetSession !== false) delete entry.targetSessionId;
26105
+ if (typeof opts?.targetSessionId === "string") entry.targetSessionId = opts.targetSessionId;
26106
+ entry.updatedAt = now;
26107
+ entry.requeuedAt = now;
26108
+ entry.requeueCount = (entry.requeueCount || 0) + 1;
26109
+ if (opts?.reason) entry.requeueReason = opts.reason;
26110
+ writeQueue(meshId, queue);
26111
+ return entry;
26112
+ }
26077
26113
  function updateSessionTaskStatus(meshId, sessionId, status) {
26078
26114
  const queue = readQueue(meshId);
26079
26115
  for (let i = queue.length - 1; i >= 0; i--) {
@@ -26092,7 +26128,8 @@ function getMeshQueueStats(meshId) {
26092
26128
  pending: queue.filter((q) => q.status === "pending").length,
26093
26129
  assigned: queue.filter((q) => q.status === "assigned").length,
26094
26130
  completed: queue.filter((q) => q.status === "completed").length,
26095
- failed: queue.filter((q) => q.status === "failed").length
26131
+ failed: queue.filter((q) => q.status === "failed").length,
26132
+ cancelled: queue.filter((q) => q.status === "cancelled").length
26096
26133
  };
26097
26134
  }
26098
26135
  function setLogLevel(level) {
@@ -26312,10 +26349,12 @@ function triggerMeshQueue(components, meshId) {
26312
26349
  const state = inst.getState();
26313
26350
  const settings = state.settings || {};
26314
26351
  const instMeshId = readNonEmptyString(settings.meshNodeFor);
26315
- if (instMeshId !== meshId && !settings.launchedByCoordinator) continue;
26352
+ if (instMeshId !== meshId) continue;
26316
26353
  const nodeId = readNonEmptyString(settings.meshNodeId) || readNonEmptyString(settings.nodeId);
26317
26354
  if (!nodeId) continue;
26318
- if (state.status !== "idle" && state.status !== "stopped" && state.activeChat?.status !== "waiting_input") continue;
26355
+ const status = readNonEmptyString(state.status).toLowerCase();
26356
+ if (["stopped", "failed", "terminated", "exited", "closed"].includes(status)) continue;
26357
+ if (status !== "idle" && state.activeChat?.status !== "waiting_input") continue;
26319
26358
  const sessionId = state.instanceId;
26320
26359
  const providerType = state.type || readNonEmptyString(settings.providerType);
26321
26360
  if (providerType) {
@@ -41348,10 +41387,12 @@ Follow these recovery rules:
41348
41387
  });
41349
41388
  mesh_work_queue_exports = {};
41350
41389
  __export2(mesh_work_queue_exports, {
41390
+ cancelTask: () => cancelTask,
41351
41391
  claimNextTask: () => claimNextTask,
41352
41392
  enqueueTask: () => enqueueTask,
41353
41393
  getMeshQueueStats: () => getMeshQueueStats,
41354
41394
  getQueue: () => getQueue,
41395
+ requeueTask: () => requeueTask,
41355
41396
  updateSessionTaskStatus: () => updateSessionTaskStatus,
41356
41397
  updateTaskStatus: () => updateTaskStatus
41357
41398
  });
@@ -53144,6 +53185,39 @@ Run 'adhdev doctor' for detailed diagnostics.`
53144
53185
  return { success: false, error: e.message };
53145
53186
  }
53146
53187
  }
53188
+ case "cancel_mesh_queue_task": {
53189
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53190
+ const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
53191
+ if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
53192
+ try {
53193
+ const { cancelTask: cancelTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
53194
+ const reason = typeof args?.reason === "string" ? args.reason : void 0;
53195
+ const task = cancelTask2(meshId, taskId, { reason });
53196
+ if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
53197
+ return { success: true, task };
53198
+ } catch (e) {
53199
+ return { success: false, error: e.message };
53200
+ }
53201
+ }
53202
+ case "requeue_mesh_queue_task": {
53203
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53204
+ const taskId = typeof args?.taskId === "string" ? args.taskId.trim() : "";
53205
+ if (!meshId || !taskId) return { success: false, error: "meshId and taskId required" };
53206
+ try {
53207
+ const { requeueTask: requeueTask2 } = await Promise.resolve().then(() => (init_mesh_work_queue(), mesh_work_queue_exports));
53208
+ const task = requeueTask2(meshId, taskId, {
53209
+ reason: typeof args?.reason === "string" ? args.reason : void 0,
53210
+ targetNodeId: typeof args?.targetNodeId === "string" ? args.targetNodeId.trim() : void 0,
53211
+ targetSessionId: typeof args?.targetSessionId === "string" ? args.targetSessionId.trim() : void 0,
53212
+ clearTargetNode: args?.clearTargetNode === true,
53213
+ clearTargetSession: args?.clearTargetSession !== false
53214
+ });
53215
+ if (!task) return { success: false, error: `Queue task '${taskId}' not found` };
53216
+ return { success: true, task };
53217
+ } catch (e) {
53218
+ return { success: false, error: e.message };
53219
+ }
53220
+ }
53147
53221
  case "add_mesh_node": {
53148
53222
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53149
53223
  const workspace = typeof args?.workspace === "string" ? args.workspace.trim() : "";
@@ -57489,6 +57563,26 @@ function unwrapCommandPayload(value) {
57489
57563
  }
57490
57564
  return current;
57491
57565
  }
57566
+ function isTerminalSessionRecord(session) {
57567
+ const status = typeof session?.status === "string" ? session.status.toLowerCase() : "";
57568
+ const lifecycle = typeof session?.lifecycle === "string" ? session.lifecycle.toLowerCase() : "";
57569
+ const state = typeof session?.state === "string" ? session.state.toLowerCase() : "";
57570
+ return [status, lifecycle, state].some((value) => ["stopped", "failed", "terminated", "exited", "closed"].includes(value));
57571
+ }
57572
+ function isIdleSessionRecord(session) {
57573
+ if (isTerminalSessionRecord(session)) return false;
57574
+ const status = typeof session?.status === "string" ? session.status.toLowerCase() : "";
57575
+ const chatStatus = typeof session?.activeChat?.status === "string" ? session.activeChat.status.toLowerCase() : "";
57576
+ return status === "idle" || chatStatus === "waiting_input";
57577
+ }
57578
+ function chooseDispatchableSession(sessions, providerType, meshId, nodeId) {
57579
+ const live = sessions.filter((session) => !isTerminalSessionRecord(session));
57580
+ const matchingProvider = (session) => !providerType || session?.providerType === providerType || session?.cliType === providerType;
57581
+ const meshSessions = live.filter(
57582
+ (session) => session?.settings?.meshNodeFor === meshId || session?.settings?.meshNodeId === nodeId
57583
+ );
57584
+ return meshSessions.find((session) => isIdleSessionRecord(session) && matchingProvider(session)) || meshSessions.find(matchingProvider) || live.find((session) => isIdleSessionRecord(session) && matchingProvider(session)) || live.find(matchingProvider) || live.find(isIdleSessionRecord) || live[0];
57585
+ }
57492
57586
  function findNestedPayload(value, predicate) {
57493
57587
  const seen = /* @__PURE__ */ new Set();
57494
57588
  const stack = [{ payload: value, depth: 0 }];
@@ -57529,18 +57623,12 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
57529
57623
  const innerResult = relayResult?.result ?? relayResult;
57530
57624
  const statusObj = innerResult?.status ?? innerResult;
57531
57625
  const sessions = Array.isArray(statusObj?.sessions) ? statusObj.sessions : [];
57532
- const meshSessions = sessions.filter(
57533
- (s) => s?.settings?.meshNodeFor === ctx.mesh.id || s?.settings?.meshNodeId === node.id || s?.settings?.launchedByCoordinator === true
57534
- );
57535
- const targetSession = meshSessions[0] || sessions.find(
57536
- (s) => !resolvedProviderType || s?.providerType === resolvedProviderType || s?.cliType === resolvedProviderType
57537
- ) || sessions[0];
57626
+ const targetSession = chooseDispatchableSession(sessions, resolvedProviderType, ctx.mesh.id, node.id);
57538
57627
  if (targetSession?.id || targetSession?.sessionId) {
57539
57628
  sessionId = targetSession.id || targetSession.sessionId;
57540
57629
  if (!resolvedProviderType) {
57541
57630
  resolvedProviderType = targetSession.providerType || targetSession.cliType || "";
57542
57631
  }
57543
- } else {
57544
57632
  }
57545
57633
  } catch (e) {
57546
57634
  }
@@ -57549,13 +57637,17 @@ async function ipcDispatchToRemoteAgent(ctx, node, args) {
57549
57637
  return { success: false, error: `Cannot dispatch to remote node '${node.id}': providerType unknown. Set providerPriority on the node policy or call mesh_launch_session first.` };
57550
57638
  }
57551
57639
  try {
57552
- await transport.meshCommand(daemonId, "agent_command", {
57640
+ const dispatchResult = await transport.meshCommand(daemonId, "agent_command", {
57553
57641
  ...sessionId ? { targetSessionId: sessionId } : {},
57554
57642
  agentType: resolvedProviderType,
57555
57643
  cliType: resolvedProviderType,
57556
57644
  action: "send_chat",
57557
57645
  message: args.message
57558
57646
  });
57647
+ const dispatchPayload = unwrapCommandPayload(dispatchResult);
57648
+ if (dispatchPayload?.success === false || dispatchResult?.success === false) {
57649
+ return { success: false, error: `P2P dispatch failed: ${dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task"}` };
57650
+ }
57559
57651
  return { success: true, dispatched: true, sessionId: sessionId || resolvedProviderType };
57560
57652
  } catch (e) {
57561
57653
  return { success: false, error: `P2P dispatch failed: ${e?.message || String(e)}` };
@@ -57702,18 +57794,46 @@ var MESH_ENQUEUE_TASK_TOOL = {
57702
57794
  };
57703
57795
  var MESH_VIEW_QUEUE_TOOL = {
57704
57796
  name: "mesh_view_queue",
57705
- description: "View the current status of the mesh work queue (pending, assigned, completed, failed tasks).",
57797
+ description: "View the current status of the mesh work queue (pending, assigned, completed, failed, cancelled tasks).",
57706
57798
  inputSchema: {
57707
57799
  type: "object",
57708
57800
  properties: {
57709
57801
  status: {
57710
57802
  type: "array",
57711
57803
  items: { type: "string" },
57712
- description: "Filter by task status: pending, assigned, completed, failed. Returns all if omitted."
57804
+ description: "Filter by task status: pending, assigned, completed, failed, cancelled. Returns all if omitted."
57713
57805
  }
57714
57806
  }
57715
57807
  }
57716
57808
  };
57809
+ var MESH_QUEUE_CANCEL_TOOL = {
57810
+ name: "mesh_queue_cancel",
57811
+ description: "Cancel a pending/assigned/completed/failed mesh queue task without deleting audit history. Use this to retire stale queue items that target dead sessions.",
57812
+ inputSchema: {
57813
+ type: "object",
57814
+ properties: {
57815
+ task_id: { type: "string", description: "Queue task ID to cancel." },
57816
+ reason: { type: "string", description: "Optional operator-visible reason for cancellation." }
57817
+ },
57818
+ required: ["task_id"]
57819
+ }
57820
+ };
57821
+ var MESH_QUEUE_REQUEUE_TOOL = {
57822
+ name: "mesh_queue_requeue",
57823
+ description: "Return a mesh queue task to pending for retry. By default clears stale assigned owner and target session so another live session can claim it.",
57824
+ inputSchema: {
57825
+ type: "object",
57826
+ properties: {
57827
+ task_id: { type: "string", description: "Queue task ID to requeue." },
57828
+ reason: { type: "string", description: "Optional operator-visible reason for requeueing." },
57829
+ target_node_id: { type: "string", description: "Optional replacement target node ID." },
57830
+ target_session_id: { type: "string", description: "Optional replacement target runtime session ID." },
57831
+ clear_target_node: { type: "boolean", description: "When true, remove any existing target node constraint." },
57832
+ keep_target_session: { type: "boolean", description: "When true, preserve an existing target session if target_session_id is not provided. Defaults false to avoid stale session targets." }
57833
+ },
57834
+ required: ["task_id"]
57835
+ }
57836
+ };
57717
57837
  var MESH_SEND_TASK_TOOL = {
57718
57838
  name: "mesh_send_task",
57719
57839
  description: "Legacy push-based task assignment. Enqueues a task specifically targeted at a given node. The node will pull it immediately if idle.",
@@ -57883,6 +58003,8 @@ var ALL_MESH_TOOLS = [
57883
58003
  MESH_LIST_NODES_TOOL,
57884
58004
  MESH_ENQUEUE_TASK_TOOL,
57885
58005
  MESH_VIEW_QUEUE_TOOL,
58006
+ MESH_QUEUE_CANCEL_TOOL,
58007
+ MESH_QUEUE_REQUEUE_TOOL,
57886
58008
  MESH_SEND_TASK_TOOL,
57887
58009
  MESH_READ_CHAT_TOOL,
57888
58010
  MESH_READ_DEBUG_TOOL,
@@ -58064,6 +58186,41 @@ async function meshViewQueue(ctx, args) {
58064
58186
  return JSON.stringify({ success: false, error: e.message });
58065
58187
  }
58066
58188
  }
58189
+ async function meshQueueCancel(ctx, args) {
58190
+ try {
58191
+ const taskId = (args.task_id || args.taskId || "").trim();
58192
+ if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
58193
+ const task = cancelTask(ctx.mesh.id, taskId, { reason: args.reason });
58194
+ if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
58195
+ return JSON.stringify({ success: true, task }, null, 2);
58196
+ } catch (e) {
58197
+ return JSON.stringify({ success: false, error: e.message });
58198
+ }
58199
+ }
58200
+ async function meshQueueRequeue(ctx, args) {
58201
+ try {
58202
+ const taskId = (args.task_id || args.taskId || "").trim();
58203
+ if (!taskId) return JSON.stringify({ success: false, error: "task_id required" });
58204
+ const targetNodeId = (args.target_node_id || args.targetNodeId || "").trim() || void 0;
58205
+ const targetSessionId = (args.target_session_id || args.targetSessionId || "").trim() || void 0;
58206
+ const keepTargetSession = args.keep_target_session === true || args.keepTargetSession === true;
58207
+ const task = requeueTask(ctx.mesh.id, taskId, {
58208
+ reason: args.reason,
58209
+ targetNodeId,
58210
+ targetSessionId,
58211
+ clearTargetNode: args.clear_target_node === true || args.clearTargetNode === true,
58212
+ clearTargetSession: targetSessionId ? false : !keepTargetSession
58213
+ });
58214
+ if (!task) return JSON.stringify({ success: false, error: `Queue task '${taskId}' not found` });
58215
+ if (isLocalTransport(ctx.transport)) {
58216
+ ctx.transport.command("trigger_mesh_queue", { meshId: ctx.mesh.id }).catch(() => {
58217
+ });
58218
+ }
58219
+ return JSON.stringify({ success: true, task }, null, 2);
58220
+ } catch (e) {
58221
+ return JSON.stringify({ success: false, error: e.message });
58222
+ }
58223
+ }
58067
58224
  async function meshSendTask(ctx, args) {
58068
58225
  const node = await findNodeWithRefresh(ctx, args.node_id);
58069
58226
  if (node.policy?.readOnly) {
@@ -58099,6 +58256,35 @@ async function meshSendTask(ctx, args) {
58099
58256
  }
58100
58257
  return JSON.stringify({ ...result, nodeId: args.node_id });
58101
58258
  }
58259
+ if (args.session_id && isLocalTransport(ctx.transport)) {
58260
+ const cached2 = meshSessionProviderMetadata.get(meshSessionCacheKey(args.node_id, args.session_id));
58261
+ const dispatchResult = await commandForNode(ctx, node, "agent_command", {
58262
+ targetSessionId: args.session_id,
58263
+ ...cached2?.providerType ? { agentType: cached2.providerType, cliType: cached2.providerType, providerType: cached2.providerType } : {},
58264
+ action: "send_chat",
58265
+ message: args.message
58266
+ });
58267
+ const dispatchPayload = unwrapCommandPayload(dispatchResult);
58268
+ if (dispatchPayload?.success === false || dispatchResult?.success === false) {
58269
+ return JSON.stringify({
58270
+ success: false,
58271
+ nodeId: args.node_id,
58272
+ sessionId: args.session_id,
58273
+ error: dispatchPayload?.error || dispatchResult?.error || "agent_command rejected the task"
58274
+ });
58275
+ }
58276
+ try {
58277
+ appendLedgerEntry(ctx.mesh.id, {
58278
+ kind: "task_dispatched",
58279
+ nodeId: args.node_id,
58280
+ sessionId: args.session_id,
58281
+ providerType: cached2?.providerType,
58282
+ payload: { message: args.message, via: "local_direct" }
58283
+ });
58284
+ } catch {
58285
+ }
58286
+ return JSON.stringify({ success: true, dispatched: true, nodeId: args.node_id, sessionId: args.session_id });
58287
+ }
58102
58288
  const task = enqueueTask(ctx.mesh.id, args.message, {
58103
58289
  targetNodeId: args.node_id,
58104
58290
  targetSessionId: args.session_id
@@ -60243,6 +60429,12 @@ async function startMcpServer(opts) {
60243
60429
  case "mesh_view_queue":
60244
60430
  text = await meshViewQueue(meshCtx, a);
60245
60431
  break;
60432
+ case "mesh_queue_cancel":
60433
+ text = await meshQueueCancel(meshCtx, a);
60434
+ break;
60435
+ case "mesh_queue_requeue":
60436
+ text = await meshQueueRequeue(meshCtx, a);
60437
+ break;
60246
60438
  case "mesh_send_task":
60247
60439
  text = await meshSendTask(meshCtx, a);
60248
60440
  break;