@adhdev/daemon-standalone 0.9.77-rc.45 → 0.9.77-rc.46

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.45",
3
+ "version": "0.9.77-rc.46",
4
4
  "description": "ADHDev standalone daemon — embedded HTTP/WS server for local dashboard",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -25503,7 +25503,8 @@ function ensureMachineId(config2) {
25503
25503
  };
25504
25504
  }
25505
25505
  function getConfigDir() {
25506
- const dir = (0, import_path.join)((0, import_os2.homedir)(), ".adhdev");
25506
+ const override = process.env.ADHDEV_CONFIG_DIR;
25507
+ const dir = override && override.trim() ? override.trim() : (0, import_path.join)((0, import_os2.homedir)(), ".adhdev");
25507
25508
  if (!(0, import_fs4.existsSync)(dir)) {
25508
25509
  (0, import_fs4.mkdirSync)(dir, { recursive: true });
25509
25510
  }
@@ -26183,12 +26184,20 @@ function updateSessionTaskStatus(meshId, sessionId, status) {
26183
26184
  }
26184
26185
  function getMeshQueueStats(meshId) {
26185
26186
  const queue = readQueue(meshId);
26187
+ const pending = queue.filter((q) => q.status === "pending").length;
26188
+ const assigned = queue.filter((q) => q.status === "assigned").length;
26189
+ const completed = queue.filter((q) => q.status === "completed").length;
26190
+ const failed = queue.filter((q) => q.status === "failed").length;
26191
+ const cancelled = queue.filter((q) => q.status === "cancelled").length;
26186
26192
  return {
26187
- pending: queue.filter((q) => q.status === "pending").length,
26188
- assigned: queue.filter((q) => q.status === "assigned").length,
26189
- completed: queue.filter((q) => q.status === "completed").length,
26190
- failed: queue.filter((q) => q.status === "failed").length,
26191
- cancelled: queue.filter((q) => q.status === "cancelled").length,
26193
+ total: queue.length,
26194
+ active: pending + assigned,
26195
+ historical: completed + failed + cancelled,
26196
+ pending,
26197
+ assigned,
26198
+ completed,
26199
+ failed,
26200
+ cancelled,
26192
26201
  activeAssignments: queue.filter((q) => q.status === "assigned").map((q) => ({
26193
26202
  id: q.id,
26194
26203
  nodeId: q.assignedNodeId,
@@ -28796,7 +28805,7 @@ function addWorkspaceEntry(config2, rawPath, label, options) {
28796
28805
  }
28797
28806
  }
28798
28807
  const v = validateWorkspacePath(abs);
28799
- if (!v.ok) return { error: v.error };
28808
+ if (v.ok !== true) return { error: v.error };
28800
28809
  const list = [...config2.workspaces || []];
28801
28810
  if (list.some((w) => path5.resolve(w.path) === abs)) {
28802
28811
  return { error: "Workspace already in list" };
@@ -58570,6 +58579,8 @@ function readString(value) {
58570
58579
  }
58571
58580
  var DUPLICATE_DISPATCH_WINDOW_MS = 6e4;
58572
58581
  var STALE_ASSIGNED_QUEUE_MS = 30 * 6e4;
58582
+ var ACTIVE_QUEUE_STATUSES = /* @__PURE__ */ new Set(["pending", "assigned"]);
58583
+ var HISTORICAL_QUEUE_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
58573
58584
  async function refreshMeshFromDaemon(ctx) {
58574
58585
  if (!(ctx.transport instanceof IpcTransport)) return;
58575
58586
  try {
@@ -58695,30 +58706,126 @@ function buildMissingNodeReadChatRecovery(ctx, args) {
58695
58706
  ]
58696
58707
  };
58697
58708
  }
58698
- function annotateQueueStaleness(queue) {
58709
+ function readSessionRecordId(session) {
58710
+ return readString(session?.id) || readString(session?.sessionId) || readString(session?.session_id) || readString(session?.runtimeSessionId) || readString(session?.runtime_session_id) || readString(session?.instanceId) || readString(session?.instance_id);
58711
+ }
58712
+ function addSessionRecord(target, session) {
58713
+ if (!session || typeof session !== "object" || isTerminalSessionRecord(session)) return;
58714
+ const sessionId = readSessionRecordId(session);
58715
+ if (sessionId) target.add(sessionId);
58716
+ }
58717
+ function collectNodeSessionIds(node) {
58718
+ const sessions = /* @__PURE__ */ new Set();
58719
+ const sessionArrays = [
58720
+ node?.sessions,
58721
+ node?.activeSessions,
58722
+ node?.active_sessions,
58723
+ node?.lastProbe?.sessions,
58724
+ node?.last_probe?.sessions,
58725
+ node?.lastProbe?.status?.sessions,
58726
+ node?.last_probe?.status?.sessions
58727
+ ];
58728
+ for (const value of sessionArrays) {
58729
+ if (Array.isArray(value)) value.forEach((session) => addSessionRecord(sessions, session));
58730
+ }
58731
+ const sessionRecords = [
58732
+ node?.activeSession,
58733
+ node?.active_session,
58734
+ node?.currentSession,
58735
+ node?.current_session,
58736
+ node?.runtimeSession,
58737
+ node?.runtime_session,
58738
+ node?.session,
58739
+ node?.lastProbe?.activeSession,
58740
+ node?.last_probe?.active_session,
58741
+ node?.lastProbe?.currentSession,
58742
+ node?.last_probe?.current_session,
58743
+ node?.lastProbe?.session,
58744
+ node?.last_probe?.session
58745
+ ];
58746
+ sessionRecords.forEach((session) => addSessionRecord(sessions, session));
58747
+ return sessions;
58748
+ }
58749
+ function buildQueueLivenessIndex(mesh) {
58750
+ const nodeIds = /* @__PURE__ */ new Set();
58751
+ const nodeSessionIds = /* @__PURE__ */ new Map();
58752
+ for (const node of Array.isArray(mesh?.nodes) ? mesh.nodes : []) {
58753
+ const nodeId = readString(node.id) || readString(node.nodeId) || readString(node.node_id);
58754
+ if (!nodeId) continue;
58755
+ nodeIds.add(nodeId);
58756
+ const sessions = collectNodeSessionIds(node);
58757
+ if (sessions.size > 0) nodeSessionIds.set(nodeId, sessions);
58758
+ }
58759
+ return { nodeIds, nodeSessionIds };
58760
+ }
58761
+ function queueAssignmentStaleReason(task, liveness) {
58762
+ if (task?.status !== "assigned") return void 0;
58763
+ const nodeId = readString(task.assignedNodeId) || readString(task.nodeId) || readString(task.node_id) || readString(task.targetNodeId);
58764
+ const sessionId = readString(task.assignedSessionId) || readString(task.sessionId) || readString(task.session_id) || readString(task.targetSessionId);
58765
+ if (nodeId && liveness.nodeIds.size > 0 && !liveness.nodeIds.has(nodeId)) {
58766
+ return "assigned node is not present in the current mesh snapshot";
58767
+ }
58768
+ if (nodeId && sessionId && liveness.nodeSessionIds.has(nodeId) && !liveness.nodeSessionIds.get(nodeId).has(sessionId)) {
58769
+ return "assigned session is not live on the assigned node";
58770
+ }
58771
+ const updatedAt = new Date(task.updatedAt).getTime();
58772
+ const ageMs = Number.isFinite(updatedAt) ? Date.now() - updatedAt : null;
58773
+ if (!nodeId && ageMs !== null && ageMs >= STALE_ASSIGNED_QUEUE_MS) {
58774
+ return "assigned task has no assigned node metadata";
58775
+ }
58776
+ return void 0;
58777
+ }
58778
+ function buildQueueStatusSummary(queue) {
58779
+ const counts = { pending: 0, assigned: 0, completed: 0, failed: 0, cancelled: 0 };
58780
+ for (const task of queue) {
58781
+ const status = typeof task?.status === "string" ? task.status : void 0;
58782
+ if (status && Object.prototype.hasOwnProperty.call(counts, status)) {
58783
+ counts[status] += 1;
58784
+ }
58785
+ }
58786
+ return {
58787
+ totalCount: queue.length,
58788
+ activeCount: counts.pending + counts.assigned,
58789
+ historicalCount: counts.completed + counts.failed + counts.cancelled,
58790
+ counts,
58791
+ activeCounts: {
58792
+ pending: counts.pending,
58793
+ assigned: counts.assigned
58794
+ },
58795
+ historicalCounts: {
58796
+ completed: counts.completed,
58797
+ failed: counts.failed,
58798
+ cancelled: counts.cancelled
58799
+ }
58800
+ };
58801
+ }
58802
+ function annotateQueueStaleness(queue, mesh) {
58803
+ const liveness = buildQueueLivenessIndex(mesh);
58699
58804
  const now = Date.now();
58700
58805
  return queue.map((task) => {
58701
58806
  const taskStatus = typeof task?.status === "string" ? task.status : void 0;
58702
58807
  const annotated = {
58703
58808
  ...task,
58704
58809
  taskStatus,
58810
+ isActive: taskStatus ? ACTIVE_QUEUE_STATUSES.has(taskStatus) : false,
58811
+ isHistorical: taskStatus ? HISTORICAL_QUEUE_STATUSES.has(taskStatus) : false,
58705
58812
  dispatchedAt: task?.createdAt,
58706
58813
  ...taskStatus === "assigned" ? { activeTaskId: task.id } : {},
58707
58814
  ...taskStatus === "completed" || taskStatus === "failed" ? {
58708
- isHistorical: true,
58709
58815
  completedAt: task.updatedAt
58710
58816
  } : {}
58711
58817
  };
58712
58818
  if (taskStatus !== "assigned") return annotated;
58713
58819
  const updatedAt = new Date(task.updatedAt).getTime();
58714
58820
  const ageMs = Number.isFinite(updatedAt) ? now - updatedAt : null;
58715
- if (ageMs === null || ageMs < STALE_ASSIGNED_QUEUE_MS) return annotated;
58821
+ const staleReason = queueAssignmentStaleReason(task, liveness);
58822
+ if (!staleReason) return annotated;
58716
58823
  return {
58717
58824
  ...annotated,
58718
58825
  stale: true,
58719
58826
  staleAssigned: true,
58720
- staleReason: "assigned task has not reached a terminal state within 30 minutes",
58721
- assignedAgeMs: ageMs
58827
+ staleReason,
58828
+ ...ageMs !== null ? { assignedAgeMs: ageMs } : {}
58722
58829
  };
58723
58830
  });
58724
58831
  }
@@ -59649,11 +59756,17 @@ async function meshEnqueueTask(ctx, args) {
59649
59756
  }
59650
59757
  async function meshViewQueue(ctx, args) {
59651
59758
  try {
59652
- const queue = annotateQueueStaleness(getQueue(ctx.mesh.id, { status: args.status }));
59759
+ const queue = annotateQueueStaleness(getQueue(ctx.mesh.id, { status: args.status }), ctx.mesh);
59653
59760
  const staleAssignedTasks = queue.filter((task) => task?.status === "assigned" && task?.staleAssigned);
59761
+ const summary = buildQueueStatusSummary(queue);
59654
59762
  return JSON.stringify({
59655
59763
  success: true,
59656
59764
  queue,
59765
+ summary,
59766
+ activeCounts: summary.activeCounts,
59767
+ historicalCounts: summary.historicalCounts,
59768
+ activeCount: summary.activeCount,
59769
+ historicalCount: summary.historicalCount,
59657
59770
  staleAssignedTasks,
59658
59771
  staleAssignedCount: staleAssignedTasks.length,
59659
59772
  // Back-compat alias for callers already reading the first hardening payload.