@adhdev/daemon-core 0.9.82-rc.396 → 0.9.82-rc.397
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/cli-adapters/provider-cli-adapter.d.ts +2 -0
- package/dist/index.js +59 -14
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +59 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/cli-adapters/provider-cli-adapter.ts +52 -3
- package/src/commands/router.ts +7 -0
- package/src/mesh/mesh-queue-assignment.ts +5 -2
- package/src/mesh/mesh-runtime-store.ts +25 -3
package/dist/index.mjs
CHANGED
|
@@ -378,10 +378,10 @@ function readInjected(value) {
|
|
|
378
378
|
}
|
|
379
379
|
function getDaemonBuildInfo() {
|
|
380
380
|
if (cached) return cached;
|
|
381
|
-
const commit = readInjected(true ? "
|
|
382
|
-
const commitShort = readInjected(true ? "
|
|
383
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
384
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
381
|
+
const commit = readInjected(true ? "5e6a6bcc5ba51a08f3941445f431cb0411217547" : void 0) ?? "unknown";
|
|
382
|
+
const commitShort = readInjected(true ? "5e6a6bcc" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
383
|
+
const version = readInjected(true ? "0.9.82-rc.397" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
384
|
+
const builtAt = readInjected(true ? "2026-06-27T08:32:58.380Z" : void 0);
|
|
385
385
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
386
386
|
return cached;
|
|
387
387
|
}
|
|
@@ -5190,6 +5190,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
5190
5190
|
init_load_better_sqlite3();
|
|
5191
5191
|
init_mesh_ledger();
|
|
5192
5192
|
init_mesh_work_queue();
|
|
5193
|
+
init_dist();
|
|
5193
5194
|
loggedMigrationFailure = false;
|
|
5194
5195
|
MeshRuntimeStore = class _MeshRuntimeStore {
|
|
5195
5196
|
static instance;
|
|
@@ -5722,6 +5723,8 @@ var init_mesh_runtime_store = __esm({
|
|
|
5722
5723
|
if (providerType && typeof providerMaxParallel === "number" && Number.isFinite(providerMaxParallel) && providerMaxParallel >= 0 && this.activeProviderAssignmentCount(meshId, nodeId, providerType) >= providerMaxParallel) {
|
|
5723
5724
|
return null;
|
|
5724
5725
|
}
|
|
5726
|
+
const nodeIdForms = expandDaemonIdForms(nodeId);
|
|
5727
|
+
const nodePinnedPlaceholders = nodeIdForms.map(() => "?").join(", ");
|
|
5725
5728
|
const rows = [
|
|
5726
5729
|
...this.db.prepare(`
|
|
5727
5730
|
SELECT payload FROM mesh_queue
|
|
@@ -5730,9 +5733,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
5730
5733
|
`).all(meshId, sessionId),
|
|
5731
5734
|
...this.db.prepare(`
|
|
5732
5735
|
SELECT payload FROM mesh_queue
|
|
5733
|
-
WHERE mesh_id = ? AND status = 'pending' AND target_node_id
|
|
5736
|
+
WHERE mesh_id = ? AND status = 'pending' AND target_node_id IN (${nodePinnedPlaceholders}) AND target_session_id IS NULL
|
|
5734
5737
|
ORDER BY created_at ASC
|
|
5735
|
-
`).all(meshId,
|
|
5738
|
+
`).all(meshId, ...nodeIdForms),
|
|
5736
5739
|
...this.db.prepare(`
|
|
5737
5740
|
SELECT payload FROM mesh_queue
|
|
5738
5741
|
WHERE mesh_id = ? AND status = 'pending' AND target_node_id IS NULL AND target_session_id IS NULL
|
|
@@ -5762,7 +5765,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
5762
5765
|
const convergenceAllows = (candidate) => candidate.taskMode !== "convergence" || !nodeIsWorktree;
|
|
5763
5766
|
const targetMatches = (candidate) => {
|
|
5764
5767
|
if (candidate.targetSessionId && candidate.targetSessionId !== sessionId) return false;
|
|
5765
|
-
if (candidate.targetNodeId && candidate.targetNodeId
|
|
5768
|
+
if (candidate.targetNodeId && !daemonIdsEquivalent(candidate.targetNodeId, nodeId) && !meshNodeIdMatches({ id: candidate.targetNodeId }, nodeId)) {
|
|
5769
|
+
return false;
|
|
5770
|
+
}
|
|
5766
5771
|
return true;
|
|
5767
5772
|
};
|
|
5768
5773
|
const entry = candidates.find((candidate) => nodeSatisfiesRequiredTags(candidate.requiredTags, capabilityTags) && dependenciesSatisfied(candidate) && convergenceAllows(candidate) && targetMatches(candidate) && nodeConflictAllows(candidate));
|
|
@@ -10779,7 +10784,7 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
|
|
|
10779
10784
|
}
|
|
10780
10785
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
10781
10786
|
const mesh = getMeshWithCache(components, meshId);
|
|
10782
|
-
const node = mesh?.nodes.find((n) =>
|
|
10787
|
+
const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
|
|
10783
10788
|
const gateNode = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
10784
10789
|
if (gateNode?.worktreeBootstrap?.status === "running") {
|
|
10785
10790
|
LOG.info("MeshQueue", `Gating queue claim for worktree node ${nodeId} (${sessionId}): worktree bootstrap still running \u2014 task left pending; claim re-fires once bootstrap reaches a terminal state (guards against dispatching into a half-built worktree \u2192 empty session)`);
|
|
@@ -11388,7 +11393,7 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
11388
11393
|
const providerType = state.type || readNonEmptyString2(settings.providerType);
|
|
11389
11394
|
if (providerType) {
|
|
11390
11395
|
localIdleSessionsChecked += 1;
|
|
11391
|
-
localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) =>
|
|
11396
|
+
localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => meshNodeIdMatches(n, nodeId)) });
|
|
11392
11397
|
} else {
|
|
11393
11398
|
skippedSessions.push({
|
|
11394
11399
|
nodeId,
|
|
@@ -19589,6 +19594,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
19589
19594
|
providerSessionId = null;
|
|
19590
19595
|
responseTimeout = null;
|
|
19591
19596
|
ready = false;
|
|
19597
|
+
// WIN32-READY-HOLD: the ready barrier can release on screen/spec-FSM grace
|
|
19598
|
+
// before win32 ConPTY's input layer is live. The first split write (text, then a
|
|
19599
|
+
// separate trailing CR via waitForEchoAndSubmit) then has its submit CR swallowed,
|
|
19600
|
+
// and every CR-only retry re-sends a bare CR the input layer keeps dropping — the
|
|
19601
|
+
// first message is typed-but-never-submitted and lost. Routing only the FIRST turn
|
|
19602
|
+
// through the atomic content+sendKey single write (submitImmediatePrompt) keeps the
|
|
19603
|
+
// Enter in the same PTY write unit as the text, the invariant win32 ConPTY needs to
|
|
19604
|
+
// recognize a submit, so the swallow is bypassed. Subsequent turns (input layer now
|
|
19605
|
+
// proven live) keep the normal echo-gated path. Flips true on first committed turn.
|
|
19606
|
+
firstTurnSent = false;
|
|
19592
19607
|
startupBuffer = "";
|
|
19593
19608
|
startupParseGate = false;
|
|
19594
19609
|
startupSettleTimer = null;
|
|
@@ -19875,6 +19890,7 @@ ${lastSnapshot}`;
|
|
|
19875
19890
|
this.resetTerminalScreen(DEFAULT_SESSION_HOST_ROWS4, DEFAULT_SESSION_HOST_COLS4);
|
|
19876
19891
|
this.pendingTerminalQueryTail = "";
|
|
19877
19892
|
this.ready = false;
|
|
19893
|
+
this.firstTurnSent = false;
|
|
19878
19894
|
await this.ptyProcess.ready;
|
|
19879
19895
|
this.engine.onSpawnReady();
|
|
19880
19896
|
this.scheduleStartupSettleCheck();
|
|
@@ -20339,6 +20355,7 @@ ${lastSnapshot}`;
|
|
|
20339
20355
|
commitSendUserTurn(state) {
|
|
20340
20356
|
if (state.didCommitUserTurn) return;
|
|
20341
20357
|
state.didCommitUserTurn = true;
|
|
20358
|
+
this.firstTurnSent = true;
|
|
20342
20359
|
}
|
|
20343
20360
|
armResponseTimeout() {
|
|
20344
20361
|
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
@@ -20361,12 +20378,30 @@ ${lastSnapshot}`;
|
|
|
20361
20378
|
LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
|
|
20362
20379
|
});
|
|
20363
20380
|
}
|
|
20381
|
+
// WIN32-READY-HOLD: choose the retry write for a stuck prompt. When the FIRST turn
|
|
20382
|
+
// is stuck on win32 — the premature-ready swallow window — the prompt text itself
|
|
20383
|
+
// may have been partially eaten by a not-yet-live ConPTY input layer, so re-sending
|
|
20384
|
+
// a bare CR keeps hitting nothing. Re-type the whole `text + sendKey` atomically
|
|
20385
|
+
// once so the input layer (now live) receives a self-contained, submit-coupled
|
|
20386
|
+
// write. All other cases keep the cheap bare-CR retry (the prompt is fully echoed
|
|
20387
|
+
// and only the Enter is missing).
|
|
20388
|
+
writeStuckRetry(state, mode) {
|
|
20389
|
+
const retypeFirstTurn = process.platform === "win32" && state.isFirstTurn;
|
|
20390
|
+
if (retypeFirstTurn) {
|
|
20391
|
+
LOG.info("CLI", `[${this.cliType}] ${mode}: re-typing full prompt atomically (win32 first-turn swallow recovery)`);
|
|
20392
|
+
void this.writeToPty(state.text + this.sendKey).catch((error) => {
|
|
20393
|
+
LOG.warn("CLI", `[${this.cliType}] ${mode} re-type write failed: ${error?.message || error}`);
|
|
20394
|
+
});
|
|
20395
|
+
return;
|
|
20396
|
+
}
|
|
20397
|
+
this.writeSubmitKeyForRetry(mode);
|
|
20398
|
+
}
|
|
20364
20399
|
retrySubmitIfStuck(state, attempt) {
|
|
20365
20400
|
this.submitRetryTimer = null;
|
|
20366
20401
|
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
20367
20402
|
this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
20368
20403
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
20369
|
-
this.
|
|
20404
|
+
this.writeStuckRetry(state, "submit_retry");
|
|
20370
20405
|
if (attempt >= 3) {
|
|
20371
20406
|
this.engine.submitRetryUsed = true;
|
|
20372
20407
|
return;
|
|
@@ -20378,7 +20413,7 @@ ${lastSnapshot}`;
|
|
|
20378
20413
|
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
20379
20414
|
this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
20380
20415
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
20381
|
-
this.
|
|
20416
|
+
this.writeStuckRetry(state, "immediate_retry");
|
|
20382
20417
|
this.engine.submitRetryUsed = true;
|
|
20383
20418
|
}
|
|
20384
20419
|
submitSendKey(state, completion) {
|
|
@@ -20631,7 +20666,9 @@ ${lastSnapshot}`;
|
|
|
20631
20666
|
submitDelayMs,
|
|
20632
20667
|
maxEchoWaitMs,
|
|
20633
20668
|
retryDelayMs,
|
|
20634
|
-
didCommitUserTurn: false
|
|
20669
|
+
didCommitUserTurn: false,
|
|
20670
|
+
// Capture BEFORE the send commits — commitSendUserTurn flips firstTurnSent.
|
|
20671
|
+
isFirstTurn: !this.firstTurnSent
|
|
20635
20672
|
};
|
|
20636
20673
|
this.engine.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
20637
20674
|
await new Promise((resolve24, reject) => {
|
|
@@ -20649,7 +20686,8 @@ ${lastSnapshot}`;
|
|
|
20649
20686
|
reject(error);
|
|
20650
20687
|
}
|
|
20651
20688
|
};
|
|
20652
|
-
|
|
20689
|
+
const useAtomicFirstTurn = this.submitStrategy === "immediate" || process.platform === "win32" && sendState.isFirstTurn;
|
|
20690
|
+
if (useAtomicFirstTurn) {
|
|
20653
20691
|
this.submitImmediatePrompt(sendState, completion);
|
|
20654
20692
|
return;
|
|
20655
20693
|
}
|
|
@@ -54030,7 +54068,14 @@ ${hintLines.join("\n")}` : "",
|
|
|
54030
54068
|
nodeId,
|
|
54031
54069
|
sessionCleanupMode: refineSessionCleanupMode,
|
|
54032
54070
|
...refineSessionIds && refineSessionIds.length > 0 ? { sessionIds: refineSessionIds } : {},
|
|
54033
|
-
inlineMesh: args?.inlineMesh
|
|
54071
|
+
inlineMesh: args?.inlineMesh,
|
|
54072
|
+
// REFINE-CLEANUP: refine reaches cleanup only AFTER a verified merge
|
|
54073
|
+
// convergence, so any residual worktree dirtiness here is incidental
|
|
54074
|
+
// (e.g. a bootstrap lockfile rewrite) — never unmerged work. `force`
|
|
54075
|
+
// sets requireClean=false so a plain-dirty worktree no longer aborts
|
|
54076
|
+
// removal with merged_cleanup_failed. Branch-ref deletion still keys off
|
|
54077
|
+
// mergeConvergence (NOT the force flag), so no merged work can be lost.
|
|
54078
|
+
force: true
|
|
54034
54079
|
});
|
|
54035
54080
|
recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
|
|
54036
54081
|
removed: removeResult?.removed,
|