2285f80e8182aa48982fa2c8eb3c31de38ffe2c8
4 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2285f80e81 |
fix(e2e): harden activation-e2e newer flows (issue #104) (#105)
Root-caused directory-picker's directory-row-frontend failure: all four
in-app @gorhom/bottom-sheet sheets (DirectoryBrowserSheet, DirectorySwitcher,
ModelPicker, VariantPicker) provide static percentage snapPoints but rely on
v5's enableDynamicSizing default (true), which never resolves without content
wrapped in a size-reporting component — so useAnimatedDetents() permanently
early-exits and the sheets can never actually open. Set
enableDynamicSizing={false} on all four (they already have explicit
snapPoints, so dynamic sizing was never needed).
variant-picker's chip failure was a stale test assumption: src/lib/
model-selection.ts's chooseModelSelection() deliberately returns null for a
fresh session (issue #37/#35 — the provider registry default is unreliable),
so a brand-new session has no model selected and the reasoning-effort chip
has nothing to key off of. Added testIDs (model-chip, model-option-*) and
updated the flow to explicitly pick a model first, matching real usage.
diff-scroll's missing markdown text: switched src/components/markdown/
Markdown.tsx from react-native-marked's FlatList-based default export to its
useMarkdown() hook rendered into a plain View. The chat screen already nests
this inside its own *inverted* FlatList (one row per message) — a nested
VirtualizedList inside an inverted outer list is a known RN footgun where the
inner content can render at zero height instead of just warning. We already
forced scrollEnabled:false + a large initialNumToRender, defeating
virtualization anyway, so rendering the parsed blocks directly loses nothing.
Extended the existing react-native-marked .d.ts shim (added for a React
18/19 ReactNode mismatch) to also declare useMarkdown/useMarkdownHookOptions.
Added diagnostic screenshots to directory-picker.yaml and diff-scroll.yaml
at the previously-failing steps for faster triage if these regress again.
Closes #104.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
||
|
|
f945cab5c6 |
feat(i18n): extract remaining screens into en/zh-Hans catalogs; full Simplified Chinese coverage (closes #68) (#103)
Extends the i18n infra from #97 (Settings screen only) to the rest of the app: session chat screen, connection add/edit/list screens, sessions list (incl. directory grouping from #96), navigation titles, notifications category metadata, error boundary, telemetry consent modal, auth gate, and every chat UI component (permission/question prompts, status indicator, model/variant pickers, directory switcher/browser, reasoning block, tool call card, session info). - 244 new keys added to en.json/zh-Hans.json with reviewed, natural Simplified Chinese (not machine-garbage), keeping key sets identical. - User content, server URLs, code snippets, log/error-detail text, and diagnostics-classify.ts (pure dependency-free module feeding Sentry/ support reports) are intentionally left untranslated per scope. - Interpolation used for counts/names (e.g. reconnect attempt, files count, connection name in delete confirmations); categoryMeta/ CONNECTION_TYPES switched to labelKey indirection since they're module-level constants evaluated before i18next is guaranteed ready. - Added src/lib/i18n/catalog-parity.test.ts (node --test) asserting en.json/zh-Hans.json expose identical key sets and no empty values, to catch future locale drift. Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
2da0fdf109 |
test: E2E coverage for directory picker, all-sessions, variant picker. Refs #46 #48 #47 #49 #57. (#82)
* test: E2E coverage for directory picker, all-sessions, variant picker Extend the Maestro suite for the features merged into main today: DirectoryBrowserSheet's server-folder picker, the directory-less all-sessions-across-projects list (+ the #46/#48 open-across-project regression), and VariantPicker's reasoning-effort chip. - tests/fixtures/mock-opencode-server.ts: GET /file (directory-scoped via the x-opencode-directory header) with a small fake tree, GET /project for the "Server Projects" section, POST /session honoring the directory header, GET /session/:id (needed to open a session from the all-sessions list), GET /provider variants for VariantPicker, and an optional --seed-sessions mode that pre-populates two sessions across two directories. --fail-auth mode is untouched. - .maestro/flows/directory-picker.yaml, all-sessions.yaml, variant-picker.yaml: three new flows, run in the same emulator session as the existing activation flows. - Additive testIDs on DirectoryBrowserSheet, the "Browse Folders" row, session list rows, the variant chip, and VariantPicker rows. - .github/workflows/activation-e2e.yml: two more mock server instances (4098 seeded, 4099 fresh) and three more maestro test steps. Verified: tsc --noEmit clean, all 108 existing unit tests pass, every new mock endpoint curled against its real shape read from the app code, YAML validated. No Android emulator available locally to run the Maestro flows themselves. * test(mock): enforce per-directory session scoping so #46/#48 coverage can fail Review finding (HIGH): GET /session/:id and /session/:id/message ignored x-opencode-directory, so all-sessions.yaml could not fail if the directory threading fix regressed. The mock now mirrors the real server's per-directory workspace scoping: - GET /session/:id and GET /session/:id/message 404 unless the request's x-opencode-directory (or DEFAULT_DIRECTORY when absent) matches the stored session's directory. - GET /session without ?roots=true is scoped to the request's directory; loadSessions()'s directory-less roots=true call still returns everything. - Document the port-4099 shared-state coupling between directory-picker and variant-picker flows, and why all-sessions.yaml now has teeth (flow comment). Curl-verified: correct header 200, wrong/no header 404, scoped vs roots listing, create-then-open paths for all three flows, --fail-auth untouched. tsc clean, 108/108 unit tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NJKAQ6HAikWGQK7PGZ5Y4E * fix(e2e): widen connect-handshake wait past client's own 30s timeout Run 29546383612 (7cbd3a6, first real emulator execution of these flows) failed on activation-positive.yaml: "Assert that id: connection-status-dot is visible" timed out after the flow's 20s extendedWaitUntil, right after tapOn connect-submit-button. The mock server itself is fast (verified locally: health + project/current + path respond in ~30ms total), so this isn't a mock fidelity gap. But Quick Connect's testConnection()/addConnection() path chains up to 3 fetches (health, then project.current + path.get in parallel), and each individual fetch is capped by src/lib/sdk.ts REQUEST_TIMEOUT_MS = 30_000 — strictly longer than the 20s the flow was willing to wait. A first-attempt emulator-to-host (10.0.2.2) connection that's merely slow to establish, rather than outright failing, would blow past the test's wait before the app's own client-side timeout even fires. Bump the connect -> connection-status-dot / "Connection Failed" waits from 20000 to 40000 across all 5 flows that share this pattern (activation-positive, activation-negative-401, all-sessions, directory-picker, variant-picker) so the wait is never shorter than the code path it's gating on. Assertions are unchanged — still requires the real dot / real error text, just with a timeout that isn't racing the client. Verified locally: typecheck clean, all 108 unit tests pass, YAML parses, mock server confirmed fast under direct curl. Emulator behavior itself (whether 40s consistently clears it) is unverified until the next CI run. * fix(e2e): use adb reverse + 127.0.0.1 instead of 10.0.2.2; capture logcat/maestro debug Root cause of the activation-e2e failure (connect step timed out, ~0 requests reaching the mock): the 10.0.2.2 host alias is unreliable under the headless emulator-runner — the app's http://10.0.2.2:4096/global/health never completed, so connection-status-dot never rendered. - run-e2e-flows.sh: single script (fixes cd-per-line fragility) that adb-reverses each mock port (4096-4099) into the emulator's localhost, runs every flow with --debug-output, and dumps logcat on exit. - All flows now connect to 127.0.0.1:<port> (the adb reverse target). - Upload maestro-debug (UI hierarchy on failure) + logcat as artifacts so future failures are diagnosable instead of blind. * fix(e2e): connect via 127.0.0.1:PORT in IP field, stop typing into port input Root cause of every activation-e2e connect failure (proven by the app's own logcat diagnostic: '[diag] probe start http://127.0.0.1:40966 ... server unreachable'): the port field defaults to useState("4096"), and the flow's eraseText + inputText "4096" raced the controlled number-pad input, leaving "40966" — nothing listens there, so connect always failed. This was never a 10.0.2.2 / adb reverse issue. Fix: buildUrl already extracts host:port from the IP field, so enter 127.0.0.1:<port> there and remove the flaky port-field steps entirely. pastedPort overrides the default port state, so each flow's port is deterministic (4096 positive / 4097 negative / 4098 all-sessions / 4099 directory+variant). --------- Co-authored-by: engineer <engineer@gray-knight-m1.local> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
c1736bd426 |
feat: add reasoning effort picker to session screen (#47) (#51)
* 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> |