🤖 feat: add an experimental native mobile companion - #4103
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
🤖 Codex-reference navigation and composer polishUpdated in
Before / after
composer-bottom-390.webmVerification
The recording is 24.3 seconds. RN Web evidence only: native keyboard/gesture/device validation remains outstanding. Generated with |
Implement native connection, grouped workspace navigation, conversation streaming and actions, server-backed creation, model settings, read-only changes, and connection settings. The mobile client uses shared API/types and aborts workspace-bound work on navigation. Validation: 15 TS/TSX syntax transforms, formatting, seven settings behavior checks. Full mobile typecheck and visual dogfood depend on the parent scaffold and transport integration.
Add a single authenticated, owned WebSocket connection for unary RPC and subscriptions, with endpoint validation, cancellation, timeout, and no retries. Reduce real chat events into authoritative, immutable mobile transcript state. Validate endpoint security, replay/interruption/truncation behavior, and live oRPC socket authentication, subscription delivery, and mutation lifecycle.
Keep the selected workspace and draft mounted while replacing the closed connection. Abort all prior-connection work, require fresh full replay before chat writes, and cancel late reconnects when disconnecting or unmounting. Warn explicitly before HTTP sends bearer credentials in plaintext. Validation: five reconnect lifecycle tests (28 assertions), 17 TS/TSX syntax checks, formatting and whitespace. Full RN typecheck and UI evidence remain with parent integration.
Isolate native dependencies and shared schema contracts, add secure credentials and a fixed-target Node preview proxy, and validate transport/replay and connection lifecycle behavior. Document native runtime limits and development commands. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$12.95`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=12.95 -->
Fix issues found through React Native Web dogfooding: exclude synthetic scratch projects, use the shared model catalog/defaults, persist effective reasoning defaults, and page older history without resurrecting truncated rows. Include behavioral regressions and synchronize the mobile documentation index. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$36.99`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=36.99 -->
Unify native spacing, type, control/card/sheet radii, and grouped form styling. Keep sheet actions visible, bound web sheets with a dismissible scrim, protect pending workspace creation from dismissal, and require confirmation before disconnecting. Add friendly model search, token visibility, and native keyboard focus progression. Validation: mobile TypeScript, targeted ESLint, formatting, 60 mobile source tests including five isolated RN-Web form behavior cases. Parent owns integrated desktop/mobile screenshot and recording gates.
Replace manual navigation with a native stack, preserve drafts and selections, and refine conversation, workspace, model, and changes layouts. Add pinned-viewport browser regressions, including composer growth/shrink and navigation retention. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_ _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$148.33`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=148.33 -->
Show a neutral fallback when an empty persisted assistant row has no interruption marker; preserve explicit interrupted and active-stream behavior. Cover these branches with native-web behavior tests. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_ _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$148.33`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=148.33 -->
Render a calmer native transcript with accessible message roles, hanging Markdown lists, readable literal code blocks, and transparent tool/reasoning action rows. Open bounded tool inspection sheets, retain inline question answers, and derive tool state only from real execution/result metadata. Validation: mobile TypeScript, targeted ESLint, formatting, 60 mobile source tests including 13 native-web interaction cases. Parent owns integrated reference screenshots and mobile browser verification.
Use quieter native surfaces and lightweight session navigation, center conversation context, integrate model and send controls into one composer, and progressively disclose thinking settings. Preserve transport, draft/model state, and native navigation; add browser coverage for focused settings. Validated mobile checks, pinned browser viewports, real-server integration, web and iOS Hermes exports, Expo compatibility, and root static checks. Captured reference provenance and real-server UI walkthroughs locally. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_ _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$248.65`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=248.65 -->
Use platform-neutral authentication copy in the native app and web development preview. Keep browser-only storage limitations in developer documentation; credential handling is unchanged. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_ _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$286.86`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=286.86 -->
Replace the combined conversation settings form with model, mode, and effort picker sheets inspired by the supplied native references. Apply list choices immediately, preserve model/effort when switching mode, and require confirmation only for custom model text. Verify selection behavior, draft retention, narrow/wide layouts, web and iOS exports, and real-server replay. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$347.29`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=347.29 -->
Show the Settings-visible catalog directly in the native model sheet instead of a four-model provider shortlist. Reuse shared routing, catalog-accessibility and OpenAI auth rules; search provider names, friendly names and aliases without resurrecting removed discovery entries. Validate hidden and gateway models, cross-provider selection, draft/effort retention, and phone/wide layouts. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$353.19`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=353.19 -->
Bring phone workspace search and creation into a fixed bottom dock, show project/server context in left-aligned conversation headers, and group navigation actions. Keep the input bottommost with Plan/model controls above it. Expand text entry for focus/drafts while preserving web picker clicks through browser focus retention rather than timers or moving controls below the input. Draw focus on the rounded composer boundary. Validate phone/wide/short layouts, keyboard and pointer picker activation, draft/settings retention, send/interrupt controls, and native bundling. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$428.45`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=428.45 -->
03d2fe7 to
eed1626
Compare
React Native's abort-controller and Expo's static AbortSignal patch do not provide throwIfAborted, which oRPC invokes before sending the initial authenticated request. Add the missing native compatibility method without replacing existing implementations or bypassing cancellation. Reproduce the generic connection error with RN's actual abort implementation and a real WebSocket/oRPC server, then run the transport/auth/cancellation suite in an isolated native-global subprocess. Import the package implementation explicitly because Bun aliases its bare name to the host's modern controller. Validated mobile tests, web/iOS exports, and static checks. Physical-device confirmation remains pending. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$564.47`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=564.47 -->
Use desktop's top-level workspace selector before counting and searching. Share the adjacent-part display projection so persisted stream chunks do not become separate reasoning blocks or paragraphs, without altering authoritative history or tool boundaries. Show the effective reasoning effort beside the model and a compact context ring using desktop token calculations and the latest step's usage. Context respects compaction/reset boundaries, authoritative completion, replay, and deletion rather than accumulating billing totals. Verified red/green native-web behavior regressions, live usage/replay/reset tests, mobile checks, production web export, desktop workspace-filter tests, and root static checks. Native keyboard correction follows separately. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$704.34`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=704.34 -->
Use the SDK-pinned keyboard controller for all four native keyboard boundaries, preserving core web behavior and safe-area layout. Measure window offsets rather than guessing header or sheet insets. Verify the installed overlap algorithm against safe-area and page-sheet geometry, keyboard-height changes, dismissal, and disabled avoidance. Native device positioning still requires iPhone validation. Validation: make -j1 mobile-check (71 passed, 1 existing integration skip); Expo iOS and web exports; web source maps exclude the native keyboard dependencies. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high -->
Use React Native's cross-platform ARIA aliases because RN Web does not forward accessibilityValue. Add a rendering regression for known, over-limit, and unknown percentages. Keep the browser model-preservation assertion on textContent for both its baseline and comparison now that effort is a separate text node. Validation: mobile checks, web/iOS exports, and repository static checks pass after these dogfood fixes. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$713.72`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=713.72 -->
Mobile parity follow-up
Validation: mobile checks 73 passed, 1 opt-in integration skip; web/iOS exports; root static checks; desktop workspace-filter tests; browser E2E 3/3 passed at 375, 390, and 1200px. Red/green regressions cover child counts, chunk grouping, usage replay/reset, ARIA progress values, and native keyboard offset calculations. The browser walkthrough below uses an isolated mock-AI server: one root/five children, raw chunked history, and 200k/1M latest context (20%, distinct from older 60% and cumulative 90%). These are RN Web captures, not physical iPhone keyboard proof. Native keyboard geometry tests use the installed controller with simulated native measurements; the iPhone retry remains necessary. Full-reload unsent state follows the existing in-memory session behavior; Back/reopen retains draft and effort. parity-390.webmGenerated with |
|
@codex review |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 66f68541ae
ℹ️ 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".
…in CI Add one bulk getProjectDiffs operation using validated per-project repo-root execution and fixed git argv with external diff/textconv disabled. Preserve checkout errors and truncation per repository so a clean primary cannot mask secondary changes. Render all results in the mobile changes view. Run mobile-check after the required workflow's root static checks because mobile's isolated graph is excluded there. Document matching client/server revisions for the evolving API. Validation: reproduced the old primary-only false-clean UI; mobile checks and root static checks pass; bulk routing/scratch/truncation/error regressions pass; actionlint/zizmor pass. Real disposable two-repository RPC checks also found secondary changes and did not execute the configured external diff helper. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$757.08`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=757.08 -->
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5c1d1e108c
ℹ️ 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".
Preserve the saved-answer recovery action after an admission no-op and retain desktop app goal capability on mobile sends and resumes. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$863.43`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=863.43 -->
Render canonical question options and descriptions with single/multi-select, ordered answer serialization, and explicit Other text. Keep subagents out of the default workspace list while making them selectable through search with their parent label. Validation: five scoped behavior regressions, full form suite, mobile typecheck/lint/format, and iOS/web exports pass. The full mobile suite remains blocked by the separately-owned session fixtures that still use malformed question payloads and the old text-field selectors (80 pass, 1 skip, 1 failing session wrapper). --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high -->
Keep the session recovery assertions on real tool payloads and selectable option controls after structured-question support. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$865.71`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=865.71 -->
Address PRRT_kwDOPxxmWM6f8a4D with lifetime-scoped policy loading and updates, canonical resolved-route restrictions, and fail-closed send/answer/resume gating while retaining model selection and draft access. Validate with mobile-check (88 pass, one real-server test skipped), web export, and iOS Hermes export. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$0.00`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=0.00 -->
Prevent a tool option labeled other from sharing a React key with the implicit custom-answer option. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$869.55`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=869.55 -->
Metro resolves mobile dependencies first, so Expo's transitive Zod 3 shadowed the shared schemas' Zod 4 and crashed before login at .meta(). Declare Zod 4 explicitly and document the resolver boundary. Validation: reproduced blank login in the production export; corrected immutable export passes all three mobile browser E2Es. Mobile checks (88 pass, 1 opt-in skip), iOS export, and root static checks pass. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$877.12`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=877.12 -->
|
@codex review |
Follow-up validation —
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1dce2bb021
ℹ️ 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".
Use the active message model until streaming settles so next-turn model selection cannot relabel current context usage. Keep deleted-file headers readable by falling back to the old-side Git path before hiding diff metadata. Validation: both red regressions reproduced, targeted tests now pass; complete mobile and root static checks pass. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$888.91`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=888.91 -->
Address PRRT_kwDOPxxmWM6f-WZw by consuming config/provider notifications before initial reads, cancelling obsolete snapshots, and gating actions while settings are unavailable. Retain answer recovery when a configuration reload overlaps its completion. Validate with mobile-check (94 pass, one real-server test skipped), web export, and iOS Hermes export. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$11.04`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=11.04 -->
Separate settings failures from transport failures so config refreshes block new AI work without hiding Interrupt for an already-running agent. Retain unavailable-settings answer recovery and existing no-op resume handling. Validate with mobile-check (94 pass, one real-server skip), web/iOS exports, and pending/failed-refresh interruption regression. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$28.71`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=28.71 -->
|
@codex review |
Round-three validation —
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c675587b32
ℹ️ 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".
Derive manual resume from the latest partial assistant tool result while suppressing duplicate starts before stream activity or reconnect. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$24.38`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=24.38 -->
Compute contextWindowTokens from the actual routed request model, built beta header, provider configuration snapshot, and wire format. Keep the numeric capacity on stream state and persist it through live/replayed starts, partials, and final metadata. Fresh attempts and refusal fallbacks get their own capacity; null explicitly means unknown. Regressions cover 1M/ZDR changes, catalog changes, transforming gateways, current resume options versus historical retry preferences, replay/partial lifetime, and schema compatibility. Validation: 267 targeted tests passed; make static-check and production mobile web/iOS exports passed. --- _Generated with [`mux`](https://github.com/coder/mux) • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$13.66`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=13.66 -->
Carry the server pin through active message projection and let the shared token meter use a request-specific limit, including authoritative unknown. Live 1M/privacy/catalog changes and reconnect replay cannot resize an in-flight request; settled turns still use next-send settings. Validation: reproduced active percentage jumping from 20 to 200 and unknown capacity incorrectly borrowing a live limit; targeted token/request/replay/session tests, mobile-check and static-check pass. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$932.21`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=932.21 -->
Consume scoped restore events once into session-owned text, attachment and review drafts. Preserve newer draft versions across sends and serialize restored payloads through the shared message contract. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$32.63`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=32.63 -->
Keep restored review formatting inside the action cleanup boundary, and let content-size events size the input rather than shrinking a newer draft when an older send is acknowledged. Validation: integrated backend/schema/token tests, mobile-check, web/iOS exports and root static-check passed. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$932.21`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=932.21 -->
Capture editable text and review metadata per enqueue call without changing formatted dispatch messages, queued display, or cancellation semantics. Share exact-prefix stripping with desktop editing. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$61.64`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=61.64 -->
Keep restoration coverage intact while using the required complex-array notation and an explicit no-op return. Validation: 137 producer tests, 277 request/schema/token tests, 30 desktop helper tests, 97 mobile tests (1 opt-in skipped), and root static-check pass. --- _Generated with `xum` • Model: `coder:openai/gpt-6-astra` • Thinking: `high` • Cost: `$982.82`_ <!-- mux-attribution: model=coder:openai/gpt-6-astra thinking=high costs=982.82 -->
|
@codex review |
Round-four validation —
|
|
Security review completed. No security issues were found in this pull request. Reviewed commit: Only the user who started this review can view the report in Codex. ℹ️ About Codex security reviews in GitHubThis is an experimental Codex feature. Security reviews are triggered when:
Once complete, Codex will leave suggestions, or a comment if no findings are found. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 81964ab950
ℹ️ 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".
| entry.restoreMessages.push({ | ||
| text: restoreText, | ||
| reviews: reviews?.slice(), | ||
| messageIndex: trimmedMessage.length > 0 ? entry.messages.length : null, |
There was a problem hiding this comment.
Omit invalid reviews from restoration payloads
When muxMetadata.reviews is a malformed array—which SendMessageOptionsSchema permits because metadata is a black box—the catch preserves the text but this still copies the invalid review objects. On interruption, restoreQueueToInput() clears the queue and emits them through RestoreToInputEventSchema, which requires valid ReviewNoteData; output validation can then terminate the subscription after the queued input has already been discarded. Validate/filter the reviews or omit them when formatting fails.
AGENTS.md reference: AGENTS.md:L110-L110
Useful? React with 👍 / 👎.
| const activeMetadata = streamingMessageId | ||
| ? messages.find((message) => message.id === streamingMessageId)?.metadata | ||
| : undefined; | ||
| const model = activeMetadata?.model ?? options?.model ?? "unknown"; |
There was a problem hiding this comment.
Refresh active capacity when a fallback model starts
When a configured refusal fallback swaps models mid-stream, StreamManager updates its model and contextWindowTokens without emitting another stream-start, while usage-delta contains neither field. Fresh evidence beyond the prior picker-change case is that this lookup therefore keeps the refused model's original metadata for usage produced by the fallback, so the mobile context percentage can remain based on the wrong capacity until stream-end; propagate the fallback's model/capacity to the transcript when the swap occurs.
Useful? React with 👍 / 👎.


















Summary
Add an experimental, remote-first React Native mobile companion in
packages/mobile, built with Expo and isolated from the desktop app's dependency graph. This draft covers the complete companion implementation, not only the model-picker refinement.Implementation
Validation
make static-check.Visual evidence
The screenshots and recording below are RN Web validation, not simulator/device evidence.
visible-models-390.webm
Draft status / known limitations
ask_user_questioncurrently uses freeform answers rather than the desktop's full structured multi-select UI.Generated with
mux• Model:coder:openai/gpt-6-astra• Thinking:high• Cost:$428.45