@adhdev/daemon-core 0.9.82-rc.420 → 0.9.82-rc.422
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.d.ts +1 -1
- package/dist/index.js +149 -41
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +148 -41
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-event-forwarding.d.ts +22 -0
- package/dist/providers/cli-provider-instance.d.ts +11 -0
- package/dist/providers/provider-instance-manager.d.ts +18 -3
- package/package.json +2 -2
- package/src/commands/cli-manager.ts +10 -2
- package/src/index.ts +1 -1
- package/src/mesh/mesh-event-forwarding.ts +95 -1
- package/src/mesh/mesh-queue-assignment.ts +55 -0
- package/src/mesh/mesh-reconcile-loop.ts +11 -3
- package/src/providers/cli-provider-instance.ts +33 -0
- package/src/providers/provider-instance-manager.ts +54 -13
package/dist/index.mjs
CHANGED
|
@@ -384,10 +384,10 @@ function readInjected(value) {
|
|
|
384
384
|
}
|
|
385
385
|
function getDaemonBuildInfo() {
|
|
386
386
|
if (cached) return cached;
|
|
387
|
-
const commit = readInjected(true ? "
|
|
388
|
-
const commitShort = readInjected(true ? "
|
|
389
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
390
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
387
|
+
const commit = readInjected(true ? "308e099c65d2de2491f3db46913f9ced6aa3992c" : void 0) ?? "unknown";
|
|
388
|
+
const commitShort = readInjected(true ? "308e099c" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
389
|
+
const version = readInjected(true ? "0.9.82-rc.422" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
390
|
+
const builtAt = readInjected(true ? "2026-06-29T05:26:31.350Z" : void 0);
|
|
391
391
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
392
392
|
return cached;
|
|
393
393
|
}
|
|
@@ -3680,21 +3680,6 @@ var init_async_batch_writer = __esm({
|
|
|
3680
3680
|
});
|
|
3681
3681
|
|
|
3682
3682
|
// src/logging/logger.ts
|
|
3683
|
-
var logger_exports = {};
|
|
3684
|
-
__export(logger_exports, {
|
|
3685
|
-
LOG: () => LOG,
|
|
3686
|
-
LOG_DIR_PATH: () => LOG_DIR_PATH,
|
|
3687
|
-
LOG_PATH: () => LOG_PATH,
|
|
3688
|
-
daemonLog: () => daemonLog,
|
|
3689
|
-
getCurrentDaemonLogPath: () => getCurrentDaemonLogPath,
|
|
3690
|
-
getDaemonLogDir: () => getDaemonLogDir,
|
|
3691
|
-
getLogBufferSize: () => getLogBufferSize,
|
|
3692
|
-
getLogLevel: () => getLogLevel,
|
|
3693
|
-
getLogPath: () => getLogPath,
|
|
3694
|
-
getRecentLogs: () => getRecentLogs,
|
|
3695
|
-
installGlobalInterceptor: () => installGlobalInterceptor,
|
|
3696
|
-
setLogLevel: () => setLogLevel
|
|
3697
|
-
});
|
|
3698
3683
|
import * as fs4 from "fs";
|
|
3699
3684
|
import * as path9 from "path";
|
|
3700
3685
|
import * as os3 from "os";
|
|
@@ -3769,9 +3754,6 @@ function getRecentLogs(count = 50, minLevel = "info") {
|
|
|
3769
3754
|
const filtered = ringBuffer.filter((e) => LEVEL_NUM[e.level] >= minNum);
|
|
3770
3755
|
return filtered.slice(-count);
|
|
3771
3756
|
}
|
|
3772
|
-
function getLogBufferSize() {
|
|
3773
|
-
return ringBuffer.length;
|
|
3774
|
-
}
|
|
3775
3757
|
function ts() {
|
|
3776
3758
|
return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
|
|
3777
3759
|
}
|
|
@@ -3851,10 +3833,7 @@ function installGlobalInterceptor() {
|
|
|
3851
3833
|
writeToFile(`Log file: ${currentLogFile}`);
|
|
3852
3834
|
writeToFile(`Log level: ${currentLevel}`);
|
|
3853
3835
|
}
|
|
3854
|
-
|
|
3855
|
-
return currentLogFile;
|
|
3856
|
-
}
|
|
3857
|
-
var LEVEL_NUM, LEVEL_LABEL, currentLevel, ADHDEV_HOME, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH, LOG_DIR_PATH;
|
|
3836
|
+
var LEVEL_NUM, LEVEL_LABEL, currentLevel, ADHDEV_HOME, LOG_DIR, MAX_LOG_SIZE, MAX_LOG_DAYS, currentDate, currentLogFile, writeCount, RING_BUFFER_SIZE, ringBuffer, origConsoleLog, origConsoleError, origConsoleWarn, LOG, interceptorInstalled, LOG_PATH;
|
|
3858
3837
|
var init_logger = __esm({
|
|
3859
3838
|
"src/logging/logger.ts"() {
|
|
3860
3839
|
"use strict";
|
|
@@ -3913,7 +3892,6 @@ var init_logger = __esm({
|
|
|
3913
3892
|
};
|
|
3914
3893
|
interceptorInstalled = false;
|
|
3915
3894
|
LOG_PATH = path9.join(LOG_DIR, `daemon-${getDateStr()}.log`);
|
|
3916
|
-
LOG_DIR_PATH = LOG_DIR;
|
|
3917
3895
|
}
|
|
3918
3896
|
});
|
|
3919
3897
|
|
|
@@ -12524,6 +12502,23 @@ function liveSessionCountForNode(components, meshId, nodeId) {
|
|
|
12524
12502
|
return !isTerminalSessionStatus(status);
|
|
12525
12503
|
}).length;
|
|
12526
12504
|
}
|
|
12505
|
+
function nodeHasLiveSessionPendingClaim(components, meshId, nodeId) {
|
|
12506
|
+
const busySessionIds = new Set(
|
|
12507
|
+
getQueue(meshId, { status: ["assigned"] }).filter((task) => daemonIdsEquivalent(task.assignedNodeId, nodeId)).map((task) => readNonEmptyString2(task.assignedSessionId)).filter(Boolean)
|
|
12508
|
+
);
|
|
12509
|
+
return components.instanceManager.getByCategory("cli").some((inst) => {
|
|
12510
|
+
const state = inst.getState();
|
|
12511
|
+
const settings = state.settings || {};
|
|
12512
|
+
if (readNonEmptyString2(settings.meshNodeFor) !== meshId) return false;
|
|
12513
|
+
const instNodeId = readNonEmptyString2(settings.meshNodeId) || readNonEmptyString2(settings.nodeId);
|
|
12514
|
+
if (!daemonIdsEquivalent(instNodeId, nodeId)) return false;
|
|
12515
|
+
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
12516
|
+
if (isTerminalSessionStatus(status)) return false;
|
|
12517
|
+
const sessionId = readNonEmptyString2(state.instanceId);
|
|
12518
|
+
if (sessionId && busySessionIds.has(sessionId)) return false;
|
|
12519
|
+
return true;
|
|
12520
|
+
});
|
|
12521
|
+
}
|
|
12527
12522
|
function recordAutoLaunchEvent(meshId, args) {
|
|
12528
12523
|
const dedupKey = `${meshId}:${args.taskId}`;
|
|
12529
12524
|
const currentSig = `${args.phase}|${args.reason || ""}`;
|
|
@@ -12709,6 +12704,10 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
12709
12704
|
sweepExpiredCooldowns();
|
|
12710
12705
|
continue;
|
|
12711
12706
|
}
|
|
12707
|
+
if (nodeHasLiveSessionPendingClaim(components, meshId, nodeId)) {
|
|
12708
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_live_session_pending_claim", nodeId });
|
|
12709
|
+
continue;
|
|
12710
|
+
}
|
|
12712
12711
|
if (!isTaskReadonly(task) && nodeHasActiveAssignment(meshId, nodeId)) {
|
|
12713
12712
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "node_has_active_assignment", nodeId });
|
|
12714
12713
|
continue;
|
|
@@ -16553,6 +16552,62 @@ function ackUnresolvedDelegateForwardByFingerprint(coordinatorDaemonId, eventNam
|
|
|
16553
16552
|
);
|
|
16554
16553
|
if (match) ackUnresolvedDelegateForward(match.id);
|
|
16555
16554
|
}
|
|
16555
|
+
function flushPendingForMeshIdleCoordinators(components, meshId) {
|
|
16556
|
+
try {
|
|
16557
|
+
const store = MeshRuntimeStore.getInstance();
|
|
16558
|
+
if (store.pendingEventCount(meshId) === 0) return;
|
|
16559
|
+
} catch {
|
|
16560
|
+
}
|
|
16561
|
+
const idleCoordinators = [];
|
|
16562
|
+
try {
|
|
16563
|
+
for (const inst of components.instanceManager.getByCategory("cli")) {
|
|
16564
|
+
const state = inst.getState();
|
|
16565
|
+
const settings = state.settings && typeof state.settings === "object" ? state.settings : {};
|
|
16566
|
+
if (readNonEmptyString2(settings.meshCoordinatorFor) !== meshId) continue;
|
|
16567
|
+
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
16568
|
+
const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
|
|
16569
|
+
if (status === "idle" && !modalParked) {
|
|
16570
|
+
idleCoordinators.push({ instance: inst, sessionId: readNonEmptyString2(state.instanceId) });
|
|
16571
|
+
}
|
|
16572
|
+
}
|
|
16573
|
+
} catch {
|
|
16574
|
+
return;
|
|
16575
|
+
}
|
|
16576
|
+
if (idleCoordinators.length === 0) return;
|
|
16577
|
+
const drainDaemonIds = resolveCoordinatorDrainDaemonIds(components);
|
|
16578
|
+
let pendingEvents;
|
|
16579
|
+
try {
|
|
16580
|
+
pendingEvents = drainPendingMeshCoordinatorEvents(meshId, drainDaemonIds.length > 0 ? drainDaemonIds : void 0);
|
|
16581
|
+
} catch (e) {
|
|
16582
|
+
LOG.warn("MeshEvents", `Event-driven coordinator drain failed for mesh ${meshId}: ${e?.message || e}`);
|
|
16583
|
+
return;
|
|
16584
|
+
}
|
|
16585
|
+
if (pendingEvents.length === 0) return;
|
|
16586
|
+
let delivered = 0;
|
|
16587
|
+
for (const pending of pendingEvents) {
|
|
16588
|
+
const wantSession = readNonEmptyString2(pending.targetCoordinatorSessionId);
|
|
16589
|
+
const targets = wantSession ? idleCoordinators.filter((c) => c.sessionId === wantSession) : idleCoordinators;
|
|
16590
|
+
if (targets.length === 0 || !pending.coordinatorMessage) {
|
|
16591
|
+
try {
|
|
16592
|
+
queuePendingMeshCoordinatorEvent(pending);
|
|
16593
|
+
} catch {
|
|
16594
|
+
}
|
|
16595
|
+
continue;
|
|
16596
|
+
}
|
|
16597
|
+
const message = pending.coordinatorMessage;
|
|
16598
|
+
const force = shouldForceInjectMeshEvent(pending.event);
|
|
16599
|
+
for (const c of targets) {
|
|
16600
|
+
c.instance.onEvent("send_message", {
|
|
16601
|
+
input: { text: message, textFallback: message },
|
|
16602
|
+
...force ? { force: true } : {}
|
|
16603
|
+
});
|
|
16604
|
+
delivered++;
|
|
16605
|
+
}
|
|
16606
|
+
}
|
|
16607
|
+
if (delivered > 0) {
|
|
16608
|
+
LOG.info("MeshEvents", `Event-driven drain delivered ${delivered} pending event(s) to ${idleCoordinators.length} idle coordinator(s) for mesh ${meshId}`);
|
|
16609
|
+
}
|
|
16610
|
+
}
|
|
16556
16611
|
function setupMeshEventForwarding(components) {
|
|
16557
16612
|
components.instanceManager.onEvent((event) => {
|
|
16558
16613
|
if (event.event === "agent:ready" || event.event === "agent:generating_completed") {
|
|
@@ -16624,6 +16679,7 @@ function setupMeshEventForwarding(components) {
|
|
|
16624
16679
|
event: event.event,
|
|
16625
16680
|
metadataEvent: event
|
|
16626
16681
|
});
|
|
16682
|
+
flushPendingForMeshIdleCoordinators(components, routing.meshId);
|
|
16627
16683
|
});
|
|
16628
16684
|
}
|
|
16629
16685
|
var REMOTE_IDLE_SESSION_TTL_MS, meshByWorkspaceCache, MESH_WORKSPACE_CACHE_TTL_MS, INTENTIONAL_CLEANUP_STOP_SUPPRESSION_MS, RECENT_COMPLETION_FINGERPRINT_TTL_MS, RECONCILED_COMPLETION_SOURCES, coordinatorForwardLanes;
|
|
@@ -16744,7 +16800,7 @@ function findLiveCoordinators(components) {
|
|
|
16744
16800
|
const meshId = readNonEmptyString2(settings.meshCoordinatorFor);
|
|
16745
16801
|
if (!meshId) continue;
|
|
16746
16802
|
const status = readNonEmptyString2(state.status).toLowerCase();
|
|
16747
|
-
const modalParked = status === "waiting_choice" || status === "waiting_approval";
|
|
16803
|
+
const modalParked = typeof inst.isModalParked === "function" ? inst.isModalParked() === true : status === "waiting_choice" || status === "waiting_approval";
|
|
16748
16804
|
const sessionId = readNonEmptyString2(state.instanceId);
|
|
16749
16805
|
const stateKey = `${meshId}::${sessionId || "?"}`;
|
|
16750
16806
|
const prevParked = coordinatorModalParkState.get(stateKey);
|
|
@@ -40637,10 +40693,27 @@ var CliProviderInstance = class _CliProviderInstance {
|
|
|
40637
40693
|
return null;
|
|
40638
40694
|
}
|
|
40639
40695
|
if (adapterStatus.status === "waiting_approval" && (!this.autoApproveEffectivelyActive(adapterStatus.status) || this.autoApproveMaskStalled())) {
|
|
40696
|
+
if (this.isTransientToolConsent()) {
|
|
40697
|
+
return null;
|
|
40698
|
+
}
|
|
40640
40699
|
return "waiting_approval";
|
|
40641
40700
|
}
|
|
40642
40701
|
return null;
|
|
40643
40702
|
}
|
|
40703
|
+
/**
|
|
40704
|
+
* NOTIF-HELD-DRAIN: true when this `waiting_approval` is a routine, transient tool-consent
|
|
40705
|
+
* of an autonomously-progressing mesh session rather than a genuine human-await modal —
|
|
40706
|
+
* i.e. it is a mesh coordinator/worker session, a turn is actively in flight
|
|
40707
|
+
* (hasAdapterPendingResponse), and no human is attending it by hand. Such a consent is
|
|
40708
|
+
* driven to resolution by the harness/operator as part of the in-flight turn, so holding
|
|
40709
|
+
* the mesh's completion events behind it (modal_parked) is the false-positive that stalls
|
|
40710
|
+
* delivery. Narrow by design: manual attendance or a non-progressing session falls through
|
|
40711
|
+
* to the genuine-modal classification.
|
|
40712
|
+
*/
|
|
40713
|
+
isTransientToolConsent(now = Date.now()) {
|
|
40714
|
+
const isAutonomousMeshSession = this.isMeshWorkerSession() || !!this.settings.meshCoordinatorFor;
|
|
40715
|
+
return isAutonomousMeshSession && this.hasAdapterPendingResponse() && !this.manualAttendance.isAttended(now);
|
|
40716
|
+
}
|
|
40644
40717
|
/** True when this session is parked on a modal awaiting a human answer. */
|
|
40645
40718
|
isModalParked() {
|
|
40646
40719
|
return this.resolveModalParkStatus() !== null;
|
|
@@ -44521,8 +44594,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
44521
44594
|
const meshContext = args?.meshContext;
|
|
44522
44595
|
if (meshContext && typeof meshContext === "object" && typeof meshContext.meshId === "string" && meshContext.meshId) {
|
|
44523
44596
|
const targetInstanceId = key2;
|
|
44597
|
+
let stampResult;
|
|
44524
44598
|
try {
|
|
44525
|
-
this.deps.getInstanceManager()?.attachMeshAssignmentToInstance(targetInstanceId, {
|
|
44599
|
+
stampResult = this.deps.getInstanceManager()?.attachMeshAssignmentToInstance(targetInstanceId, {
|
|
44526
44600
|
meshId: meshContext.meshId,
|
|
44527
44601
|
...typeof meshContext.nodeId === "string" && meshContext.nodeId ? { nodeId: meshContext.nodeId } : {},
|
|
44528
44602
|
...typeof meshContext.taskId === "string" && meshContext.taskId ? { taskId: meshContext.taskId } : {},
|
|
@@ -44530,6 +44604,9 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
44530
44604
|
});
|
|
44531
44605
|
} catch {
|
|
44532
44606
|
}
|
|
44607
|
+
if (stampResult && stampResult.stamped === false && stampResult.reason === "task_already_stamped_on_live_instance") {
|
|
44608
|
+
throw new Error(`Refusing duplicate mesh dispatch: task ${meshContext.taskId} is already being worked by a live session on this daemon`);
|
|
44609
|
+
}
|
|
44533
44610
|
}
|
|
44534
44611
|
const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
|
|
44535
44612
|
const provider = this.providerLoader.resolve(agentType) || this.providerLoader.getMeta(agentType);
|
|
@@ -58137,25 +58214,54 @@ var ProviderInstanceManager = class {
|
|
|
58137
58214
|
}
|
|
58138
58215
|
/** Stamp a mesh assignment on a single instance (used by mesh_send_task
|
|
58139
58216
|
* --direct so the worker's completion event has a coordinator routing
|
|
58140
|
-
* marker in state.settings). Returns true
|
|
58141
|
-
*
|
|
58217
|
+
* marker in state.settings). Returns `{ stamped: true }` when the stamp was
|
|
58218
|
+
* applied, or `{ stamped: false, reason }` when it was refused — the instance
|
|
58219
|
+
* was missing / has no attach method, or the DOUBLE-DISPATCH idempotence guard
|
|
58220
|
+
* fired (the same task is already running on another live session here). */
|
|
58142
58221
|
attachMeshAssignmentToInstance(instanceId, assignment) {
|
|
58143
58222
|
const inst = this.instances.get(instanceId);
|
|
58144
58223
|
if (!inst || typeof inst.attachMeshAssignment !== "function") {
|
|
58145
|
-
|
|
58146
|
-
|
|
58147
|
-
|
|
58148
|
-
|
|
58224
|
+
LOG.warn("MeshDispatch", `attachMeshAssignment skipped: instance ${instanceId} ${inst ? "has no attach method" : "not found"}`);
|
|
58225
|
+
return { stamped: false, reason: inst ? "instance_has_no_attach_method" : "instance_not_found" };
|
|
58226
|
+
}
|
|
58227
|
+
if (assignment.taskId) {
|
|
58228
|
+
const conflict = this.findLiveWorkingTaskHolder(assignment.meshId, assignment.taskId, instanceId);
|
|
58229
|
+
if (conflict) {
|
|
58230
|
+
LOG.warn("MeshDispatch", `attachMeshAssignment refused: task ${assignment.taskId} (mesh ${assignment.meshId}) is already being worked by live session ${conflict} \u2014 skipping duplicate stamp on ${instanceId}`);
|
|
58231
|
+
return { stamped: false, reason: "task_already_stamped_on_live_instance" };
|
|
58149
58232
|
}
|
|
58150
|
-
return false;
|
|
58151
58233
|
}
|
|
58152
58234
|
inst.attachMeshAssignment(assignment);
|
|
58153
|
-
|
|
58154
|
-
|
|
58155
|
-
|
|
58156
|
-
|
|
58235
|
+
LOG.info("MeshDispatch", `stamped mesh assignment on ${instanceId}: mesh=${assignment.meshId} node=${assignment.nodeId || ""} task=${assignment.taskId || ""} coordinator=${assignment.coordinatorDaemonId || ""}`);
|
|
58236
|
+
return { stamped: true };
|
|
58237
|
+
}
|
|
58238
|
+
/**
|
|
58239
|
+
* DOUBLE-DISPATCH support: the id of another LIVE, actively-working instance that already
|
|
58240
|
+
* holds (meshId, taskId), or null. "Live working" = stamped with this exact mesh+task AND
|
|
58241
|
+
* currently mid-turn / booting toward it (generating / waiting on approval-or-choice /
|
|
58242
|
+
* starting) — NOT idle, stopped, or errored. A stale/dead/idle holder is deliberately
|
|
58243
|
+
* ignored so a legitimate re-dispatch (e.g. after a dispatch failure) is never blocked.
|
|
58244
|
+
* The instance being stamped (excludeInstanceId) is skipped so re-stamping the same
|
|
58245
|
+
* session stays idempotent. O(n) over instances — the count is small.
|
|
58246
|
+
*/
|
|
58247
|
+
findLiveWorkingTaskHolder(meshId, taskId, excludeInstanceId) {
|
|
58248
|
+
const working = /* @__PURE__ */ new Set(["generating", "waiting_approval", "waiting_choice", "starting", "streaming", "working", "no_progress", "long_generating"]);
|
|
58249
|
+
for (const [id, inst] of this.instances) {
|
|
58250
|
+
if (id === excludeInstanceId) continue;
|
|
58251
|
+
let state;
|
|
58252
|
+
try {
|
|
58253
|
+
state = inst.getState();
|
|
58254
|
+
} catch {
|
|
58255
|
+
continue;
|
|
58256
|
+
}
|
|
58257
|
+
const settings = state.settings || {};
|
|
58258
|
+
if (settings.meshNodeFor !== meshId) continue;
|
|
58259
|
+
if (settings.meshActiveTaskId !== taskId) continue;
|
|
58260
|
+
const status = (typeof state.status === "string" ? state.status : "").toLowerCase();
|
|
58261
|
+
const chatStatus = (typeof state.activeChat?.status === "string" ? state.activeChat.status : "").toLowerCase();
|
|
58262
|
+
if (working.has(status) || working.has(chatStatus)) return id;
|
|
58157
58263
|
}
|
|
58158
|
-
return
|
|
58264
|
+
return null;
|
|
58159
58265
|
}
|
|
58160
58266
|
/** Clear a mesh assignment after the dispatched task reaches a terminal
|
|
58161
58267
|
* state (generating_completed / stopped / failed). */
|
|
@@ -64860,6 +64966,7 @@ export {
|
|
|
64860
64966
|
isSetupComplete,
|
|
64861
64967
|
isTaskReadonly,
|
|
64862
64968
|
isUserFacingChatMessage,
|
|
64969
|
+
isWeakCompletionEvidence,
|
|
64863
64970
|
killIdeProcess,
|
|
64864
64971
|
launchIDE,
|
|
64865
64972
|
launchWithCdp,
|