fix(ios): replace failed agent turns on daemon retry

Merged
TE
6d ago
+244-5

Failed agent Retry previously sent a fresh user prompt, duplicating the failed turn. It now calls the daemon's retry operation. The daemon records the previous turn id on each retry attempt; the phone folds that attempt into the failed turn on live delivery and history replay, retaining the original prompt, attachments and partial work. A refused request leaves the failed turn intact, and repeated taps are suppressed while the request is pending.

Leo's request:

well i just think we can improve it a f***ton more than it is now... it's slow it's bad it belabours the point in too many tooltips it's ugly in places it doesn't even work in places there's lots of functionality that needs to get in

Scope: ordinary Retry on a failed latest agent turn. Chief attachments are covered separately by #27286. Edit and Resend still needs the historical-fork path and navigation support. #27205's menu additions are preserved; its failed-turn model retry should use the daemon retry operation after the model change.

Validation:

  • Tests cover one turn after retry, kept attachment bytes, no optimistic deletion, refusal followed by retry, repeated taps, and recorded-history replay.
  • Static prepush checks passed at 51c54b8e52491883f6732359d3607fa21fd7dc12. No local Swift compiler or executed Swift tests.
  • Fleet request: compile the iOS package and run FailedTurnRetryTests|RetriedTurnLiveTests. Regression commit cb7f956ca76 should fail the replay test.
  • Before/after light/dark capture scene: agent=-cmux-mobile-demo kbd-chat; base ba6bbf43e28b3d49f431d9438855650c90089347, head 51c54b8e52491883f6732359d3607fa21fd7dc12. Captures pending.
  • Independent review pending coordinator dispatch; the local review box cannot isolate its process scope.

Risk: an older daemon without the retry operation refuses the request and keeps the failed turn. No fallback sends a duplicate prompt. No timers or observers are added. Shared CmuxConversation and CmuxTabsKit are unchanged.

Agent session: agent session
šŸ¤– Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Fixes iOS retry of a failed agent turn so it uses the daemon's retry operation instead of sending a duplicate prompt, preserving the original prompt, attachments, and partial work.

  • The daemon records the previous turn id; on retry, the phone folds the new attempt into the existing failed turn for both live delivery and history replay.
  • Retry obeys the same phone-mode and Full-access checks, and the Retry button is disabled once the turn is no longer the latest failed turn.
  • The retried attempt's agent output starts a new message or thought item instead of appending to the failed attempt's partial output.
  • Repeated retry taps are suppressed while the request is pending; a refused request leaves the failed turn intact.
  • A dropped link clears the pending retry state, so a retry lost before the daemon accepted it can be sent again after reconnect.
  • Older daemons without the retry operation refuse the request and keep the failed turn, with no fallback duplicate prompt.