Extract platform-neutral client logic into @bb/client-core - #1986
Merged
Conversation
This was referenced Aug 20, 2026
Move the pure, DOM-free pieces of the web app (route paths, sidebar grouping/ordering/read state, prompt drafts and mention triggers, timeline merge/paging helpers, thread activity/runtime status, fixed-panel tab state, file-preview and localhost-link policy, terminal websocket transport, API types) into a new `packages/client-core` workspace package so a native client can share them with `apps/app`. Every moved module keeps a one-line re-export shim at its old path in `apps/app`, so web behavior and imports are unchanged; the moved tests now run under `@bb/client-core`, plus a guard test that the package never touches DOM globals. `apps/app` gains the `@bb/client-core` dependency. Co-Authored-By: Claude <noreply@anthropic.com>
SawyerHood
force-pushed
the
bb-mobile-1-client-core
branch
from
August 20, 2026 01:07
f1df923 to
536bdda
Compare
There was a problem hiding this comment.
🚨 SLOP COP 🚨 · review
Plain-English summary: This pull request moves shared client rules into a new package. Mobile and web clients can then use the same rules.
I am SlopCop, and I have started the review. I will check security, code quality, performance, architecture, duplicate code, and the main user path.
I will post one final review after these checks finish.
- TerminalWebSocketTransport.start() now records `started` before the suspended early-return, so suspend() -> start() -> resume() opens the socket instead of leaving the transport idle forever (the mobile terminal hit this when the app backgrounded before the WebView posted "ready"). Test added for that ordering. - The no-dom guard now also catches `globalThis.<global>`, `self.<global>`, optional chaining, `as Window`, and bare location/history/matchMedia/ requestAnimationFrame references. Co-Authored-By: Claude <noreply@anthropic.com>
SawyerHood
marked this pull request as ready for review
August 20, 2026 02:49
SawyerHood
added a commit
that referenced
this pull request
Aug 20, 2026
Stack layer 2 of 4 for the bb mobile app (stack #1990). Prerequisite: #1986 (`@bb/client-core`). Next layer: #1988 (the app). ## What was wrong A native client needs a few small, additive pieces the server, cloud, SDK, and test harness do not have today: a way to tell the server it is a mobile client, SDK types that survive React Native's global `Response`/`FormData` declarations, a shared contract for the two plugin-rendered pending interactions so the phone can render them natively, a deterministic approval path in the fake provider for e2e, a harness that can run on a fixed port behind a stub gate, a way to mint a connect pairing code for a phone, and app-link association files so universal links can work. ## What changed - `packages/config` + `apps/server`: request-side `RequestAppSurface` (`desktop | web | mobile`) for `x-bb-app-surface` + telemetry; the server config union stays `desktop | web`. Test added. - `packages/sdk`: `SdkResponseLike` structural constraint in `response.ts`/`transport.ts` (Hono client responses stay assignable under RN globals); `projects.sidebarBootstrap()`; public-types test updates. - New `packages/plugin-interaction-contracts`: the ask-user-question and secret-request payload/resolution schemas moved from the two plugins' private `contracts.ts`; both plugins re-export them (their tests unchanged). - `packages/agent-runtime` fake provider: `approve:<kind>` control token (`command | file_change | permission_grant | plan`) emits an approval interactive request; adapter decodes/encodes approval payloads; 5 tests. - `tests/integration`: harness `serverPort`/`bindHost` options; `mobile-e2e/backend.ts` (seeded long-lived harness) and `connect-stub.ts` (TLS stub gate in front of the harness) + scripts + turbo tasks. - `plugins/connect`: "Add mobile device" QR/code in Settings → Remote access and `bb connect machine-code [--json]` (uses the existing `createMachineCode` RPC; 409 machine-limit surfaced). Guide template, bb-cli SKILL, `docs/multiple-devices.md`, `docs/configuration.md` pairing section updated per `docs/cli-guide-and-skill.md`. - **Hidden behind the new `mobileApp` experiment** (off by default; Settings → Experiments → "Mobile app", or `bb settings experiment mobileApp true`) until the app is generally available. `@bb/domain` gains the key; the connect plugin reads it through its loopback SDK (`bb.sdk.system.config()`) on every call — a new `mobilePairing` rpc tells the panel whether to render the section, and `createMachineCode` / `bb connect machine-code` refuse with a pointer to the toggle. No new plugin-SDK API. With the experiment off, a paired install sees no visual change from this PR. - `packages/connect-client`: pairing helpers used by the phone. - `apps/connect` (gate) + `apps/web` (apex) + `packages/connect-db`: serve `/.well-known/apple-app-site-association` and `/.well-known/assetlinks.json` before the session gate (static JSON only; Android fingerprints from `ASSETLINKS_SHA256_FINGERPRINTS`, empty if unset). No auth change. No daemon contract change → `HOST_DAEMON_PROTOCOL_VERSION` untouched. ## How you verified - `pnpm exec turbo run typecheck lint` for config, server, sdk, plugin-interaction-contracts, ask-user-question, secrets, connect plugin, agent-runtime, integration-tests, connect-client, templates, @bb/connect, @bb/web, connect-db, cli — pass (the only failure is the pre-existing `conversation-outline-parity.test.ts` typecheck on main from #1657). - Tests: sdk 96, agent-runtime 413, connect plugin 88, templates 43, connect/connect-db/connect-client, server telemetry + public route tests (342), `@bb/integration-tests test:smoke` 28 — all pass. Part of the bb mobile app plan (`plans/bb-mobile-expo.md`, lands in #1988). > AGENT GENERATED: by Claude Opus 5 --------- Co-authored-by: Claude <noreply@anthropic.com>
SawyerHood
added a commit
that referenced
this pull request
Aug 20, 2026
Stack layer 3 of 4 for the bb mobile app (stack #1990). Prerequisites: #1986 (`@bb/client-core`) and #1987 (core prep). Next layer: #1989 (push notifications). ## What was wrong bb has no native phone client. The PWA works on a phone but is bounded by mobile-web limits (keyboard/viewport hacks, no push, no background reconnect, no secure credential storage, no camera/photo attachments, WebKit style-recalc stalls). Plan, decisions, and research: `plans/bb-mobile-expo.md`, `plans/bb-mobile-research/`; execution log with per-phase verification: `plans/bb-mobile-progress.md`. ## What changed New `apps/mobile` (`@bb/mobile`, Expo SDK 57 / React Native 0.86 / Expo Router / NativeWind v5, iOS first; ~81k lines of app code, ~20k of unit tests, 26 Maestro flows). Everything else in this PR is toolchain/docs; no server or web behavior changes. - Connectivity: server profiles in SecureStore; Direct mode (LAN / Tailscale / simulator) and bb connect (machine enrollment by QR/code → desktop-session cookie in the native jar, renewal, re-pair); per-profile SDK + realtime manager (ping/pong, watermark reconnect, AppState suspend/resume) + QueryClient with realtime invalidation; global mutation error toasts. - Screens: drawer sidebar + home thread list (organize/sort, pinned, unread glyphs, long-press actions), search, archived, compose with pickers (project, provider, model+reasoning, permission mode, service tier, environment incl. reuse/worktree/branch/path, machine), new project + project settings + machine setup, thread detail (FlashList timeline with every row kind via a renderer registry, native markdown, native diffs, ANSI, lightbox, unread divider, ToC, prompt-stack cards), prompt area (composer with mentions/typeahead/attachments/voice/drafts, send/queue/steer/stop, queued messages, pending-interaction banner incl. approvals, questions, ask-user-question and secret-request forms, context banner with git/PR/parent/children, message/thread/git action sheets, fork/handoff), workspace panel (Info, Diff, Files + previews, terminal = bundled xterm WebView with RN-owned socket + accessory bar, synced thread tabs), settings (general, appearance palettes from `theme.css`, experiments, providers, usage, machines list/detail/add, updates, plugins management + marketplaces, skills library/registry, haptics), deep links (`bb://`, universal link mapping, thread-open signal), outbound share. - Design system: generated native theme tokens (`scripts/generate-native-theme.ts` from `theme.css`, drift-tested), primitives (sheets, action sheets, toasts, etc.), Inter + Fira Code, hugeicons. - Toolchain: Metro resolves `@bb/*` from TS source (`source` condition scoped to workspace packages), `pnpm patch` for `expo-modules-jsi@57.0.4` on Xcode 26.2, scoped `lightningcss` override for NativeWind v5, turbo/eslint/prettier wiring, `.github/workflows/mobile-e2e.yml` (label `mobile-e2e` / nightly; Release build + Maestro) and `mobile-runner-probe.yml`, `eas.json` profiles, docs (`docs/platform-support.md`, `docs/repository-overview.md`). - Early access: the bb-side pairing surfaces (Settings → Remote access → Add mobile device, `bb connect machine-code`) are behind the `mobileApp` experiment from #1987; the app's own Settings → Experiments screen lists that toggle too (it is shared server state). - Not in this layer: push notifications (#1989). Not yet: Android, plugin frontends (SPA-in-WebView planned), inbound share (needs a native rebuild), TestFlight (needs an EAS account). ## How you verified - `pnpm exec turbo run typecheck lint test --filter=@bb/mobile` — 794 tests / 117 files, 0 lint findings. - Every phase was built by parallel agents and independently re-verified; the full Maestro regression (26 flows) passed on the iPhone 17 Pro simulator (iOS 26.3) against the seeded harness backend (`tests/integration/mobile-e2e/backend.ts`) and the connect stub gate; results table and screenshots list in `plans/bb-mobile-progress.md`. Connect enrollment was also exercised against the real `bee.getbb.app`. - On this layer specifically (no push): `phase1-shell`, `phase4b-send`, `phase5-links` flows re-run and pass. - Known gap carried in the log: on bb connect profiles the left-edge drawer swipe can also press the home row under the touch (Direct profiles are fine). > AGENT GENERATED: by Claude Opus 5 --------- Co-authored-by: Claude <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack layer 1 of 4 for the bb mobile app (stack #1990). No prerequisite; the next layer is #1987.
What was wrong
The native mobile app (
apps/mobile, layer 3) needs the web app's platform-neutral client logic — sidebar grouping and sorting, thread read state, prompt draft and submission policy, mention triggers, timeline merge/paging helpers, renderable-patch rules, the terminal WebSocket transport, panel tab schemas, file preview, localhost link rewriting, route builders. Today these live insideapps/app/srcnext to DOM and react-router code, so a React Native app cannot import them.What changed
packages/client-core(@bb/client-core): the pure modules moved out ofapps/appunchanged, plus atest/no-dom.test.tsguard that walkssrc/**and fails onwindow/document/localStorage/navigator/react-router/@/references.apps/app: every old path is a one-line re-export shim, so web imports and tests keep working; the few files that mixed DOM and pure code (route-paths.ts,fixed-panel-tabs-state.ts,useThreadTimelineController.ts,localhost-link-rewrite-preference.ts,terminal-websocket-url.ts,TimelineFileDiffBlock.tsx,secondaryPanelTabState.ts) keep the web-only parts and import the rest from client-core. 19 tests moved with their modules.TerminalWebSocketTransporttreats an undefinedsocket.bufferedAmountas 0 (React Native's WebSocket never sets it), with a regression test.@bb/client-coredepends on@bb/domain,@bb/server-contract,@bb/core-ui,@bb/thread-view,@bb/fuzzy-match,@bb/desktop-contract(pure),zod. No React.No behavior change in the web app is intended.
How you verified
pnpm exec turbo run typecheck lint test --filter=@bb/client-core --filter=@bb/app— client-core 236 tests, app 2955 tests / 392 files, lint 0 errors (the 144 warnings pre-exist on main).packages/client-core/test/no-dom.test.tsguards the DOM-free rule; the transport test fails without thebufferedAmountfix.Part of the bb mobile app plan (
plans/bb-mobile-expo.md, lands in #1988).