@integrity-labs/agt-cli 0.28.947 → 0.28.948

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.
@@ -20,12 +20,24 @@ import {
20
20
  sessionFileExists,
21
21
  todayLocalIso
22
22
  } from "./chunk-YZ5HGHPG.js";
23
+ import {
24
+ classifyUnanswerablePane,
25
+ findUsageLimitResetHint,
26
+ focusedConfirmDialogBlock,
27
+ isLoginPickerVisible,
28
+ isResumeModeDialogVisible,
29
+ isUnanswerableUsageLimitDialog,
30
+ isUnclaimedConfirmDialog,
31
+ sendDialogKeys,
32
+ simpleTextHash,
33
+ sweepDialogs
34
+ } from "./chunk-DHWNVVX4.js";
23
35
  import {
24
36
  reapOrphanChannelMcps
25
37
  } from "./chunk-XWVM4KPK.js";
26
38
 
27
39
  // src/lib/persistent-session.ts
28
- import { spawn as spawn2, execSync as execSync2, execFileSync as execFileSync4 } from "child_process";
40
+ import { spawn as spawn2, execSync as execSync2, execFileSync as execFileSync3 } from "child_process";
29
41
 
30
42
  // src/lib/bounded-exec.ts
31
43
  import { execFileSync } from "child_process";
@@ -2737,292 +2749,6 @@ function describeError(err) {
2737
2749
  return code ? `${code}: ${msg}` : msg;
2738
2750
  }
2739
2751
 
