@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
|
@@ -39,6 +39,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
|
|
|
39
39
|
private providerSessionId;
|
|
40
40
|
private responseTimeout;
|
|
41
41
|
private ready;
|
|
42
|
+
private firstTurnSent;
|
|
42
43
|
private startupBuffer;
|
|
43
44
|
private startupParseGate;
|
|
44
45
|
private startupSettleTimer;
|
|
@@ -178,6 +179,7 @@ export declare class ProviderCliAdapter implements CliAdapter {
|
|
|
178
179
|
private commitSendUserTurn;
|
|
179
180
|
private armResponseTimeout;
|
|
180
181
|
private writeSubmitKeyForRetry;
|
|
182
|
+
private writeStuckRetry;
|
|
181
183
|
private retrySubmitIfStuck;
|
|
182
184
|
private retryImmediateSubmitIfStuck;
|
|
183
185
|
private submitSendKey;
|
package/dist/index.js
CHANGED
|
@@ -383,10 +383,10 @@ function readInjected(value) {
|
|
|
383
383
|
}
|
|
384
384
|
function getDaemonBuildInfo() {
|
|
385
385
|
if (cached) return cached;
|
|
386
|
-
const commit = readInjected(true ? "
|
|
387
|
-
const commitShort = readInjected(true ? "
|
|
388
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
389
|
-
const builtAt = readInjected(true ? "2026-06-
|
|
386
|
+
const commit = readInjected(true ? "5e6a6bcc5ba51a08f3941445f431cb0411217547" : void 0) ?? "unknown";
|
|
387
|
+
const commitShort = readInjected(true ? "5e6a6bcc" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
388
|
+
const version = readInjected(true ? "0.9.82-rc.397" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
389
|
+
const builtAt = readInjected(true ? "2026-06-27T08:32:58.380Z" : void 0);
|
|
390
390
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
391
391
|
return cached;
|
|
392
392
|
}
|
|
@@ -5197,6 +5197,7 @@ var init_mesh_runtime_store = __esm({
|
|
|
5197
5197
|
init_load_better_sqlite3();
|
|
5198
5198
|
init_mesh_ledger();
|
|
5199
5199
|
init_mesh_work_queue();
|
|
5200
|
+
init_dist();
|
|
5200
5201
|
loggedMigrationFailure = false;
|
|
5201
5202
|
MeshRuntimeStore = class _MeshRuntimeStore {
|
|
5202
5203
|
static instance;
|
|
@@ -5729,6 +5730,8 @@ var init_mesh_runtime_store = __esm({
|
|
|
5729
5730
|
if (providerType && typeof providerMaxParallel === "number" && Number.isFinite(providerMaxParallel) && providerMaxParallel >= 0 && this.activeProviderAssignmentCount(meshId, nodeId, providerType) >= providerMaxParallel) {
|
|
5730
5731
|
return null;
|
|
5731
5732
|
}
|
|
5733
|
+
const nodeIdForms = expandDaemonIdForms(nodeId);
|
|
5734
|
+
const nodePinnedPlaceholders = nodeIdForms.map(() => "?").join(", ");
|
|
5732
5735
|
const rows = [
|
|
5733
5736
|
...this.db.prepare(`
|
|
5734
5737
|
SELECT payload FROM mesh_queue
|
|
@@ -5737,9 +5740,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
5737
5740
|
`).all(meshId, sessionId),
|
|
5738
5741
|
...this.db.prepare(`
|
|
5739
5742
|
SELECT payload FROM mesh_queue
|
|
5740
|
-
WHERE mesh_id = ? AND status = 'pending' AND target_node_id
|
|
5743
|
+
WHERE mesh_id = ? AND status = 'pending' AND target_node_id IN (${nodePinnedPlaceholders}) AND target_session_id IS NULL
|
|
5741
5744
|
ORDER BY created_at ASC
|
|
5742
|
-
`).all(meshId,
|
|
5745
|
+
`).all(meshId, ...nodeIdForms),
|
|
5743
5746
|
...this.db.prepare(`
|
|
5744
5747
|
SELECT payload FROM mesh_queue
|
|
5745
5748
|
WHERE mesh_id = ? AND status = 'pending' AND target_node_id IS NULL AND target_session_id IS NULL
|
|
@@ -5769,7 +5772,9 @@ var init_mesh_runtime_store = __esm({
|
|
|
5769
5772
|
const convergenceAllows = (candidate) => candidate.taskMode !== "convergence" || !nodeIsWorktree;
|
|
5770
5773
|
const targetMatches = (candidate) => {
|
|
5771
5774
|
if (candidate.targetSessionId && candidate.targetSessionId !== sessionId) return false;
|
|
5772
|
-
if (candidate.targetNodeId && candidate.targetNodeId
|
|
5775
|
+
if (candidate.targetNodeId && !daemonIdsEquivalent(candidate.targetNodeId, nodeId) && !meshNodeIdMatches({ id: candidate.targetNodeId }, nodeId)) {
|
|
5776
|
+
return false;
|
|
5777
|
+
}
|
|
5773
5778
|
return true;
|
|
5774
5779
|
};
|
|
5775
5780
|
const entry = candidates.find((candidate) => nodeSatisfiesRequiredTags(candidate.requiredTags, capabilityTags) && dependenciesSatisfied(candidate) && convergenceAllows(candidate) && targetMatches(candidate) && nodeConflictAllows(candidate));
|
|
@@ -10783,7 +10788,7 @@ function deliverTaskToSession(dispatchThunk, ctx, warmup) {
|
|
|
10783
10788
|
}
|
|
10784
10789
|
function tryAssignQueueTask(components, meshId, nodeId, sessionId, providerType) {
|
|
10785
10790
|
const mesh = getMeshWithCache(components, meshId);
|
|
10786
|
-
const node = mesh?.nodes.find((n) =>
|
|
10791
|
+
const node = mesh?.nodes.find((n) => meshNodeIdMatches(n, nodeId));
|
|
10787
10792
|
const gateNode = mesh?.nodes?.find((n) => meshNodeIdMatches(n, nodeId));
|
|
10788
10793
|
if (gateNode?.worktreeBootstrap?.status === "running") {
|
|
10789
10794
|
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)`);
|
|
@@ -11392,7 +11397,7 @@ async function triggerMeshQueue(components, meshId) {
|
|
|
11392
11397
|
const providerType = state.type || readNonEmptyString2(settings.providerType);
|
|
11393
11398
|
if (providerType) {
|
|
11394
11399
|
localIdleSessionsChecked += 1;
|
|
11395
|
-
localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) =>
|
|
11400
|
+
localCandidates.push({ nodeId, sessionId, providerType, origin: "local", node: mesh.nodes.find((n) => meshNodeIdMatches(n, nodeId)) });
|
|
11396
11401
|
} else {
|
|
11397
11402
|
skippedSessions.push({
|
|
11398
11403
|
nodeId,
|
|
@@ -19596,6 +19601,16 @@ var init_provider_cli_adapter = __esm({
|
|
|
19596
19601
|
providerSessionId = null;
|
|
19597
19602
|
responseTimeout = null;
|
|
19598
19603
|
ready = false;
|
|
19604
|
+
// WIN32-READY-HOLD: the ready barrier can release on screen/spec-FSM grace
|
|
19605
|
+
// before win32 ConPTY's input layer is live. The first split write (text, then a
|
|
19606
|
+
// separate trailing CR via waitForEchoAndSubmit) then has its submit CR swallowed,
|
|
19607
|
+
// and every CR-only retry re-sends a bare CR the input layer keeps dropping — the
|
|
19608
|
+
// first message is typed-but-never-submitted and lost. Routing only the FIRST turn
|
|
19609
|
+
// through the atomic content+sendKey single write (submitImmediatePrompt) keeps the
|
|
19610
|
+
// Enter in the same PTY write unit as the text, the invariant win32 ConPTY needs to
|
|
19611
|
+
// recognize a submit, so the swallow is bypassed. Subsequent turns (input layer now
|
|
19612
|
+
// proven live) keep the normal echo-gated path. Flips true on first committed turn.
|
|
19613
|
+
firstTurnSent = false;
|
|
19599
19614
|
startupBuffer = "";
|
|
19600
19615
|
startupParseGate = false;
|
|
19601
19616
|
startupSettleTimer = null;
|
|
@@ -19882,6 +19897,7 @@ ${lastSnapshot}`;
|
|
|
19882
19897
|
this.resetTerminalScreen(import_session_host_core5.DEFAULT_SESSION_HOST_ROWS, import_session_host_core5.DEFAULT_SESSION_HOST_COLS);
|
|
19883
19898
|
this.pendingTerminalQueryTail = "";
|
|
19884
19899
|
this.ready = false;
|
|
19900
|
+
this.firstTurnSent = false;
|
|
19885
19901
|
await this.ptyProcess.ready;
|
|
19886
19902
|
this.engine.onSpawnReady();
|
|
19887
19903
|
this.scheduleStartupSettleCheck();
|
|
@@ -20346,6 +20362,7 @@ ${lastSnapshot}`;
|
|
|
20346
20362
|
commitSendUserTurn(state) {
|
|
20347
20363
|
if (state.didCommitUserTurn) return;
|
|
20348
20364
|
state.didCommitUserTurn = true;
|
|
20365
|
+
this.firstTurnSent = true;
|
|
20349
20366
|
}
|
|
20350
20367
|
armResponseTimeout() {
|
|
20351
20368
|
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
@@ -20368,12 +20385,30 @@ ${lastSnapshot}`;
|
|
|
20368
20385
|
LOG.warn("CLI", `[${this.cliType}] ${mode} write failed: ${error?.message || error}`);
|
|
20369
20386
|
});
|
|
20370
20387
|
}
|
|
20388
|
+
// WIN32-READY-HOLD: choose the retry write for a stuck prompt. When the FIRST turn
|
|
20389
|
+
// is stuck on win32 — the premature-ready swallow window — the prompt text itself
|
|
20390
|
+
// may have been partially eaten by a not-yet-live ConPTY input layer, so re-sending
|
|
20391
|
+
// a bare CR keeps hitting nothing. Re-type the whole `text + sendKey` atomically
|
|
20392
|
+
// once so the input layer (now live) receives a self-contained, submit-coupled
|
|
20393
|
+
// write. All other cases keep the cheap bare-CR retry (the prompt is fully echoed
|
|
20394
|
+
// and only the Enter is missing).
|
|
20395
|
+
writeStuckRetry(state, mode) {
|
|
20396
|
+
const retypeFirstTurn = process.platform === "win32" && state.isFirstTurn;
|
|
20397
|
+
if (retypeFirstTurn) {
|
|
20398
|
+
LOG.info("CLI", `[${this.cliType}] ${mode}: re-typing full prompt atomically (win32 first-turn swallow recovery)`);
|
|
20399
|
+
void this.writeToPty(state.text + this.sendKey).catch((error) => {
|
|
20400
|
+
LOG.warn("CLI", `[${this.cliType}] ${mode} re-type write failed: ${error?.message || error}`);
|
|
20401
|
+
});
|
|
20402
|
+
return;
|
|
20403
|
+
}
|
|
20404
|
+
this.writeSubmitKeyForRetry(mode);
|
|
20405
|
+
}
|
|
20371
20406
|
retrySubmitIfStuck(state, attempt) {
|
|
20372
20407
|
this.submitRetryTimer = null;
|
|
20373
20408
|
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
20374
20409
|
this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
20375
20410
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt ${attempt})`);
|
|
20376
|
-
this.
|
|
20411
|
+
this.writeStuckRetry(state, "submit_retry");
|
|
20377
20412
|
if (attempt >= 3) {
|
|
20378
20413
|
this.engine.submitRetryUsed = true;
|
|
20379
20414
|
return;
|
|
@@ -20385,7 +20420,7 @@ ${lastSnapshot}`;
|
|
|
20385
20420
|
if (!this.isSubmitStuck(state.normalizedPromptSnippet)) return;
|
|
20386
20421
|
this.engine.responseSettleIgnoreUntil = Date.now() + this.timeouts.outputSettle + 400;
|
|
20387
20422
|
LOG.info("CLI", `[${this.cliType}] Retrying submit key for stuck prompt (attempt 1)`);
|
|
20388
|
-
this.
|
|
20423
|
+
this.writeStuckRetry(state, "immediate_retry");
|
|
20389
20424
|
this.engine.submitRetryUsed = true;
|
|
20390
20425
|
}
|
|
20391
20426
|
submitSendKey(state, completion) {
|
|
@@ -20638,7 +20673,9 @@ ${lastSnapshot}`;
|
|
|
20638
20673
|
submitDelayMs,
|
|
20639
20674
|
maxEchoWaitMs,
|
|
20640
20675
|
retryDelayMs,
|
|
20641
|
-
didCommitUserTurn: false
|
|
20676
|
+
didCommitUserTurn: false,
|
|
20677
|
+
// Capture BEFORE the send commits — commitSendUserTurn flips firstTurnSent.
|
|
20678
|
+
isFirstTurn: !this.firstTurnSent
|
|
20642
20679
|
};
|
|
20643
20680
|
this.engine.responseSettleIgnoreUntil = Date.now() + submitDelayMs + this.timeouts.outputSettle + 250;
|
|
20644
20681
|
await new Promise((resolve24, reject) => {
|
|
@@ -20656,7 +20693,8 @@ ${lastSnapshot}`;
|
|
|
20656
20693
|
reject(error);
|
|
20657
20694
|
}
|
|
20658
20695
|
};
|
|
20659
|
-
|
|
20696
|
+
const useAtomicFirstTurn = this.submitStrategy === "immediate" || process.platform === "win32" && sendState.isFirstTurn;
|
|
20697
|
+
if (useAtomicFirstTurn) {
|
|
20660
20698
|
this.submitImmediatePrompt(sendState, completion);
|
|
20661
20699
|
return;
|
|
20662
20700
|
}
|
|
@@ -54406,7 +54444,14 @@ ${hintLines.join("\n")}` : "",
|
|
|
54406
54444
|
nodeId,
|
|
54407
54445
|
sessionCleanupMode: refineSessionCleanupMode,
|
|
54408
54446
|
...refineSessionIds && refineSessionIds.length > 0 ? { sessionIds: refineSessionIds } : {},
|
|
54409
|
-
inlineMesh: args?.inlineMesh
|
|
54447
|
+
inlineMesh: args?.inlineMesh,
|
|
54448
|
+
// REFINE-CLEANUP: refine reaches cleanup only AFTER a verified merge
|
|
54449
|
+
// convergence, so any residual worktree dirtiness here is incidental
|
|
54450
|
+
// (e.g. a bootstrap lockfile rewrite) — never unmerged work. `force`
|
|
54451
|
+
// sets requireClean=false so a plain-dirty worktree no longer aborts
|
|
54452
|
+
// removal with merged_cleanup_failed. Branch-ref deletion still keys off
|
|
54453
|
+
// mergeConvergence (NOT the force flag), so no merged work can be lost.
|
|
54454
|
+
force: true
|
|
54410
54455
|
});
|
|
54411
54456
|
recordMeshRefineStage(refineStages, "cleanup", removeResult?.success === false ? "failed" : "passed", cleanupStarted, {
|
|
54412
54457
|
removed: removeResult?.removed,
|