mirror of
https://github.com/stablyai/orca.git
synced 2026-09-24 00:02:24 +00:00
fix(mobile): let runRpcOperation send a params-less method
A3 declares `mobileWeb.bundle.manifest` with `params: null`, so the generated catalog types its send params as `void` and the two call sites that pass an explicit `null` stopped compiling. `bindDeferredRpcOperation.request` already solved this: `RpcSendArguments` admits `null` exactly where the catalog declares no params, because `params: null` is not the frame that omits the key and narrowing it would rewrite bytes shipped senders already put on the wire. `runRpcOperation` was the one send entry point that never adopted the tuple, having had no params-less caller until now. The compile fence pins all three accepted shapes and that a params-bearing object is still refused. Claude-Session: https://claude.ai/code/session_01JNnE9qzUZMMnqpZWCqM3nb
This commit is contained in:
@@ -9,6 +9,7 @@ import {
|
||||
} from './rpc-operation'
|
||||
import { rpcResultVariants } from './rpc-operation-result-reader'
|
||||
import {
|
||||
pushTestWithoutParams,
|
||||
workspaceListAtBarrier,
|
||||
workspaceListOrNull,
|
||||
workspaceRowsReader,
|
||||
@@ -146,6 +147,17 @@ export async function fenceBarrierAndParams(): Promise<void> {
|
||||
)
|
||||
}
|
||||
|
||||
// A method the catalog declares params-less keeps every shape a shipped sender may use. An
|
||||
// explicit `null` is the one that matters: `params: null` is not the frame that omits the key,
|
||||
// so narrowing this to omission would rewrite bytes main already puts on the wire.
|
||||
export async function fenceParamlessSend(): Promise<void> {
|
||||
await runRpcOperation(client, pushTestWithoutParams, null)
|
||||
await runRpcOperation(client, pushTestWithoutParams, undefined)
|
||||
await runRpcOperation(client, pushTestWithoutParams)
|
||||
// @ts-expect-error a method that declares no params accepts none
|
||||
await runRpcOperation(client, pushTestWithoutParams, { path: 'main.js' })
|
||||
}
|
||||
|
||||
export async function fenceVerdictTypes(): Promise<void> {
|
||||
// @ts-expect-error the probe's policy yields a boolean, not the other family's rows
|
||||
const rows: WorkspaceRows = await runRpcOperation(client, worktreePsProbe, {})
|
||||
|
||||
@@ -54,6 +54,14 @@ export const worktreePsProbe = defineRpcOperation({
|
||||
barrier: 'on-settle'
|
||||
})
|
||||
|
||||
/** A method the catalog declares with no params at all, so `RpcSendParams` reads `void`. */
|
||||
export const pushTestWithoutParams = defineRpcOperation({
|
||||
name: 'test.pushTestWithoutParams',
|
||||
method: 'notifications.testPush',
|
||||
acceptance: 'method-not-found-refusal',
|
||||
barrier: 'on-settle'
|
||||
})
|
||||
|
||||
export const terminalStreamOpener = defineRpcOperation({
|
||||
name: 'test.terminalStreamOpener',
|
||||
method: 'terminal.subscribe',
|
||||
|
||||
@@ -173,10 +173,12 @@ export async function runRpcOperation<
|
||||
>(
|
||||
client: UnvalidatedRpcRequestPort,
|
||||
operation: RpcOperation<Method, Acceptance, Variant, Value, 'on-settle'>,
|
||||
params: RpcSendParams<Method>,
|
||||
options?: SendRequestOptions
|
||||
// Shares the deferred sender's tuple so the two cannot disagree about what a params-less
|
||||
// method may be called with: the catalog types those `void`, and an explicit `null` is the
|
||||
// frame several shipped senders already put on the wire.
|
||||
...args: RpcSendArguments<Method>
|
||||
): Promise<RpcVerdict<Acceptance, Value>> {
|
||||
const outcome = await request(client, operation, params, options)
|
||||
const outcome = await request(client, operation, args[0], args[1])
|
||||
// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: Preserve the established response shape at this boundary.
|
||||
return interpretRpcOutcome(operation, outcome) as RpcVerdict<Acceptance, Value>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user