2740
- // src/lib/claude-dialogs.ts
2741
- import { execFileSync as execFileSync3 } from "child_process";
2742
- function isLoginPickerVisible(screen) {
2743
- return screen.includes("Select login method") || screen.includes("Claude account with subscription") && screen.includes("Anthropic Console account");
2744
- }
2745
- function isResumeModeDialogVisible(screen) {
2746
- return screen.includes("Resume from summary") && screen.includes("Don't ask me again");
2747
- }
2748
- function isSessionFeedbackDialogVisible(screen) {
2749
- return screen.includes("How is Claude doing this session") && screen.includes("0: Dismiss");
2750
- }
2751
- var USAGE_LIMIT_SAFE_OPTION = "Stop and wait for limit to reset";
2752
- var USAGE_LIMIT_CONTINUE_OPTION = "Wait here, then continue automatically";
2753
- var USAGE_LIMIT_SAFE_OPTIONS = [
2754
- USAGE_LIMIT_CONTINUE_OPTION,
2755
- USAGE_LIMIT_SAFE_OPTION
2756
- ];
2757
- var USAGE_LIMIT_KNOWN_OPTIONS = [
2758
- ...USAGE_LIMIT_SAFE_OPTIONS,
2759
- "Switch to usage credits",
2760
- "Switch to Team plan",
2761
- // ENG-9006: the two-option variant Claude Code shipped ~2026-08-17. Filed
2762
- // with a wedged pane and four unanswered customer Telegram messages queued
2763
- // behind it.
2764
- "Upgrade your plan",
2765
- "Ask your admin for more usage"
2766
- ];
2767
- var USAGE_LIMIT_BLOCK_LINES = 6;
2768
- function optionRowDigit(line2, label) {
2769
- const m = line2.match(
2770
- new RegExp(
2771
- String.raw`^[^\S\n]*(?:❯[^\S\n]*)?(\d)\.[^\S\n]*` + label.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)
2772
- )
2773
- );
2774
- return m?.[1] ?? null;
2775
- }
2776
- function focusedModalBlock(screen, blockLines) {
2777
- const lines = screen.split("\n");
2778
- let footer = -1;
2779
- for (let i = lines.length - 1; i >= 0; i--) {
2780
- if (lines[i].includes("Enter to confirm")) {
2781
- footer = i;
2782
- break;
2783
- }
2784
- }
2785
- if (footer < 0) return null;
2786
- return lines.slice(Math.max(0, footer - blockLines), footer);
2787
- }
2788
- var MCP_DIALOG_OPTIONS = [
2789
- "Use this and all future MCP servers in this project",
2790
- "Continue without using these MCP servers"
2791
- ];
2792
- function isMcpServersDialogVisible(screen) {
2793
- const block = focusedModalBlock(screen, USAGE_LIMIT_BLOCK_LINES);
2794
- if (!block) return false;
2795
- return block.some((l) => MCP_DIALOG_OPTIONS.some((label) => optionRowDigit(l, label) !== null));
2796
- }
2797
- var MCP_CHECKBOX_HEADER = /new MCP servers? found in this project/i;
2798
- var MCP_CHECKED_ROW = /^[^\S\n]*(?:❯[^\S\n]*)?\[[✓x]\][^\S\n]*\S/iu;
2799
- var MCP_CHECKBOX_BLOCK_LINES = 20;
2800
- function isMcpCheckboxDialogVisible(screen) {
2801
- const block = focusedModalBlock(screen, MCP_CHECKBOX_BLOCK_LINES);
2802
- if (!block) return false;
2803
- if (!block.some((l) => MCP_CHECKBOX_HEADER.test(l))) return false;
2804
- return block.some((l) => MCP_CHECKED_ROW.test(l));
2805
- }
2806
- function usageLimitModalBlock(screen) {
2807
- const lines = screen.split("\n");
2808
- let footer = -1;
2809
- for (let i = lines.length - 1; i >= 0; i--) {
2810
- if (lines[i].includes("Enter to confirm")) {
2811
- footer = i;
2812
- break;
2813
- }
2814
- }
2815
- if (footer < 0) return null;
2816
- const block = lines.slice(Math.max(0, footer - USAGE_LIMIT_BLOCK_LINES), footer);
2817
- const hasKnownOptionRow = block.some(
2818
- (l) => USAGE_LIMIT_KNOWN_OPTIONS.some((label) => optionRowDigit(l, label) !== null)
2819
- );
2820
- return hasKnownOptionRow ? block : null;
2821
- }
2822
- function isUsageLimitChoiceDialogVisible(screen) {
2823
- return usageLimitModalBlock(screen) !== null;
2824
- }
2825
- function findUsageLimitSafeOption(screen) {
2826
- const block = usageLimitModalBlock(screen);
2827
- if (!block) return null;
2828
- for (const label of USAGE_LIMIT_SAFE_OPTIONS) {
2829
- for (const line2 of block) {
2830
- const digit = optionRowDigit(line2, label);
2831
- if (digit !== null) return { key: digit, label };
2832
- }
2833
- }
2834
- return null;
2835
- }
2836
- function findUsageLimitSafeOptionKey(screen) {
2837
- return findUsageLimitSafeOption(screen)?.key ?? null;
2838
- }
2839
- var CONSENT_BLOCK_LINES = 12;
2840
- function lastIndexWhere(xs, pred) {
2841
- for (let i = xs.length - 1; i >= 0; i--) {
2842
- if (pred(xs[i])) return i;
2843
- }
2844
- return -1;
2845
- }
2846
- function isCursorRow(line2) {
2847
- return /^[^\S\n]*❯[^\S\n]+\S/.test(line2);
2848
- }
2849
- function isOptionRowFor(line2, label) {
2850
- const escaped = label.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
2851
- return new RegExp(
2852
- String.raw`^[^\S\n]*(?:❯[^\S\n]*)?(?:\d\.[^\S\n]*)?` + escaped + String.raw`[^\S\n]*$`
2853
- ).test(line2);
2854
- }
2855
- function selectRowKeys(screen, label) {
2856
- const block = focusedModalBlock(screen, CONSENT_BLOCK_LINES);
2857
- if (!block) return null;
2858
- const target = lastIndexWhere(block, (l) => isOptionRowFor(l, label));
2859
- if (target < 0) return null;
2860
- const digit = optionRowDigit(block[target], label);
2861
- if (digit !== null) return [digit, "Enter"];
2862
- const cursors = [];
2863
- for (let i = 0; i < block.length; i++) {
2864
- if (isCursorRow(block[i])) cursors.push(i);
2865
- }
2866
- if (cursors.length === 0) return null;
2867
- let cursor = cursors[0];
2868
- let tied = false;
2869
- for (const i of cursors.slice(1)) {
2870
- const d = Math.abs(i - target);
2871
- const best = Math.abs(cursor - target);
2872
- if (d < best) {
2873
- cursor = i;
2874
- tied = false;
2875
- } else if (d === best) {
2876
- tied = true;
2877
- }
2878
- }
2879
- if (tied) return null;
2880
- const distance = target - cursor;
2881
- if (distance === 0) return ["Enter"];
2882
- const step = distance > 0 ? "Down" : "Up";
2883
- return [...Array(Math.abs(distance)).fill(step), "Enter"];
2884
- }
2885
- function findUsageLimitResetHint(screen) {
2886
- const block = usageLimitModalBlock(screen);
2887
- if (!block) return null;
2888
- for (const line2 of block) {
2889
- if (optionRowDigit(line2, USAGE_LIMIT_CONTINUE_OPTION) === null) continue;
2890
- const idx = line2.indexOf(USAGE_LIMIT_CONTINUE_OPTION);
2891
- const tail = line2.slice(idx + USAGE_LIMIT_CONTINUE_OPTION.length).trim();
2892
- const when = tail.replace(/^at\s+/i, "").trim();
2893
- if (!when) return null;
2894
- return when.slice(0, 40);
2895
- }
2896
- return null;
2897
- }
2898
- function isUnanswerableUsageLimitDialog(screen) {
2899
- return isUsageLimitChoiceDialogVisible(screen) && findUsageLimitSafeOptionKey(screen) === null;
2900
- }
2901
- function sweepDialogs(screen) {
2902
- if (isUsageLimitChoiceDialogVisible(screen)) {
2903
- const safe = findUsageLimitSafeOption(screen);
2904
- if (!safe) return null;
2905
- return {
2906
- kind: "usage-limit-choice",
2907
- // The log names the option ACTUALLY picked, not a fixed literal. With two
2908
- // selectable rows now, a constant string would make a fleet sweep unable
2909
- // to tell an agent that will resume by itself from one parked until a
2910
- // human touches it.
2911
- keys: [safe.key, "Enter"],
2912
- interKeyDelayMs: 300,
2913
- logMessage: `Auto-answered usage-limit choice dialog (picked '${safe.label}')`
2914
- };
2915
- }
2916
- if (screen.includes("Choose the text style") || screen.includes("Dark mode") && screen.includes("Light mode")) {
2917
- return {
2918
- kind: "theme-picker",
2919
- keys: ["Enter"],
2920
- interKeyDelayMs: 0,
2921
- logMessage: "Auto-accepted theme picker"
2922
- };
2923
- }
2924
- const trustKeys = screen.includes("Yes, I trust this folder") ? selectRowKeys(screen, "Yes, I trust this folder") : null;
2925
- if (trustKeys) {
2926
- return {
2927
- kind: "folder-trust",
2928
- keys: trustKeys,
2929
- interKeyDelayMs: 300,
2930
- logMessage: "Auto-accepted folder trust"
2931
- };
2932
- }
2933
- const resumeKeys = isResumeModeDialogVisible(screen) ? selectRowKeys(screen, "Don't ask me again") : null;
2934
- if (resumeKeys) {
2935
- return {
2936
- kind: "resume-mode",
2937
- keys: resumeKeys,
2938
- interKeyDelayMs: 300,
2939
- logMessage: "Auto-dismissed resume-mode dialog (picked 'Don't ask me again')"
2940
- };
2941
- }
2942
- if (screen.includes("I am using this for local development")) {
2943
- return {
2944
- kind: "dev-channels",
2945
- keys: ["Enter"],
2946
- interKeyDelayMs: 0,
2947
- logMessage: "Auto-accepted dev channels"
2948
- };
2949
- }
2950
- if (isMcpServersDialogVisible(screen) || isMcpCheckboxDialogVisible(screen)) {
2951
- return {
2952
- kind: "mcp-servers",
2953
- keys: ["Enter"],
2954
- interKeyDelayMs: 0,
2955
- logMessage: "Auto-accepted MCP servers"
2956
- };
2957
- }
2958
- const bypassKeys = screen.includes("Yes, I accept") && screen.includes("Bypass Permissions") ? selectRowKeys(screen, "Yes, I accept") : null;
2959
- if (bypassKeys) {
2960
- return {
2961
- kind: "bypass-permissions",
2962
- keys: bypassKeys,
2963
- interKeyDelayMs: 300,
2964
- logMessage: "Auto-accepted bypass permissions"
2965
- };
2966
- }
2967
- if (isSessionFeedbackDialogVisible(screen)) {
2968
- return {
2969
- kind: "session-feedback",
2970
- keys: ["0"],
2971
- interKeyDelayMs: 0,
2972
- logMessage: "Auto-dismissed session-feedback dialog"
2973
- };
2974
- }
2975
- return null;
2976
- }
2977
- async function sendDialogKeys(tmuxSession, action) {
2978
- for (let i = 0; i < action.keys.length; i++) {
2979
- if (i > 0 && action.interKeyDelayMs > 0) {
2980
- await new Promise((r) => setTimeout(r, action.interKeyDelayMs));
2981
- }
2982
- execFileSync3("tmux", ["send-keys", "-t", tmuxSession, action.keys[i]], {
2983
- stdio: "ignore"
2984
- });
2985
- }
2986
- }
2987
- function focusedConfirmDialogBlock(screen) {
2988
- const lines = screen.split("\n");
2989
- let footer = -1;
2990
- for (let i = lines.length - 1; i >= 0; i--) {
2991
- if (lines[i].includes("Enter to confirm")) {
2992
- footer = i;
2993
- break;
2994
- }
2995
- }
2996
- if (footer < 0) return null;
2997
- return lines.slice(Math.max(0, footer - USAGE_LIMIT_BLOCK_LINES), footer + 1);
2998
- }
2999
- function isUnclaimedConfirmDialog(screen) {
3000
- if (focusedConfirmDialogBlock(screen) === null) return false;
3001
- if (sweepDialogs(screen) !== null) return false;
3002
- if (isUnanswerableUsageLimitDialog(screen)) return false;
3003
- return true;
3004
- }
3005
- function simpleTextHash(s) {
3006
- let h = 0;
3007
- for (let i = 0; i < s.length; i++) {
3008
- h = (h << 5) - h + s.charCodeAt(i) | 0;
3009
- }
3010
- return h.toString(16);
3011
- }
3012
- function classifyUnanswerablePane(screen) {
3013
- if (!screen) return null;
3014
- if (isLoginPickerVisible(screen)) return "login-picker";
3015
- if (isUnanswerableUsageLimitDialog(screen)) return "usage-limit-unanswerable";
3016
- if (isUnclaimedConfirmDialog(screen)) return "unclaimed-modal";
3017
- return null;
3018
- }
3019
- function summarizeUnanswerablePane(screen) {
3020
- const block = focusedConfirmDialogBlock(screen);
3021
- if (!block) return null;
3022
- const flat = block.join("\n");
3023
- return { hash: simpleTextHash(flat), length: flat.length };
3024
- }
3025
-
3026
2752
  // src/lib/session-blocked-prompt.ts
