@integrity-labs/agt-cli 0.28.694 → 0.28.696
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-YLADZNC5.js → chunk-QCYRC5FK.js} +2 -2
- package/dist/{chunk-7F4RC4PU.js → chunk-WB6ERJPU.js} +4 -4
- package/dist/{chunk-NYWCE5JH.js → chunk-Y7AHOXHP.js} +255 -80
- package/dist/chunk-Y7AHOXHP.js.map +1 -0
- package/dist/{claude-pair-runtime-WRVD63Q7.js → claude-pair-runtime-I7MIDQSW.js} +2 -2
- package/dist/lib/manager-worker.js +271 -144
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +114 -79
- package/dist/mcp/index.js +49 -4
- package/dist/mcp/origami.js +49 -4
- package/dist/mcp/slack-channel.js +114 -79
- package/dist/mcp/telegram-channel.js +114 -79
- package/dist/{persistent-session-WC27KXJE.js → persistent-session-5ZWDVVIH.js} +3 -3
- package/dist/{responsiveness-probe-V5M5OXNB.js → responsiveness-probe-KDQFIROB.js} +3 -3
- package/dist/{session-auth-dead-TVTRCTJR.js → session-auth-dead-7S7IQGNX.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-NYWCE5JH.js.map +0 -1
- /package/dist/{chunk-YLADZNC5.js.map → chunk-QCYRC5FK.js.map} +0 -0
- /package/dist/{chunk-7F4RC4PU.js.map → chunk-WB6ERJPU.js.map} +0 -0
- /package/dist/{claude-pair-runtime-WRVD63Q7.js.map → claude-pair-runtime-I7MIDQSW.js.map} +0 -0
- /package/dist/{persistent-session-WC27KXJE.js.map → persistent-session-5ZWDVVIH.js.map} +0 -0
- /package/dist/{responsiveness-probe-V5M5OXNB.js.map → responsiveness-probe-KDQFIROB.js.map} +0 -0
- /package/dist/{session-auth-dead-TVTRCTJR.js.map → session-auth-dead-7S7IQGNX.js.map} +0 -0
|
@@ -54,7 +54,7 @@ import {
|
|
|
54
54
|
safeWriteJsonAtomic,
|
|
55
55
|
setConfigHash,
|
|
56
56
|
tripClass
|
|
57
|
-
} from "../chunk-
|
|
57
|
+
} from "../chunk-WB6ERJPU.js";
|
|
58
58
|
import {
|
|
59
59
|
getProjectDir as getProjectDir2,
|
|
60
60
|
getReadyTasks,
|
|
@@ -112,7 +112,7 @@ import {
|
|
|
112
112
|
takeZombieDetection,
|
|
113
113
|
toOpencodeModel,
|
|
114
114
|
writeEgressAllowlist
|
|
115
|
-
} from "../chunk-
|
|
115
|
+
} from "../chunk-QCYRC5FK.js";
|
|
116
116
|
import {
|
|
117
117
|
ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
|
|
118
118
|
AnchorSessionClient,
|
|
@@ -136,6 +136,7 @@ import {
|
|
|
136
136
|
appendDmFooter,
|
|
137
137
|
attributeTranscriptUsageByRun,
|
|
138
138
|
buildFailureCategoryPromptLines,
|
|
139
|
+
buildHostUsageReading,
|
|
139
140
|
buildScheduledTaskContextBlocks,
|
|
140
141
|
classifyActor,
|
|
141
142
|
classifyCursorAdvance,
|
|
@@ -181,6 +182,7 @@ import {
|
|
|
181
182
|
parseDeliveryTarget,
|
|
182
183
|
parseTranscriptUsage,
|
|
183
184
|
parseUsageBanner,
|
|
185
|
+
parseUsageReport,
|
|
184
186
|
peekCurrentSession,
|
|
185
187
|
pickNewerClassification,
|
|
186
188
|
remoteMcpServerKey,
|
|
@@ -190,10 +192,11 @@ import {
|
|
|
190
192
|
resolveDmTarget,
|
|
191
193
|
serializeAccountEnforcementMarker,
|
|
192
194
|
sessionTranscriptDir,
|
|
195
|
+
stabiliseResetInstant,
|
|
193
196
|
subagentActivityAgeSeconds,
|
|
194
197
|
sumTranscriptUsageInWindow,
|
|
195
198
|
transcriptActivityAgeSeconds
|
|
196
|
-
} from "../chunk-
|
|
199
|
+
} from "../chunk-Y7AHOXHP.js";
|
|
197
200
|
import {
|
|
198
201
|
reapOrphanChannelMcps
|
|
199
202
|
} from "../chunk-XWVM4KPK.js";
|
|
@@ -2504,6 +2507,89 @@ async function maybeReportUsageBanner(args) {
|
|
|
2504
2507
|
}
|
|
2505
2508
|
}
|
|
2506
2509
|
|
|
2510
|
+
// src/lib/host-usage-poller.ts
|
|
2511
|
+
var HOST_USAGE_POLL_INTERVAL_MS = 15 * 60 * 1e3;
|
|
2512
|
+
var HOST_USAGE_POLL_TIMEOUT_MS = 6e4;
|
|
2513
|
+
var USAGE_COMMAND_ARGS = ["-p", "/usage", "--output-format", "json"];
|
|
2514
|
+
var state2 = {
|
|
2515
|
+
lastPolledAt: 0,
|
|
2516
|
+
inFlight: false,
|
|
2517
|
+
lastWeekResetsAt: null,
|
|
2518
|
+
lastSessionResetsAt: null
|
|
2519
|
+
};
|
|
2520
|
+
function extractUsageText(stdout) {
|
|
2521
|
+
try {
|
|
2522
|
+
const parsed = JSON.parse(stdout);
|
|
2523
|
+
if (!parsed || typeof parsed !== "object") return null;
|
|
2524
|
+
const envelope = parsed;
|
|
2525
|
+
if (envelope.is_error === true) return null;
|
|
2526
|
+
return typeof envelope.result === "string" ? envelope.result : null;
|
|
2527
|
+
} catch {
|
|
2528
|
+
return null;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2531
|
+
async function maybePollHostUsage(deps) {
|
|
2532
|
+
const { api: api2, runUsageCommand, authMode, cliVersion, log: log2 } = deps;
|
|
2533
|
+
const now = deps.now ?? /* @__PURE__ */ new Date();
|
|
2534
|
+
const nowMs = now.getTime();
|
|
2535
|
+
if (state2.inFlight) return;
|
|
2536
|
+
if (nowMs - state2.lastPolledAt < HOST_USAGE_POLL_INTERVAL_MS) return;
|
|
2537
|
+
state2.inFlight = true;
|
|
2538
|
+
try {
|
|
2539
|
+
let reading;
|
|
2540
|
+
try {
|
|
2541
|
+
const { stdout, failed } = await runUsageCommand();
|
|
2542
|
+
const text = failed ? null : extractUsageText(stdout);
|
|
2543
|
+
reading = buildHostUsageReading({
|
|
2544
|
+
report: text === null ? null : parseUsageReport(text, now),
|
|
2545
|
+
readAt: now,
|
|
2546
|
+
cliVersion,
|
|
2547
|
+
authMode,
|
|
2548
|
+
pollFailed: failed
|
|
2549
|
+
});
|
|
2550
|
+
} catch (err) {
|
|
2551
|
+
log2(`[host-usage] /usage poll failed: ${err.message}`);
|
|
2552
|
+
reading = buildHostUsageReading({
|
|
2553
|
+
report: null,
|
|
2554
|
+
readAt: now,
|
|
2555
|
+
cliVersion,
|
|
2556
|
+
authMode,
|
|
2557
|
+
pollFailed: true
|
|
2558
|
+
});
|
|
2559
|
+
}
|
|
2560
|
+
const weekResetsAt = stabiliseResetInstant(state2.lastWeekResetsAt, reading.weekResetsAt);
|
|
2561
|
+
const sessionResetsAt = stabiliseResetInstant(
|
|
2562
|
+
state2.lastSessionResetsAt,
|
|
2563
|
+
reading.sessionResetsAt
|
|
2564
|
+
);
|
|
2565
|
+
await api2.post("/host/usage-readings", {
|
|
2566
|
+
state: reading.state,
|
|
2567
|
+
week_pct: reading.weekPct,
|
|
2568
|
+
week_resets_at: weekResetsAt ? weekResetsAt.toISOString() : null,
|
|
2569
|
+
session_pct: reading.sessionPct,
|
|
2570
|
+
session_resets_at: sessionResetsAt ? sessionResetsAt.toISOString() : null,
|
|
2571
|
+
read_at: reading.readAt.toISOString(),
|
|
2572
|
+
cli_version: reading.cliVersion,
|
|
2573
|
+
source: reading.source,
|
|
2574
|
+
unknown_reason: reading.unknownReason
|
|
2575
|
+
});
|
|
2576
|
+
state2.lastWeekResetsAt = weekResetsAt;
|
|
2577
|
+
state2.lastSessionResetsAt = sessionResetsAt;
|
|
2578
|
+
if (reading.state === "ok") {
|
|
2579
|
+
log2(
|
|
2580
|
+
`[host-usage] week ${reading.weekPct}%` + (weekResetsAt ? ` (resets ${weekResetsAt.toISOString()})` : "") + `, session ${reading.sessionPct}%`
|
|
2581
|
+
);
|
|
2582
|
+
} else if (reading.state === "unknown") {
|
|
2583
|
+
log2(`[host-usage] reading unknown: ${reading.unknownReason}`);
|
|
2584
|
+
}
|
|
2585
|
+
} catch (err) {
|
|
2586
|
+
log2(`[host-usage] post failed: ${err.message}`);
|
|
2587
|
+
} finally {
|
|
2588
|
+
state2.lastPolledAt = nowMs;
|
|
2589
|
+
state2.inFlight = false;
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2507
2593
|
// src/lib/claude-account-fingerprint.ts
|
|
2508
2594
|
import { createHash as createHash6 } from "crypto";
|
|
2509
2595
|
import { readFile as readFile3, readdir as readdir3 } from "fs/promises";
|
|
@@ -2785,12 +2871,12 @@ import { join as join13 } from "path";
|
|
|
2785
2871
|
var MIN_CHECK_INTERVAL_MS2 = 6e4;
|
|
2786
2872
|
var TRANSCRIPT_MTIME_WINDOW_MS = 2 * 24 * 60 * 60 * 1e3;
|
|
2787
2873
|
var MAX_ENTRIES_PER_POST = 200;
|
|
2788
|
-
var
|
|
2874
|
+
var state3 = /* @__PURE__ */ new Map();
|
|
2789
2875
|
async function maybeReportTokenUsage(args) {
|
|
2790
2876
|
const { api: api2, codeName, agentId, log: log2 } = args;
|
|
2791
2877
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
2792
2878
|
const nowMs = now.getTime();
|
|
2793
|
-
const existing =
|
|
2879
|
+
const existing = state3.get(codeName);
|
|
2794
2880
|
if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS2) {
|
|
2795
2881
|
return;
|
|
2796
2882
|
}
|
|
@@ -2801,7 +2887,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2801
2887
|
try {
|
|
2802
2888
|
dirEntries = readdirSync(dir);
|
|
2803
2889
|
} catch {
|
|
2804
|
-
|
|
2890
|
+
state3.set(codeName, next);
|
|
2805
2891
|
return;
|
|
2806
2892
|
}
|
|
2807
2893
|
const pending2 = [];
|
|
@@ -2866,7 +2952,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2866
2952
|
}
|
|
2867
2953
|
}
|
|
2868
2954
|
if (pending2.length === 0) {
|
|
2869
|
-
|
|
2955
|
+
state3.set(codeName, next);
|
|
2870
2956
|
return;
|
|
2871
2957
|
}
|
|
2872
2958
|
let reported = 0;
|
|
@@ -2903,7 +2989,7 @@ async function maybeReportTokenUsage(args) {
|
|
|
2903
2989
|
if (reported > 0) {
|
|
2904
2990
|
log2(`[token-usage] reported ${reported} entr${reported === 1 ? "y" : "ies"} for '${codeName}'`);
|
|
2905
2991
|
}
|
|
2906
|
-
|
|
2992
|
+
state3.set(codeName, next);
|
|
2907
2993
|
}
|
|
2908
2994
|
|
|
2909
2995
|
// src/lib/workflow-run-reconciler.ts
|
|
@@ -3183,7 +3269,7 @@ function selectEvalBackend(opts) {
|
|
|
3183
3269
|
}
|
|
3184
3270
|
};
|
|
3185
3271
|
}
|
|
3186
|
-
var
|
|
3272
|
+
var state4 = /* @__PURE__ */ new Map();
|
|
3187
3273
|
function channelRefTokens(channelRef) {
|
|
3188
3274
|
return channelRef.split(":").slice(1).filter((p) => p && p !== "dm");
|
|
3189
3275
|
}
|
|
@@ -3359,11 +3445,11 @@ async function maybeEvaluateConversations(args) {
|
|
|
3359
3445
|
const { api: api2, backend, codeName, agentId, log: log2 } = args;
|
|
3360
3446
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
3361
3447
|
const nowMs = now.getTime();
|
|
3362
|
-
const existing =
|
|
3448
|
+
const existing = state4.get(codeName);
|
|
3363
3449
|
if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS4) {
|
|
3364
3450
|
return;
|
|
3365
3451
|
}
|
|
3366
|
-
|
|
3452
|
+
state4.set(codeName, { lastCheckedAt: nowMs });
|
|
3367
3453
|
let pending2;
|
|
3368
3454
|
try {
|
|
3369
3455
|
const resp = await api2.get(
|
|
@@ -3644,7 +3730,7 @@ function scrubSensitive(text) {
|
|
|
3644
3730
|
for (const re of SECRET_PATTERNS) out = out.replace(re, "[redacted]");
|
|
3645
3731
|
return out;
|
|
3646
3732
|
}
|
|
3647
|
-
var
|
|
3733
|
+
var state5 = /* @__PURE__ */ new Map();
|
|
3648
3734
|
function buildExtractionPrompt(channel, transcript) {
|
|
3649
3735
|
return `You are extracting durable, reusable memories from one completed ${channel} conversation between an AI agent and an end-user. A good memory is a stable preference, fact, correction, or recurring work context that will help the agent in FUTURE conversations \u2014 not a one-off task detail or pleasantry.
|
|
3650
3736
|
|
|
@@ -3698,11 +3784,11 @@ async function maybeExtractMemories(args) {
|
|
|
3698
3784
|
const { api: api2, backend, codeName, agentId, log: log2 } = args;
|
|
3699
3785
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
3700
3786
|
const nowMs = now.getTime();
|
|
3701
|
-
const existing =
|
|
3787
|
+
const existing = state5.get(codeName);
|
|
3702
3788
|
if (existing && nowMs - existing.lastCheckedAt < MIN_CHECK_INTERVAL_MS5) {
|
|
3703
3789
|
return;
|
|
3704
3790
|
}
|
|
3705
|
-
|
|
3791
|
+
state5.set(codeName, { lastCheckedAt: nowMs });
|
|
3706
3792
|
let pending2;
|
|
3707
3793
|
try {
|
|
3708
3794
|
const resp = await api2.get(
|
|
@@ -4699,7 +4785,7 @@ async function reportCoverage(args, cursors, touched, log2) {
|
|
|
4699
4785
|
// src/lib/tool-call-audit.ts
|
|
4700
4786
|
var MIN_CHECK_INTERVAL_MS6 = 10 * 6e4;
|
|
4701
4787
|
var ENTITLEMENT_RECHECK_MS = 30 * 6e4;
|
|
4702
|
-
var
|
|
4788
|
+
var state6 = /* @__PURE__ */ new Map();
|
|
4703
4789
|
function entitlementLatch(entry, nowMs) {
|
|
4704
4790
|
if (!entry?.notEntitledAt) return false;
|
|
4705
4791
|
return !hasElapsed(entry.notEntitledAt, nowMs, ENTITLEMENT_RECHECK_MS);
|
|
@@ -4714,13 +4800,13 @@ async function maybeScanToolCalls(args) {
|
|
|
4714
4800
|
const nowFn = args.now ?? Date.now;
|
|
4715
4801
|
const nowMs = nowFn();
|
|
4716
4802
|
try {
|
|
4717
|
-
const existing =
|
|
4803
|
+
const existing = state6.get(codeName);
|
|
4718
4804
|
if (existing && !hasElapsed(existing.lastCheckedAt, nowMs, MIN_CHECK_INTERVAL_MS6)) return;
|
|
4719
4805
|
if (entitlementLatch(existing, nowMs)) {
|
|
4720
|
-
|
|
4806
|
+
state6.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: existing?.notEntitledAt ?? null });
|
|
4721
4807
|
return;
|
|
4722
4808
|
}
|
|
4723
|
-
|
|
4809
|
+
state6.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: existing?.notEntitledAt ?? null });
|
|
4724
4810
|
const loggingMode = readAgentLoggingMode(codeName, args.homeDir);
|
|
4725
4811
|
const hashOnly = loggingModeWithholdsTargets(loggingMode);
|
|
4726
4812
|
if (loggingMode.mode === null) {
|
|
@@ -4752,9 +4838,9 @@ async function maybeScanToolCalls(args) {
|
|
|
4752
4838
|
...args.cursorPath === void 0 ? {} : { cursorPath: args.cursorPath }
|
|
4753
4839
|
});
|
|
4754
4840
|
if (summary.notEntitled) {
|
|
4755
|
-
|
|
4841
|
+
state6.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: nowMs });
|
|
4756
4842
|
} else if (summary.callsIngested > 0) {
|
|
4757
|
-
|
|
4843
|
+
state6.set(codeName, { lastCheckedAt: nowMs, notEntitledAt: null });
|
|
4758
4844
|
}
|
|
4759
4845
|
} catch (err) {
|
|
4760
4846
|
log2(`[tool-call-audit] ${codeName}: scan failed: ${err.message}`);
|
|
@@ -4768,7 +4854,7 @@ import { join as join21 } from "path";
|
|
|
4768
4854
|
var MIN_CHECK_INTERVAL_MS7 = 6e4;
|
|
4769
4855
|
var STATS_CACHE_PATH = join21(homedir12(), ".claude", "stats-cache.json");
|
|
4770
4856
|
var ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4771
|
-
var
|
|
4857
|
+
var state7 = { lastObservedDate: null, lastCheckedAt: 0 };
|
|
4772
4858
|
function selectNewDailyRows(raw, lastObservedDate) {
|
|
4773
4859
|
let parsed;
|
|
4774
4860
|
try {
|
|
@@ -4807,8 +4893,8 @@ async function maybeReportActivityCache(args) {
|
|
|
4807
4893
|
const { api: api2, log: log2 } = args;
|
|
4808
4894
|
const now = args.now ?? /* @__PURE__ */ new Date();
|
|
4809
4895
|
const nowMs = now.getTime();
|
|
4810
|
-
if (nowMs -
|
|
4811
|
-
|
|
4896
|
+
if (nowMs - state7.lastCheckedAt < MIN_CHECK_INTERVAL_MS7) return;
|
|
4897
|
+
state7.lastCheckedAt = nowMs;
|
|
4812
4898
|
if (!existsSync5(STATS_CACHE_PATH)) {
|
|
4813
4899
|
return;
|
|
4814
4900
|
}
|
|
@@ -4819,12 +4905,12 @@ async function maybeReportActivityCache(args) {
|
|
|
4819
4905
|
log2(`[activity-cache] readFileSync failed: ${err.message}`);
|
|
4820
4906
|
return;
|
|
4821
4907
|
}
|
|
4822
|
-
const rows = selectNewDailyRows(raw,
|
|
4908
|
+
const rows = selectNewDailyRows(raw, state7.lastObservedDate);
|
|
4823
4909
|
if (rows.length === 0) return;
|
|
4824
4910
|
for (const row of rows) {
|
|
4825
4911
|
try {
|
|
4826
4912
|
await api2.post("/host/activity-observations", row);
|
|
4827
|
-
|
|
4913
|
+
state7.lastObservedDate = row.date;
|
|
4828
4914
|
} catch (err) {
|
|
4829
4915
|
log2(
|
|
4830
4916
|
`[activity-cache] POST /host/activity-observations failed for date=${row.date}: ${err.message}`
|
|
@@ -6010,21 +6096,21 @@ function nudgeIntervalForCount(nudgeCount, fullCadenceMs, maxCadenceMs) {
|
|
|
6010
6096
|
const exponent = Math.max(0, Math.min(nudgeCount - 1, 8));
|
|
6011
6097
|
return Math.min(fullCadenceMs * 3 ** exponent, Math.max(maxCadenceMs, fullCadenceMs));
|
|
6012
6098
|
}
|
|
6013
|
-
function shouldNudgeUnchangedBoard(signature,
|
|
6014
|
-
if (!
|
|
6015
|
-
if (
|
|
6016
|
-
return now -
|
|
6099
|
+
function shouldNudgeUnchangedBoard(signature, state9, now, fullCadenceMs, maxCadenceMs = fullCadenceMs) {
|
|
6100
|
+
if (!state9) return true;
|
|
6101
|
+
if (state9.signature !== signature) return true;
|
|
6102
|
+
return now - state9.nudgedAt >= nudgeIntervalForCount(state9.nudgeCount ?? 1, fullCadenceMs, maxCadenceMs);
|
|
6017
6103
|
}
|
|
6018
6104
|
function failureRetryIntervalForCount(failureCount, baseMs, maxMs) {
|
|
6019
6105
|
const exponent = Math.max(0, Math.min(failureCount - 1, 8));
|
|
6020
6106
|
return Math.min(baseMs * 3 ** exponent, Math.max(maxMs, baseMs));
|
|
6021
6107
|
}
|
|
6022
6108
|
var KANBAN_NOTICE_BREAKER_THRESHOLD = 5;
|
|
6023
|
-
function shouldAttemptNoticeEnqueue(
|
|
6024
|
-
const failures =
|
|
6109
|
+
function shouldAttemptNoticeEnqueue(state9, now, baseMs, maxMs, breakerThreshold = KANBAN_NOTICE_BREAKER_THRESHOLD) {
|
|
6110
|
+
const failures = state9?.failureCount ?? 0;
|
|
6025
6111
|
if (failures <= 0) return { attempt: true, breakerOpen: false };
|
|
6026
6112
|
const breakerOpen = failures >= breakerThreshold;
|
|
6027
|
-
const failedAt =
|
|
6113
|
+
const failedAt = state9?.failedAt;
|
|
6028
6114
|
const due = failedAt === void 0 || failedAt > now || now - failedAt >= failureRetryIntervalForCount(failures, baseMs, maxMs);
|
|
6029
6115
|
return { attempt: due, breakerOpen };
|
|
6030
6116
|
}
|
|
@@ -6314,7 +6400,7 @@ function loadKanbanNudgeState(target, configDir) {
|
|
|
6314
6400
|
function saveKanbanNudgeState(source, configDir) {
|
|
6315
6401
|
const path = getKanbanNudgeStateFile(configDir);
|
|
6316
6402
|
const agents = {};
|
|
6317
|
-
for (const [codeName,
|
|
6403
|
+
for (const [codeName, state9] of source) agents[codeName] = state9;
|
|
6318
6404
|
try {
|
|
6319
6405
|
writeFileSync9(path, JSON.stringify({ version: KANBAN_NUDGE_STATE_VERSION, agents }, null, 2));
|
|
6320
6406
|
} catch {
|
|
@@ -7154,8 +7240,8 @@ async function runScheduledCardDelivery(codeName, agentId, cardId, completedBy,
|
|
|
7154
7240
|
markScheduledCardDeliveryComplete(cardId);
|
|
7155
7241
|
return "terminal";
|
|
7156
7242
|
}
|
|
7157
|
-
const
|
|
7158
|
-
const task =
|
|
7243
|
+
const state9 = claudeSchedulerStates.get(codeName) ?? loadSchedulerState(codeName);
|
|
7244
|
+
const task = state9.tasks[card.source_ref];
|
|
7159
7245
|
if (!task) {
|
|
7160
7246
|
log(`[scheduled-kanban] delivery: no scheduler task for source_ref=${card.source_ref} on '${codeName}' \u2014 skipping`);
|
|
7161
7247
|
markScheduledCardDeliveryComplete(cardId);
|
|
@@ -7607,16 +7693,16 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
|
|
|
7607
7693
|
const prevHash = agentState.knownTasksHashes.get(agent.agent_id);
|
|
7608
7694
|
if (combinedHash !== prevHash) {
|
|
7609
7695
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
7610
|
-
const
|
|
7611
|
-
claudeSchedulerStates.set(codeName,
|
|
7696
|
+
const state10 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
7697
|
+
claudeSchedulerStates.set(codeName, state10);
|
|
7612
7698
|
agentState.knownTasksHashes.set(agent.agent_id, combinedHash);
|
|
7613
7699
|
log(`[claude-scheduler] Tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
|
|
7614
7700
|
}
|
|
7615
7701
|
if (!claudeSchedulerStates.has(codeName)) {
|
|
7616
7702
|
claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
|
|
7617
7703
|
}
|
|
7618
|
-
const
|
|
7619
|
-
const ready = getReadyTasks(
|
|
7704
|
+
const state9 = claudeSchedulerStates.get(codeName);
|
|
7705
|
+
const ready = getReadyTasks(state9, inFlightClaudeTasks);
|
|
7620
7706
|
if (ready.length === 0) return;
|
|
7621
7707
|
const limitedUntil = readUsageCapUntil({ codeName, projectDir: getProjectDir(codeName) });
|
|
7622
7708
|
if (limitedUntil) {
|
|
@@ -7759,17 +7845,17 @@ function candidateTranscriptPaths(dir) {
|
|
|
7759
7845
|
return { paths, complete };
|
|
7760
7846
|
}
|
|
7761
7847
|
function foldToolCallBrackets(codeName, eventsByPath, nowMs) {
|
|
7762
|
-
const
|
|
7848
|
+
const state9 = brackets.get(codeName) ?? {
|
|
7763
7849
|
open: /* @__PURE__ */ new Map(),
|
|
7764
7850
|
closed: []
|
|
7765
7851
|
};
|
|
7766
7852
|
const nextOpen = /* @__PURE__ */ new Map();
|
|
7767
7853
|
const openOut = [];
|
|
7768
|
-
const paths = /* @__PURE__ */ new Set([...
|
|
7854
|
+
const paths = /* @__PURE__ */ new Set([...state9.open.keys(), ...eventsByPath.keys()]);
|
|
7769
7855
|
for (const path of paths) {
|
|
7770
|
-
const carried =
|
|
7856
|
+
const carried = state9.open.get(path) ?? [];
|
|
7771
7857
|
const paired = pairToolCallBrackets(eventsByPath.get(path) ?? [], carried);
|
|
7772
|
-
|
|
7858
|
+
state9.closed.push(...paired.brackets);
|
|
7773
7859
|
const live = paired.open.filter((c) => nowMs - c.startMs <= MAX_BRACKET_DEFERRAL_MS);
|
|
7774
7860
|
if (live.length > 0) {
|
|
7775
7861
|
nextOpen.set(path, live);
|
|
@@ -7779,7 +7865,7 @@ function foldToolCallBrackets(codeName, eventsByPath, nowMs) {
|
|
|
7779
7865
|
const keepFrom = nowMs - GATE_MAX_BUCKET_AGE_MS;
|
|
7780
7866
|
const seen = /* @__PURE__ */ new Set();
|
|
7781
7867
|
const closed = [];
|
|
7782
|
-
for (const b of
|
|
7868
|
+
for (const b of state9.closed) {
|
|
7783
7869
|
if (b.endMs < keepFrom) continue;
|
|
7784
7870
|
const key = `${b.id}\0${b.startMs}\0${b.endMs}`;
|
|
7785
7871
|
if (seen.has(key)) continue;
|
|
@@ -8053,8 +8139,8 @@ function countDefunct(cgroupDir, readText) {
|
|
|
8053
8139
|
if (stat2 == null) continue;
|
|
8054
8140
|
const close = stat2.lastIndexOf(")");
|
|
8055
8141
|
if (close < 0) continue;
|
|
8056
|
-
const
|
|
8057
|
-
if (
|
|
8142
|
+
const state9 = stat2.slice(close + 1).trim().charAt(0);
|
|
8143
|
+
if (state9 === "Z") defunct += 1;
|
|
8058
8144
|
}
|
|
8059
8145
|
return defunct;
|
|
8060
8146
|
}
|
|
@@ -9225,16 +9311,16 @@ async function syncAndCheckOpencodeScheduler(agent, tasks, refreshData) {
|
|
|
9225
9311
|
const tasksHash = createHash15("sha256").update(JSON.stringify(tasks)).digest("hex").slice(0, 16);
|
|
9226
9312
|
if (knownOpencodeTaskHashes.get(agent.agent_id) !== tasksHash) {
|
|
9227
9313
|
const taskInputs = tasks.map((t) => buildSchedulerTaskInput(t));
|
|
9228
|
-
const
|
|
9229
|
-
opencodeSchedulerStates.set(codeName,
|
|
9314
|
+
const state10 = syncTasksToScheduler(codeName, agent.agent_id, taskInputs);
|
|
9315
|
+
opencodeSchedulerStates.set(codeName, state10);
|
|
9230
9316
|
knownOpencodeTaskHashes.set(agent.agent_id, tasksHash);
|
|
9231
9317
|
log(`[opencode-scheduler] tasks synced for '${codeName}' (${taskInputs.length} task(s))`);
|
|
9232
9318
|
}
|
|
9233
9319
|
if (!opencodeSchedulerStates.has(codeName)) {
|
|
9234
9320
|
opencodeSchedulerStates.set(codeName, loadSchedulerState(codeName));
|
|
9235
9321
|
}
|
|
9236
|
-
const
|
|
9237
|
-
const ready = getReadyTasks(
|
|
9322
|
+
const state9 = opencodeSchedulerStates.get(codeName);
|
|
9323
|
+
const ready = getReadyTasks(state9, inFlightOpencodeTasks);
|
|
9238
9324
|
if (ready.length === 0) return;
|
|
9239
9325
|
if (!isOpencodeSessionHealthy(codeName)) {
|
|
9240
9326
|
log(`[opencode-scheduler] '${codeName}' has ${ready.length} due task(s) but no healthy serve yet - deferring`);
|
|
@@ -10109,10 +10195,10 @@ function recordWedgeForCards(states, inProgressCardIds, nowMs, config2) {
|
|
|
10109
10195
|
function pruneCardStates(states, liveInProgressCardIds, nowMs, config2) {
|
|
10110
10196
|
const live = liveInProgressCardIds instanceof Set ? liveInProgressCardIds : new Set(liveInProgressCardIds);
|
|
10111
10197
|
const next = /* @__PURE__ */ new Map();
|
|
10112
|
-
for (const [id,
|
|
10198
|
+
for (const [id, state9] of states) {
|
|
10113
10199
|
if (!live.has(id)) continue;
|
|
10114
|
-
if (nowMs -
|
|
10115
|
-
next.set(id,
|
|
10200
|
+
if (nowMs - state9.lastWedgeAtMs > config2.cooldownMs) continue;
|
|
10201
|
+
next.set(id, state9);
|
|
10116
10202
|
}
|
|
10117
10203
|
return next;
|
|
10118
10204
|
}
|
|
@@ -11053,8 +11139,8 @@ var KNOWN_SAFE_TAIL_SIGNATURES = /* @__PURE__ */ new Set(["session_id_in_use"]);
|
|
|
11053
11139
|
function shouldSkipRevokedCleanup(previousKnownStatus) {
|
|
11054
11140
|
return previousKnownStatus === "revoked";
|
|
11055
11141
|
}
|
|
11056
|
-
function hasRevokedResiduals(
|
|
11057
|
-
return
|
|
11142
|
+
function hasRevokedResiduals(state9) {
|
|
11143
|
+
return state9.gatewayRunning || state9.portAllocated || state9.provisionDirExists;
|
|
11058
11144
|
}
|
|
11059
11145
|
var pendingSessionRestarts = /* @__PURE__ */ new Map();
|
|
11060
11146
|
var lastRestartWasExternal = /* @__PURE__ */ new Map();
|
|
@@ -11256,12 +11342,12 @@ function maybeClearStaleTrip(agent) {
|
|
|
11256
11342
|
const marker = getAutoResumeMarker(codeName);
|
|
11257
11343
|
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
11258
11344
|
if (!isSelfResume) deleteAutoResumeMarker(codeName);
|
|
11259
|
-
|
|
11260
|
-
...
|
|
11345
|
+
state8 = {
|
|
11346
|
+
...state8,
|
|
11261
11347
|
circuitBreakerTrips: restartBreaker.serialize(),
|
|
11262
11348
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
11263
11349
|
};
|
|
11264
|
-
send({ type: "state-update", state:
|
|
11350
|
+
send({ type: "state-update", state: state8 });
|
|
11265
11351
|
}
|
|
11266
11352
|
var autoResumeMarkers = /* @__PURE__ */ new Map();
|
|
11267
11353
|
function autoResumeMarkerKey(codeName) {
|
|
@@ -11354,12 +11440,12 @@ function maybeAutoResume(agent) {
|
|
|
11354
11440
|
restartBreaker.clear(codeName);
|
|
11355
11441
|
reportedTrips.delete(codeName);
|
|
11356
11442
|
dependencyRecoveryLedger.clear(codeName);
|
|
11357
|
-
|
|
11358
|
-
...
|
|
11443
|
+
state8 = {
|
|
11444
|
+
...state8,
|
|
11359
11445
|
circuitBreakerTrips: restartBreaker.serialize(),
|
|
11360
11446
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
11361
11447
|
};
|
|
11362
|
-
send({ type: "state-update", state:
|
|
11448
|
+
send({ type: "state-update", state: state8 });
|
|
11363
11449
|
log(`[auto-resume] agent=${codeName} resumed \u2014 re-trip within backoff window will stay paused (ENG-6088)`);
|
|
11364
11450
|
} else {
|
|
11365
11451
|
autoResumeStandDowns.add(`${codeName}:${trippedAt}`);
|
|
@@ -11468,12 +11554,12 @@ async function maybeResumeReconcile(agent) {
|
|
|
11468
11554
|
restartBreaker.clear(codeName);
|
|
11469
11555
|
reportedTrips.delete(codeName);
|
|
11470
11556
|
dependencyRecoveryLedger.clear(codeName);
|
|
11471
|
-
|
|
11472
|
-
...
|
|
11557
|
+
state8 = {
|
|
11558
|
+
...state8,
|
|
11473
11559
|
circuitBreakerTrips: restartBreaker.serialize(),
|
|
11474
11560
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
11475
11561
|
};
|
|
11476
|
-
send({ type: "state-update", state:
|
|
11562
|
+
send({ type: "state-update", state: state8 });
|
|
11477
11563
|
log(`[resume-reconciler] agent=${codeName} resumed \u2014 a re-trip within the backoff window will latch unstable (ENG-6383)`);
|
|
11478
11564
|
} else {
|
|
11479
11565
|
autoResumeStandDowns.add(standDownKey);
|
|
@@ -11754,7 +11840,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
|
|
|
11754
11840
|
var dayRolloverInboundHold = /* @__PURE__ */ new Map();
|
|
11755
11841
|
var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
|
|
11756
11842
|
async function channelInboundActivityAgeSecondsFor(codeName) {
|
|
11757
|
-
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-
|
|
11843
|
+
const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-KDQFIROB.js");
|
|
11758
11844
|
const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
|
|
11759
11845
|
if (newest === null) return null;
|
|
11760
11846
|
return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
|
|
@@ -11903,7 +11989,7 @@ function restartGateFor(codeName, reason) {
|
|
|
11903
11989
|
}
|
|
11904
11990
|
function isHostBusyForForcedUpdate(opts) {
|
|
11905
11991
|
const now = /* @__PURE__ */ new Date();
|
|
11906
|
-
for (const agent of
|
|
11992
|
+
for (const agent of state8.agents) {
|
|
11907
11993
|
const decision = decideRestartGate({
|
|
11908
11994
|
window: null,
|
|
11909
11995
|
paneLogAgeSeconds: paneLogAgeSecondsFor(agent.codeName),
|
|
@@ -11936,7 +12022,7 @@ function runPendingForcedUpdate() {
|
|
|
11936
12022
|
relaxed
|
|
11937
12023
|
} = decidePendingForcedUpdate({
|
|
11938
12024
|
requestedAt: requestedUpdateAt,
|
|
11939
|
-
lastProcessedAt:
|
|
12025
|
+
lastProcessedAt: state8.lastUpdateRequestProcessedAt ?? null,
|
|
11940
12026
|
deferStreak: forcedUpdateDeferStreak,
|
|
11941
12027
|
nowMs: Date.now(),
|
|
11942
12028
|
isHostBusy: (isRelaxed) => isHostBusyForForcedUpdate({ relaxed: isRelaxed })
|
|
@@ -11970,7 +12056,7 @@ function runPendingForcedUpdate() {
|
|
|
11970
12056
|
log(
|
|
11971
12057
|
forcedUpdate === "consume-deadline" ? `[self-update] WARN "Update CLI now" requested at ${requestedUpdateAt} has been pending ${describePendingFor(pendingForMs)} and the host still reads busy \u2014 running the window-bypassing self-update anyway (ENG-8449 hard deadline). A live turn may be interrupted; the operator asked for this update explicitly.` : `[self-update] "Update CLI now" requested at ${requestedUpdateAt} \u2014 running window-bypassing self-update now (host idle${relaxed ? ", relaxed gate" : ""}).`
|
|
11972
12058
|
);
|
|
11973
|
-
const prevProcessedAt =
|
|
12059
|
+
const prevProcessedAt = state8.lastUpdateRequestProcessedAt ?? null;
|
|
11974
12060
|
void checkAndUpdateCli({ force: true }).then((outcome) => {
|
|
11975
12061
|
if (!shouldConsumeForcedUpdate(outcome)) {
|
|
11976
12062
|
log(
|
|
@@ -11981,11 +12067,11 @@ function runPendingForcedUpdate() {
|
|
|
11981
12067
|
log(
|
|
11982
12068
|
outcome === "updated" ? `[self-update] "Update CLI now" completed \u2014 upgrade installed; manager restart scheduled.` : `[self-update] "Update CLI now" completed \u2014 host was already on the latest in-channel build; nothing to install.`
|
|
11983
12069
|
);
|
|
11984
|
-
|
|
12070
|
+
state8.lastUpdateRequestProcessedAt = requestedUpdateAt;
|
|
11985
12071
|
try {
|
|
11986
|
-
atomicWriteFileSync(getStateFile(), JSON.stringify(
|
|
12072
|
+
atomicWriteFileSync(getStateFile(), JSON.stringify(state8, null, 2));
|
|
11987
12073
|
} catch (err) {
|
|
11988
|
-
|
|
12074
|
+
state8.lastUpdateRequestProcessedAt = prevProcessedAt;
|
|
11989
12075
|
log(
|
|
11990
12076
|
`[self-update] failed to persist update-request ack; retrying next poll: ${err.message}`
|
|
11991
12077
|
);
|
|
@@ -12345,7 +12431,7 @@ var STALE_TASK_THRESHOLD_MS = (() => {
|
|
|
12345
12431
|
})();
|
|
12346
12432
|
var taskDisplayInfo = /* @__PURE__ */ new Map();
|
|
12347
12433
|
var activeChannels = /* @__PURE__ */ new Map();
|
|
12348
|
-
var
|
|
12434
|
+
var state8 = {
|
|
12349
12435
|
pid: process.pid,
|
|
12350
12436
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
12351
12437
|
lastPollAt: null,
|
|
@@ -12402,7 +12488,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
12402
12488
|
var lastVersionCheckAt = 0;
|
|
12403
12489
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
12404
12490
|
var lastResponsivenessProbeAt = 0;
|
|
12405
|
-
var agtCliVersion = true ? "0.28.
|
|
12491
|
+
var agtCliVersion = true ? "0.28.696" : "dev";
|
|
12406
12492
|
function resolveBrewPath(execFileSync3) {
|
|
12407
12493
|
try {
|
|
12408
12494
|
const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -13391,6 +13477,46 @@ async function runClaudeRuntimeAuthProbe() {
|
|
|
13391
13477
|
});
|
|
13392
13478
|
}
|
|
13393
13479
|
}
|
|
13480
|
+
async function runHostUsageCommand() {
|
|
13481
|
+
try {
|
|
13482
|
+
const childEnv = { ...process.env };
|
|
13483
|
+
await applyClaudeAuthToEnv(childEnv, "host-usage-poll");
|
|
13484
|
+
const emptyMcp = ensureEvalEmptyMcpConfig();
|
|
13485
|
+
const args = [
|
|
13486
|
+
...USAGE_COMMAND_ARGS,
|
|
13487
|
+
"--mcp-config",
|
|
13488
|
+
emptyMcp,
|
|
13489
|
+
"--strict-mcp-config",
|
|
13490
|
+
"--permission-mode",
|
|
13491
|
+
"auto",
|
|
13492
|
+
"--allowedTools",
|
|
13493
|
+
""
|
|
13494
|
+
];
|
|
13495
|
+
const { stdout } = await execFilePromiseLong(resolveClaudeBinary(), args, {
|
|
13496
|
+
cwd: homedir17(),
|
|
13497
|
+
timeout: HOST_USAGE_POLL_TIMEOUT_MS,
|
|
13498
|
+
stdin: "ignore",
|
|
13499
|
+
env: childEnv,
|
|
13500
|
+
onSpawn: (pid) => registerClaudeSpawn({ pid, started_at: Date.now(), kind: "conv-eval" }),
|
|
13501
|
+
onExit: (pid) => unregisterClaudeSpawn(pid)
|
|
13502
|
+
});
|
|
13503
|
+
return { stdout, failed: false };
|
|
13504
|
+
} catch (err) {
|
|
13505
|
+
if (err instanceof ChildProcessError) return { stdout: err.stdout ?? "", failed: true };
|
|
13506
|
+
return { stdout: "", failed: true };
|
|
13507
|
+
}
|
|
13508
|
+
}
|
|
13509
|
+
async function maybePollHostUsageFromCycle() {
|
|
13510
|
+
const { execFileSync: execFileSync3 } = await import("child_process");
|
|
13511
|
+
if (!claudeBinaryInstalled(execFileSync3)) return;
|
|
13512
|
+
await maybePollHostUsage({
|
|
13513
|
+
api,
|
|
13514
|
+
runUsageCommand: runHostUsageCommand,
|
|
13515
|
+
authMode: getCachedClaudeAuthMode(),
|
|
13516
|
+
cliVersion: cachedFrameworkVersion,
|
|
13517
|
+
log
|
|
13518
|
+
});
|
|
13519
|
+
}
|
|
13394
13520
|
async function checkClaudeAuth() {
|
|
13395
13521
|
try {
|
|
13396
13522
|
const report = await detectClaudeAuth();
|
|
@@ -13561,21 +13687,21 @@ function recordChannelSyncFailure(failures, agentId, reason, now) {
|
|
|
13561
13687
|
failures.set(agentId, next);
|
|
13562
13688
|
return next;
|
|
13563
13689
|
}
|
|
13564
|
-
function shouldLogChannelSyncFailure(
|
|
13565
|
-
if (
|
|
13566
|
-
if (
|
|
13567
|
-
return
|
|
13690
|
+
function shouldLogChannelSyncFailure(state9) {
|
|
13691
|
+
if (state9.attempts === 1) return true;
|
|
13692
|
+
if (state9.attempts <= CHANNEL_SYNC_FREE_ATTEMPTS) return false;
|
|
13693
|
+
return state9.attempts > state9.loggedAtAttempt;
|
|
13568
13694
|
}
|
|
13569
13695
|
function stuckChannelSyncs(failures, now, thresholdMs = CHANNEL_SYNC_STUCK_AFTER_MS) {
|
|
13570
13696
|
const out = [];
|
|
13571
|
-
for (const [agentId,
|
|
13572
|
-
const stuckForMs = now -
|
|
13697
|
+
for (const [agentId, state9] of failures) {
|
|
13698
|
+
const stuckForMs = now - state9.since;
|
|
13573
13699
|
if (stuckForMs < thresholdMs) continue;
|
|
13574
13700
|
out.push({
|
|
13575
13701
|
agent_id: agentId,
|
|
13576
|
-
attempts:
|
|
13702
|
+
attempts: state9.attempts,
|
|
13577
13703
|
stuck_for_seconds: Math.floor(stuckForMs / 1e3),
|
|
13578
|
-
reason:
|
|
13704
|
+
reason: state9.lastReason
|
|
13579
13705
|
});
|
|
13580
13706
|
}
|
|
13581
13707
|
out.sort((a, b) => b.stuck_for_seconds - a.stuck_for_seconds);
|
|
@@ -13863,7 +13989,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
13863
13989
|
if (codeNames.length === 0) return;
|
|
13864
13990
|
void (async () => {
|
|
13865
13991
|
try {
|
|
13866
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
13992
|
+
const { collectDiagnostics } = await import("../persistent-session-5ZWDVVIH.js");
|
|
13867
13993
|
await api.post("/host/heartbeat", {
|
|
13868
13994
|
host_id: hostId,
|
|
13869
13995
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor)
|
|
@@ -13959,6 +14085,7 @@ async function pollCycleInner() {
|
|
|
13959
14085
|
}
|
|
13960
14086
|
maybeUpgradeClaudeCode().catch((err) => log(`[claude-code-upgrade] Check failed: ${err.message}`));
|
|
13961
14087
|
maybeProbeClaudeRuntimeAuth().catch((err) => log(`[runtime-auth-probe] Check failed: ${err.message}`));
|
|
14088
|
+
maybePollHostUsageFromCycle().catch((err) => log(`[host-usage] Check failed: ${err.message}`));
|
|
13962
14089
|
try {
|
|
13963
14090
|
registeredAgentsCache.clear();
|
|
13964
14091
|
const hostId = await getHostId();
|
|
@@ -13969,7 +14096,7 @@ async function pollCycleInner() {
|
|
|
13969
14096
|
const now = Date.now();
|
|
13970
14097
|
if (now - lastVersionCheckAt > VERSION_CHECK_INTERVAL_MS) {
|
|
13971
14098
|
try {
|
|
13972
|
-
const firstAgent =
|
|
14099
|
+
const firstAgent = state8.agents[0];
|
|
13973
14100
|
const versionAdapter = firstAgent ? resolveAgentFramework(firstAgent.codeName) : getFramework(DEFAULT_FRAMEWORK);
|
|
13974
14101
|
if (versionAdapter.getVersion) {
|
|
13975
14102
|
cachedFrameworkVersion = await versionAdapter.getVersion();
|
|
@@ -13980,7 +14107,7 @@ async function pollCycleInner() {
|
|
|
13980
14107
|
}
|
|
13981
14108
|
try {
|
|
13982
14109
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
13983
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14110
|
+
const { collectDiagnostics } = await import("../persistent-session-5ZWDVVIH.js");
|
|
13984
14111
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
13985
14112
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor) : void 0;
|
|
13986
14113
|
let tailscaleHostname;
|
|
@@ -14013,7 +14140,7 @@ async function pollCycleInner() {
|
|
|
14013
14140
|
const errId = createHash17("sha256").update(errText).digest("hex").slice(0, 12);
|
|
14014
14141
|
log(`Claude auth detection failed (error_id=${errId})`);
|
|
14015
14142
|
}
|
|
14016
|
-
const hostHasClaudeCode =
|
|
14143
|
+
const hostHasClaudeCode = state8.agents.some(
|
|
14017
14144
|
(a) => agentFrameworkCache.get(a.codeName) === "claude-code"
|
|
14018
14145
|
);
|
|
14019
14146
|
if (hostHasClaudeCode) {
|
|
@@ -14092,7 +14219,7 @@ async function pollCycleInner() {
|
|
|
14092
14219
|
// ENG-6692: ack the last consumed "Update CLI now" timestamp so the API
|
|
14093
14220
|
// clears hosts.update_requested_at. Echoes our persisted dedup marker;
|
|
14094
14221
|
// null until we've ever consumed one.
|
|
14095
|
-
update_request_processed_at:
|
|
14222
|
+
update_request_processed_at: state8.lastUpdateRequestProcessedAt ?? null
|
|
14096
14223
|
});
|
|
14097
14224
|
if (hbResp?.maintenance_window) {
|
|
14098
14225
|
cachedMaintenanceWindow = hbResp.maintenance_window;
|
|
@@ -14132,7 +14259,7 @@ async function pollCycleInner() {
|
|
|
14132
14259
|
collectPanelessActivityProbes,
|
|
14133
14260
|
getResponsivenessIntervalMs,
|
|
14134
14261
|
occupancyQualificationClassifications
|
|
14135
|
-
} = await import("../responsiveness-probe-
|
|
14262
|
+
} = await import("../responsiveness-probe-KDQFIROB.js");
|
|
14136
14263
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
14137
14264
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
14138
14265
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -14242,7 +14369,7 @@ async function pollCycleInner() {
|
|
|
14242
14369
|
collectResponsivenessProbes,
|
|
14243
14370
|
livePendingInboundOldestAgeSeconds,
|
|
14244
14371
|
parkPendingInbound
|
|
14245
|
-
} = await import("../responsiveness-probe-
|
|
14372
|
+
} = await import("../responsiveness-probe-KDQFIROB.js");
|
|
14246
14373
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
14247
14374
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
14248
14375
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -14398,7 +14525,7 @@ async function pollCycleInner() {
|
|
|
14398
14525
|
}
|
|
14399
14526
|
try {
|
|
14400
14527
|
const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
|
|
14401
|
-
const { probeSessionAuth } = await import("../session-auth-dead-
|
|
14528
|
+
const { probeSessionAuth } = await import("../session-auth-dead-7S7IQGNX.js");
|
|
14402
14529
|
const observations = [];
|
|
14403
14530
|
const pendingCacheCommits = [];
|
|
14404
14531
|
const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
|
|
@@ -14479,7 +14606,7 @@ async function pollCycleInner() {
|
|
|
14479
14606
|
const requested = agent.restart_requested_at ?? null;
|
|
14480
14607
|
if (!requested) continue;
|
|
14481
14608
|
if (restartInFlight.has(agent.agent_id)) continue;
|
|
14482
|
-
const prev =
|
|
14609
|
+
const prev = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
14483
14610
|
const lastProcessed = prev?.lastRestartProcessedAt ?? null;
|
|
14484
14611
|
const alreadyServiced = lastProcessed != null && Date.parse(lastProcessed) >= Date.parse(requested);
|
|
14485
14612
|
if (!alreadyServiced) {
|
|
@@ -14560,7 +14687,7 @@ async function pollCycleInner() {
|
|
|
14560
14687
|
managedPruneLedger = createManagedPruneLedger();
|
|
14561
14688
|
for (const agent of processOrder) {
|
|
14562
14689
|
if (restartInFlight.has(agent.agent_id)) {
|
|
14563
|
-
const existing =
|
|
14690
|
+
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
14564
14691
|
if (existing) {
|
|
14565
14692
|
agentStates.push(existing);
|
|
14566
14693
|
continue;
|
|
@@ -14570,7 +14697,7 @@ async function pollCycleInner() {
|
|
|
14570
14697
|
await processAgent(agent, agentStates, managedToolkits);
|
|
14571
14698
|
} catch (err) {
|
|
14572
14699
|
log(`Error processing agent '${agent.code_name}': ${err.message}`);
|
|
14573
|
-
const existing =
|
|
14700
|
+
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
14574
14701
|
if (existing) {
|
|
14575
14702
|
agentStates.push(existing);
|
|
14576
14703
|
} else {
|
|
@@ -14601,12 +14728,12 @@ async function pollCycleInner() {
|
|
|
14601
14728
|
if (crossAgentPrune) log(crossAgentPrune);
|
|
14602
14729
|
const restartAckStateChanged = applyRestartAcks({
|
|
14603
14730
|
agentStates,
|
|
14604
|
-
priorAgents:
|
|
14731
|
+
priorAgents: state8.agents,
|
|
14605
14732
|
restartAcks
|
|
14606
14733
|
});
|
|
14607
14734
|
if (restartAckStateChanged) {
|
|
14608
14735
|
try {
|
|
14609
|
-
const ackedState = { ...
|
|
14736
|
+
const ackedState = { ...state8, agents: agentStates };
|
|
14610
14737
|
atomicWriteFileSync(getStateFile(), JSON.stringify(ackedState, null, 2));
|
|
14611
14738
|
} catch (err) {
|
|
14612
14739
|
log(`[restart] failed to persist ack immediately: ${err.message}`);
|
|
@@ -14628,7 +14755,7 @@ async function pollCycleInner() {
|
|
|
14628
14755
|
} catch {
|
|
14629
14756
|
}
|
|
14630
14757
|
const currentIds = new Set(agents.map((a) => a.agent_id));
|
|
14631
|
-
for (const prev of
|
|
14758
|
+
for (const prev of state8.agents) {
|
|
14632
14759
|
if (!currentIds.has(prev.agentId)) {
|
|
14633
14760
|
log(`Agent '${prev.codeName}' removed from host (deleted or unassigned)`);
|
|
14634
14761
|
const adapter = resolveAgentFramework(prev.codeName);
|
|
@@ -14790,10 +14917,10 @@ async function pollCycleInner() {
|
|
|
14790
14917
|
}
|
|
14791
14918
|
} catch {
|
|
14792
14919
|
}
|
|
14793
|
-
|
|
14794
|
-
...
|
|
14920
|
+
state8 = {
|
|
14921
|
+
...state8,
|
|
14795
14922
|
lastPollAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
14796
|
-
pollCount:
|
|
14923
|
+
pollCount: state8.pollCount + 1,
|
|
14797
14924
|
agents: agentStates,
|
|
14798
14925
|
// ENG-5441: serialise trip state on every poll so manager restarts
|
|
14799
14926
|
// never silently clear a tripped breaker. Cheap — only tripped
|
|
@@ -14807,9 +14934,9 @@ async function pollCycleInner() {
|
|
|
14807
14934
|
consecutivePollFailures = 0;
|
|
14808
14935
|
}
|
|
14809
14936
|
verifyPendingRestarts(Date.now());
|
|
14810
|
-
send({ type: "state-update", state:
|
|
14937
|
+
send({ type: "state-update", state: state8 });
|
|
14811
14938
|
} catch (err) {
|
|
14812
|
-
|
|
14939
|
+
state8.errorCount++;
|
|
14813
14940
|
const message = err.message;
|
|
14814
14941
|
log(`Poll error: ${message}`);
|
|
14815
14942
|
send({ type: "error", message });
|
|
@@ -15105,11 +15232,11 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15105
15232
|
const marker = getAutoResumeMarker(agent.code_name);
|
|
15106
15233
|
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
15107
15234
|
if (!isSelfResume && deleteAutoResumeMarker(agent.code_name)) {
|
|
15108
|
-
|
|
15109
|
-
...
|
|
15235
|
+
state8 = {
|
|
15236
|
+
...state8,
|
|
15110
15237
|
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
15111
15238
|
};
|
|
15112
|
-
send({ type: "state-update", state:
|
|
15239
|
+
send({ type: "state-update", state: state8 });
|
|
15113
15240
|
log(`[auto-resume] Cleared auto-resume marker for '${agent.code_name}' on operator resume \u2014 credit re-armed (ENG-6088)`);
|
|
15114
15241
|
}
|
|
15115
15242
|
}
|
|
@@ -15140,7 +15267,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15140
15267
|
});
|
|
15141
15268
|
} catch (err) {
|
|
15142
15269
|
log(`Refresh failed for '${agent.code_name}': ${err.message}`);
|
|
15143
|
-
const existing =
|
|
15270
|
+
const existing = state8.agents.find((a) => a.agentId === agent.agent_id);
|
|
15144
15271
|
agentStates.push(existing ?? {
|
|
15145
15272
|
agentId: agent.agent_id,
|
|
15146
15273
|
codeName: agent.code_name,
|
|
@@ -15204,7 +15331,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15204
15331
|
const charterVersion = refreshData.charter.version;
|
|
15205
15332
|
const toolsVersion = refreshData.tools.version;
|
|
15206
15333
|
const known = agentState.knownVersions.get(agent.agent_id);
|
|
15207
|
-
let lastProvisionAt =
|
|
15334
|
+
let lastProvisionAt = state8.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
|
|
15208
15335
|
const quarantinedChannels = channelQuarantineStore().getQuarantinedKeys(agent.code_name);
|
|
15209
15336
|
const currentChannelIds = setWithout(
|
|
15210
15337
|
launchableChannelIds(refreshData.channel_configs),
|
|
@@ -15659,18 +15786,18 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15659
15786
|
agentState.knownChannels.set(agent.agent_id, currentChannelIds);
|
|
15660
15787
|
}
|
|
15661
15788
|
} else {
|
|
15662
|
-
const
|
|
15789
|
+
const state9 = recordChannelSyncFailure(
|
|
15663
15790
|
channelSyncFailures,
|
|
15664
15791
|
agent.agent_id,
|
|
15665
15792
|
channelConfigFailureReason || "reason not recorded",
|
|
15666
15793
|
Date.now()
|
|
15667
15794
|
);
|
|
15668
|
-
if (shouldLogChannelSyncFailure(
|
|
15669
|
-
|
|
15670
|
-
const stuckForSeconds = Math.floor((Date.now() -
|
|
15671
|
-
const waitMs = channelSyncBackoffMs(
|
|
15795
|
+
if (shouldLogChannelSyncFailure(state9)) {
|
|
15796
|
+
state9.loggedAtAttempt = state9.attempts;
|
|
15797
|
+
const stuckForSeconds = Math.floor((Date.now() - state9.since) / 1e3);
|
|
15798
|
+
const waitMs = channelSyncBackoffMs(state9.attempts);
|
|
15672
15799
|
log(
|
|
15673
|
-
`[channels] Credential sync did not converge for '${agent.code_name}' \u2014 attempt ${
|
|
15800
|
+
`[channels] Credential sync did not converge for '${agent.code_name}' \u2014 attempt ${state9.attempts}, stuck ${stuckForSeconds}s, next retry in ${Math.round(waitMs / 1e3)}s. Cause: ${state9.lastReason}. Diff left live (ENG-9252).`
|
|
15674
15801
|
);
|
|
15675
15802
|
}
|
|
15676
15803
|
}
|
|
@@ -15970,7 +16097,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
|
|
|
15970
16097
|
log(`Failed to provision direct-chat channel for '${agent.code_name}': ${err.message}`);
|
|
15971
16098
|
}
|
|
15972
16099
|
}
|
|
15973
|
-
let lastSecretsProvisionAt =
|
|
16100
|
+
let lastSecretsProvisionAt = state8.agents.find((a) => a.agentId === agent.agent_id)?.lastSecretsProvisionAt ?? null;
|
|
15974
16101
|
let secretsHash = agentState.knownSecretsHashes.get(agent.agent_id) ?? null;
|
|
15975
16102
|
try {
|
|
15976
16103
|
const secretsData = await api.post("/host/secrets", { agent_id: agent.agent_id });
|
|
@@ -17854,9 +17981,9 @@ ${truncateForLog(ctx.tail)}` : `; pane_tail_hash=sha256:${createHash17("sha256")
|
|
|
17854
17981
|
} else if (!claudeSchedulerStates.has(codeName)) {
|
|
17855
17982
|
claudeSchedulerStates.set(codeName, loadSchedulerState(codeName));
|
|
17856
17983
|
}
|
|
17857
|
-
const
|
|
17858
|
-
if (
|
|
17859
|
-
const ready = getReadyTasks(
|
|
17984
|
+
const state9 = claudeSchedulerStates.get(codeName);
|
|
17985
|
+
if (state9) {
|
|
17986
|
+
const ready = getReadyTasks(state9, inFlightClaudeTasks);
|
|
17860
17987
|
if (ready.length > 0) {
|
|
17861
17988
|
log(`[persistent-session] ${ready.length} ready task(s) for '${codeName}': ${ready.map((t) => `${t.name}(next=${t.nextFireAt ? new Date(t.nextFireAt).toISOString() : "null"})`).join(", ")}`);
|
|
17862
17989
|
}
|
|
@@ -17950,19 +18077,19 @@ function recordRealtimeRebindFailure(failures, agentId, status, now) {
|
|
|
17950
18077
|
return next;
|
|
17951
18078
|
}
|
|
17952
18079
|
function realtimeRebindDue(failures, now) {
|
|
17953
|
-
for (const
|
|
18080
|
+
for (const state9 of failures.values()) if (now >= state9.nextAttemptAt) return true;
|
|
17954
18081
|
return false;
|
|
17955
18082
|
}
|
|
17956
18083
|
function stuckRealtimeRebinds(failures, now, thresholdMs = REALTIME_REBIND_STUCK_AFTER_MS) {
|
|
17957
18084
|
const out = [];
|
|
17958
|
-
for (const [agentId,
|
|
17959
|
-
const stuckForMs = now -
|
|
18085
|
+
for (const [agentId, state9] of failures) {
|
|
18086
|
+
const stuckForMs = now - state9.since;
|
|
17960
18087
|
if (stuckForMs < thresholdMs) continue;
|
|
17961
18088
|
out.push({
|
|
17962
18089
|
agent_id: agentId,
|
|
17963
|
-
attempts:
|
|
18090
|
+
attempts: state9.attempts,
|
|
17964
18091
|
stuck_for_seconds: Math.floor(stuckForMs / 1e3),
|
|
17965
|
-
status:
|
|
18092
|
+
status: state9.lastStatus
|
|
17966
18093
|
});
|
|
17967
18094
|
}
|
|
17968
18095
|
out.sort((a, b) => b.stuck_for_seconds - a.stuck_for_seconds);
|
|
@@ -17985,8 +18112,8 @@ function pruneRealtimeRebindState(failures, liveAgentIds) {
|
|
|
17985
18112
|
function holdRealtimeRebindInFlight(failures, agentIds, now, graceMs = REALTIME_REBIND_IN_FLIGHT_GRACE_MS) {
|
|
17986
18113
|
const until = now + graceMs;
|
|
17987
18114
|
for (const agentId of agentIds) {
|
|
17988
|
-
const
|
|
17989
|
-
if (
|
|
18115
|
+
const state9 = failures.get(agentId);
|
|
18116
|
+
if (state9) state9.nextAttemptAt = Math.max(state9.nextAttemptAt, until);
|
|
17990
18117
|
}
|
|
17991
18118
|
}
|
|
17992
18119
|
var realtimeAssignStarted = false;
|
|
@@ -18107,7 +18234,7 @@ function restartReasonStampsTiming(reason) {
|
|
|
18107
18234
|
return reason === "integration-change";
|
|
18108
18235
|
}
|
|
18109
18236
|
async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
18110
|
-
const prev =
|
|
18237
|
+
const prev = state8.agents.find((a) => a.agentId === agentId);
|
|
18111
18238
|
const codeName = prev?.codeName;
|
|
18112
18239
|
if (!codeName) return;
|
|
18113
18240
|
const lastProcessed = prev?.lastRestartProcessedAt ?? null;
|
|
@@ -18158,7 +18285,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
18158
18285
|
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}`));
|
|
18159
18286
|
void (async () => {
|
|
18160
18287
|
try {
|
|
18161
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
18288
|
+
const { collectDiagnostics } = await import("../persistent-session-5ZWDVVIH.js");
|
|
18162
18289
|
await api.post("/host/heartbeat", {
|
|
18163
18290
|
host_id: hostId,
|
|
18164
18291
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor)
|
|
@@ -18169,7 +18296,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
18169
18296
|
})();
|
|
18170
18297
|
prev.lastRestartProcessedAt = requestedAt;
|
|
18171
18298
|
try {
|
|
18172
|
-
atomicWriteFileSync(getStateFile(), JSON.stringify(
|
|
18299
|
+
atomicWriteFileSync(getStateFile(), JSON.stringify(state8, null, 2));
|
|
18173
18300
|
} catch (err) {
|
|
18174
18301
|
log(`[restart-lane] failed to persist ack for '${codeName}': ${err.message}`);
|
|
18175
18302
|
}
|
|
@@ -18179,7 +18306,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
18179
18306
|
}
|
|
18180
18307
|
}
|
|
18181
18308
|
async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
18182
|
-
const prev =
|
|
18309
|
+
const prev = state8.agents.find((a) => a.codeName === codeName);
|
|
18183
18310
|
if (!prev) return;
|
|
18184
18311
|
const agentId = prev.agentId;
|
|
18185
18312
|
if (restartInFlight.has(agentId)) return;
|
|
@@ -18209,7 +18336,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
18209
18336
|
}
|
|
18210
18337
|
try {
|
|
18211
18338
|
const hostId = await getHostId();
|
|
18212
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
18339
|
+
const { collectDiagnostics } = await import("../persistent-session-5ZWDVVIH.js");
|
|
18213
18340
|
await api.post("/host/heartbeat", {
|
|
18214
18341
|
host_id: hostId,
|
|
18215
18342
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor)
|
|
@@ -18430,18 +18557,18 @@ function ensureRealtimeIntegrationContextStarted(agentStates) {
|
|
|
18430
18557
|
);
|
|
18431
18558
|
},
|
|
18432
18559
|
onSubscriptionLost: (agentId, status) => {
|
|
18433
|
-
const
|
|
18560
|
+
const state9 = recordRealtimeRebindFailure(
|
|
18434
18561
|
realtimeRebindFailures,
|
|
18435
18562
|
agentId,
|
|
18436
18563
|
status,
|
|
18437
18564
|
Date.now()
|
|
18438
18565
|
);
|
|
18439
|
-
const waitMs = realtimeRebindBackoffMs(
|
|
18440
|
-
if (
|
|
18441
|
-
|
|
18442
|
-
const stuckForSeconds = Math.floor((Date.now() -
|
|
18566
|
+
const waitMs = realtimeRebindBackoffMs(state9.attempts);
|
|
18567
|
+
if (state9.attempts === 1 || state9.attempts > state9.loggedAtAttempt) {
|
|
18568
|
+
state9.loggedAtAttempt = state9.attempts;
|
|
18569
|
+
const stuckForSeconds = Math.floor((Date.now() - state9.since) / 1e3);
|
|
18443
18570
|
log(
|
|
18444
|
-
`[realtime] Token rotation subscription lost for agent ${agentId} (${status}) \u2014 attempt ${
|
|
18571
|
+
`[realtime] Token rotation subscription lost for agent ${agentId} (${status}) \u2014 attempt ${state9.attempts}, stuck ${stuckForSeconds}s, next rebind in ${Math.round(waitMs / 1e3)}s (ENG-9265)`
|
|
18445
18572
|
);
|
|
18446
18573
|
}
|
|
18447
18574
|
if (waitMs === 0) subscribedIntegrationContextAgentIds = /* @__PURE__ */ new Set();
|
|
@@ -18657,10 +18784,10 @@ function getKanbanNudgeState(codeName) {
|
|
|
18657
18784
|
function loadKanbanNudgeStateFromDisk() {
|
|
18658
18785
|
loadKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
18659
18786
|
}
|
|
18660
|
-
function setKanbanNudgeState(codeName,
|
|
18787
|
+
function setKanbanNudgeState(codeName, state9) {
|
|
18661
18788
|
const key = kanbanNudgeStateKey(codeName);
|
|
18662
18789
|
if (key !== codeName) kanbanNudgeStateByCode.delete(codeName);
|
|
18663
|
-
kanbanNudgeStateByCode.set(key,
|
|
18790
|
+
kanbanNudgeStateByCode.set(key, state9);
|
|
18664
18791
|
saveKanbanNudgeState(kanbanNudgeStateByCode, channelHashCacheDir());
|
|
18665
18792
|
}
|
|
18666
18793
|
function clearKanbanNudgeState(codeName) {
|
|
@@ -18841,7 +18968,7 @@ async function processClaudePairSessions(agents) {
|
|
|
18841
18968
|
killPairSession,
|
|
18842
18969
|
pairTmuxSession,
|
|
18843
18970
|
finalizeClaudePairOnboarding
|
|
18844
|
-
} = await import("../claude-pair-runtime-
|
|
18971
|
+
} = await import("../claude-pair-runtime-I7MIDQSW.js");
|
|
18845
18972
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
18846
18973
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
18847
18974
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -19479,7 +19606,7 @@ async function driveArtifactStreaming() {
|
|
|
19479
19606
|
}
|
|
19480
19607
|
async function driveArtifactStreamingInner() {
|
|
19481
19608
|
const liveIds = /* @__PURE__ */ new Set();
|
|
19482
|
-
for (const agent of
|
|
19609
|
+
for (const agent of state8.agents) {
|
|
19483
19610
|
if (!agent.agentId || !agent.codeName || agent.status !== "active") continue;
|
|
19484
19611
|
liveIds.add(agent.agentId);
|
|
19485
19612
|
let scanner = artifactScanners.get(agent.agentId);
|
|
@@ -19512,7 +19639,7 @@ async function postLivenessHeartbeat() {
|
|
|
19512
19639
|
await api.post("/host/heartbeat", {
|
|
19513
19640
|
host_id: hostId,
|
|
19514
19641
|
agt_version: agtCliVersion,
|
|
19515
|
-
last_poll_at:
|
|
19642
|
+
last_poll_at: state8.lastPollAt ?? void 0,
|
|
19516
19643
|
// The delay actually in force, so the monitor compares against reality
|
|
19517
19644
|
// rather than a constant — a manager riding out an API outage under the
|
|
19518
19645
|
// ENG-5041 backoff must not be paged as stopped.
|
|
@@ -19689,8 +19816,8 @@ function startManager(opts) {
|
|
|
19689
19816
|
const raw = readFileSync29(stateFile, "utf-8");
|
|
19690
19817
|
const parsed = JSON.parse(raw);
|
|
19691
19818
|
if (Array.isArray(parsed.agents)) {
|
|
19692
|
-
|
|
19693
|
-
log(`[startup] rehydrated ${
|
|
19819
|
+
state8.agents = parsed.agents;
|
|
19820
|
+
log(`[startup] rehydrated ${state8.agents.length} agent state(s) from ${stateFile}`);
|
|
19694
19821
|
}
|
|
19695
19822
|
if (parsed.circuitBreakerTrips && typeof parsed.circuitBreakerTrips === "object") {
|
|
19696
19823
|
restartBreaker.hydrate(parsed.circuitBreakerTrips);
|
|
@@ -19703,9 +19830,9 @@ function startManager(opts) {
|
|
|
19703
19830
|
if (n > 0) log(`[startup] rehydrated ${n} auto-resume marker(s) (ENG-6088)`);
|
|
19704
19831
|
}
|
|
19705
19832
|
if (typeof parsed.lastUpdateRequestProcessedAt === "string" || parsed.lastUpdateRequestProcessedAt === null) {
|
|
19706
|
-
|
|
19707
|
-
if (
|
|
19708
|
-
log(`[startup] rehydrated update-request ack at ${
|
|
19833
|
+
state8.lastUpdateRequestProcessedAt = parsed.lastUpdateRequestProcessedAt;
|
|
19834
|
+
if (state8.lastUpdateRequestProcessedAt) {
|
|
19835
|
+
log(`[startup] rehydrated update-request ack at ${state8.lastUpdateRequestProcessedAt} (ENG-6692)`);
|
|
19709
19836
|
}
|
|
19710
19837
|
}
|
|
19711
19838
|
}
|
|
@@ -19725,7 +19852,7 @@ function startManager(opts) {
|
|
|
19725
19852
|
}
|
|
19726
19853
|
try {
|
|
19727
19854
|
refreshSlackRestartContextHints(
|
|
19728
|
-
|
|
19855
|
+
state8.agents.map((a) => a.codeName),
|
|
19729
19856
|
{ log }
|
|
19730
19857
|
);
|
|
19731
19858
|
} catch (err) {
|