Files
orca/src/main/agent-launch/agent-launch-opencode-model.test.ts
T
Brennan Benson 251516de60 feat(native-chat): choose which agents open as a chat (#29071)
* feat(native-chat): choose which agents open as a chat

Settings → Chat gets a Providers list. Each agent the host can open as a chat
has a switch; off opens that agent in a terminal instead. Only choices the user
makes are saved. Unchosen: Claude and Codex on, others on when their CLI is
installed on this computer.

The renderer's route and the host's launch-mode decision both read one rule, so
the tab menu, shortcuts, CLI, orchestration and relayed phone launches agree.

* fix: keep chat provider settings with the other chat settings types

* test: route input carries this computer's detected agents

* fix(chat): resolve provider choices from their owning computer

* test(chat): use checked native inventory fixtures

* Fix launch preparation lifetime and execution host startup

* fix(chat): keep unchosen providers on without discovery

* test(chat): type provider routing fixtures against store contracts

* test(chat): align shared launch fixture with private settings reader

* test(chat): give the structured-session RPC fixture the private settings reader

The host now reads saved chat choices through requireStore().getSettings(); the
shared RPC fixture only had getClientSettings, so the launch-mode reader saw no
settings and create support refused Claude. The fixture now follows each test's
client settings.

* fix: preserve provider choice and cached native inventory
2026-10-17 00:51:43 -07:00

90 lines
3.0 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import type { AgentLaunchIntent } from '../../shared/agent-launch-intent'
import { executeAgentLaunch } from './agent-launch-executor'
function harness() {
const readSettings = vi.fn(() => {
throw new Error('settings_not_needed_for_refusal')
})
const createSupport = vi.fn(async () => {
throw new Error('support_not_needed_for_refusal')
})
const createTerminal = vi.fn(async () => ({ handle: 'term_new' }))
const deliverPrompt = vi.fn(async () => true)
const createWorktree = vi.fn(async () => ({
worktreeId: 'wt_new',
connectionId: null,
startupTerminalHandle: 'term_new'
}))
return {
readSettings,
createTerminal,
deliverPrompt,
createWorktree,
run: (intent: AgentLaunchIntent) =>
executeAgentLaunch({
intent,
runtime: {
requireStore: () => ({ getSettings: readSettings }),
getStructuredAgentSessionCreateSupport: createSupport
},
surfaces: {
createTerminalAgent: createTerminal,
createStructuredSession: async () => {
throw new Error('structured_not_expected')
},
deliverTerminalPrompt: deliverPrompt
},
workspaces: {
createWorktree,
createFolderWorkspace: async () => {
throw new Error('folder_create_not_expected')
}
}
})
}
}
const reused: AgentLaunchIntent = {
agent: 'opencode',
target: { kind: 'existing', worktree: 'folder:private' },
reuseTerminal: { handle: 'term_existing' },
prompt: { text: 'Read only', delivery: 'submit' },
sessionOptions: { model: 'private-proof/model-b' }
}
const creating: AgentLaunchIntent = {
...reused,
reuseTerminal: undefined,
target: { kind: 'create-worktree', create: { repo: 'id:private', name: 'task' } }
}
describe('OpenCode model preferences on unsupported launch placements', () => {
it.each([reused, creating])(
'refuses before reading settings or creating or delivering',
async (intent) => {
const h = harness()
await expect(h.run(intent)).rejects.toMatchObject({ code: 'capability_unsupported' })
expect(h.readSettings).not.toHaveBeenCalled()
expect(h.createTerminal).not.toHaveBeenCalled()
expect(h.createWorktree).not.toHaveBeenCalled()
expect(h.deliverPrompt).not.toHaveBeenCalled()
}
)
it('preserves prompt delivery to a reused terminal without model preferences', async () => {
const h = harness()
expect((await h.run({ ...reused, sessionOptions: undefined })).outcome).toEqual({
kind: 'terminal',
handle: 'term_existing'
})
expect(h.deliverPrompt).toHaveBeenCalledOnce()
expect(h.createWorktree).not.toHaveBeenCalled()
})
it('preserves ordinary worktree creation without model preferences', async () => {
const h = harness()
expect((await h.run({ ...creating, sessionOptions: undefined })).worktreeId).toBe('wt_new')
expect(h.createWorktree).toHaveBeenCalledOnce()
})
})