3027
2753
  import { execFile } from "child_process";
3028
2754
  var BLOCKED_PROMPT_VERDICT_TTL_MS = 15e3;
@@ -3871,7 +3597,7 @@ function isNoSuchContainer(err) {
3871
3597
  }
3872
3598
  function reloadEgressSidecar(codeName) {
3873
3599
  try {
3874
- execFileSync4("docker", ["kill", "--signal=HUP", `agt-squid-${codeName}`], {
3600
+ execFileSync3("docker", ["kill", "--signal=HUP", `agt-squid-${codeName}`], {
3875
3601
  stdio: "pipe",
3876
3602
  timeout: EGRESS_DOCKER_TIMEOUT_MS
3877
3603
  });
@@ -3883,7 +3609,7 @@ function reloadEgressSidecar(codeName) {
3883
3609
  }
3884
3610
  function restartEgressSidecar(codeName) {
3885
3611
  try {
3886
- execFileSync4("docker", ["restart", `agt-squid-${codeName}`], {
3612
+ execFileSync3("docker", ["restart", `agt-squid-${codeName}`], {
3887
3613
  stdio: "pipe",
3888
3614
  timeout: EGRESS_DOCKER_TIMEOUT_MS
3889
3615
  });
@@ -5140,7 +4866,7 @@ async function waitForPromptReady(tmuxSession) {
5140
4866
  const deadline = Date.now() + 1e4;
5141
4867
  while (Date.now() < deadline) {
5142
4868
  try {
5143
- const screen = execFileSync4(
4869
+ const screen = execFileSync3(
5144
4870
  "tmux",
5145
4871
  ["capture-pane", "-t", tmuxSession, "-p"],
5146
4872
  { encoding: "utf-8", stdio: ["ignore", "pipe", "ignore"] }
@@ -5159,11 +4885,11 @@ function sleepBlockingMs(ms) {
5159
4885
  }
5160
4886
  function defaultArmSender(tmuxSession, command) {
5161
4887
  try {
5162
- execFileSync4("tmux", ["send-keys", "-t", tmuxSession, "-l", command], {
4888
+ execFileSync3("tmux", ["send-keys", "-t", tmuxSession, "-l", command], {
5163
4889
  stdio: ["ignore", "ignore", "pipe"]
5164
4890
  });
5165
4891
  sleepBlockingMs(SEND_KEYS_ENTER_DELAY_MS);
5166
- execFileSync4("tmux", ["send-keys", "-t", tmuxSession, "Enter"], {
4892
+ execFileSync3("tmux", ["send-keys", "-t", tmuxSession, "Enter"], {
5167
4893
  stdio: ["ignore", "ignore", "pipe"]
5168
4894
  });
5169
4895
  return true;
@@ -5174,7 +4900,7 @@ function defaultArmSender(tmuxSession, command) {
5174
4900
  var armSender = defaultArmSender;
5175
4901
  function defaultPaneCapture(tmuxSession) {
5176
4902
  try {
5177
- return execFileSync4("tmux", ["capture-pane", "-t", tmuxSession, "-p"], {
4903
+ return execFileSync3("tmux", ["capture-pane", "-t", tmuxSession, "-p"], {
5178
4904
  encoding: "utf-8",
5179
4905
  stdio: ["ignore", "pipe", "ignore"],
5180
4906
  timeout: 2e3
@@ -5189,7 +4915,7 @@ var defaultHygieneKeySender = async (tmuxSession, keys, interKeyDelayMs) => {
5189
4915
  if (i > 0 && interKeyDelayMs > 0) {
5190
4916
  await new Promise((r) => setTimeout(r, interKeyDelayMs));
5191
4917
  }
5192
- execFileSync4("tmux", ["send-keys", "-t", tmuxSession, keys[i]], {
4918
+ execFileSync3("tmux", ["send-keys", "-t", tmuxSession, keys[i]], {
5193
4919
  stdio: "ignore"
5194
4920
  });
5195
4921
  }
@@ -5198,7 +4924,7 @@ var hygieneKeySender = defaultHygieneKeySender;
5198
4924
  var SESSION_CREATED_TIMEOUT_MS = 3e3;
5199
4925
  function defaultSessionCreatedProbe(tmuxSession) {
5200
4926
  try {
5201
- const created = execFileSync4("tmux", ["display", "-p", "-t", tmuxSession, "#{session_created}"], {
4927
+ const created = execFileSync3("tmux", ["display", "-p", "-t", tmuxSession, "#{session_created}"], {
5202
4928
  encoding: "utf-8",
5203
4929
  timeout: SESSION_CREATED_TIMEOUT_MS
5204
4930
  }).trim();
@@ -5325,7 +5051,7 @@ function stopPersistentSession(codeName, log2) {
5325
5051
  log2(`[persistent-session] Stopping session for '${codeName}'`);
5326
5052
  session.status = "stopped";
5327
5053
  try {
5328
- execFileSync4("tmux", ["kill-session", "-t", `agt-${codeName}`], { stdio: ["ignore", "ignore", "pipe"] });
5054
+ execFileSync3("tmux", ["kill-session", "-t", `agt-${codeName}`], { stdio: ["ignore", "ignore", "pipe"] });
5329
5055
  } catch (err) {
5330
5056
  const stderr = (err.stderr ?? "").toString().trim();
5331
5057
  const alreadyGone = /can't find session|no server running/i.test(stderr);
@@ -5425,7 +5151,7 @@ function isSessionHealthy(codeName) {
5425
5151
  if (!claudeAlive) {
5426
5152
  const paneTail = readPaneLogTail(codeName);
5427
5153
  try {
5428
- execFileSync4("tmux", ["kill-session", "-t", tmuxSession], { stdio: "ignore" });
5154
+ execFileSync3("tmux", ["kill-session", "-t", tmuxSession], { stdio: "ignore" });
5429
5155
  } catch {
5430
5156
  }
5431
5157
  session.status = "crashed";
@@ -5521,13 +5247,13 @@ function collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, sp
5521
5247
  let launchArgs = null;
5522
5248
  let channelStatus = null;
5523
5249
  try {
5524
- execFileSync4("tmux", ["has-session", "-t", tmuxSession], { stdio: "ignore" });
5250
+ execFileSync3("tmux", ["has-session", "-t", tmuxSession], { stdio: "ignore" });
5525
5251
  tmuxAlive = true;
5526
5252
  } catch {
5527
5253
  }
5528
5254
  if (tmuxAlive) {
5529
5255
  try {
5530
- screenCapture = execFileSync4("tmux", ["capture-pane", "-t", tmuxSession, "-p", "-S", "-30"], {
5256
+ screenCapture = execFileSync3("tmux", ["capture-pane", "-t", tmuxSession, "-p", "-S", "-30"], {
5531
5257
  encoding: "utf-8",
5532
5258
  timeout: 3e3
5533
5259
  }).trim();
@@ -5535,7 +5261,7 @@ function collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, sp
5535
5261
  }
5536
5262
  }
5537
5263
  try {
5538
- const psOutput = execFileSync4("ps", ["aux"], { encoding: "utf-8", timeout: 3e3 });
5264
+ const psOutput = execFileSync3("ps", ["aux"], { encoding: "utf-8", timeout: 3e3 });
5539
5265
  const line2 = psOutput.split("\n").find((l) => l.includes(`agt-${codeName}`) && !l.includes("grep"));
5540
5266
  if (line2) {
5541
5267
  const match = line2.match(/claude\s+.*/);
@@ -5628,8 +5354,6 @@ export {
5628
5354
  readChannelServerEnv,
5629
5355
  hardBoundedExecFile,
5630
5356
  hardBoundedCapture,
5631
- classifyUnanswerablePane,
5632
- summarizeUnanswerablePane,
5633
5357
  LATE_BOUND_VARS,
5634
5358
  expandTemplateVars,
5635
5359
  parseEnvIntegrations,
@@ -5730,4 +5454,4 @@ export {
5730
5454
  stopAllSessionsAndWait,
5731
5455
  getProjectDir
5732
5456
  };
5733
- //# sourceMappingURL=chunk-XN5MOKSV.js.map
5457
+ //# sourceMappingURL=chunk-LRVXTEFJ.js.map