Skip to content

Mobile chat UI overhaul: staged send, question cards, artifact cards#785

Merged
arul28 merged 5 commits into
mainfrom
ade/users-admin-downloads-new-folder-7a7eab7d
Jul 10, 2026
Merged

Mobile chat UI overhaul: staged send, question cards, artifact cards#785
arul28 merged 5 commits into
mainfrom
ade/users-admin-downloads-new-folder-7a7eab7d

Conversation

@arul28

@arul28 arul28 commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes four mobile chat defects visible in Claude Agent SDK chats but applying to all runtimes:

  • Staged prompt send (steer) strip: compact rows — one-line truncated text, muted "Sends after turn · time" line, icon-only actions with accessibility labels (fixes mid-word button-label wrapping like "Inter-rupt"). Send now / Interrupt remain claude-only per the existing capability gate.
  • Staged-send reliability: the sync host's chat.send now converts a send arriving during an active turn into the existing steer path (routeActiveToSteer, additive {steerId, queued} ack), so offline-replayed sends queue instead of being dropped; iOS additionally reconciles lingering optimistic steers on the active→idle transition via a forced canonical refresh.
  • Question cards: pending card is capped to the transcript viewport (62%, min 240pt) with an internal self-sizing scroll for long option lists; the multi-question TabView(.page) pager is replaced with a chip tab strip + "n of m answered". Answered questions collapse to a single compact row ("Answered · {choice}", typed answers quoted, secrets never echoed) matching desktop/Claude Code.
  • Artifact in-thread card: icon tile + 2-line-max title + "Kind · time" metadata line; raw backend errors ("Artifact path must resolve within .ade/artifacts.") replaced with a muted preview-unavailable fallback.

Validation

  • iOS: full xcodebuild green (twice, including post-review fixes).
  • Desktop: agentChatService 534/534, including two new regression tests (send-during-active-turn queues + delivers at turn end; empty send stays a no-op).
  • /quality dual-review: no Blocker/High; safe findings auto-applied; re-review CLEAN.
  • Parity: docs updated; TUI/CLI/mobile-compat verified no changes needed (CLI already auto-steers via chat.messageSession; ack fields are additive for old clients).

🤖 Generated with Claude Code

Greptile Summary

This PR updates mobile chat behavior and presentation for staged sends, question cards, and artifact cards. The main changes are:

  • Routes remote chat.send calls during active turns into the queued steer path.
  • Persists queued steer display text and mode metadata for later delivery.
  • Adds tests for active-turn send queuing and empty send no-op behavior.
  • Reworks iOS staged-send rows with compact text and icon-only actions.
  • Replaces mobile question paging with chip tabs and capped internal scrolling.
  • Collapses resolved question cards and refreshes artifact card previews.

Confidence Score: 5/5

Safe to merge with low risk.

No correctness or security issues were identified in the reviewed changed paths. The active-send routing behavior is covered by new tests, and the iOS changes are localized UI and reconciliation updates.

No files require special attention.

T-Rex T-Rex Logs

What T-Rex did

  • Primary test run verified by the general contract validation proof, showing agentChatService.test.ts (534 tests) and syncRemoteCommandService.test.ts (183 tests) passed.
  • The regression scope was validated via the filtered log, confirming the named regression tests passed: send during active Claude turn queues through steer path, and empty send during active turn remains a no-op.
  • Environment details were captured in the environment proof log, recording repo path, HEAD SHA, Node/npm versions, and blocked native iOS tooling.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
apps/desktop/src/main/services/chat/agentChatService.ts Persists richer queued steer metadata and routes active sends through the existing steer delivery path.
apps/ade-cli/src/services/sync/syncRemoteCommandService.ts Routes queued remote chat.send calls through steer when a turn is active and returns additive queue acknowledgement fields.
apps/ios/ADE/Views/Work/WorkChatComposerAndInputViews.swift Overhauls staged steer rows and pending question cards with compact actions, tab chips, and internally capped question content.
apps/ios/ADE/Views/Work/WorkSessionDestinationView+Actions.swift Updates send and steer reconciliation actions so queued optimistic steers refresh and clear consistently.
apps/ios/ADE/Views/Work/WorkChatRichCardViews.swift Collapses resolved question cards to a compact answer summary while avoiding secret answer echoing.
apps/ios/ADE/Views/Work/WorkArtifactTerminalViews.swift Refreshes artifact cards with compact icon metadata rows and muted preview-unavailable status rendering.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
  participant iOS as iOS chat UI
  participant Sync as Sync remote command
  participant Chat as AgentChatService
  participant Runtime as Active runtime

  iOS->>Sync: chat.send(text, attachments)
  Sync->>Chat: sendMessage(..., routeActiveToSteer: true)
  Chat->>Chat: canRouteActiveSendToSteer()
  alt turn active and message routable
    Chat->>Chat: steer(...displayText/modes)
    Chat->>iOS: user_message(deliveryState: queued, steerId)
    Chat-->>Sync: "{ steerId, queued: true }"
    Sync-->>iOS: "{ ok: true, steerId, queued: true }"
    Runtime-->>Chat: active turn completes
    Chat->>Runtime: deliver queued steer with saved directives
    Chat->>iOS: delivered transcript update
  else idle or empty no-op
    Chat->>Runtime: normal send or no-op
    Sync-->>iOS: "{ ok: true }"
  end
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
  participant iOS as iOS chat UI
  participant Sync as Sync remote command
  participant Chat as AgentChatService
  participant Runtime as Active runtime

  iOS->>Sync: chat.send(text, attachments)
  Sync->>Chat: sendMessage(..., routeActiveToSteer: true)
  Chat->>Chat: canRouteActiveSendToSteer()
  alt turn active and message routable
    Chat->>Chat: steer(...displayText/modes)
    Chat->>iOS: user_message(deliveryState: queued, steerId)
    Chat-->>Sync: "{ steerId, queued: true }"
    Sync-->>iOS: "{ ok: true, steerId, queued: true }"
    Runtime-->>Chat: active turn completes
    Chat->>Runtime: deliver queued steer with saved directives
    Chat->>iOS: delivered transcript update
  else idle or empty no-op
    Chat->>Runtime: normal send or no-op
    Sync-->>iOS: "{ ok: true }"
  end
