@integrity-labs/agt-cli 0.28.352 → 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
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
success,
|
|
41
41
|
table,
|
|
42
42
|
warn
|
|
43
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-5MZMXKVD.js";
|
|
44
44
|
import {
|
|
45
45
|
AnchorSessionClient,
|
|
46
46
|
CHANNEL_REGISTRY,
|
|
@@ -4829,7 +4829,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4829
4829
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4830
4830
|
import chalk18 from "chalk";
|
|
4831
4831
|
import ora16 from "ora";
|
|
4832
|
-
var cliVersion = true ? "0.28.
|
|
4832
|
+
var cliVersion = true ? "0.28.353" : "dev";
|
|
4833
4833
|
async function fetchLatestVersion() {
|
|
4834
4834
|
const host2 = getHost();
|
|
4835
4835
|
if (!host2) return null;
|
|
@@ -6001,7 +6001,7 @@ function handleError(err) {
|
|
|
6001
6001
|
}
|
|
6002
6002
|
|
|
6003
6003
|
// src/bin/agt.ts
|
|
6004
|
-
var cliVersion2 = true ? "0.28.
|
|
6004
|
+
var cliVersion2 = true ? "0.28.353" : "dev";
|
|
6005
6005
|
var program = new Command();
|
|
6006
6006
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
6007
6007
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -7111,7 +7111,7 @@ function requireHost() {
|
|
|
7111
7111
|
}
|
|
7112
7112
|
|
|
7113
7113
|
// src/lib/api-client.ts
|
|
7114
|
-
var agtCliVersion = true ? "0.28.
|
|
7114
|
+
var agtCliVersion = true ? "0.28.353" : "dev";
|
|
7115
7115
|
var lastConfigHash = null;
|
|
7116
7116
|
function setConfigHash(hash) {
|
|
7117
7117
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -9561,4 +9561,4 @@ export {
|
|
|
9561
9561
|
managerInstallSystemUnitCommand,
|
|
9562
9562
|
managerUninstallSystemUnitCommand
|
|
9563
9563
|
};
|
|
9564
|
-
//# sourceMappingURL=chunk-
|
|
9564
|
+
//# sourceMappingURL=chunk-5MZMXKVD.js.map
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
safeWriteJsonAtomic,
|
|
48
48
|
setConfigHash,
|
|
49
49
|
toOpencodeModel
|
|
50
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-5MZMXKVD.js";
|
|
51
51
|
import {
|
|
52
52
|
getProjectDir as getProjectDir2,
|
|
53
53
|
getReadyTasks,
|
|
@@ -807,6 +807,19 @@ function countByClass(events) {
|
|
|
807
807
|
}
|
|
808
808
|
return { crash, provisioning, "credential-rotation": credentialRotation };
|
|
809
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
|
+
}
|
|
810
823
|
var DEFAULT_MAX = 2;
|
|
811
824
|
var DEFAULT_WINDOW_MS = 6e5;
|
|
812
825
|
var DEFAULT_PROVISIONING_MAX = 5;
|
|
@@ -863,20 +876,25 @@ var RestartBreaker = class {
|
|
|
863
876
|
* without double-counting events. Callers may still record the reason
|
|
864
877
|
* via the decision-log for forensics.
|
|
865
878
|
*/
|
|
866
|
-
record(codeName, reason) {
|
|
879
|
+
record(codeName, reason, integrationKey) {
|
|
867
880
|
const existing = this.trips.get(codeName);
|
|
868
881
|
if (existing) {
|
|
882
|
+
const bucket = maxProvisioningBucket(existing.eventsAtTrip);
|
|
869
883
|
return {
|
|
870
884
|
tripped: false,
|
|
871
885
|
trip: existing,
|
|
872
886
|
windowCount: existing.eventsAtTrip.length,
|
|
873
|
-
classCounts: countByClass(existing.eventsAtTrip)
|
|
887
|
+
classCounts: countByClass(existing.eventsAtTrip),
|
|
888
|
+
maxProvisioningBucket: bucket.count,
|
|
889
|
+
maxProvisioningBucketKey: bucket.key
|
|
874
890
|
};
|
|
875
891
|
}
|
|
876
892
|
const at = this.now();
|
|
877
893
|
const retentionCutoff = at - this.retentionMs;
|
|
878
894
|
const prior = (this.events.get(codeName) ?? []).filter((e) => e.at >= retentionCutoff);
|
|
879
|
-
prior.push(
|
|
895
|
+
prior.push(
|
|
896
|
+
isProvisioningReloadReason(reason) && integrationKey ? { reason, at, integrationKey } : { reason, at }
|
|
897
|
+
);
|
|
880
898
|
this.events.set(codeName, prior);
|
|
881
899
|
const crashCount = prior.filter(
|
|
882
900
|
(e) => e.at >= at - this.windowMs && restartReasonClass(e.reason) === "crash"
|
|
@@ -893,6 +911,7 @@ var RestartBreaker = class {
|
|
|
893
911
|
provisioning: provEvents.length,
|
|
894
912
|
"credential-rotation": credRotCount
|
|
895
913
|
};
|
|
914
|
+
const provBucket = maxProvisioningBucket(provEvents);
|
|
896
915
|
let trippedClass;
|
|
897
916
|
let tripEvents;
|
|
898
917
|
let tripWindowMs = this.windowMs;
|
|
@@ -902,22 +921,36 @@ var RestartBreaker = class {
|
|
|
902
921
|
(e) => e.at >= at - this.windowMs && restartReasonClass(e.reason) === "crash"
|
|
903
922
|
);
|
|
904
923
|
tripWindowMs = this.windowMs;
|
|
905
|
-
} else if (
|
|
924
|
+
} else if (provBucket.count > this.provisioningMax) {
|
|
906
925
|
trippedClass = "provisioning";
|
|
907
|
-
tripEvents = provEvents;
|
|
926
|
+
tripEvents = provEvents.filter((e) => (e.integrationKey ?? "") === provBucket.key);
|
|
908
927
|
tripWindowMs = this.provisioningWindowMs;
|
|
909
928
|
}
|
|
910
929
|
if (trippedClass && tripEvents) {
|
|
911
930
|
const trip = {
|
|
912
931
|
trippedAt: at,
|
|
913
932
|
eventsAtTrip: [...tripEvents],
|
|
914
|
-
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass)
|
|
933
|
+
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key)
|
|
915
934
|
};
|
|
916
935
|
this.trips.set(codeName, trip);
|
|
917
936
|
this.events.delete(codeName);
|
|
918
|
-
return {
|
|
937
|
+
return {
|
|
938
|
+
tripped: true,
|
|
939
|
+
trip,
|
|
940
|
+
windowCount,
|
|
941
|
+
classCounts,
|
|
942
|
+
trippedClass,
|
|
943
|
+
maxProvisioningBucket: provBucket.count,
|
|
944
|
+
maxProvisioningBucketKey: provBucket.key
|
|
945
|
+
};
|
|
919
946
|
}
|
|
920
|
-
return {
|
|
947
|
+
return {
|
|
948
|
+
tripped: false,
|
|
949
|
+
windowCount,
|
|
950
|
+
classCounts,
|
|
951
|
+
maxProvisioningBucket: provBucket.count,
|
|
952
|
+
maxProvisioningBucketKey: provBucket.key
|
|
953
|
+
};
|
|
921
954
|
}
|
|
922
955
|
/** Operator-initiated reset: drops the trip + the events log for this agent. */
|
|
923
956
|
clear(codeName) {
|
|
@@ -948,14 +981,15 @@ var RestartBreaker = class {
|
|
|
948
981
|
return (this.events.get(codeName) ?? []).filter((e) => e.at >= cutoff).length;
|
|
949
982
|
}
|
|
950
983
|
};
|
|
951
|
-
function formatStatusMessage(events, windowMs, klass = "crash") {
|
|
984
|
+
function formatStatusMessage(events, windowMs, klass = "crash", integrationKey = "") {
|
|
952
985
|
const last = events[events.length - 1];
|
|
953
986
|
const windowLabel = windowMs < 6e4 ? `${Math.round(windowMs / 1e3)}s` : `${(windowMs / 6e4).toFixed(1).replace(/\.0$/, "")}min`;
|
|
954
987
|
const reasonCounts = /* @__PURE__ */ new Map();
|
|
955
988
|
for (const e of events) reasonCounts.set(e.reason, (reasonCounts.get(e.reason) ?? 0) + 1);
|
|
956
989
|
const breakdown = Array.from(reasonCounts.entries()).map(([r, n]) => `${r}=${n}`).join(", ");
|
|
957
990
|
const classLabel = klass === "provisioning" ? "provisioning-reload " : "";
|
|
958
|
-
|
|
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()}`;
|
|
959
993
|
}
|
|
960
994
|
|
|
961
995
|
// src/lib/mcp-flap-dampener.ts
|
|
@@ -3769,6 +3803,17 @@ var agentState = {
|
|
|
3769
3803
|
knownModels: /* @__PURE__ */ new Map(),
|
|
3770
3804
|
knownTasksHashes: /* @__PURE__ */ new Map(),
|
|
3771
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(),
|
|
3772
3817
|
knownManagedMcpHashes: /* @__PURE__ */ new Map(),
|
|
3773
3818
|
knownManagedMcpStructure: /* @__PURE__ */ new Map(),
|
|
3774
3819
|
/**
|
|
@@ -3804,6 +3849,16 @@ var agentState = {
|
|
|
3804
3849
|
// ---------------------------------------------------------------------------
|
|
3805
3850
|
agentDisplayNames: /* @__PURE__ */ new Map(),
|
|
3806
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(),
|
|
3807
3862
|
/**
|
|
3808
3863
|
* Set of code_names with a live persistent session managed by this worker.
|
|
3809
3864
|
* Borderline ownership: written from pollCycle and the persistent-session
|
|
@@ -3841,6 +3896,7 @@ function clearAgentState(agentId, codeName) {
|
|
|
3841
3896
|
agentState.knownModels.delete(agentId);
|
|
3842
3897
|
agentState.knownTasksHashes.delete(agentId);
|
|
3843
3898
|
agentState.knownIntegrationHashes.delete(agentId);
|
|
3899
|
+
agentState.knownIntegrationMembership.delete(agentId);
|
|
3844
3900
|
agentState.knownManagedMcpHashes.delete(agentId);
|
|
3845
3901
|
agentState.knownManagedMcpStructure.delete(agentId);
|
|
3846
3902
|
agentState.knownSenderPolicyHashes.delete(agentId);
|
|
@@ -3849,6 +3905,7 @@ function clearAgentState(agentId, codeName) {
|
|
|
3849
3905
|
agentState.knownGlobalSkillIds.delete(agentId);
|
|
3850
3906
|
agentState.agentDisplayNames.delete(codeName);
|
|
3851
3907
|
agentState.codeNameToAgentId.delete(codeName);
|
|
3908
|
+
agentState.provisioningAttribution.delete(codeName);
|
|
3852
3909
|
let channelCacheMutated = false;
|
|
3853
3910
|
for (const key of agentState.knownChannelConfigHashes.keys()) {
|
|
3854
3911
|
if (key.startsWith(`${agentId}:`)) {
|
|
@@ -8472,6 +8529,10 @@ var pendingRestartVerifications = /* @__PURE__ */ new Map();
|
|
|
8472
8529
|
var restartBreaker = new RestartBreaker();
|
|
8473
8530
|
var reportedTrips = /* @__PURE__ */ new Map();
|
|
8474
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
|
+
);
|
|
8475
8536
|
var mcpFlapDampener = new McpFlapDampener();
|
|
8476
8537
|
var FLAP_BREAKER_COOLDOWN_MS = readEnvNumber2(
|
|
8477
8538
|
"AGT_MCP_FLAP_BREAKER_COOLDOWN_MS",
|
|
@@ -8510,11 +8571,19 @@ function recordRestartForBreaker(codeName, reason) {
|
|
|
8510
8571
|
);
|
|
8511
8572
|
return;
|
|
8512
8573
|
}
|
|
8513
|
-
|
|
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);
|
|
8514
8582
|
if (!result.tripped || !result.trip) {
|
|
8515
|
-
if (isProvisioningReloadReason(reason) && result.
|
|
8583
|
+
if (isProvisioningReloadReason(reason) && result.maxProvisioningBucket >= RESTART_BREAKER_PROVISIONING_MAX) {
|
|
8584
|
+
const culprit = result.maxProvisioningBucketKey ? ` [${result.maxProvisioningBucketKey}]` : "";
|
|
8516
8585
|
log(
|
|
8517
|
-
`[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)`
|
|
8518
8587
|
);
|
|
8519
8588
|
}
|
|
8520
8589
|
return;
|
|
@@ -9342,7 +9411,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9342
9411
|
var lastVersionCheckAt = 0;
|
|
9343
9412
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9344
9413
|
var lastResponsivenessProbeAt = 0;
|
|
9345
|
-
var agtCliVersion = true ? "0.28.
|
|
9414
|
+
var agtCliVersion = true ? "0.28.353" : "dev";
|
|
9346
9415
|
function resolveBrewPath(execFileSync2) {
|
|
9347
9416
|
try {
|
|
9348
9417
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -12231,6 +12300,25 @@ async function processAgent(agent, agentStates) {
|
|
|
12231
12300
|
}
|
|
12232
12301
|
}
|
|
12233
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);
|
|
12234
12322
|
if (integrations.length > 0) {
|
|
12235
12323
|
const intHash = computeIntegrationsHash(integrations);
|
|
12236
12324
|
const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
|