mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
`ResolvedRuntimeFileTarget` carried `connectionId?: string` and no host id, so `undefined` spelled three different answers at once — "runtime: host", "unresolved" and "genuinely local". Its sole resolver read `store.getRepo(worktree.repoId)?.connectionId` and never looked at `worktree.hostId`, which outranks every repo row, so one arbitrarily chosen row decided the execution host for ~30 filesystem dispatches. This is #18307's defect in the same file family; it was deliberately left out of that PR rather than doubling an already-36-site diff. The target now carries `executionHostId: ExecutionHostId` (never null, never optional), resolved through `resolveWorktreeHostRouting` — the same adapter #18307 added — and dispatched through #18296's `resolveFilesystemRouteForHost`. Dispatch sites call `requireRuntimeFileProvider`, where `null` means exactly one thing: the host is `local` and the read happens here. Four answers that used to collapse into one: - `ssh:x` with a rival row on `ssh:y` — routes to x. Previously the first row won. - `local` with a surviving `connectionId` — a row contradicting itself; no SSH connection is handed out. - `runtime:<env>` — throws `ExecutionHostNotDispatchableError`. Its repo row's connection names a target in the *server's* namespace; reading it here reaches a same-named target on this client. - rival rows disagreeing with no worktree host — `worktree_execution_host_unresolved`, matching the launch and Git paths rather than guessing a row. Two further reads stop degrading. `assertRuntimeFileMutationExpectation` recomputed the host from `connectionId`, so a client's host expectation could pass against a host the workspace never named; it now compares the resolved host. And the cross-workspace terminal tap coalesced `knownWorkspaceTarget?.connectionId ?? connectionId`, so a sibling workspace resolved as `local` inherited the origin worktree's SSH target and statted a local path on the remote box; a non-optional host id replaces rather than coalesces. An unreachable SSH host still throws `SSH_FILESYSTEM_PROVIDER_UNAVAILABLE_MESSAGE`; loss of contact is never evidence of locality (docs/reference/ssh-execution-boundary.md). Quick-open listing and path search keep degrading to empty for an unreachable host — that is a false negative, not a local answer — and now do so only for a host that really is remote. The whole `runtime-file-commands-*` family carries `@ts-nocheck` from a mechanical class split, so removing the field could not raise the compile errors that made #18307 safe. `runtime-file-command-target.ts` is deliberately checked, and a ratchet test stands in for the errors the family cannot produce. No wire change: `ResolvedRuntimeFileTarget` is main-process internal, and the SSH watcher-release and grant keys are byte-identical to before.
91 lines
3.8 KiB
TypeScript
91 lines
3.8 KiB
TypeScript
import type { ExecutionHostId } from '../../shared/execution-host'
|
|
import type { GitWorktreeInfo, Worktree } from '../../shared/worktree/types'
|
|
import {
|
|
ExecutionHostNotDispatchableError,
|
|
resolveFilesystemRouteForHost
|
|
} from '../providers/execution-host-provider-dispatch'
|
|
import { SSH_FILESYSTEM_PROVIDER_UNAVAILABLE_MESSAGE } from '../providers/ssh-filesystem-dispatch'
|
|
import type { IFilesystemProvider } from '../providers/types'
|
|
|
|
export type ResolvedRuntimeFileWorktree = Worktree & { git: GitWorktreeInfo }
|
|
|
|
export type ResolvedRuntimeFileTarget = {
|
|
worktree: ResolvedRuntimeFileWorktree
|
|
/**
|
|
* The host whose filesystem holds this workspace. Never optional and never null: the field it
|
|
* replaced (`connectionId?: string`) spelled "runtime host", "unresolved" and "genuinely local"
|
|
* all as `undefined`, so every path that could not resolve answered "local" and read remote
|
|
* paths on the client (#11163). Unresolved now fails at resolution time instead of arriving here
|
|
* as a silently-local target. Mirrors `RuntimeGitTarget.executionHostId`.
|
|
*/
|
|
executionHostId: ExecutionHostId
|
|
}
|
|
|
|
/** A workspace-relative path already joined onto its host's root; `executionHostId` routes it. */
|
|
export type RuntimeFileExplorerPath = {
|
|
worktree: ResolvedRuntimeFileWorktree
|
|
path: string
|
|
executionHostId: ExecutionHostId
|
|
}
|
|
|
|
/**
|
|
* The two hosts this process can itself run a runtime filesystem command on, narrowed from the
|
|
* shared host-keyed route in `src/main/providers/execution-host-provider-dispatch.ts`.
|
|
*
|
|
* `runtime:<env>` is deliberately not a variant, for the same reason it is not one for Git: the
|
|
* files live on that environment's own server, which normalizes the call to its own `local`, and
|
|
* the SSH target on its repo row is that server's *nested* one — addressable only as the pair
|
|
* (environmentId, targetId). Handing that id to this client's SSH table reads a same-named target
|
|
* in the wrong namespace, so it throws rather than routing.
|
|
*/
|
|
export type RuntimeFileRoute =
|
|
| { kind: 'local' }
|
|
/** `provider: null` is "remote and currently unreachable" — never "read it here". */
|
|
| { kind: 'ssh'; connectionId: string; provider: IFilesystemProvider | null }
|
|
|
|
/** The remote half of the route, for leaf helpers that only ever run against an SSH host. */
|
|
export type RuntimeFileSshRoute = Extract<RuntimeFileRoute, { kind: 'ssh' }>
|
|
|
|
export function runtimeFileRouteForTarget(target: {
|
|
executionHostId: ExecutionHostId
|
|
}): RuntimeFileRoute {
|
|
const route = resolveFilesystemRouteForHost(target.executionHostId)
|
|
switch (route.kind) {
|
|
case 'local':
|
|
return { kind: 'local' }
|
|
case 'ssh':
|
|
return { kind: 'ssh', connectionId: route.connectionId, provider: route.provider }
|
|
case 'runtime':
|
|
throw new ExecutionHostNotDispatchableError(route.hostId)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* `null` means exactly one thing: the host is `local`, and this command reads and writes here. An
|
|
* unreachable SSH host and a `runtime:` host both throw.
|
|
*/
|
|
export function requireRuntimeFileProvider(target: {
|
|
executionHostId: ExecutionHostId
|
|
}): IFilesystemProvider | null {
|
|
const route = runtimeFileRouteForTarget(target)
|
|
if (route.kind === 'local') {
|
|
return null
|
|
}
|
|
if (!route.provider) {
|
|
throw new Error(SSH_FILESYSTEM_PROVIDER_UNAVAILABLE_MESSAGE)
|
|
}
|
|
return route.provider
|
|
}
|
|
|
|
/**
|
|
* The SSH target id for the leaf helpers that still address a connection by name — watcher release
|
|
* keys, re-arm registration, remote path stats. `undefined` is `local`; a `runtime:` host throws
|
|
* rather than surrendering its nested target id to this client's namespace.
|
|
*/
|
|
export function runtimeFileSshTargetId(target: {
|
|
executionHostId: ExecutionHostId
|
|
}): string | undefined {
|
|
const route = runtimeFileRouteForTarget(target)
|
|
return route.kind === 'ssh' ? route.connectionId : undefined
|
|
}
|