Files
orca/src/main/runtime/runtime-skill-install-authority.ts
T
OrcaWinandm4air 6a303be248 refactor(main): agent detection, automations, skills, AI vault and ephemeral VM drop SSH provider arms (#27511)
* refactor(main): agent detection, automations, AI vault and ephemeral VM drop SSH provider arms

* refactor(skills): refuse SSH skill destinations at the branch and delete the relay skill services

* test(preflight): clear the local-detection mock before the SSH refusal cases

---------

Co-authored-by: m4air <m4air@Mac.localdomain>
2026-10-11 09:54:46 -07:00

168 lines
6.1 KiB
TypeScript

import { homedir } from 'node:os'
import { getWslHome } from '../wsl'
import { parseWslUncPath } from '../../shared/wsl-paths'
import {
getConnectionExecutionHostId,
getRepoExecutionHostId,
LOCAL_EXECUTION_HOST_ID,
normalizeExecutionHostId,
parseExecutionHostId,
type ExecutionHostId
} from '../../shared/execution-host'
import { getRepoIdFromWorktreeId } from '../../shared/worktree/id'
import type { SkillInstallDestinationAuthority } from '../skills/skill-install-destinations'
import {
resolveEnvironmentSkillProviderRoots,
resolveWslGrokSkillProviderRoot,
withClaudeSkillProviderRoot
} from '../skills/skill-provider-runtime-roots'
import type { SkillInstallRequest, SkillProviderRootOverrides } from './runtime-skill-types'
import type { RuntimeSkillCommandHost } from './runtime-skill-command-surface'
/** Whether the destination lives on an SSH target; a workspace that cannot be placed throws. */
export async function isSkillSshDestination(
host: RuntimeSkillCommandHost,
destination: SkillInstallRequest['destination']
): Promise<boolean> {
if (destination.scope === 'global') {
return destination.executionTarget?.kind === 'ssh'
}
if (destination.worktreeId) {
const repos = host
.listRepos()
.filter((candidate) => candidate.id === getRepoIdFromWorktreeId(destination.worktreeId!))
const hostIds = new Set(repos.map((repo) => getRepoExecutionHostId(repo)))
if (hostIds.size > 1) {
throw new Error('skill-install-workspace-host-ambiguous')
}
const executionHost = parseExecutionHostId([...hostIds][0])
if (!executionHost || executionHost.kind === 'local') {
return false
}
// Why false and not a throw: base treated any non-ssh host as "not an SSH install" and
// fell through to the local path; a runtime-owned repo must not hard-error here.
if (executionHost.kind !== 'ssh') {
return false
}
// Why the resolved inventory and not showManagedWorktree: a worktree id can collide across
// hosts, and only this list carries the hostId needed to pick the SSH-owned row.
const worktrees = (await host.listResolvedWorktrees()).filter(
(candidate) =>
candidate.id === destination.worktreeId &&
(!candidate.hostId || candidate.hostId === executionHost.id)
)
if (worktrees.length !== 1) {
throw new Error(
worktrees.length > 1
? 'skill-install-workspace-host-ambiguous'
: 'skill-install-workspace-not-found'
)
}
return true
}
const folders = host
.listFolderWorkspaces()
.filter((candidate) => candidate.id === destination.folderWorkspaceId)
const folderHosts = new Set(folders.map((folder) => folderExecutionHostId(folder)))
if (folders.length > 1 || folderHosts.size > 1) {
throw new Error('skill-install-workspace-host-ambiguous')
}
// Why only ssh: base gated this branch on `folder.connectionId`, so any other host simply
// was not an SSH install and fell through to the local path.
return Boolean(folders[0]) && parseExecutionHostId([...folderHosts][0])?.kind === 'ssh'
}
export async function resolveSkillProviderRoots(
host: RuntimeSkillCommandHost,
destination: {
scope: 'global' | 'workspace'
homeDirectory: string
workspaceDirectory?: string
wslDistro?: string
}
): Promise<SkillProviderRootOverrides> {
if (destination.scope !== 'global') {
return {}
}
const grok = destination.wslDistro
? await resolveWslGrokSkillProviderRoot(destination.wslDistro)
: null
const roots = destination.wslDistro
? grok
? { grok }
: {}
: resolveEnvironmentSkillProviderRoots()
const config = host.getClaudeConfigDirectory?.(
destination.wslDistro
? { runtime: 'wsl', wslDistro: destination.wslDistro }
: { runtime: 'host' }
)
return withClaudeSkillProviderRoot(roots, config)
}
export function folderExecutionHostId(folder: {
connectionId?: string | null
executionHostId?: ExecutionHostId | null
}): ExecutionHostId {
return (
normalizeExecutionHostId(folder.executionHostId) ??
getConnectionExecutionHostId(folder.connectionId)
)
}
export function createSkillInstallAuthority(
host: RuntimeSkillCommandHost
): SkillInstallDestinationAuthority {
return {
environmentId: host.getRuntimeId(),
homeDirectory: homedir(),
resolveWorktree: async (id) => {
const repos = host
.listRepos()
.filter((candidate) => candidate.id === getRepoIdFromWorktreeId(id))
const hostIds = new Set(repos.map((repo) => getRepoExecutionHostId(repo)))
if (hostIds.size > 1) {
throw new Error('skill-install-workspace-host-ambiguous')
}
if (hostIds.size === 1 && !hostIds.has(LOCAL_EXECUTION_HOST_ID)) {
throw new Error('skill-install-ssh-dispatch-required')
}
// Why no catch: swallowing here reports a transient git/IO failure as a missing
// workspace and loses the real cause.
const worktree = await host.showManagedWorktree(`id:${id}`)
if (worktree.id !== id) {
return null
}
const projectRuntime = host.resolveProjectRuntimeForWorktree?.(id)
return {
id,
path: worktree.path,
...(projectRuntime?.status === 'resolved' &&
projectRuntime.runtime?.kind === 'wsl' &&
projectRuntime.runtime.distro
? { wslDistro: projectRuntime.runtime.distro }
: {})
}
},
resolveFolderWorkspace: async (id) => {
const workspaces = host.listFolderWorkspaces().filter((candidate) => candidate.id === id)
if (workspaces.length > 1) {
throw new Error('skill-install-workspace-host-ambiguous')
}
const workspace = workspaces[0]
if (!workspace) {
return null
}
if (folderExecutionHostId(workspace) !== LOCAL_EXECUTION_HOST_ID) {
throw new Error('skill-install-ssh-dispatch-required')
}
const wsl = parseWslUncPath(workspace.folderPath)
return { id, path: workspace.folderPath, ...(wsl ? { wslDistro: wsl.distro } : {}) }
},
resolveWsl: async (distro) =>
process.platform === 'win32'
? ((homeDirectory) => (homeDirectory ? { homeDirectory } : null))(getWslHome(distro))
: null
}
}