pi-model-scout0.6.0
Pi provider extension: automatic model discovery for OpenAI-compatible endpoints (vLLM, LM Studio, Ollama, LiteLLM, etc.), including Unsloth Studio connected services.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-model-scout
A pi package that automatically discovers models from OpenAI-compatible endpoints, so you don't have to list every model in models.json by hand.
Works with any server that implements GET /v1/models: Unsloth Studio, vLLM, SGLang, LM Studio, Ollama (/v1), LiteLLM, llama-server, and similar.
For Unsloth Studio it also discovers the connected services (OpenRouter, OpenAI, …) configured in Studio and exposes them as separate providers.
Install
# from npm (after publishing)
pi install npm:pi-model-scout
# from git
pi install git:github.com/cobomi-lab/pi-model-scout@v0.1.0
# from a local checkout
pi install ./pi-model-scout
# try once without installing
pi -e ./pi-model-scout
Configure
Add "discoverModels": true to any OpenAI-compatible provider in ~/.pi/agent/models.json (or $PI_CODING_AGENT_DIR/models.json). You don't need a models array.
{
"providers": {
"cobomi": {
"baseUrl": "https://unsloth.example.com/v1",
"api": "openai-completions",
"apiKey": "$UNSLOTH_API_KEY",
"discoverModels": true,
"contextWindow": 32768,
"maxTokens": 8192,
"compat": {
"supportsDeveloperRole": false,
"supportsReasoningEffort": false,
"supportsUsageInStreaming": false
}
},
"vllm": {
"baseUrl": "http://localhost:8000/v1",
"apiKey": "none",
"discoverModels": true
}
}
}
| Field | Required | Description |
|---|---|---|
discoverModels |
yes | Set to true to enable discovery for this provider. |
baseUrl |
yes | OpenAI-compatible base URL. It usually ends in /v1. |
apiKey |
no | Sent as Authorization: Bearer …. Accepts the same syntax as pi: $VAR, ${VAR}, !command, or a literal value. |
api |
no | Pi API type. Default: openai-completions. |
headers |
no | Extra request headers (the same value syntax applies). |
compat |
no | Applied to every discovered model. |
contextWindow |
no | Context window to use when the server doesn't report one. Default: 32768 (local models) or 128000 (connected services). |
maxTokens |
no | Default output-token limit. Default: 8192. |
contextWindow and maxTokens at the provider level are fields this extension adds; pi itself ignores them.
Then select a model with /model, or:
pi --list-models
pi --model cobomi/unsloth/Qwen3.8-27B-GGUF
How it works
- On startup the extension reads
models.jsonand callsGET {baseUrl}/modelsfor every provider withdiscoverModels: true. - It registers each provider with the discovered models through
pi.registerProvider(). Requests use pi's built-inopenai-completionsstreaming. - A
refreshModelshook queries the server again whenever pi refreshes its catalog (for example, when you open/modelor runpi update --models).
Each discovery request times out after 2 seconds, so an unreachable server delays startup by at most about 2 seconds. Discovery errors are shown as a pi notification once the session starts. In print/JSON mode, where there is no UI, they are written to stderr with the prefix [pi-model-scout].
4. Unsloth Studio only: it also calls GET {root}/api/providers/ (Unsloth's API path, not part of the OpenAI spec). Each enabled connected service becomes its own provider named <provider>-<service>, for example cobomi-openrouter. Requests for those models still go to Unsloth's /v1/chat/completions and carry extra body fields that tell Unsloth which service to forward them to (provider_id, provider_type, external_model). For servers other than Unsloth, this step quietly does nothing.
Context length is taken from context_length or max_model_len in the /models response, if present. Reasoning and image support are guessed from the model ID. To correct them, use pi's modelOverrides in models.json:
{
"providers": {
"cobomi": {
"modelOverrides": {
"unsloth/Qwen3.8-27B-GGUF": { "contextWindow": 131072, "input": ["text", "image"] }
}
}
}
}
Commands
| Command | Description |
|---|---|
/scout-refresh |
Re-reads models.json and runs discovery again. This picks up providers you added or removed, new models, and newly connected Unsloth services without restarting pi. Shows a summary of the providers and model counts. If models.json can't be parsed, it reports the error and keeps the current providers. |
Known limitations
- Unsloth connected services must have a key saved for the API-key user. Unsloth forwards the request using its saved key for that service. If it has none, you get errors such as
401 Failed to authenticate request with Clerk(OpenRouter). Save the service key in Studio for the user that owns the API key. Alternatively, use pi's built-in provider directly (for example/login openrouter). - All discovered models report a cost of 0.
- If a server can't be reached at startup, that provider has no models. A later catalog refresh or
/scout-refreshretries. - Embedding, audio, and image-generation models listed by
/modelsare registered as chat models.
Development
pi -e ./extensions/pi-model-scout.ts --list-models # load without installing
Pi loads TypeScript directly, so no build step is needed. Pi provides @earendil-works/pi-coding-agent at runtime, so it is a peerDependency. It is also a devDependency, used only for type checking:
npm install
npm run typecheck
Tasks (just)
A justfile wraps the common tasks. Run just to list them.
| Recipe | What it does |
|---|---|
just test |
Type check and run a smoke test against a fake /v1/models server. Your ~/.pi config is not touched. |
just try / just models |
Run pi with the extension loaded from this checkout |
just install-local / just uninstall-local |
Add or remove this checkout in your pi install |
just check |
Check for leftover placeholders, run test, and preview the npm tarball |
just git-init <url> |
Initialise git, add the remote, make the first commit, and push |
just release-git [patch|minor|major] |
Run check, bump the version, then commit, tag and push |
just release [patch|minor|major] |
Same as release-git, then npm publish |
Publish
npm pack --dry-run # check tarball contents
npm publish # or: npm publish --registry https://your.registry/
The pi-package keyword makes the package eligible for the pi package gallery.
License
MIT