Loading

Reviews (3): Last reviewed commit: "Carry per-send options through the queue..." | Re-trigger Greptile

arul28 and others added 3 commits July 10, 2026 16:42
- Staged (steer) strip: compact rows with one-line truncated text and
  icon-only actions (fixes mid-word button-label wrapping); host now
  converts chat.send during an active turn into the steer path so
  offline-replayed sends are queued instead of dropped; iOS reconciles
  lingering optimistic steers on turn end via a forced canonical refresh.
- Pending question card: capped to the transcript viewport (62%, min
  240pt) with an internal self-sizing scroll for long option lists;
  multi-question pager replaced with a chip tab strip + answered count.
- Answered questions collapse to a single compact row ("Answered · {choice}",
  typed answers echoed in quotes, secrets never echoed) matching desktop.
- Artifact in-thread card: icon tile + 2-line title + "Kind · time"
  metadata line; raw backend errors replaced with a muted preview-unavailable
  fallback.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Drop dead accent property and stale doc comment on WorkResolvedQuestionCard;
  only echo freeform resolutions when the question model is present and
  known non-secret.
- steerActionButton takes one required async closure; measuredBodyHeight
  sentinel replaced with an Optional.
- routeActiveToSteer skips empty sends so they keep prepareSendMessage's
  no-op semantics instead of reporting a queued:false steer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ade Error Error Jul 10, 2026 9:20pm

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@arul28, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 34 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 253d5a93-932c-40ef-9b7a-dfd56116216a

📥 Commits

Reviewing files that changed from the base of the PR and between 3bf54cc and bf32980.

⛔ Files ignored due to path filters (3)
  • docs/features/chat/README.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/ios-companion.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/remote-commands.md is excluded by !docs/**
📒 Files selected for processing (11)
  • apps/ade-cli/src/services/sync/syncRemoteCommandService.ts
  • apps/desktop/src/main/services/chat/agentChatService.test.ts
  • apps/desktop/src/main/services/chat/agentChatService.ts
  • apps/desktop/src/main/services/sync/syncRemoteCommandService.test.ts
  • apps/desktop/src/shared/types/chat.ts
  • apps/ios/ADE/Views/Work/WorkArtifactTerminalViews.swift
  • apps/ios/ADE/Views/Work/WorkChatComposerAndInputViews.swift
  • apps/ios/ADE/Views/Work/WorkChatRichCardViews.swift
  • apps/ios/ADE/Views/Work/WorkChatSessionView+Timeline.swift
  • apps/ios/ADE/Views/Work/WorkSessionDestinationView+Actions.swift
  • apps/ios/ADE/Views/Work/WorkSessionDestinationView.swift
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/users-admin-downloads-new-folder-7a7eab7d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@arul28

arul28 commented Jul 10, 2026

Copy link
Copy Markdown
Owner Author

@copilot review but do not make fixes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@arul28

arul28 commented Jul 10, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1b7ee72ee3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +27402 to +27405
text: args.text,
attachments: args.attachments,
contextAttachments: args.contextAttachments,
metadata: args.metadata,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve chat.send options when steering active sends

When a remote client calls chat.send during an active turn with fields such as displayText, reasoningEffort, executionMode, or interactionMode, this new branch bypasses prepareSendMessage(args) and calls steer with only text/attachments/context/metadata. Those fields are accepted by the remote chat.send parser, so the active-turn-only path now loses per-send mode settings and can render the raw expanded prompt instead of the intended displayText. Please carry the original send options through the steer path or prepare the message from the original args before enqueueing.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in bf32980: AgentChatSteerArgs and the pending-steer entries now carry displayText / reasoningEffort / executionMode / interactionMode; the chat.send routing passes them through, and deliverNextQueuedSteer applies executionMode/interactionMode (same session mutations + directives as prepareSendMessage) and uses displayText for the visible message. reasoningEffort is persisted on the entry but not yet applied at delivery — there is no turn-option channel for it (the send path applies it out-of-band via session mutation + query reset); flagged as a follow-up rather than replicating that block here.

displayText, executionMode, and interactionMode set on a chat.send that
gets routed to the steer queue now survive to delivery: entries persist
the fields, deliverNextQueuedSteer applies the same session mutations and
prompt directives prepareSendMessage would, and the visible text stays
the displayText. reasoningEffort is stored on the entry; applying it at
delivery needs the send path's query-reset replication and is left as a
follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@arul28

arul28 commented Jul 10, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@vercel

vercel Bot commented Jul 10, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/arul28s-projects?upgradeToPro=build-rate-limit

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@arul28 arul28 merged commit 734797c into main Jul 10, 2026
31 of 32 checks passed
@arul28 arul28 deleted the ade/users-admin-downloads-new-folder-7a7eab7d branch July 10, 2026 22:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant