diff --git a/src/main/agent-launch/agent-launch-executor.ts b/src/main/agent-launch/agent-launch-executor.ts index 9e2841c8759..551ba1695ad 100644 --- a/src/main/agent-launch/agent-launch-executor.ts +++ b/src/main/agent-launch/agent-launch-executor.ts @@ -337,8 +337,7 @@ async function createTerminalSurface( worktreeId, agent: intent.agent, ...(startupPrompt ? { startupPrompt } : {}), - ...terminalLaunchInputs(intent), - ...(intent.viewMode ? { viewMode: intent.viewMode } : {}) + ...terminalLaunchInputs(intent) }) return { outcome: { diff --git a/src/main/agent-launch/agent-launch-surface-factories.ts b/src/main/agent-launch/agent-launch-surface-factories.ts index 39f8785bc72..e7d36f05ea1 100644 --- a/src/main/agent-launch/agent-launch-surface-factories.ts +++ b/src/main/agent-launch/agent-launch-surface-factories.ts @@ -35,8 +35,6 @@ export type AgentLaunchSurfaceFactory = { launchSource?: string /** The caller-minted pane to create; refused with `AgentLaunchPaneAlreadyLiveError` if live. */ paneKey?: string - /** How the tab first shows, as the caller would have opened it. */ - viewMode?: 'terminal' | 'chat' }): Promise<{ handle: string /** The pane this create minted; a factory whose runtime reports none omits it, never invents. */ diff --git a/src/main/ipc/runtime-agent-launch-capability.test.ts b/src/main/ipc/runtime-agent-launch-capability.test.ts index dd36727e8b3..6c85455a324 100644 --- a/src/main/ipc/runtime-agent-launch-capability.test.ts +++ b/src/main/ipc/runtime-agent-launch-capability.test.ts @@ -12,8 +12,6 @@ import { AGENT_LAUNCH_RUNTIME_CAPABILITY } from '../../shared/agent-launch-runti type AdvertisedClient = { clientKind?: 'mobile' | 'runtime' clientCapabilities?: readonly RuntimeCapability[] - trustedLocalCallerId?: string - pairedDeviceId?: string } const { handlers, advertised } = vi.hoisted( @@ -59,7 +57,6 @@ vi.mock('../runtime/rpc/dispatcher', () => ({ const { registerRuntimeHandlers } = await import('./runtime') const { supportsAgentLaunch } = await import('../runtime/rpc/methods/agent-launch') -const { agentLaunchOperationCallerKey } = await import('../runtime/rpc/methods/agent-launch-replay') function rendererEvent() { const mainFrame = {} @@ -129,20 +126,4 @@ describe('desktop renderer reaching agent.launch on its own main process', () => ) expect(supportsAgentLaunch(streaming)).toBe(true) }) - - // Why: the desktop has no paired device, so without its own host-set identity every - // replay-protected launch it sent was refused with agent_session_identity_required. - it('gives a replay-protected launch a caller identity of its own', () => { - invoke('runtime:call', { - method: 'agent.launchReplay', - params: { agent: 'claude', target: { kind: 'existing', worktree: 'id:wt-7' } } - }) - - const client = onlyAdvertisedClient(advertised.unary) - expect(agentLaunchOperationCallerKey(client)).toBe('trusted-local:desktop-renderer') - // Negative control: the same client kind with no host-set identity is still refused. - expect(() => - agentLaunchOperationCallerKey({ clientKind: client.clientKind, pairedDeviceId: undefined }) - ).toThrow('agent_session_identity_required') - }) }) diff --git a/src/main/ipc/runtime.ts b/src/main/ipc/runtime.ts index 94ee84c1fab..e768de463d8 100644 --- a/src/main/ipc/runtime.ts +++ b/src/main/ipc/runtime.ts @@ -78,7 +78,6 @@ export function registerRuntimeHandlers(runtime: OrcaRuntimeService): void { }, { clientId: 'desktop-renderer', - trustedLocalCallerId: 'desktop-renderer', clientKind: 'runtime', connectionId: desktopSenders.connectionIdFor(event.sender), clientCapabilities: DESKTOP_RENDERER_RUNTIME_CLIENT_CAPABILITIES @@ -121,7 +120,6 @@ export function registerRuntimeHandlers(runtime: OrcaRuntimeService): void { { signal: controller.signal, clientId: 'desktop-renderer', - trustedLocalCallerId: 'desktop-renderer', clientKind: 'runtime', connectionId, clientCapabilities: DESKTOP_RENDERER_RUNTIME_CLIENT_CAPABILITIES diff --git a/src/main/runtime/rpc/core.ts b/src/main/runtime/rpc/core.ts index 46529f592d7..1402f10b223 100644 --- a/src/main/runtime/rpc/core.ts +++ b/src/main/runtime/rpc/core.ts @@ -75,9 +75,6 @@ export type RpcContext = { clientId?: string // Why: navigation is keyed by revocable device identity, never by the bearer credential or transient socket id. pairedDeviceId?: string - // Why: an in-process caller (the desktop renderer over IPC) has no paired device, yet its identity - // is fixed by the host, so replay-protected operations can key on it. - trustedLocalCallerId?: string // Why: lets handlers gate mobile payload truncation to phones only; undefined for in-process callers → treat as full-class (no clip). clientKind?: 'mobile' | 'runtime' // Why: negotiation is bound to the authenticated socket, never asserted by a destructive request. diff --git a/src/main/runtime/rpc/dispatcher-stream-options.ts b/src/main/runtime/rpc/dispatcher-stream-options.ts index ca8c79ad0ac..e3151c66b0e 100644 --- a/src/main/runtime/rpc/dispatcher-stream-options.ts +++ b/src/main/runtime/rpc/dispatcher-stream-options.ts @@ -8,8 +8,6 @@ export type RpcDispatchStreamingOptions = { signal?: AbortSignal clientId?: string pairedDeviceId?: string - /** Set only by an in-process transport (desktop IPC); never derived from anything a peer sends. */ - trustedLocalCallerId?: string clientKind?: 'mobile' | 'runtime' clientCapabilities?: readonly RuntimeCapability[] updateClientCapabilities?: (capabilities: readonly RuntimeCapability[]) => void diff --git a/src/main/runtime/rpc/dispatcher-trusted-local-caller.test.ts b/src/main/runtime/rpc/dispatcher-trusted-local-caller.test.ts deleted file mode 100644 index fa8011fdbdd..00000000000 --- a/src/main/runtime/rpc/dispatcher-trusted-local-caller.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { describe, expect, it } from 'vitest' -import { z } from 'zod' -import { RpcDispatcher } from './dispatcher' -import { defineMethod, type RpcRequest } from './core' -import type { OrcaRuntimeService } from '../orca-runtime' - -// oxlint-disable-next-line typescript/consistent-type-assertions -- SAFETY: the dispatcher reads only getRuntimeId on this path; any other runtime member it touched would throw rather than read a wrong value. -const RUNTIME = { getRuntimeId: () => 'test-runtime' } as OrcaRuntimeService - -const INSPECT = defineMethod({ - name: 'test.inspectCaller', - params: z.object({}), - handler: (_params, { trustedLocalCallerId }) => ({ - trustedLocalCallerId: trustedLocalCallerId ?? null - }) -}) - -function request(): RpcRequest { - return { id: 'req-1', authToken: 'tok', method: 'test.inspectCaller', params: {} } -} - -describe('the in-process caller identity a transport vouches for', () => { - it('reaches a unary handler from the transport that set it', async () => { - const dispatcher = new RpcDispatcher({ runtime: RUNTIME, methods: [INSPECT] }) - - const response = await dispatcher.dispatch(request(), { - clientKind: 'runtime', - trustedLocalCallerId: 'desktop-renderer' - }) - - expect(response).toMatchObject({ - ok: true, - result: { trustedLocalCallerId: 'desktop-renderer' } - }) - }) - - it('is absent for a transport that set none, whatever the request carries', async () => { - const dispatcher = new RpcDispatcher({ runtime: RUNTIME, methods: [INSPECT] }) - - const response = await dispatcher.dispatch( - { ...request(), params: { trustedLocalCallerId: 'desktop-renderer' } }, - { clientKind: 'runtime' } - ) - - expect(response).toMatchObject({ ok: true, result: { trustedLocalCallerId: null } }) - }) -}) diff --git a/src/main/runtime/rpc/dispatcher.ts b/src/main/runtime/rpc/dispatcher.ts index 871037ea63c..04600fcc4ec 100644 --- a/src/main/runtime/rpc/dispatcher.ts +++ b/src/main/runtime/rpc/dispatcher.ts @@ -116,7 +116,6 @@ export class RpcDispatcher { : undefined, requestId: request.id, clientId: options?.clientId, - trustedLocalCallerId: options?.trustedLocalCallerId, clientKind: options?.clientKind, clientCapabilities: options?.clientCapabilities, updateClientCapabilities: options?.updateClientCapabilities, diff --git a/src/main/runtime/rpc/methods/agent-launch-replay.ts b/src/main/runtime/rpc/methods/agent-launch-replay.ts index 2bab7d12535..bb87d8098a9 100644 --- a/src/main/runtime/rpc/methods/agent-launch-replay.ts +++ b/src/main/runtime/rpc/methods/agent-launch-replay.ts @@ -29,16 +29,11 @@ import type { AgentLaunchParams } from './agent-launch-schemas' /** Remote replay needs the paired-device subject because its bearer credential can rotate. */ export function agentLaunchOperationCallerKey( - context: Pick + context: Pick ): string { if (context.clientKind === undefined) { return 'trusted-local:runtime' } - // The desktop renderer is in-process like the CLI, but advertises capabilities as a client. - const trustedLocalCallerId = context.trustedLocalCallerId?.trim() - if (trustedLocalCallerId) { - return `trusted-local:${trustedLocalCallerId}` - } const pairedDeviceId = context.pairedDeviceId?.trim() if (!pairedDeviceId) { throw new Error('agent_session_identity_required') diff --git a/src/main/runtime/rpc/methods/agent-launch-surfaces.ts b/src/main/runtime/rpc/methods/agent-launch-surfaces.ts index 2e383e876d2..7be7fe8034b 100644 --- a/src/main/runtime/rpc/methods/agent-launch-surfaces.ts +++ b/src/main/runtime/rpc/methods/agent-launch-surfaces.ts @@ -118,7 +118,6 @@ export function agentLaunchSurfaceFactory( cwd, launchSource, paneKey, - viewMode, options }) => { const launchPreferences = toAgentLaunchPreferences(options) @@ -144,8 +143,6 @@ export function agentLaunchSurfaceFactory( // A live reserved pane would be attached, not launched into, so the runtime refuses it. ...(paneKey ? { ...paneIdentity(paneKey), requireFreshPane: true } : {}), ...(launchSource ? { launchSource } : {}), - // Not `presentation`: a focused create takes the renderer path, which drops the pane identity. - ...(viewMode ? { viewMode } : {}), onPtySpawnDispatched: terminalSpawn.onPtySpawnDispatched }) const terminal = await created.catch(terminalSpawn.rethrow) diff --git a/src/main/runtime/rpc/methods/agent-launch-terminal-preferences.test.ts b/src/main/runtime/rpc/methods/agent-launch-terminal-preferences.test.ts index 12945df369a..f75fdc803f2 100644 --- a/src/main/runtime/rpc/methods/agent-launch-terminal-preferences.test.ts +++ b/src/main/runtime/rpc/methods/agent-launch-terminal-preferences.test.ts @@ -80,16 +80,6 @@ describe('a terminal launch into an existing workspace', () => { expect(terminalOptions(runtime)).toMatchObject({ launchPreferences: PICKS }) }) - it('opens the tab in the view mode the caller asked for, without asking for a focused create', async () => { - const runtime = runtimeStub({ settings: TERMINAL_ONLY }) - - await launch({ ...EXISTING_LAUNCH, viewMode: 'chat' }, runtime) - - // A focused create takes the renderer path, which drops the caller's pane identity. - expect(terminalOptions(runtime)).toMatchObject({ viewMode: 'chat' }) - expect(terminalOptions(runtime)).not.toHaveProperty('presentation') - }) - it('drops options that are not launch preferences', async () => { const runtime = runtimeStub({ settings: TERMINAL_ONLY }) diff --git a/src/main/runtime/rpc/methods/agent-launch.ts b/src/main/runtime/rpc/methods/agent-launch.ts index 0ee01066674..27178d13874 100644 --- a/src/main/runtime/rpc/methods/agent-launch.ts +++ b/src/main/runtime/rpc/methods/agent-launch.ts @@ -105,7 +105,6 @@ async function agentLaunchIntent( ...(params.cwd ? { cwd: params.cwd } : {}), ...(params.launchSource ? { launchSource: params.launchSource } : {}), ...(params.paneKey ? { paneKey: params.paneKey } : {}), - ...(params.viewMode ? { viewMode: params.viewMode } : {}), ...(params.sessionId ? { sessionId: params.sessionId } : {}) } } diff --git a/src/main/runtime/rpc/rpc-streaming-dispatcher.ts b/src/main/runtime/rpc/rpc-streaming-dispatcher.ts index 41847a0eb23..07706125c23 100644 --- a/src/main/runtime/rpc/rpc-streaming-dispatcher.ts +++ b/src/main/runtime/rpc/rpc-streaming-dispatcher.ts @@ -138,7 +138,6 @@ export class RpcStreamingDispatcher { subscriptionRegistrationVersion, clientId: options?.clientId, pairedDeviceId: options?.pairedDeviceId, - trustedLocalCallerId: options?.trustedLocalCallerId, clientKind: options?.clientKind, clientCapabilities: options?.clientCapabilities, updateClientCapabilities: options?.updateClientCapabilities, @@ -193,7 +192,6 @@ export class RpcStreamingDispatcher { connectionId: options?.connectionId, clientId: options?.clientId, pairedDeviceId: options?.pairedDeviceId, - trustedLocalCallerId: options?.trustedLocalCallerId, clientKind: options?.clientKind, clientCapabilities: options?.clientCapabilities, updateClientCapabilities: options?.updateClientCapabilities, diff --git a/src/shared/agent-launch-intent.ts b/src/shared/agent-launch-intent.ts index 2f59619dc2c..bffb93c1b9a 100644 --- a/src/shared/agent-launch-intent.ts +++ b/src/shared/agent-launch-intent.ts @@ -93,8 +93,6 @@ export type AgentLaunchIntent = { /** The `tabId:leafId` a terminal launch creates its pane under, for a caller that places its own * tabs. Not a route input; refused when that pane is already live. */ paneKey?: string - /** How a terminal launched into an existing workspace first shows its tab. Not a route input. */ - viewMode?: 'terminal' | 'chat' /** The caller-minted id of the chat session a structured launch creates. Not a route input; * refused when that session already exists. */ sessionId?: string diff --git a/src/shared/rpc-contract/agent-launch-params.ts b/src/shared/rpc-contract/agent-launch-params.ts index 0737a1d3e64..3926c610708 100644 --- a/src/shared/rpc-contract/agent-launch-params.ts +++ b/src/shared/rpc-contract/agent-launch-params.ts @@ -102,12 +102,6 @@ export const AgentLaunchFields = z.object({ ) }, 'Malformed launch pane key') .optional(), - /** - * How a terminal launch in an existing workspace first shows its tab, so the tab opens as the - * caller would have opened it. Presentation only; a chat and a new workspace's startup terminal - * ignore it, and an older host strips it. - */ - viewMode: z.enum(['terminal', 'chat']).optional(), /** * The id of the chat session a structured launch creates, minted by the caller so it knows which * conversation it started before the reply arrives. Refused when a session with this id already