@adhdev/daemon-core 1.0.18-rc.13 → 1.0.18-rc.15

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/dist/index.mjs CHANGED
@@ -437,10 +437,10 @@ function readInjected(value) {
437
437
  }
438
438
  function getDaemonBuildInfo() {
439
439
  if (cached) return cached;
440
- const commit = readInjected(true ? "2a9ab536171fcf675788ac5b41596e740046bbfa" : void 0) ?? "unknown";
441
- const commitShort = readInjected(true ? "2a9ab536" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
- const version = readInjected(true ? "1.0.18-rc.13" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
- const builtAt = readInjected(true ? "2026-07-22T14:01:45.066Z" : void 0);
440
+ const commit = readInjected(true ? "64f056340da99d3b28464efcf5c05fe643e5db63" : void 0) ?? "unknown";
441
+ const commitShort = readInjected(true ? "64f05634" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
+ const version = readInjected(true ? "1.0.18-rc.15" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
+ const builtAt = readInjected(true ? "2026-07-23T00:51:36.808Z" : void 0);
444
444
  cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
445
445
  return cached;
446
446
  }
@@ -12929,6 +12929,12 @@ var init_spawn_env = __esm({
12929
12929
  // src/cli-adapters/provider-cli-shared.ts
12930
12930
  import * as os5 from "os";
12931
12931
  import * as path11 from "path";
12932
+ function isPurePtyTranscriptProvider(provider) {
12933
+ if (provider.transcriptAuthority === "provider") return false;
12934
+ if (provider.nativeHistory) return false;
12935
+ const transcriptPty = provider.tui?.transcriptPty;
12936
+ return transcriptPty?.scope === "buffer";
12937
+ }
12932
12938
  function stripAnsi(str) {
12933
12939
  return str.replace(/\x1B\][^\x07]*(?:\x07|\x1B\\)/g, "").replace(/\x1B[P^_X][\s\S]*?(?:\x07|\x1B\\)/g, "").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
12934
12940
  }
@@ -22229,34 +22235,37 @@ async function pullRemoteNodeQueues(components, mesh, localDaemonId, candidateDa
22229
22235
  if (!dispatchMeshCommand) return;
22230
22236
  const meshId = mesh.id;
22231
22237
  const pulls = candidateDaemonIds.length > 0 ? candidateDaemonIds.map((id) => ({ meshId, coordinatorDaemonId: id })) : [{ meshId }];
22232
- await Promise.allSettled(mesh.nodes.map(async (node) => {
22233
- const nodeDaemonId = readNonEmptyString(node.daemonId);
22234
- if (!nodeDaemonId) return;
22235
- if (daemonIdsEquivalent(nodeDaemonId, localDaemonId)) return;
22236
- if (daemonIdListIncludes(candidateDaemonIds, nodeDaemonId)) return;
22237
- const getPeerStatus = components.getMeshPeerConnectionStatus;
22238
- if (getPeerStatus) {
22239
- const peerSnapshot = getPeerStatus(nodeDaemonId);
22240
- if (!peerSnapshot || String(peerSnapshot.state) !== "connected") return;
22241
- }
22242
- for (const pendingEventArgs of pulls) {
22243
- let events;
22238
+ await Promise.allSettled(mesh.nodes.map((node) => pullPendingEventsFromNode(components, meshId, node, localDaemonId, candidateDaemonIds, pulls)));
22239
+ }
22240
+ async function pullPendingEventsFromNode(components, meshId, node, localDaemonId, candidateDaemonIds, pulls) {
22241
+ const dispatchMeshCommand = components.dispatchMeshCommand;
22242
+ if (!dispatchMeshCommand) return;
22243
+ const nodeDaemonId = readNonEmptyString(node.daemonId);
22244
+ if (!nodeDaemonId) return;
22245
+ if (daemonIdsEquivalent(nodeDaemonId, localDaemonId)) return;
22246
+ if (daemonIdListIncludes(candidateDaemonIds, nodeDaemonId)) return;
22247
+ const getPeerStatus = components.getMeshPeerConnectionStatus;
22248
+ if (getPeerStatus) {
22249
+ const peerSnapshot = getPeerStatus(nodeDaemonId);
22250
+ if (!peerSnapshot || String(peerSnapshot.state) !== "connected") return;
22251
+ }
22252
+ for (const pendingEventArgs of pulls) {
22253
+ let events;
22254
+ try {
22255
+ events = await dispatchMeshCommand(nodeDaemonId, "get_pending_mesh_events", pendingEventArgs);
22256
+ } catch {
22257
+ break;
22258
+ }
22259
+ const list = extractPendingEvents(events).filter((e) => readNonEmptyString(e?.meshId) === meshId);
22260
+ for (const event of list) {
22261
+ const payload = buildForwardPayloadFromPending(event);
22262
+ if (!payload.event || !payload.meshId) continue;
22244
22263
  try {
22245
- events = await dispatchMeshCommand(nodeDaemonId, "get_pending_mesh_events", pendingEventArgs);
22264
+ handleMeshForwardEvent(components, payload);
22246
22265
  } catch {
22247
- break;
22248
- }
22249
- const list = extractPendingEvents(events).filter((e) => readNonEmptyString(e?.meshId) === meshId);
22250
- for (const event of list) {
22251
- const payload = buildForwardPayloadFromPending(event);
22252
- if (!payload.event || !payload.meshId) continue;
22253
- try {
22254
- handleMeshForwardEvent(components, payload);
22255
- } catch {
22256
- }
22257
22266
  }
22258
22267
  }
22259
- }));
22268
+ }
22260
22269
  }
22261
22270
  function unwrapReadChatPayload(raw) {
22262
22271
  let cursor = raw;
@@ -23164,7 +23173,7 @@ function assignedRowLiveStatusIsAwaitingApproval(mesh, nodeId, sessionId) {
23164
23173
  return false;
23165
23174
  }
23166
23175
  }
23167
- async function recoverStrandedAssignedDispatches(components, mesh, store) {
23176
+ async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
23168
23177
  const meshId = mesh.id;
23169
23178
  const assigned = getQueue(meshId, { status: ["assigned"] });
23170
23179
  if (!assigned.length) return;
@@ -23177,10 +23186,54 @@ async function recoverStrandedAssignedDispatches(components, mesh, store) {
23177
23186
  for (const key2 of [...deliveredUnconsumedUnknownStreak.keys()]) {
23178
23187
  if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) deliveredUnconsumedUnknownStreak.delete(key2);
23179
23188
  }
23189
+ for (const key2 of [...assignedIdleFinalAssistantSince.keys()]) {
23190
+ if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) assignedIdleFinalAssistantSince.delete(key2);
23191
+ }
23180
23192
  for (const row of assigned) {
23181
23193
  const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
23182
23194
  if (!Number.isFinite(dispatchedAtMs)) continue;
23183
23195
  const ageMs = nowMs - dispatchedAtMs;
23196
+ const idleTranscriptStreakKey = `${meshId}::${row.id}`;
23197
+ if (store.taskHasConfirmedDelivery(meshId, row.id) && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id }) && readNonEmptyString(row.assignedSessionId) && resolveSessionBusyVerdict(components, row.assignedSessionId) !== "GENERATING") {
23198
+ const since = assignedIdleFinalAssistantSince.get(idleTranscriptStreakKey);
23199
+ if (since === void 0) {
23200
+ assignedIdleFinalAssistantSince.set(idleTranscriptStreakKey, nowMs);
23201
+ } else if (nowMs - since >= ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS) {
23202
+ const terminalEvidence = await pollAssignedTaskTerminalEvidence(components, mesh, row);
23203
+ if (terminalEvidence) {
23204
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
23205
+ updateTaskStatus(meshId, row.id, terminalEvidence);
23206
+ if (!findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
23207
+ try {
23208
+ appendLedgerEntry(meshId, {
23209
+ kind: terminalEvidence === "completed" ? "task_completed" : "task_failed",
23210
+ nodeId: row.assignedNodeId,
23211
+ sessionId: row.assignedSessionId,
23212
+ providerType: row.assignedProviderType,
23213
+ payload: {
23214
+ taskId: row.id,
23215
+ event: "agent:generating_completed",
23216
+ source: "early_idle_transcript_evidence"
23217
+ }
23218
+ });
23219
+ } catch {
23220
+ }
23221
+ }
23222
+ LOG.warn("MeshReconcile", `Early-completed assigned task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}): worker idle with a final assistant message after dispatch for \u2265${Math.round(ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS / 1e3)}s \u2014 the completion event was lost/late (pure-PTY provider), task is ${terminalEvidence} without waiting the 15-min deadline`);
23223
+ traceMeshEventDrop("assigned_early_transcript_completed", {
23224
+ taskId: row.id,
23225
+ sessionId: row.assignedSessionId,
23226
+ nodeId: row.assignedNodeId,
23227
+ meshId,
23228
+ event: "agent:generating_completed"
23229
+ }, terminalEvidence);
23230
+ continue;
23231
+ }
23232
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
23233
+ }
23234
+ } else {
23235
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
23236
+ }
23184
23237
  if (ageMs >= ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS && ageMs < ASSIGNED_STRANDED_DEADLINE_MS && store.taskHasConfirmedDelivery(meshId, row.id) && !store.taskDeliveryConsumed(meshId, row.id)) {
23185
23238
  const terminal2 = findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id });
23186
23239
  if (terminal2) {
@@ -23188,6 +23241,24 @@ async function recoverStrandedAssignedDispatches(components, mesh, store) {
23188
23241
  updateTaskStatus(meshId, row.id, status);
23189
23242
  continue;
23190
23243
  }
23244
+ const assignedNode = row.assignedNodeId ? mesh.nodes?.find((n) => meshNodeIdMatches(n, row.assignedNodeId)) : void 0;
23245
+ if (assignedNode?.daemonId) {
23246
+ try {
23247
+ await pullPendingEventsFromNode(
23248
+ components,
23249
+ meshId,
23250
+ assignedNode,
23251
+ localDaemonId,
23252
+ selfIds,
23253
+ selfIds.length > 0 ? selfIds.map((id) => ({ meshId, coordinatorDaemonId: id })) : [{ meshId }]
23254
+ );
23255
+ } catch {
23256
+ }
23257
+ if (store.taskDeliveryConsumed(meshId, row.id)) {
23258
+ deliveredUnconsumedUnknownStreak.delete(`${meshId}::${row.id}`);
23259
+ continue;
23260
+ }
23261
+ }
23191
23262
  const shortStreakKey = `${meshId}::${row.id}`;
23192
23263
  const verdict = row.assignedSessionId ? resolveSessionBusyVerdict(components, row.assignedSessionId) : "IDLE_CONFIRMED";
23193
23264
  if (verdict === "GENERATING") {
@@ -23446,7 +23517,7 @@ async function runMeshReconcileTick(components) {
23446
23517
  const selfIds = resolveCoordinatorSelfIds(mesh, drainDaemonIds);
23447
23518
  if (!daemonHostsMesh(mesh, selfIds)) continue;
23448
23519
  try {
23449
- await recoverStrandedAssignedDispatches(components, mesh, store);
23520
+ await recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds);
23450
23521
  } catch (e) {
23451
23522
  LOG.warn("MeshReconcile", `Assigned-stranded watchdog failed for mesh ${mesh.id}: ${e?.message || e}`);
23452
23523
  }
@@ -23838,7 +23909,7 @@ function setupMeshReconcileLoop(components) {
23838
23909
  }
23839
23910
  };
23840
23911
  }
23841
- var coordinatorModalParkState, DISK_RETENTION_INTERVAL_MS, lastDiskRetentionRunAt, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, deliveredUnconsumedUnknownStreak, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
23912
+ var coordinatorModalParkState, DISK_RETENTION_INTERVAL_MS, lastDiskRetentionRunAt, heldEventLedgerRecorded, ASSIGNED_STRANDED_DEADLINE_MS, DELIVERED_NO_TURN_DEADLINE_MS, ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS, RECLAIM_UNKNOWN_GRACE_TICKS, deliveredNoTurnUnknownStreak, deliveredUnconsumedUnknownStreak, ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS, assignedIdleFinalAssistantSince, ZOMBIE_ASSIGNED_MIN_AGE_MS, STRICT_SESSION_MATCH_TTL_MS, unresolvedForwardRejectionCounts, MAX_FORWARD_REJECTIONS, UNRESOLVED_FORWARD_NUDGE_DELAY_MS, unresolvedForwardNudgeTimer, unresolvedForwardNudgeRunning;
23842
23913
  var init_mesh_reconcile_loop = __esm({
23843
23914
  "src/mesh/mesh-reconcile-loop.ts"() {
23844
23915
  "use strict";
@@ -23876,6 +23947,8 @@ var init_mesh_reconcile_loop = __esm({
23876
23947
  RECLAIM_UNKNOWN_GRACE_TICKS = 3;
23877
23948
  deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
23878
23949
  deliveredUnconsumedUnknownStreak = /* @__PURE__ */ new Map();
23950
+ ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS = 8e3;
23951
+ assignedIdleFinalAssistantSince = /* @__PURE__ */ new Map();
23879
23952
  ZOMBIE_ASSIGNED_MIN_AGE_MS = 30 * 60 * 1e3;
23880
23953
  STRICT_SESSION_MATCH_TTL_MS = 6e4;
23881
23954
  unresolvedForwardRejectionCounts = /* @__PURE__ */ new Map();
@@ -26644,7 +26717,8 @@ var init_cli_state_engine = __esm({
26644
26717
  this.currentTurnStartedAt = Date.now();
26645
26718
  this.responseEpoch += 1;
26646
26719
  this.clearApprovalResolutionMemory();
26647
- if (this.provider.transcriptAuthority === "provider" && this.currentStatus !== "waiting_approval") {
26720
+ const promoteOnTurnStart = this.provider.transcriptAuthority === "provider" || isPurePtyTranscriptProvider(this.provider);
26721
+ if (promoteOnTurnStart && this.currentStatus !== "waiting_approval") {
26648
26722
  this.setStatus("generating", "turn_started");
26649
26723
  this.callbacks.onStatusChange();
26650
26724
  }
@@ -28174,10 +28248,7 @@ ${lastSnapshot}`;
28174
28248
  * provider-owned) so no other provider's turn-scoped parse changes.
28175
28249
  */
28176
28250
  parsesFullPtyTranscriptFromBuffer() {
28177
- if (this.providerOwnsTranscript()) return false;
28178
- if (this.provider.nativeHistory) return false;
28179
- const transcriptPty = this.provider.tui?.transcriptPty;
28180
- return transcriptPty?.scope === "buffer";
28251
+ return isPurePtyTranscriptProvider(this.provider);
28181
28252
  }
28182
28253
  /**
28183
28254
  * The turn scope to feed the transcript parser. Normally the live turn scope
@@ -44909,6 +44980,7 @@ import * as os21 from "os";
44909
44980
  import * as crypto5 from "crypto";
44910
44981
  import * as fs24 from "fs";
44911
44982
  init_hash();
44983
+ init_provider_cli_shared();
44912
44984
 
44913
44985
  // src/providers/spec/route.ts
44914
44986
  init_provider_cli_adapter();
@@ -50585,6 +50657,10 @@ var CliProviderInstance = class _CliProviderInstance {
50585
50657
  return;
50586
50658
  }
50587
50659
  }
50660
+ if (this.tryReconcilePurePtyCompletionForStall(observedStatus)) {
50661
+ this.meshStallEmittedForAnchor = true;
50662
+ return;
50663
+ }
50588
50664
  this.meshStallEmittedForAnchor = true;
50589
50665
  if (this.meshStallLastFiredAt >= 0 && now - this.meshStallLastFiredAt < _CliProviderInstance.MESH_WORKER_STALL_REFIRE_COOLDOWN_MS) {
50590
50666
  return;
@@ -50715,6 +50791,70 @@ var CliProviderInstance = class _CliProviderInstance {
50715
50791
  });
50716
50792
  return true;
50717
50793
  }
50794
+ /**
50795
+ * KIMI-PURE-PTY-COMPLETION-EMIT (Fix 3): stall-path completion reconcile for the
50796
+ * PURE-PTY transcript class (kimi and kin — no native transcript, no provider
50797
+ * authority; see isPurePtyTranscriptProvider). Such a worker whose
50798
+ * generating_completed never emitted (the onTurnStarted idle→idle collapse Fix 1
50799
+ * fixes at the source) sits at a STATIC idle prompt: its PTY output stops the
50800
+ * instant the answer is rendered, so the status-agnostic no-progress watchdog
50801
+ * (checkMeshWorkerStall) reads the finished-but-quiet session as a stall and would
50802
+ * false-fire monitor:no_progress. The native-transcript reconcile
50803
+ * (sampleNativeTranscriptProgress) does NOT cover this class (no native source →
50804
+ * null sample), so the stall path needs its own guard.
50805
+ *
50806
+ * Called from checkMeshWorkerStall just before the fire. Returns true when the
50807
+ * session is a finished pure-PTY turn — idle, no pending response, and a PTY-parsed
50808
+ * in-turn final assistant summary — in which case it emits the missing
50809
+ * generating_completed (idempotent: a real/late emit writes the terminal ledger and
50810
+ * the coordinator's reconcile makes any duplicate a no-op) and the caller SUPPRESSES
50811
+ * the stall. Returns false for every other class/state (native-source provider, a
50812
+ * genuinely mid-turn or wedged worker with no final assistant), so a real stall still
50813
+ * fires unchanged.
50814
+ *
50815
+ * Evidence bar is identical to flushMeshCompletionBeforeCleanup: injected task's turn
50816
+ * genuinely started + an in-turn final assistant summary. Conservative by
50817
+ * construction — no summary ⇒ no proof of completion ⇒ return false and let the real
50818
+ * stall fire.
50819
+ */
50820
+ tryReconcilePurePtyCompletionForStall(observedStatus) {
50821
+ if (!isPurePtyTranscriptProvider(this.provider)) return false;
50822
+ if (observedStatus !== "idle") return false;
50823
+ if (this.hasAdapterPendingResponse()) return false;
50824
+ const taskId = this.completingTurnTaskId();
50825
+ if (this.lastEmittedCompletion && this.lastEmittedCompletion.taskId === (taskId ?? "")) {
50826
+ return false;
50827
+ }
50828
+ if (!this.injectedTaskHasStartedGenerating()) return false;
50829
+ const turnStartedAt = typeof this.adapter?.currentTurnStartedAt === "number" ? this.adapter.currentTurnStartedAt : this.meshTaskInjectedAt || void 0;
50830
+ let parsedMessages;
50831
+ try {
50832
+ parsedMessages = this.adapter?.getScriptParsedStatus?.()?.messages;
50833
+ } catch {
50834
+ parsedMessages = void 0;
50835
+ }
50836
+ let finalSummary;
50837
+ try {
50838
+ finalSummary = this.completionFinalSummary(parsedMessages, turnStartedAt);
50839
+ } catch {
50840
+ finalSummary = void 0;
50841
+ }
50842
+ if (!finalSummary) return false;
50843
+ LOG.warn("CLI", `[${this.type}] reconciling pure-PTY mesh completion from the stall path for session ${this.instanceId} task=${taskId ?? "(none)"} \u2014 PTY is idle-quiet with an in-turn final assistant message but the completion event never fired (pure-PTY provider); emitting it instead of a false monitor:no_progress.`);
50844
+ if (this.isMeshWorkerSession()) {
50845
+ traceMeshEventStage("fired", this.meshTraceCtx(), "stall_pure_pty_transcript_completion");
50846
+ }
50847
+ this.emitGeneratingCompleted({
50848
+ chatTitle: "",
50849
+ duration: void 0,
50850
+ timestamp: Date.now(),
50851
+ taskId,
50852
+ finalSummary,
50853
+ evidenceLevel: "transcript",
50854
+ completionDiagnostic: { source: "stall_pure_pty_transcript_completion" }
50855
+ });
50856
+ return true;
50857
+ }
50718
50858
  /**
50719
50859
  * AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
50720
50860
  * persist before the in-progress settle gate is torn down. For a delegated