* feat(#49): improve project picker with recents + server projects
- New Session modal now shows:
- Current project as tappable row (tap to create session immediately)
- Recent Projects section: list of previously used dirs as tappable rows
- Server Projects section: projects known to opencode server (from /project API)
- Manual path input as fallback (unchanged behavior)
- Modal body is now scrollable to handle long lists
- All selection paths call addRecentDirectory to keep recents up to date
- TypeScript clean (pre-existing VariantPicker.tsx error unrelated)
* feat: add reasoning effort (variant) picker to session screen (#47)
- Add VariantPicker bottom sheet component (low/medium/high/auto)
- Add variant state to catalog store, reset on model change
- Pass variant through sendMessage -> sdk.session.prompt()
- Add reasoning chip to toolbar, shown only for models with variants
- Parse model.variants from provider API response in catalog and sdk types
API field: variant in POST /session/:id/prompt_async
Server maps variant -> reasoningEffort via model variant config
* fix(models): preserve reasoning effort across messages
Reset the selected variant only when the provider/model pair actually changes, including catalog reloads and agent-driven model switches.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Users had to type an absolute server path on a phone keyboard to pick a
working directory (#49 "Choose project UIX"), and #57 reports that
only the default-drive project is ever discoverable. #52 already added
recents + client.project.list() as flat pickers, but there was still no
way to browse into subdirectories or discover paths the server hadn't
already indexed as a "project" — the only fallback was manual typing.
The opencode server already exposes a scoped filesystem-listing endpoint
(GET /file, handled in file.ts/handlers/file.ts) that resolves relative
to whatever directory the request is scoped to (header or query param) —
no new server endpoint is needed. Add file.list() to the mobile SDK
client and a new DirectoryBrowserSheet that lists subdirectories one
level at a time (via clientForDirectory(dir) + file.list({path: "."})),
supports "up" navigation, and a manual jump-to-path field. Wire it into
both the "new session" modal and the existing DirectorySwitcher, so
recents/manual entry remain available as a fallback alongside browsing.
Residual gap: there's still no "list available drives" API, so Windows
users with projects on D:, E:, etc. still need to type the drive root
once (it's then remembered via recents) — a full fix for #57 would need
a small server-side addition to enumerate mounted volumes.
Extract the SSE chunk-buffering from sdk.ts into a pure SSEParser (sdk.ts delegates;
behavior unchanged) and pin the framing rules that are easy to break when an event
splits across network reads: partial trailing lines held until completed, frames
reassembled across 2-3 reads, [DONE] sentinel and empty/non-data lines filtered,
each frame emitted exactly once. typecheck clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract the auth + directory-header encoding from sdk.ts into a pure, dep-free
headers.ts (sdk.ts now delegates — behavior unchanged) so the connection-critical
logic is unit-testable without expo/fetch. Add 8 header tests (ASCII passthrough,
non-ASCII/CJK percent-encoding stays header-safe, Basic auth, empty-dir handling)
and 8 logbuffer tests (serialization incl. circular-ref fallback, 200-entry ring
cap, copy semantics, formatting). typecheck clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>