refactor(mobile): read only the rows of a server's workspace list

The desktop no longer sends a freshness flag, so the phone's schema drops it.
The relay capability list names the delegated-devices constant instead of
repeating its literal, which also retires a now-circular type check.

Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
This commit is contained in:
Jinwoo-H
2026-10-11 01:52:32 -04:00
parent 46ff087757
commit 7873c58f4a
5 changed files with 10 additions and 11 deletions
@@ -36,6 +36,7 @@ type Props = {
}
export function MobileFilePreviewScreen({ route }: Props) {
// Why: every workspace screen uses the handoff so it shares the route chunk; else the bundle overruns its asset budget.
const router = useWorkspaceRouteHandoff()
const previewParams = route.ok ? route.params : null
const { client, state: connState } = useWorkspaceClient(previewParams?.hostId)
@@ -76,7 +76,7 @@ function desktop({ hostWorktrees, carriesExecutionHost }: Desktop = {}): FakeSes
const { hostId } = z.object({ hostId: z.string() }).parse(params)
const result = hostWorktrees
? hostWorktrees(hostId)
: { worktrees: [row(`${hostId}-wt`, hostId)], stale: false, fetchedAt: 1 }
: { worktrees: [row(`${hostId}-wt`, hostId)] }
if (result instanceof Error) {
throw result
}
@@ -244,7 +244,7 @@ describe("a desktop's server workspaces on the phone", () => {
hostWorktrees: (hostId) =>
failing && hostId === 'runtime:vm'
? new Error('timed out')
: { worktrees: [row(`${hostId}-wt`, hostId)], stale: false, fetchedAt: 1 }
: { worktrees: [row(`${hostId}-wt`, hostId)] }
})
const screen = await mountScreen(client, RELAYS)
failing = true
@@ -255,7 +255,7 @@ describe("a desktop's server workspaces on the phone", () => {
method === 'mobileRelay.hosts.list'
? reply({ hosts: [HOSTS[1]] })
: method === 'mobileRelay.hosts.worktrees'
? reply({ worktrees: [row('stray', 'runtime:vm')], stale: true, fetchedAt: 1 })
? reply({ worktrees: [row('stray', 'runtime:vm')] })
: reply({ worktrees: [row('mac-wt', 'local')], snapshotId: 's1' })
)
await screen.poll()
@@ -64,10 +64,7 @@ export const relayHostWorktreesRead = bindDeferredRpcOperation(
barrier: 'after-caller-barrier',
read: rpcResultVariant(
'relay-host-worktrees',
z.looseObject({
worktrees: z.array(z.unknown()).nullable(),
stale: z.boolean().optional()
})
z.looseObject({ worktrees: z.array(z.unknown()).nullable() })
)
})
)
@@ -1,11 +1,10 @@
import { z } from 'zod'
import type { RUNTIME_CAPABILITIES } from './protocol-version'
// Why: a paired desktop relays each of its phones to this host as an ordinary phone device it owns.
export const DELEGATED_MOBILE_DEVICE_SYNC_METHOD = 'pairing.delegatedMobileDevice.sync'
// Why: a desktop relays phones only to a host advertising this; `satisfies` ties it to RUNTIME_CAPABILITIES.
// Why: a desktop relays phones only to a host advertising this (via MOBILE_RELAY_RUNTIME_CAPABILITIES).
export const DELEGATED_MOBILE_DEVICES_RUNTIME_CAPABILITY =
'pairing.delegated-mobile-devices.v1' satisfies (typeof RUNTIME_CAPABILITIES)[number]
'pairing.delegated-mobile-devices.v1' as const
export const DELEGATED_MOBILE_DEVICE_SYNC_MAX_PHONES = 32
export const DELEGATED_PHONE_NAME_MAX_CHARS = 128
+3 -1
View File
@@ -1,9 +1,11 @@
import { DELEGATED_MOBILE_DEVICES_RUNTIME_CAPABILITY } from './delegated-mobile-device-contract'
// Why: a phone may put `executionHost` on a request only after its desktop advertises this; an older
// desktop ignores the field and would run the call on itself.
export const MOBILE_DESKTOP_RELAY_RUNTIME_CAPABILITY = 'mobile.desktop-relay.v1' as const
/** A desktop relays a phone to a server that mints delegated phone devices; each side advertises. */
export const MOBILE_RELAY_RUNTIME_CAPABILITIES = [
'pairing.delegated-mobile-devices.v1',
DELEGATED_MOBILE_DEVICES_RUNTIME_CAPABILITY,
MOBILE_DESKTOP_RELAY_RUNTIME_CAPABILITY
] as const