mirror of
https://github.com/stablyai/orca.git
synced 2026-10-26 00:03:55 +00:00
* Add per-model session-option pickers (model/effort/fast-mode) to native Introduces a shared agent session-option catalog (Claude/Codex/Gemini/Cursor) with model-scoped options, launch-command composition, mid-session dispatch via slash commands, and per-model persisted defaults. Wires the new NativeChatSessionOptionPickers UI into the composer, threads sessionOptions through every startup-plan builder (worktree creation, onboarding, source control actions, folder workspace, direct work-item launches), and adds localized strings and tests across the affected surfaces. * Add per-model session-option pickers with a verified Claude model switch Native chat's model/effort picker now dispatches option commands through a body-then-verified-Enter write path and, for Claude, arms a PTY observer that classifies the cached-history confirmation prompt as applied/rejected/needs interaction before the picker returns — falling back to the terminal only when Claude genuinely requires manual input, and clearing stale truth otherwise. Also reorders the composer's model/effort pills, disambiguates their tooltip labels, and switches disabled-reason strings to a closed enum so producer and localized copy can't drift. * Add live model/effort detection from Claude's TUI header - Reads the mounted xterm's main-buffer snapshot (falling back to the rendered screen when the alternate screen owns the buffer) to parse Claude's header for the currently active model and effort, so the native chat picker reflects reality instead of only dispatched state - Extracts command-apply recording and reported-value application into dedicated modules, and factors file-link click handling into a hook, to keep native-chat-pty-session-options.ts focused
154 lines
4.5 KiB
TypeScript
154 lines
4.5 KiB
TypeScript
import type { AgentSessionOptionCatalog, CatalogOption } from './agent-session-option-catalog-types'
|
|
|
|
function hasFlag(tokens: readonly string[], flags: readonly string[]): boolean {
|
|
return tokens.some((token) =>
|
|
flags.some(
|
|
(flag) =>
|
|
token === flag ||
|
|
token.startsWith(`${flag}=`) ||
|
|
(flag.startsWith('-') && !flag.startsWith('--') && token.startsWith(flag))
|
|
)
|
|
)
|
|
}
|
|
|
|
function hasCodexEffortOverride(tokens: readonly string[]): boolean {
|
|
if (hasFlag(tokens, ['--reasoning-effort'])) {
|
|
return true
|
|
}
|
|
return tokens.some((token, index) => {
|
|
const previous = tokens[index - 1]
|
|
return (
|
|
(token.startsWith('model_reasoning_effort=') &&
|
|
(previous === '-c' || previous === '--config')) ||
|
|
token.startsWith('-cmodel_reasoning_effort=') ||
|
|
token.startsWith('-c=model_reasoning_effort=') ||
|
|
token.startsWith('--config=model_reasoning_effort=')
|
|
)
|
|
})
|
|
}
|
|
|
|
const STANDARD_EFFORT_CHOICES = [
|
|
{ value: 'low', label: 'Low' },
|
|
{ value: 'medium', label: 'Medium' },
|
|
{ value: 'high', label: 'High' }
|
|
]
|
|
|
|
const EXTENDED_EFFORT_CHOICES = [
|
|
...STANDARD_EFFORT_CHOICES,
|
|
{ value: 'xhigh', label: 'Extra high' },
|
|
{ value: 'max', label: 'Max' }
|
|
]
|
|
|
|
function claudeEffort(extended: boolean): CatalogOption {
|
|
return {
|
|
id: 'effort',
|
|
label: 'Effort',
|
|
category: 'thought_level',
|
|
kind: {
|
|
type: 'select',
|
|
choices: extended ? EXTENDED_EFFORT_CHOICES : STANDARD_EFFORT_CHOICES,
|
|
defaultValue: 'high'
|
|
},
|
|
apply: {
|
|
launchArgs: (value) => ['--effort', String(value)],
|
|
agentArgsOverride: (tokens) => hasFlag(tokens, ['--effort']),
|
|
midSession: { kind: 'command', build: (value) => `/effort ${String(value)}` }
|
|
}
|
|
}
|
|
}
|
|
|
|
const CLAUDE_FAST_MODE: CatalogOption = {
|
|
id: 'fastMode',
|
|
label: 'Fast mode',
|
|
category: 'mode',
|
|
kind: { type: 'boolean', defaultValue: false },
|
|
apply: { midSession: { kind: 'toggle-command', command: '/fast' } }
|
|
}
|
|
|
|
export const CLAUDE_SESSION_OPTION_CATALOG: AgentSessionOptionCatalog = {
|
|
models: [
|
|
{
|
|
id: 'fable',
|
|
label: 'Fable 5',
|
|
options: [claudeEffort(true)]
|
|
},
|
|
{
|
|
id: 'opus',
|
|
label: 'Opus 4.8',
|
|
options: [claudeEffort(true), CLAUDE_FAST_MODE]
|
|
},
|
|
{
|
|
id: 'sonnet',
|
|
label: 'Sonnet 5',
|
|
isDefault: true,
|
|
options: [claudeEffort(true)]
|
|
},
|
|
{
|
|
id: 'haiku',
|
|
label: 'Haiku',
|
|
options: []
|
|
}
|
|
],
|
|
modelApply: {
|
|
launchArgs: (value) => ['--model', String(value)],
|
|
agentArgsOverride: (tokens) => hasFlag(tokens, ['--model']),
|
|
midSession: {
|
|
kind: 'command',
|
|
build: (value) => `/model ${String(value)}`,
|
|
pickerCommand: '/model',
|
|
// Why: Claude sometimes confirms a cached-history switch. Detect the
|
|
// actual prompt so ordinary model changes stay in native chat.
|
|
detectAgentInteraction: 'claude-model-switch-confirmation'
|
|
}
|
|
}
|
|
}
|
|
|
|
const CODEX_EFFORT_CHOICES = [
|
|
{ value: 'minimal', label: 'Minimal' },
|
|
{ value: 'low', label: 'Low' },
|
|
{ value: 'medium', label: 'Medium' },
|
|
{ value: 'high', label: 'High' },
|
|
{ value: 'xhigh', label: 'Extra high' }
|
|
]
|
|
|
|
function codexEffort(includeExtraHigh: boolean): CatalogOption {
|
|
return {
|
|
id: 'effort',
|
|
label: 'Reasoning effort',
|
|
category: 'thought_level',
|
|
kind: {
|
|
type: 'select',
|
|
choices: includeExtraHigh
|
|
? CODEX_EFFORT_CHOICES
|
|
: CODEX_EFFORT_CHOICES.filter((choice) => choice.value !== 'xhigh'),
|
|
defaultValue: 'medium'
|
|
},
|
|
apply: {
|
|
launchArgs: (value) => ['-c', `model_reasoning_effort=${String(value)}`],
|
|
agentArgsOverride: hasCodexEffortOverride,
|
|
midSession: { kind: 'agent-picker', command: '/model' }
|
|
}
|
|
}
|
|
}
|
|
|
|
export const CODEX_SESSION_OPTION_CATALOG: AgentSessionOptionCatalog = {
|
|
// Why: Codex model access depends on auth. Keep this seed short and allow
|
|
// unknown persisted ids to pass through instead of claiming a complete list.
|
|
models: [
|
|
{ id: 'gpt-5.6-sol', label: 'GPT-5.6 Sol', options: [codexEffort(true)] },
|
|
{ id: 'gpt-5.6-terra', label: 'GPT-5.6 Terra', options: [codexEffort(true)] },
|
|
{ id: 'gpt-5.6-luna', label: 'GPT-5.6 Luna', options: [codexEffort(false)] },
|
|
{ id: 'gpt-5.5', label: 'GPT-5.5', options: [codexEffort(true)] },
|
|
{
|
|
id: 'gpt-5.2-codex',
|
|
label: 'GPT-5.2 Codex',
|
|
options: [codexEffort(true)]
|
|
}
|
|
],
|
|
modelApply: {
|
|
launchArgs: (value) => ['-m', String(value)],
|
|
agentArgsOverride: (tokens) => hasFlag(tokens, ['-m', '--model']),
|
|
midSession: { kind: 'agent-picker', command: '/model' }
|
|
}
|
|
}
|