mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 08:03:28 +00:00
215 lines
8.2 KiB
TypeScript
215 lines
8.2 KiB
TypeScript
import { getRepoExecutionHostId, parseExecutionHostId } from '../../../shared/execution-host'
|
|
import type { ExecutionHostId } from '../../../shared/execution-host'
|
|
import type { GlobalSettings, Worktree } from '../../../shared/types'
|
|
import { parseWorkspaceKey } from '../../../shared/workspace-scope'
|
|
import { FLOATING_TERMINAL_WORKTREE_ID } from '../../../shared/constants'
|
|
import { getRepoIdFromWorktreeId } from '@/store/slices/worktree-helpers'
|
|
import {
|
|
findIndexedRepoOwner as findRepoRecord,
|
|
findIndexedWorktreeOwner as findWorktreeRecord,
|
|
hasIndexedDetectedWorktree,
|
|
resolveIndexedRepoOwner,
|
|
resolveIndexedWorktreeOwner
|
|
} from './worktree-runtime-owner-index'
|
|
import { getSingleFocusedRuntimeEnvironmentId } from './single-runtime-legacy-owner'
|
|
import {
|
|
getExecutionHostIdForFolderWorkspace,
|
|
getExplicitRuntimeEnvironmentIdForFolderWorkspace,
|
|
getRuntimeEnvironmentIdForFolderWorkspace
|
|
} from './folder-workspace-runtime-owner'
|
|
import {
|
|
resolveActiveWorkspaceRoute,
|
|
resolveExplicitWorktreeOperationRouteResult,
|
|
resolveWorktreeOperationRouteResult
|
|
} from './worktree-operation-route'
|
|
import type { WorktreeRuntimeOwnerState } from './worktree-runtime-owner-state'
|
|
export type { WorktreeRuntimeOwnerState } from './worktree-runtime-owner-state'
|
|
export { getRuntimeSessionMirrorEnvironmentIds } from './runtime-session-mirror-owners'
|
|
|
|
function getExplicitRuntimeEnvironmentIdFromHost(
|
|
executionHostId: string | null | undefined
|
|
): string | null {
|
|
const parsed = parseExecutionHostId(executionHostId)
|
|
return parsed?.kind === 'runtime' ? parsed.environmentId : null
|
|
}
|
|
|
|
function getProjectedRuntimeOwnerEnvironmentId(
|
|
worktree: Pick<Worktree, 'runtimeOwnerEnvironmentId'> | null | undefined
|
|
): string | null {
|
|
return worktree?.runtimeOwnerEnvironmentId?.trim() || null
|
|
}
|
|
|
|
function getExecutionHostIdFromWorktreeHost(
|
|
hostId: string | null | undefined
|
|
): ExecutionHostId | null {
|
|
return parseExecutionHostId(hostId)?.id ?? null
|
|
}
|
|
|
|
function getActiveWorkspaceExecutionHostId(
|
|
state: WorktreeRuntimeOwnerState,
|
|
worktreeId: string
|
|
): ExecutionHostId | null {
|
|
return state.activeWorktreeId === worktreeId
|
|
? (state.activeWorkspaceExecutionHostId ?? null)
|
|
: null
|
|
}
|
|
|
|
export function getRuntimeEnvironmentIdForWorktree(
|
|
state: WorktreeRuntimeOwnerState,
|
|
worktreeId: string | null | undefined
|
|
): string | null {
|
|
if (!worktreeId) {
|
|
return null
|
|
}
|
|
if (worktreeId === FLOATING_TERMINAL_WORKTREE_ID) {
|
|
return null
|
|
}
|
|
const activeRoute = resolveActiveWorkspaceRoute(state, worktreeId)
|
|
if (activeRoute) {
|
|
return activeRoute.runtimeEnvironmentId
|
|
}
|
|
const workspaceScope = parseWorkspaceKey(worktreeId)
|
|
if (workspaceScope?.type === 'folder') {
|
|
return getRuntimeEnvironmentIdForFolderWorkspace(state, workspaceScope.folderWorkspaceId)
|
|
}
|
|
const indexedOwner = resolveIndexedWorktreeOwner(state.worktreesByRepo, worktreeId)
|
|
if (indexedOwner.kind === 'ambiguous') {
|
|
return null
|
|
}
|
|
if (indexedOwner.kind === 'resolved') {
|
|
const owner = indexedOwner.owner
|
|
const projectedRuntimeOwner = getProjectedRuntimeOwnerEnvironmentId(owner)
|
|
const parsedHost = parseExecutionHostId(owner.hostId)
|
|
const hasDetectedOwner = hasIndexedDetectedWorktree(state.detectedWorktreesByRepo, worktreeId)
|
|
if (!hasDetectedOwner && (projectedRuntimeOwner || parsedHost)) {
|
|
return (
|
|
projectedRuntimeOwner || (parsedHost?.kind === 'runtime' ? parsedHost.environmentId : null)
|
|
)
|
|
}
|
|
if (!hasDetectedOwner) {
|
|
const repoResolution = resolveIndexedRepoOwner(state.repos, owner.repoId)
|
|
if (repoResolution.kind === 'ambiguous') {
|
|
return null
|
|
}
|
|
if (
|
|
repoResolution.kind === 'resolved' &&
|
|
(repoResolution.owner.executionHostId?.trim() || repoResolution.owner.connectionId?.trim())
|
|
) {
|
|
const repoHost = parseExecutionHostId(getRepoExecutionHostId(repoResolution.owner))
|
|
if (repoHost) {
|
|
return repoHost.kind === 'runtime' ? repoHost.environmentId : null
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const resolution = resolveWorktreeOperationRouteResult(state, worktreeId)
|
|
return resolution.kind === 'resolved' ? resolution.route.runtimeEnvironmentId : null
|
|
}
|
|
|
|
export function getExplicitRuntimeEnvironmentIdForWorktree(
|
|
state: WorktreeRuntimeOwnerState,
|
|
worktreeId: string | null | undefined
|
|
): string | null {
|
|
if (!worktreeId) {
|
|
return null
|
|
}
|
|
const activeRoute = resolveActiveWorkspaceRoute(state, worktreeId)
|
|
if (activeRoute) {
|
|
return activeRoute.runtimeEnvironmentId
|
|
}
|
|
const workspaceScope = parseWorkspaceKey(worktreeId)
|
|
if (workspaceScope?.type === 'folder') {
|
|
return getExplicitRuntimeEnvironmentIdForFolderWorkspace(
|
|
state,
|
|
workspaceScope.folderWorkspaceId
|
|
)
|
|
}
|
|
const hasDetectedOwner = hasIndexedDetectedWorktree(state.detectedWorktreesByRepo, worktreeId)
|
|
if (hasDetectedOwner) {
|
|
// Why: detected-only rows are selectable before the primary catalog lands; use the same
|
|
// ambiguity-aware explicit provenance as filesystem and terminal operations.
|
|
const resolution = resolveExplicitWorktreeOperationRouteResult(state, worktreeId)
|
|
return resolution.kind === 'resolved' ? resolution.route.runtimeEnvironmentId : null
|
|
}
|
|
if (resolveIndexedWorktreeOwner(state.worktreesByRepo, worktreeId).kind === 'ambiguous') {
|
|
return null
|
|
}
|
|
const worktree = findWorktreeRecord(state.worktreesByRepo, worktreeId)
|
|
const projectedRuntimeOwner = getProjectedRuntimeOwnerEnvironmentId(worktree)
|
|
if (projectedRuntimeOwner) {
|
|
return projectedRuntimeOwner
|
|
}
|
|
const parsedWorktreeHost = parseExecutionHostId(worktree?.hostId)
|
|
if (parsedWorktreeHost?.kind === 'runtime') {
|
|
return parsedWorktreeHost.environmentId
|
|
}
|
|
if (parsedWorktreeHost?.kind === 'local') {
|
|
return null
|
|
}
|
|
const repoId = worktree?.repoId ?? getRepoIdFromWorktreeId(worktreeId)
|
|
const repo = findRepoRecord(state.repos, repoId)
|
|
if (!repo) {
|
|
return null
|
|
}
|
|
// Why: session mirroring is expensive; a merely focused runtime must not make
|
|
// legacy/local worktrees look remote-owned.
|
|
return getExplicitRuntimeEnvironmentIdFromHost(getRepoExecutionHostId(repo))
|
|
}
|
|
|
|
export function getExecutionHostIdForWorktree(
|
|
state: WorktreeRuntimeOwnerState,
|
|
worktreeId: string | null | undefined
|
|
): ExecutionHostId {
|
|
if (!worktreeId) {
|
|
return 'local'
|
|
}
|
|
if (worktreeId === FLOATING_TERMINAL_WORKTREE_ID) {
|
|
return 'local'
|
|
}
|
|
const activeHostId = getActiveWorkspaceExecutionHostId(state, worktreeId)
|
|
if (activeHostId) {
|
|
return activeHostId
|
|
}
|
|
const workspaceScope = parseWorkspaceKey(worktreeId)
|
|
if (workspaceScope?.type === 'folder') {
|
|
return getExecutionHostIdForFolderWorkspace(state, workspaceScope.folderWorkspaceId)
|
|
}
|
|
const hasDetectedOwner = hasIndexedDetectedWorktree(state.detectedWorktreesByRepo, worktreeId)
|
|
if (hasDetectedOwner) {
|
|
const resolution = resolveExplicitWorktreeOperationRouteResult(state, worktreeId)
|
|
if (resolution.kind === 'resolved') {
|
|
return (
|
|
resolution.route.executionHostId ??
|
|
`runtime:${encodeURIComponent(resolution.route.runtimeEnvironmentId ?? 'unresolved-owner')}`
|
|
)
|
|
}
|
|
// Why: conflicting detected publications must never enable paired-client-local PTY behavior.
|
|
return 'runtime:unresolved-owner'
|
|
}
|
|
const worktree = findWorktreeRecord(state.worktreesByRepo, worktreeId)
|
|
const worktreeHostId = getExecutionHostIdFromWorktreeHost(worktree?.hostId)
|
|
if (worktreeHostId) {
|
|
// Why: per-worktree host ownership is more specific than the repo host
|
|
// default, especially when local and runtime checkouts share a project.
|
|
return worktreeHostId
|
|
}
|
|
const repoId = worktree?.repoId ?? getRepoIdFromWorktreeId(worktreeId)
|
|
const repo = findRepoRecord(state.repos, repoId)
|
|
const hasExplicitOwner = Boolean(repo?.executionHostId?.trim() || repo?.connectionId?.trim())
|
|
if (repo && hasExplicitOwner) {
|
|
return getRepoExecutionHostId(repo)
|
|
}
|
|
const environmentId = getSingleFocusedRuntimeEnvironmentId(state)
|
|
return environmentId ? `runtime:${encodeURIComponent(environmentId)}` : 'local'
|
|
}
|
|
|
|
export function getSettingsForWorktreeRuntimeOwner(
|
|
state: WorktreeRuntimeOwnerState,
|
|
worktreeId: string | null | undefined
|
|
): Pick<GlobalSettings, 'activeRuntimeEnvironmentId'> {
|
|
return {
|
|
...state.settings,
|
|
activeRuntimeEnvironmentId: getRuntimeEnvironmentIdForWorktree(state, worktreeId)
|
|
}
|
|
}
|