@adhdev/daemon-core 0.9.82-rc.504 → 0.9.82-rc.506
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 +18 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +18 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/mesh/mesh-event-forwarding.ts +10 -2
- package/src/mesh/mesh-node-identity.ts +11 -2
- package/src/mesh/mesh-queue-assignment.ts +11 -3
- package/src/mesh/mesh-reconcile-loop.ts +10 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adhdev/daemon-core",
|
|
3
|
-
"version": "0.9.82-rc.
|
|
3
|
+
"version": "0.9.82-rc.506",
|
|
4
4
|
"description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"author": "vilmire",
|
|
48
48
|
"license": "AGPL-3.0-or-later",
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@adhdev/mesh-shared": "0.9.82-rc.
|
|
51
|
-
"@adhdev/session-host-core": "0.9.82-rc.
|
|
50
|
+
"@adhdev/mesh-shared": "0.9.82-rc.506",
|
|
51
|
+
"@adhdev/session-host-core": "0.9.82-rc.506",
|
|
52
52
|
"@agentclientprotocol/sdk": "^0.16.1",
|
|
53
53
|
"ajv": "^8.20.0",
|
|
54
54
|
"ajv-formats": "^3.0.1",
|
|
@@ -16,7 +16,7 @@ import { enqueueUnresolvedDelegateForward, nudgeUnresolvedForwardRetry } from '.
|
|
|
16
16
|
import { traceMeshEventStage, traceMeshEventDrop } from './mesh-event-trace.js';
|
|
17
17
|
import { getLastDisplayMessage } from '../status/snapshot.js';
|
|
18
18
|
import { resolveDelegatedWorkerAutoApprove } from '../repo-mesh-types.js';
|
|
19
|
-
import { meshNodeIdMatches, daemonIdsEquivalent, expandDaemonIdForms, sessionIdsEquivalent, type MeshNodeIdentified } from '@adhdev/mesh-shared';
|
|
19
|
+
import { meshNodeIdMatches, daemonIdsEquivalent, expandDaemonIdForms, sessionIdsEquivalent, withStatusProbeMarker, type MeshNodeIdentified } from '@adhdev/mesh-shared';
|
|
20
20
|
import {
|
|
21
21
|
findRecentTerminalLedgerEvidence,
|
|
22
22
|
findTerminalLedgerEvidenceForTask,
|
|
@@ -760,7 +760,15 @@ function stopStaleMeshWorker(
|
|
|
760
760
|
} catch { /* best-effort */ }
|
|
761
761
|
}
|
|
762
762
|
if (daemonId && components.dispatchMeshCommand) {
|
|
763
|
-
|
|
763
|
+
// OFFLINE-NODE-BLOCKING: this stop is fire-and-forget. Without a short connect-wait,
|
|
764
|
+
// a stop_cli to a worker node whose daemon is powered off leaves a pending request
|
|
765
|
+
// hanging for the full 90s connect deadline before its .catch fires (a leaked
|
|
766
|
+
// pending per stale worker). Stamp the status-origin marker so the daemon-cloud relay
|
|
767
|
+
// grants the SHORT connect-wait budget — an offline node rejects in ~2s and the .catch
|
|
768
|
+
// logs it immediately. The marker only affects the connect wait and is stripped before
|
|
769
|
+
// stop_cli executes, so a live worker is stopped identically. (Best-effort by design:
|
|
770
|
+
// a failed stop only loses the belt-and-suspenders stop; the ack was already rejected.)
|
|
771
|
+
Promise.resolve(components.dispatchMeshCommand(daemonId, 'stop_cli', withStatusProbeMarker(stopArgs)))
|
|
764
772
|
.catch((e: any) => LOG.warn('MeshQueue', `Remote stop of stale worker ${sessionId} on daemon ${daemonId} failed: ${e?.message || e}`));
|
|
765
773
|
} else {
|
|
766
774
|
LOG.warn('MeshQueue', `Cannot stop stale worker ${sessionId}: no local adapter and no resolvable remote daemon id (node ${args.nodeId ?? '?'}). Ack already rejected — task will re-strand-and-fail if the worker completes.`);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
import type { ProviderLoader } from '../providers/provider-loader.js';
|
|
15
15
|
import { detectCLI } from '../detection/cli-detector.js';
|
|
16
16
|
import { getGitRepoStatus } from '../git/git-status.js';
|
|
17
|
-
import { normalizeGitStatus as sharedNormalizeGitStatus, pickBestTransitGitStatus as sharedPickBestTransitGitStatus, summarizeGitShape as sharedSummarizeGitShape, normalizeMeshNodeId, daemonIdsEquivalent, meshWorkspacesEquivalent, sessionIdsEquivalent } from '@adhdev/mesh-shared';
|
|
17
|
+
import { normalizeGitStatus as sharedNormalizeGitStatus, pickBestTransitGitStatus as sharedPickBestTransitGitStatus, summarizeGitShape as sharedSummarizeGitShape, normalizeMeshNodeId, daemonIdsEquivalent, meshWorkspacesEquivalent, sessionIdsEquivalent, withStatusProbeMarker } from '@adhdev/mesh-shared';
|
|
18
18
|
import { LOG } from '../logging/logger.js';
|
|
19
19
|
import { getSessionHostSurfaceKind } from '../session-host/runtime-surface.js';
|
|
20
20
|
import { awaitWithWarmupDeadline, resolveWarmupDeadlineOpts } from '../mesh/mesh-warmup-deadline.js';
|
|
@@ -1468,7 +1468,16 @@ async function probeRemoteMeshGitStatus(args: {
|
|
|
1468
1468
|
// cold-open handshake to the connect budget and only the warm round trip to
|
|
1469
1469
|
// the response budget, so the first probe to a cold peer is no longer
|
|
1470
1470
|
// false-timed-out before its channel has even opened.
|
|
1471
|
-
|
|
1471
|
+
// OFFLINE-NODE-STATUS-REFRESH: stamp the status-origin marker so the daemon-cloud
|
|
1472
|
+
// dispatch wrapper grants this explicit_refresh / mesh_status git_status probe the
|
|
1473
|
+
// SHORT connect-wait budget. Without it, an offline (powered-off) peer sinks the
|
|
1474
|
+
// probe into the 90s connect deadline and blocks the whole status assembly. A
|
|
1475
|
+
// user-driven / targeted git_status (no marker) is unaffected.
|
|
1476
|
+
const dispatch = args.dispatchMeshCommand(
|
|
1477
|
+
args.daemonId,
|
|
1478
|
+
'git_status',
|
|
1479
|
+
withStatusProbeMarker({ workspace: args.workspace, refreshUpstream: true }),
|
|
1480
|
+
);
|
|
1472
1481
|
// A missing connection getter no longer silently becomes `() => true`
|
|
1473
1482
|
// ("always warm") — that charged a still-opening channel against the response
|
|
1474
1483
|
// budget and re-introduced the cold-open false-timeout. resolveWarmupDeadlineOpts
|
|
@@ -15,7 +15,7 @@ import { traceMeshEventDrop } from './mesh-event-trace.js';
|
|
|
15
15
|
import { awaitWithWarmupDeadline, resolveWarmupDeadlineOpts } from './mesh-warmup-deadline.js';
|
|
16
16
|
import { resolveDelegatedWorkerAutoApprove, resolveProviderMaxParallel, resolveNodeSchedulingPriority, normalizeMeshSchedulingStrategy, resolveMaxParallelTasks, resolveMaxReadonlyParallelTasks } from '../repo-mesh-types.js';
|
|
17
17
|
import type { RepoMeshSchedulingStrategy } from '../repo-mesh-types.js';
|
|
18
|
-
import { normalizeMeshNodeId, meshNodeIdMatches, daemonIdsEquivalent, canonicalDaemonId, normalizeMeshWorkspaceForCompare, meshWorkspacesEquivalent, sessionIdsEquivalent, deriveSlotsFromLegacy, normalizeNodeCapabilitySlots, isMeshTaskDifficulty, type MeshNodeIdentified, type NodeCapabilitySlot, type MeshTaskDifficulty } from '@adhdev/mesh-shared';
|
|
18
|
+
import { normalizeMeshNodeId, meshNodeIdMatches, daemonIdsEquivalent, canonicalDaemonId, normalizeMeshWorkspaceForCompare, meshWorkspacesEquivalent, sessionIdsEquivalent, deriveSlotsFromLegacy, normalizeNodeCapabilitySlots, isMeshTaskDifficulty, withStatusProbeMarker, type MeshNodeIdentified, type NodeCapabilitySlot, type MeshTaskDifficulty } from '@adhdev/mesh-shared';
|
|
19
19
|
import { findTerminalLedgerEvidenceForTask, hasUnterminalDirectDispatchLedgerEntry } from './mesh-events-stale.js';
|
|
20
20
|
import { readNonEmptyString } from './mesh-events-utils.js';
|
|
21
21
|
import { readMeshNodeDaemonId } from './mesh-node-identity.js';
|
|
@@ -2100,7 +2100,15 @@ async function maybeAutoLaunchOneQueueSession(components: DaemonComponents, mesh
|
|
|
2100
2100
|
markAutoLaunch(meshId, task.id, { status: 'started', nodeId, providerType: resolved.providerType });
|
|
2101
2101
|
let launchResult: any;
|
|
2102
2102
|
try {
|
|
2103
|
-
|
|
2103
|
+
// OFFLINE-NODE-BLOCKING: no peer-connected pre-check before this remote
|
|
2104
|
+
// launch_cli meant an OFFLINE target node sank the dispatch into the 90s
|
|
2105
|
+
// connect deadline, stalling the 4s auto-launch loop for a full 90s. Stamp
|
|
2106
|
+
// the status-origin marker so the daemon-cloud relay grants the SHORT
|
|
2107
|
+
// connect-wait budget — an offline node throws in ~2s, the catch below sets
|
|
2108
|
+
// the 25s cooldown (autoLaunchCooldownUntil) that already gates retries, so
|
|
2109
|
+
// the loop moves on. The marker only affects the connect wait and is
|
|
2110
|
+
// stripped before launch_cli executes, so a live node spawns identically.
|
|
2111
|
+
launchResult = await components.dispatchMeshCommand!(launchTarget.daemonId!, 'launch_cli', withStatusProbeMarker({
|
|
2104
2112
|
cliType: resolved.providerType,
|
|
2105
2113
|
dir: node.workspace,
|
|
2106
2114
|
settings: remoteSettings,
|
|
@@ -2110,7 +2118,7 @@ async function maybeAutoLaunchOneQueueSession(components: DaemonComponents, mesh
|
|
|
2110
2118
|
...(effectiveModel ? { initialModel: effectiveModel } : {}),
|
|
2111
2119
|
// BRAIN-ROUTING thinking axis: forward the effective thinking level (initialThinkingLevel).
|
|
2112
2120
|
...(effectiveThinkingLevel ? { initialThinkingLevel: effectiveThinkingLevel } : {}),
|
|
2113
|
-
});
|
|
2121
|
+
}));
|
|
2114
2122
|
} catch (e: any) {
|
|
2115
2123
|
markAutoLaunch(meshId, task.id, { status: 'failed', reason: `remote_launch_dispatch_failed: ${e?.message || String(e)}`, nodeId, providerType: resolved.providerType });
|
|
2116
2124
|
autoLaunchCooldownUntil.set(launchKey, Date.now() + AUTO_LAUNCH_COOLDOWN_MS); sweepExpiredCooldowns();
|
|
@@ -59,7 +59,7 @@ import {
|
|
|
59
59
|
} from './mesh-unresolved-forward-outbox.js';
|
|
60
60
|
import { readNonEmptyString, readMeshCompletionSummary, buildMeshSystemMessage } from './mesh-events-utils.js';
|
|
61
61
|
import { traceMeshEventStage, traceMeshEventDrop } from './mesh-event-trace.js';
|
|
62
|
-
import { expandDaemonIdForms, daemonIdsEquivalent, sessionIdsEquivalent, meshNodeIdMatches } from '@adhdev/mesh-shared';
|
|
62
|
+
import { expandDaemonIdForms, daemonIdsEquivalent, sessionIdsEquivalent, meshNodeIdMatches, withStatusProbeMarker } from '@adhdev/mesh-shared';
|
|
63
63
|
import { getQueue, reclaimStrandedAssignedTask, updateTaskStatus } from './mesh-work-queue.js';
|
|
64
64
|
import { resolveSessionBusyVerdict } from './mesh-queue-assignment.js';
|
|
65
65
|
import { readLedgerEntries } from './mesh-ledger.js';
|
|
@@ -1637,7 +1637,15 @@ async function retryUnresolvedDelegateForwards(components: DaemonComponents): Pr
|
|
|
1637
1637
|
let result: any;
|
|
1638
1638
|
try {
|
|
1639
1639
|
traceMeshEventStage('forward_send', entryTraceCtx, `retry → ${entry.coordinatorDaemonId}`);
|
|
1640
|
-
|
|
1640
|
+
// OFFLINE-NODE-BLOCKING: stamp the status-origin marker so the daemon-cloud relay
|
|
1641
|
+
// grants the SHORT connect-wait budget. Without it, a retry to a coordinator whose
|
|
1642
|
+
// daemon is powered off sinks into the 90s connect deadline per entry, serializing
|
|
1643
|
+
// the whole unresolved-forward outbox behind one dead coordinator. With it, the
|
|
1644
|
+
// dispatch throws in ~2s and the entry is left queued for the next tick — the
|
|
1645
|
+
// existing retry-backoff and age-expiry below are unchanged. The marker only
|
|
1646
|
+
// affects the connect wait and is stripped before mesh_forward_event executes, so
|
|
1647
|
+
// delivery semantics are identical.
|
|
1648
|
+
result = await dispatchMeshCommand(entry.coordinatorDaemonId, 'mesh_forward_event', withStatusProbeMarker(pushPayload));
|
|
1641
1649
|
} catch (e: any) {
|
|
1642
1650
|
// Coordinator unreachable (transport threw) — keep the entry queued and try again
|
|
1643
1651
|
// next tick. This is NOT a hard rejection, so it does not count toward the cap;
|