Skip to content

🤖 feat: add an experimental native mobile companion - #4103

Draft
ThomasK33 wants to merge 39 commits into
mainfrom
mobile-app-z0ya
Draft

🤖 feat: add an experimental native mobile companion#4103
ThomasK33 wants to merge 39 commits into
mainfrom
mobile-app-z0ya

Conversation

@ThomasK33

@ThomasK33 ThomasK33 commented Sep 6, 2026

Copy link
Copy Markdown
Member

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

  • Authenticate to an existing Xum server using a typed oRPC WebSocket client; retain reverse-proxy path prefixes and replace the connection explicitly on retry before enabling sends after history replay.
  • Browse/search projects and workspaces, create repository workspaces or scratch chats, and navigate through native-stack conversation, changes, and settings screens. Wide layouts retain the workspace sidebar. Phone search and creation stay in a bottom dock; conversation headers show left-aligned project/server context and grouped navigation actions.
  • Stream assistant text, reasoning, and tool activity; inspect tool input/output, answer questions, interrupt turns, and load older conversation history. Keep drafts and model choices across navigation and reconnects.
  • Inspect read-only Git changes and disconnect through a confirmation flow.
  • Keep the adaptive text input at the very bottom, with separate mode/model controls directly above it and focused native-style pickers. Preserve first-tap and keyboard picker activation without blur-driven layout shifts. Search the full Settings-visible model catalog across providers and gateway routes by model name, provider, or alias; preserve mode/effort on model changes and require explicit confirmation for custom IDs.
  • Store native credentials through Expo SecureStore; keep browser-preview credentials in memory. A fixed-target Node preview proxy supports RN Web development without weakening server Origin checks.
  • Add Make targets, package-local unit/behavior/browser tests, and mobile setup/architecture documentation.

Validation

  • Mobile typecheck, lint, formatting, and 68 passing top-level tests (the opt-in live-server case is excluded from the default run).
  • Root make static-check.
  • Production RN Web export and iOS Hermes bundle export.
  • Browser regressions at 375×812, 390×844, and 1200×900, covering navigation/draft retention, picker actions, resizing, and composer growth/shrink.
  • Separate disposable-server integration verified real authentication, persistence, streaming, and reconnect/replay with deterministic mock model output.
  • Recorded browser dogfooding covered cross-provider selection, hidden-model filtering, custom input, and retention of mode/effort/drafts; no browser errors observed in the final picker walkthrough.

Visual evidence

The screenshots and recording below are RN Web validation, not simulator/device evidence.

All Settings-visible models Search across providers
Native-style model picker with provider groups Searching OpenAI models
visible-models-390.webm

Draft status / known limitations

  • Native device/simulator validation is outstanding. The iOS export verifies bundling, not a native app build or native keyboard, gestures, Keychain, or background/resume behavior.
  • This is a companion to an existing server, not an embedded mobile backend. Xum's process/filesystem/PTY tooling stays on the server.
  • Terminal/VNC, provider administration, and advanced Git editing remain in the main app; mobile Changes is read-only.
  • Provider/model configuration loads with the conversation; live settings synchronization is not added here.
  • ask_user_question currently 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

@mintlify

mintlify Bot commented Sep 6, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
Mux 🟢 Ready View Preview Sep 6, 2026, 3:34 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

@ThomasK33

Copy link
Copy Markdown
Member Author

🤖 Codex-reference navigation and composer polish

Updated in e61d2ecf04aa91935f1c23d0367ff5e23260b505; this PR remains a draft.

  • Phone search/New stay within thumb reach; wide layouts retain top-positioned controls.
  • Conversation headers show project/server context with grouped navigation actions.
  • The input is bottommost, with Plan/model directly above it. It expands for focus/drafts while picker clicks retain browser focus until activation; cancelled drags and keyboard activation behave correctly.
  • Rounded focus indication replaces the browser's inner rectangular outline.

Before / after

Before After
Previous workspace navigation Phone bottom search and create dock
Previous focused composer Corrected bottommost input with controls above
composer-bottom-390.webm

