@adhdev/daemon-standalone 1.0.28-rc.33 → 1.0.28-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/dist/index.js +140 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -33311,10 +33311,10 @@ var require_dist3 = __commonJS({
|
|
|
33311
33311
|
}
|
|
33312
33312
|
function getDaemonBuildInfo() {
|
|
33313
33313
|
if (cached2) return cached2;
|
|
33314
|
-
const commit = readInjected(true ? "
|
|
33315
|
-
const commitShort = readInjected(true ? "
|
|
33316
|
-
const version2 = readInjected(true ? "1.0.28-rc.
|
|
33317
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
33314
|
+
const commit = readInjected(true ? "fcccd1309a13173048d54bcfb1edbf698ee22ee3" : void 0) ?? "unknown";
|
|
33315
|
+
const commitShort = readInjected(true ? "fcccd130" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
33316
|
+
const version2 = readInjected(true ? "1.0.28-rc.34" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
33317
|
+
const builtAt = readInjected(true ? "2026-07-31T01:14:11.973Z" : void 0);
|
|
33318
33318
|
cached2 = builtAt ? { commit, commitShort, version: version2, builtAt } : { commit, commitShort, version: version2 };
|
|
33319
33319
|
return cached2;
|
|
33320
33320
|
}
|
|
@@ -38307,6 +38307,37 @@ Next step: ${nextStep}`;
|
|
|
38307
38307
|
nowMs: args.nowMs
|
|
38308
38308
|
});
|
|
38309
38309
|
}
|
|
38310
|
+
function rebindAttemptToLiveHolder(args) {
|
|
38311
|
+
const holder = typeof args.holderSessionId === "string" ? args.holderSessionId.trim() : "";
|
|
38312
|
+
if (!holder) return { rebound: false, reason: "no_holder" };
|
|
38313
|
+
const store = MeshRuntimeStore.getInstance();
|
|
38314
|
+
const attempt = store.getCurrentTurnAttempt(args.meshId, args.taskId);
|
|
38315
|
+
if (!attempt) return { rebound: false, reason: "no_attempt" };
|
|
38316
|
+
if (attempt.terminalOutcome) return { rebound: false, reason: "attempt_terminal", attemptId: attempt.attemptId };
|
|
38317
|
+
if (attempt.sessionId && sessionIdsEquivalent(attempt.sessionId, holder)) {
|
|
38318
|
+
return { rebound: false, reason: "same_session", attemptId: attempt.attemptId };
|
|
38319
|
+
}
|
|
38320
|
+
const nowMs = args.nowMs ?? Date.now();
|
|
38321
|
+
const nowIso = new Date(nowMs).toISOString();
|
|
38322
|
+
const ok = store.rebindTurnAttemptSession(attempt.attemptId, holder, nowIso);
|
|
38323
|
+
if (!ok) return { rebound: false, reason: "store_rejected", attemptId: attempt.attemptId };
|
|
38324
|
+
try {
|
|
38325
|
+
store.insertTurnEvent({
|
|
38326
|
+
eventId: (0, import_crypto5.randomUUID)(),
|
|
38327
|
+
meshId: args.meshId,
|
|
38328
|
+
attemptId: attempt.attemptId,
|
|
38329
|
+
taskId: args.taskId,
|
|
38330
|
+
kind: "session_rebound",
|
|
38331
|
+
dedupeKey: holder,
|
|
38332
|
+
payload: safeEvidenceJson({ fromSessionId: attempt.sessionId ?? null, toSessionId: holder, reason: "duplicate_dispatch_refused" }),
|
|
38333
|
+
occurredAtMs: nowMs,
|
|
38334
|
+
recordedAt: nowIso
|
|
38335
|
+
});
|
|
38336
|
+
} catch {
|
|
38337
|
+
}
|
|
38338
|
+
LOG2.info("TurnLedger", `Rebound attempt ${attempt.attemptId} (task ${args.taskId}) from session ${attempt.sessionId ?? "none"} to live holder ${holder} after a duplicate-dispatch refusal`);
|
|
38339
|
+
return { rebound: true, attemptId: attempt.attemptId, fromSessionId: attempt.sessionId ?? void 0, toSessionId: holder };
|
|
38340
|
+
}
|
|
38310
38341
|
function evaluateRedrive(meshId, taskId, nowMs = Date.now()) {
|
|
38311
38342
|
const store = MeshRuntimeStore.getInstance();
|
|
38312
38343
|
const attempt = store.getCurrentTurnAttempt(meshId, taskId);
|
|
@@ -43655,6 +43686,23 @@ Next step: ${nextStep}`;
|
|
|
43655
43686
|
`).run(leaseDeadlineMs, updatedAt, attemptId);
|
|
43656
43687
|
this.maybeCheckpointWal();
|
|
43657
43688
|
}
|
|
43689
|
+
/**
|
|
43690
|
+
* DUP-CLAIM-REBIND: point a still-open attempt at the session that is ACTUALLY
|
|
43691
|
+
* working it. Used when a node refuses a duplicate dispatch and names the live
|
|
43692
|
+
* holder — the attempt was opened against the session we tried to dispatch to,
|
|
43693
|
+
* but the work is running on the holder, so the binding (not the attempt) is what
|
|
43694
|
+
* is wrong. Conditional on `terminal_outcome IS NULL` so a settled attempt is
|
|
43695
|
+
* never rewritten; returns whether the rebind landed.
|
|
43696
|
+
*/
|
|
43697
|
+
rebindTurnAttemptSession(attemptId, sessionId, updatedAt) {
|
|
43698
|
+
const res = this.db.prepare(`
|
|
43699
|
+
UPDATE mesh_turn_attempts
|
|
43700
|
+
SET session_id = ?, updated_at = ?
|
|
43701
|
+
WHERE attempt_id = ? AND terminal_outcome IS NULL
|
|
43702
|
+
`).run(sessionId, updatedAt, attemptId);
|
|
43703
|
+
this.maybeCheckpointWal();
|
|
43704
|
+
return res.changes > 0;
|
|
43705
|
+
}
|
|
43658
43706
|
// ── TURN-LEDGER (Stage 5): idempotency-keyed causal events ───────────────
|
|
43659
43707
|
/**
|
|
43660
43708
|
* Append a causal event. INSERT OR IGNORE on UNIQUE(attempt_id, kind, dedupe_key)
|
|
@@ -44879,7 +44927,8 @@ Valid status values: \`completed\` | \`failed\` | \`blocked\` | \`partial\`.`;
|
|
|
44879
44927
|
"task_reclaimed",
|
|
44880
44928
|
"task_approval_needed",
|
|
44881
44929
|
"task_question_pending",
|
|
44882
|
-
"p2p_dispatch_failed"
|
|
44930
|
+
"p2p_dispatch_failed",
|
|
44931
|
+
"dispatch_duplicate_rebound"
|
|
44883
44932
|
]);
|
|
44884
44933
|
LEDGER_DIR_NAME = "mesh-ledger";
|
|
44885
44934
|
MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
|
@@ -53979,6 +54028,42 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
53979
54028
|
]);
|
|
53980
54029
|
}
|
|
53981
54030
|
});
|
|
54031
|
+
function encodeDuplicateMeshDispatchCode(holderSessionId) {
|
|
54032
|
+
const holder = typeof holderSessionId === "string" ? holderSessionId.trim() : "";
|
|
54033
|
+
return holder ? `${DUPLICATE_MESH_DISPATCH_CODE}:${holder}` : DUPLICATE_MESH_DISPATCH_CODE;
|
|
54034
|
+
}
|
|
54035
|
+
function classifyDuplicateMeshDispatch(err) {
|
|
54036
|
+
if (!err || typeof err !== "object") return null;
|
|
54037
|
+
const e = err;
|
|
54038
|
+
if (e.code === DUPLICATE_MESH_DISPATCH_CODE) {
|
|
54039
|
+
const holder = typeof e.holderSessionId === "string" ? e.holderSessionId.trim() : "";
|
|
54040
|
+
return holder ? { holderSessionId: holder } : {};
|
|
54041
|
+
}
|
|
54042
|
+
for (const raw of [e.meshCode, e.code]) {
|
|
54043
|
+
if (typeof raw !== "string") continue;
|
|
54044
|
+
if (raw !== DUPLICATE_MESH_DISPATCH_CODE && !raw.startsWith(`${DUPLICATE_MESH_DISPATCH_CODE}:`)) continue;
|
|
54045
|
+
const holder = raw.slice(DUPLICATE_MESH_DISPATCH_CODE.length + 1).trim();
|
|
54046
|
+
return holder ? { holderSessionId: holder } : {};
|
|
54047
|
+
}
|
|
54048
|
+
return null;
|
|
54049
|
+
}
|
|
54050
|
+
var DUPLICATE_MESH_DISPATCH_CODE;
|
|
54051
|
+
var DuplicateMeshDispatchError;
|
|
54052
|
+
var init_mesh_duplicate_dispatch = __esm2({
|
|
54053
|
+
"src/mesh/mesh-duplicate-dispatch.ts"() {
|
|
54054
|
+
"use strict";
|
|
54055
|
+
DUPLICATE_MESH_DISPATCH_CODE = "DUPLICATE_MESH_DISPATCH";
|
|
54056
|
+
DuplicateMeshDispatchError = class extends Error {
|
|
54057
|
+
code = DUPLICATE_MESH_DISPATCH_CODE;
|
|
54058
|
+
holderSessionId;
|
|
54059
|
+
constructor(message, info = {}) {
|
|
54060
|
+
super(message);
|
|
54061
|
+
this.name = "DuplicateMeshDispatchError";
|
|
54062
|
+
this.holderSessionId = info.holderSessionId;
|
|
54063
|
+
}
|
|
54064
|
+
};
|
|
54065
|
+
}
|
|
54066
|
+
});
|
|
53982
54067
|
function localCoordinatorDaemonId() {
|
|
53983
54068
|
return canonicalDaemonId(readNonEmptyString(loadConfig2().machineId));
|
|
53984
54069
|
}
|
|
@@ -54179,6 +54264,37 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
54179
54264
|
}
|
|
54180
54265
|
}).catch((e) => {
|
|
54181
54266
|
if (timer) clearTimeout(timer);
|
|
54267
|
+
const duplicate = classifyDuplicateMeshDispatch(e);
|
|
54268
|
+
if (duplicate?.holderSessionId) {
|
|
54269
|
+
const rebind = rebindAttemptToLiveHolder({
|
|
54270
|
+
meshId: ctx.meshId,
|
|
54271
|
+
taskId: ctx.task.id,
|
|
54272
|
+
holderSessionId: duplicate.holderSessionId
|
|
54273
|
+
});
|
|
54274
|
+
if (rebind.rebound || rebind.reason === "same_session") {
|
|
54275
|
+
LOG2.info("MeshQueue", `Duplicate dispatch of task ${ctx.task.id} refused by node ${ctx.nodeId}: it is already being worked by live session ${duplicate.holderSessionId}. Task stays assigned; turn attempt ${rebind.attemptId ?? "n/a"} ${rebind.rebound ? "rebound to that session" : "was already bound to it"}.`);
|
|
54276
|
+
updateSessionDeliveryStatus(delivery.id, "delivered");
|
|
54277
|
+
try {
|
|
54278
|
+
appendLedgerEntry(ctx.meshId, {
|
|
54279
|
+
kind: "dispatch_duplicate_rebound",
|
|
54280
|
+
nodeId: ctx.nodeId,
|
|
54281
|
+
sessionId: duplicate.holderSessionId,
|
|
54282
|
+
payload: {
|
|
54283
|
+
taskId: ctx.task.id,
|
|
54284
|
+
deliveryId: delivery.id,
|
|
54285
|
+
transport: ctx.transport,
|
|
54286
|
+
attemptedSessionId: ctx.sessionId,
|
|
54287
|
+
holderSessionId: duplicate.holderSessionId,
|
|
54288
|
+
...rebind.attemptId ? { attemptId: rebind.attemptId } : {},
|
|
54289
|
+
rebound: rebind.rebound
|
|
54290
|
+
}
|
|
54291
|
+
});
|
|
54292
|
+
} catch {
|
|
54293
|
+
}
|
|
54294
|
+
return;
|
|
54295
|
+
}
|
|
54296
|
+
LOG2.warn("MeshQueue", `Duplicate dispatch of task ${ctx.task.id} refused by node ${ctx.nodeId} (holder ${duplicate.holderSessionId}), but the turn attempt could not be rebound (${rebind.reason}) \u2014 falling back to the requeue path.`);
|
|
54297
|
+
}
|
|
54182
54298
|
LOG2.error("MeshQueue", `Failed to dispatch task via ${ctx.transport} to node ${ctx.nodeId}: ${e?.message}`);
|
|
54183
54299
|
updateSessionDeliveryStatus(delivery.id, "failed", { lastError: e?.message, incrementAttempt: true });
|
|
54184
54300
|
endTaskDispatchInFlight(ctx.meshId, ctx.task.id);
|
|
@@ -55751,6 +55867,7 @@ The mesh has no work in flight. For each mission, decide its outcome: continue i
|
|
|
55751
55867
|
init_mesh_task_inflight();
|
|
55752
55868
|
init_model_provider_compat();
|
|
55753
55869
|
init_mesh_turn_ledger();
|
|
55870
|
+
init_mesh_duplicate_dispatch();
|
|
55754
55871
|
IDLE_AUTO_FAST_FORWARD_THROTTLE_MS = 30 * 60 * 1e3;
|
|
55755
55872
|
idleAutoFastForwardLastAttempt = /* @__PURE__ */ new Map();
|
|
55756
55873
|
CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS = 45 * 1e3;
|
|
@@ -70921,6 +71038,7 @@ ${lastSnapshot}`;
|
|
|
70921
71038
|
DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS: () => DEFAULT_STATUS_P2P_REPORT_INTERVAL_MS,
|
|
70922
71039
|
DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS: () => DEFAULT_STATUS_SERVER_REPORT_INTERVAL_MS,
|
|
70923
71040
|
DEV_SERVER_PORT: () => DEV_SERVER_PORT,
|
|
71041
|
+
DUPLICATE_MESH_DISPATCH_CODE: () => DUPLICATE_MESH_DISPATCH_CODE,
|
|
70924
71042
|
DaemonAgentStreamManager: () => DaemonAgentStreamManager,
|
|
70925
71043
|
DaemonCdpInitializer: () => DaemonCdpInitializer,
|
|
70926
71044
|
DaemonCdpManager: () => DaemonCdpManager,
|
|
@@ -70930,6 +71048,7 @@ ${lastSnapshot}`;
|
|
|
70930
71048
|
DaemonCommandRouter: () => DaemonCommandRouter,
|
|
70931
71049
|
DaemonStatusReporter: () => DaemonStatusReporter,
|
|
70932
71050
|
DevServer: () => DevServer,
|
|
71051
|
+
DuplicateMeshDispatchError: () => DuplicateMeshDispatchError,
|
|
70933
71052
|
FsmDriver: () => FsmDriver,
|
|
70934
71053
|
GOAL_PREVIEW_MAX: () => GOAL_PREVIEW_MAX,
|
|
70935
71054
|
GitCommandError: () => GitCommandError,
|
|
@@ -71039,6 +71158,7 @@ ${lastSnapshot}`;
|
|
|
71039
71158
|
canonicalDaemonId: () => canonicalDaemonId,
|
|
71040
71159
|
claimNextTask: () => claimNextTask,
|
|
71041
71160
|
classifyChatMessageVisibility: () => classifyChatMessageVisibility,
|
|
71161
|
+
classifyDuplicateMeshDispatch: () => classifyDuplicateMeshDispatch,
|
|
71042
71162
|
classifyHotChatSessionsForSubscriptionFlush: () => classifyHotChatSessionsForSubscriptionFlush2,
|
|
71043
71163
|
classifyP2pRelayFailure: () => classifyP2pRelayFailure,
|
|
71044
71164
|
classifyShadowDivergence: () => classifyShadowDivergence,
|
|
@@ -71081,6 +71201,7 @@ ${lastSnapshot}`;
|
|
|
71081
71201
|
detectIDEs: () => detectIDEs,
|
|
71082
71202
|
detectNewlySettledCompletedSessions: () => detectNewlySettledCompletedSessions2,
|
|
71083
71203
|
drainPendingMeshCoordinatorEvents: () => drainPendingMeshCoordinatorEvents,
|
|
71204
|
+
encodeDuplicateMeshDispatchCode: () => encodeDuplicateMeshDispatchCode,
|
|
71084
71205
|
enqueueTask: () => enqueueTask,
|
|
71085
71206
|
ensureSessionHostReady: () => ensureSessionHostReady2,
|
|
71086
71207
|
evaluateFsm: () => evaluateFsm,
|
|
@@ -73641,6 +73762,7 @@ ${lastSnapshot}`;
|
|
|
73641
73762
|
this.authEpoch = context.authEpoch;
|
|
73642
73763
|
}
|
|
73643
73764
|
};
|
|
73765
|
+
init_mesh_duplicate_dispatch();
|
|
73644
73766
|
init_state_store();
|
|
73645
73767
|
var import_child_process5 = require("child_process");
|
|
73646
73768
|
var import_util22 = require("util");
|
|
@@ -85333,6 +85455,7 @@ ${body}
|
|
|
85333
85455
|
init_recent_activity();
|
|
85334
85456
|
init_hash();
|
|
85335
85457
|
init_coordinator_registry();
|
|
85458
|
+
init_mesh_duplicate_dispatch();
|
|
85336
85459
|
init_summary_metadata();
|
|
85337
85460
|
var os19 = __toESM2(require("os"));
|
|
85338
85461
|
var crypto5 = __toESM2(require("crypto"));
|
|
@@ -94846,7 +94969,10 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
94846
94969
|
} catch {
|
|
94847
94970
|
}
|
|
94848
94971
|
if (stampResult && stampResult.stamped === false && stampResult.reason === "task_already_stamped_on_live_instance") {
|
|
94849
|
-
throw new
|
|
94972
|
+
throw new DuplicateMeshDispatchError(
|
|
94973
|
+
`Refusing duplicate mesh dispatch: task ${meshContext.taskId} is already being worked by a live session on this daemon`,
|
|
94974
|
+
{ holderSessionId: stampResult.holderSessionId }
|
|
94975
|
+
);
|
|
94850
94976
|
}
|
|
94851
94977
|
if (meshContext.silentIdlePush === true) {
|
|
94852
94978
|
try {
|
|
@@ -110614,7 +110740,13 @@ ${e?.stderr || ""}`;
|
|
|
110614
110740
|
* marker in state.settings). Returns `{ stamped: true }` when the stamp was
|
|
110615
110741
|
* applied, or `{ stamped: false, reason }` when it was refused — the instance
|
|
110616
110742
|
* was missing / has no attach method, or the DOUBLE-DISPATCH idempotence guard
|
|
110617
|
-
* fired (the same task is already running on another live session here).
|
|
110743
|
+
* fired (the same task is already running on another live session here).
|
|
110744
|
+
*
|
|
110745
|
+
* DUP-CLAIM-REBIND: when the guard fires, the id of the live session that already
|
|
110746
|
+
* holds the task is returned as `holderSessionId`. The coordinator needs it to
|
|
110747
|
+
* REBIND its turn-ledger attempt onto the real worker instead of cancelling the
|
|
110748
|
+
* attempt — the guard already resolved that instance, so surfacing it here keeps
|
|
110749
|
+
* the caller from having to parse it back out of an error string. */
|
|
110618
110750
|
attachMeshAssignmentToInstance(instanceId, assignment) {
|
|
110619
110751
|
const inst = this.instances.get(instanceId);
|
|
110620
110752
|
if (!inst || typeof inst.attachMeshAssignment !== "function") {
|
|
@@ -110625,7 +110757,7 @@ ${e?.stderr || ""}`;
|
|
|
110625
110757
|
const conflict = this.findLiveWorkingTaskHolder(assignment.meshId, assignment.taskId, instanceId);
|
|
110626
110758
|
if (conflict) {
|
|
110627
110759
|
LOG2.warn("MeshDispatch", `attachMeshAssignment refused: task ${assignment.taskId} (mesh ${assignment.meshId}) is already being worked by live session ${conflict} \u2014 skipping duplicate stamp on ${instanceId}`);
|
|
110628
|
-
return { stamped: false, reason: "task_already_stamped_on_live_instance" };
|
|
110760
|
+
return { stamped: false, reason: "task_already_stamped_on_live_instance", holderSessionId: conflict };
|
|
110629
110761
|
}
|
|
110630
110762
|
}
|
|
110631
110763
|
inst.attachMeshAssignment(assignment);
|