From 76a446c50e01a0ff91e00610d10aebd3c00b88a0 Mon Sep 17 00:00:00 2001 From: Jinwoo-H Date: Fri, 12 Jun 2026 22:08:01 -0700 Subject: [PATCH] Surface host model runtime capability skew Co-authored-by: Orca --- .../host-context-implementation-checklist.md | 3 +- .../settings/RuntimeEnvironmentsPane.test.ts | 47 ++++++++++++++- .../settings/RuntimeEnvironmentsPane.tsx | 60 ++++++++++++++++++- src/shared/protocol-version.ts | 6 +- 4 files changed, 112 insertions(+), 4 deletions(-) diff --git a/notes/host-context-implementation-checklist.md b/notes/host-context-implementation-checklist.md index 0bfa91176be..57de7716ecb 100644 --- a/notes/host-context-implementation-checklist.md +++ b/notes/host-context-implementation-checklist.md @@ -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 ` 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`. diff --git a/src/renderer/src/components/settings/RuntimeEnvironmentsPane.test.ts b/src/renderer/src/components/settings/RuntimeEnvironmentsPane.test.ts index 95a028b5881..ad4f4dca632 100644 --- a/src/renderer/src/components/settings/RuntimeEnvironmentsPane.test.ts +++ b/src/renderer/src/components/settings/RuntimeEnvironmentsPane.test.ts @@ -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') diff --git a/src/renderer/src/components/settings/RuntimeEnvironmentsPane.tsx b/src/renderer/src/components/settings/RuntimeEnvironmentsPane.tsx index 672522ac5e9..35fea6222f7 100644 --- a/src/renderer/src/components/settings/RuntimeEnvironmentsPane.tsx +++ b/src/renderer/src/components/settings/RuntimeEnvironmentsPane.tsx @@ -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({ } )} + {getHostModelCapabilitySummary(details.runtimeStatus)} ) : detailsDescription ? ( {detailsDescription} diff --git a/src/shared/protocol-version.ts b/src/shared/protocol-version.ts index 861a640ba84..778196c1adc 100644 --- a/src/shared/protocol-version.ts +++ b/src/shared/protocol-version.ts @@ -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 & {})