Repository navigation
Conversation
(cherry picked from commit 2bf857a)
|
@AmethystLiang three small web-client/orcad fixes from running the orcad-served webapp headless:
Each branch is off current main and self-contained. Refs the template's issue-linking requirement: #2 links #18504; #1 relates to #13201; #3 has no matching issue yet - happy to file one if preferred. |
📝 WalkthroughWalkthroughThe web mobile API now forwards supported mobile operations to runtime RPCs instead of returning fixed empty or unavailable results. It obtains host status through the Priority: ⬇️ Low Merge Risk: 🟠 High · up to The web app cannot typecheck and build, and the paired web client cannot reach the new mobile host operations. The web build and mobile pairing/device workflows are not ready to merge. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
ℹ️ Review info
⚙️ Run configuration
- Configuration used: Repository UI
- Review profile: CHILL
- Plan: Advanced
- Run ID:
a5c6f3bc-6064-49ee-a643-7b09a02aac8e
📒 Files selected for processing (1)
src/renderer/src/web/preload-api/web-mobile-api.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 8 remain after this review.
| import type { MobileHostStatus } from '../../../../shared/mobile-pairing-rpc-contract' | ||
| import { callRuntimeResult } from './web-runtime-calls' |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
find src -iname '*mobile*pairing*contract*' -o -iname '*mobile*host*status*'
rg -n 'mobile-pairing-rpc-contract|include|paths|tc:web' tsconfig*.json src/renderer package.jsonRepository: stablyai/orca
Length of output: 45651
🏁 Script executed:
set -eu
HEAD=bed4ec0991780702a87a3f77a2ea980bed75dbff
printf '%s\n' '--- reviewed head and target file ---'
git rev-parse --verify "$HEAD^{commit}"
git show "$HEAD:src/renderer/src/web/preload-api/web-mobile-api.ts" | nl -ba | sed -n '1,240p'
printf '%s\n' '--- exact MobileHostStatus references at reviewed head ---'
git grep -n -F -- "$HEAD" MobileHostStatus 2>/dev/null || :
git grep -n -F "$HEAD" -- 'mobile-pairing-rpc-contract' 2>/dev/null || :
printf '%s\n' '--- candidate declarations and path files ---'
git ls-tree -r --name-only "$HEAD" | grep -E '(^|/)(mobile-pairing-rpc-contract|tsconfig[^/]*\.json|package\.json|vite[^/]*|webpack[^/]*)$' || :
for f in tsconfig.json tsconfig.web.json tsconfig.renderer.json package.json; do
if git cat-file -e "$HEAD:$f" 2>/dev/null; then
printf '%s\n' "--- $f ---"
git show "$HEAD:$f" | nl -ba | sed -n '1,180p'
fi
done
printf '%s\n' '--- web-mobile-api references and web entrypoints ---'
git grep -n -F "$HEAD" -- 'web-mobile-api' 'createWebMobileApi' 'preload-api' 2>/dev/null | sed -n '1,240p'Repository: stablyai/orca
Length of output: 28535
🏁 Script executed:
set -eu
HEAD=bed4ec0991780702a87a3f77a2ea980bed75dbff
printf '%s\n' '--- all mobile pairing files at reviewed head ---'
git ls-tree -r --name-only "$HEAD" | grep -Ei 'mobile|pairing|rpc-contract' | grep -E '(^|/)([^/]*(mobile|pairing|rpc)[^/]*)\.(ts|tsx|json|mjs|mts)$' | sed -n '1,240p'
printf '%s\n' '--- exact symbol and import references ---'
git grep -n -F 'MobileHostStatus' "$HEAD" -- ':!pnpm-lock.yaml' ':!*.map' || :
git grep -n -F 'mobile-pairing-rpc-contract' "$HEAD" -- ':!pnpm-lock.yaml' ':!*.map' || :
printf '%s\n' '--- resolved relative-import candidates ---'
for p in \
src/shared/mobile-pairing-rpc-contract.ts \
src/shared/mobile-pairing-rpc-contract.tsx \
src/shared/mobile-pairing-rpc-contract/index.ts \
src/shared/mobile-pairing-rpc-contract.mts \
src/shared/mobile-pairing-rpc-contract.d.ts
do
if git cat-file -e "$HEAD:$p" 2>/dev/null; then
printf '%s\n' "--- $p ---"
git show "$HEAD:$p" | nl -ba | sed -n '1,180p'
fi
done
printf '%s\n' '--- web typecheck configs ---'
for p in config/tsconfig.tc.web.json config/tsconfig.web.json vite.web.config.ts config/scripts/project-renderer-web-client.mjs config/scripts/run-vite-web-build.mjs config/scripts/verify-web-build.mjs; do
if git cat-file -e "$HEAD:$p" 2>/dev/null; then
printf '%s\n' "--- $p ---"
git show "$HEAD:$p" | nl -ba | sed -n '1,260p'
fi
done
printf '%s\n' '--- target-file references in source/config ---'
git grep -n -F 'createWebMobileApi' "$HEAD" -- ':!pnpm-lock.yaml' ':!*.map' || :
git grep -n -F 'web-mobile-api' "$HEAD" -- ':!pnpm-lock.yaml' ':!*.map' || :
git grep -n -F 'src/renderer/src/web' "$HEAD" -- '*.json' '*.ts' '*.tsx' '*.mjs' '*.js' || :Repository: stablyai/orca
Length of output: 35108
🏁 Script executed:
set -eu
HEAD=bed4ec0991780702a87a3f77a2ea980bed75dbff
for p in src/renderer/web-index.html src/renderer/src/web/main.tsx src/renderer/src/web/web-preload-api.ts; do
printf '%s\n' "--- $p ---"
git show "$HEAD:$p" | nl -ba | grep -E 'web-preload-api|script|createWebMobileApi|export|from ' | sed -n '1,120p'
doneRepository: stablyai/orca
Length of output: 4633
Add the missing MobileHostStatus contract.
The relative import has no target in the reviewed tree. The web typecheck includes this file, and the web entrypoint imports it through web-preload-api.ts. This unresolved module blocks the web typecheck and build. Add the checked-in contract or update the import to the actual contract path.
| const hostStatus = () => callRuntimeResult<MobileHostStatus>('mobile.hostStatus') | ||
| return { | ||
| mobile: { | ||
| listNetworkInterfaces: () => Promise.resolve({ interfaces: [] }), | ||
| getPairingQR: () => Promise.resolve({ available: false }), | ||
| listNetworkInterfaces: () => callRuntimeResult('mobile.listNetworkInterfaces'), | ||
| getPairingQR: (args) => callRuntimeResult('mobile.getPairingQR', args), | ||
| getWindowsFirewallStatus: () => Promise.resolve({ supported: false }), | ||
| repairWindowsFirewall: () => Promise.resolve({ ok: false, reason: 'unsupported' }), | ||
| openWindowsNetworkSettings: () => Promise.resolve(false), | ||
| getRuntimePairingUrl: () => Promise.resolve({ available: false }), | ||
| listDevices: () => Promise.resolve({ devices: [] }), | ||
| revokeDevice: () => Promise.resolve({ revoked: false }), | ||
| getRuntimePairingUrl: (args) => callRuntimeResult('mobile.getRuntimePairingUrl', args), | ||
| listDevices: () => callRuntimeResult('mobile.listDevices'), | ||
| revokeDevice: (args) => callRuntimeResult('mobile.revokeDevice', args), |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
rg -n 'register.*mobile|MOBILE_WEB_BUNDLE_METHODS|mobile\.(hostStatus|listNetworkInterfaces|getPairingQR|getRuntimePairingUrl|listDevices|revokeDevice)' src/main/runtime src/main
sed -n '1,140p' src/main/runtime/rpc/methods/index.ts
sed -n '1,240p' src/main/runtime/runtime-rpc/runtime-rpc-mobile-method-allowlist.tsRepository: stablyai/orca
Length of output: 15743
🏁 Script executed:
set -o pipefail
printf '%s\n' '--- changed web API ---'
nl -ba src/renderer/src/web/preload-api/web-mobile-api.ts | sed -n '1,90p'
printf '%s\n' '--- runtime call dispatch ---'
rg -n -F --glob '*.ts' -- 'callRuntimeResult' src/renderer/src/web src/main src/preload
rg -n -F --glob '*.ts' -- 'new RpcDispatcher' src/main/runtime src/main/startup
printf '%s\n' '--- runtime registration assembly ---'
rg -n -F --glob '*.ts' -- 'ALL_RPC_METHODS' src/main
rg -n -F --glob '*.ts' -- 'MOBILE_WEB_BUNDLE_METHODS' src/main/runtime
rg -n -F --glob '*.ts' -- 'registerMobileHandlers' src/main
printf '%s\n' '--- relevant runtime and IPC definitions ---'
nl -ba src/renderer/src/web/preload-api/web-runtime-calls.ts | sed -n '1,115p'
nl -ba src/main/runtime/rpc/methods/mobile-web-bundle.ts | sed -n '145,190p'
nl -ba src/main/startup/main-process-runtime-launch.ts | sed -n '1,100p'
nl -ba src/main/ipc/mobile.ts | sed -n '50,90p'
nl -ba src/main/ipc/mobile.ts | sed -n '240,275p'Repository: stablyai/orca
Length of output: 41651
🏁 Script executed:
set -o pipefail
printf '%s\n' '--- runtime server registration ---'
rg -n -F --glob '*.ts' -- 'ALL_RPC_METHODS' src/main/runtime src/main/startup
rg -n -F --glob '*.ts' -- 'new RpcDispatcher' src/main/runtime src/main
rg -n -F --glob '*.ts' -- 'methods:' src/main/runtime/runtime-rpc src/main/runtime | head -40
printf '%s\n' '--- web mobile API consumer ---'
rg -n -F --glob '*.ts' -- 'createWebMobileApi' src/renderer src/main src/preload
printf '%s\n' '--- runtime server constructor ---'
rg -n -F --glob '*.ts' -- 'class OrcaRuntimeRpcServer' src/main/runtimeRepository: stablyai/orca
Length of output: 41186
Register the mobile methods on the runtime RPC boundary.
createWebMobileApi is included in web-preload-api.ts, so paired web clients can invoke all six methods. Those calls use callRuntimeResult, but the production dispatcher defaults to ALL_RPC_METHODS, which contains no matching mobile methods. registerMobileHandlers only creates mobile:* Electron IPC handlers. The paired web calls therefore fail before reaching the existing host logic. Add runtime registrations for all six methods and preserve their current arguments and result shapes.
ELI5
The web client's mobile pane was fake: every call (
getPairingQR,listDevices, …) returned hardcoded empty answers, so a browser paired to a headless orcad could never mint a pairing QR and showed a misleading "WebSocket transport is not running" toast even while the transport was healthy.What Changed
getPairingQR,getRuntimePairingUrl,listNetworkInterfaces,listDevices,revokeDevicethroughcallRuntimeResultto the host'smobile.*RPCs (already registered and exercised on orcad).isWebSocketReady/getRelayStatusnow derive frommobile.hostStatus(webSocketEndpoint,relayAvailable) instead of constants and local state.Before: paired web client →
window.api.mobilestubs →available: falsealways. After: the same calls answer from the live host over the runtime WebSocket.Why
The
mobile.*RPC surface already exists on the host (registered in orcad-entry); the web client just never called it. Delegating 1:1 is the smallest change and keeps the desktopwindow.api.mobile.*shape, so no callers branch.mobile.hostStatusis the single source of truth for transport/relay facts a remote client can actually observe.Linked Issue
Fixes part of #18504 (headless serve cannot complete mobile pairing - this removes the web-client-side stub failure mode; host-side items in that issue are separate).
Visual Proof
N/A for the diff itself (no styling change). Behavioral before/after: before, the Mobile pane on a web session always showed the pairing fallback with a "WebSocket transport is not running" toast; after, it renders the live QR/device list from the host. Happy to attach captures if useful.
Testing
pnpm tc:webclean.orcadand probedmobile.hostStatus/mobile.listNetworkInterfacesover the same WebSocket path the web client uses - all answer correctly; QR mints in the Mobile pane.mobile.*methods: the calls surface transport errors rather than wrong answers - mixed-version pairing already requires a host new enough to register the surface.AI Disclosure
Authored with an AI coding agent (GLM via Maki); human reviewed and verified the diff.
Review
Agent skill upstream boundary
Notes
Security: no new surface - calls go to already-authenticated runtime RPCs on the paired WS. Cross-platform: Windows firewall stubs intentionally unchanged (desktop-only concern). Remote/SSH: this is the paired-web-client path. Backwards compatibility: additive client behavior; hosts without the RPCs were already unable to serve mobile pairing from the web. Performance: one RPC per call, same as desktop IPC cost.
Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)