* Support dictation and image attachments in live terminal input mode
- Unify image attachment and voice dictation actions across both live
and buffered terminal input views using a shared action bar.
- Route completed dictations directly to the active PTY (matching
live keystroke semantics) when live mode is active, or append
them to the input field in buffered mode.
- Add live terminal status headers to indicate mic activity and
image upload progress.
- Include unit tests for the dictation routing logic.
* rm unused file
* feat(mobile): add commit failure recovery panel with AI fix action
- Surfaces a "Commit failed" panel with a one-tap AI fix button when a
git commit fails in the source control view or PR creation flow
- Detects commit failures specifically during the committing progress
step and captures staged entries and commit message for context
- Extracts commit failure summary and prompt logic into
`src/shared/source-control-commit-failure.ts` and PR checks prompt
into `src/shared/pr-checks-fix-prompt.ts` so both desktop and mobile
share the same implementations
- Adds auto-find of an available Metro port starting from 8081 and
extracts expo CLI bootstrap into `mobile-expo-cli.mjs` shared by
`start-emulator` and a new `start-expo.mjs` wrapper
* Share source-control AI prompts and simplify mobile PR actions
- Extract conflict, check-fixing, and commit-failure prompt builders
to shared modules for reuse by both desktop and mobile.
- Configure Metro in the mobile package to watch and bundle modules
from the repository-root shared directory.
- Remove the desktop-style merge method picker from the mobile PR
actions panel, opting to use repository defaults automatically.
- Refactor mobile hosted review creation and git preparation logic
into dedicated helper files.
* Implement automated git preparation workflow for mobile PR creation
Introduce a structured hosted review intent preparation workflow to handle
staging, AI commit message generation, committing, and pushing changes
automatically before displaying the pull request composer on mobile.
- Map creation block reasons to descriptive user-facing validation errors
(e.g., dirty working tree, default branch, detached head) to match desktop.
- Decouple hosted-review business logic into a dedicated service helper.
- Update source control runner hooks to handle the new preparation flow.
* Refactor mobile PR creation to run intent and open URL directly
Remove MobilePrComposeSheet and the local compose form, moving instead
to a direct PR creation workflow that matches the desktop experience.
- Add runMobileHostedReviewCreateIntent to handle the full prepare,
push, and create sequence.
- Replace useMobileOpenPrSheetRunner with useMobileCreatePrRunner to
trigger the creation workflow and directly open the created PR URL.
- Simplify state management by removing showPrSheet, prPrefill, and
associated local compose sheets.
* Propagate git status and commit state on PR creation failure
Update `MobileHostedReviewCreateIntentOutcome` and the local change
commit helper to include optional `committed` and `status` fields in
their failure results.
This ensures that if PR preparation fails, callers still receive the
current repository status and know if their local changes have already
been committed.
* Add tests for mobile hosted review creation flow
Introduce unit tests for runMobileHostedReviewCreateIntent to verify
different scenarios of creating a hosted review on mobile, including:
- Successful flow including staging, committing, pushing, and creating
- Eligibility block handling (e.g., authentication requirements)
- Error reporting when creation fails after an automatic commit
* Block mobile PR creation on unresolved conflicts and refresh status
Prevent creating a hosted review on mobile when there are unresolved
merge conflicts. Also, return the latest git status on failures and
reload it in the UI to keep the source control screen in sync.
* Prefer fetched PR head SHA over cached status SHA for PR checks
On mobile, a create command can commit before opening the review,
meaning the fetched PR's head SHA is fresher than the route's cached
status SHA. Prioritizing the fetched PR head SHA ensures we fetch checks
for the most up-to-date commit.
* Fix mobile PR creation errors and validate branch presence
- Reject branch matches when the status branch is null or missing to
prevent PR creation when the branch is lost.
- Display actual PR creation errors in the sidebar instead of silently
ignoring them on failure.
- Trim leading and trailing whitespace from the base branch reference
before persisting the worktree link.
* fix: close mirrored editor tabs on the host so they stop reopening
On web and mobile companions, editor file tabs are mirrored from the
host's runtime-session snapshot, which the host derives from its
authoritative `openFiles`. Closing a mirrored tab only removed it
locally, so the next snapshot re-mirrored the still-open host file and
the tab immediately reopened.
Route the close to the host from the single chokepoint every editor
close funnels through (`store.closeFile`): when the file is mirrored and
a web runtime session is active, send `session.tabs.close` for the host
tab id. The RPC's recorded close-intent suppresses re-mirroring until the
host snapshot catches up, so the local removal is not undone. No-op for
the host's own (non-mirrored) files.
Also fix the desktop `ui:closeSessionTab` handler so a companion-driven
editor close goes through `closeFile` (clears `openFiles`) instead of
`closeUnifiedTab` (tab strip only), which had the same re-mirror bug for
mobile-originated closes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Fix mirrored editor close import cycle
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
Harden mobile session-tab snapshot reconciliation and terminal creation. Rejects stale mobile snapshots, tombstones locally closed tabs until the publisher catches up, rolls back half-created terminal tabs when their surface never appears, and scopes terminal-create idempotency by worktree.
Query the `worktree.show` RPC endpoint on screen focus and poll every
3 seconds to retrieve up-to-date worktree metadata. This ensures that
task-generated names and subsequent displayName updates are reflected,
rather than relying solely on the initial route parameter entry hint.
* fix(mobile): downscale oversized clipboard images so paste no longer fails
Pasting a large clipboard image (high-res screenshot or photo) failed with
'Image too large to paste' because the re-encoded PNG exceeded the 24 MiB
base64 upload cap, with nothing shrinking it first.
Now an oversized image is downscaled to fit the budget before upload:
- computeMobileClipboardImageDownscale() picks target dimensions by area
(~sqrt(budget/actual)), with a bounded retry loop since PNG size is nonlinear.
- prepareMobileClipboardImageBase64() drives the loop with an injected resizer,
so the byte/dimension logic is unit-tested without native modules.
- The resizer stages the image to a temp file and hands ImageManipulator a
file:// URI; the iOS native loader (Data(contentsOf:)) cannot decode large
base64 data URIs, so a data URI made renderAsync throw.
Adds expo-image-manipulator and expo-file-system.
* fix(mobile): fail fast when resized clipboard image has no base64
Empty base64 from saveAsync would pass the downstream base64 check and
upload a corrupt image; throw instead so the paste surfaces an error.
Addresses CodeRabbit review on #5601.
* Fix mobile clipboard image resize cleanup
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
## Summary
- add mobile Settings → Browser → Open terminal links
- route terminal HTTP(S)/OSC 8 link taps to either the streamed Orca browser or the phone browser
- keep existing file-path tap behavior intact
## Verification
- pnpm --dir mobile test
- pnpm --dir mobile lint
- pnpm --dir mobile exec tsc --noEmit
- git diff --check
* release: v1.4.48-rc.0 [rc-slot:2026-06-05-15]
* release: v0.0.1-rc.0 [rc-slot:2026-06-06-03]
* feat(mobile): add terminal text size (zoom) setting
The mobile terminal fits the desktop's full column count to the phone
width with a CSS scale, which cancels out xterm's raw fontSize — so there
was no way to make text bigger or smaller. Add a persisted baseline zoom
multiplier the WebView applies on top of the fit.
- Settings → Terminal → "Text size": 50%–200% presets.
- Pinch-to-zoom in the terminal snaps to the same presets and persists.
- Per-device display preference; does not change the desktop terminal.
- Extracts the xterm WebView HTML into terminal-webview-html.ts to keep
TerminalWebView.tsx within its max-lines budget.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* refactor(mobile): make terminal text size reflow columns instead of CSS scaling
Text size now drives the real xterm fontSize rather than a CSS transform
baseline. A larger cell means fewer columns fit the phone width, so the
existing measure -> terminal.updateViewport pipeline resizes the PTY and the
shell rewraps to the new width (and smaller sizes show more columns). Pinch
still snaps to a preset, but now changes the font size and reflows instead of
scaling pixels; the refit hook re-fits the PTY whenever the scale changes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(mobile): restore terminal touch scrollback (undefined contentWiderThanViewport)
The single-finger touchmove handler gated horizontal panning on
contentWiderThanViewport(), which is never defined — so every one-finger
touchmove threw a ReferenceError before reaching the vertical-scroll code
below it, killing all touch scrolling including scrollback.
Replace the call with the inline overflow check clampPan() already uses
(scrollWidth * getTotalScale() > innerWidth). Vertical scroll now always runs;
two-finger pinch-to-zoom is unaffected. Merged two adjacent var decls to keep
the file under its max-lines cap without a disable.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(mobile): guard terminal text scale viewport refit
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* Add mobile diff review
* Wrap mobile review notes prompt
* Fix mobile review unreviewed navigation
* Clear review completion when a refreshed diff invalidates a reviewed file
mergeMobileDiffReviewState invalidates a file's reviewed flag when its
diff identity changes, but left completedAt set — inconsistent with
markUnreviewed. Drop completedAt on invalidation and add a regression
test.
Co-authored-by: Orca <help@stably.ai>
---------
Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
Co-authored-by: Orca <help@stably.ai>
* Improve mobile session tab scrolling and editor keyboard layout
- Auto-scroll the active session tab into view within the horizontal
tab strip, using a new layout-aware utility with minimal scrolling.
- Use visual viewport measurements in the editor WebView to accurately
report keyboard insets and lift floating controls above the keyboard,
as native events can under-report covered areas.
* Fix active tab scrolling and normalize editor keyboard inset
- Ensure the active session tab is scrolled into view immediately when
its layout finishes to prevent it from remaining hidden off-screen.
- Round, clamp, and validate WebView visualViewport bottom measurements
to avoid rendering inconsistencies from fractional or invalid insets.
- Trigger an immediate keyboard inset report on script initialization.
* Update tabStripOffsetRef when scrolling mobile tab strip
Ensure the cached offset is updated to match the next scroll position. Without this update, subsequent scroll calculations would use stale offset values.