@adhdev/daemon-core 1.0.18-rc.8 → 1.0.18-rc.9
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/commands/windows-atomic-upgrade.d.ts +4 -0
- package/dist/index.js +115 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +115 -42
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/commands/upgrade-helper.ts +28 -14
- package/src/commands/windows-atomic-upgrade.ts +61 -18
- package/src/mesh/mesh-queue-assignment.ts +126 -1
package/dist/index.mjs
CHANGED
|
@@ -437,10 +437,10 @@ function readInjected(value) {
|
|
|
437
437
|
}
|
|
438
438
|
function getDaemonBuildInfo() {
|
|
439
439
|
if (cached) return cached;
|
|
440
|
-
const commit = readInjected(true ? "
|
|
441
|
-
const commitShort = readInjected(true ? "
|
|
442
|
-
const version = readInjected(true ? "1.0.18-rc.
|
|
443
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
440
|
+
const commit = readInjected(true ? "3a1a0d16c0dd7ce3df15591fbe30b7e8638ab876" : void 0) ?? "unknown";
|
|
441
|
+
const commitShort = readInjected(true ? "3a1a0d16" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
442
|
+
const version = readInjected(true ? "1.0.18-rc.9" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
443
|
+
const builtAt = readInjected(true ? "2026-07-22T05:27:14.328Z" : void 0);
|
|
444
444
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
445
445
|
return cached;
|
|
446
446
|
}
|
|
@@ -16642,6 +16642,33 @@ function isTargetNodeTransientlyUnresolved(mesh, task) {
|
|
|
16642
16642
|
}
|
|
16643
16643
|
return isWithinCloneBootstrapGrace(targetNodeId);
|
|
16644
16644
|
}
|
|
16645
|
+
function resolveDeadTargetVerdict(components, meshId, mesh, task) {
|
|
16646
|
+
const NOT_DEAD = { dead: false, nodeDead: false, reason: "" };
|
|
16647
|
+
const targetSessionId = readNonEmptyString(task.targetSessionId);
|
|
16648
|
+
const targetNodeId = readNonEmptyString(task.targetNodeId);
|
|
16649
|
+
if (!targetSessionId && !targetNodeId) return NOT_DEAD;
|
|
16650
|
+
const lastUpdateMs = Date.parse(task.updatedAt || task.createdAt || "");
|
|
16651
|
+
if (Number.isFinite(lastUpdateMs) && Date.now() - lastUpdateMs < DEAD_TARGET_GRACE_MS) return NOT_DEAD;
|
|
16652
|
+
const nodes = Array.isArray(mesh?.nodes) ? mesh.nodes : [];
|
|
16653
|
+
if (targetNodeId) {
|
|
16654
|
+
const nodePresent = nodes.some((n) => meshNodeIdMatches(n, targetNodeId));
|
|
16655
|
+
if (!nodePresent) {
|
|
16656
|
+
if (isTargetNodeTransientlyUnresolved(mesh, task)) return NOT_DEAD;
|
|
16657
|
+
return { dead: true, nodeDead: true, reason: "dead_target_node_absent" };
|
|
16658
|
+
}
|
|
16659
|
+
}
|
|
16660
|
+
if (targetSessionId) {
|
|
16661
|
+
const node = targetNodeId ? nodes.find((n) => meshNodeIdMatches(n, targetNodeId)) : void 0;
|
|
16662
|
+
const nodeIsLocal = node ? isLocalAutoLaunchNode(node) : true;
|
|
16663
|
+
if (nodeIsLocal) {
|
|
16664
|
+
const verdict = resolveSessionBusyVerdict(components, targetSessionId);
|
|
16665
|
+
if (verdict === "UNKNOWN") {
|
|
16666
|
+
return { dead: true, nodeDead: false, reason: "dead_target_session_absent" };
|
|
16667
|
+
}
|
|
16668
|
+
}
|
|
16669
|
+
}
|
|
16670
|
+
return NOT_DEAD;
|
|
16671
|
+
}
|
|
16645
16672
|
function retractActionableSkipIfPreviouslyNotified(meshId, taskId) {
|
|
16646
16673
|
const dedupKey = `${meshId}:${taskId}`;
|
|
16647
16674
|
if (!lastActionableSkipNotified.delete(dedupKey)) return;
|
|
@@ -17159,6 +17186,21 @@ async function maybeAutoLaunchOneQueueSession(components, meshId, mesh) {
|
|
|
17159
17186
|
continue;
|
|
17160
17187
|
}
|
|
17161
17188
|
if (task.targetSessionId) {
|
|
17189
|
+
const deadTarget = resolveDeadTargetVerdict(components, meshId, mesh, task);
|
|
17190
|
+
if (deadTarget.dead) {
|
|
17191
|
+
const requeued = requeueTask(meshId, task.id, {
|
|
17192
|
+
reason: deadTarget.reason,
|
|
17193
|
+
clearTargetSession: true,
|
|
17194
|
+
// Keep the node pin if only the SESSION died on a still-live node; clear it
|
|
17195
|
+
// when the NODE itself is absent (nothing to pin to).
|
|
17196
|
+
clearTargetNode: deadTarget.nodeDead
|
|
17197
|
+
});
|
|
17198
|
+
if (requeued) {
|
|
17199
|
+
LOG.warn("MeshQueue", `DEAD-TARGET-SELFHEAL: task ${task.id} (mesh ${meshId}) was pinned to a dead target (${deadTarget.reason}); requeued${deadTarget.nodeDead ? " and unpinned node" : ""} (requeueCount=${requeued.requeueCount ?? "?"}, status=${requeued.status}).`);
|
|
17200
|
+
}
|
|
17201
|
+
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_dead_requeued" });
|
|
17202
|
+
continue;
|
|
17203
|
+
}
|
|
17162
17204
|
markAutoLaunch(meshId, task.id, { status: "skipped", reason: "target_session_constraint" });
|
|
17163
17205
|
continue;
|
|
17164
17206
|
}
|
|
@@ -17730,7 +17772,7 @@ function runIdleMaintenanceThenAssignQueue(components, args) {
|
|
|
17730
17772
|
});
|
|
17731
17773
|
});
|
|
17732
17774
|
}
|
|
17733
|
-
var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS, continuousAutoFastForwardLastScan, autoFastForwardWorkspaceLease, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified;
|
|
17775
|
+
var IDLE_AUTO_FAST_FORWARD_THROTTLE_MS, idleAutoFastForwardLastAttempt, CONTINUOUS_AUTO_FAST_FORWARD_SCAN_COOLDOWN_MS, continuousAutoFastForwardLastScan, autoFastForwardWorkspaceLease, BOOTSTRAP_TERMINAL_STATUSES, DISPATCH_CONFIRM_TIMEOUT_MS, DISPATCH_CONNECT_TIMEOUT_MS, dispatchWarmupGetterMissingWarned, LOCAL_LAUNCH_READY_TIMEOUT_MS, LOCAL_LAUNCH_READY_POLL_MS, autoLaunchInProgress, autoLaunchCooldownUntil, AUTO_LAUNCH_COOLDOWN_MS, AUTO_LAUNCH_AWAIT_CLAIM_MS, AUTO_LAUNCH_AWAIT_CLAIM_BACKOFF_CAP_CYCLES, AUTO_LAUNCH_REMOTE_IDLE_TTL_MS, autoLaunchAwaitClaimBackoff, lastAutoLaunchLedgerKey, AUTO_LAUNCH_LEDGER_DEDUP_MAX, ACTIONABLE_SKIP_REASON_PREFIXES, TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON, lastActionableSkipNotified, DEAD_TARGET_GRACE_MS;
|
|
17734
17776
|
var init_mesh_queue_assignment = __esm({
|
|
17735
17777
|
"src/mesh/mesh-queue-assignment.ts"() {
|
|
17736
17778
|
"use strict";
|
|
@@ -17791,6 +17833,7 @@ var init_mesh_queue_assignment = __esm({
|
|
|
17791
17833
|
];
|
|
17792
17834
|
TRANSIENT_TARGET_NODE_BOOTSTRAP_PENDING_REASON = "target_node_bootstrap_pending";
|
|
17793
17835
|
lastActionableSkipNotified = /* @__PURE__ */ new Map();
|
|
17836
|
+
DEAD_TARGET_GRACE_MS = 6e4;
|
|
17794
17837
|
}
|
|
17795
17838
|
});
|
|
17796
17839
|
|
|
@@ -42968,6 +43011,40 @@ async function stopOwnedProcessesForPrefixes(options) {
|
|
|
42968
43011
|
var POINTER_NAME = ".adhdev-current";
|
|
42969
43012
|
var STABLE_FILES = [POINTER_NAME, "adhdev.cmd", "adhdev.ps1", "adhdev"];
|
|
42970
43013
|
var DEFAULT_HEALTH_PORT = 19222;
|
|
43014
|
+
function fetchLocalJson(port, pathname) {
|
|
43015
|
+
return new Promise((resolve27) => {
|
|
43016
|
+
const req = http2.get(`http://127.0.0.1:${port}${pathname}`, { timeout: 1500 }, (res) => {
|
|
43017
|
+
let body = "";
|
|
43018
|
+
res.setEncoding("utf8");
|
|
43019
|
+
res.on("data", (chunk) => {
|
|
43020
|
+
body += chunk;
|
|
43021
|
+
});
|
|
43022
|
+
res.on("end", () => resolve27({ ok: res.statusCode === 200, body }));
|
|
43023
|
+
});
|
|
43024
|
+
req.on("timeout", () => req.destroy());
|
|
43025
|
+
req.on("error", () => resolve27({ ok: false, body: "" }));
|
|
43026
|
+
});
|
|
43027
|
+
}
|
|
43028
|
+
async function fetchLocalHealth(port) {
|
|
43029
|
+
const { ok, body } = await fetchLocalJson(port, "/health");
|
|
43030
|
+
if (!ok) return { ok: false };
|
|
43031
|
+
try {
|
|
43032
|
+
const pid = Number(JSON.parse(body)?.pid);
|
|
43033
|
+
return { ok: true, pid: Number.isFinite(pid) ? pid : void 0 };
|
|
43034
|
+
} catch {
|
|
43035
|
+
return { ok: false };
|
|
43036
|
+
}
|
|
43037
|
+
}
|
|
43038
|
+
async function fetchLocalStatusVersion(port) {
|
|
43039
|
+
const { ok, body } = await fetchLocalJson(port, "/api/v1/status");
|
|
43040
|
+
if (!ok) return void 0;
|
|
43041
|
+
try {
|
|
43042
|
+
const version = JSON.parse(body)?.status?.version;
|
|
43043
|
+
return typeof version === "string" ? version : void 0;
|
|
43044
|
+
} catch {
|
|
43045
|
+
return void 0;
|
|
43046
|
+
}
|
|
43047
|
+
}
|
|
42971
43048
|
var ADHDEV_OWNED_MARKERS = [
|
|
42972
43049
|
"session-host-daemon",
|
|
42973
43050
|
"node_modules/adhdev",
|
|
@@ -43245,6 +43322,8 @@ async function performWindowsAtomicUpgrade(options) {
|
|
|
43245
43322
|
}
|
|
43246
43323
|
}
|
|
43247
43324
|
function createDefaultWindowsAtomicHooks(options) {
|
|
43325
|
+
const healthPort = options.healthPort ?? DEFAULT_HEALTH_PORT;
|
|
43326
|
+
const healthTimeoutMs = options.healthTimeoutMs ?? 3e4;
|
|
43248
43327
|
return {
|
|
43249
43328
|
install: (stagedPrefix, portableNode) => {
|
|
43250
43329
|
const env = {
|
|
@@ -43255,7 +43334,7 @@ function createDefaultWindowsAtomicHooks(options) {
|
|
|
43255
43334
|
};
|
|
43256
43335
|
const pathKey = Object.keys(env).find((key2) => key2.toLowerCase() === "path") || "Path";
|
|
43257
43336
|
env[pathKey] = `${path20.dirname(portableNode)};${env[pathKey] || ""}`;
|
|
43258
|
-
execFileSync4(portableNode, [
|
|
43337
|
+
const installOutput = String(execFileSync4(portableNode, [
|
|
43259
43338
|
options.npmCliPath,
|
|
43260
43339
|
"install",
|
|
43261
43340
|
"-g",
|
|
@@ -43270,7 +43349,8 @@ function createDefaultWindowsAtomicHooks(options) {
|
|
|
43270
43349
|
maxBuffer: 20 * 1024 * 1024,
|
|
43271
43350
|
windowsHide: true,
|
|
43272
43351
|
env
|
|
43273
|
-
});
|
|
43352
|
+
}));
|
|
43353
|
+
if (installOutput.trim()) options.log(installOutput.trim());
|
|
43274
43354
|
},
|
|
43275
43355
|
restart: (portableNode, stagedCliEntry) => {
|
|
43276
43356
|
const restartArgv = options.restartArgv.map((arg, index) => index === 0 ? stagedCliEntry : arg);
|
|
@@ -43297,28 +43377,12 @@ function createDefaultWindowsAtomicHooks(options) {
|
|
|
43297
43377
|
child.unref();
|
|
43298
43378
|
},
|
|
43299
43379
|
waitForHealth: async (pid, targetVersion) => {
|
|
43300
|
-
const deadline = Date.now() +
|
|
43380
|
+
const deadline = Date.now() + healthTimeoutMs;
|
|
43301
43381
|
while (Date.now() < deadline) {
|
|
43302
|
-
const
|
|
43303
|
-
|
|
43304
|
-
|
|
43305
|
-
|
|
43306
|
-
res.on("data", (chunk) => {
|
|
43307
|
-
body += chunk;
|
|
43308
|
-
});
|
|
43309
|
-
res.on("end", () => {
|
|
43310
|
-
let responsePid;
|
|
43311
|
-
try {
|
|
43312
|
-
responsePid = Number(JSON.parse(body)?.pid);
|
|
43313
|
-
} catch {
|
|
43314
|
-
}
|
|
43315
|
-
resolve27({ ok: res.statusCode === 200, pid: responsePid, body });
|
|
43316
|
-
});
|
|
43317
|
-
});
|
|
43318
|
-
req.on("timeout", () => req.destroy());
|
|
43319
|
-
req.on("error", () => resolve27({ ok: false }));
|
|
43320
|
-
});
|
|
43321
|
-
if (result.ok && result.pid === pid && result.body?.includes(targetVersion)) return true;
|
|
43382
|
+
const liveness = await fetchLocalHealth(healthPort);
|
|
43383
|
+
const alive = liveness.ok && liveness.pid === pid;
|
|
43384
|
+
const version = alive ? await fetchLocalStatusVersion(healthPort) : void 0;
|
|
43385
|
+
if (alive && version === targetVersion) return true;
|
|
43322
43386
|
await new Promise((resolve27) => setTimeout(resolve27, 500));
|
|
43323
43387
|
}
|
|
43324
43388
|
return false;
|
|
@@ -43747,22 +43811,31 @@ async function runDaemonUpgradeHelper(payload) {
|
|
|
43747
43811
|
`Cannot upgrade: owned processes still running under current prefix: ${preStop.survivors.map((s2) => s2.pid).join(", ")}`
|
|
43748
43812
|
);
|
|
43749
43813
|
}
|
|
43750
|
-
|
|
43751
|
-
|
|
43752
|
-
|
|
43753
|
-
targetVersion: payload.targetVersion,
|
|
43754
|
-
portableNode,
|
|
43755
|
-
excludePids: upgradePids,
|
|
43756
|
-
hooks: createDefaultWindowsAtomicHooks({
|
|
43814
|
+
try {
|
|
43815
|
+
await performWindowsAtomicUpgrade({
|
|
43816
|
+
layout: windowsInstallerLayout,
|
|
43757
43817
|
packageName: payload.packageName,
|
|
43758
43818
|
targetVersion: payload.targetVersion,
|
|
43759
|
-
|
|
43760
|
-
|
|
43761
|
-
|
|
43762
|
-
|
|
43763
|
-
|
|
43764
|
-
|
|
43765
|
-
|
|
43819
|
+
portableNode,
|
|
43820
|
+
excludePids: upgradePids,
|
|
43821
|
+
hooks: createDefaultWindowsAtomicHooks({
|
|
43822
|
+
packageName: payload.packageName,
|
|
43823
|
+
targetVersion: payload.targetVersion,
|
|
43824
|
+
npmCliPath,
|
|
43825
|
+
restartArgv,
|
|
43826
|
+
cwd: payload.cwd || process.cwd(),
|
|
43827
|
+
env: Object.fromEntries(Object.entries(process.env).filter(([key2]) => key2 !== UPGRADE_HELPER_ENV)),
|
|
43828
|
+
log: appendUpgradeLog
|
|
43829
|
+
})
|
|
43830
|
+
});
|
|
43831
|
+
} catch (error) {
|
|
43832
|
+
emitUpgradeFailureNotice([
|
|
43833
|
+
`adhdev ${payload.packageName}@${payload.targetVersion} upgrade failed and was rolled back: ${error?.message || String(error)}`,
|
|
43834
|
+
`Previous version preserved (active prefix: ${windowsInstallerLayout.activePrefix}).`,
|
|
43835
|
+
"See daemon-upgrade.log for the full install/health trace. The next daemon start will retry."
|
|
43836
|
+
]);
|
|
43837
|
+
throw error;
|
|
43838
|
+
}
|
|
43766
43839
|
try {
|
|
43767
43840
|
fs15.unlinkSync(getUpgradeFailureNoticePath());
|
|
43768
43841
|
} catch {
|