@integrity-labs/agt-cli 0.28.883 → 0.28.885

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,12 +40,12 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-B3WKENVI.js";
43
+ } from "../chunk-MT3CF4UQ.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
47
47
  readDirectChatSessionState
48
- } from "../chunk-PZHDYVFU.js";
48
+ } from "../chunk-FP5M5OVX.js";
49
49
  import {
50
50
  AnchorSessionClient,
51
51
  CHANNEL_REGISTRY,
@@ -5467,7 +5467,7 @@ import { execFileSync, execSync } from "child_process";
5467
5467
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5468
5468
  import chalk18 from "chalk";
5469
5469
  import ora16 from "ora";
5470
- var cliVersion = true ? "0.28.883" : "dev";
5470
+ var cliVersion = true ? "0.28.885" : "dev";
5471
5471
  async function fetchLatestVersion() {
5472
5472
  const host2 = getHost();
5473
5473
  if (!host2) return null;
@@ -6658,7 +6658,7 @@ function handleError(err) {
6658
6658
  }
6659
6659
 
6660
6660
  // src/bin/agt.ts
6661
- var cliVersion2 = true ? "0.28.883" : "dev";
6661
+ var cliVersion2 = true ? "0.28.885" : "dev";
6662
6662
  var program = new Command();
6663
6663
  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");
6664
6664
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -3825,6 +3825,7 @@ function buildDockerRunCommand(args) {
3825
3825
  ];
3826
3826
  const image = process.env.AGT_ISOLATION_IMAGE || "agt-runtime:latest";
3827
3827
  const memory = process.env.AGT_ISOLATION_MEMORY || "2g";
3828
+ const memorySwap = memory;
3828
3829
  const cpus = process.env.AGT_ISOLATION_CPUS || "1.0";
3829
3830
  const pids = process.env.AGT_ISOLATION_PIDS || "512";
3830
3831
  const envArgs = [`-e ${q(`HOME=${homeDir}`)}`];
@@ -3881,7 +3882,13 @@ function buildDockerRunCommand(args) {
3881
3882
  // squid processes untrusted agent traffic - give it the same hardening as
3882
3883
  // the agent container (drop all caps, block privilege escalation). squid
3883
3884
  // binds 3128 (>1024) and needs no capabilities; verified it still boots.
3884
- `docker run -d --name ${squidName} --network ${internalNet} --restart unless-stopped --memory 128m --cap-drop ALL --security-opt no-new-privileges -v ${q(`${egress.allowlistHostPath}:/etc/squid/allowlist.txt:ro`)} ${q(egressImage)} >/dev/null`,
3885
+ // ENG-10369: `--memory-swap 128m` equal to `--memory 128m`, same reasoning
3886
+ // as the agent container above. squid is small and steady-state, so the
3887
+ // phantom 256m grant was never load-bearing - but leaving ONE container on
3888
+ // the implicit-doubling path is how the next host-swap change finds a way
3889
+ // back in, and an exemption nobody wrote down is an exemption nobody
3890
+ // re-checks.
3891
+ `docker run -d --name ${squidName} --network ${internalNet} --restart unless-stopped --memory 128m --memory-swap 128m --cap-drop ALL --security-opt no-new-privileges -v ${q(`${egress.allowlistHostPath}:/etc/squid/allowlist.txt:ro`)} ${q(egressImage)} >/dev/null`,
3885
3892
  `docker network connect agt-egress ${squidName} >/dev/null 2>&1`
3886
3893
  ].join(" && ");
3887
3894
  }
@@ -3915,6 +3922,9 @@ function buildDockerRunCommand(args) {
3915
3922
  // per-application is how it gets forgotten again next time.
3916
3923
  "--init",
3917
3924
  `--memory ${memory}`,
3925
+ // ENG-10369 - equal to `--memory`, so the container gets no swap access.
3926
+ // See the `memorySwap` definition above for why this is not optional.
3927
+ `--memory-swap ${memorySwap}`,
3918
3928
  `--cpus ${cpus}`,
3919
3929
  `--pids-limit ${pids}`,
3920
3930
  // Defence in depth (red-team 2026-06-16): drop all Linux capabilities and
@@ -3975,6 +3985,77 @@ function collectMcpServerNames(mcpConfigPath) {
3975
3985
  }
3976
3986
  }
3977
3987
  var PANE_AGENT_ID_PROBE_TIMEOUT_MS = 2e3;
3988
+ function applyPaneAgentIdVerdict(args) {
3989
+ const { session, mismatch, codeName, tmuxSession, log: log2 } = args;
3990
+ if (!mismatch) return false;
3991
+ log2(
3992
+ `[persistent-session] PANE AGENT ID MISMATCH agent=${codeName} isolation=${args.isolation} \u2014 ${mismatch}`
3993
+ );
3994
+ session.status = "crashed";
3995
+ session.startedAt = args.now ? args.now() : Date.now();
3996
+ log2(
3997
+ `[persistent-session] requesting kill of session '${tmuxSession}' for '${codeName}' \u2014 refusing to run an agent under another agent's identity (ENG-8800)`
3998
+ );
3999
+ let teardown;
4000
+ try {
4001
+ teardown = Promise.resolve(args.killSession(tmuxSession));
4002
+ } catch (err) {
4003
+ teardown = Promise.resolve({
4004
+ ok: false,
4005
+ reason: `could not start the kill: ${err instanceof Error ? err.message : String(err)}`
4006
+ });
4007
+ }
4008
+ void teardown.catch((err) => ({
4009
+ ok: false,
4010
+ reason: `the kill rejected: ${err instanceof Error ? err.message : String(err)}`
4011
+ })).then((result) => {
4012
+ if (result?.ok) {
4013
+ log2(`[persistent-session] killed session '${tmuxSession}' for '${codeName}' (ENG-8800)`);
4014
+ } else {
4015
+ const reason = result && !result.ok ? result.reason : "no result from the kill";
4016
+ log2(
4017
+ `[persistent-session] FAILED TO KILL session '${tmuxSession}' for '${codeName}': ${reason}. It is marked crashed, but its pane may still be running under another agent's identity. Kill it by hand: tmux kill-session -t ${tmuxSession} (ENG-8800)`
4018
+ );
4019
+ }
4020
+ args.onTeardownSettled?.(result ?? { ok: false, reason: "no result from the kill" });
4021
+ });
4022
+ return true;
4023
+ }
4024
+ function killTmuxSessionBounded(tmuxSession, deps = {}) {
4025
+ const spawnFn = deps.spawnFn ?? spawn2;
4026
+ const timeoutMs = deps.timeoutMs ?? PANE_AGENT_ID_PROBE_TIMEOUT_MS;
4027
+ return new Promise((resolve) => {
4028
+ let deadline;
4029
+ let settled = false;
4030
+ const settle = (result) => {
4031
+ if (settled) return;
4032
+ settled = true;
4033
+ if (deadline) clearTimeout(deadline);
4034
+ resolve(result);
4035
+ };
4036
+ let killer;
4037
+ try {
4038
+ killer = spawnFn("tmux", ["kill-session", "-t", tmuxSession], { stdio: "ignore" });
4039
+ } catch (err) {
4040
+ settle({ ok: false, reason: `could not spawn tmux: ${err instanceof Error ? err.message : String(err)}` });
4041
+ return;
4042
+ }
4043
+ deadline = setTimeout(() => {
4044
+ try {
4045
+ killer.kill("SIGKILL");
4046
+ } catch {
4047
+ }
4048
+ settle({ ok: false, reason: `tmux kill-session did not exit within ${timeoutMs}ms` });
4049
+ }, timeoutMs);
4050
+ deadline.unref?.();
4051
+ killer.on("error", (err) => {
4052
+ settle({ ok: false, reason: `tmux kill-session could not run: ${err.message}` });
4053
+ });
4054
+ killer.on("close", (code, signal) => {
4055
+ settle(code === 0 ? { ok: true } : { ok: false, reason: `tmux kill-session exited ${code ?? signal}` });
4056
+ });
4057
+ });
4058
+ }
3978
4059
  var REQUIRED_SPAWN_ENV = ["AGT_AGENT_ID", "AGT_HOST", "AGT_API_KEY"];
3979
4060
  function buildSpawnEnv(args) {
3980
4061
  const { base, agentId, runId } = args;
@@ -4660,31 +4741,15 @@ function spawnSession(config, session) {
4660
4741
  showEnvOutput: output,
4661
4742
  expectedAgentId: config.agentId
4662
4743
  });
4663
- if (mismatch) {
4664
- log2(
4665
- `[persistent-session] PANE AGENT ID MISMATCH agent=${codeName} isolation=${effectiveMode} \u2014 ${mismatch}`
4666
- );
4667
- session.status = "crashed";
4668
- session.startedAt = Date.now();
4669
- try {
4670
- const killer = spawn2("tmux", ["kill-session", "-t", tmuxSession], {
4671
- stdio: "ignore"
4672
- });
4673
- const killDeadline = setTimeout(() => {
4674
- try {
4675
- killer.kill("SIGKILL");
4676
- } catch {
4677
- }
4678
- }, PANE_AGENT_ID_PROBE_TIMEOUT_MS);
4679
- killDeadline.unref?.();
4680
- killer.on("error", () => clearTimeout(killDeadline));
4681
- killer.on("close", () => clearTimeout(killDeadline));
4682
- } catch {
4683
- }
4684
- log2(
4685
- `[persistent-session] killed session '${tmuxSession}' for '${codeName}' \u2014 refusing to run an agent under another agent's identity (ENG-8800)`
4686
- );
4687
- }
4744
+ applyPaneAgentIdVerdict({
4745
+ session,
4746
+ mismatch,
4747
+ codeName,
4748
+ tmuxSession,
4749
+ isolation: effectiveMode,
4750
+ log: log2,
4751
+ killSession: killTmuxSessionBounded
4752
+ });
4688
4753
  };
4689
4754
  const deadline = setTimeout(() => {
4690
4755
  settle(null);
@@ -5391,6 +5456,8 @@ export {
5391
5456
  buildDockerRunCommand,
5392
5457
  writePersistentClaudeWrapper,
5393
5458
  PANE_AGENT_ID_PROBE_TIMEOUT_MS,
5459
+ applyPaneAgentIdVerdict,
5460
+ killTmuxSessionBounded,
5394
5461
  REQUIRED_SPAWN_ENV,
5395
5462
  buildSpawnEnv,
5396
5463
  findMissingSpawnEnv,
@@ -5431,4 +5498,4 @@ export {
5431
5498
  stopAllSessionsAndWait,
5432
5499
  getProjectDir
5433
5500
  };
5434
- //# sourceMappingURL=chunk-PZHDYVFU.js.map
5501
+ //# sourceMappingURL=chunk-FP5M5OVX.js.map