@integrity-labs/agt-cli 0.28.886 → 0.28.887

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-2E7GOSID.js";
43
+ } from "../chunk-2H3YMBEO.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
47
47
  readDirectChatSessionState
48
- } from "../chunk-FP5M5OVX.js";
48
+ } from "../chunk-OMRYKBFE.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.886" : "dev";
5470
+ var cliVersion = true ? "0.28.887" : "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.886" : "dev";
6661
+ var cliVersion2 = true ? "0.28.887" : "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) => {
@@ -16,7 +16,7 @@ import {
16
16
  parseEnvIntegrations,
17
17
  shellQuote,
18
18
  summarizeUnanswerablePane
19
- } from "./chunk-FP5M5OVX.js";
19
+ } from "./chunk-OMRYKBFE.js";
20
20
  import {
21
21
  BIND_FAILURE_QUARANTINE_THRESHOLD,
22
22
  INTEGRATIONS_SECTION_END,
@@ -6841,7 +6841,7 @@ function exchangeFailureKind(err) {
6841
6841
  }
6842
6842
 
6843
6843
  // src/lib/api-client.ts
6844
- var agtCliVersion = true ? "0.28.886" : "dev";
6844
+ var agtCliVersion = true ? "0.28.887" : "dev";
6845
6845
  var lastConfigHash = null;
6846
6846
  function setConfigHash(hash) {
6847
6847
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -11451,4 +11451,4 @@ export {
11451
11451
  managerInstallSystemUnitCommand,
11452
11452
  managerUninstallSystemUnitCommand
11453
11453
  };
11454
- //# sourceMappingURL=chunk-2E7GOSID.js.map
11454
+ //# sourceMappingURL=chunk-2H3YMBEO.js.map
@@ -74,7 +74,7 @@ function hardBoundedExecFile(file, args, opts) {
74
74
  );
75
75
  }
76
76
  const nodeTimeoutMs = available ? opts.timeoutMs + killAfterMs + 5e3 : opts.timeoutMs;
77
- const execFile = available ? "timeout" : file;
77
+ const execFile2 = available ? "timeout" : file;
78
78
  const execArgs = available ? [
79
79
  "--signal=TERM",
80
80
  `--kill-after=${toTimeoutArg(killAfterMs)}`,
@@ -85,7 +85,7 @@ function hardBoundedExecFile(file, args, opts) {
85
85
  const now = opts.now ?? (() => performance.now());
86
86
  const startedAt = now();
87
87
  try {
88
- const stdout = exec(execFile, execArgs, {
88
+ const stdout = exec(execFile2, execArgs, {
89
89
  encoding: "utf-8",
90
90
  timeout: nodeTimeoutMs,
91
91
  maxBuffer: opts.maxBuffer,
@@ -3022,6 +3022,90 @@ function summarizeUnanswerablePane(screen) {
3022
3022
  return { hash: simpleTextHash(flat), length: flat.length };
3023
3023
  }
3024
3024
 
3025
+ // src/lib/session-blocked-prompt.ts
3026
+ import { execFile } from "child_process";
3027
+ var BLOCKED_PROMPT_VERDICT_TTL_MS = 15e3;
3028
+ var BLOCKED_ON_PROMPT_DECISION = "blocked-on-prompt";
3029
+ var suspects = /* @__PURE__ */ new Map();
3030
+ var readAgentPane = (codeName) => new Promise((resolve) => {
3031
+ execFile("tmux", ["capture-pane", "-t", `agt-${codeName}`, "-p"], { timeout: 2e3 }, (err, stdout) => {
3032
+ resolve(err ? null : String(stdout));
3033
+ });
3034
+ });
3035
+ function noteSessionBlockedOnPrompt(codeName, kind, source, now = Date.now()) {
3036
+ const existing = suspects.get(codeName);
3037
+ suspects.set(codeName, {
3038
+ kind,
3039
+ source,
3040
+ verifiedAt: now,
3041
+ loggedSurfaces: existing && existing.kind === kind ? existing.loggedSurfaces : /* @__PURE__ */ new Set()
3042
+ });
3043
+ }
3044
+ function clearSessionBlockedOnPrompt(codeName) {
3045
+ return suspects.delete(codeName);
3046
+ }
3047
+ function sessionBlockedOnPrompt(codeName, options = {}) {
3048
+ const entry = suspects.get(codeName);
3049
+ if (!entry) return null;
3050
+ const now = options.now ?? Date.now();
3051
+ if (now - entry.verifiedAt >= BLOCKED_PROMPT_VERDICT_TTL_MS) {
3052
+ void refreshSessionBlockedOnPrompt(codeName, { ...options, now });
3053
+ }
3054
+ return entry.kind;
3055
+ }
3056
+ function refreshSessionBlockedOnPrompt(codeName, options = {}) {
3057
+ const entry = suspects.get(codeName);
3058
+ if (!entry) return Promise.resolve(null);
3059
+ if (entry.refresh) return entry.refresh;
3060
+ const startedAt = options.now ?? Date.now();
3061
+ const readPane = options.readPane ?? readAgentPane;
3062
+ let capture;
3063
+ try {
3064
+ capture = Promise.resolve(readPane(codeName));
3065
+ } catch {
3066
+ capture = Promise.resolve(null);
3067
+ }
3068
+ const refresh = capture.catch(() => null).then((pane) => {
3069
+ entry.refresh = void 0;
3070
+ if (suspects.get(codeName) !== entry) return suspects.get(codeName)?.kind ?? null;
3071
+ const kind = classifyUnanswerablePane(pane);
3072
+ if (!kind) {
3073
+ suspects.delete(codeName);
3074
+ return null;
3075
+ }
3076
+ if (kind !== entry.kind) entry.loggedSurfaces = /* @__PURE__ */ new Set();
3077
+ entry.kind = kind;
3078
+ entry.verifiedAt = startedAt;
3079
+ return kind;
3080
+ });
3081
+ entry.refresh = refresh;
3082
+ return refresh;
3083
+ }
3084
+ function sessionHealthyAndUnblocked(codeName, isHealthy, blockedOn = sessionBlockedOnPrompt) {
3085
+ const healthy = isHealthy(codeName);
3086
+ return healthy && blockedOn(codeName) === null;
3087
+ }
3088
+ function shouldLogBlockedPrompt(codeName, surface) {
3089
+ const entry = suspects.get(codeName);
3090
+ if (!entry || entry.loggedSurfaces.has(surface)) return false;
3091
+ entry.loggedSurfaces.add(surface);
3092
+ return true;
3093
+ }
3094
+ function applyBlockedPromptVerdict(result, blocked) {
3095
+ if (!blocked || !result.sessionHealthyAfter) return result;
3096
+ return {
3097
+ ...result,
3098
+ decision: BLOCKED_ON_PROMPT_DECISION,
3099
+ underlyingDecision: result.decision,
3100
+ sessionHealthyAfter: false,
3101
+ detail: `session blocked on an interactive prompt (${blocked}) and cannot run a tool call; underlying decision=${result.decision}` + (result.detail ? `; ${result.detail}` : "")
3102
+ };
3103
+ }
3104
+ function isConfirmedRespawn(result) {
3105
+ if (result.decision === BLOCKED_ON_PROMPT_DECISION) return result.underlyingDecision === "spawn";
3106
+ return result.decision === "spawn" && result.sessionHealthyAfter;
3107
+ }
3108
+
3025
3109
  // src/lib/channel-input-watchdog.ts
3026
3110
  var UNCLAIMED_DIALOG_ALERT_MS = 12e4;
3027
3111
  var STUCK_THRESHOLD_MS = 5e3;
@@ -4294,6 +4378,7 @@ function startPersistentSession(config) {
4294
4378
  return existing;
4295
4379
  }
4296
4380
  }
4381
+ clearSessionBlockedOnPrompt(config.codeName);
4297
4382
  const session = {
4298
4383
  codeName: config.codeName,
4299
4384
  startedAt: null,
@@ -4854,6 +4939,7 @@ async function acceptDialogs(tmuxSession, codeName, log2, primaryModel = null, s
4854
4939
  try {
4855
4940
  const screen = execSync2(`tmux capture-pane -t ${tmuxSession} -p 2>/dev/null`, { encoding: "utf-8" });
4856
4941
  if (isLoginPickerVisible(screen)) {
4942
+ noteSessionBlockedOnPrompt(codeName, "login-picker", "spawn-dialogs");
4857
4943
  if (!loginPickerReported) {
4858
4944
  log2(`[persistent-session] CLAUDE LOGIN REQUIRED for '${codeName}' \u2014 agent cannot start until ~/.claude.json is provisioned. Pair via the Hosts page or run 'claude /login' on the host.`);
4859
4945
  loginPickerReported = true;
@@ -4872,11 +4958,13 @@ async function acceptDialogs(tmuxSession, codeName, log2, primaryModel = null, s
4872
4958
  log2(
4873
4959
  `[persistent-session] BLOCKED DIALOG (usage-limit-choice-unrecognised-options) for '${codeName}' \u2014 refusing to send any key; needs a human to attach to the pane`
4874
4960
  );
4961
+ noteSessionBlockedOnPrompt(codeName, "usage-limit-unanswerable", "spawn-dialogs");
4875
4962
  return;
4876
4963
  }
4877
4964
  if (screen.includes("\u276F") && !screen.includes("Enter to confirm")) {
4878
4965
  if (hasMcpChildren(tmuxSession)) {
4879
4966
  log2(`[persistent-session] Session ready for '${codeName}' \u2014 MCP servers spawned`);
4967
+ clearSessionBlockedOnPrompt(codeName);
4880
4968
  await maybeSendFastMode({
4881
4969
  tmuxSession,
4882
4970
  codeName,
@@ -5118,6 +5206,7 @@ function stopPersistentSession(codeName, log2) {
5118
5206
  }
5119
5207
  }
5120
5208
  sessions2.delete(codeName);
5209
+ clearSessionBlockedOnPrompt(codeName);
5121
5210
  setTimeout(() => {
5122
5211
  reapOrphanChannelMcps({ log: log2 });
5123
5212
  }, 3e3).unref();
@@ -5430,6 +5519,13 @@ export {
5430
5519
  getOpencodeSessionState,
5431
5520
  getOpencodeTurnHealth,
5432
5521
  getOpencodeActivityAgeSeconds,
5522
+ BLOCKED_ON_PROMPT_DECISION,
5523
+ noteSessionBlockedOnPrompt,
5524
+ sessionBlockedOnPrompt,
5525
+ sessionHealthyAndUnblocked,
5526
+ shouldLogBlockedPrompt,
5527
+ applyBlockedPromptVerdict,
5528
+ isConfirmedRespawn,
5433
5529
  checkChannelInputs,
5434
5530
  takeWatchdogGiveUpCount,
5435
5531
  creditWatchdogGiveUpCount,
@@ -5498,4 +5594,4 @@ export {
5498
5594
  stopAllSessionsAndWait,
5499
5595
  getProjectDir
5500
5596
  };
5501
- //# sourceMappingURL=chunk-FP5M5OVX.js.map
5597
+ //# sourceMappingURL=chunk-OMRYKBFE.js.map