Files
orca/src/main/runtime/runtime-git-generation-context.ts
T
Neil 62451920ed fix(git): preserve SSH review context and worktree ownership (#24945)
* fix(git): preserve SSH arguments and guard background writes

* test(terminal): settle fish fixture startup readiness

* fix(git): preserve bare UNC SSH paths

* fix(git): unescape shell operators in Windows SSH paths

* test(runtime): settle removal writes before fixture cleanup

* test(git): skip optional OpenSSH probe when unavailable

* perf(git): skip equal-tip reads and bound relay discovery

* test(processes): ratchet the removed relay Git spawn

* test(shells): wait for initial zsh output before sending input

* Fix SSH review context and recover Git maintenance cleanup safely

* Keep relay Git compatibility fixtures outside shared client projects

* Fence superseded maintenance and preserve mixed-version session search

* test: model Git child termination and search catalogs

* test: retain catalog authority over history flags
2026-10-03 05:24:35 -07:00

119 lines
4.3 KiB
TypeScript

import type { GlobalSettings } from '../../shared/global-settings-types'
import { gitExecFileAsync } from '../git/runner'
import type { getPullRequestDraftContext } from '../text-generation/pull-request-context'
import {
mergeLegacyCommitMessageAiIntoSourceControlAi,
type ResolvedSourceControlAiGenerationParams
} from '../../shared/source-control-ai'
import type { SourceControlAiOperation } from '../../shared/source-control-ai-types'
import type { CommitMessageAgentRuntimeTarget } from '../text-generation/commit-message-agent-environment'
import type { CommitMessageGenerationTarget } from '../text-generation/commit-message-text-generation'
import type { PullRequestLinkedIssueMeta } from '../source-control/pull-request-linked-issue'
import { execSshReviewDraft } from '../providers/ssh-review-draft-context'
import {
localGitOptionsForTarget,
type RuntimeGitCommandHost,
type RuntimeGitRoute,
type RuntimeGitTarget
} from './runtime-git-command-target'
type PullRequestDraftGitExec = Parameters<typeof getPullRequestDraftContext>[0]
/** Runs the PR draft-context probes on whichever host `route` resolved to. */
export function pullRequestDraftGitExec(
target: RuntimeGitTarget,
route: RuntimeGitRoute
): PullRequestDraftGitExec {
if (route.kind === 'ssh') {
const provider = route.provider
if (!provider) {
throw new Error('ssh_git_provider_unavailable')
}
return (argv, options) => execSshReviewDraft(provider, argv, target.worktree.path, options)
}
return (argv, options) =>
gitExecFileAsync(argv, {
cwd: target.worktree.path,
...localGitOptionsForTarget(target),
...(options?.maxBuffer === undefined ? {} : { maxBuffer: options.maxBuffer }),
...(options?.timeoutMs === undefined && options?.timeout === undefined
? {}
: { timeout: options?.timeoutMs ?? options?.timeout }),
admissionTier: 'interactive'
})
}
export type RuntimeCommitMessageSettingsOverride = Partial<
Pick<
GlobalSettings,
'commitMessageAi' | 'sourceControlAi' | 'agentCmdOverrides' | 'defaultTuiAgent'
>
> & {
commitMessageDiscoveryHostKey?: string
sourceControlAiResolvedParams?: ResolvedSourceControlAiGenerationParams
}
export function getRuntimeGitGenerationSettings(
settings: GlobalSettings,
settingsOverride: RuntimeCommitMessageSettingsOverride | undefined,
operation: SourceControlAiOperation
): GlobalSettings {
const mergedSettings = { ...settings, ...settingsOverride }
if (
settingsOverride?.commitMessageAi !== undefined &&
settingsOverride.sourceControlAi === undefined
) {
mergedSettings.sourceControlAi = mergeLegacyCommitMessageAiIntoSourceControlAi(
settings.sourceControlAi,
settingsOverride.commitMessageAi,
{ pullRequestInstructionsFromLegacy: operation === 'pullRequest' }
)
}
return mergedSettings
}
export function localAgentRuntimeTargetForTarget(
target: RuntimeGitTarget
): CommitMessageAgentRuntimeTarget {
const wslDistro = localGitOptionsForTarget(target).wslDistro
return wslDistro ? { runtime: 'wsl', wslDistro } : { runtime: 'host' }
}
export function localTextGenerationTargetForTarget(
target: RuntimeGitTarget,
env?: NodeJS.ProcessEnv
): Extract<CommitMessageGenerationTarget, { kind: 'local' }> {
const wslDistro = localGitOptionsForTarget(target).wslDistro
return {
kind: 'local',
cwd: target.worktree.path,
...(wslDistro ? { wslDistro } : {}),
...(env ? { env } : {})
}
}
export function linkedIssueForTarget(
host: RuntimeGitCommandHost,
target: RuntimeGitTarget
): number | null | undefined {
const live = host.getWorktreeLinkedIssue?.(target.worktree.id)
// Why: `undefined` means the host could not answer, not "unlinked".
return live === undefined ? target.worktree.linkedIssue : live
}
export function linkedIssueMetaForTarget(
host: RuntimeGitCommandHost,
target: RuntimeGitTarget
): PullRequestLinkedIssueMeta | null {
const live = host.getWorktreeLinkedIssueMeta?.(target.worktree.id)
if (live !== undefined) {
return live
}
const liveGitHubIssue = host.getWorktreeLinkedIssue?.(target.worktree.id)
return {
linkedIssue: liveGitHubIssue === undefined ? target.worktree.linkedIssue : liveGitHubIssue,
linkedGitLabIssue: target.worktree.linkedGitLabIssue,
linkedWorkItem: target.worktree.linkedWorkItem
}
}