mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 02:27:43 +00:00
* Source control actions start chats and terminals on their saved model A "start an agent" action's model lived only in free-text CLI arguments, which a native chat never reads, so AI Fix opened a chat on the default model. Each action now saves a structured model and effort that both routes apply: chat create options, or the agent's own flags in a terminal (winning over the same flag in CLI arguments). Desktop, dialog, fix-checks and mobile launches carry it; Settings rows get Model/Effort selects and the CLI arguments field says it is terminal-only. Tracked in STA-11102. * Name the model in the repository override note * Type the dialog's model hand-off; keep Agent in English in Japanese copy * fix: preserve action chat model choices through launch * Preserve action selection ownership across chat launches * Keep terminal host contract fixtures aligned with preflight * fix: wait for action Settings agent inventory * fix: consolidate direct agent routing imports * fix: use standard action option labels * fix: align action launch contracts with shared types * fix: sync action option localization metadata * test: provide action Settings inventory in mounted fixtures * Keep action options row height stable while loading * Let each Source Control action choose its chat permission mode An action's saved chat choice may now carry a permission mode, with or without a model; "Same as new chats" saves nothing. A model is replaced only when the action names one, so a permission-only choice keeps the chat's remembered model and options. * fix(native-chat): leave older hosts their own permission mode and keep action options readable - An action's saved permission mode is sent only to hosts that advertise agentSession.create.options-mode.v1. Older hosts get no mode, in create options or a later setOption, so the chat starts on that host's new-chat default, as a phone launch to such a host already does. Hosts from 1.4.225 to 1.4.227 refused a mode their tables lacked (OpenCode, Grok, OMP), leaving the action unable to start. - Settings action rows give Model and Permissions full rows in the options column so saved values are readable; the loading placeholder reserves the same rows. - Remove two unused locale keys; fix two stale comments. - Tests: the older-host create carries no permission mode; a permission mode picked alone keeps the remembered model on an acquired create. * fix(settings): reserve one options row while loading an action with nothing saved Terminal and permissions-only rows no longer shrink when loading ends; a chat agent with a model list may grow by its Model row once known. * fix(native-chat): keep the create options mode a checked literal type * fix(settings): share verified action option fields * fix(settings): keep action selectors on standard typography * Keep the launch files under their length limits after the main merge The structured route imports its result types where they are defined, and the two older-host action-launch tests share one setup helper. * One action settings section for chat and terminal launches A Source Control action's Model, model options and Permissions now apply whether it opens a chat or a terminal; terminals receive them as the agent's own flags, and a repository's own CLI arguments keep the flags it sets. Extra CLI arguments stay terminal-only. * fix(source-control-ai): one terminal projection for saved action choices Ask in a terminal now states its permission instead of leaving it to the user's own config: Claude and Grok pass --permission-mode default, Codex passes -a on-request -s read-only -c approvals_reviewer="user" (the interactive CLI has no untrusted policy, so a read-only sandbox is what asks before edits). Agents whose CLI has no flag for a mode show the existing "Applies to chats only" hint. The strict launch-preferences projection now requires the launch agent at every caller, composes model ids through the resolver's own step, carries a mode only where the agent's terminal has a flag for it, and the local string wire keeps booleans as 'true'/'false', so Cursor Thinking/Fast reach the terminal and an OpenCode permission-only choice is not refused. The argument parser knows flag arity, so removing a boolean permission flag keeps other options' values, following positionals and '--'. Pre-admission and executor share one terminal admission check on the options the terminal will receive. Customize with Save launches the recipe as it will resolve once saved; legacy partial repository overrides are edited as the complete recipe they resolve to. Empty Extra CLI arguments start collapsed. * fix(source-control-ai): an edited repository action saves complete Every Settings edit of a repository action (agent, model, permission, prompt or arguments) now starts from the complete recipe the action resolves to, whether its stored override is owned or a legacy partial. The resolved agent selection is kept (never an agent only detected to run a default), an explicit null args clear stays null, and empty args stay empty instead of being dropped. Clearing the last preference therefore means the action agent's own defaults rather than re-inheriting Global. The action text draft is lossless: unset or cleared prompt and args stay so until the user types, and the inputs show them as empty, so saving a prompt no longer writes empty args that suppress the agent's default flags. Untouched sibling actions are not rewritten by the edit. * fix(settings): style the Extra CLI arguments toggle through Button's own variant and size CI's changed-code quality check refuses restyle classes on Button and CollapsibleContent. Use the ghost variant at size xs with a margin, and put the content spacing on a plain inner wrapper. * fix: keep saved action and restart launch recipes consistent * fix: describe inherited arguments and chat-only permissions accurately * test: check repository action settings fixture type * test: map saved action options into terminal compiler inputs * fix: retain saved action controls during agent detection * fix(i18n): retire obsolete Portuguese action labels * test: align folder launch fallback mock with outcome export * fix: carry resolved connector launch intent and mode together * test: pin shared action launch branches to recorded agent output * test: preserve saved source control choices through detection and migration * test: align launch fixtures with integrated result contract * test: retain recipe and restart contracts after main integration * Unify Source Control action permission settings * Keep native Ask copy with its owning change * Preserve action drafts and old-host permission intent * Consume rejected Source Control action saves * Follow the moved Settings persistence fixture * Keep permission integration contracts in the cross-version test project * Include the action permission inheritance label in English catalogs * Align launch contracts with shared permission recipes * Keep Source Control action controls within their Settings columns * Use primitive variants for compact action settings controls * Show action arguments only for terminal defaults and widen recipe rows * Apply terminal-only action arguments visibility to repository overrides * Align action permission control with model controls * Use shared settings label for action permissions * Hide action model controls until argument migration ships
127 lines
5.5 KiB
TypeScript
127 lines
5.5 KiB
TypeScript
/** Share settings defaults and per-launch feasibility between renderer tab launches and orchestration workers to prevent drift. */
|
||
|
||
import { isAgentSessionHandleProvider } from './agent-session-provider-handle'
|
||
import { parseExecutionHostId } from './execution-host'
|
||
import type { GlobalSettings } from './global-settings-types'
|
||
import type { NativeChatProviderSettings } from './native-chat/native-chat-providers'
|
||
import type { ProjectExecutionRuntimeResolution } from './project-execution-runtime'
|
||
import {
|
||
STRUCTURED_AGENT_SESSION_CLIENT_LAUNCH_MODE_CAPABILITY,
|
||
STRUCTURED_AGENT_SESSION_REGISTERED_AGENTS_RUNTIME_CAPABILITY,
|
||
STRUCTURED_AGENT_SESSION_RUNTIME_CAPABILITY
|
||
} from './protocol-version'
|
||
import type { TuiAgent } from './tui-agent'
|
||
import type { WorkspaceLaunchKind } from './workspace-launch-kind'
|
||
|
||
export type NativeChatDefaultSettings = Pick<GlobalSettings, 'experimentalNativeChat'> &
|
||
Partial<NativeChatProviderSettings>
|
||
|
||
/** Why a launch that the user's default asked to be structured cannot be. */
|
||
export type StructuredNativeChatBlocker =
|
||
| 'reused-terminal'
|
||
| 'agent-without-structured-session'
|
||
/** Only PTYs apply a start directory outside the workspace; configured command/arguments do not choose the surface. */
|
||
| 'custom-start-directory'
|
||
| 'remote-execution-host'
|
||
| 'project-runtime'
|
||
| 'runtime-capability'
|
||
/** Unestablished host support is unknown, distinct from an explicit capability refusal. */
|
||
| 'runtime-capability-unknown'
|
||
/** This client does not tell a paired host it can read and launch structured sessions. */
|
||
| 'client-capability'
|
||
|
||
export type StructuredNativeChatSupport =
|
||
| { supported: true }
|
||
| { supported: false; blocker: StructuredNativeChatBlocker }
|
||
|
||
export type StructuredNativeChatSupportInput = {
|
||
agent: TuiAgent
|
||
executionHostId: string
|
||
/** Owning host’s capabilities, including paired servers; null means unestablished. */
|
||
hostCapabilities: readonly string[] | null
|
||
/** What this client advertises to a paired host; read only for `runtime:` hosts. */
|
||
clientCapabilities?: readonly string[]
|
||
/** Host-derived. Absent means the kind was never established, which is not evidence of any kind. */
|
||
workspaceKind?: WorkspaceLaunchKind
|
||
projectExecutionKind?: 'host' | 'ssh'
|
||
projectRuntime?: ProjectExecutionRuntimeResolution | null
|
||
startsOutsideWorkspaceRoot?: boolean
|
||
/** An existing PTY agent keeps its execution transport. */
|
||
reusesTerminal?: boolean
|
||
/** Without host inventory, offer only Claude/Codex, which every structured host supports. */
|
||
hostStructuredAgents?: readonly string[]
|
||
}
|
||
|
||
/** The single Chat UI switch selects structured chat for supported new launches. */
|
||
export function isNativeChatEnabled(
|
||
settings: Partial<NativeChatDefaultSettings> | null | undefined
|
||
): boolean {
|
||
return settings?.experimentalNativeChat === true
|
||
}
|
||
|
||
/** Unchosen agents retain the chat default, independently of installation inventory. */
|
||
export function isNativeChatDefaultFor(
|
||
settings: Partial<NativeChatDefaultSettings> | null | undefined,
|
||
agent: TuiAgent
|
||
): boolean {
|
||
return isNativeChatEnabled(settings) && (settings?.nativeChatProviders?.[agent] ?? true)
|
||
}
|
||
|
||
function clientChoosesStructuredLaunches(capabilities: readonly string[] | undefined): boolean {
|
||
return (
|
||
capabilities?.includes(STRUCTURED_AGENT_SESSION_RUNTIME_CAPABILITY) === true &&
|
||
capabilities.includes(STRUCTURED_AGENT_SESSION_CLIENT_LAUNCH_MODE_CAPABILITY)
|
||
)
|
||
}
|
||
|
||
export function resolveStructuredNativeChatSupport(
|
||
input: StructuredNativeChatSupportInput
|
||
): StructuredNativeChatSupport {
|
||
// Paired runtimes execute structured sessions themselves; relay SSH hosts cannot.
|
||
const host = parseExecutionHostId(input.executionHostId)
|
||
if (
|
||
input.projectExecutionKind === 'ssh' ||
|
||
(host?.kind !== 'local' && host?.kind !== 'runtime')
|
||
) {
|
||
return { supported: false, blocker: 'remote-execution-host' }
|
||
}
|
||
if (input.reusesTerminal === true) {
|
||
return { supported: false, blocker: 'reused-terminal' }
|
||
}
|
||
const builtInAgent = isAgentSessionHandleProvider(input.agent)
|
||
if (!builtInAgent && !input.hostStructuredAgents?.includes(input.agent)) {
|
||
return { supported: false, blocker: 'agent-without-structured-session' }
|
||
}
|
||
if (input.startsOutsideWorkspaceRoot === true) {
|
||
return { supported: false, blocker: 'custom-start-directory' }
|
||
}
|
||
const projectRuntime = input.projectRuntime
|
||
if (projectRuntime?.status === 'repair-required' || projectRuntime?.runtime.kind === 'wsl') {
|
||
return { supported: false, blocker: 'project-runtime' }
|
||
}
|
||
if (input.hostCapabilities === null) {
|
||
return { supported: false, blocker: 'runtime-capability-unknown' }
|
||
}
|
||
if (
|
||
!input.hostCapabilities.includes(STRUCTURED_AGENT_SESSION_RUNTIME_CAPABILITY) ||
|
||
// A host that does not advertise its registered agents accepts only Claude and Codex.
|
||
(!builtInAgent &&
|
||
!input.hostCapabilities.includes(
|
||
STRUCTURED_AGENT_SESSION_REGISTERED_AGENTS_RUNTIME_CAPABILITY
|
||
))
|
||
) {
|
||
return { supported: false, blocker: 'runtime-capability' }
|
||
}
|
||
if (host.kind === 'runtime') {
|
||
// Older paired hosts gate on their own chat setting, so retain terminal launches without client-launch-mode support.
|
||
if (!input.hostCapabilities.includes(STRUCTURED_AGENT_SESSION_CLIENT_LAUNCH_MODE_CAPABILITY)) {
|
||
return { supported: false, blocker: 'runtime-capability' }
|
||
}
|
||
// Hosts refuse unadvertised client support; retain terminals for those clients.
|
||
if (!clientChoosesStructuredLaunches(input.clientCapabilities)) {
|
||
return { supported: false, blocker: 'client-capability' }
|
||
}
|
||
}
|
||
return { supported: true }
|
||
}
|