mirror of
https://github.com/stablyai/orca.git
synced 2026-09-26 16:02:43 +00:00
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:
@@ -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 = [
|
||||
|
||||
@@ -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
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user