@adhdev/daemon-standalone 0.9.82-rc.532 → 0.9.82-rc.534
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.js +156 -24
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -30208,10 +30208,10 @@ var require_dist3 = __commonJS({
|
|
|
30208
30208
|
}
|
|
30209
30209
|
function getDaemonBuildInfo() {
|
|
30210
30210
|
if (cached2) return cached2;
|
|
30211
|
-
const commit = readInjected(true ? "
|
|
30212
|
-
const commitShort = readInjected(true ? "
|
|
30213
|
-
const version2 = readInjected(true ? "0.9.82-rc.
|
|
30214
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
30211
|
+
const commit = readInjected(true ? "7b6411ebc267c71484a3f7d16c392b5bd3e71bd8" : void 0) ?? "unknown";
|
|
30212
|
+
const commitShort = readInjected(true ? "7b6411eb" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
30213
|
+
const version2 = readInjected(true ? "0.9.82-rc.534" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
30214
|
+
const builtAt = readInjected(true ? "2026-07-15T08:30:49.700Z" : void 0);
|
|
30215
30215
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
30216
30216
|
return cached2;
|
|
30217
30217
|
}
|
|
@@ -35486,12 +35486,16 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
35486
35486
|
return [];
|
|
35487
35487
|
}
|
|
35488
35488
|
}
|
|
35489
|
+
function consumeSessionDelivery(meshId, sessionId, status, taskId) {
|
|
35490
|
+
try {
|
|
35491
|
+
return MeshRuntimeStore.getInstance().consumeSessionDelivery(meshId, sessionId, status, taskId);
|
|
35492
|
+
} catch {
|
|
35493
|
+
return 0;
|
|
35494
|
+
}
|
|
35495
|
+
}
|
|
35489
35496
|
function markSessionDeliveriesTerminal(meshId, sessionId, terminalStatus) {
|
|
35490
35497
|
try {
|
|
35491
|
-
|
|
35492
|
-
for (const delivery of active) {
|
|
35493
|
-
MeshRuntimeStore.getInstance().updateSessionDeliveryStatus(delivery.id, terminalStatus);
|
|
35494
|
-
}
|
|
35498
|
+
MeshRuntimeStore.getInstance().markOpenSessionDeliveriesTerminal(meshId, sessionId, terminalStatus);
|
|
35495
35499
|
} catch {
|
|
35496
35500
|
}
|
|
35497
35501
|
}
|
|
@@ -37556,6 +37560,25 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
37556
37560
|
});
|
|
37557
37561
|
this.maybeCheckpointWal();
|
|
37558
37562
|
}
|
|
37563
|
+
// DELIVERED-NOT-CONSUMED-REDRIVE monotonic FSM: the forward-progress lifecycle of a
|
|
37564
|
+
// delivery is a strictly increasing rank — a status may only advance, never regress.
|
|
37565
|
+
// The redrive bug was a NON-monotonic FSM: the transport-confirm callback
|
|
37566
|
+
// (mesh-queue-assignment :384) writes 'delivered' unconditionally by PK, so when the
|
|
37567
|
+
// worker's agent:generating_started raced AHEAD of the confirm and already flipped the
|
|
37568
|
+
// row 'delivering'→'acked', the late confirm CLOBBERED 'acked' back to 'delivered'.
|
|
37569
|
+
// taskDeliveryConsumed() (which keys on 'acked'/'completed') then read false forever,
|
|
37570
|
+
// and the short-grace re-drive re-opened an already-consumed task. Enforcing the rank
|
|
37571
|
+
// ordering here makes the two event orders converge on the same monotone terminal state
|
|
37572
|
+
// regardless of arrival order, so a late confirm can never demote a consumed delivery.
|
|
37573
|
+
// 'failed'/'expired'/'cancelled' are absorbing OUTCOMES, not progress ranks — they are
|
|
37574
|
+
// always allowed (a genuine dispatch failure must be recordable even from 'acked').
|
|
37575
|
+
static DELIVERY_PROGRESS_RANK = {
|
|
37576
|
+
queued: 0,
|
|
37577
|
+
delivering: 1,
|
|
37578
|
+
delivered: 2,
|
|
37579
|
+
acked: 3,
|
|
37580
|
+
completed: 4
|
|
37581
|
+
};
|
|
37559
37582
|
updateSessionDeliveryStatus(id, status, opts) {
|
|
37560
37583
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
37561
37584
|
if (opts?.incrementAttempt) {
|
|
@@ -37564,13 +37587,75 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
37564
37587
|
SET status = @status, last_error = @lastError, attempt_count = attempt_count + 1, updated_at = @updatedAt
|
|
37565
37588
|
WHERE id = @id
|
|
37566
37589
|
`).run({ id, status, lastError: opts?.lastError ?? null, updatedAt: now });
|
|
37567
|
-
|
|
37590
|
+
return;
|
|
37591
|
+
}
|
|
37592
|
+
const targetRank = _MeshRuntimeStore.DELIVERY_PROGRESS_RANK[status];
|
|
37593
|
+
if (targetRank === void 0) {
|
|
37568
37594
|
this.db.prepare(`
|
|
37569
37595
|
UPDATE mesh_session_delivery
|
|
37570
37596
|
SET status = @status, last_error = @lastError, updated_at = @updatedAt
|
|
37571
37597
|
WHERE id = @id
|
|
37572
37598
|
`).run({ id, status, lastError: opts?.lastError ?? null, updatedAt: now });
|
|
37599
|
+
return;
|
|
37573
37600
|
}
|
|
37601
|
+
this.db.prepare(`
|
|
37602
|
+
UPDATE mesh_session_delivery
|
|
37603
|
+
SET status = @status, last_error = @lastError, updated_at = @updatedAt
|
|
37604
|
+
WHERE id = @id AND (@targetRank >= CASE status
|
|
37605
|
+
WHEN 'queued' THEN 0 WHEN 'delivering' THEN 1 WHEN 'delivered' THEN 2
|
|
37606
|
+
WHEN 'acked' THEN 3 WHEN 'completed' THEN 4 ELSE 99 END)
|
|
37607
|
+
`).run({ id, status, lastError: opts?.lastError ?? null, updatedAt: now, targetRank });
|
|
37608
|
+
}
|
|
37609
|
+
/**
|
|
37610
|
+
* DELIVERED-NOT-CONSUMED-REDRIVE consume path. Advance a task's delivery record(s) to a
|
|
37611
|
+
* CONSUMED status ('acked' or 'completed'), matching on mesh + session (+ taskId when the
|
|
37612
|
+
* event names one) and INCLUDING rows already in 'delivered'/'acked'/'delivering'.
|
|
37613
|
+
*
|
|
37614
|
+
* The ack/terminal callers previously routed through getActiveSessionDeliveries(), whose SQL
|
|
37615
|
+
* EXCLUDES 'delivered' — so in the normal event order (transport confirm flips 'delivered'
|
|
37616
|
+
* BEFORE the worker's generating_started fires) the ack matched zero rows and the delivery
|
|
37617
|
+
* was stranded 'delivered', never 'acked'. This finds the row by (mesh, session[, task])
|
|
37618
|
+
* directly and relies on updateSessionDeliveryStatus's monotonic guard to only advance it.
|
|
37619
|
+
* Returns the number of rows advanced.
|
|
37620
|
+
*/
|
|
37621
|
+
consumeSessionDelivery(meshId, sessionId, status, taskId) {
|
|
37622
|
+
const rows = this.db.prepare(
|
|
37623
|
+
taskId ? `SELECT id, session_id FROM mesh_session_delivery
|
|
37624
|
+
WHERE mesh_id = ? AND task_id = ?
|
|
37625
|
+
AND status IN ('queued','delivering','delivered','acked')` : `SELECT id, session_id FROM mesh_session_delivery
|
|
37626
|
+
WHERE mesh_id = ? AND session_id = ?
|
|
37627
|
+
AND status IN ('queued','delivering','delivered','acked')`
|
|
37628
|
+
).all(meshId, taskId ?? sessionId);
|
|
37629
|
+
let advanced = 0;
|
|
37630
|
+
for (const r of rows) {
|
|
37631
|
+
if (!sessionIdsEquivalent(r.session_id ?? void 0, sessionId)) continue;
|
|
37632
|
+
this.updateSessionDeliveryStatus(r.id, status);
|
|
37633
|
+
advanced++;
|
|
37634
|
+
}
|
|
37635
|
+
return advanced;
|
|
37636
|
+
}
|
|
37637
|
+
/**
|
|
37638
|
+
* DELIVERED-NOT-CONSUMED-REDRIVE terminal path. Mark every OPEN delivery for a session
|
|
37639
|
+
* (queued/delivering/delivered/acked) terminal on task completion/failure. The prior
|
|
37640
|
+
* markSessionDeliveriesTerminal() routed through getActiveSessionDeliveries(), whose SQL
|
|
37641
|
+
* EXCLUDES 'delivered'/'completed' — so a 'delivered' row (the common case, since the
|
|
37642
|
+
* transport confirm flips it before the completion event) was never marked terminal and
|
|
37643
|
+
* stayed 'delivered', keeping taskDeliveryConsumed() false and feeding the false re-drive.
|
|
37644
|
+
* We match rows in OPEN states directly here. 'completed' advances monotonically (it is the
|
|
37645
|
+
* top progress rank); 'failed' is an absorbing outcome written unconditionally.
|
|
37646
|
+
*/
|
|
37647
|
+
markOpenSessionDeliveriesTerminal(meshId, sessionId, terminalStatus) {
|
|
37648
|
+
const rows = this.db.prepare(
|
|
37649
|
+
`SELECT id, session_id FROM mesh_session_delivery
|
|
37650
|
+
WHERE mesh_id = ? AND status IN ('queued','delivering','delivered','acked')`
|
|
37651
|
+
).all(meshId);
|
|
37652
|
+
let marked = 0;
|
|
37653
|
+
for (const r of rows) {
|
|
37654
|
+
if (!sessionIdsEquivalent(r.session_id ?? void 0, sessionId)) continue;
|
|
37655
|
+
this.updateSessionDeliveryStatus(r.id, terminalStatus);
|
|
37656
|
+
marked++;
|
|
37657
|
+
}
|
|
37658
|
+
return marked;
|
|
37574
37659
|
}
|
|
37575
37660
|
getActiveSessionDeliveries(meshId, sessionId) {
|
|
37576
37661
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -50570,17 +50655,7 @@ ${cleanBody}`;
|
|
|
50570
50655
|
updateDirectDispatchStatus(args.meshId, sessionId, "acked", soleTaskId);
|
|
50571
50656
|
}
|
|
50572
50657
|
}
|
|
50573
|
-
|
|
50574
|
-
try {
|
|
50575
|
-
return MeshRuntimeStore.getInstance().getActiveSessionDeliveries(args.meshId, sessionId);
|
|
50576
|
-
} catch {
|
|
50577
|
-
return [];
|
|
50578
|
-
}
|
|
50579
|
-
})();
|
|
50580
|
-
const deliveriesToAck = startedTaskId ? activeDeliveries.filter((d) => d.taskId === startedTaskId) : activeDeliveries;
|
|
50581
|
-
for (const d of deliveriesToAck) {
|
|
50582
|
-
updateSessionDeliveryStatus(d.id, "acked");
|
|
50583
|
-
}
|
|
50658
|
+
consumeSessionDelivery(args.meshId, sessionId, "acked", startedTaskId);
|
|
50584
50659
|
}
|
|
50585
50660
|
} else if (args.event === "agent:stopped") {
|
|
50586
50661
|
const sessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
@@ -52015,6 +52090,9 @@ ${cleanBody}`;
|
|
|
52015
52090
|
for (const key2 of [...deliveredNoTurnUnknownStreak.keys()]) {
|
|
52016
52091
|
if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) deliveredNoTurnUnknownStreak.delete(key2);
|
|
52017
52092
|
}
|
|
52093
|
+
for (const key2 of [...deliveredUnconsumedUnknownStreak.keys()]) {
|
|
52094
|
+
if (key2.startsWith(meshKeyPrefix) && !assignedKeys.has(key2)) deliveredUnconsumedUnknownStreak.delete(key2);
|
|
52095
|
+
}
|
|
52018
52096
|
for (const row of assigned) {
|
|
52019
52097
|
const dispatchedAtMs = Date.parse(row.dispatchTimestamp ?? "");
|
|
52020
52098
|
if (!Number.isFinite(dispatchedAtMs)) continue;
|
|
@@ -52026,13 +52104,33 @@ ${cleanBody}`;
|
|
|
52026
52104
|
updateTaskStatus(meshId, row.id, status);
|
|
52027
52105
|
continue;
|
|
52028
52106
|
}
|
|
52107
|
+
const shortStreakKey = `${meshId}::${row.id}`;
|
|
52029
52108
|
const verdict = row.assignedSessionId ? resolveSessionBusyVerdict(components, row.assignedSessionId) : "IDLE_CONFIRMED";
|
|
52030
|
-
if (verdict
|
|
52109
|
+
if (verdict === "GENERATING") {
|
|
52110
|
+
deliveredUnconsumedUnknownStreak.delete(shortStreakKey);
|
|
52111
|
+
} else {
|
|
52112
|
+
if (verdict === "IDLE_CONFIRMED") {
|
|
52113
|
+
deliveredUnconsumedUnknownStreak.delete(shortStreakKey);
|
|
52114
|
+
} else {
|
|
52115
|
+
const streak = (deliveredUnconsumedUnknownStreak.get(shortStreakKey) ?? 0) + 1;
|
|
52116
|
+
deliveredUnconsumedUnknownStreak.set(shortStreakKey, streak);
|
|
52117
|
+
if (streak < RECLAIM_UNKNOWN_GRACE_TICKS) {
|
|
52118
|
+
traceMeshEventDrop("short_redrive_deferred_unknown_verdict", {
|
|
52119
|
+
taskId: row.id,
|
|
52120
|
+
sessionId: row.assignedSessionId,
|
|
52121
|
+
nodeId: row.assignedNodeId,
|
|
52122
|
+
meshId,
|
|
52123
|
+
event: "agent:generating_started"
|
|
52124
|
+
}, `unknown ${streak}/${RECLAIM_UNKNOWN_GRACE_TICKS}`);
|
|
52125
|
+
continue;
|
|
52126
|
+
}
|
|
52127
|
+
}
|
|
52031
52128
|
const redriven = reclaimStrandedAssignedTask(meshId, row.id, {
|
|
52032
52129
|
reason: "delivered_not_consumed_redrive",
|
|
52033
52130
|
ageMs
|
|
52034
52131
|
});
|
|
52035
52132
|
if (redriven) {
|
|
52133
|
+
deliveredUnconsumedUnknownStreak.delete(shortStreakKey);
|
|
52036
52134
|
LOG2.warn("MeshReconcile", `Re-drove delivered-but-unconsumed task ${row.id} on mesh ${meshId} (node=${row.assignedNodeId ?? "?"} session=${row.assignedSessionId ?? "?"}, delivered but no generating_started in ${Math.round(ageMs / 1e3)}s, verdict ${verdict} \u2192 ${redriven.status})`);
|
|
52037
52135
|
traceMeshEventDrop("assigned_delivered_not_consumed_redrive", {
|
|
52038
52136
|
taskId: row.id,
|
|
@@ -52594,6 +52692,7 @@ ${cleanBody}`;
|
|
|
52594
52692
|
var ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS;
|
|
52595
52693
|
var RECLAIM_UNKNOWN_GRACE_TICKS;
|
|
52596
52694
|
var deliveredNoTurnUnknownStreak;
|
|
52695
|
+
var deliveredUnconsumedUnknownStreak;
|
|
52597
52696
|
var ZOMBIE_ASSIGNED_MIN_AGE_MS;
|
|
52598
52697
|
var STRICT_SESSION_MATCH_TTL_MS;
|
|
52599
52698
|
var unresolvedForwardRejectionCounts;
|
|
@@ -52634,6 +52733,7 @@ ${cleanBody}`;
|
|
|
52634
52733
|
ASSIGNED_DELIVERED_UNCONSUMED_REDRIVE_MS = 25e3;
|
|
52635
52734
|
RECLAIM_UNKNOWN_GRACE_TICKS = 3;
|
|
52636
52735
|
deliveredNoTurnUnknownStreak = /* @__PURE__ */ new Map();
|
|
52736
|
+
deliveredUnconsumedUnknownStreak = /* @__PURE__ */ new Map();
|
|
52637
52737
|
ZOMBIE_ASSIGNED_MIN_AGE_MS = 30 * 60 * 1e3;
|
|
52638
52738
|
STRICT_SESSION_MATCH_TTL_MS = 6e4;
|
|
52639
52739
|
unresolvedForwardRejectionCounts = /* @__PURE__ */ new Map();
|
|
@@ -56838,8 +56938,8 @@ ${lastSnapshot}`;
|
|
|
56838
56938
|
const stableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
|
|
56839
56939
|
if (stableMs < 2e3) return;
|
|
56840
56940
|
const startupModal = this.runParseApproval(this.recentOutputBuffer);
|
|
56841
|
-
const
|
|
56842
|
-
if (!startupModal &&
|
|
56941
|
+
const startupIdle = this.detectIdleHonoringOnNoMatch(screenText || this.recentOutputBuffer);
|
|
56942
|
+
if (!startupModal && !startupIdle) {
|
|
56843
56943
|
this.scheduleStartupSettleCheck();
|
|
56844
56944
|
return;
|
|
56845
56945
|
}
|
|
@@ -56975,6 +57075,38 @@ ${lastSnapshot}`;
|
|
|
56975
57075
|
tailScreen: buildCliScreenSnapshot(tail)
|
|
56976
57076
|
});
|
|
56977
57077
|
}
|
|
57078
|
+
/**
|
|
57079
|
+
* WRITE-READINESS ONNOMATCH (opencode): resolve whether the session is
|
|
57080
|
+
* genuinely idle *for the purpose of opening the PTY write gate*, honoring
|
|
57081
|
+
* the manifest's `dispatchOrder.onNoMatch` policy.
|
|
57082
|
+
*
|
|
57083
|
+
* The split-brain this closes: the engine's settled evaluation runs
|
|
57084
|
+
* detectStatus through parseSession, whose builder collapses a null verdict
|
|
57085
|
+
* to `'idle'` (buildParseSessionFromTui: `detectStatus(input) ?? 'idle'`),
|
|
57086
|
+
* so the dashboard status flips to idle via `script_detect`. But the
|
|
57087
|
+
* write-readiness gates (resolveStartupState / sendMessage recovery) call
|
|
57088
|
+
* `runDetectStatus` *directly* and require the literal `=== 'idle'` return —
|
|
57089
|
+
* they never apply the `onNoMatch` policy. opencode's only idle cue is the
|
|
57090
|
+
* `Ask anything` composer placeholder in the last-8-lines scope with
|
|
57091
|
+
* `onNoMatch: preserve-last`; when that placeholder is momentarily out of
|
|
57092
|
+
* frame the raw detector returns null, the gate stays shut, `this.ready`
|
|
57093
|
+
* never flips, and the first queued prompt sits in `not_ready_pending_prompt`
|
|
57094
|
+
* forever (no turn ever starts, so no turn-completion drain fires).
|
|
57095
|
+
*
|
|
57096
|
+
* The fix keeps the raw detector as the primary signal (unchanged behavior
|
|
57097
|
+
* for providers whose detector returns a literal idle) and only falls back
|
|
57098
|
+
* when BOTH (a) the manifest policy is idle-preserving (`preserve-last` or
|
|
57099
|
+
* `idle`) AND (b) the engine has *durably* settled to idle (no in-flight
|
|
57100
|
+
* turn, no modal, no parse error). That guard makes the fallback safe: it
|
|
57101
|
+
* cannot open the gate mid-turn or while a modal is up.
|
|
57102
|
+
*/
|
|
57103
|
+
detectIdleHonoringOnNoMatch(text) {
|
|
57104
|
+
if (this.runDetectStatus(text) === "idle") return true;
|
|
57105
|
+
const dispatchOrder = this.provider.tui?.dispatchOrder;
|
|
57106
|
+
const onNoMatch = dispatchOrder?.onNoMatch;
|
|
57107
|
+
if (onNoMatch !== "preserve-last" && onNoMatch !== "idle") return false;
|
|
57108
|
+
return this.engine.currentStatus === "idle" && !this.engine.isWaitingForResponse && !this.engine.currentTurnScope && !this.engine.activeModal && !this.parseErrorMessage;
|
|
57109
|
+
}
|
|
56978
57110
|
runParseApproval(tail) {
|
|
56979
57111
|
const screenText = this.terminalScreen.getText();
|
|
56980
57112
|
const buffer = screenText || this.accumulatedBuffer;
|
|
@@ -57507,7 +57639,7 @@ ${lastSnapshot}`;
|
|
|
57507
57639
|
}
|
|
57508
57640
|
if (!this.ready) {
|
|
57509
57641
|
this.resolveStartupState("send_precheck");
|
|
57510
|
-
if (this.
|
|
57642
|
+
if (!this.ready && this.detectIdleHonoringOnNoMatch(this.recentOutputBuffer)) {
|
|
57511
57643
|
this.ready = true;
|
|
57512
57644
|
this.startupParseGate = false;
|
|
57513
57645
|
this.engine.setStatus("idle", "send_message_idle_prompt_recovery");
|