@integrity-labs/agt-cli 0.27.60 → 0.27.61
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 +95 -3
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-2YSXMB7P.js → chunk-I4RL6YLR.js} +1 -1
- package/dist/lib/manager-worker.js +212 -21
- package/dist/lib/manager-worker.js.map +1 -1
- package/package.json +1 -1
- /package/dist/{chunk-2YSXMB7P.js.map → chunk-I4RL6YLR.js.map} +0 -0
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
provisionOrientHook,
|
|
16
16
|
provisionStopHook,
|
|
17
17
|
requireHost
|
|
18
|
-
} from "../chunk-
|
|
18
|
+
} from "../chunk-I4RL6YLR.js";
|
|
19
19
|
import {
|
|
20
20
|
getProjectDir as getProjectDir2,
|
|
21
21
|
getReadyTasks,
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
isAgentPromptReady,
|
|
35
35
|
isSessionHealthy,
|
|
36
36
|
isStaleForToday,
|
|
37
|
+
paneLogPath,
|
|
37
38
|
peekCurrentSession,
|
|
38
39
|
prepareForRespawn,
|
|
39
40
|
readPaneLogTail,
|
|
@@ -1177,6 +1178,109 @@ function formatCoalesceDeferLogLine(opts) {
|
|
|
1177
1178
|
return `[self-update] coalescing \u2014 ${opts.installed} \u2192 ${opts.latest} (${opts.channelLabel}) available, deferring for ${remainingSec}s (last restart inside ${windowMin}min window). See ENG-5862. Override with AGT_SELF_UPDATE_COALESCE_MS=0 during incident response.`;
|
|
1178
1179
|
}
|
|
1179
1180
|
|
|
1181
|
+
// src/lib/maintenance-window.ts
|
|
1182
|
+
var DEFAULT_WINDOW_START = "01:00";
|
|
1183
|
+
var DEFAULT_WINDOW_END = "02:00";
|
|
1184
|
+
function isMaintenanceWindowDisabled(env = process.env) {
|
|
1185
|
+
return env["AGT_MAINTENANCE_WINDOW_DISABLE"] === "1";
|
|
1186
|
+
}
|
|
1187
|
+
var HHMM_RE = /^([01]\d|2[0-3]):([0-5]\d)$/;
|
|
1188
|
+
function normalizeHhmm(value) {
|
|
1189
|
+
if (typeof value !== "string") return null;
|
|
1190
|
+
const trimmed = value.trim();
|
|
1191
|
+
return HHMM_RE.test(trimmed) ? trimmed : null;
|
|
1192
|
+
}
|
|
1193
|
+
function resolveWindow(input) {
|
|
1194
|
+
const tzRaw = typeof input.timezone === "string" ? input.timezone.trim() : "";
|
|
1195
|
+
return {
|
|
1196
|
+
start: normalizeHhmm(input.start) ?? DEFAULT_WINDOW_START,
|
|
1197
|
+
end: normalizeHhmm(input.end) ?? DEFAULT_WINDOW_END,
|
|
1198
|
+
// Blank/whitespace → UTC. An explicit 'UTC' is also UTC. (Unlike
|
|
1199
|
+
// getTeamTimezone we keep 'UTC' here because this is the *evaluation* tz,
|
|
1200
|
+
// not an inherit-or-not decision.)
|
|
1201
|
+
timezone: tzRaw.length > 0 ? tzRaw : "UTC"
|
|
1202
|
+
};
|
|
1203
|
+
}
|
|
1204
|
+
function hhmmToMinutes(hhmm) {
|
|
1205
|
+
const [h, m] = hhmm.split(":");
|
|
1206
|
+
return Number(h) * 60 + Number(m);
|
|
1207
|
+
}
|
|
1208
|
+
function localHhmm(now, timezone) {
|
|
1209
|
+
try {
|
|
1210
|
+
const parts = new Intl.DateTimeFormat("en-GB", {
|
|
1211
|
+
timeZone: timezone,
|
|
1212
|
+
hour: "2-digit",
|
|
1213
|
+
minute: "2-digit",
|
|
1214
|
+
hour12: false
|
|
1215
|
+
}).formatToParts(now);
|
|
1216
|
+
const hh = parts.find((p) => p.type === "hour")?.value ?? "00";
|
|
1217
|
+
const mm = parts.find((p) => p.type === "minute")?.value ?? "00";
|
|
1218
|
+
const h = hh === "24" ? "00" : hh;
|
|
1219
|
+
return `${h}:${mm}`;
|
|
1220
|
+
} catch {
|
|
1221
|
+
const h = String(now.getUTCHours()).padStart(2, "0");
|
|
1222
|
+
const m = String(now.getUTCMinutes()).padStart(2, "0");
|
|
1223
|
+
return `${h}:${m}`;
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
function isWithinMaintenanceWindow(input, now) {
|
|
1227
|
+
const w = resolveWindow(input);
|
|
1228
|
+
const start = hhmmToMinutes(w.start);
|
|
1229
|
+
const end = hhmmToMinutes(w.end);
|
|
1230
|
+
if (start === end) return false;
|
|
1231
|
+
const cur = hhmmToMinutes(localHhmm(now, w.timezone));
|
|
1232
|
+
if (start < end) return cur >= start && cur < end;
|
|
1233
|
+
return cur >= start || cur < end;
|
|
1234
|
+
}
|
|
1235
|
+
function minutesUntilWindowOpen(input, now) {
|
|
1236
|
+
if (isWithinMaintenanceWindow(input, now)) return 0;
|
|
1237
|
+
const w = resolveWindow(input);
|
|
1238
|
+
const start = hhmmToMinutes(w.start);
|
|
1239
|
+
const cur = hhmmToMinutes(localHhmm(now, w.timezone));
|
|
1240
|
+
return cur <= start ? start - cur : 1440 - cur + start;
|
|
1241
|
+
}
|
|
1242
|
+
function formatWindowDeferLogLine(input, now) {
|
|
1243
|
+
const w = resolveWindow(input);
|
|
1244
|
+
const mins = minutesUntilWindowOpen(input, now);
|
|
1245
|
+
return `next maintenance window ${w.start} ${w.timezone} (~${mins} min)`;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
// src/lib/update-window-gate.ts
|
|
1249
|
+
function decideMaintenanceWindowGate(opts) {
|
|
1250
|
+
if (isMaintenanceWindowDisabled(opts.env)) return "proceed";
|
|
1251
|
+
if (!opts.window) return "proceed";
|
|
1252
|
+
return isWithinMaintenanceWindow(opts.window, opts.now) ? "proceed" : "defer";
|
|
1253
|
+
}
|
|
1254
|
+
function isUrgentUpgrade(opts) {
|
|
1255
|
+
if (!opts.urgentTarget) return false;
|
|
1256
|
+
if (opts.installed === "dev") return false;
|
|
1257
|
+
return opts.isNewer(opts.installed, opts.urgentTarget);
|
|
1258
|
+
}
|
|
1259
|
+
var RESTART_IDLE_THRESHOLD_SECONDS = 120;
|
|
1260
|
+
var RESTART_INBOUND_QUIET_SECONDS = 300;
|
|
1261
|
+
var GATEABLE_RESTART_REASONS = /* @__PURE__ */ new Set([
|
|
1262
|
+
"model-change",
|
|
1263
|
+
"channel-set-change",
|
|
1264
|
+
"sender-policy-change",
|
|
1265
|
+
"hot-reload-mcp",
|
|
1266
|
+
"mcp-presence-reaper"
|
|
1267
|
+
]);
|
|
1268
|
+
function isGateableRestartReason(reason) {
|
|
1269
|
+
return reason != null && GATEABLE_RESTART_REASONS.has(reason);
|
|
1270
|
+
}
|
|
1271
|
+
function decideRestartGate(opts) {
|
|
1272
|
+
if (isMaintenanceWindowDisabled(opts.env)) return "proceed";
|
|
1273
|
+
if (opts.window && !isWithinMaintenanceWindow(opts.window, opts.now)) {
|
|
1274
|
+
return "defer-window";
|
|
1275
|
+
}
|
|
1276
|
+
const paneThreshold = opts.idleThresholdSeconds ?? RESTART_IDLE_THRESHOLD_SECONDS;
|
|
1277
|
+
const inboundThreshold = opts.inboundQuietSeconds ?? RESTART_INBOUND_QUIET_SECONDS;
|
|
1278
|
+
const paneBusy = opts.paneLogAgeSeconds !== null && opts.paneLogAgeSeconds < paneThreshold;
|
|
1279
|
+
const inboundBusy = opts.inboundAgeSeconds !== null && opts.inboundAgeSeconds < inboundThreshold;
|
|
1280
|
+
if (paneBusy || inboundBusy) return "defer-idle";
|
|
1281
|
+
return "proceed";
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1180
1284
|
// src/lib/claude-pid-tracker.ts
|
|
1181
1285
|
import { existsSync, readFileSync as readFileSync3 } from "fs";
|
|
1182
1286
|
function readPidFile(path) {
|
|
@@ -3375,6 +3479,14 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
|
|
|
3375
3479
|
}
|
|
3376
3480
|
const timer = setTimeout(() => {
|
|
3377
3481
|
pendingSessionRestarts.delete(codeName);
|
|
3482
|
+
const gate = restartGateFor(codeName, breakerReason);
|
|
3483
|
+
if (gate !== "bypass" && gate !== "proceed") {
|
|
3484
|
+
log(
|
|
3485
|
+
`[maintenance-window] Deferring '${reason}' restart for '${codeName}' (${gate}) \u2014 re-checking in ${RESTART_DEFER_RECHECK_MS / 1e3}s`
|
|
3486
|
+
);
|
|
3487
|
+
scheduleSessionRestart(codeName, RESTART_DEFER_RECHECK_MS, reason, breakerReason);
|
|
3488
|
+
return;
|
|
3489
|
+
}
|
|
3378
3490
|
stopPersistentSession(codeName, log);
|
|
3379
3491
|
runningMcpHashes.delete(codeName);
|
|
3380
3492
|
recordRestartForBreaker(codeName, breakerReason);
|
|
@@ -3390,6 +3502,34 @@ function cancelPendingSessionRestart(codeName) {
|
|
|
3390
3502
|
pendingSessionRestarts.delete(codeName);
|
|
3391
3503
|
log(`[hot-reload] Cancelled pending restart timer for '${codeName}' (another teardown path is handling it)`);
|
|
3392
3504
|
}
|
|
3505
|
+
var RESTART_DEFER_RECHECK_MS = 6e4;
|
|
3506
|
+
var lastInboundMs = /* @__PURE__ */ new Map();
|
|
3507
|
+
function noteInbound(codeName) {
|
|
3508
|
+
lastInboundMs.set(codeName, Date.now());
|
|
3509
|
+
}
|
|
3510
|
+
function inboundAgeSecondsFor(codeName) {
|
|
3511
|
+
const ts = lastInboundMs.get(codeName);
|
|
3512
|
+
if (ts === void 0) return null;
|
|
3513
|
+
return Math.max(0, Math.floor((Date.now() - ts) / 1e3));
|
|
3514
|
+
}
|
|
3515
|
+
function paneLogAgeSecondsFor(codeName) {
|
|
3516
|
+
try {
|
|
3517
|
+
const mtimeMs = statSync2(paneLogPath(codeName)).mtimeMs;
|
|
3518
|
+
return Math.max(0, Math.floor((Date.now() - mtimeMs) / 1e3));
|
|
3519
|
+
} catch (err) {
|
|
3520
|
+
if (err?.code === "ENOENT") return null;
|
|
3521
|
+
return 0;
|
|
3522
|
+
}
|
|
3523
|
+
}
|
|
3524
|
+
function restartGateFor(codeName, breakerReason) {
|
|
3525
|
+
if (!isGateableRestartReason(breakerReason)) return "bypass";
|
|
3526
|
+
return decideRestartGate({
|
|
3527
|
+
window: cachedMaintenanceWindow,
|
|
3528
|
+
paneLogAgeSeconds: paneLogAgeSecondsFor(codeName),
|
|
3529
|
+
inboundAgeSeconds: inboundAgeSecondsFor(codeName),
|
|
3530
|
+
now: /* @__PURE__ */ new Date()
|
|
3531
|
+
});
|
|
3532
|
+
}
|
|
3393
3533
|
var runningMcpHashes = /* @__PURE__ */ new Map();
|
|
3394
3534
|
var runningMcpServerKeys = /* @__PURE__ */ new Map();
|
|
3395
3535
|
function projectMcpHash(_codeName, projectDir) {
|
|
@@ -3468,6 +3608,11 @@ async function runAgentConnectivityProbes(agent, integrations, projectDir) {
|
|
|
3468
3608
|
}
|
|
3469
3609
|
}
|
|
3470
3610
|
function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason) {
|
|
3611
|
+
const gate = restartGateFor(codeName, breakerReason);
|
|
3612
|
+
if (gate !== "bypass" && gate !== "proceed") {
|
|
3613
|
+
log(`[maintenance-window] Deferring '${breakerReason}' restart for '${codeName}' (${gate})`);
|
|
3614
|
+
return;
|
|
3615
|
+
}
|
|
3471
3616
|
cancelPendingSessionRestart(codeName);
|
|
3472
3617
|
stopPersistentSession(codeName, log);
|
|
3473
3618
|
runningMcpHashes.delete(codeName);
|
|
@@ -3595,10 +3740,11 @@ function clearAgentCaches(agentId, codeName) {
|
|
|
3595
3740
|
if (channelCacheMutated) saveChannelHashCache2();
|
|
3596
3741
|
}
|
|
3597
3742
|
var cachedFrameworkVersion = null;
|
|
3743
|
+
var cachedMaintenanceWindow = null;
|
|
3598
3744
|
var lastVersionCheckAt = 0;
|
|
3599
3745
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
3600
3746
|
var lastResponsivenessProbeAt = 0;
|
|
3601
|
-
var agtCliVersion = true ? "0.27.
|
|
3747
|
+
var agtCliVersion = true ? "0.27.61" : "dev";
|
|
3602
3748
|
function resolveBrewPath(execFileSync4) {
|
|
3603
3749
|
try {
|
|
3604
3750
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -3867,6 +4013,9 @@ function claudeCodeUpgradeThrottled() {
|
|
|
3867
4013
|
async function maybeUpgradeClaudeCode() {
|
|
3868
4014
|
if (claudeCodeUpgradeInFlight) return;
|
|
3869
4015
|
if (claudeCodeUpgradeThrottled()) return;
|
|
4016
|
+
if (decideMaintenanceWindowGate({ window: cachedMaintenanceWindow, now: /* @__PURE__ */ new Date() }) === "defer") {
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
3870
4019
|
claudeCodeUpgradeInFlight = true;
|
|
3871
4020
|
stampClaudeCodeUpgradeMarker();
|
|
3872
4021
|
const { execFileSync: execFileSync4 } = await import("child_process");
|
|
@@ -3972,6 +4121,12 @@ async function checkAndUpdateCliViaBrew() {
|
|
|
3972
4121
|
if (agtOutdated) {
|
|
3973
4122
|
const installed = agtOutdated.installed_versions?.[0] ?? "unknown";
|
|
3974
4123
|
const latest = agtOutdated.current_version ?? "unknown";
|
|
4124
|
+
if (decideMaintenanceWindowGate({ window: cachedMaintenanceWindow, now: /* @__PURE__ */ new Date() }) === "defer") {
|
|
4125
|
+
log(
|
|
4126
|
+
`[self-update] agt CLI ${installed} \u2192 ${latest} (brew) deferred \u2014 ` + formatWindowDeferLogLine(cachedMaintenanceWindow ?? {}, /* @__PURE__ */ new Date())
|
|
4127
|
+
);
|
|
4128
|
+
return;
|
|
4129
|
+
}
|
|
3975
4130
|
const coalesceWindowMs = resolveCoalesceWindowMs();
|
|
3976
4131
|
const coalesce = decideSelfUpdateCoalesce({
|
|
3977
4132
|
windowMs: coalesceWindowMs,
|
|
@@ -4010,7 +4165,6 @@ async function checkAndUpdateCliViaBrew() {
|
|
|
4010
4165
|
}
|
|
4011
4166
|
}
|
|
4012
4167
|
async function checkAndUpdateCliViaNpm() {
|
|
4013
|
-
const { execFileSync: execFileSync4 } = await import("child_process");
|
|
4014
4168
|
if (agtCliVersion === "dev") return;
|
|
4015
4169
|
const channel = process.env.AGT_CLI_RELEASE_CHANNEL || "latest";
|
|
4016
4170
|
let latest;
|
|
@@ -4036,6 +4190,18 @@ async function checkAndUpdateCliViaNpm() {
|
|
|
4036
4190
|
log(`[self-update] npm registry fetch failed: ${err.message}`);
|
|
4037
4191
|
return;
|
|
4038
4192
|
}
|
|
4193
|
+
const urgentTarget = await fetchUrgentDistTagVersion();
|
|
4194
|
+
if (isUrgentUpgrade({
|
|
4195
|
+
urgentTarget,
|
|
4196
|
+
installed: agtCliVersion,
|
|
4197
|
+
isNewer: (installed, candidate) => candidate !== installed && !isOlderSemverTuple(installed, candidate)
|
|
4198
|
+
})) {
|
|
4199
|
+
log(
|
|
4200
|
+
`[self-update] URGENT agt CLI hotfix ${agtCliVersion} \u2192 ${urgentTarget} (overrides channel=${channel} + maintenance window). Upgrading via npm...`
|
|
4201
|
+
);
|
|
4202
|
+
await installAgtCliViaNpm(urgentTarget, "urgent");
|
|
4203
|
+
return;
|
|
4204
|
+
}
|
|
4039
4205
|
let shouldUpdate;
|
|
4040
4206
|
if (channel === "latest") {
|
|
4041
4207
|
shouldUpdate = isNewerSemver(agtCliVersion, latest);
|
|
@@ -4056,6 +4222,12 @@ async function checkAndUpdateCliViaNpm() {
|
|
|
4056
4222
|
}
|
|
4057
4223
|
return;
|
|
4058
4224
|
}
|
|
4225
|
+
if (decideMaintenanceWindowGate({ window: cachedMaintenanceWindow, now: /* @__PURE__ */ new Date() }) === "defer") {
|
|
4226
|
+
log(
|
|
4227
|
+
`[self-update] agt CLI ${agtCliVersion} \u2192 ${latest} (channel=${channel}) deferred \u2014 ` + formatWindowDeferLogLine(cachedMaintenanceWindow ?? {}, /* @__PURE__ */ new Date())
|
|
4228
|
+
);
|
|
4229
|
+
return;
|
|
4230
|
+
}
|
|
4059
4231
|
const coalesceWindowMs = resolveCoalesceWindowMs();
|
|
4060
4232
|
const coalesce = decideSelfUpdateCoalesce({
|
|
4061
4233
|
windowMs: coalesceWindowMs,
|
|
@@ -4073,27 +4245,40 @@ async function checkAndUpdateCliViaNpm() {
|
|
|
4073
4245
|
return;
|
|
4074
4246
|
}
|
|
4075
4247
|
log(`[self-update] agt CLI update available: ${agtCliVersion} \u2192 ${latest} (channel=${channel}). Upgrading via npm...`);
|
|
4248
|
+
await installAgtCliViaNpm(latest, `channel=${channel}`);
|
|
4249
|
+
}
|
|
4250
|
+
async function fetchUrgentDistTagVersion() {
|
|
4251
|
+
try {
|
|
4252
|
+
const res = await fetch("https://registry.npmjs.org/@integrity-labs/agt-cli/urgent", {
|
|
4253
|
+
signal: AbortSignal.timeout(1e4),
|
|
4254
|
+
headers: { Accept: "application/json" }
|
|
4255
|
+
});
|
|
4256
|
+
if (!res.ok) return null;
|
|
4257
|
+
const body = await res.json();
|
|
4258
|
+
return body.version ?? null;
|
|
4259
|
+
} catch {
|
|
4260
|
+
return null;
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
async function installAgtCliViaNpm(version, reasonLabel) {
|
|
4264
|
+
const { execFileSync: execFileSync4 } = await import("child_process");
|
|
4076
4265
|
const isRoot = typeof process.getuid === "function" && process.getuid() === 0;
|
|
4077
4266
|
const cmd = isRoot ? "npm" : "sudo";
|
|
4078
|
-
const
|
|
4079
|
-
"install",
|
|
4080
|
-
"-g",
|
|
4081
|
-
`@integrity-labs/agt-cli@${latest}`,
|
|
4082
|
-
"--registry=https://registry.npmjs.org"
|
|
4083
|
-
] : [
|
|
4084
|
-
"-n",
|
|
4085
|
-
"npm",
|
|
4267
|
+
const installArgs = [
|
|
4086
4268
|
"install",
|
|
4087
4269
|
"-g",
|
|
4088
|
-
`@integrity-labs/agt-cli@${
|
|
4270
|
+
`@integrity-labs/agt-cli@${version}`,
|
|
4089
4271
|
"--registry=https://registry.npmjs.org"
|
|
4090
4272
|
];
|
|
4273
|
+
const args = isRoot ? installArgs : ["-n", "npm", ...installArgs];
|
|
4091
4274
|
try {
|
|
4092
4275
|
execFileSync4(cmd, args, { timeout: 18e4, stdio: "pipe" });
|
|
4093
|
-
log(
|
|
4276
|
+
log(
|
|
4277
|
+
`[self-update] agt CLI upgraded to ${version} (${reasonLabel}). Scheduling manager restart so the new binary takes effect.`
|
|
4278
|
+
);
|
|
4094
4279
|
stampLastSelfUpdateApplied(selfUpdateAppliedMarkerPath());
|
|
4095
4280
|
restartAfterUpgrade = true;
|
|
4096
|
-
pendingUpgradeVersion =
|
|
4281
|
+
pendingUpgradeVersion = version;
|
|
4097
4282
|
} catch (err) {
|
|
4098
4283
|
log(`[self-update] npm upgrade failed: ${err.message}`);
|
|
4099
4284
|
}
|
|
@@ -4612,7 +4797,7 @@ async function pollCycle() {
|
|
|
4612
4797
|
log,
|
|
4613
4798
|
resolveFramework: (codeName) => agentFrameworkCache.get(codeName) ?? null,
|
|
4614
4799
|
stopSession: (codeName) => {
|
|
4615
|
-
stopPersistentSessionAndForgetMcpBaseline(codeName, "channel-
|
|
4800
|
+
stopPersistentSessionAndForgetMcpBaseline(codeName, "channel-restart-flag");
|
|
4616
4801
|
agentState.persistentSessionAgents.delete(codeName);
|
|
4617
4802
|
claudeAuthTupleBySession.delete(codeName);
|
|
4618
4803
|
},
|
|
@@ -4724,13 +4909,18 @@ async function pollCycle() {
|
|
|
4724
4909
|
// behind a fresh heartbeat.
|
|
4725
4910
|
realtime_socket_connected: isRealtimeSocketConnected()
|
|
4726
4911
|
});
|
|
4912
|
+
if (hbResp?.maintenance_window) {
|
|
4913
|
+
cachedMaintenanceWindow = hbResp.maintenance_window;
|
|
4914
|
+
}
|
|
4727
4915
|
try {
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4916
|
+
if (decideMaintenanceWindowGate({ window: cachedMaintenanceWindow, now: /* @__PURE__ */ new Date() }) === "proceed") {
|
|
4917
|
+
const { maybeUpdateClaudeCode } = await import("../claude-code-updater-4E5T2X3Z.js");
|
|
4918
|
+
await maybeUpdateClaudeCode({
|
|
4919
|
+
desiredVersion: hbResp?.desired_claude_code_version ?? "latest",
|
|
4920
|
+
currentVersion: cachedFrameworkVersion,
|
|
4921
|
+
log
|
|
4922
|
+
});
|
|
4923
|
+
}
|
|
4734
4924
|
} catch (err) {
|
|
4735
4925
|
log(`Claude Code updater error: ${err.message}`);
|
|
4736
4926
|
}
|
|
@@ -7779,6 +7969,7 @@ async function pollDirectChatMessages(agentStates) {
|
|
|
7779
7969
|
}
|
|
7780
7970
|
}
|
|
7781
7971
|
async function processDirectChatMessage(agent, msg) {
|
|
7972
|
+
noteInbound(agent.codeName);
|
|
7782
7973
|
const fw = agentFrameworkCache.get(agent.codeName) ?? "openclaw";
|
|
7783
7974
|
log(`[direct-chat] Processing message for '${agent.codeName}' (fw=${fw}): id=${msg.id} len=${msg.content.length}`);
|
|
7784
7975
|
if (isDirectChatMessageExpired(msg.created_at, Date.now(), directChatMaxAgeMs())) {
|