@integrity-labs/agt-cli 0.28.215 → 0.28.216
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
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
success,
|
|
39
39
|
table,
|
|
40
40
|
warn
|
|
41
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-6DMZIXM6.js";
|
|
42
42
|
import {
|
|
43
43
|
CHANNEL_REGISTRY,
|
|
44
44
|
DEFAULT_FRAMEWORK,
|
|
@@ -4826,7 +4826,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4826
4826
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4827
4827
|
import chalk18 from "chalk";
|
|
4828
4828
|
import ora16 from "ora";
|
|
4829
|
-
var cliVersion = true ? "0.28.
|
|
4829
|
+
var cliVersion = true ? "0.28.216" : "dev";
|
|
4830
4830
|
async function fetchLatestVersion() {
|
|
4831
4831
|
const host2 = getHost();
|
|
4832
4832
|
if (!host2) return null;
|
|
@@ -5840,7 +5840,7 @@ function handleError(err) {
|
|
|
5840
5840
|
}
|
|
5841
5841
|
|
|
5842
5842
|
// src/bin/agt.ts
|
|
5843
|
-
var cliVersion2 = true ? "0.28.
|
|
5843
|
+
var cliVersion2 = true ? "0.28.216" : "dev";
|
|
5844
5844
|
var program = new Command();
|
|
5845
5845
|
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");
|
|
5846
5846
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -5529,7 +5529,7 @@ function requireHost() {
|
|
|
5529
5529
|
}
|
|
5530
5530
|
|
|
5531
5531
|
// src/lib/api-client.ts
|
|
5532
|
-
var agtCliVersion = true ? "0.28.
|
|
5532
|
+
var agtCliVersion = true ? "0.28.216" : "dev";
|
|
5533
5533
|
var lastConfigHash = null;
|
|
5534
5534
|
function setConfigHash(hash) {
|
|
5535
5535
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -7581,4 +7581,4 @@ export {
|
|
|
7581
7581
|
managerInstallSystemUnitCommand,
|
|
7582
7582
|
managerUninstallSystemUnitCommand
|
|
7583
7583
|
};
|
|
7584
|
-
//# sourceMappingURL=chunk-
|
|
7584
|
+
//# sourceMappingURL=chunk-6DMZIXM6.js.map
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
requireHost,
|
|
37
37
|
safeWriteJsonAtomic,
|
|
38
38
|
setConfigHash
|
|
39
|
-
} from "../chunk-
|
|
39
|
+
} from "../chunk-6DMZIXM6.js";
|
|
40
40
|
import {
|
|
41
41
|
getProjectDir as getProjectDir2,
|
|
42
42
|
getReadyTasks,
|
|
@@ -685,6 +685,11 @@ var McpFlapDampener = class {
|
|
|
685
685
|
now;
|
|
686
686
|
history = /* @__PURE__ */ new Map();
|
|
687
687
|
flapping = /* @__PURE__ */ new Set();
|
|
688
|
+
// ENG-7239: timestamp of the most recent poll on which each (agent, channel)
|
|
689
|
+
// was flapping. Drives `flappedWithin` so the caller can exempt a managed-MCP
|
|
690
|
+
// churn restart from the ENG-5441 breaker for a short cool-off after a flap;
|
|
691
|
+
// see that method for the Kylie/dig (2026-06-29) rationale.
|
|
692
|
+
lastFlapAt = /* @__PURE__ */ new Map();
|
|
688
693
|
constructor(opts = {}) {
|
|
689
694
|
this.windowMs = opts.windowMs ?? readEnvNumber2("AGT_MCP_FLAP_WINDOW_MS", DEFAULT_WINDOW_MS2);
|
|
690
695
|
this.minTransitions = opts.minTransitions ?? readEnvNumber2("AGT_MCP_FLAP_MIN_TRANSITIONS", DEFAULT_MIN_TRANSITIONS);
|
|
@@ -742,9 +747,11 @@ var McpFlapDampener = class {
|
|
|
742
747
|
this.flapping.add(k);
|
|
743
748
|
onset = true;
|
|
744
749
|
}
|
|
750
|
+
const nowFlapping = this.flapping.has(k);
|
|
751
|
+
if (nowFlapping) this.lastFlapAt.set(k, at);
|
|
745
752
|
const reported = tier === "slow" ? slow : fast;
|
|
746
753
|
return {
|
|
747
|
-
flapping:
|
|
754
|
+
flapping: nowFlapping,
|
|
748
755
|
distinctStates: reported.distinctStates,
|
|
749
756
|
transitions: reported.transitions,
|
|
750
757
|
windowCount: prior.length,
|
|
@@ -776,6 +783,27 @@ var McpFlapDampener = class {
|
|
|
776
783
|
isFlapping(codeName, channel) {
|
|
777
784
|
return this.flapping.has(this.key(codeName, channel));
|
|
778
785
|
}
|
|
786
|
+
/**
|
|
787
|
+
* ENG-7239: true if (codeName, channel) was flapping within the last
|
|
788
|
+
* `withinMs`. Lets the caller exempt a managed-MCP-churn session restart from
|
|
789
|
+
* the ENG-5441 circuit breaker during (and for a short cool-off after) a
|
|
790
|
+
* flap episode.
|
|
791
|
+
*
|
|
792
|
+
* Why a cool-off and not just `isFlapping`: the dampener recovers eagerly, on
|
|
793
|
+
* the first stable poll (ENG-6512), so during an ACTIVE oscillation a single
|
|
794
|
+
* transient poll where the desired set momentarily repeats clears `flapping`
|
|
795
|
+
* for that instant. If the very next poll flips again, that flip's restart
|
|
796
|
+
* would (pre-fix) be treated as a genuine change and counted toward the
|
|
797
|
+
* breaker; three such flips in 10 min auto-paused Kylie (org dig) on
|
|
798
|
+
* 2026-06-29 and left her unreachable on every channel. Keying the breaker
|
|
799
|
+
* exemption off "flapped within the cool-off" instead of the exact-instant
|
|
800
|
+
* `isFlapping` closes that race. Mirrors ENG-5547's single-dead-MCP reaper
|
|
801
|
+
* exemption ("restart, but don't count toward the agent-wide breaker").
|
|
802
|
+
*/
|
|
803
|
+
flappedWithin(codeName, channel, withinMs) {
|
|
804
|
+
const at = this.lastFlapAt.get(this.key(codeName, channel));
|
|
805
|
+
return at !== void 0 && this.now() - at <= withinMs;
|
|
806
|
+
}
|
|
779
807
|
/** Drop all state for an agent (called on deprovision / agent removal). */
|
|
780
808
|
forget(codeName) {
|
|
781
809
|
const prefix = `${codeName}\0`;
|
|
@@ -785,10 +813,29 @@ var McpFlapDampener = class {
|
|
|
785
813
|
for (const k of [...this.flapping]) {
|
|
786
814
|
if (k.startsWith(prefix)) this.flapping.delete(k);
|
|
787
815
|
}
|
|
816
|
+
for (const k of [...this.lastFlapAt.keys()]) {
|
|
817
|
+
if (k.startsWith(prefix)) this.lastFlapAt.delete(k);
|
|
818
|
+
}
|
|
788
819
|
}
|
|
789
820
|
};
|
|
790
821
|
var FLAP_CHANNEL_INTEGRATIONS = "integrations";
|
|
791
822
|
var FLAP_CHANNEL_MANAGED_MCP = "managed-mcp";
|
|
823
|
+
var DEFAULT_FLAP_BREAKER_COOLDOWN_MS = 6e5;
|
|
824
|
+
var MANAGED_MCP_SERVER_PREFIXES = [
|
|
825
|
+
"composio_",
|
|
826
|
+
"one_",
|
|
827
|
+
"pipedream_",
|
|
828
|
+
"nango_",
|
|
829
|
+
"paragon_",
|
|
830
|
+
"composio-",
|
|
831
|
+
"one-",
|
|
832
|
+
"pipedream-",
|
|
833
|
+
"nango-",
|
|
834
|
+
"paragon-"
|
|
835
|
+
];
|
|
836
|
+
function isManagedMcpServerKey(key) {
|
|
837
|
+
return MANAGED_MCP_SERVER_PREFIXES.some((p) => key.startsWith(p));
|
|
838
|
+
}
|
|
792
839
|
|
|
793
840
|
// src/lib/auto-resume.ts
|
|
794
841
|
var DEFAULT_QUIET_MS = 18e5;
|
|
@@ -5469,6 +5516,10 @@ var pendingRestartVerifications = /* @__PURE__ */ new Map();
|
|
|
5469
5516
|
var restartBreaker = new RestartBreaker();
|
|
5470
5517
|
var reportedTrips = /* @__PURE__ */ new Map();
|
|
5471
5518
|
var mcpFlapDampener = new McpFlapDampener();
|
|
5519
|
+
var FLAP_BREAKER_COOLDOWN_MS = readEnvNumber2(
|
|
5520
|
+
"AGT_MCP_FLAP_BREAKER_COOLDOWN_MS",
|
|
5521
|
+
DEFAULT_FLAP_BREAKER_COOLDOWN_MS
|
|
5522
|
+
);
|
|
5472
5523
|
function recordConfigChurnEvent(agentId, codeName, channel, signature) {
|
|
5473
5524
|
api.post("/host/mcp-config-churn", {
|
|
5474
5525
|
agent_id: agentId,
|
|
@@ -5496,6 +5547,12 @@ async function reportReaperEvent(agentId, reaper, action, reason) {
|
|
|
5496
5547
|
}
|
|
5497
5548
|
}
|
|
5498
5549
|
function recordRestartForBreaker(codeName, reason) {
|
|
5550
|
+
if (reason === "managed-mcp-churn" && mcpFlapDampener.flappedWithin(codeName, FLAP_CHANNEL_MANAGED_MCP, FLAP_BREAKER_COOLDOWN_MS)) {
|
|
5551
|
+
log(
|
|
5552
|
+
`[mcp-flap-dampener] '${codeName}' managed-MCP churn restart NOT counted toward circuit breaker, managed-MCP set flapped within ${Math.round(FLAP_BREAKER_COOLDOWN_MS / 1e3)}s (ENG-7239)`
|
|
5553
|
+
);
|
|
5554
|
+
return;
|
|
5555
|
+
}
|
|
5499
5556
|
const result = restartBreaker.record(codeName, reason);
|
|
5500
5557
|
if (!result.tripped || !result.trip) return;
|
|
5501
5558
|
const trip = result.trip;
|
|
@@ -5752,7 +5809,7 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
|
|
|
5752
5809
|
runningMcpHashes.delete(codeName);
|
|
5753
5810
|
recordRestartForBreaker(codeName, breakerReason);
|
|
5754
5811
|
log(`[hot-reload] Session stopped for '${codeName}' \u2014 will respawn with ${reason}`);
|
|
5755
|
-
if (breakerReason === "hot-reload-mcp" || breakerReason === "bind-remediation" || breakerReason === "channel-set-change") {
|
|
5812
|
+
if (breakerReason === "hot-reload-mcp" || breakerReason === "managed-mcp-churn" || breakerReason === "bind-remediation" || breakerReason === "channel-set-change") {
|
|
5756
5813
|
const prior = pendingRestartVerifications.get(codeName);
|
|
5757
5814
|
pendingRestartVerifications.set(codeName, {
|
|
5758
5815
|
firedAt: Date.now(),
|
|
@@ -6064,7 +6121,8 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
|
|
|
6064
6121
|
);
|
|
6065
6122
|
}
|
|
6066
6123
|
if (decision.restart && !quarantineOnlyDrift && !flapSuppressed) {
|
|
6067
|
-
|
|
6124
|
+
const driftBreakerReason = decision.addedOrRemoved.length > 0 && decision.addedOrRemoved.every(isManagedMcpServerKey) ? "managed-mcp-churn" : "hot-reload-mcp";
|
|
6125
|
+
scheduleSessionRestart(codeName, 0, ".mcp.json content change (ENG-4897)", driftBreakerReason);
|
|
6068
6126
|
runningMcpHashes.delete(codeName);
|
|
6069
6127
|
runningMcpServerKeys.delete(codeName);
|
|
6070
6128
|
} else if (flapSuppressed) {
|
|
@@ -6163,7 +6221,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
6163
6221
|
var lastVersionCheckAt = 0;
|
|
6164
6222
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
6165
6223
|
var lastResponsivenessProbeAt = 0;
|
|
6166
|
-
var agtCliVersion = true ? "0.28.
|
|
6224
|
+
var agtCliVersion = true ? "0.28.216" : "dev";
|
|
6167
6225
|
function resolveBrewPath(execFileSync2) {
|
|
6168
6226
|
try {
|
|
6169
6227
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -8750,20 +8808,8 @@ async function processAgent(agent, agentStates) {
|
|
|
8750
8808
|
const { readFileSync: readFileSync15 } = await import("fs");
|
|
8751
8809
|
const mcpConfig = JSON.parse(readFileSync15(mcpPath, "utf-8"));
|
|
8752
8810
|
if (mcpConfig.mcpServers) {
|
|
8753
|
-
const managedPrefixes = [
|
|
8754
|
-
"composio_",
|
|
8755
|
-
"one_",
|
|
8756
|
-
"pipedream_",
|
|
8757
|
-
"nango_",
|
|
8758
|
-
"paragon_",
|
|
8759
|
-
"composio-",
|
|
8760
|
-
"one-",
|
|
8761
|
-
"pipedream-",
|
|
8762
|
-
"nango-",
|
|
8763
|
-
"paragon-"
|
|
8764
|
-
];
|
|
8765
8811
|
for (const key of Object.keys(mcpConfig.mcpServers)) {
|
|
8766
|
-
if (
|
|
8812
|
+
if (isManagedMcpServerKey(key) && !expectedServerIds.has(key)) {
|
|
8767
8813
|
frameworkAdapter.removeMcpServer(agent.code_name, key);
|
|
8768
8814
|
log(`[managed-toolkit] Removed stale MCP server '${key}' for '${agent.code_name}'`);
|
|
8769
8815
|
}
|