@adhdev/daemon-core 1.0.18-rc.14 → 1.0.18-rc.16

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 ? "a44f4a2814c4db171a9ebb0f6fcfb0798203aebb" : void 0) ?? "unknown";
441
- const commitShort = readInjected(true ? "a44f4a28" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
- const version = readInjected(true ? "1.0.18-rc.14" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
- const builtAt = readInjected(true ? "2026-07-22T17:37:52.683Z" : void 0);
440
+ const commit = readInjected(true ? "74f34080bcd7c145e55fd7e5fd492a40a4942bc4" : void 0) ?? "unknown";
441
+ const commitShort = readInjected(true ? "74f34080" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
442
+ const version = readInjected(true ? "1.0.18-rc.16" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
443
+ const builtAt = readInjected(true ? "2026-07-23T02:29:46.281Z" : 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
  }
@@ -19178,6 +19184,26 @@ function selectFinalAssistantTurnEndMessage(messages) {
19178
19184
  }
19179
19185
  return null;
19180
19186
  }
19187
+ function hasTrailingToolActivityAfterFinalAssistant(messages) {
19188
+ if (!Array.isArray(messages) || messages.length === 0) return false;
19189
+ let sawTrailingToolActivity = false;
19190
+ for (let i = messages.length - 1; i >= 0; i--) {
19191
+ const msg = messages[i];
19192
+ if (!msg) continue;
19193
+ const classification = classifyChatMessageVisibility(msg);
19194
+ if (classification.isUserFacing && (msg.role === "assistant" || msg.role === "model")) {
19195
+ if (flattenContent(msg.content).trim()) return sawTrailingToolActivity;
19196
+ return false;
19197
+ }
19198
+ if (classification.isUserFacing) {
19199
+ return false;
19200
+ }
19201
+ if (classification.kind === "tool" || classification.kind === "terminal") {
19202
+ sawTrailingToolActivity = true;
19203
+ }
19204
+ }
19205
+ return false;
19206
+ }
19181
19207
  function canonicalizeKindHint(value) {
19182
19208
  return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
19183
19209
  }
@@ -22875,6 +22901,7 @@ async function pollAssignedTaskTerminalEvidence(components, mesh, row) {
22875
22901
  const messages = Array.isArray(payload.messages) ? payload.messages : [];
22876
22902
  const evidence = extractFinalAssistantSummaryEvidence(messages);
22877
22903
  if (!evidence.finalSummary) return null;
22904
+ if (hasTrailingToolActivityAfterFinalAssistant(messages)) return null;
22878
22905
  const dispatchedAtMs = Date.parse(readNonEmptyString(row.dispatchTimestamp));
22879
22906
  const transcriptAtMs = Date.parse(evidence.transcriptMessageAt ?? "");
22880
22907
  if (!(Number.isFinite(dispatchedAtMs) && Number.isFinite(transcriptAtMs) && transcriptAtMs >= dispatchedAtMs)) {
@@ -23167,6 +23194,52 @@ function assignedRowLiveStatusIsAwaitingApproval(mesh, nodeId, sessionId) {
23167
23194
  return false;
23168
23195
  }
23169
23196
  }
23197
+ function resolveLocalSessionPurePty(components, sessionId) {
23198
+ try {
23199
+ const instances = components.instanceManager?.getByCategory?.("cli") || [];
23200
+ const inst = instances.find((i) => {
23201
+ const sid = readNonEmptyString(i?.getState?.().instanceId);
23202
+ return sid && sessionIdsEquivalent(sid, sessionId);
23203
+ });
23204
+ if (!inst) return void 0;
23205
+ const provider = inst.provider;
23206
+ if (!provider || typeof provider !== "object") return void 0;
23207
+ return isPurePtyTranscriptProvider(provider);
23208
+ } catch {
23209
+ return void 0;
23210
+ }
23211
+ }
23212
+ async function evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds = []) {
23213
+ const sessionId = readNonEmptyString(row.assignedSessionId);
23214
+ if (!sessionId) return false;
23215
+ const verdict = resolveSessionBusyVerdict(components, sessionId);
23216
+ if (verdict === "GENERATING") return false;
23217
+ if (verdict === "UNKNOWN") {
23218
+ const nodeId = readNonEmptyString(row.assignedNodeId);
23219
+ const node = (mesh.nodes ?? []).find((n) => n.id === nodeId);
23220
+ const liveStatus = nodeId ? readNonEmptyString(sessionStatusFromNodes(mesh.nodes, nodeId, sessionId).status).toLowerCase() : "";
23221
+ if (liveStatus && liveStatus !== "idle") return false;
23222
+ if (!liveStatus) {
23223
+ const nodeDaemonId = readNonEmptyString(node?.daemonId);
23224
+ const isLocalNode = !nodeDaemonId || daemonIdsEquivalent(nodeDaemonId, localDaemonId) || daemonIdListIncludes(selfIds, nodeDaemonId) || !!components.instanceManager?.getInstance?.(sessionId);
23225
+ const providerType = readNonEmptyString(row.assignedProviderType);
23226
+ const readArgs = {
23227
+ sessionId,
23228
+ targetSessionId: sessionId,
23229
+ tailLimit: 1,
23230
+ ...node?.workspace ? { workspace: node.workspace } : {},
23231
+ ...providerType ? { agentType: providerType, providerType } : {}
23232
+ };
23233
+ const probedStatus = await reprobeWorkerStatus(components, { isLocalNode, nodeDaemonId, readArgs });
23234
+ if (probedStatus !== "idle") return false;
23235
+ }
23236
+ }
23237
+ if (store.taskDeliveryConsumed(mesh.id, row.id)) return true;
23238
+ const localPurePty = resolveLocalSessionPurePty(components, sessionId);
23239
+ if (localPurePty === true) return true;
23240
+ if (localPurePty === false) return false;
23241
+ return verdict === "UNKNOWN";
23242
+ }
23170
23243
  async function recoverStrandedAssignedDispatches(components, mesh, store, localDaemonId, selfIds = []) {
23171
23244
  const meshId = mesh.id;
23172
23245
  const assigned = getQueue(meshId, { status: ["assigned"] });
@@ -23180,10 +23253,55 @@ async function recoverStrandedAssignedDispatches(components, mesh, store, localD
23180
23253
  for (const key2 of [...deliveredUnconsumedUnknownStreak.keys()]) {
23181
23254
  if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) deliveredUnconsumedUnknownStreak.delete(key2);
23182
23255
  }
23256
+ for (const key2 of [...assignedIdleFinalAssistantSince.keys()]) {
23257
+ if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) assignedIdleFinalAssistantSince.delete(key2);
23258
+ }
23183
23259
  for (const row of assigned) {
23184
23260
  const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
23185
23261
  if (!Number.isFinite(dispatchedAtMs)) continue;
23186
23262
  const ageMs = nowMs - dispatchedAtMs;
23263
+ const idleTranscriptStreakKey = `${meshId}::${row.id}`;
23264
+ const earlyArm = store.taskHasConfirmedDelivery(meshId, row.id) && !findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id }) && readNonEmptyString(row.assignedSessionId) ? await evaluateEarlyIdleTranscriptArm(components, mesh, store, row, localDaemonId, selfIds) : false;
23265
+ if (earlyArm) {
23266
+ const since = assignedIdleFinalAssistantSince.get(idleTranscriptStreakKey);
23267
+ if (since === void 0) {
23268
+ assignedIdleFinalAssistantSince.set(idleTranscriptStreakKey, nowMs);
23269
+ } else if (nowMs - since >= ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS) {
23270
+ const terminalEvidence = await pollAssignedTaskTerminalEvidence(components, mesh, row);
23271
+ if (terminalEvidence) {
23272
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
23273
+ updateTaskStatus(meshId, row.id, terminalEvidence);
23274
+ if (!findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id })) {
23275
+ try {
23276
+ appendLedgerEntry(meshId, {
23277
+ kind: terminalEvidence === "completed" ? "task_completed" : "task_failed",
23278
+ nodeId: row.assignedNodeId,
23279
+ sessionId: row.assignedSessionId,
23280
+ providerType: row.assignedProviderType,
23281
+ payload: {
23282
+ taskId: row.id,
23283
+ event: "agent:generating_completed",
23284
+ source: "early_idle_transcript_evidence"
23285
+ }
23286
+ });
23287
+ } catch {
23288
+ }
23289
+ }
23290
+ 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`);
23291
+ traceMeshEventDrop("assigned_early_transcript_completed", {
23292
+ taskId: row.id,
23293
+ sessionId: row.assignedSessionId,
23294
+ nodeId: row.assignedNodeId,
23295
+ meshId,
23296
+ event: "agent:generating_completed"
23297
+ }, terminalEvidence);
23298
+ continue;
23299
+ }
23300
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
23301
+ }
23302
+ } else {
23303
+ assignedIdleFinalAssistantSince.delete(idleTranscriptStreakKey);
23304
+ }
23187
23305
  if (ageMs >= ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS && ageMs < ASSIGNED_STRANDED_DEADLINE_MS && store.taskHasConfirmedDelivery(meshId, row.id) && !store.taskDeliveryConsumed(meshId, row.id)) {
23188
23306
  const terminal2 = findTerminalLedgerEvidenceForTask({ meshId, taskId: row.id });
23189
23307
  if (terminal2) {
@@ -23859,7 +23977,7 @@ function setupMeshReconcileLoop(components) {
23859
23977
  }
23860
23978
  };
23861
23979
  }
23862
- 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;
23980
+ 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;
23863
23981
  var init_mesh_reconcile_loop = __esm({
23864
23982
  "src/mesh/mesh-reconcile-loop.ts"() {
23865
23983
  "use strict";
@@ -23883,6 +24001,7 @@ var init_mesh_reconcile_loop = __esm({
23883
24001
  init_mesh_reconcile_identity();
23884
24002
  init_mesh_reconcile_config();
23885
24003
  init_mesh_remote_event_pull();
24004
+ init_provider_cli_shared();
23886
24005
  init_mesh_disk_retention();
23887
24006
  init_mesh_completion_synthesis();
23888
24007
  init_mesh_active_work();
@@ -23897,6 +24016,8 @@ var init_mesh_reconcile_loop = __esm({
23897
24016
  RECLAIM_UNKNOWN_GRACE_TICKS = 3;
23898
24017
  deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
23899
24018
  deliveredUnconsumedUnknownStreak = /* @__PURE__ */ new Map();
24019
+ ASSIGNED_IDLE_TRANSCRIPT_COMPLETE_MS = 8e3;
24020
+ assignedIdleFinalAssistantSince = /* @__PURE__ */ new Map();
23900
24021
  ZOMBIE_ASSIGNED_MIN_AGE_MS = 30 * 60 * 1e3;
23901
24022
  STRICT_SESSION_MATCH_TTL_MS = 6e4;
23902
24023
  unresolvedForwardRejectionCounts = /* @__PURE__ */ new Map();
@@ -26665,7 +26786,8 @@ var init_cli_state_engine = __esm({
26665
26786
  this.currentTurnStartedAt = Date.now();
26666
26787
  this.responseEpoch += 1;
26667
26788
  this.clearApprovalResolutionMemory();
26668
- if (this.provider.transcriptAuthority === "provider" && this.currentStatus !== "waiting_approval") {
26789
+ const promoteOnTurnStart = this.provider.transcriptAuthority === "provider" || isPurePtyTranscriptProvider(this.provider);
26790
+ if (promoteOnTurnStart && this.currentStatus !== "waiting_approval") {
26669
26791
  this.setStatus("generating", "turn_started");
26670
26792
  this.callbacks.onStatusChange();
26671
26793
  }
@@ -28195,10 +28317,7 @@ ${lastSnapshot}`;
28195
28317
  * provider-owned) so no other provider's turn-scoped parse changes.
28196
28318
  */
28197
28319
  parsesFullPtyTranscriptFromBuffer() {
28198
- if (this.providerOwnsTranscript()) return false;
28199
- if (this.provider.nativeHistory) return false;
28200
- const transcriptPty = this.provider.tui?.transcriptPty;
28201
- return transcriptPty?.scope === "buffer";
28320
+ return isPurePtyTranscriptProvider(this.provider);
28202
28321
  }
28203
28322
  /**
28204
28323
  * The turn scope to feed the transcript parser. Normally the live turn scope
@@ -44930,6 +45049,7 @@ import * as os21 from "os";
44930
45049
  import * as crypto5 from "crypto";
44931
45050
  import * as fs24 from "fs";
44932
45051
  init_hash();
45052
+ init_provider_cli_shared();
44933
45053
 
44934
45054
  // src/providers/spec/route.ts
44935
45055
  init_provider_cli_adapter();
@@ -50606,6 +50726,10 @@ var CliProviderInstance = class _CliProviderInstance {
50606
50726
  return;
50607
50727
  }
50608
50728
  }
50729
+ if (this.tryReconcilePurePtyCompletionForStall(observedStatus)) {
50730
+ this.meshStallEmittedForAnchor = true;
50731
+ return;
50732
+ }
50609
50733
  this.meshStallEmittedForAnchor = true;
50610
50734
  if (this.meshStallLastFiredAt >= 0 && now - this.meshStallLastFiredAt < _CliProviderInstance.MESH_WORKER_STALL_REFIRE_COOLDOWN_MS) {
50611
50735
  return;
@@ -50736,6 +50860,70 @@ var CliProviderInstance = class _CliProviderInstance {
50736
50860
  });
50737
50861
  return true;
50738
50862
  }
50863
+ /**
50864
+ * KIMI-PURE-PTY-COMPLETION-EMIT (Fix 3): stall-path completion reconcile for the
50865
+ * PURE-PTY transcript class (kimi and kin — no native transcript, no provider
50866
+ * authority; see isPurePtyTranscriptProvider). Such a worker whose
50867
+ * generating_completed never emitted (the onTurnStarted idle→idle collapse Fix 1
50868
+ * fixes at the source) sits at a STATIC idle prompt: its PTY output stops the
50869
+ * instant the answer is rendered, so the status-agnostic no-progress watchdog
50870
+ * (checkMeshWorkerStall) reads the finished-but-quiet session as a stall and would
50871
+ * false-fire monitor:no_progress. The native-transcript reconcile
50872
+ * (sampleNativeTranscriptProgress) does NOT cover this class (no native source →
50873
+ * null sample), so the stall path needs its own guard.
50874
+ *
50875
+ * Called from checkMeshWorkerStall just before the fire. Returns true when the
50876
+ * session is a finished pure-PTY turn — idle, no pending response, and a PTY-parsed
50877
+ * in-turn final assistant summary — in which case it emits the missing
50878
+ * generating_completed (idempotent: a real/late emit writes the terminal ledger and
50879
+ * the coordinator's reconcile makes any duplicate a no-op) and the caller SUPPRESSES
50880
+ * the stall. Returns false for every other class/state (native-source provider, a
50881
+ * genuinely mid-turn or wedged worker with no final assistant), so a real stall still
50882
+ * fires unchanged.
50883
+ *
50884
+ * Evidence bar is identical to flushMeshCompletionBeforeCleanup: injected task's turn
50885
+ * genuinely started + an in-turn final assistant summary. Conservative by
50886
+ * construction — no summary ⇒ no proof of completion ⇒ return false and let the real
50887
+ * stall fire.
50888
+ */
50889
+ tryReconcilePurePtyCompletionForStall(observedStatus) {
50890
+ if (!isPurePtyTranscriptProvider(this.provider)) return false;
50891
+ if (observedStatus !== "idle") return false;
50892
+ if (this.hasAdapterPendingResponse()) return false;
50893
+ const taskId = this.completingTurnTaskId();
50894
+ if (this.lastEmittedCompletion && this.lastEmittedCompletion.taskId === (taskId ?? "")) {
50895
+ return false;
50896
+ }
50897
+ if (!this.injectedTaskHasStartedGenerating()) return false;
50898
+ const turnStartedAt = typeof this.adapter?.currentTurnStartedAt === "number" ? this.adapter.currentTurnStartedAt : this.meshTaskInjectedAt || void 0;
50899
+ let parsedMessages;
50900
+ try {
50901
+ parsedMessages = this.adapter?.getScriptParsedStatus?.()?.messages;
50902
+ } catch {
50903
+ parsedMessages = void 0;
50904
+ }
50905
+ let finalSummary;
50906
+ try {
50907
+ finalSummary = this.completionFinalSummary(parsedMessages, turnStartedAt);
50908
+ } catch {
50909
+ finalSummary = void 0;
50910
+ }
50911
+ if (!finalSummary) return false;
50912
+ 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.`);
50913
+ if (this.isMeshWorkerSession()) {
50914
+ traceMeshEventStage("fired", this.meshTraceCtx(), "stall_pure_pty_transcript_completion");
50915
+ }
50916
+ this.emitGeneratingCompleted({
50917
+ chatTitle: "",
50918
+ duration: void 0,
50919
+ timestamp: Date.now(),
50920
+ taskId,
50921
+ finalSummary,
50922
+ evidenceLevel: "transcript",
50923
+ completionDiagnostic: { source: "stall_pure_pty_transcript_completion" }
50924
+ });
50925
+ return true;
50926
+ }
50739
50927
  /**
50740
50928
  * AUTOAPPROVE-FLAP-RECUR (Fix A+B): how long a busy blip / modal scroll-out may
50741
50929
  * persist before the in-progress settle gate is torn down. For a delegated