Files
KRATOS 952788f72d fix(tui): resolve every permission request so the agent can't deadlock (#397)
A goroutine dump of a run "stuck for 33 minutes" showed the agent parked
forever in executeToolCall -> requestPermission, blocked on the TUI's
decision channel. Root cause: a shell command whose sandbox decision was
Allow but which requested additional sandbox permissions
(sandbox_permissions: with_additional_permissions) made shouldRequestPermission
block on OnPermissionRequest, yet buildPermissionEvent stamped the event
Action=allow. The TUI's permissionRequestMsg handler only rendered/resolved
Action=prompt requests and silently dropped everything else — so the decide
callback was never called, the agent waited on a channel nothing would signal
(no ctx cancellation on the active run), and the UI showed "Working" with no
prompt and zero network activity. Intermittent and model-dependent: gpt-5.5's
folder-creation command set the additional-permissions flag, glm's did not,
which is exactly why one hung and the other ran clean.

Two-part fix:

- agent (buildPermissionEvent): an additional-permissions request is an
  ELEVATION the user must consent to, even over a sandbox Allow, so mark it
  Action=prompt (matching shouldRequestPermission's own condition). It now
  surfaces as a real prompt instead of a dropped auto-allow.

- tui (permissionRequestMsg handler): enforce the contract that a blocked
  agent ALWAYS gets a decision. A non-prompt action resolves immediately and
  FAILS CLOSED (deny; cancel stays cancel) so the UI can never silently grant
  an unsurfaced permission; a superseded-run (runID mismatch) resolves as
  cancel so its parked goroutine unblocks without depending on ctx-cancel
  ordering. Matches the ACP handler's always-resolve, fail-closed contract.

Red-green: reverting the tui branch reproduces the deadlock (decide never
called); reverting the agent override reproduces Action=allow. End-to-end
against a mock backend emitting the exact triggering tool call, the real TUI
now renders the permission prompt and the run completes on approval, where
before it parked forever.
2026-07-03 06:02:57 +08:00
..