2.8 KiB
name, description
| name | description |
|---|---|
| omp-models-yml-runner-api-placement | Add or edit a non-chat (tts/image/embedding) model row in ~/.omp/agent/models.yml without disabling every custom provider |
Scope
~/.omp/agent/models.yml (or models.yaml) on a workstation: adding a runner
model row (TTS / image / embedding / rerank / video) alongside chat providers.
The landmine
Provider-level api accepts only chat/judge transports:
openai-completions, openai-responses, openai-codex-responses,
azure-openai-responses, anthropic-messages, bedrock-converse-stream,
google-generative-ai, google-gemini-cli, google-vertex,
openrouter-decisions, typesafe.
Naming a runner API (openai-speech, openai-images, openai-embeddings, …)
at provider level fails whole-file validation, and the failure mode is not
scoped to your provider:
Warning: models.yml validation failed — custom providers disabled
Failed to load config file models, Schema error: providers.<id>.api: must be "openai-completions", …
Every custom provider disappears from the registry (fleet chat endpoints stop
resolving) and omp models lists only built-in locals. Measured 2026-10-18.
Correct shape
Runner api goes on the model entry only; auth: none satisfies the
credential requirement; omit contextWindow/maxTokens (the positivity check
fires only when they are provided — omp models still prints filled defaults,
which the runner transport never reads).
"frank-tts (dankclaw)":
baseUrl: http://192.168.0.143:7772/v1 # no `api:` here
auth: none
models:
- id: frank-tts
name: "frank-tts (dankclaw) — cloned voices"
api: openai-speech # runner api on the model
input: [text]
Roles live in config.yml (modelRoles), not in models.yml. Kind roles
(image, web, speech, dictation, judge) take no :thinking suffix.
Verify after every edit (never assume the file loaded)
omp models --kind tts --no-extensions # the new row must appear
omp models --no-extensions | grep -E '<each fleet chat model>' # and still be listed
omp models | grep -c 'validation failed' # must be 0
A run that lists only built-ins means your row broke the file — revert before yielding.
Speech transport contract (openai-speech)
Body is {model, input, response_format, voice?, speed?}; voice is forwarded
only when explicitly set; sample_rate/bit_rate throw
(openai-speech does not support sampleRate). Codec comes from the
output_path suffix; 15 000-character cap. An unknown voice name is a server
error, not a fallback — and auth: none makes a dead endpoint read as
available, so point modelRoles.speech at such a provider only after it has
answered a real synthesis.