@integrity-labs/agt-cli 0.28.351 → 0.28.353
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 +4 -4
- package/dist/{chunk-F2TH5XVJ.js → chunk-5MZMXKVD.js} +89 -88
- package/dist/{chunk-F2TH5XVJ.js.map → chunk-5MZMXKVD.js.map} +1 -1
- package/dist/{chunk-OEJ35WXL.js → chunk-ZALWFOHO.js} +1 -1
- package/dist/chunk-ZALWFOHO.js.map +1 -0
- package/dist/{claude-pair-runtime-NUGUTMMT.js → claude-pair-runtime-KO2HWC7E.js} +2 -2
- package/dist/lib/manager-worker.js +173 -25
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-KFR2GLKC.js → persistent-session-WMQO3QKU.js} +2 -2
- package/dist/{responsiveness-probe-PFPXYTL2.js → responsiveness-probe-TCTSHDH3.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-OEJ35WXL.js.map +0 -1
- /package/dist/{claude-pair-runtime-NUGUTMMT.js.map → claude-pair-runtime-KO2HWC7E.js.map} +0 -0
- /package/dist/{persistent-session-KFR2GLKC.js.map → persistent-session-WMQO3QKU.js.map} +0 -0
- /package/dist/{responsiveness-probe-PFPXYTL2.js.map → responsiveness-probe-TCTSHDH3.js.map} +0 -0
|
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
|
|
|
100
100
|
return { ok: true };
|
|
101
101
|
} catch {
|
|
102
102
|
}
|
|
103
|
-
const { resolveClaudeBinary } = await import("./persistent-session-
|
|
103
|
+
const { resolveClaudeBinary } = await import("./persistent-session-WMQO3QKU.js");
|
|
104
104
|
const claudeBin = resolveClaudeBinary();
|
|
105
105
|
const pairEnv = {
|
|
106
106
|
...process.env,
|
|
@@ -373,4 +373,4 @@ export {
|
|
|
373
373
|
startClaudePair,
|
|
374
374
|
submitClaudePairCode
|
|
375
375
|
};
|
|
376
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
376
|
+
//# sourceMappingURL=claude-pair-runtime-KO2HWC7E.js.map
|
|
@@ -45,8 +45,9 @@ import {
|
|
|
45
45
|
requireHost,
|
|
46
46
|
resolveEffectivePinRaw,
|
|
47
47
|
safeWriteJsonAtomic,
|
|
48
|
-
setConfigHash
|
|
49
|
-
|
|
48
|
+
setConfigHash,
|
|
49
|
+
toOpencodeModel
|
|
50
|
+
} from "../chunk-5MZMXKVD.js";
|
|
50
51
|
import {
|
|
51
52
|
getProjectDir as getProjectDir2,
|
|
52
53
|
getReadyTasks,
|
|
@@ -137,7 +138,7 @@ import {
|
|
|
137
138
|
takeZombieDetection,
|
|
138
139
|
transcriptActivityAgeSeconds,
|
|
139
140
|
writeEgressAllowlist
|
|
140
|
-
} from "../chunk-
|
|
141
|
+
} from "../chunk-ZALWFOHO.js";
|
|
141
142
|
import {
|
|
142
143
|
reapOrphanChannelMcps
|
|
143
144
|
} from "../chunk-XWVM4KPK.js";
|
|
@@ -806,6 +807,19 @@ function countByClass(events) {
|
|
|
806
807
|
}
|
|
807
808
|
return { crash, provisioning, "credential-rotation": credentialRotation };
|
|
808
809
|
}
|
|
810
|
+
function maxProvisioningBucket(events) {
|
|
811
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
812
|
+
for (const e of events) {
|
|
813
|
+
if (!isProvisioningReloadReason(e.reason)) continue;
|
|
814
|
+
const key = e.integrationKey ?? "";
|
|
815
|
+
buckets.set(key, (buckets.get(key) ?? 0) + 1);
|
|
816
|
+
}
|
|
817
|
+
let best = { count: 0, key: "" };
|
|
818
|
+
for (const [key, count] of buckets) {
|
|
819
|
+
if (count > best.count) best = { count, key };
|
|
820
|
+
}
|
|
821
|
+
return best;
|
|
822
|
+
}
|
|
809
823
|
var DEFAULT_MAX = 2;
|
|
810
824
|
var DEFAULT_WINDOW_MS = 6e5;
|
|
811
825
|
var DEFAULT_PROVISIONING_MAX = 5;
|
|
@@ -862,20 +876,25 @@ var RestartBreaker = class {
|
|
|
862
876
|
* without double-counting events. Callers may still record the reason
|
|
863
877
|
* via the decision-log for forensics.
|
|
864
878
|
*/
|
|
865
|
-
record(codeName, reason) {
|
|
879
|
+
record(codeName, reason, integrationKey) {
|
|
866
880
|
const existing = this.trips.get(codeName);
|
|
867
881
|
if (existing) {
|
|
882
|
+
const bucket = maxProvisioningBucket(existing.eventsAtTrip);
|
|
868
883
|
return {
|
|
869
884
|
tripped: false,
|
|
870
885
|
trip: existing,
|
|
871
886
|
windowCount: existing.eventsAtTrip.length,
|
|
872
|
-
classCounts: countByClass(existing.eventsAtTrip)
|
|
887
|
+
classCounts: countByClass(existing.eventsAtTrip),
|
|
888
|
+
maxProvisioningBucket: bucket.count,
|
|
889
|
+
maxProvisioningBucketKey: bucket.key
|
|
873
890
|
};
|
|
874
891
|
}
|
|
875
892
|
const at = this.now();
|
|
876
893
|
const retentionCutoff = at - this.retentionMs;
|
|
877
894
|
const prior = (this.events.get(codeName) ?? []).filter((e) => e.at >= retentionCutoff);
|
|
878
|
-
prior.push(
|
|
895
|
+
prior.push(
|
|
896
|
+
isProvisioningReloadReason(reason) && integrationKey ? { reason, at, integrationKey } : { reason, at }
|
|
897
|
+
);
|
|
879
898
|
this.events.set(codeName, prior);
|
|
880
899
|
const crashCount = prior.filter(
|
|
881
900
|
(e) => e.at >= at - this.windowMs && restartReasonClass(e.reason) === "crash"
|
|
@@ -892,6 +911,7 @@ var RestartBreaker = class {
|
|
|
892
911
|
provisioning: provEvents.length,
|
|
893
912
|
"credential-rotation": credRotCount
|
|
894
913
|
};
|
|
914
|
+
const provBucket = maxProvisioningBucket(provEvents);
|
|
895
915
|
let trippedClass;
|
|
896
916
|
let tripEvents;
|
|
897
917
|
let tripWindowMs = this.windowMs;
|
|
@@ -901,22 +921,36 @@ var RestartBreaker = class {
|
|
|
901
921
|
(e) => e.at >= at - this.windowMs && restartReasonClass(e.reason) === "crash"
|
|
902
922
|
);
|
|
903
923
|
tripWindowMs = this.windowMs;
|
|
904
|
-
} else if (
|
|
924
|
+
} else if (provBucket.count > this.provisioningMax) {
|
|
905
925
|
trippedClass = "provisioning";
|
|
906
|
-
tripEvents = provEvents;
|
|
926
|
+
tripEvents = provEvents.filter((e) => (e.integrationKey ?? "") === provBucket.key);
|
|
907
927
|
tripWindowMs = this.provisioningWindowMs;
|
|
908
928
|
}
|
|
909
929
|
if (trippedClass && tripEvents) {
|
|
910
930
|
const trip = {
|
|
911
931
|
trippedAt: at,
|
|
912
932
|
eventsAtTrip: [...tripEvents],
|
|
913
|
-
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass)
|
|
933
|
+
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key)
|
|
914
934
|
};
|
|
915
935
|
this.trips.set(codeName, trip);
|
|
916
936
|
this.events.delete(codeName);
|
|
917
|
-
return {
|
|
937
|
+
return {
|
|
938
|
+
tripped: true,
|
|
939
|
+
trip,
|
|
940
|
+
windowCount,
|
|
941
|
+
classCounts,
|
|
942
|
+
trippedClass,
|
|
943
|
+
maxProvisioningBucket: provBucket.count,
|
|
944
|
+
maxProvisioningBucketKey: provBucket.key
|
|
945
|
+
};
|
|
918
946
|
}
|
|
919
|
-
return {
|
|
947
|
+
return {
|
|
948
|
+
tripped: false,
|
|
949
|
+
windowCount,
|
|
950
|
+
classCounts,
|
|
951
|
+
maxProvisioningBucket: provBucket.count,
|
|
952
|
+
maxProvisioningBucketKey: provBucket.key
|
|
953
|
+
};
|
|
920
954
|
}
|
|
921
955
|
/** Operator-initiated reset: drops the trip + the events log for this agent. */
|
|
922
956
|
clear(codeName) {
|
|
@@ -947,14 +981,15 @@ var RestartBreaker = class {
|
|
|
947
981
|
return (this.events.get(codeName) ?? []).filter((e) => e.at >= cutoff).length;
|
|
948
982
|
}
|
|
949
983
|
};
|
|
950
|
-
function formatStatusMessage(events, windowMs, klass = "crash") {
|
|
984
|
+
function formatStatusMessage(events, windowMs, klass = "crash", integrationKey = "") {
|
|
951
985
|
const last = events[events.length - 1];
|
|
952
986
|
const windowLabel = windowMs < 6e4 ? `${Math.round(windowMs / 1e3)}s` : `${(windowMs / 6e4).toFixed(1).replace(/\.0$/, "")}min`;
|
|
953
987
|
const reasonCounts = /* @__PURE__ */ new Map();
|
|
954
988
|
for (const e of events) reasonCounts.set(e.reason, (reasonCounts.get(e.reason) ?? 0) + 1);
|
|
955
989
|
const breakdown = Array.from(reasonCounts.entries()).map(([r, n]) => `${r}=${n}`).join(", ");
|
|
956
990
|
const classLabel = klass === "provisioning" ? "provisioning-reload " : "";
|
|
957
|
-
|
|
991
|
+
const integrationLabel = klass === "provisioning" && integrationKey ? ` for integration '${integrationKey}'` : "";
|
|
992
|
+
return `Circuit breaker tripped: ${events.length} ${classLabel}restarts in ${windowLabel}${integrationLabel} (${breakdown}); most recent=${last.reason} at ${new Date(last.at).toISOString()}`;
|
|
958
993
|
}
|
|
959
994
|
|
|
960
995
|
// src/lib/mcp-flap-dampener.ts
|
|
@@ -1250,12 +1285,25 @@ function parseResumeHealthResponse(raw) {
|
|
|
1250
1285
|
// src/lib/model-change-respawn.ts
|
|
1251
1286
|
function shouldRespawnForModelChange(input) {
|
|
1252
1287
|
const { previousModel, primaryModel, framework, sessionHealthy } = input;
|
|
1253
|
-
if (framework !== "claude-code") return false;
|
|
1288
|
+
if (framework !== "claude-code" && framework !== "opencode") return false;
|
|
1254
1289
|
if (!sessionHealthy) return false;
|
|
1255
1290
|
if (!previousModel) return false;
|
|
1256
1291
|
if (!primaryModel) return false;
|
|
1257
1292
|
return previousModel !== primaryModel;
|
|
1258
1293
|
}
|
|
1294
|
+
function decideOpencodeModelRestart(input) {
|
|
1295
|
+
const { previousModel, primaryModel, provisionedModel, onDiskModel, sessionHealthy } = input;
|
|
1296
|
+
if (onDiskModel !== provisionedModel) {
|
|
1297
|
+
return { restart: false, recordModel: false };
|
|
1298
|
+
}
|
|
1299
|
+
const restart = shouldRespawnForModelChange({
|
|
1300
|
+
previousModel,
|
|
1301
|
+
primaryModel,
|
|
1302
|
+
framework: "opencode",
|
|
1303
|
+
sessionHealthy
|
|
1304
|
+
});
|
|
1305
|
+
return { restart, recordModel: true };
|
|
1306
|
+
}
|
|
1259
1307
|
|
|
1260
1308
|
// src/lib/connectivity-probe-runner.ts
|
|
1261
1309
|
var DEFAULT_INTERVAL_MS = 60 * 60 * 1e3;
|
|
@@ -3755,6 +3803,17 @@ var agentState = {
|
|
|
3755
3803
|
knownModels: /* @__PURE__ */ new Map(),
|
|
3756
3804
|
knownTasksHashes: /* @__PURE__ */ new Map(),
|
|
3757
3805
|
knownIntegrationHashes: /* @__PURE__ */ new Map(),
|
|
3806
|
+
/**
|
|
3807
|
+
* ENG-7812: the integration MEMBERSHIP (sorted `definition_id`s, credential/
|
|
3808
|
+
* config churn ignored) observed on the previous refresh. Diffed against the
|
|
3809
|
+
* current membership each poll to derive which integration(s) an
|
|
3810
|
+
* `integration-change` / `hot-reload-mcp` restart is attributable to, which the
|
|
3811
|
+
* restart breaker buckets its provisioning trip by (so onboarding many distinct
|
|
3812
|
+
* integrations doesn't auto-pause a healthy new agent). In-memory only: a
|
|
3813
|
+
* manager restart re-seeds it on the first poll (that first delta is treated as
|
|
3814
|
+
* "no attribution", which is safe: it only widens, never narrows, the trip).
|
|
3815
|
+
*/
|
|
3816
|
+
knownIntegrationMembership: /* @__PURE__ */ new Map(),
|
|
3758
3817
|
knownManagedMcpHashes: /* @__PURE__ */ new Map(),
|
|
3759
3818
|
knownManagedMcpStructure: /* @__PURE__ */ new Map(),
|
|
3760
3819
|
/**
|
|
@@ -3790,6 +3849,16 @@ var agentState = {
|
|
|
3790
3849
|
// ---------------------------------------------------------------------------
|
|
3791
3850
|
agentDisplayNames: /* @__PURE__ */ new Map(),
|
|
3792
3851
|
codeNameToAgentId: /* @__PURE__ */ new Map(),
|
|
3852
|
+
/**
|
|
3853
|
+
* ENG-7812: the most recent integration-membership delta for this agent, used
|
|
3854
|
+
* to attribute a provisioning-reload restart to the integration that caused it.
|
|
3855
|
+
* Set when a poll observes an integration add/remove (the changed
|
|
3856
|
+
* `definition_id`s, `+`-joined); read by `recordRestartForBreaker` when a
|
|
3857
|
+
* provisioning restart fires shortly after. `at` bounds its freshness to the
|
|
3858
|
+
* breaker's provisioning window so a stale delta can't mis-attribute a much
|
|
3859
|
+
* later reprovision (those fall through to the shared unattributed bucket).
|
|
3860
|
+
*/
|
|
3861
|
+
provisioningAttribution: /* @__PURE__ */ new Map(),
|
|
3793
3862
|
/**
|
|
3794
3863
|
* Set of code_names with a live persistent session managed by this worker.
|
|
3795
3864
|
* Borderline ownership: written from pollCycle and the persistent-session
|
|
@@ -3827,6 +3896,7 @@ function clearAgentState(agentId, codeName) {
|
|
|
3827
3896
|
agentState.knownModels.delete(agentId);
|
|
3828
3897
|
agentState.knownTasksHashes.delete(agentId);
|
|
3829
3898
|
agentState.knownIntegrationHashes.delete(agentId);
|
|
3899
|
+
agentState.knownIntegrationMembership.delete(agentId);
|
|
3830
3900
|
agentState.knownManagedMcpHashes.delete(agentId);
|
|
3831
3901
|
agentState.knownManagedMcpStructure.delete(agentId);
|
|
3832
3902
|
agentState.knownSenderPolicyHashes.delete(agentId);
|
|
@@ -3835,6 +3905,7 @@ function clearAgentState(agentId, codeName) {
|
|
|
3835
3905
|
agentState.knownGlobalSkillIds.delete(agentId);
|
|
3836
3906
|
agentState.agentDisplayNames.delete(codeName);
|
|
3837
3907
|
agentState.codeNameToAgentId.delete(codeName);
|
|
3908
|
+
agentState.provisioningAttribution.delete(codeName);
|
|
3838
3909
|
let channelCacheMutated = false;
|
|
3839
3910
|
for (const key of agentState.knownChannelConfigHashes.keys()) {
|
|
3840
3911
|
if (key.startsWith(`${agentId}:`)) {
|
|
@@ -5577,6 +5648,15 @@ function opencodeTmuxSession(codeName) {
|
|
|
5577
5648
|
function opencodePaneLogPath(codeName) {
|
|
5578
5649
|
return join20(homedir10(), ".augmented", codeName, "opencode-serve.log");
|
|
5579
5650
|
}
|
|
5651
|
+
function readProvisionedOpencodeModel(agentDir) {
|
|
5652
|
+
try {
|
|
5653
|
+
const raw = readFileSync16(join20(agentDir, "provision", "opencode.json"), "utf-8");
|
|
5654
|
+
const parsed = JSON.parse(raw);
|
|
5655
|
+
return typeof parsed.model === "string" ? parsed.model : null;
|
|
5656
|
+
} catch {
|
|
5657
|
+
return null;
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5580
5660
|
function baseUrlFor(port) {
|
|
5581
5661
|
return `http://127.0.0.1:${port}`;
|
|
5582
5662
|
}
|
|
@@ -5737,6 +5817,21 @@ function getBridge(codeName, port, password) {
|
|
|
5737
5817
|
bridges.set(codeName, { port, password, bridge });
|
|
5738
5818
|
return bridge;
|
|
5739
5819
|
}
|
|
5820
|
+
function stopOpencodeSession(codeName, log2) {
|
|
5821
|
+
const tmuxSession = opencodeTmuxSession(codeName);
|
|
5822
|
+
try {
|
|
5823
|
+
execSync(`tmux kill-session -t ${tmuxSession} 2>/dev/null`, { stdio: "ignore" });
|
|
5824
|
+
log2(`[opencode-session] stopped '${tmuxSession}' for '${codeName}'`);
|
|
5825
|
+
} catch {
|
|
5826
|
+
}
|
|
5827
|
+
bridges.delete(codeName);
|
|
5828
|
+
const session = sessions.get(codeName);
|
|
5829
|
+
if (session) {
|
|
5830
|
+
session.status = "stopped";
|
|
5831
|
+
session.port = null;
|
|
5832
|
+
session.password = null;
|
|
5833
|
+
}
|
|
5834
|
+
}
|
|
5740
5835
|
function stripUndefined(env) {
|
|
5741
5836
|
const out = {};
|
|
5742
5837
|
for (const [k, v] of Object.entries(env)) if (v !== void 0) out[k] = v;
|
|
@@ -8434,6 +8529,10 @@ var pendingRestartVerifications = /* @__PURE__ */ new Map();
|
|
|
8434
8529
|
var restartBreaker = new RestartBreaker();
|
|
8435
8530
|
var reportedTrips = /* @__PURE__ */ new Map();
|
|
8436
8531
|
var RESTART_BREAKER_PROVISIONING_MAX = readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_MAX", 5);
|
|
8532
|
+
var RESTART_BREAKER_PROVISIONING_WINDOW_MS = readEnvNumber(
|
|
8533
|
+
"AGT_RESTART_BREAKER_PROVISIONING_WINDOW_MS",
|
|
8534
|
+
18e5
|
|
8535
|
+
);
|
|
8437
8536
|
var mcpFlapDampener = new McpFlapDampener();
|
|
8438
8537
|
var FLAP_BREAKER_COOLDOWN_MS = readEnvNumber2(
|
|
8439
8538
|
"AGT_MCP_FLAP_BREAKER_COOLDOWN_MS",
|
|
@@ -8472,11 +8571,19 @@ function recordRestartForBreaker(codeName, reason) {
|
|
|
8472
8571
|
);
|
|
8473
8572
|
return;
|
|
8474
8573
|
}
|
|
8475
|
-
|
|
8574
|
+
let integrationKey;
|
|
8575
|
+
if (isProvisioningReloadReason(reason)) {
|
|
8576
|
+
const attribution = agentState.provisioningAttribution.get(codeName);
|
|
8577
|
+
if (attribution && Date.now() - attribution.at <= RESTART_BREAKER_PROVISIONING_WINDOW_MS) {
|
|
8578
|
+
integrationKey = attribution.key;
|
|
8579
|
+
}
|
|
8580
|
+
}
|
|
8581
|
+
const result = restartBreaker.record(codeName, reason, integrationKey);
|
|
8476
8582
|
if (!result.tripped || !result.trip) {
|
|
8477
|
-
if (isProvisioningReloadReason(reason) && result.
|
|
8583
|
+
if (isProvisioningReloadReason(reason) && result.maxProvisioningBucket >= RESTART_BREAKER_PROVISIONING_MAX) {
|
|
8584
|
+
const culprit = result.maxProvisioningBucketKey ? ` [${result.maxProvisioningBucketKey}]` : "";
|
|
8478
8585
|
log(
|
|
8479
|
-
`[restart-breaker] agent=${codeName} provisioning-reload churn at the trip bar: ${result.
|
|
8586
|
+
`[restart-breaker] agent=${codeName} provisioning-reload churn at the trip bar: ${result.maxProvisioningBucket} restarts for one integration${culprit} in window (reason=${reason}); one more will auto-pause the agent; that integration is likely churning (ENG-7560, ENG-7812)`
|
|
8480
8587
|
);
|
|
8481
8588
|
}
|
|
8482
8589
|
return;
|
|
@@ -9304,7 +9411,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9304
9411
|
var lastVersionCheckAt = 0;
|
|
9305
9412
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9306
9413
|
var lastResponsivenessProbeAt = 0;
|
|
9307
|
-
var agtCliVersion = true ? "0.28.
|
|
9414
|
+
var agtCliVersion = true ? "0.28.353" : "dev";
|
|
9308
9415
|
function resolveBrewPath(execFileSync2) {
|
|
9309
9416
|
try {
|
|
9310
9417
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10323,7 +10430,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
10323
10430
|
if (codeNames.length === 0) return;
|
|
10324
10431
|
void (async () => {
|
|
10325
10432
|
try {
|
|
10326
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10433
|
+
const { collectDiagnostics } = await import("../persistent-session-WMQO3QKU.js");
|
|
10327
10434
|
await api.post("/host/heartbeat", {
|
|
10328
10435
|
host_id: hostId,
|
|
10329
10436
|
agent_diagnostics: collectDiagnostics(codeNames)
|
|
@@ -10422,7 +10529,7 @@ async function pollCycle() {
|
|
|
10422
10529
|
}
|
|
10423
10530
|
try {
|
|
10424
10531
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
10425
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
10532
|
+
const { collectDiagnostics } = await import("../persistent-session-WMQO3QKU.js");
|
|
10426
10533
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
10427
10534
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
10428
10535
|
let tailscaleHostname;
|
|
@@ -10577,7 +10684,7 @@ async function pollCycle() {
|
|
|
10577
10684
|
const {
|
|
10578
10685
|
collectResponsivenessProbes,
|
|
10579
10686
|
getResponsivenessIntervalMs
|
|
10580
|
-
} = await import("../responsiveness-probe-
|
|
10687
|
+
} = await import("../responsiveness-probe-TCTSHDH3.js");
|
|
10581
10688
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
10582
10689
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
10583
10690
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -10609,7 +10716,7 @@ async function pollCycle() {
|
|
|
10609
10716
|
collectResponsivenessProbes,
|
|
10610
10717
|
livePendingInboundOldestAgeSeconds,
|
|
10611
10718
|
parkPendingInbound
|
|
10612
|
-
} = await import("../responsiveness-probe-
|
|
10719
|
+
} = await import("../responsiveness-probe-TCTSHDH3.js");
|
|
10613
10720
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-HYOOQV4A.js");
|
|
10614
10721
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
10615
10722
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -11584,6 +11691,28 @@ async function processAgent(agent, agentStates) {
|
|
|
11584
11691
|
}
|
|
11585
11692
|
}
|
|
11586
11693
|
agentState.knownModels.set(agent.agent_id, primaryModel);
|
|
11694
|
+
} else if (primaryModel && frameworkId === "opencode") {
|
|
11695
|
+
const previousModel = agentState.knownModels.get(agent.agent_id);
|
|
11696
|
+
const provisionedModel = toOpencodeModel(primaryModel);
|
|
11697
|
+
const onDiskModel = readProvisionedOpencodeModel(getFramework("opencode").getAgentDir(agent.code_name));
|
|
11698
|
+
const { restart, recordModel } = decideOpencodeModelRestart({
|
|
11699
|
+
previousModel,
|
|
11700
|
+
primaryModel,
|
|
11701
|
+
provisionedModel,
|
|
11702
|
+
onDiskModel,
|
|
11703
|
+
sessionHealthy: isOpencodeSessionHealthy(agent.code_name)
|
|
11704
|
+
});
|
|
11705
|
+
if (restart) {
|
|
11706
|
+
log(
|
|
11707
|
+
`[hot-reload] opencode model changed for '${agent.code_name}': ${previousModel} -> ${primaryModel} - restarting serve`
|
|
11708
|
+
);
|
|
11709
|
+
stopOpencodeSession(agent.code_name, log);
|
|
11710
|
+
} else if (previousModel && previousModel !== primaryModel && onDiskModel !== provisionedModel) {
|
|
11711
|
+
log(
|
|
11712
|
+
`[hot-reload] opencode model change for '${agent.code_name}' deferred: opencode.json shows '${onDiskModel}' not '${provisionedModel}' (provision not yet applied) - retrying next poll`
|
|
11713
|
+
);
|
|
11714
|
+
}
|
|
11715
|
+
if (recordModel) agentState.knownModels.set(agent.agent_id, primaryModel);
|
|
11587
11716
|
}
|
|
11588
11717
|
let lastDriftCheckAt = now;
|
|
11589
11718
|
const written = agentState.writtenHashes.get(agent.agent_id);
|
|
@@ -12171,6 +12300,25 @@ async function processAgent(agent, agentStates) {
|
|
|
12171
12300
|
}
|
|
12172
12301
|
}
|
|
12173
12302
|
}
|
|
12303
|
+
const currentIntIds = integrations.map((i) => i.definition_id);
|
|
12304
|
+
const prevIntIds = agentState.knownIntegrationMembership.get(agent.agent_id) ?? [];
|
|
12305
|
+
const prevIntSet = new Set(prevIntIds);
|
|
12306
|
+
const curIntSet = new Set(currentIntIds);
|
|
12307
|
+
const changedIntIds = Array.from(
|
|
12308
|
+
/* @__PURE__ */ new Set([
|
|
12309
|
+
...currentIntIds.filter((id) => !prevIntSet.has(id)),
|
|
12310
|
+
// added
|
|
12311
|
+
...prevIntIds.filter((id) => !curIntSet.has(id))
|
|
12312
|
+
// removed
|
|
12313
|
+
])
|
|
12314
|
+
).sort();
|
|
12315
|
+
if (changedIntIds.length > 0) {
|
|
12316
|
+
agentState.provisioningAttribution.set(agent.code_name, {
|
|
12317
|
+
key: changedIntIds.join("+"),
|
|
12318
|
+
at: Date.now()
|
|
12319
|
+
});
|
|
12320
|
+
}
|
|
12321
|
+
agentState.knownIntegrationMembership.set(agent.agent_id, currentIntIds);
|
|
12174
12322
|
if (integrations.length > 0) {
|
|
12175
12323
|
const intHash = computeIntegrationsHash(integrations);
|
|
12176
12324
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|
|
@@ -13723,7 +13871,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
13723
13871
|
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}`));
|
|
13724
13872
|
void (async () => {
|
|
13725
13873
|
try {
|
|
13726
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
13874
|
+
const { collectDiagnostics } = await import("../persistent-session-WMQO3QKU.js");
|
|
13727
13875
|
await api.post("/host/heartbeat", {
|
|
13728
13876
|
host_id: hostId,
|
|
13729
13877
|
agent_diagnostics: collectDiagnostics([codeName])
|
|
@@ -13773,7 +13921,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
13773
13921
|
}
|
|
13774
13922
|
try {
|
|
13775
13923
|
const hostId = await getHostId();
|
|
13776
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
13924
|
+
const { collectDiagnostics } = await import("../persistent-session-WMQO3QKU.js");
|
|
13777
13925
|
await api.post("/host/heartbeat", {
|
|
13778
13926
|
host_id: hostId,
|
|
13779
13927
|
agent_diagnostics: collectDiagnostics([codeName])
|
|
@@ -14271,7 +14419,7 @@ async function processClaudePairSessions(agents) {
|
|
|
14271
14419
|
killPairSession,
|
|
14272
14420
|
pairTmuxSession,
|
|
14273
14421
|
finalizeClaudePairOnboarding
|
|
14274
|
-
} = await import("../claude-pair-runtime-
|
|
14422
|
+
} = await import("../claude-pair-runtime-KO2HWC7E.js");
|
|
14275
14423
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
14276
14424
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
14277
14425
|
const killed = await killPairSession(pairTmuxSession(pairId));
|