Verification

  • make mobile-check: 68 passing top-level tests, one opt-in integration skipped, 231 assertions; type/lint/format pass.
  • All three browser viewport cases pass (375/390/1200), including control placement, stable pointer-down/click, keyboard activation, search resizing, draft/settings retention and real send/interrupt controls on disposable scratch chats with mock output.
  • Web export, iOS Hermes export and root make static-check pass.
  • Visual checks also cover 375×500; no horizontal overflow, empty-input collapse, first-tap pickers and cancelled pointer drags verified. Final browser diagnostics empty.

The recording is 24.3 seconds. RN Web evidence only: native keyboard/gesture/device validation remains outstanding.


Generated with mux • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $428.45

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 -->
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 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

Mobile parity follow-up

  • Reuse desktop's root-workspace filtering before counts/search, preserving orphan access.
  • Share desktop's adjacent text/reasoning projection so persisted streaming chunks do not become separate accordions or paragraphs. Tool boundaries and authoritative history remain intact.
  • Use Expo SDK 57's keyboard-controller with automatic window offsets across conversation, search, connection, and sheets; preserve the bottommost composer and web focus handling.
  • Show selected effort beside the model and a circular context meter using latest-step usage, provider context limits, and reset/compaction boundaries—not cumulative billing totals.

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.

Root-only workspace list

Merged transcript, XHIGH effort, and context ring

parity-390.webm

Generated with mux • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $713.72

@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

This comment has been minimized.

@chatgpt-codex-connector

This comment has been minimized.

@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: 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".

Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Comment thread packages/mobile/src/settings.ts Outdated
Comment thread packages/mobile/App.tsx
Comment thread Makefile
Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Comment thread packages/mobile/src/screens/ChangesScreen.tsx Outdated
Comment thread packages/mobile/App.tsx Outdated
Comment thread packages/mobile/src/settings.ts
Comment thread packages/mobile/src/settings.ts
…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 -->
@chatgpt-codex-connector

This comment has been minimized.

@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: 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".

Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Comment thread packages/mobile/src/components/Message.tsx Outdated
Comment thread packages/mobile/src/api.ts Outdated
Comment thread packages/mobile/src/settings.ts Outdated
Comment thread packages/mobile/src/screens/Navigator.tsx Outdated
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 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

Follow-up validation — 1dce2bb02

All five review findings are addressed. Production dogfooding also caught a pre-login Zod version mismatch that compilation/unit tests missed; explicitly pinning the shared schema runtime in mobile fixed it.

Gates: make -j1 mobile-check (88 passed, 1 opt-in server test skipped), make static-check, web/iOS exports, and the original three-width browser E2Es pass.

Real-backend checks: clean default root list; search and open a child conversation at 390px/1200px; canonical single/multi-select and Other validation; trimmed answers persisted; send carries allowAgentSetGoal: true; actual mock-stream interruption succeeds during a client policy block.

Controlled transport checks: synthetic started:false retains Resume, with two resume calls but only one answer; both resume payloads retain goal capability. Controlled policy notifications refetch policy, block send/answer/resume for blocked/unavailable/disallowed routes, retain the current banned model visibly, and allow switching to an approved model. These verify client behavior, not a real-server busy race or server-side policy enforcement.

Recorded walkthrough

structured-search-390.webm

Phone and wide layouts

Structured choices and custom answers at 390px

Child conversation reachable through search without cluttering the default list

Resume remains available after a controlled no-op response

Structured questions at 1200px

Limits: physical-iPhone keyboard/native secure-storage confirmation remains outstanding. This round does not claim a successful real-provider resumed reply. All owned UAT browsers/services were stopped; ports 39201/39202/39209 are free. PR remains draft while fresh CI and code/security review run.


Generated with xum • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $878.87

@chatgpt-codex-connector

This comment has been minimized.

@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: 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".

Comment thread packages/mobile/src/useConversation.ts Outdated
Comment thread packages/mobile/src/contextUsage.ts Outdated
Comment thread packages/mobile/src/screens/ChangesScreen.tsx Outdated
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 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

Round-three validation — c675587b3

Addressed live configuration/provider updates, active-stream context capacity, and deleted-file names. Settings refresh failures also preserve Interrupt and the saved-answer resume action while blocking new AI work.

Gates: make -j1 mobile-check (95 passed, 1 opt-in server test skipped), make static-check, web/iOS exports, and all 3 original browser E2Es passed.

