mirror of
https://github.com/stablyai/orca.git
synced 2026-10-16 08:03:09 +00:00
Surface host model runtime capability skew
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
@@ -98,7 +98,7 @@ Done means: settings pages no longer imply one global provider/account when the
|
||||
- [~] Audit caches keyed by repo id, path, owner/repo, or active runtime and add host/source identity where needed.
|
||||
- [~] Ensure request ownership is explicit for provider fetches, provider mutations, file-system calls, git calls, terminal calls, and automation runs.
|
||||
- [~] Add capability negotiation for remote servers so new clients can degrade gracefully with older servers.
|
||||
- [~] Add version-skew UX for unsupported source-context or host-context APIs.
|
||||
- [x] Add version-skew UX for unsupported source-context or host-context APIs.
|
||||
- [x] Ensure SSH hosts and remote servers expose comparable availability/health states to the UI.
|
||||
- [x] Keep future cloud VM support as a host capability model, not a separate user-facing mental model.
|
||||
|
||||
@@ -246,3 +246,4 @@ Done means: reviewers and future agents can understand the vision, implementatio
|
||||
- [x] 2026-06-12: Preserved explicit automation run-host context in CLI project selectors: `orca automations create/edit --project/--host` and `--project-host-setup` now send `WorkspaceRunContext` alongside the legacy repo selector, so scheduled runs retain logical project, host, setup, repo, and path identity. Verified with focused CLI regressions (108 tests), targeted oxlint, full `pnpm run typecheck`, and `git diff --check`.
|
||||
- [x] 2026-06-12: Added an advanced automation CLI source selector via `--source-context <json|null>` for create/edit, normalizing the shared `TaskSourceContext` shape before RPC and allowing edit callers to clear the source context with `null`; verified with focused CLI regressions (111 tests), targeted oxlint, full `pnpm run typecheck`, and `git diff --check`.
|
||||
- [x] 2026-06-12: Added a reusable Tasks source availability notice and wired unavailable source-host/account states into the Tasks source chrome, so disconnected/auth-needed/blocked hosts show an inline status, fully unavailable sources disable their icon, and partial multi-host failures remain selectable with warning copy; verified with focused source-summary tests, targeted oxlint, and full `pnpm run typecheck`.
|
||||
- [x] 2026-06-12: Added explicit remote-runtime Host model capability names for project setup, task source context, and workspace run context, then surfaced a Settings saved-server summary that says whether Host model support is ready, unknown, or requires a server update for specific missing capabilities; verified with focused RuntimeEnvironmentsPane tests, targeted oxlint, and full `pnpm run typecheck`.
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import {
|
||||
MIN_COMPATIBLE_RUNTIME_SERVER_VERSION,
|
||||
RUNTIME_PROTOCOL_VERSION
|
||||
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY,
|
||||
RUNTIME_PROTOCOL_VERSION,
|
||||
TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY,
|
||||
WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY
|
||||
} from '../../../../shared/protocol-version'
|
||||
import {
|
||||
evaluateHostDetails,
|
||||
getActiveServerModeDescription,
|
||||
getHostDetailsDescription,
|
||||
getHostDetailsSummary,
|
||||
getHostModelCapabilitySummary,
|
||||
getRuntimeCapabilitiesSummary,
|
||||
type RuntimeHostDetails
|
||||
} from './RuntimeEnvironmentsPane'
|
||||
@@ -129,6 +133,47 @@ describe('RuntimeEnvironmentsPane host details', () => {
|
||||
).toBe('runtime.environments.v1, browser.screencast.v1, terminal.multiplex.v1 +1')
|
||||
})
|
||||
|
||||
it('summarizes Host model capability support for version-skewed servers', () => {
|
||||
expect(
|
||||
getHostModelCapabilitySummary({
|
||||
runtimeId: 'runtime',
|
||||
rendererGraphEpoch: 1,
|
||||
graphStatus: 'ready',
|
||||
authoritativeWindowId: 1,
|
||||
liveTabCount: 0,
|
||||
liveLeafCount: 0
|
||||
})
|
||||
).toBe('Host model support: checking server capabilities')
|
||||
|
||||
expect(
|
||||
getHostModelCapabilitySummary({
|
||||
runtimeId: 'runtime',
|
||||
rendererGraphEpoch: 1,
|
||||
graphStatus: 'ready',
|
||||
authoritativeWindowId: 1,
|
||||
liveTabCount: 0,
|
||||
liveLeafCount: 0,
|
||||
capabilities: [
|
||||
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY,
|
||||
TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY,
|
||||
WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY
|
||||
]
|
||||
})
|
||||
).toBe('Host model support: ready')
|
||||
|
||||
expect(
|
||||
getHostModelCapabilitySummary({
|
||||
runtimeId: 'runtime',
|
||||
rendererGraphEpoch: 1,
|
||||
graphStatus: 'ready',
|
||||
authoritativeWindowId: 1,
|
||||
liveTabCount: 0,
|
||||
liveLeafCount: 0,
|
||||
capabilities: [PROJECT_HOST_SETUP_RUNTIME_CAPABILITY]
|
||||
})
|
||||
).toBe('Host model support: update server for task source context, workspace run context')
|
||||
})
|
||||
|
||||
it('explains that selecting a saved server is the explicit default Host mode', () => {
|
||||
expect(getActiveServerModeDescription(true)).toContain('default Host')
|
||||
expect(getActiveServerModeDescription(true)).toContain('browser/mobile handoff')
|
||||
|
||||
@@ -15,7 +15,10 @@ import {
|
||||
} from '../../../../shared/protocol-compat'
|
||||
import {
|
||||
MIN_COMPATIBLE_RUNTIME_SERVER_VERSION,
|
||||
RUNTIME_PROTOCOL_VERSION
|
||||
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY,
|
||||
RUNTIME_PROTOCOL_VERSION,
|
||||
TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY,
|
||||
WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY
|
||||
} from '../../../../shared/protocol-version'
|
||||
import { Button } from '../ui/button'
|
||||
import { Input } from '../ui/input'
|
||||
@@ -110,6 +113,60 @@ export function getRuntimeCapabilitiesSummary(status: RuntimeStatus | null | und
|
||||
return hiddenCount > 0 ? `${visibleCapabilities} +${hiddenCount}` : visibleCapabilities
|
||||
}
|
||||
|
||||
export function getHostModelCapabilitySummary(
|
||||
status: RuntimeStatus | null | undefined
|
||||
): string | null {
|
||||
if (!status) {
|
||||
return null
|
||||
}
|
||||
const capabilities = status.capabilities
|
||||
if (!capabilities) {
|
||||
return translate(
|
||||
'auto.components.settings.RuntimeEnvironmentsPane.hostModelCapabilityUnknown',
|
||||
'Host model support: checking server capabilities'
|
||||
)
|
||||
}
|
||||
const missing = [
|
||||
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY,
|
||||
TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY,
|
||||
WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY
|
||||
].filter((capability) => !capabilities.includes(capability))
|
||||
if (missing.length === 0) {
|
||||
return translate(
|
||||
'auto.components.settings.RuntimeEnvironmentsPane.hostModelCapabilitySupported',
|
||||
'Host model support: ready'
|
||||
)
|
||||
}
|
||||
const missingLabels = missing.map(getHostModelCapabilityLabel)
|
||||
return translate(
|
||||
'auto.components.settings.RuntimeEnvironmentsPane.hostModelCapabilityMissing',
|
||||
'Host model support: update server for {{value0}}',
|
||||
{ value0: missingLabels.join(', ') }
|
||||
)
|
||||
}
|
||||
|
||||
function getHostModelCapabilityLabel(capability: string): string {
|
||||
switch (capability) {
|
||||
case PROJECT_HOST_SETUP_RUNTIME_CAPABILITY:
|
||||
return translate(
|
||||
'auto.components.settings.RuntimeEnvironmentsPane.hostModelCapabilityProjectSetup',
|
||||
'project setup'
|
||||
)
|
||||
case TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY:
|
||||
return translate(
|
||||
'auto.components.settings.RuntimeEnvironmentsPane.hostModelCapabilityTaskSourceContext',
|
||||
'task source context'
|
||||
)
|
||||
case WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY:
|
||||
return translate(
|
||||
'auto.components.settings.RuntimeEnvironmentsPane.hostModelCapabilityWorkspaceRunContext',
|
||||
'workspace run context'
|
||||
)
|
||||
default:
|
||||
return capability
|
||||
}
|
||||
}
|
||||
|
||||
export function getActiveServerModeDescription(allowLocalRuntime: boolean): string {
|
||||
return allowLocalRuntime
|
||||
? translate(
|
||||
@@ -715,6 +772,7 @@ export function RuntimeEnvironmentsPane({
|
||||
}
|
||||
)}
|
||||
</span>
|
||||
<span>{getHostModelCapabilitySummary(details.runtimeStatus)}</span>
|
||||
</>
|
||||
) : detailsDescription ? (
|
||||
<span className="truncate text-destructive">{detailsDescription}</span>
|
||||
|
||||
@@ -22,6 +22,8 @@ export const MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION = 2
|
||||
export const MIN_COMPATIBLE_RUNTIME_SERVER_VERSION = 2
|
||||
|
||||
export const PROJECT_HOST_SETUP_RUNTIME_CAPABILITY = 'project-host-setup.v1' as const
|
||||
export const TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY = 'task-source-context.v1' as const
|
||||
export const WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY = 'workspace-run-context.v1' as const
|
||||
|
||||
export const RUNTIME_CAPABILITIES = [
|
||||
'runtime.status.compat.v1',
|
||||
@@ -31,7 +33,9 @@ export const RUNTIME_CAPABILITIES = [
|
||||
'terminal.multiplex.v1',
|
||||
'workspace-ports.v1',
|
||||
'mobile.tasks.v1',
|
||||
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY
|
||||
PROJECT_HOST_SETUP_RUNTIME_CAPABILITY,
|
||||
TASK_SOURCE_CONTEXT_RUNTIME_CAPABILITY,
|
||||
WORKSPACE_RUN_CONTEXT_RUNTIME_CAPABILITY
|
||||
] as const
|
||||
|
||||
export type RuntimeCapability = (typeof RUNTIME_CAPABILITIES)[number] | (string & {})
|
||||
|
||||
Reference in New Issue
Block a user