From 99697c8af1dda0c5e7eac4b4659fe555950c3e5c Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Mon, 21 Sep 2026 15:40:55 -0700 Subject: [PATCH] refactor(agent-launch): lift launch execution-context resolution into its own module --- .../src/lib/launch-agent-execution-context.ts | 54 +++++++++++++++++++ .../src/lib/launch-agent-in-new-tab.ts | 35 +++--------- 2 files changed, 60 insertions(+), 29 deletions(-) create mode 100644 src/renderer/src/lib/launch-agent-execution-context.ts diff --git a/src/renderer/src/lib/launch-agent-execution-context.ts b/src/renderer/src/lib/launch-agent-execution-context.ts new file mode 100644 index 00000000000..4d9cf4b41c8 --- /dev/null +++ b/src/renderer/src/lib/launch-agent-execution-context.ts @@ -0,0 +1,54 @@ +import type { AgentStartupShell } from '../../../shared/tui-agent-startup-shell' +import { resolveLocalWindowsAgentStartupShell } from '../../../shared/windows-terminal-shell' +import { CLIENT_PLATFORM } from '@/lib/new-workspace' +import { getAgentLaunchPlatformForRepo } from '@/lib/agent-launch-platform' +import { getConnectionIdFromState } from '@/lib/connection-context' +import { getLocalProjectExecutionRuntimeContext } from '@/lib/local-preflight-context' +import type { useAppStore } from '@/store' + +/** Where a new-tab agent launch runs, and the quoting rules that follow from it. */ +export type AgentLaunchExecutionContext = { + /** `undefined` means rival host rows disagree, which is not evidence of a remote. */ + worktreeSshConnectionId: string | null | undefined + resolvedLaunchPlatform: NodeJS.Platform + isRemote: boolean + /** Only set for a local Windows launch; remote targets need their own shell signal. */ + queuedShell: AgentStartupShell | undefined +} + +export function resolveAgentLaunchExecutionContext( + store: ReturnType, + args: { worktreeId: string; launchPlatform?: NodeJS.Platform } +): AgentLaunchExecutionContext { + const worktree = store + .allWorktrees?.() + .find((entry: { id: string }) => entry.id === args.worktreeId) + const repo = worktree ? store.repos?.find((entry) => entry.id === worktree.repoId) : null + // Why: `store.repos.find` is host-blind and the same repo id can exist on local, SSH and runtime + // hosts, so the row it returns can belong to a different host than the worktree names (#11163). + // The shared resolver answers from the worktree's own host; `undefined` (rival rows disagree) is + // not evidence of a remote, and main rejects that launch anyway. + const worktreeSshConnectionId = getConnectionIdFromState(store, args.worktreeId) + const resolvedLaunchPlatform = + args.launchPlatform ?? + (repo + ? getAgentLaunchPlatformForRepo( + repo, + worktreeSshConnectionId + ? undefined + : getLocalProjectExecutionRuntimeContext(store, args.worktreeId) + ) + : CLIENT_PLATFORM) + // Why: SSH remotes deploy the shim as plain `orca`, so skip the Linux-only `orca-ide` rename for remote launches. + const isRemote = Boolean(worktreeSshConnectionId) + return { + worktreeSshConnectionId, + resolvedLaunchPlatform, + isRemote, + queuedShell: resolveLocalWindowsAgentStartupShell({ + platform: resolvedLaunchPlatform, + isRemote, + terminalWindowsShell: store.settings?.terminalWindowsShell + }) + } +} diff --git a/src/renderer/src/lib/launch-agent-in-new-tab.ts b/src/renderer/src/lib/launch-agent-in-new-tab.ts index b02dcab23ab..cd823a86f8c 100644 --- a/src/renderer/src/lib/launch-agent-in-new-tab.ts +++ b/src/renderer/src/lib/launch-agent-in-new-tab.ts @@ -1,8 +1,6 @@ import { useAppStore } from '@/store' import type { AgentStartupPlan } from '@/lib/tui-agent-startup' import { planLaunchAgentStartupPrompt } from '@/lib/launch-agent-startup-prompt-plan' -import { CLIENT_PLATFORM } from '@/lib/new-workspace' -import { getAgentLaunchPlatformForRepo } from '@/lib/agent-launch-platform' import { persistAgentLaunchTabOrder } from '@/lib/launch-agent-tab-order' import { tuiAgentToAgentKind } from '@/lib/telemetry' import { createPasteReadinessTimeoutNotice } from '@/lib/launch-agent-paste-timeout-notice' @@ -13,19 +11,17 @@ import { import { initialAgentTabViewModeProps } from '@/lib/native-chat-initial-view-mode' import { isNativeChatTranscriptLocalReadable } from '@/lib/native-chat-transcript-readability' import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner' -import { getLocalProjectExecutionRuntimeContext } from '@/lib/local-preflight-context' import { isWebRuntimeSessionActive } from '@/runtime/web-runtime-session' import { launchAgentInWebHostTab } from '@/lib/launch-agent-web-host-tab' import { resolveTuiAgentLaunchArgs, resolveTuiAgentLaunchEnv } from '../../../shared/tui-agent-launch-defaults' -import { resolveLocalWindowsAgentStartupShell } from '../../../shared/windows-terminal-shell' import { TUI_AGENT_CONFIG } from '../../../shared/tui-agent-config' import { seedCommandCodeSubmittedPromptStatus } from '@/lib/command-code-prompt-status-seed' import type { TuiAgent } from '../../../shared/tui-agent' import type { LaunchSource } from '../../../shared/telemetry-events' -import { getConnectionIdFromState } from '@/lib/connection-context' +import { resolveAgentLaunchExecutionContext } from '@/lib/launch-agent-execution-context' import { resolveInitialNativeChatSessionOptions } from '@/components/native-chat/native-chat-launch-session-options' import { seedNativeChatAppliedSessionOptions } from '@/components/native-chat/native-chat-session-option-cache' import { launchAgentInStructuredNewTab } from '@/lib/launch-agent-in-new-tab-structured' @@ -122,30 +118,11 @@ function launchAgentInNewTabInternal(args: LaunchAgentInNewTabArgs): LaunchAgent activate } = args const store = useAppStore.getState() - const worktree = store.allWorktrees?.().find((entry: { id: string }) => entry.id === worktreeId) - const repo = worktree ? store.repos?.find((entry) => entry.id === worktree.repoId) : null - // Why: `store.repos.find` is host-blind and the same repo id can exist on local, SSH and runtime - // hosts, so the row it returns can belong to a different host than the worktree names (#11163). - // The shared resolver answers from the worktree's own host; `undefined` (rival rows disagree) is - // not evidence of a remote, and main rejects that launch anyway. - const worktreeSshConnectionId = getConnectionIdFromState(store, worktreeId) - const resolvedLaunchPlatform = - launchPlatform ?? - (repo - ? getAgentLaunchPlatformForRepo( - repo, - worktreeSshConnectionId - ? undefined - : getLocalProjectExecutionRuntimeContext(store, worktreeId) - ) - : CLIENT_PLATFORM) - // Why: SSH remotes deploy the shim as plain `orca`, so skip the Linux-only `orca-ide` rename for remote launches. - const isRemote = Boolean(worktreeSshConnectionId) - const queuedShell = resolveLocalWindowsAgentStartupShell({ - platform: resolvedLaunchPlatform, - isRemote, - terminalWindowsShell: store.settings?.terminalWindowsShell - }) + const { worktreeSshConnectionId, resolvedLaunchPlatform, isRemote, queuedShell } = + resolveAgentLaunchExecutionContext(store, { + worktreeId, + ...(launchPlatform ? { launchPlatform } : {}) + }) const cmdOverrides = store.settings?.agentCmdOverrides ?? {} const effectiveAgentArgs = agentArgs !== undefined