72 lines
2.8 KiB
Markdown
72 lines
2.8 KiB
Markdown
---
|
|
name: omp-models-yml-runner-api-placement
|
|
description: 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).
|
|
|
|
```yaml
|
|
"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)
|
|
|
|
```bash
|
|
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.
|