@integrity-labs/agt-cli 0.28.1138 → 0.28.1139
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/bin/agt.js +5 -5
- package/dist/{chunk-J6ORWGUB.js → chunk-7U4VSBOE.js} +2 -2
- package/dist/{chunk-EIXOI2ZB.js → chunk-DYFE224A.js} +14 -1
- package/dist/{chunk-EIXOI2ZB.js.map → chunk-DYFE224A.js.map} +1 -1
- package/dist/{chunk-3INFJV37.js → chunk-PI2WUKWD.js} +4 -4
- package/dist/{claude-pair-runtime-VQGEM5AY.js → claude-pair-runtime-BOTE3DRW.js} +2 -2
- package/dist/lib/manager-worker.js +261 -16
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +13 -0
- package/dist/mcp/index.js +13 -0
- package/dist/mcp/origami.js +13 -0
- package/dist/mcp/slack-channel.js +13 -0
- package/dist/mcp/telegram-channel.js +13 -0
- package/dist/{persistent-session-ZBKLEYUQ.js → persistent-session-6O66QEI4.js} +3 -3
- package/dist/{responsiveness-probe-FXDO35IT.js → responsiveness-probe-WGD3NDWG.js} +3 -3
- package/dist/{session-auth-dead-OGNOSJIB.js → session-auth-dead-6N2AEFKX.js} +2 -2
- package/package.json +1 -1
- /package/dist/{chunk-J6ORWGUB.js.map → chunk-7U4VSBOE.js.map} +0 -0
- /package/dist/{chunk-3INFJV37.js.map → chunk-PI2WUKWD.js.map} +0 -0
- /package/dist/{claude-pair-runtime-VQGEM5AY.js.map → claude-pair-runtime-BOTE3DRW.js.map} +0 -0
- /package/dist/{persistent-session-ZBKLEYUQ.js.map → persistent-session-6O66QEI4.js.map} +0 -0
- /package/dist/{responsiveness-probe-FXDO35IT.js.map → responsiveness-probe-WGD3NDWG.js.map} +0 -0
- /package/dist/{session-auth-dead-OGNOSJIB.js.map → session-auth-dead-6N2AEFKX.js.map} +0 -0
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
parseEnvFileEntries,
|
|
17
17
|
parseEnvIntegrations,
|
|
18
18
|
shellQuote
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-7U4VSBOE.js";
|
|
20
20
|
import {
|
|
21
21
|
BIND_FAILURE_QUARANTINE_THRESHOLD,
|
|
22
22
|
INTEGRATIONS_SECTION_END,
|
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
sessionTranscriptDir,
|
|
80
80
|
worseConnectivityOutcome,
|
|
81
81
|
wrapScheduledTaskPrompt
|
|
82
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-DYFE224A.js";
|
|
83
83
|
import {
|
|
84
84
|
classifyUnanswerablePane,
|
|
85
85
|
isConsumerTermsDialogVisible,
|
|
@@ -8076,7 +8076,7 @@ function exchangeFailureKind(err) {
|
|
|
8076
8076
|
}
|
|
8077
8077
|
|
|
8078
8078
|
// src/lib/api-client.ts
|
|
8079
|
-
var agtCliVersion = true ? "0.28.
|
|
8079
|
+
var agtCliVersion = true ? "0.28.1139" : "dev";
|
|
8080
8080
|
var lastConfigHash = null;
|
|
8081
8081
|
function setConfigHash(hash) {
|
|
8082
8082
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -13227,4 +13227,4 @@ export {
|
|
|
13227
13227
|
managerInstallSystemUnitCommand,
|
|
13228
13228
|
managerUninstallSystemUnitCommand
|
|
13229
13229
|
};
|
|
13230
|
-
//# sourceMappingURL=chunk-
|
|
13230
|
+
//# sourceMappingURL=chunk-PI2WUKWD.js.map
|
|
@@ -269,7 +269,7 @@ async function spawnPairSession(session) {
|
|
|
269
269
|
return { ok: true };
|
|
270
270
|
} catch {
|
|
271
271
|
}
|
|
272
|
-
const { resolveClaudeBinary } = await import("./persistent-session-
|
|
272
|
+
const { resolveClaudeBinary } = await import("./persistent-session-6O66QEI4.js");
|
|
273
273
|
const claudeBin = resolveClaudeBinary();
|
|
274
274
|
const pairEnv = {
|
|
275
275
|
...process.env,
|
|
@@ -739,4 +739,4 @@ export {
|
|
|
739
739
|
startClaudePair,
|
|
740
740
|
submitClaudePairCode
|
|
741
741
|
};
|
|
742
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
742
|
+
//# sourceMappingURL=claude-pair-runtime-BOTE3DRW.js.map
|
|
@@ -76,7 +76,7 @@ import {
|
|
|
76
76
|
setConfigHash,
|
|
77
77
|
shellGuard,
|
|
78
78
|
tripClass
|
|
79
|
-
} from "../chunk-
|
|
79
|
+
} from "../chunk-PI2WUKWD.js";
|
|
80
80
|
import {
|
|
81
81
|
getProjectDir as getProjectDir2,
|
|
82
82
|
getReadyTasks,
|
|
@@ -163,7 +163,7 @@ import {
|
|
|
163
163
|
webFetchBaselineValue,
|
|
164
164
|
webFetchRestartNeeded,
|
|
165
165
|
writeEgressAllowlist
|
|
166
|
-
} from "../chunk-
|
|
166
|
+
} from "../chunk-7U4VSBOE.js";
|
|
167
167
|
import {
|
|
168
168
|
ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
|
|
169
169
|
AnchorSessionClient,
|
|
@@ -274,7 +274,7 @@ import {
|
|
|
274
274
|
subagentActivityAgeSeconds,
|
|
275
275
|
sumTranscriptUsageInWindow,
|
|
276
276
|
transcriptActivityAgeSeconds
|
|
277
|
-
} from "../chunk-
|
|
277
|
+
} from "../chunk-DYFE224A.js";
|
|
278
278
|
import {
|
|
279
279
|
classifyUnanswerablePane,
|
|
280
280
|
focusedConfirmDialogBlock,
|
|
@@ -321,6 +321,173 @@ function defaultUnique() {
|
|
|
321
321
|
return `${process.pid}-${seq}-${Date.now().toString(36)}`;
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
+
// src/lib/host-node-pin.ts
|
|
325
|
+
var HOST_NODE_PIN_VERSION_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
326
|
+
var HOST_NODE_PIN_MIN_MAJOR = 22;
|
|
327
|
+
function normalizeHostNodePinVersion(raw) {
|
|
328
|
+
if (raw == null) return null;
|
|
329
|
+
const v = raw.trim().replace(/^v/, "");
|
|
330
|
+
if (!HOST_NODE_PIN_VERSION_RE.test(v)) return null;
|
|
331
|
+
const major = Number(v.split(".")[0]);
|
|
332
|
+
if (!Number.isInteger(major) || major < HOST_NODE_PIN_MIN_MAJOR) return null;
|
|
333
|
+
return v;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/lib/host-node-convergence.ts
|
|
337
|
+
var HOST_NODE_RETRY_MS = 15 * 6e4;
|
|
338
|
+
var HOST_NODE_MAX_FAILURES = 3;
|
|
339
|
+
var HostNodeConvergence = class {
|
|
340
|
+
constructor(maxFailures = HOST_NODE_MAX_FAILURES, retryMs = HOST_NODE_RETRY_MS) {
|
|
341
|
+
this.maxFailures = maxFailures;
|
|
342
|
+
this.retryMs = retryMs;
|
|
343
|
+
}
|
|
344
|
+
converged = /* @__PURE__ */ new Set();
|
|
345
|
+
abandoned = /* @__PURE__ */ new Set();
|
|
346
|
+
failures = /* @__PURE__ */ new Map();
|
|
347
|
+
retryAfter = /* @__PURE__ */ new Map();
|
|
348
|
+
/**
|
|
349
|
+
* The ONE pin currently installing, or null. Deliberately a single slot
|
|
350
|
+
* rather than a per-pin set: see {@link shouldAttempt}.
|
|
351
|
+
*/
|
|
352
|
+
inFlightPin = null;
|
|
353
|
+
lastDesired = null;
|
|
354
|
+
/**
|
|
355
|
+
* Record what the control plane currently wants, and discard stale
|
|
356
|
+
* conclusions when that changes.
|
|
357
|
+
*
|
|
358
|
+
* Keying per pin is necessary but NOT sufficient, which is the hole CodeRabbit
|
|
359
|
+
* found on #7088. Every state here is a claim about THIS HOST'S DISK at some
|
|
360
|
+
* past moment, and a pin change invalidates all of them: if the fleet moves
|
|
361
|
+
* 22.23.4 -> 22.23.5 and later back to 22.23.4, the disk now holds 22.23.5,
|
|
362
|
+
* while `converged` still asserts 22.23.4 from before. Without this the
|
|
363
|
+
* manager would skip the re-install forever on the strength of a measurement
|
|
364
|
+
* that a later install had already falsified - and 'converged' would once again
|
|
365
|
+
* mean something other than "this host is on the pin", which is the one thing
|
|
366
|
+
* this class exists to keep true.
|
|
367
|
+
*
|
|
368
|
+
* Clearing is cheap to be wrong about in the safe direction: a re-attempt
|
|
369
|
+
* reads `node --version` once and, if the disk already matches, records
|
|
370
|
+
* success immediately.
|
|
371
|
+
*
|
|
372
|
+
* `null` means NO pin is in force — the control plane sent none, or sent one
|
|
373
|
+
* this host refused as malformed. That must be recorded rather than ignored,
|
|
374
|
+
* which was the second hole on #7088: skipping the call left `lastDesired`
|
|
375
|
+
* pointing at the last pin seen, so clearing A and later restoring it looked
|
|
376
|
+
* like no change at all. Any drift on disk during the cleared window —
|
|
377
|
+
* an OS patch, an AMI replacement, a manual install — then survived
|
|
378
|
+
* indefinitely, because the restored pin's stale 'converged' suppressed the
|
|
379
|
+
* one disk read that would have caught it.
|
|
380
|
+
*/
|
|
381
|
+
noteDesiredPin(pin) {
|
|
382
|
+
if (this.lastDesired === pin) return;
|
|
383
|
+
this.lastDesired = pin;
|
|
384
|
+
this.converged.clear();
|
|
385
|
+
this.abandoned.clear();
|
|
386
|
+
this.failures.clear();
|
|
387
|
+
this.retryAfter.clear();
|
|
388
|
+
}
|
|
389
|
+
/** The pin last passed to {@link noteDesiredPin}, for reporting. */
|
|
390
|
+
desiredPin() {
|
|
391
|
+
return this.lastDesired;
|
|
392
|
+
}
|
|
393
|
+
stateOf(pin, now = Date.now()) {
|
|
394
|
+
if (this.converged.has(pin)) return "converged";
|
|
395
|
+
if (this.abandoned.has(pin)) return "abandoned";
|
|
396
|
+
if ((this.retryAfter.get(pin) ?? 0) > now) return "cooling";
|
|
397
|
+
return "ready";
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Whether to start an attempt now. False while ANY attempt is running —
|
|
401
|
+
* across pins, not just this one.
|
|
402
|
+
*
|
|
403
|
+
* Per-pin gating was the hole CodeRabbit found on #7088, and it is reachable
|
|
404
|
+
* because the caller is fire-and-forget while a `dnf install` may run for ten
|
|
405
|
+
* minutes. Sequence: A is converged; the pin moves to B and an install
|
|
406
|
+
* starts; the pin reverts to A. {@link noteDesiredPin} clears A's stale
|
|
407
|
+
* conclusion (correctly), a per-pin gate does not see B's attempt, so an A
|
|
408
|
+
* attempt starts WHILE B is installing. It reads the disk, which still says
|
|
409
|
+
* A, and records A as converged. B's install then lands, leaving B on disk
|
|
410
|
+
* with `converged` asserting A — and because that is terminal, every later
|
|
411
|
+
* poll skips the check. The host sits off-pin permanently while this class
|
|
412
|
+
* claims otherwise, which is the exact failure it was written to prevent.
|
|
413
|
+
*
|
|
414
|
+
* Serializing costs nothing in the steady state: convergence is a once-per
|
|
415
|
+
* -pin event, and a skipped poll retries ~10s later.
|
|
416
|
+
*/
|
|
417
|
+
shouldAttempt(pin, now = Date.now()) {
|
|
418
|
+
if (this.inFlightPin !== null) return false;
|
|
419
|
+
return this.stateOf(pin, now) === "ready";
|
|
420
|
+
}
|
|
421
|
+
/** The pin currently installing, or null. For reporting and for tests. */
|
|
422
|
+
inFlight() {
|
|
423
|
+
return this.inFlightPin;
|
|
424
|
+
}
|
|
425
|
+
beginAttempt(pin) {
|
|
426
|
+
this.inFlightPin = pin;
|
|
427
|
+
}
|
|
428
|
+
endAttempt(pin) {
|
|
429
|
+
if (this.inFlightPin === pin) this.inFlightPin = null;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* The on-disk version now equals the pin. Clears any failure history.
|
|
433
|
+
*
|
|
434
|
+
* A success for a pin that is no longer the desired one is DISCARDED. An
|
|
435
|
+
* attempt can outlive the pin that started it, and 'converged' is terminal —
|
|
436
|
+
* so recording it would suppress all future attempts on the strength of a
|
|
437
|
+
* measurement taken against a pin nobody wants any more. Dropping it costs
|
|
438
|
+
* one extra disk read if that pin is ever requested again.
|
|
439
|
+
*
|
|
440
|
+
* The guard is inactive until {@link noteDesiredPin} has been called at least
|
|
441
|
+
* once, so a caller that does not track a desired pin is unaffected.
|
|
442
|
+
*/
|
|
443
|
+
recordSuccess(pin) {
|
|
444
|
+
if (this.lastDesired !== null && pin !== this.lastDesired) return;
|
|
445
|
+
this.converged.add(pin);
|
|
446
|
+
this.abandoned.delete(pin);
|
|
447
|
+
this.failures.delete(pin);
|
|
448
|
+
this.retryAfter.delete(pin);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* An attempt failed. Returns the resulting state so the caller can log the
|
|
452
|
+
* right thing: 'cooling' means it will retry, 'abandoned' means it will not.
|
|
453
|
+
*/
|
|
454
|
+
recordFailure(pin, now = Date.now()) {
|
|
455
|
+
const count = (this.failures.get(pin) ?? 0) + 1;
|
|
456
|
+
this.failures.set(pin, count);
|
|
457
|
+
if (count >= this.maxFailures) {
|
|
458
|
+
this.abandoned.add(pin);
|
|
459
|
+
this.retryAfter.delete(pin);
|
|
460
|
+
return "abandoned";
|
|
461
|
+
}
|
|
462
|
+
this.retryAfter.set(pin, now + this.retryMs);
|
|
463
|
+
return "cooling";
|
|
464
|
+
}
|
|
465
|
+
attemptCount(pin) {
|
|
466
|
+
return this.failures.get(pin) ?? 0;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Every pin this host stopped trying to reach. A non-empty result means "a
|
|
470
|
+
* patch the control plane asked for is NOT applied and nothing is retrying".
|
|
471
|
+
*
|
|
472
|
+
* BE PRECISE ABOUT WHO CAN SEE THAT, because this module's header argues for
|
|
473
|
+
* telling abandonment apart from success "from outside" and Obi Wan correctly
|
|
474
|
+
* pointed out (#7088) that the claim outruns the code. Nothing in production
|
|
475
|
+
* reads this method, `stateOf`, `desiredPin` or `inFlight`: the state is not
|
|
476
|
+
* reported to the API, the heartbeat, or any console surface. The only signal
|
|
477
|
+
* that leaves the host is one `[host-node] … GIVING UP` line in manager.log.
|
|
478
|
+
*
|
|
479
|
+
* So what this class actually buys today is that the DISTINCTION EXISTS and
|
|
480
|
+
* cannot collapse — `converged` can never come to mean "gave up", which is
|
|
481
|
+
* the `ensureIsolationImage` defect the header cites. Surfacing it is a
|
|
482
|
+
* separate, unbuilt piece of work (ENG-11617 acceptance criterion 6), and it
|
|
483
|
+
* matters most for a BYO host in a customer account, which is the one
|
|
484
|
+
* population we cannot inspect any other way.
|
|
485
|
+
*/
|
|
486
|
+
abandonedPins() {
|
|
487
|
+
return [...this.abandoned];
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
|
|
324
491
|
// src/lib/manager-worker.ts
|
|
325
492
|
import { execFileSync as syncExecFile } from "child_process";
|
|
326
493
|
import { join as join43, dirname as dirname11, delimiter as pathDelimiter } from "path";
|
|
@@ -14491,7 +14658,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
|
|
|
14491
14658
|
var dayRolloverInboundHold = /* @__PURE__ */ new Map();
|
|
14492
14659
|
var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
|
|
14493
14660
|
async function channelInboundActivityAgeSecondsFor(codeName) {
|
|
14494
|
-
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-
|
|
14661
|
+
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-WGD3NDWG.js");
|
|
14495
14662
|
const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
|
|
14496
14663
|
if (newest === null) return null;
|
|
14497
14664
|
return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
|
|
@@ -15249,7 +15416,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
15249
15416
|
var lastVersionCheckAt = 0;
|
|
15250
15417
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
15251
15418
|
var lastResponsivenessProbeAt = 0;
|
|
15252
|
-
var agtCliVersion = true ? "0.28.
|
|
15419
|
+
var agtCliVersion = true ? "0.28.1139" : "dev";
|
|
15253
15420
|
function resolveBrewPath(execFileSync3) {
|
|
15254
15421
|
try {
|
|
15255
15422
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -15413,6 +15580,81 @@ function recordIsolationImageFailure(imageUri, reason) {
|
|
|
15413
15580
|
isolationImageRetryAfter.set(imageUri, Date.now() + ISOLATION_IMAGE_RETRY_MS);
|
|
15414
15581
|
}
|
|
15415
15582
|
}
|
|
15583
|
+
var hostNodeConvergence = new HostNodeConvergence();
|
|
15584
|
+
var hostNodeInvalidLogged = /* @__PURE__ */ new Set();
|
|
15585
|
+
var hostNodeNoDnfLogged = false;
|
|
15586
|
+
function recordHostNodeFailure(pin, reason) {
|
|
15587
|
+
const outcome = hostNodeConvergence.recordFailure(pin);
|
|
15588
|
+
const attempts = hostNodeConvergence.attemptCount(pin);
|
|
15589
|
+
if (outcome === "abandoned") {
|
|
15590
|
+
log(
|
|
15591
|
+
`[host-node] ${reason} \u2014 GIVING UP after ${attempts} attempts. Host Node is NOT on ${pin} and nothing will retry until the manager restarts. This host remains unpatched (ENG-11617).`
|
|
15592
|
+
);
|
|
15593
|
+
} else {
|
|
15594
|
+
log(`[host-node] ${reason} (attempt ${attempts}/${HOST_NODE_MAX_FAILURES}, retrying in ${HOST_NODE_RETRY_MS / 6e4}m)`);
|
|
15595
|
+
}
|
|
15596
|
+
}
|
|
15597
|
+
async function diskNodeVersion() {
|
|
15598
|
+
const probe = await runAsync("node", ["--version"], { timeout: 15e3 });
|
|
15599
|
+
if (probe.code !== 0) return null;
|
|
15600
|
+
const m = /^v?(\d+\.\d+\.\d+)/.exec(probe.stdout.trim());
|
|
15601
|
+
return m?.[1] ?? null;
|
|
15602
|
+
}
|
|
15603
|
+
async function ensureHostNodeVersion(rawPin) {
|
|
15604
|
+
const pin = normalizeHostNodePinVersion(rawPin);
|
|
15605
|
+
if (!pin) {
|
|
15606
|
+
const raw = rawPin == null ? "" : String(rawPin).trim();
|
|
15607
|
+
if (raw !== "" && !hostNodeInvalidLogged.has(raw)) {
|
|
15608
|
+
hostNodeInvalidLogged.add(raw);
|
|
15609
|
+
log(`[host-node] ignoring malformed desired_node_version '${raw.slice(0, 40)}' - not an exact MAJOR.MINOR.PATCH at or above major ${HOST_NODE_PIN_MIN_MAJOR}`);
|
|
15610
|
+
}
|
|
15611
|
+
hostNodeConvergence.noteDesiredPin(null);
|
|
15612
|
+
return;
|
|
15613
|
+
}
|
|
15614
|
+
hostNodeConvergence.noteDesiredPin(pin);
|
|
15615
|
+
if (!hostNodeConvergence.shouldAttempt(pin)) return;
|
|
15616
|
+
hostNodeConvergence.beginAttempt(pin);
|
|
15617
|
+
try {
|
|
15618
|
+
const current = await diskNodeVersion();
|
|
15619
|
+
if (current === pin) {
|
|
15620
|
+
hostNodeConvergence.recordSuccess(pin);
|
|
15621
|
+
return;
|
|
15622
|
+
}
|
|
15623
|
+
const { execFileSync: execFileSync3 } = await import("child_process");
|
|
15624
|
+
try {
|
|
15625
|
+
execFileSync3("which", ["dnf"], { timeout: 5e3, stdio: "pipe" });
|
|
15626
|
+
} catch {
|
|
15627
|
+
if (!hostNodeNoDnfLogged) {
|
|
15628
|
+
hostNodeNoDnfLogged = true;
|
|
15629
|
+
log(`[host-node] 'dnf' not found - cannot converge host Node onto ${pin} on this platform (leaving ${current ?? "unknown"} in place)`);
|
|
15630
|
+
}
|
|
15631
|
+
hostNodeConvergence.recordSuccess(pin);
|
|
15632
|
+
return;
|
|
15633
|
+
}
|
|
15634
|
+
const asRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
15635
|
+
const pkg = `nodejs-${pin}`;
|
|
15636
|
+
const dnfArgs = ["-y", "--refresh", "install", pkg];
|
|
15637
|
+
const bin = asRoot ? "dnf" : "sudo";
|
|
15638
|
+
const argv = asRoot ? dnfArgs : ["-n", "dnf", ...dnfArgs];
|
|
15639
|
+
log(`[host-node] converging host Node ${current ?? "unknown"} -> ${pin}\u2026`);
|
|
15640
|
+
const res = await runAsync(bin, argv, { timeout: 6e5 });
|
|
15641
|
+
if (res.code !== 0) {
|
|
15642
|
+
recordHostNodeFailure(pin, `install of ${pkg} failed (exit ${res.code}): ${(res.stderr || res.stdout).slice(0, 300)}`);
|
|
15643
|
+
return;
|
|
15644
|
+
}
|
|
15645
|
+
const after = await diskNodeVersion();
|
|
15646
|
+
if (after !== pin) {
|
|
15647
|
+
recordHostNodeFailure(pin, `installer reported success but on-disk Node is ${after ?? "unreadable"}, not ${pin}`);
|
|
15648
|
+
return;
|
|
15649
|
+
}
|
|
15650
|
+
log(`[host-node] host Node is now ${pin} on disk. Running processes keep the previous binary until they restart - this does NOT restart the manager (ENG-11617).`);
|
|
15651
|
+
hostNodeConvergence.recordSuccess(pin);
|
|
15652
|
+
} catch (err) {
|
|
15653
|
+
recordHostNodeFailure(pin, `install attempt threw: ${isolationImageErrDetail(err)}`);
|
|
15654
|
+
} finally {
|
|
15655
|
+
hostNodeConvergence.endAttempt(pin);
|
|
15656
|
+
}
|
|
15657
|
+
}
|
|
15416
15658
|
async function ensureIsolationImage(imageUri) {
|
|
15417
15659
|
if (process.env.AGT_ISOLATION_IMAGE) return;
|
|
15418
15660
|
if (!imageUri || isolationImageEnsured.has(imageUri)) return;
|
|
@@ -16879,7 +17121,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
16879
17121
|
if (codeNames.length === 0) return;
|
|
16880
17122
|
void (async () => {
|
|
16881
17123
|
try {
|
|
16882
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
17124
|
+
const { collectDiagnostics } = await import("../persistent-session-6O66QEI4.js");
|
|
16883
17125
|
await api.post("/host/heartbeat", {
|
|
16884
17126
|
host_id: hostId,
|
|
16885
17127
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
|
|
@@ -17021,7 +17263,7 @@ async function pollCycleInner() {
|
|
|
17021
17263
|
}
|
|
17022
17264
|
try {
|
|
17023
17265
|
const { detectHostSecurity } = await import("../host-security-KQYYZZVW.js");
|
|
17024
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
17266
|
+
const { collectDiagnostics } = await import("../persistent-session-6O66QEI4.js");
|
|
17025
17267
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
17026
17268
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor) : void 0;
|
|
17027
17269
|
let tailscaleHostname;
|
|
@@ -17229,7 +17471,7 @@ async function pollCycleInner() {
|
|
|
17229
17471
|
collectPanelessActivityProbes,
|
|
17230
17472
|
getResponsivenessIntervalMs,
|
|
17231
17473
|
occupancyQualificationClassifications
|
|
17232
|
-
} = await import("../responsiveness-probe-
|
|
17474
|
+
} = await import("../responsiveness-probe-WGD3NDWG.js");
|
|
17233
17475
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
17234
17476
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
17235
17477
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -17346,7 +17588,7 @@ async function pollCycleInner() {
|
|
|
17346
17588
|
collectResponsivenessProbes,
|
|
17347
17589
|
livePendingInboundOldestAgeSeconds,
|
|
17348
17590
|
parkPendingInbound
|
|
17349
|
-
} = await import("../responsiveness-probe-
|
|
17591
|
+
} = await import("../responsiveness-probe-WGD3NDWG.js");
|
|
17350
17592
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-M6AFZWNU.js");
|
|
17351
17593
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
17352
17594
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -17632,7 +17874,7 @@ async function pollCycleInner() {
|
|
|
17632
17874
|
}
|
|
17633
17875
|
}
|
|
17634
17876
|
);
|
|
17635
|
-
const { parkPendingInbound } = await import("../responsiveness-probe-
|
|
17877
|
+
const { parkPendingInbound } = await import("../responsiveness-probe-WGD3NDWG.js");
|
|
17636
17878
|
const { parked, deadLettered } = parkPendingInbound(codeName, new Date(fatalNowMs));
|
|
17637
17879
|
paneFatalStreak.delete(codeName);
|
|
17638
17880
|
paneFatalRestarts.set(codeName, [...history, fatalNowMs]);
|
|
@@ -17663,7 +17905,7 @@ async function pollCycleInner() {
|
|
|
17663
17905
|
TRANSCRIPT_MOUNT_ESCALATION_REFRESH_MS,
|
|
17664
17906
|
bindSourceEscalations
|
|
17665
17907
|
} = await import("../transcript-mount-health-OHE6IVJV.js");
|
|
17666
|
-
const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-
|
|
17908
|
+
const { transcriptBindSourcesFor, ensureTranscriptBindSources } = await import("../persistent-session-6O66QEI4.js");
|
|
17667
17909
|
const mountConfig = resolveTranscriptMountConfig();
|
|
17668
17910
|
const liveAgents = agentState.persistentSessionAgents;
|
|
17669
17911
|
for (const tracked of [
|
|
@@ -17828,7 +18070,7 @@ async function pollCycleInner() {
|
|
|
17828
18070
|
}
|
|
17829
18071
|
try {
|
|
17830
18072
|
const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-VR5QGP3J.js");
|
|
17831
|
-
const { probeSessionAuth } = await import("../session-auth-dead-
|
|
18073
|
+
const { probeSessionAuth } = await import("../session-auth-dead-6N2AEFKX.js");
|
|
17832
18074
|
const observations = [];
|
|
17833
18075
|
const pendingCacheCommits = [];
|
|
17834
18076
|
const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
|
|
@@ -20633,6 +20875,9 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
20633
20875
|
log(`[isolation-image] unexpected managed-pull failure: ${isolationImageErrDetail(err)}`);
|
|
20634
20876
|
});
|
|
20635
20877
|
}
|
|
20878
|
+
void ensureHostNodeVersion(refreshAny.desired_node_version).catch((err) => {
|
|
20879
|
+
log(`[host-node] unexpected convergence failure: ${isolationImageErrDetail(err)}`);
|
|
20880
|
+
});
|
|
20636
20881
|
const agentFw2 = agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK;
|
|
20637
20882
|
if (agentFw2 === "claude-code" && installedIntegrationSkills.length > 0 && isSessionHealthy(agent.code_name)) {
|
|
20638
20883
|
const names = installedIntegrationSkills.join(", ");
|
|
@@ -22423,7 +22668,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
22423
22668
|
try {
|
|
22424
22669
|
const freshId = rotateSessionForWedge(codeName);
|
|
22425
22670
|
consecutiveWedgeCycles.delete(codeName);
|
|
22426
|
-
const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-
|
|
22671
|
+
const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-WGD3NDWG.js");
|
|
22427
22672
|
const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
|
|
22428
22673
|
const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
|
|
22429
22674
|
const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
|
|
@@ -22466,7 +22711,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
22466
22711
|
void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
|
|
22467
22712
|
void (async () => {
|
|
22468
22713
|
try {
|
|
22469
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
22714
|
+
const { collectDiagnostics } = await import("../persistent-session-6O66QEI4.js");
|
|
22470
22715
|
await api.post("/host/heartbeat", {
|
|
22471
22716
|
host_id: hostId,
|
|
22472
22717
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
|
|
@@ -22517,7 +22762,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
22517
22762
|
}
|
|
22518
22763
|
try {
|
|
22519
22764
|
const hostId = await getHostId();
|
|
22520
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
22765
|
+
const { collectDiagnostics } = await import("../persistent-session-6O66QEI4.js");
|
|
22521
22766
|
await api.post("/host/heartbeat", {
|
|
22522
22767
|
host_id: hostId,
|
|
22523
22768
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor, runtimeVersionFor)
|
|
@@ -23190,7 +23435,7 @@ async function processClaudePairSessions(agents) {
|
|
|
23190
23435
|
// cannot take it for itself — by the time it runs, the write it is looking
|
|
23191
23436
|
// for may already have happened.
|
|
23192
23437
|
snapshotPairConfig
|
|
23193
|
-
} = await import("../claude-pair-runtime-
|
|
23438
|
+
} = await import("../claude-pair-runtime-BOTE3DRW.js");
|
|
23194
23439
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
23195
23440
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
23196
23441
|
const killed = await killPairSession(pairTmuxSession(pairId));
|