mirror of
https://github.com/stablyai/orca.git
synced 2026-11-13 17:37:40 +00:00
fix(pi): start Pi terminal launches on the model picked in the launcher (#41005)
Pi had no launch catalog, so a picked model compiled to no arguments. A launch-only catalog maps it to `pi --model <provider/id>`. A --model in Pi's Arguments stays literal: Pi's CLI fuzzy-matches it, while Pi chats need an exact provider/id. Co-authored-by: lucas-wu-wakakak <8309814+lucas-wu-wakakak@users.noreply.github.com>
This commit is contained in:
co-authored by
lucas-wu-wakakak
parent
59fd2dac7c
commit
bb1d4789c4
@@ -12,20 +12,10 @@ import {
|
||||
type AgentStartupShell
|
||||
} from '../startup/tui-agent-startup-shell'
|
||||
import type { TuiAgent } from '../catalog/tui-agent'
|
||||
import type { ChoiceOccurrence } from './agent-launch-choices'
|
||||
import { agentChoiceConfigString, agentChoiceConfigValue } from './agent-choice-cli-apply'
|
||||
|
||||
export type ChoiceOccurrence = {
|
||||
key: string
|
||||
value: string
|
||||
valueType?: 'string' | 'boolean'
|
||||
source?: boolean
|
||||
words: string[]
|
||||
start: number
|
||||
end: number
|
||||
lift: boolean
|
||||
owned: boolean
|
||||
replacement?: string
|
||||
}
|
||||
export type { ChoiceOccurrence } from './agent-launch-choices'
|
||||
|
||||
/** Every cut uses the original spans and preserves operand roles in its consuming grammar. */
|
||||
export function analyzeChoiceArgs(
|
||||
@@ -137,6 +127,10 @@ export function analyzeChoiceArgs(
|
||||
(!inline || name.startsWith('--')) &&
|
||||
!!value &&
|
||||
!value.startsWith('-')
|
||||
if (form.kind === 'value' && form.recognizes?.(value) === false) {
|
||||
valueType = undefined
|
||||
lift = false
|
||||
}
|
||||
if (form.kind === 'settings') {
|
||||
const effective = effectiveSettings.get(form)
|
||||
if (effective?.index !== index || opaqueKeys.has(key)) {
|
||||
|
||||
@@ -92,3 +92,25 @@ it.each(['true', '42', '["high"]', '{key="high"}'])(
|
||||
expect(result.userArgs).toBe(userArgs)
|
||||
}
|
||||
)
|
||||
|
||||
it('keeps a Pi model in Arguments literal so chats never receive a CLI pattern', () => {
|
||||
const lift = (userArgs: string) =>
|
||||
reconcileAgentChoiceArgsDetailed({
|
||||
agent: 'pi',
|
||||
userArgs,
|
||||
choices: {},
|
||||
mode: 'arguments-edit',
|
||||
keys
|
||||
})
|
||||
for (const userArgs of [
|
||||
'--model sonnet:high',
|
||||
'--model anthropic/sonnet',
|
||||
'--model anthropic/claude-opus-5-5',
|
||||
'--provider openai --model gpt-6'
|
||||
]) {
|
||||
const result = lift(userArgs)
|
||||
expect(result.recognized).toEqual([])
|
||||
expect(result.choices).toEqual({})
|
||||
expect(result.userArgs).toBe(userArgs)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -25,11 +25,31 @@ export function terminalAgentChoices(
|
||||
|
||||
export type AgentLaunchChoices = Partial<Record<TuiAgent, AgentModelOptionChoices>>
|
||||
export type AgentChoiceCliForm =
|
||||
| { kind: 'value'; names: readonly string[]; lift: 'separate-and-long-equals' | 'never' }
|
||||
| {
|
||||
kind: 'value'
|
||||
names: readonly string[]
|
||||
lift: 'separate-and-long-equals' | 'never'
|
||||
/** Values outside the choice's grammar stay literal arguments instead of becoming choices. */
|
||||
recognizes?: (value: string) => boolean
|
||||
}
|
||||
| { kind: 'config'; names: readonly string[]; key: string; lift: 'codex-bare-string' | 'never' }
|
||||
| { kind: 'settings'; names: readonly string[]; key: string; lift: 'merged-json' }
|
||||
| { kind: 'recipe'; words: readonly string[]; value: AgentPermissionChoice }
|
||||
|
||||
/** One choice flag found in free-form agent arguments. */
|
||||
export type ChoiceOccurrence = {
|
||||
key: string
|
||||
value: string
|
||||
valueType?: 'string' | 'boolean'
|
||||
source?: boolean
|
||||
words: string[]
|
||||
start: number
|
||||
end: number
|
||||
lift: boolean
|
||||
owned: boolean
|
||||
replacement?: string
|
||||
}
|
||||
|
||||
export function normalizeAgentModelOptionChoices(
|
||||
value: unknown
|
||||
): AgentModelOptionChoices | undefined {
|
||||
|
||||
@@ -41,6 +41,20 @@ describe('tui agent startup session options', () => {
|
||||
expect(plan?.sessionOptions).toEqual({ model: 'zai-coding-plan/glm-5.3-flash' })
|
||||
})
|
||||
|
||||
it('starts Pi on the picked model in place of its configured one', () => {
|
||||
const plan = buildAgentStartupPlan({
|
||||
agent: 'pi',
|
||||
prompt: '',
|
||||
cmdOverrides: {},
|
||||
platform: 'linux',
|
||||
allowEmptyPromptLaunch: true,
|
||||
sessionOptions: { model: 'anthropic/claude-opus-5-5' },
|
||||
sessionOptionsOverrideAgentArgs: true,
|
||||
agentArgs: '--model openai/gpt-6 --no-skills'
|
||||
})
|
||||
expect(plan?.launchCommand).toBe("pi '--no-skills' '--model' 'anthropic/claude-opus-5-5'")
|
||||
})
|
||||
|
||||
it('rejects conflicting singleton flags in an agent command override', () => {
|
||||
expect(
|
||||
resolveAgentLaunchCommand({
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { agentChoiceCliApply } from '../../agent-launch/choices/agent-choice-cli-apply'
|
||||
import type { AgentSessionOptionCatalog } from './agent-session-option-catalog-types'
|
||||
|
||||
// Why: terminal launches need Pi's `--model`; Pi chats keep applying picks over RPC.
|
||||
export const PI_LAUNCH_OPTION_CATALOG: AgentSessionOptionCatalog = {
|
||||
// Pi models depend on configured providers; ids are opaque `provider/id` selectors.
|
||||
models: [],
|
||||
modelApply: agentChoiceCliApply(
|
||||
'pi',
|
||||
[
|
||||
{
|
||||
kind: 'value',
|
||||
names: ['--model'],
|
||||
lift: 'separate-and-long-equals',
|
||||
// Pi's CLI fuzzy-matches `--model`; chats need exact ids, so Arguments never become a model choice.
|
||||
recognizes: () => false
|
||||
}
|
||||
],
|
||||
'--model'
|
||||
)
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
import { GROK_SESSION_OPTION_CATALOG } from './agent-session-option-catalog-grok'
|
||||
import { MUSE_SESSION_OPTION_CATALOG } from './agent-session-option-catalog-muse'
|
||||
import { OMP_SESSION_OPTION_CATALOG } from './agent-session-option-catalog-omp'
|
||||
import { PI_LAUNCH_OPTION_CATALOG } from './agent-session-option-catalog-pi'
|
||||
import type {
|
||||
AgentSessionOptionCatalog,
|
||||
AgentSessionOptionCatalogMap,
|
||||
@@ -91,5 +92,9 @@ export function sessionOptionValueIsValid(value: unknown): value is SessionOptio
|
||||
export function getAgentSessionOptionLaunchCatalog(
|
||||
agent: AgentType
|
||||
): AgentSessionOptionCatalog | null {
|
||||
return agent === 'opencode' ? OPENCODE_LAUNCH_OPTION_CATALOG : getAgentSessionOptionCatalog(agent)
|
||||
return agent === 'opencode'
|
||||
? OPENCODE_LAUNCH_OPTION_CATALOG
|
||||
: agent === 'pi'
|
||||
? PI_LAUNCH_OPTION_CATALOG
|
||||
: getAgentSessionOptionCatalog(agent)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user