Real-backend checks: two deleted files remain identifiable at 390px and 1200px alongside added/modified controls; actual config.saveConfig and providers.setModels notifications refresh the mounted conversation; the next mock send carries updated privacy/context preferences; local policy refresh updates client route guards without losing the draft. One chat subscription and one agent-list load remained throughout recovery testing.

Controlled timing/failure checks: switching the picker during a stream retains its 1M limit (100k tokens = 10%); stream end switches to the next model’s 200k limit (50%). Pending/failed settings snapshots retain usable Interrupt. Saved-answer recovery survives unavailable settings, then retries with updated options without answering twice. Stream timing, snapshot failures, and started:false are controlled transport scenarios—not upstream-provider claims.

Screenshots and recordings

Changes and context walkthrough — 33 seconds:

diff-context-390.webm

Controlled recovery during settings refresh — 27.8 seconds:

controlled-recovery-refresh-390.webm

Deleted files retain distinct names at 390px

Active stream keeps its context capacity despite next-model selection

After stream end the selected model owns context capacity

Deleted filenames at 1200px

Browser error/console collectors were empty. Owned browsers/services are stopped and ports 39201/39202/39209 are free. Physical-iPhone keyboard/storage confirmation remains outstanding. The PR stays draft pending fresh CI and code/security review.


Generated with xum • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $899.71

@chatgpt-codex-connector

This comment has been minimized.

@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: 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".

Comment thread packages/mobile/src/screens/ConversationScreen.tsx Outdated
Comment thread packages/mobile/src/contextUsage.ts
Comment thread packages/mobile/src/transcript.ts
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 -->
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

Round-four validation — 81964ab95

Fixed durable answered-question recovery, queued text/files/reviews on Stop, and request-pinned context capacity. Real UAT additionally found and fixed rendered-review duplication and missing later batched review metadata at the queue producer boundary.

Verification

  • 137 queue/session/review tests using repo-pinned Bun 1.3.5; 277 request/replay/schema/token tests; 30 desktop helper tests; 97 mobile tests passed (1 opt-in test skipped).
  • make static-check, production web/iOS exports, fresh backend build, and all 3 original browser E2Es passed.
  • Real request builder + Anthropic adapter, with a controlled loopback SSE server—not mock-AI or synthetic stream-start events:
    • Actual 1M beta-header request stays pinned across live ZDR/catalog changes and cold reconnect. Later ZDR request pins 200k; explicit unknown remains unknown after a known-model selection.
    • Two reviewed messages queued during one held turn restore as two raw bodies, two images, two notes, and no embedded canonical blocks. A second Stop and navigation retain the whole draft. Explicit resend contains exactly two canonical review blocks, two metadata reviews, and two images. No automatic queued dispatch.
    • Cold persisted answered-partial exposes Resume without another answer form; continuation used zero answer RPCs, one resume RPC, and persisted its reply.
Phone/wide screenshots and recordings

Actual queue/Stop/resend — 39.4 seconds:

two-review-queue-390.webm

Durable answered-question recovery — 54.2 seconds:

durable-resume-390.webm

Actual header-derived 1M request pin and reconnect — 48.9 seconds:

real-request-pin-390.webm

Two reviewed messages restored without rendered-prefix duplication

Resume available after cold replay of an answered partial

Active request capacity remains pinned after a live catalog change

Full restored draft retained at 1200px

Limits: the provider was an owned loopback stub, not an upstream service. Restored drafts remain session-memory scoped, and a restore event lost before consumption is not durable. Physical-iPhone keyboard/storage confirmation remains outstanding. All owned browsers/backend/preview/SSE services are stopped; ports 39201/39202/39209 are free. Run matching client/server revisions to receive the new capacity snapshot. The PR remains draft while fresh CI and code/security review run.


Generated with xum • Model: coder:openai/gpt-6-astra • Thinking: high • Cost: $982.82

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 81964ab950

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@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: 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".

Comment on lines +653 to +656
entry.restoreMessages.push({
text: restoreText,
reviews: reviews?.slice(),
messageIndex: trimmedMessage.length > 0 ? entry.messages.length : null,

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 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 👍 / 👎.

Comment on lines +40 to +43
const activeMetadata = streamingMessageId
? messages.find((message) => message.id === streamingMessageId)?.metadata
: undefined;
const model = activeMetadata?.model ?? options?.model ?? "unknown";

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 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 👍 / 👎.

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