feat(orchestration): accept Muse model and effort for supervised workers (#22383)

* feat(orchestration): accept Muse model and effort for supervised workers

`worker-start --agent muse` already launched, but `--model` was refused because
Muse had no session-option catalog. Add one that maps worker preferences to
`muse --model <id>` and `--reasoning-effort <level>`; it seeds no models, so
native-chat surfaces show no picker.

opencode stays without `--model`: the opencode 2 TUI (now shipped as
`opencode`) rejects the flag, so the refusal now tells callers to rely on the
agent's own config. Help, skill guide, and docs list valid `--agent` ids and
the agents that accept `--model`.

Refs #19823

* test(mobile): repin session route closure for the Muse option catalog
This commit is contained in:
Neil
2026-09-22 22:20:35 -07:00
committed by GitHub
parent 0afc66ebd3
commit 52a1e2875b
10 changed files with 107 additions and 11 deletions
@@ -412,8 +412,14 @@ const MERMAID_PACKAGE = 'node_modules/mermaid/'
*
* modules 4213 -> 4214 (+1)
* local modules 1027 -> 1028 (+1)
*
* Muse's worker launch preferences then added `src/shared/agent-session-option-catalog-muse.ts`,
* which the option catalog this route already reaches imports. One local module, measured.
*
* modules 4214 -> 4215 (+1)
* local modules 1028 -> 1029 (+1)
*/
const SESSION_ROUTE_MODULES = 4214
const SESSION_ROUTE_MODULES = 4215
/** What the page enters this route through once the route is a switch with a `.web.tsx` sibling. */
const ROUTE_ENTRY = [
+2 -2
View File
@@ -40,11 +40,11 @@ orca orchestration task-create --spec "Audit billing settings for mobile layout"
orca orchestration worker-start --task <taskId> --worktree current --agent codex --json
# or new worktree:
orca orchestration worker-start --task <taskId> --worktree new-child --name billing-audit --agent codex --setup run --json
# optional per-worker model / effort (Claude, Codex, Cursor only; not with --terminal):
# optional per-worker model / effort (Claude, Codex, Cursor, Antigravity, Muse; not with --terminal):
orca orchestration worker-start --task <taskId> --worktree current --agent claude --model <opaque-model-id> --effort high --json
```
`--model` accepts opaque provider model IDs for Claude, Codex, and Cursor. `--effort` requires `--model` and only applies when that agent/model supports the level. Neither flag can combine with `--terminal` (reuse an existing pane). Overrides apply to that launch only and show under `launch.requested` / `launch.effective` in the start receipt. Federated starts need a worker host that advertises launch-preference support.
`--agent` takes any Orca agent ID enabled on the worker server, for example `claude`, `codex`, `cursor`, `antigravity`, `muse`, `opencode`, or `opencode2`. `--model` accepts opaque provider model IDs for Claude, Codex, Cursor, Antigravity, and Muse (for example `--agent muse --model muse-spark-1.3`); other agents, including opencode, run the model from their own config. `--effort` requires `--model` and only applies when that agent/model supports the level. Neither flag can combine with `--terminal` (reuse an existing pane). Overrides apply to that launch only and show under `launch.requested` / `launch.effective` in the start receipt. Federated starts need a worker host that advertises launch-preference support.
Wait for completions (process every message in a Delivery, then ack):
@@ -21,15 +21,20 @@ when an older CLI rejects the flag. A nested worker must respect
## Launch preferences
For a fresh Claude, Codex, Cursor, or Antigravity terminal, `--model` accepts an opaque
provider model ID. Pass it only when the user named a model; otherwise omit it
so the worker inherits the user's configured agent default. Add `--effort` only
when that model supports it:
For a fresh Claude, Codex, Cursor, Antigravity, or Muse terminal, `--model`
accepts an opaque provider model ID. Pass it only when the user named a model;
otherwise omit it so the worker inherits the user's configured agent default.
Add `--effort` only when that model supports it:
```text
ORCA orchestration worker-start --task <task_id> --worktree current --agent claude --model opus --effort high --json
ORCA orchestration worker-start --task <task_id> --worktree current --agent muse --model muse-spark-1.3 --json
```
Other agents, including `opencode`, reject `--model`; they run the model set in
their own config, so a coordinator wanting a same-model opencode worker relies
on that config.
`--effort` requires `--model`; neither option combines with `--terminal`. A
connected worker server must advertise launch-preference support before Orca
forwards either field. Compare `launch.requested` with `launch.effective`; never
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -34,7 +34,8 @@ export const ORCHESTRATION_WORKER_COMMAND_SPECS: CommandSpec[] = [
notes: [
'Current and existing worktrees never rerun setup; a fresh agent terminal is created unless --terminal is explicit.',
'When reusing --terminal, pass --worktree for that terminal; current means the coordinator worktree.',
'--model supports Claude, Codex, Cursor, and Antigravity opaque provider model ids; --effort requires --model. Neither can combine with --terminal.',
'--agent takes an Orca agent id enabled on the worker server, such as claude, codex, cursor, antigravity, muse, opencode, or opencode2.',
'--model supports Claude, Codex, Cursor, Antigravity, and Muse opaque provider model ids; --effort requires --model. Neither can combine with --terminal. Other agents, including opencode, launch with the model from their own config.',
'New worktrees use agent-first creation and default --setup to run. Repository start-immediately runs setup beside the agent; wait-for-setup gates agent readiness and task input.',
'Creation flags (--name, --repo, --base-branch, --display-name, --comment, --setup) are rejected for current/existing worktrees. Use exact --repo on the selected server; project/host convenience routing remains on worktree create.',
"How the worker runs follows the user's own setting for new agent tabs; there is no flag for it and no caller needs to ask. A dispatch the setting cannot apply to still starts, so the placement, agent, and launch options passed here are always the ones honoured.",
@@ -61,6 +61,30 @@ describe('orchestration worker launch preferences', () => {
).toThrow('does not support effort xhigh')
})
it('passes a Muse model and reasoning effort through the shared catalog', () => {
expect(
resolveWorkerLaunchPreferences({ agent: 'muse', model: 'muse-spark-1.3', effort: 'xhigh' })
).toEqual({
preferences: { model: 'muse-spark-1.3', effort: 'xhigh' },
receipt: {
requested: { agent: 'muse', model: 'muse-spark-1.3', effort: 'xhigh' },
effective: { agent: 'muse', model: 'muse-spark-1.3', effort: 'xhigh' }
}
})
})
it('rejects Muse effort values outside its reasoning ladder', () => {
expect(() =>
resolveWorkerLaunchPreferences({ agent: 'muse', model: 'muse-spark-1.3', effort: 'turbo' })
).toThrow('does not support effort turbo')
})
it('refuses an opencode model because the opencode 2 TUI rejects --model', () => {
expect(() =>
resolveWorkerLaunchPreferences({ agent: 'opencode', model: 'meta/muse-spark-1.3' })
).toThrow('does not support launch-time model selection')
})
it('does not invent an effort when only a model is requested', () => {
expect(
resolveWorkerLaunchPreferences({ agent: 'codex', model: 'gpt-5.6-sol' }).preferences
@@ -70,7 +70,7 @@ export function resolveWorkerLaunchPreferences(args: {
if (!catalog?.supportsWorkerLaunchPreferences || !catalog.modelApply.launchArgs) {
throw new OrchestrationError(
'invalid_argument',
`Agent ${args.agent} does not support launch-time model selection.`
`Agent ${args.agent} does not support launch-time model selection. Omit --model to run the model from its own config.`
)
}
@@ -0,0 +1,41 @@
import { hasFlag } from './agent-cli-flag-detection'
import { removeAgentArgOption } from './agent-session-option-agent-args'
import type { AgentSessionOptionCatalog, CatalogOption } from './agent-session-option-catalog-types'
// `none` is omitted: native-chat-session-option-labels.ts has no translation for it.
const MUSE_EFFORT: CatalogOption = {
id: 'effort',
label: 'Reasoning effort',
category: 'thought_level',
kind: {
type: 'select',
choices: [
{ value: 'minimal', label: 'Minimal' },
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
{ value: 'xhigh', label: 'Extra high' },
{ value: 'max', label: 'Max' },
{ value: 'ultra', label: 'Ultra' }
],
defaultValue: 'high'
},
apply: {
launchArgs: (value) => ['--reasoning-effort', String(value)],
agentArgsOverride: (tokens) => hasFlag(tokens, ['--reasoning-effort']),
removeAgentArgs: (tokens) => removeAgentArgOption(tokens, ['--reasoning-effort'])
}
}
export const MUSE_SESSION_OPTION_CATALOG: AgentSessionOptionCatalog = {
supportsWorkerLaunchPreferences: true,
// Why: Muse model ids are account/channel-scoped and it has no listing command, so
// seed nothing (no picker) and let worker-start pass the caller's id to `--model`.
models: [],
modelApply: {
launchArgs: (value) => ['--model', String(value)],
agentArgsOverride: (tokens) => hasFlag(tokens, ['--model']),
removeAgentArgs: (tokens) => removeAgentArgOption(tokens, ['--model'])
},
unknownModelOptions: [MUSE_EFFORT]
}
@@ -10,6 +10,7 @@ import {
GEMINI_SESSION_OPTION_CATALOG
} from './agent-session-option-catalog-gemini-cursor'
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 type {
AgentSessionOptionCatalog,
@@ -37,6 +38,7 @@ const CATALOGS: AgentSessionOptionCatalogMap = {
gemini: GEMINI_SESSION_OPTION_CATALOG,
cursor: CURSOR_SESSION_OPTION_CATALOG,
grok: GROK_SESSION_OPTION_CATALOG,
muse: MUSE_SESSION_OPTION_CATALOG,
omp: OMP_SESSION_OPTION_CATALOG
}
@@ -72,6 +72,23 @@ describe('tui agent startup session options', () => {
expect(plan?.sessionOptions).toEqual({ model: 'gemini-3.1-pro-high', effort: 'high' })
})
it('forwards Muse worker model and effort after its workspace-trust default', () => {
const plan = buildAgentStartupPlan({
agent: 'muse',
prompt: '',
cmdOverrides: {},
platform: 'linux',
allowEmptyPromptLaunch: true,
sessionOptions: { model: 'muse-spark-1.3', effort: 'xhigh' },
sessionOptionsOverrideAgentArgs: true,
agentArgs: '--model muse-spark-1.2'
})
expect(plan?.launchCommand).toBe(
"muse --trust-workspace '--model' 'muse-spark-1.3' '--reasoning-effort' 'xhigh'"
)
expect(plan?.sessionOptions).toEqual({ model: 'muse-spark-1.3', effort: 'xhigh' })
})
it('inserts worker preferences before an argument terminator', () => {
const plan = buildAgentStartupPlan({
agent: 'codex',