mirror of
https://github.com/stablyai/orca.git
synced 2026-11-04 02:57:36 +00:00
refactor(execution-host): one connection-to-host helper (#26929)
Co-authored-by: m4air <m4air@m4airs-MacBook-Air.local>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
getConnectionExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
import type { FolderWorkspace } from '../../shared/folder-workspace-types'
|
||||
@@ -96,8 +95,7 @@ function resolveDeclaredExecutionHost(owner: ExecutionHostOwner): ExecutionHostI
|
||||
if (owner.executionHostId?.trim()) {
|
||||
return parseExecutionHostId(owner.executionHostId)?.id ?? null
|
||||
}
|
||||
const connectionId = owner.connectionId?.trim()
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
return getConnectionExecutionHostId(owner.connectionId?.trim())
|
||||
}
|
||||
|
||||
/** Resolve persisted workspace ownership; unknown provenance is not local authority. */
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { ptyOwnership } from '../provider/ownership-state'
|
||||
import { getProvider, localProvider, registeredPtyProviders } from '../provider/registry'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
toSshExecutionHostId,
|
||||
getConnectionExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import type { PtyProcessInfo } from '../../../providers/pty-process-info'
|
||||
@@ -27,9 +26,7 @@ export async function listProcessesWithHostScopeFromRuntimeController(
|
||||
): Promise<{ processes: PtyProcessInfo[]; hostIds: ExecutionHostId[] }> {
|
||||
const providerSessions = await Promise.all(
|
||||
registeredPtyProviders().map(async ({ provider, connectionId }) => {
|
||||
const hostId: ExecutionHostId = connectionId
|
||||
? toSshExecutionHostId(connectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
const hostId = getConnectionExecutionHostId(connectionId)
|
||||
try {
|
||||
return {
|
||||
processes: await (connectionId ? provider.listProcesses(opts) : provider.listProcesses()),
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
} from '../../project-groups/nested-repo-import'
|
||||
import { createNestedRepoImportTargetResolver } from '../../project-groups/nested-repo-import-target'
|
||||
import { getSshGitProvider } from '../../providers/ssh-git-dispatch'
|
||||
import { LOCAL_EXECUTION_HOST_ID, toSshExecutionHostId } from '../../../shared/execution-host'
|
||||
import { getConnectionExecutionHostId } from '../../../shared/execution-host'
|
||||
import { detectRepoIconAndUpstream } from '../../repo-icon-autodetect'
|
||||
import { prepareLocalWorktreeRootForRepo } from '../../worktree-root-preparation'
|
||||
import { getActiveMultiplexer } from '../ssh'
|
||||
@@ -123,9 +123,7 @@ export function registerNestedRepoImportHandler(mainWindow: BrowserWindow, store
|
||||
const detected = await detectRepoIconAndUpstream({
|
||||
repoPath: importRepoPath,
|
||||
kind: 'git',
|
||||
executionHostId: args.connectionId
|
||||
? toSshExecutionHostId(args.connectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
executionHostId: getConnectionExecutionHostId(args.connectionId)
|
||||
})
|
||||
const repo: Repo = {
|
||||
id: randomUUID(),
|
||||
|
||||
@@ -3,9 +3,8 @@ import { awaitRuntimeFileWatcherUnsubscribes, RuntimeFileCommands } from './orca
|
||||
import { resetSshConnectionGenerations } from '../ssh/ssh-connection-generation'
|
||||
import { resetRuntimeFileMocks } from './orca-runtime-files-mock-registry'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
getConnectionExecutionHostId,
|
||||
normalizeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
|
||||
@@ -61,10 +60,7 @@ export function createRuntimeFileCommands(options?: {
|
||||
// Mirrors the real resolver: the worktree's own host outranks the repo row.
|
||||
const runtimeFileTargetExecutionHostId = (): ExecutionHostId => {
|
||||
const connectionId = store.getRepo(worktree.repoId)?.connectionId
|
||||
return (
|
||||
normalizeExecutionHostId(options?.hostId) ??
|
||||
(connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID)
|
||||
)
|
||||
return normalizeExecutionHostId(options?.hostId) ?? getConnectionExecutionHostId(connectionId)
|
||||
}
|
||||
const commands = new RuntimeFileCommands({
|
||||
getRuntimeId: () => 'runtime-1',
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
import { OrcaRuntimeWithResolveKnownWorkspaceFileTarget } from './orca-runtime-resolve-known-workspace-file-target'
|
||||
import type { PtyIncarnationId } from '../../shared/pty-incarnation'
|
||||
import { getPtyExecutionHost } from '../../shared/terminal-execution-host'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
import { getConnectionExecutionHostId, parseExecutionHostId } from '../../shared/execution-host'
|
||||
|
||||
export class OrcaRuntimeWithInvalidateAllHandlesForPty extends OrcaRuntimeWithResolveKnownWorkspaceFileTarget {
|
||||
protected invalidateAllHandlesForPty(ptyId: string, preserveHandle?: string): Set<string> {
|
||||
@@ -128,8 +124,7 @@ export class OrcaRuntimeWithInvalidateAllHandlesForPty extends OrcaRuntimeWithRe
|
||||
}
|
||||
const connection =
|
||||
connectionId === undefined ? this.ptysById.get(ptyId)?.connectionId : connectionId
|
||||
const providerKey =
|
||||
hostId ?? (connection ? toSshExecutionHostId(connection) : LOCAL_EXECUTION_HOST_ID)
|
||||
const providerKey = hostId ?? getConnectionExecutionHostId(connection)
|
||||
// A pending census predates this admission or exit, including legacy IDs without an incarnation.
|
||||
this.ptyControllerInventoryGenerationByProvider.set(providerKey, generation)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,8 @@ import type {
|
||||
import type { ResolvedWorktree } from './runtime-worktree-path-identity'
|
||||
import type { Repo } from '../../shared/repo-types'
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
import { getLocalProjectWorktreeGitOptions } from '../project-runtime-git-options'
|
||||
@@ -214,9 +214,7 @@ export class OrcaRuntimeWithPersistHeadlessTerminalTitle extends OrcaRuntimeWith
|
||||
// ambiguous one, and it is never hosted by a runtime environment.
|
||||
return {
|
||||
worktree: this.folderWorkspaceToResolvedWorktree(folderScope.folderWorkspace),
|
||||
executionHostId: folderScope.connectionId
|
||||
? toSshExecutionHostId(folderScope.connectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
executionHostId: getConnectionExecutionHostId(folderScope.connectionId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ import type { ResolvedWorktree } from './runtime-worktree-path-identity'
|
||||
import type * as PtyControllerContract from './runtime-pty-controller-contract'
|
||||
import { FLOATING_TERMINAL_WORKTREE_ID } from '../../shared/constants'
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId
|
||||
@@ -55,7 +56,7 @@ export class OrcaRuntimeWithRefreshPtyWorktreeRecordsWithControllerInventory ext
|
||||
return null
|
||||
}
|
||||
const inventoryGeneration = ++this.ptyControllerInventorySequence
|
||||
const providerKey = connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
const providerKey = getConnectionExecutionHostId(connectionId)
|
||||
const livenessObservationAtStart = this.ptyLivenessObservationSequence
|
||||
if (connectionId === undefined) {
|
||||
this.ptyControllerAggregateInventoryGeneration = inventoryGeneration
|
||||
@@ -150,7 +151,7 @@ export class OrcaRuntimeWithRefreshPtyWorktreeRecordsWithControllerInventory ext
|
||||
parseAppSshPtyId(session.id)?.connectionId ??
|
||||
(typeof connectionId === 'string' ? connectionId : null)
|
||||
const persistedIndexes = getPersistedIndexes(
|
||||
sessionConnectionId ? toSshExecutionHostId(sessionConnectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
getConnectionExecutionHostId(sessionConnectionId)
|
||||
)
|
||||
const controllerIdentity = controllerIdentityByPtyId.get(session.id)
|
||||
const persistedWorktreeId = persistedIndexes.worktreeIdByPtyId.get(session.id)
|
||||
@@ -243,8 +244,7 @@ export class OrcaRuntimeWithRefreshPtyWorktreeRecordsWithControllerInventory ext
|
||||
const ptyHostId =
|
||||
encodedHostId === 'foreign'
|
||||
? null
|
||||
: (encodedHostId ??
|
||||
(pty.connectionId ? toSshExecutionHostId(pty.connectionId) : LOCAL_EXECUTION_HOST_ID))
|
||||
: (encodedHostId ?? getConnectionExecutionHostId(pty.connectionId))
|
||||
if (!ptyHostId) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// @ts-nocheck -- mechanically split from OrcaRuntimeService; behavior is covered by AST equivalence and characterization tests.
|
||||
import { OrcaRuntimeWithPersistHeadlessTerminalTitle } from './orca-runtime-persist-headless-terminal-title'
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
import type { ResolvedWorktree } from './runtime-worktree-path-identity'
|
||||
@@ -57,9 +57,7 @@ export class OrcaRuntimeWithResolveKnownWorkspaceFileTarget extends OrcaRuntimeW
|
||||
const worktree = this.folderWorkspaceToResolvedWorktree(folderWorkspace)
|
||||
const target = {
|
||||
worktree,
|
||||
executionHostId: candidateConnectionId
|
||||
? toSshExecutionHostId(candidateConnectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
executionHostId: getConnectionExecutionHostId(candidateConnectionId)
|
||||
}
|
||||
targets.set(`${target.executionHostId}\0${worktree.id}`, target)
|
||||
} catch {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { parseAppSshPtyId } from '../../shared/ssh-pty-id'
|
||||
import { LOCAL_EXECUTION_HOST_ID, toSshExecutionHostId } from '../../shared/execution-host'
|
||||
import { getConnectionExecutionHostId } from '../../shared/execution-host'
|
||||
import { getPtyExecutionHost } from '../../shared/terminal-execution-host'
|
||||
import type { RuntimeLegacyWorkerTerminalRecoveryController } from './runtime-legacy-worker-terminal-recovery-controller'
|
||||
import {
|
||||
@@ -104,9 +104,7 @@ export async function runLegacyWorkerTerminalRecovery(
|
||||
).values()
|
||||
]
|
||||
const inventory = await ports.refreshInventory(resolvedWorktrees, provider.connectionId)
|
||||
const hostId = provider.connectionId
|
||||
? toSshExecutionHostId(provider.connectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
const hostId = getConnectionExecutionHostId(provider.connectionId)
|
||||
if (!inventory || !inventory.queriedHostIds.has(hostId)) {
|
||||
provider.entries.forEach(({ candidate }) => deferredDispatchIds.add(candidate.dispatchId))
|
||||
continue
|
||||
|
||||
@@ -2,12 +2,12 @@ import { homedir } from 'node:os'
|
||||
import { getWslHome } from '../wsl'
|
||||
import { parseWslUncPath } from '../../shared/wsl-paths'
|
||||
import {
|
||||
type ExecutionHostId,
|
||||
getConnectionExecutionHostId,
|
||||
getRepoExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
normalizeExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId
|
||||
type ExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
import { getRepoIdFromWorktreeId } from '../../shared/worktree/id'
|
||||
import type { IPtyProvider } from '../providers/types'
|
||||
@@ -124,7 +124,7 @@ export function folderExecutionHostId(folder: {
|
||||
}): ExecutionHostId {
|
||||
return (
|
||||
normalizeExecutionHostId(folder.executionHostId) ??
|
||||
(folder.connectionId ? toSshExecutionHostId(folder.connectionId) : LOCAL_EXECUTION_HOST_ID)
|
||||
getConnectionExecutionHostId(folder.connectionId)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
getConnectionExecutionHostId,
|
||||
getRepoExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../shared/execution-host'
|
||||
import type { FolderWorkspace } from '../../shared/folder-workspace-types'
|
||||
@@ -43,8 +43,7 @@ export class RuntimeWorkspaceSessionController {
|
||||
}
|
||||
return parsedHostId
|
||||
}
|
||||
const connectionId = this.deps.resolveFolderConnectionId(workspace)
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
return getConnectionExecutionHostId(this.deps.resolveFolderConnectionId(workspace))
|
||||
}
|
||||
const resolvedWorktreeId = scope?.type === 'worktree' ? scope.worktreeId : worktreeId
|
||||
const repo = store?.getRepo?.(getRepoIdFromWorktreeId(resolvedWorktreeId))
|
||||
@@ -156,11 +155,7 @@ export class RuntimeWorkspaceSessionController {
|
||||
? (parseExecutionHostId(workspace.executionHostId)?.id ?? null)
|
||||
: null
|
||||
const connectionId = explicitHostId ? null : this.deps.resolveFolderConnectionId(workspace)
|
||||
return [
|
||||
workspace.id,
|
||||
explicitHostId ??
|
||||
(connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID)
|
||||
] as const
|
||||
return [workspace.id, explicitHostId ?? getConnectionExecutionHostId(connectionId)] as const
|
||||
})
|
||||
)
|
||||
const hostIds = new Set<ExecutionHostId>(['local'])
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { randomBytes } from 'node:crypto'
|
||||
import { toSshExecutionHostId } from '../../shared/execution-host'
|
||||
import { getConnectionExecutionHostId } from '../../shared/execution-host'
|
||||
|
||||
const SESSION_COUNTER_BITS = 13
|
||||
const SESSION_COUNTER_STRIDE = 2 ** SESSION_COUNTER_BITS
|
||||
@@ -105,7 +105,7 @@ export function assertSshMutationExpectation(
|
||||
expectedGeneration: number | undefined,
|
||||
expectedExecutionHostId?: string
|
||||
): void {
|
||||
const actualExecutionHostId = connectionId ? toSshExecutionHostId(connectionId) : 'local'
|
||||
const actualExecutionHostId = getConnectionExecutionHostId(connectionId)
|
||||
if (expectedExecutionHostId !== undefined && expectedExecutionHostId !== actualExecutionHostId) {
|
||||
throw new Error('Workspace host changed; refresh and try again')
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { findIndexedRepoOwnerForHost } from '@/lib/worktree-runtime-owner-index'
|
||||
import { getRemoteRuntimePtyEnvironmentId } from '@/runtime/runtime-terminal-stream'
|
||||
import type { AgentStatusEntry } from '../../../../shared/agent-status-types'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
getConnectionExecutionHostId,
|
||||
toRuntimeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
@@ -126,7 +126,7 @@ function resolveActivityExecutionHostId(
|
||||
return toRuntimeExecutionHostId(runtimeEnvironmentId)
|
||||
}
|
||||
if (entry.connectionId !== undefined) {
|
||||
return entry.connectionId ? toSshExecutionHostId(entry.connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
return getConnectionExecutionHostId(entry.connectionId)
|
||||
}
|
||||
const connectionId = parseAppSshPtyId(terminalPtyId ?? '')?.connectionId
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : undefined
|
||||
|
||||
@@ -9,9 +9,9 @@ import { translate } from '@/i18n/i18n'
|
||||
import { extractIpcErrorMessage } from '@/lib/ipc-error'
|
||||
import { findKnownWorktreeById } from '@/store/slices/worktrees/listing/detected-worktree-meta'
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toRuntimeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import { getConnectionIdFromState } from '@/lib/connection-context'
|
||||
@@ -106,9 +106,7 @@ export function resolveNativeChatAttachmentHost(
|
||||
}
|
||||
const hostId = runtimeId
|
||||
? toRuntimeExecutionHostId(runtimeId)
|
||||
: connectionId
|
||||
? toSshExecutionHostId(connectionId)
|
||||
: 'local'
|
||||
: getConnectionExecutionHostId(connectionId)
|
||||
return findKnownWorktreeById(state, worktreeId, hostId) ? hostId : null
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,9 @@ import {
|
||||
} from '../../../../shared/new-workspace/workspace-source'
|
||||
import { isPathInsideOrEqual } from '../../../../shared/cross-platform-path'
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
getRepoExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
normalizeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import { getProjectGroupSubtreeIds } from '../../../../shared/project-groups'
|
||||
@@ -33,9 +32,7 @@ function getProjectGroupExecutionHostId(projectGroup: ProjectGroup): ExecutionHo
|
||||
if (executionHostId) {
|
||||
return executionHostId
|
||||
}
|
||||
return projectGroup.connectionId
|
||||
? toSshExecutionHostId(projectGroup.connectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
return getConnectionExecutionHostId(projectGroup.connectionId)
|
||||
}
|
||||
|
||||
export function getFolderSourceRepos(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ALL_EXECUTION_HOSTS_SCOPE,
|
||||
getConnectionExecutionHostId,
|
||||
normalizeExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
@@ -110,7 +111,7 @@ function getProjectGroupExecutionHostIdForFolderPathStatus(
|
||||
if (executionHostId) {
|
||||
return executionHostId
|
||||
}
|
||||
return group.connectionId ? toSshExecutionHostId(group.connectionId) : 'local'
|
||||
return getConnectionExecutionHostId(group.connectionId)
|
||||
}
|
||||
|
||||
export function getFolderPathStatusRouteOptionsForRows({
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { toSshExecutionHostId } from '../../../../shared/execution-host'
|
||||
import { getConnectionExecutionHostId } from '../../../../shared/execution-host'
|
||||
import { attachIpcPty } from './ipc-pty-attach'
|
||||
import { connectIpcPty } from './ipc-pty-connect'
|
||||
import { createIpcPtySessionHandlers } from './ipc-pty-session-handlers'
|
||||
@@ -296,7 +296,7 @@ export function createIpcPtyTransport(opts: IpcPtyTransportOptions = {}): PtyTra
|
||||
isConnected: () => connected,
|
||||
getPtyId: () => ptyId,
|
||||
getConnectionId: () => connectionId ?? null,
|
||||
getExecutionHostId: () => (connectionId ? toSshExecutionHostId(connectionId) : 'local'),
|
||||
getExecutionHostId: () => getConnectionExecutionHostId(connectionId),
|
||||
getRuntimeEnvironmentId: () => null,
|
||||
getLocalSessionMetadata: () =>
|
||||
connectionId
|
||||
|
||||
@@ -16,9 +16,8 @@ import {
|
||||
type TerminalFileContext
|
||||
} from './terminal-file-path-mapping'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
getConnectionExecutionHostId,
|
||||
toRuntimeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import { statUserOpenedPath } from '@/lib/user-opened-local-path'
|
||||
@@ -231,9 +230,7 @@ export function openDetectedFilePath(
|
||||
const runtimeOwnerId = fileContext.settings?.activeRuntimeEnvironmentId?.trim()
|
||||
const executionHostId = runtimeOwnerId
|
||||
? toRuntimeExecutionHostId(runtimeOwnerId)
|
||||
: fileContext.connectionId
|
||||
? toSshExecutionHostId(fileContext.connectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
: getConnectionExecutionHostId(fileContext.connectionId)
|
||||
const siblingRoute = findWorkspaceFileRoute(store, executionHostId, mappedFilePath)
|
||||
if (siblingRoute) {
|
||||
targetWorktreeId = siblingRoute.worktreeId
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
normalizeExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../shared/execution-host'
|
||||
|
||||
@@ -13,9 +13,7 @@ export function resolveJiraSourceHostId(args: {
|
||||
}): ExecutionHostId {
|
||||
const groupHostId =
|
||||
normalizeExecutionHostId(args.groupExecutionHostId) ??
|
||||
(args.groupConnectionId
|
||||
? toSshExecutionHostId(args.groupConnectionId)
|
||||
: LOCAL_EXECUTION_HOST_ID)
|
||||
getConnectionExecutionHostId(args.groupConnectionId)
|
||||
const hostId = normalizeExecutionHostId(args.workspaceHostId) ?? groupHostId
|
||||
return parseExecutionHostId(hostId)?.kind === 'ssh' ? LOCAL_EXECUTION_HOST_ID : hostId
|
||||
}
|
||||
|
||||
@@ -4,12 +4,7 @@ import type { Project, ProjectHostSetup } from '../../../shared/project-types'
|
||||
import type { Repo } from '../../../shared/repo-types'
|
||||
import { isClipboardTextByteLengthOverLimit } from '../../../shared/clipboard-text'
|
||||
import type { ExecutionHostRegistryEntry } from '../../../shared/execution-host-registry'
|
||||
import {
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../shared/execution-host'
|
||||
import { getRepoExecutionHostId, type ExecutionHostId } from '../../../shared/execution-host'
|
||||
import {
|
||||
getDuplicateProjectDetailsById,
|
||||
type ProjectSetupDirectory
|
||||
@@ -154,12 +149,7 @@ function getProjectGroupDetail(group: ProjectGroup): string {
|
||||
}
|
||||
|
||||
export function getNewWorkspaceProjectGroupHostId(group: ProjectGroup): ExecutionHostId {
|
||||
const executionHost = parseExecutionHostId(group.executionHostId)
|
||||
if (executionHost) {
|
||||
return executionHost.id
|
||||
}
|
||||
const connectionId = group.connectionId?.trim()
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
return getRepoExecutionHostId(group)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
getRepoExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toRuntimeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../shared/execution-host'
|
||||
|
||||
@@ -58,12 +57,7 @@ export function getCatalogOwnerHostId(owner: {
|
||||
connectionId?: string | null
|
||||
executionHostId?: string | null
|
||||
}): ExecutionHostId {
|
||||
const explicitHost = parseExecutionHostId(owner.executionHostId)
|
||||
if (explicitHost) {
|
||||
return explicitHost.id
|
||||
}
|
||||
const connectionId = owner.connectionId?.trim()
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : 'local'
|
||||
return getRepoExecutionHostId(owner)
|
||||
}
|
||||
|
||||
function buildCatalogOwnerIndex<
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import type { GlobalSettings } from '../../../../shared/global-settings-types'
|
||||
import type { ProjectGroup } from '../../../../shared/project-group-types'
|
||||
import {
|
||||
getRepoExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
normalizeExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from '../../../../shared/execution-host'
|
||||
import { findIndexedProjectGroupOwner } from '@/lib/worktree-runtime-owner-index'
|
||||
@@ -21,12 +20,7 @@ type ProjectGroupOwnerRoutingState = {
|
||||
// Why: persisted rows predate host stamping and may carry padded/unparseable ids; normalize so
|
||||
// routing and catalog identity agree on the same owner host.
|
||||
export function getProjectGroupHostId(group: ProjectGroupHostParts): ExecutionHostId {
|
||||
const executionHostId = normalizeExecutionHostId(group.executionHostId)
|
||||
if (executionHostId) {
|
||||
return executionHostId
|
||||
}
|
||||
const connectionId = group.connectionId?.trim()
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
return getRepoExecutionHostId(group)
|
||||
}
|
||||
|
||||
export function catalogOwnsHost(catalogHostId: string, rowHostId: string): boolean {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import {
|
||||
ALL_EXECUTION_HOSTS_SCOPE,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
getConnectionExecutionHostId,
|
||||
getExecutionHostLabel,
|
||||
getLocalExecutionHostLabel,
|
||||
getRepoExecutionHostId,
|
||||
@@ -97,6 +98,12 @@ describe('execution host identity', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('maps a legacy connection id to its host without trimming it', () => {
|
||||
expect(getConnectionExecutionHostId(null)).toBe('local')
|
||||
expect(getConnectionExecutionHostId('')).toBe('local')
|
||||
expect(getConnectionExecutionHostId('a b')).toBe('ssh:a%20b')
|
||||
})
|
||||
|
||||
it('derives repo ownership from SSH connection ids', () => {
|
||||
expect(getRepoExecutionHostId({ connectionId: null })).toBe(LOCAL_EXECUTION_HOST_ID)
|
||||
expect(getRepoExecutionHostId({ connectionId: 'ssh-target-1' })).toBe('ssh:ssh-target-1')
|
||||
|
||||
@@ -54,6 +54,13 @@ export function toSshExecutionHostId(targetId: string): `ssh:${string}` {
|
||||
return `ssh:${encodeURIComponent(targetId)}`
|
||||
}
|
||||
|
||||
/** Legacy `connectionId` spelling: absent means this machine, present means that SSH target. */
|
||||
export function getConnectionExecutionHostId(
|
||||
connectionId: string | null | undefined
|
||||
): ExecutionHostId {
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
}
|
||||
|
||||
export function toRuntimeExecutionHostId(environmentId: string): `runtime:${string}` {
|
||||
return `runtime:${encodeURIComponent(environmentId)}`
|
||||
}
|
||||
@@ -165,8 +172,7 @@ export function getRepoExecutionHostId(repo: {
|
||||
if (executionHostId) {
|
||||
return executionHostId
|
||||
}
|
||||
const connectionId = normalizeHostPart(repo.connectionId)
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
return getConnectionExecutionHostId(normalizeHostPart(repo.connectionId))
|
||||
}
|
||||
|
||||
export function getSshTargetIdForExecutionHost(
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import type { FolderWorkspace } from './folder-workspace-types'
|
||||
import type { Worktree } from './worktree/types'
|
||||
import { folderWorkspaceKey } from './workspace-scope'
|
||||
import { parseExecutionHostId, toSshExecutionHostId, type ExecutionHostId } from './execution-host'
|
||||
import {
|
||||
getConnectionExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
type ExecutionHostId
|
||||
} from './execution-host'
|
||||
import { composeWorktreeHostIdentity } from './worktree/host-qualified-identity'
|
||||
import { normalizeWorkspaceCreatorProvenance } from './workspace-creator-provenance'
|
||||
import { getWorkspaceAttachments } from './workspace-attachments'
|
||||
@@ -32,10 +36,7 @@ export function projectGroupIdFromRepoId(repoId: string | null | undefined): str
|
||||
function getFolderWorkspaceWorktreeHostId(
|
||||
workspace: Pick<FolderWorkspace, 'executionHostId' | 'connectionId'>
|
||||
): ExecutionHostId {
|
||||
return (
|
||||
workspace.executionHostId ??
|
||||
(workspace.connectionId ? toSshExecutionHostId(workspace.connectionId) : 'local')
|
||||
)
|
||||
return workspace.executionHostId ?? getConnectionExecutionHostId(workspace.connectionId)
|
||||
}
|
||||
|
||||
export function getFolderWorkspaceHostIdentity(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
getRepoExecutionHostId,
|
||||
LOCAL_EXECUTION_HOST_ID,
|
||||
type ExecutionHostId,
|
||||
normalizeExecutionHostId,
|
||||
parseExecutionHostId,
|
||||
toRuntimeExecutionHostId,
|
||||
toSshExecutionHostId
|
||||
type ExecutionHostId
|
||||
} from './execution-host'
|
||||
import {
|
||||
areTaskProviderIdentitiesEqual,
|
||||
@@ -113,7 +113,7 @@ export function buildTaskSourceContextFromRepo(args: {
|
||||
return normalizeTaskSourceContext({
|
||||
provider: args.provider,
|
||||
projectId: args.projectId,
|
||||
hostId: getRepoHostId(args.repo),
|
||||
hostId: getRepoExecutionHostId(args.repo),
|
||||
repoId: args.repo.id,
|
||||
projectHostSetupId: args.projectHostSetupId,
|
||||
providerIdentity: args.providerIdentity,
|
||||
@@ -195,15 +195,6 @@ export function buildWorkspaceRunContext(args: {
|
||||
}
|
||||
}
|
||||
|
||||
function getRepoHostId(repo: Pick<Repo, 'connectionId' | 'executionHostId'>): ExecutionHostId {
|
||||
const explicit = normalizeExecutionHostId(repo.executionHostId)
|
||||
if (explicit) {
|
||||
return explicit
|
||||
}
|
||||
const connectionId = normalizeNonEmptyString(repo.connectionId)
|
||||
return connectionId ? toSshExecutionHostId(connectionId) : LOCAL_EXECUTION_HOST_ID
|
||||
}
|
||||
|
||||
function normalizeTaskProvider(value: unknown): TaskProvider | null {
|
||||
switch (value) {
|
||||
case 'github':
|
||||
|
||||
Reference in New Issue
Block a user