@integrity-labs/agt-cli 0.28.635 → 0.28.637

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,10 +40,10 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-J6KQDGWM.js";
43
+ } from "../chunk-3JBA6RYG.js";
44
44
  import {
45
45
  readDirectChatSessionState
46
- } from "../chunk-GNTCOXZG.js";
46
+ } from "../chunk-W4GVD3KK.js";
47
47
  import {
48
48
  AnchorSessionClient,
49
49
  CHANNEL_REGISTRY,
@@ -73,7 +73,7 @@ import {
73
73
  requiredMcpWildcard,
74
74
  resolveChannels,
75
75
  serializeManifestForSlackCli
76
- } from "../chunk-FKG7DIE2.js";
76
+ } from "../chunk-JT2JQUK3.js";
77
77
  import "../chunk-XWVM4KPK.js";
78
78
 
79
79
  // src/bin/agt.ts
@@ -4909,7 +4909,7 @@ import { execFileSync, execSync } from "child_process";
4909
4909
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4910
4910
  import chalk18 from "chalk";
4911
4911
  import ora16 from "ora";
4912
- var cliVersion = true ? "0.28.635" : "dev";
4912
+ var cliVersion = true ? "0.28.637" : "dev";
4913
4913
  async function fetchLatestVersion() {
4914
4914
  const host2 = getHost();
4915
4915
  if (!host2) return null;
@@ -6089,7 +6089,7 @@ function handleError(err) {
6089
6089
  }
6090
6090
 
6091
6091
  // src/bin/agt.ts
6092
- var cliVersion2 = true ? "0.28.635" : "dev";
6092
+ var cliVersion2 = true ? "0.28.637" : "dev";
6093
6093
  var program = new Command();
6094
6094
  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");
6095
6095
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -7,7 +7,7 @@ import {
7
7
  expandTemplateVars,
8
8
  isolationMode,
9
9
  parseEnvIntegrations
10
- } from "./chunk-GNTCOXZG.js";
10
+ } from "./chunk-W4GVD3KK.js";
11
11
  import {
12
12
  BIND_FAILURE_QUARANTINE_THRESHOLD,
13
13
  INTEGRATIONS_SECTION_END,
@@ -21,6 +21,8 @@ import {
21
21
  RESTART_BREAKER_OPERATOR_MAX,
22
22
  RESTART_BREAKER_PROVISIONING_MAX,
23
23
  RESTART_BREAKER_PROVISIONING_WINDOW_MS,
24
+ RESTART_BREAKER_SCHEDULED_MAX,
25
+ RESTART_BREAKER_SCHEDULED_WINDOW_MS,
24
26
  SCRATCH_RETENTION_DAYS,
25
27
  SLACK_SOCKET_STATE_FILENAME,
26
28
  bestConnectivityEvidence,
@@ -33,6 +35,7 @@ import {
33
35
  handshakeToolsListOutcome,
34
36
  isControlPlaneOnlyConfigKey,
35
37
  isDefaultRemoteMcpConnection,
38
+ isSessionToolBindCandidate,
36
39
  isSlackInboundTransportDown,
37
40
  listFlagDefinitions,
38
41
  mcpWildcardsForServers,
@@ -51,7 +54,7 @@ import {
51
54
  resolveConnectivityProbe,
52
55
  worseConnectivityOutcome,
53
56
  wrapScheduledTaskPrompt
54
- } from "./chunk-FKG7DIE2.js";
57
+ } from "./chunk-JT2JQUK3.js";
55
58
  import {
56
59
  parsePsRows
57
60
  } from "./chunk-XWVM4KPK.js";
@@ -6069,7 +6072,7 @@ function exchangeFailureKind(err) {
6069
6072
  }
6070
6073
 
6071
6074
  // src/lib/api-client.ts
6072
- var agtCliVersion = true ? "0.28.635" : "dev";
6075
+ var agtCliVersion = true ? "0.28.637" : "dev";
6073
6076
  var lastConfigHash = null;
6074
6077
  function setConfigHash(hash) {
6075
6078
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -7465,7 +7468,12 @@ var KNOWN_REASON_CLASS_MAP = {
7465
7468
  // forced by the Record type, which is exactly why that shape was chosen over
7466
7469
  // a Set literal (ENG-7577, CodeRabbit on #3861) - a new union member cannot
7467
7470
  // be silently omitted from the rehydration allowlist.
7468
- "self-healing": true
7471
+ "self-healing": true,
7472
+ // ENG-9138: the platform-scheduled class. Same Record-not-Set reasoning: the
7473
+ // compiler forces every new class into this allowlist, so a `trippedClass`
7474
+ // rehydrated from manager-state.json can never name a class this build does
7475
+ // not know about.
7476
+ scheduled: true
7469
7477
  };
7470
7478
  var KNOWN_REASON_CLASSES = new Set(
7471
7479
  Object.keys(KNOWN_REASON_CLASS_MAP)
@@ -7506,6 +7514,12 @@ var SELF_HEALING_REASONS = /* @__PURE__ */ new Set([
7506
7514
  function isSelfHealingReason(reason) {
7507
7515
  return SELF_HEALING_REASONS.has(reason);
7508
7516
  }
7517
+ var SCHEDULED_REASONS = /* @__PURE__ */ new Set([
7518
+ "day-rollover"
7519
+ ]);
7520
+ function isScheduledRestartReason(reason) {
7521
+ return SCHEDULED_REASONS.has(reason);
7522
+ }
7509
7523
  var OPERATOR_CONFIG_REASONS = /* @__PURE__ */ new Set([
7510
7524
  "operator-integration-change"
7511
7525
  ]);
@@ -7519,6 +7533,7 @@ function restartReasonClass(reason) {
7519
7533
  if (isCredentialRotationReason(reason)) return "credential-rotation";
7520
7534
  if (isSelfHealingReason(reason)) return "self-healing";
7521
7535
  if (isOperatorConfigReason(reason)) return "operator-config";
7536
+ if (isScheduledRestartReason(reason)) return "scheduled";
7522
7537
  return isProvisioningReloadReason(reason) ? "provisioning" : "crash";
7523
7538
  }
7524
7539
  function countByClass(events) {
@@ -7527,12 +7542,14 @@ function countByClass(events) {
7527
7542
  let credentialRotation = 0;
7528
7543
  let selfHealing = 0;
7529
7544
  let operatorConfig = 0;
7545
+ let scheduled = 0;
7530
7546
  for (const e of events) {
7531
7547
  const klass = restartReasonClass(e.reason);
7532
7548
  if (klass === "provisioning") provisioning += 1;
7533
7549
  else if (klass === "credential-rotation") credentialRotation += 1;
7534
7550
  else if (klass === "self-healing") selfHealing += 1;
7535
7551
  else if (klass === "operator-config") operatorConfig += 1;
7552
+ else if (klass === "scheduled") scheduled += 1;
7536
7553
  else crash += 1;
7537
7554
  }
7538
7555
  return {
@@ -7540,7 +7557,8 @@ function countByClass(events) {
7540
7557
  provisioning,
7541
7558
  "credential-rotation": credentialRotation,
7542
7559
  "self-healing": selfHealing,
7543
- "operator-config": operatorConfig
7560
+ "operator-config": operatorConfig,
7561
+ scheduled
7544
7562
  };
7545
7563
  }
7546
7564
  function maxProvisioningBucket(events) {
@@ -7570,6 +7588,8 @@ var DEFAULT_WINDOW_MS = 6e5;
7570
7588
  var DEFAULT_PROVISIONING_MAX = RESTART_BREAKER_PROVISIONING_MAX;
7571
7589
  var DEFAULT_PROVISIONING_WINDOW_MS = RESTART_BREAKER_PROVISIONING_WINDOW_MS;
7572
7590
  var DEFAULT_OPERATOR_MAX = RESTART_BREAKER_OPERATOR_MAX;
7591
+ var DEFAULT_SCHEDULED_MAX = RESTART_BREAKER_SCHEDULED_MAX;
7592
+ var DEFAULT_SCHEDULED_WINDOW_MS = RESTART_BREAKER_SCHEDULED_WINDOW_MS;
7573
7593
  function readEnvNumber(name, fallback) {
7574
7594
  const raw = process.env[name];
7575
7595
  if (!raw) return fallback;
@@ -7597,7 +7617,15 @@ var RestartBreaker = class {
7597
7617
  * env var without the other cannot invert the two tallies.
7598
7618
  */
7599
7619
  operatorMax;
7600
- /** Longest window either tally needs — how long the events log must retain. */
7620
+ /**
7621
+ * ENG-9138: the scheduled class's LOOP bar. Readonly and deliberately NOT
7622
+ * floored against any other tally: it gates a REPORT, not a pause, so it
7623
+ * cannot invert anything the way operatorMax/provisioningMax can.
7624
+ */
7625
+ scheduledMax;
7626
+ /** ENG-9138: sliding window for the scheduled tally. */
7627
+ scheduledWindowMs;
7628
+ /** Longest window any tally needs — how long the events log must retain. */
7601
7629
  retentionMs;
7602
7630
  now;
7603
7631
  /** ENG-7891 slice 5b: code_name → durable runtime key (agent_id when id-keyed). Identity on the legacy fleet. */
@@ -7623,6 +7651,8 @@ var RestartBreaker = class {
7623
7651
  this.provisioningMax = opts.provisioningMax ?? readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_MAX", DEFAULT_PROVISIONING_MAX);
7624
7652
  this.provisioningWindowMs = opts.provisioningWindowMs ?? readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_WINDOW_MS", DEFAULT_PROVISIONING_WINDOW_MS);
7625
7653
  this.operatorMax = opts.operatorMax ?? readEnvNumber("AGT_RESTART_BREAKER_OPERATOR_MAX", DEFAULT_OPERATOR_MAX);
7654
+ this.scheduledMax = opts.scheduledMax ?? readEnvNumber("AGT_RESTART_BREAKER_SCHEDULED_MAX", DEFAULT_SCHEDULED_MAX);
7655
+ this.scheduledWindowMs = opts.scheduledWindowMs ?? readEnvNumber("AGT_RESTART_BREAKER_SCHEDULED_WINDOW_MS", DEFAULT_SCHEDULED_WINDOW_MS);
7626
7656
  this.now = opts.now ?? Date.now;
7627
7657
  this.runtimeKey = opts.runtimeKey ?? ((codeName) => codeName);
7628
7658
  this.agentCreatedAt = opts.agentCreatedAt ?? (() => void 0);
@@ -7664,7 +7694,7 @@ var RestartBreaker = class {
7664
7694
  if (this.newAgentGraceCeiling < minimumGraceCeiling) {
7665
7695
  this.newAgentGraceCeiling = minimumGraceCeiling;
7666
7696
  }
7667
- this.retentionMs = Math.max(this.windowMs, this.provisioningWindowMs);
7697
+ this.retentionMs = Math.max(this.windowMs, this.provisioningWindowMs, this.scheduledWindowMs);
7668
7698
  }
7669
7699
  /**
7670
7700
  * ENG-8215: the clamp record, if the configured provisioning max had to be
@@ -7753,14 +7783,23 @@ var RestartBreaker = class {
7753
7783
  const operatorEvents = prior.filter(
7754
7784
  (e) => e.at >= at - this.provisioningWindowMs && isOperatorConfigReason(e.reason)
7755
7785
  );
7786
+ const scheduledEvents = prior.filter(
7787
+ (e) => e.at >= at - this.scheduledWindowMs && isScheduledRestartReason(e.reason)
7788
+ );
7756
7789
  const windowCount = prior.filter((e) => e.at >= at - this.windowMs).length;
7757
7790
  const classCounts = {
7758
7791
  crash: crashCount,
7759
7792
  provisioning: provEvents.length,
7760
7793
  "credential-rotation": credRotCount,
7761
7794
  "self-healing": selfHealCount,
7762
- "operator-config": operatorEvents.length
7795
+ "operator-config": operatorEvents.length,
7796
+ scheduled: scheduledEvents.length
7763
7797
  };
7798
+ const scheduledLoop = scheduledEvents.length > this.scheduledMax ? {
7799
+ count: scheduledEvents.length,
7800
+ windowMs: this.scheduledWindowMs,
7801
+ reason: scheduledEvents[scheduledEvents.length - 1].reason
7802
+ } : void 0;
7764
7803
  const provBucket = maxProvisioningBucket(provEvents);
7765
7804
  const operatorBucket = maxBucketWhere(operatorEvents, isOperatorConfigReason);
7766
7805
  const createdAt = this.newAgentGraceMs > 0 ? this.agentCreatedAt(codeName) : void 0;
@@ -7820,7 +7859,9 @@ var RestartBreaker = class {
7820
7859
  trippedClass,
7821
7860
  maxProvisioningBucket: provBucket.count,
7822
7861
  maxProvisioningBucketKey: provBucket.key,
7823
- ...graceCeilingExceeded ? { newAgentGraceCeilingExceeded: true } : {}
7862
+ ...graceCeilingExceeded ? { newAgentGraceCeilingExceeded: true } : {},
7863
+ // ENG-9138: a co-occurring rollover loop still reports on a real trip.
7864
+ ...scheduledLoop ? { scheduledLoop } : {}
7824
7865
  };
7825
7866
  }
7826
7867
  const suppressedOperator = operatorBucket.count > this.operatorMax;
@@ -7832,6 +7873,7 @@ var RestartBreaker = class {
7832
7873
  classCounts,
7833
7874
  maxProvisioningBucket: provBucket.count,
7834
7875
  maxProvisioningBucketKey: provBucket.key,
7876
+ ...scheduledLoop ? { scheduledLoop } : {},
7835
7877
  ...newAgentGraceActive ? {
7836
7878
  newAgentGraceSuppressedTrip: wouldHaveTripped,
7837
7879
  ...newAgentGraceExpiresAt !== void 0 ? { newAgentGraceExpiresAt } : {},
@@ -8300,6 +8342,17 @@ function resolveIntegrationServerKeys(definitionId, declaredKeys, hint) {
8300
8342
  for (const c of candidates) if (declared.has(c)) out.add(c);
8301
8343
  return [...out];
8302
8344
  }
8345
+ function hasDeliverySignal(integ) {
8346
+ return DELIVERY_FIELDS.some((k) => Object.prototype.hasOwnProperty.call(integ, k));
8347
+ }
8348
+ var DELIVERY_FIELDS = [
8349
+ "source_type",
8350
+ "provider",
8351
+ "mcp_command",
8352
+ "mcp_url",
8353
+ "cli_binary",
8354
+ "cli_package"
8355
+ ];
8303
8356
  function isDue(last, now, intervalMs) {
8304
8357
  if (!last) return true;
8305
8358
  const t = Date.parse(last);
@@ -8320,6 +8373,8 @@ async function runSessionToolBindProbes(integrations, options) {
8320
8373
  const reports = [];
8321
8374
  const rebindCandidates = [];
8322
8375
  let skipped = 0;
8376
+ let notApplicable = 0;
8377
+ const skippedDetail = [];
8323
8378
  let probed = 0;
8324
8379
  for (const integ of batch) {
8325
8380
  const keys = resolveIntegrationServerKeys(
@@ -8328,7 +8383,29 @@ async function runSessionToolBindProbes(integrations, options) {
8328
8383
  integ.mcp_server_key
8329
8384
  );
8330
8385
  if (keys.length === 0) {
8386
+ if (!hasDeliverySignal(integ)) {
8387
+ skipped += 1;
8388
+ skippedDetail.push({ definition_id: integ.definition_id, reason: "delivery-unknown" });
8389
+ continue;
8390
+ }
8391
+ if (!isSessionToolBindCandidate({
8392
+ sourceType: integ.source_type,
8393
+ provider: integ.provider,
8394
+ mcpCommand: integ.mcp_command,
8395
+ mcpUrl: integ.mcp_url,
8396
+ cliBinary: integ.cli_binary,
8397
+ cliPackage: integ.cli_package
8398
+ })) {
8399
+ notApplicable += 1;
8400
+ reports.push({
8401
+ integration_id: integ.id,
8402
+ scope: integ.scope,
8403
+ status: "not_applicable"
8404
+ });
8405
+ continue;
8406
+ }
8331
8407
  skipped += 1;
8408
+ skippedDetail.push({ definition_id: integ.definition_id, reason: "no-declared-server" });
8332
8409
  continue;
8333
8410
  }
8334
8411
  probed += 1;
@@ -8358,6 +8435,7 @@ async function runSessionToolBindProbes(integrations, options) {
8358
8435
  });
8359
8436
  if (status === "unknown") {
8360
8437
  skipped += 1;
8438
+ skippedDetail.push({ definition_id: integ.definition_id, reason: "inconclusive" });
8361
8439
  continue;
8362
8440
  }
8363
8441
  reports.push({ integration_id: integ.id, scope: integ.scope, status });
@@ -8384,7 +8462,7 @@ async function runSessionToolBindProbes(integrations, options) {
8384
8462
  }
8385
8463
  }
8386
8464
  }
8387
- return { reports, rebindCandidates, due: due.length, probed, skipped };
8465
+ return { reports, rebindCandidates, due: due.length, probed, skipped, skippedDetail, notApplicable };
8388
8466
  }
8389
8467
 
8390
8468
  // src/lib/connectivity-probe-context.ts
@@ -8651,35 +8729,58 @@ import { execFileSync as syncExecFile } from "child_process";
8651
8729
  import { readFileSync as readFileSync7 } from "fs";
8652
8730
  import { join as join6 } from "path";
8653
8731
  import { dirname as dirname4 } from "path";
8732
+ function deliveryFields(i) {
8733
+ const keys = ["source_type", "provider", "mcp_command", "mcp_url", "cli_binary", "cli_package"];
8734
+ const out = {};
8735
+ for (const k of keys) {
8736
+ if (Object.prototype.hasOwnProperty.call(i, k)) out[k] = i[k];
8737
+ }
8738
+ return out;
8739
+ }
8654
8740
  async function gatherSessionToolBindProbe(agent, integrations, projectDir, opts) {
8655
8741
  if (integrations.length === 0) return null;
8656
- let mcpJson = null;
8742
+ let mcpRaw = null;
8657
8743
  try {
8658
- mcpJson = JSON.parse(readFileSync7(join6(projectDir, ".mcp.json"), "utf-8"));
8744
+ mcpRaw = readFileSync7(join6(projectDir, ".mcp.json"), "utf-8");
8659
8745
  } catch {
8660
- return null;
8746
+ mcpRaw = null;
8661
8747
  }
8662
- if (!mcpJson?.mcpServers || Object.keys(mcpJson.mcpServers).length === 0) return null;
8748
+ let parsed = null;
8749
+ if (mcpRaw !== null) {
8750
+ try {
8751
+ parsed = JSON.parse(mcpRaw);
8752
+ } catch {
8753
+ return null;
8754
+ }
8755
+ }
8756
+ const declaredServers = parsed?.mcpServers && typeof parsed.mcpServers === "object" ? parsed.mcpServers : {};
8757
+ const mcpJson = {
8758
+ ...parsed ?? {},
8759
+ mcpServers: declaredServers
8760
+ };
8761
+ const declaredServerCount = Object.keys(declaredServers).length;
8663
8762
  const isolated = isolationMode(agent.code_name) === "docker";
8664
8763
  const hasDeclaredStdio = Object.values(mcpJson.mcpServers).some(
8665
8764
  (entry) => typeof entry?.command === "string"
8666
8765
  );
8667
8766
  let missingStdioKeys = /* @__PURE__ */ new Set();
8668
- try {
8669
- const psOutput = isolated ? syncExecFile("docker", ["exec", `agt-${agent.code_name}`, "ps", "-eo", "pid,ppid,args"], {
8670
- encoding: "utf-8",
8671
- timeout: 8e3
8672
- }) : syncExecFile("ps", ["-eo", "pid,ppid,args"], { encoding: "utf-8", timeout: 5e3 });
8673
- missingStdioKeys = new Set(
8674
- findMissingMcpServers({
8675
- rows: parsePsRows(psOutput),
8676
- codeName: agent.code_name,
8677
- mcpJson,
8678
- inContainer: isolated
8679
- })
8680
- );
8681
- } catch {
8682
- if (hasDeclaredStdio) return null;
8767
+ if (declaredServerCount > 0) {
8768
+ try {
8769
+ const psOutput = isolated ? syncExecFile("docker", ["exec", `agt-${agent.code_name}`, "ps", "-eo", "pid,ppid,args"], {
8770
+ encoding: "utf-8",
8771
+ timeout: 8e3
8772
+ }) : syncExecFile("ps", ["-eo", "pid,ppid,args"], { encoding: "utf-8", timeout: 5e3 });
8773
+ missingStdioKeys = new Set(
8774
+ findMissingMcpServers({
8775
+ rows: parsePsRows(psOutput),
8776
+ codeName: agent.code_name,
8777
+ mcpJson,
8778
+ inContainer: isolated
8779
+ })
8780
+ );
8781
+ } catch {
8782
+ if (hasDeclaredStdio) return null;
8783
+ }
8683
8784
  }
8684
8785
  const probeEnv = buildProbeEnv(projectDir, agent.agent_id);
8685
8786
  const probeDeps = buildConnectivityProbeDeps(projectDir, probeEnv);
@@ -8696,6 +8797,15 @@ async function gatherSessionToolBindProbe(agent, integrations, projectDir, opts)
8696
8797
  definition_id: i.definition_id,
8697
8798
  scope: i.scope,
8698
8799
  last_session_tool_bind_at: i.last_session_tool_bind_at ?? null,
8800
+ // ENG-9114: forwarded by PRESENCE, not by value. `hasDeliverySignal` in
8801
+ // the runner asks "did the API speak about delivery at all?", and spreading
8802
+ // these unconditionally would have made it impossible to answer: a key
8803
+ // written as `undefined` is still an own property, so an old API's omitted
8804
+ // columns would have looked identical to a current API's explicit nulls.
8805
+ // Both readings are needed and they mean opposite things - explicit null is
8806
+ // a real answer (this toolkit sets no mcp_command), absence is no answer at
8807
+ // all. Omitting the key here is what keeps them distinguishable. (CodeRabbit)
8808
+ ...deliveryFields(i),
8699
8809
  // Server-key hint for managed/remote-MCP kinds; the runner also tries the
8700
8810
  // raw + sanitised definition_id against the real `.mcp.json` keys.
8701
8811
  mcp_server_key: deriveMcpServerKey({
@@ -9630,4 +9740,4 @@ export {
9630
9740
  managerInstallSystemUnitCommand,
9631
9741
  managerUninstallSystemUnitCommand
9632
9742
  };
9633
- //# sourceMappingURL=chunk-J6KQDGWM.js.map
9743
+ //# sourceMappingURL=chunk-3JBA6RYG.js.map