Show host connection state for setup-needed targets

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Jinwoo-H
2026-07-08 18:03:33 -04:00
co-authored by Orca
parent f70f920846
commit fe984e79b4
2 changed files with 54 additions and 1 deletions
@@ -1,6 +1,9 @@
import { describe, expect, it } from 'vitest'
import { getExecutionHostLabel, type ExecutionHostId } from '../../../shared/execution-host'
import type { ExecutionHostRegistryEntry } from '../../../shared/execution-host-registry'
import type {
ExecutionHostHealth,
ExecutionHostRegistryEntry
} from '../../../shared/execution-host-registry'
import {
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY,
WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY
@@ -216,6 +219,30 @@ describe('buildProjectHostSetupOptions', () => {
])
})
it.each([
['connecting' as const, 'Connecting to host'],
['disconnected' as const, 'Connect this host to set up projects'],
['error' as const, 'Host connection needs attention']
])(
'marks %s hosts unavailable before project setup guidance',
(health: ExecutionHostHealth, detail: string) => {
const options = buildProjectHostSetupOptions({
projectId: 'project-1',
eligibleRepos: [repo('local-repo')],
hosts: [host('local'), host('ssh:builder', { label: 'Builder', health })],
projectHostSetups: [setup('local', 'project-1', 'local', 'local-repo')]
})
expect(options.at(-1)).toMatchObject({
id: 'needs-setup:ssh:builder',
kind: 'needs-setup',
label: 'Builder',
detail,
isAvailable: false
})
}
)
it('shows pending setup status for known hosts with non-ready setup metadata', () => {
const options = buildProjectHostSetupOptions({
projectId: 'project-1',
@@ -188,6 +188,15 @@ function getHostSetupAvailability(host: ExecutionHostRegistryEntry): {
detail: 'Orca server version is incompatible'
}
}
// Why: disconnected hosts cannot confirm project setup or runtime capabilities,
// so connection state needs to win over setup guidance.
const healthUnavailableDetail = getHostHealthUnavailableDetail(host.health)
if (healthUnavailableDetail) {
return {
isAvailable: false,
detail: healthUnavailableDetail
}
}
if (host.kind === 'runtime') {
if (!host.capabilities) {
return {
@@ -211,6 +220,23 @@ function getHostSetupAvailability(host: ExecutionHostRegistryEntry): {
}
}
function getHostHealthUnavailableDetail(
health: ExecutionHostRegistryEntry['health']
): string | null {
switch (health) {
case 'connecting':
return 'Connecting to host'
case 'disconnected':
return 'Connect this host to set up projects'
case 'error':
return 'Host connection needs attention'
case 'available':
case 'blocked':
case 'local':
return null
}
}
function getPendingSetupDetail(setup: ProjectHostSetup): string {
switch (setup.setupState) {
case 'not-set-up':