From 16c9c232fcee783c337d244273b409e35b36f4d8 Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Mon, 14 Sep 2026 21:05:25 -0400 Subject: [PATCH] refactor(mobile): ask these call sites for a request port, not a whole client The migration widened seven files from `Pick` to the full `RpcClient` for no reason: a bound operation's `request` takes `UnvalidatedRpcRequestPort`, which is structurally that same single member. Name the port instead, so the signature says what each function actually needs and a caller holding only a port still satisfies it. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb --- .../MobileAgentSessionHistoryPanel.tsx | 4 ++-- mobile/src/dictation/mobile-dictation-setup.ts | 17 +++++++++++------ mobile/src/notifications/push-registration.ts | 4 ++-- .../native-voice-settings-operations.ts | 6 ++++-- .../src/terminal/mobile-terminal-query-reply.ts | 4 ++-- .../terminal-live-accessory-raw-send.ts | 4 ++-- .../terminal/worker-terminal-takeover-report.ts | 4 ++-- 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx b/mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx index 6be4acf29c7..fbe1648fc90 100644 --- a/mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx +++ b/mobile/src/agent-history/MobileAgentSessionHistoryPanel.tsx @@ -16,7 +16,7 @@ import { ChevronLeft, RefreshCw } from 'lucide-react-native' import { colors } from '../theme/mobile-theme' import { useHostClient } from '../transport/client-context' import type { RpcSuccess } from '../transport/types' -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import { readMobileRuntimeHostPlatform } from '../transport/mobile-runtime-host-platform' import { getWorktreeLabel } from '../session/worktree-label' import { @@ -369,7 +369,7 @@ export function MobileAgentSessionHistoryPanel({ const EMPTY_SESSIONS: AiVaultSession[] = [] const EMPTY_ISSUES: { agent: AiVaultSession['agent']; path: string; message: string }[] = [] -async function loadMobileResumeMetadata(client: RpcClient): Promise<{ +async function loadMobileResumeMetadata(client: UnvalidatedRpcRequestPort): Promise<{ repos: MobileAiVaultResumeRepo[] folderWorkspaces: MobileAiVaultResumeFolderWorkspace[] projectGroups: MobileAiVaultResumeProjectGroup[] diff --git a/mobile/src/dictation/mobile-dictation-setup.ts b/mobile/src/dictation/mobile-dictation-setup.ts index 9ac8aae5d21..c9104f82bd7 100644 --- a/mobile/src/dictation/mobile-dictation-setup.ts +++ b/mobile/src/dictation/mobile-dictation-setup.ts @@ -1,5 +1,5 @@ import type { RuntimeSpeechSetupState } from '../../../src/shared/runtime-types' -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import type { RpcResponse } from '../transport/types' import { interpretOrThrowRefusalMessage } from '../transport/rpc-refusal-message' import { LogicalClientCutoverError } from '../transport/stable-logical-rpc-client' @@ -40,7 +40,9 @@ export function isDictationSetupRequiredError(message: string): boolean { return SETUP_REQUIRED_CODES.has(message) || message.startsWith('voice_model_not_ready:') } -export async function fetchDictationSetup(client: RpcClient): Promise { +export async function fetchDictationSetup( + client: UnvalidatedRpcRequestPort +): Promise { const reply = await requestDictationSetupReply(client) if (isLegacyDesktopSpeechSetupReply(reply)) { throw new Error(LEGACY_DESKTOP_SPEECH_SETUP_MESSAGE) @@ -52,7 +54,7 @@ export async function fetchDictationSetup(client: RpcClient): Promise { +async function requestDictationSetupReply(client: UnvalidatedRpcRequestPort): Promise { try { return await dictationSetupRead.request(client, null) } catch (error) { @@ -65,7 +67,10 @@ async function requestDictationSetupReply(client: RpcClient): Promise { +export async function downloadDictationModel( + client: UnvalidatedRpcRequestPort, + modelId: string +): Promise { const reply = await dictationModelDownload.request(client, { modelId }) interpretOrThrowRefusalMessage( () => dictationModelDownload.interpret(reply), @@ -74,7 +79,7 @@ export async function downloadDictationModel(client: RpcClient, modelId: string) } export async function deleteDictationModel( - client: RpcClient, + client: UnvalidatedRpcRequestPort, modelId: string ): Promise { const reply = await dictationModelDelete.request(client, { modelId }) @@ -86,7 +91,7 @@ export async function deleteDictationModel( } export async function setDictationConfig( - client: RpcClient, + client: UnvalidatedRpcRequestPort, params: { enabled?: boolean; modelId?: string; dictationMode?: 'toggle' | 'hold' } ): Promise { const reply = await dictationConfigWrite.request(client, params) diff --git a/mobile/src/notifications/push-registration.ts b/mobile/src/notifications/push-registration.ts index f52e3d88ae6..8aac71108b9 100644 --- a/mobile/src/notifications/push-registration.ts +++ b/mobile/src/notifications/push-registration.ts @@ -13,7 +13,7 @@ import type { MobilePushRegisterResult } from '../../../src/shared/mobile-push-contract' import { NOTIFICATIONS_REMOTE_PUSH_RUNTIME_CAPABILITY } from '../../../src/shared/protocol-version' -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import { startRuntimeCapabilityProbe } from '../transport/runtime-capability-probe' import { pushRouteRegister, pushRouteUnregister } from './mobile-push-registration-operations' import { @@ -26,7 +26,7 @@ import { addPushTokenListener, getDevicePushToken, type MobilePushToken } from ' export const NOTIFICATIONS_REMOTE_PUSH_CAPABILITY = NOTIFICATIONS_REMOTE_PUSH_RUNTIME_CAPABILITY -type PushClient = RpcClient +type PushClient = UnvalidatedRpcRequestPort const REQUEST_TIMEOUT_MS = 5_000 const REMOVAL_TIMEOUT_MS = 2_000 diff --git a/mobile/src/settings/native-voice-settings-operations.ts b/mobile/src/settings/native-voice-settings-operations.ts index b2e05a35831..002203f2916 100644 --- a/mobile/src/settings/native-voice-settings-operations.ts +++ b/mobile/src/settings/native-voice-settings-operations.ts @@ -1,4 +1,4 @@ -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import { fetchDictationSetup, setDictationConfig, @@ -7,7 +7,9 @@ import { } from '../dictation/mobile-dictation-setup' import type { VoiceSettingsOperations } from './voice-settings-operations' -export function nativeVoiceSettingsOperations(client: RpcClient): VoiceSettingsOperations { +export function nativeVoiceSettingsOperations( + client: UnvalidatedRpcRequestPort +): VoiceSettingsOperations { return { load: () => fetchDictationSetup(client), configure: (params) => setDictationConfig(client, params), diff --git a/mobile/src/terminal/mobile-terminal-query-reply.ts b/mobile/src/terminal/mobile-terminal-query-reply.ts index a14a97144e4..2282082c2da 100644 --- a/mobile/src/terminal/mobile-terminal-query-reply.ts +++ b/mobile/src/terminal/mobile-terminal-query-reply.ts @@ -1,5 +1,5 @@ import { isTerminalQueryReply } from '../../../src/shared/terminal-query-reply' -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import { terminalInputSend } from './mobile-terminal-operations' type TerminalSubscriptionRegistry = { @@ -8,7 +8,7 @@ type TerminalSubscriptionRegistry = { type MobileTerminalQueryReplyOptions = { bytes: string - client: RpcClient | null + client: UnvalidatedRpcRequestPort | null clientId: string | null connected: boolean handle: string diff --git a/mobile/src/terminal/terminal-live-accessory-raw-send.ts b/mobile/src/terminal/terminal-live-accessory-raw-send.ts index 2133d1855ac..aed0074e10b 100644 --- a/mobile/src/terminal/terminal-live-accessory-raw-send.ts +++ b/mobile/src/terminal/terminal-live-accessory-raw-send.ts @@ -2,11 +2,11 @@ import { reportWorkerTerminalUserInput } from './worker-terminal-takeover-report import { getTerminalLiveAccessoryRawSendTarget } from './terminal-live-accessory-raw-send-target' import { buildTerminalSendParams, TERMINAL_INPUT_SEND_OPTIONS } from './terminal-send-request' import { terminalInputSend } from './mobile-terminal-operations' -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import type { ConnectionState } from '../transport/types' type TerminalLiveAccessoryRawSendArgs = { - readonly client: RpcClient | null + readonly client: UnvalidatedRpcRequestPort | null readonly targetHandle: string readonly activeHandle: string | null readonly activeSessionTabType: string | null diff --git a/mobile/src/terminal/worker-terminal-takeover-report.ts b/mobile/src/terminal/worker-terminal-takeover-report.ts index 91151123687..cc6579ae48a 100644 --- a/mobile/src/terminal/worker-terminal-takeover-report.ts +++ b/mobile/src/terminal/worker-terminal-takeover-report.ts @@ -1,7 +1,7 @@ -import type { RpcClient } from '../transport/rpc-client' +import type { UnvalidatedRpcRequestPort } from '../transport/unvalidated-rpc-request-port' import { workerTerminalTakeoverReport } from './mobile-terminal-operations' -type ReportClient = RpcClient +type ReportClient = UnvalidatedRpcRequestPort const REPORT_INTERVAL_MS = 30_000 const REPORT_RETRY_DELAY_MS = 250 let reportsByClient = new WeakMap>()