pi-autofill-model-metadata
Pi extension: auto-fill model metadata from models.dev for custom providers
Package details
Install pi-autofill-model-metadata from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-autofill-model-metadata- Package
pi-autofill-model-metadata- Version
0.2.3- Published
- Aug 18, 2026
- Downloads
- 640/mo · 62/wk
- Author
- peach0x33a
- License
- MIT
- Types
- extension
- Size
- 84.9 KB
- Dependencies
- 3 dependencies · 1 peer
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
English | 简体中文
pi-autofill-model-metadata
A Pi extension that obtains custom model metadata from models.dev or the standalone Codex specification catalog according to explicit mappings supplied by the user, then completes Provider configuration through pi.registerProvider() when Pi starts.
It is intended for third-party gateways, self-hosted proxies, and OpenAI/Anthropic-compatible APIs. Declare the connection details and model IDs in Pi's models.json, then explicitly specify which models.dev metadata each model should use in auto-models.jsonc.
Features
- Fills in model name, context window, maximum output, reasoning capability, input modalities, and pricing from models.dev.
- Accepts only explicit
models.dev-provider/models.dev-modelmappings; it never makes global guesses. - Requires mappings to completely cover the target Provider, preventing models from silently disappearing during re-registration.
- Preserves model fields explicitly set by the user in
models.json. - Caches models.dev data with a default lifetime of 24 hours.
- Supports HTTP(S) or SOCKS/SOCKS5 network proxies configured with a one-line proxy URL, including usernames and passwords.
- Falls back to structurally valid stale cache data when downloading fails.
- Uses atomic cache writes so an interrupted process cannot leave a partially written file.
- Can produce credential-redacted debug snapshots.
- Does not modify
models.jsonorauto-models.jsonc; all enhancements apply only to the current Pi runtime. - Configuration, caching, parsing, and Provider registration are covered by automated tests.
How it works
When Pi loads the extension, it:
- Reads
~/.pi/agent/models.jsonto obtain Provider URLs, API types, credentials, headers, and model lists. - Reads
~/.pi/agent/auto-models.jsoncto obtain proxy settings, the explicit metadata source for each Pi model, and cache/debug options. - Checks that mappings are complete, contain no extra models, and use correctly typed configuration fields.
- Statically dispatches each source to the models.dev or Codex adapter; it reads the cache or requests the API only when a models.dev source is first encountered.
- Parses only the explicitly selected source models, validates the required models.dev fields, and normalizes them into source-independent metadata and provenance records.
- Constructs a complete Pi model configuration in one pass with the field mapper, merging explicit overrides from
models.json. - After every source is parsed successfully, atomically registers or replaces the Provider in memory through
pi.registerProvider().
~/.pi/agent/models.json
│
├── Provider URL, API, credentials, model IDs
│
▼
~/.pi/agent/auto-models.jsonc ──► Explicit metadata sources
│
├── models.dev adapter ──► API / local cache (once, on demand)
└── Codex adapter ───────► Standalone specification catalog
│
▼
Source-independent normalization + field mapping + user overrides
│
▼
pi.registerProvider() (current runtime only)
Requirements
- Pi installed.
- Node.js with native
fetchsupport; the current Node.js LTS is recommended. - A custom Provider configured in
~/.pi/agent/models.json. - When using a models.dev source, access to models.dev or a valid local cache.
- If the current network cannot access models.dev directly, an HTTP(S) or SOCKS/SOCKS5 proxy configured in
auto-models.jsonc.
[!IMPORTANT] Pi extensions run with the current user's permissions. Inspect the source of any third-party extension before installing it.
Installation
Install from npm
pi install npm:pi-autofill-model-metadata
Install from the GitHub monorepo
pi install git:github.com/peach0x33a/pi-extensions
pi config
The Git package downloads the entire monorepo. After running pi config, enable only packages/autofill-model-metadata/index.ts.
To see the packages registered with Pi after installation:
pi list
Install from local source
git clone https://github.com/peach0x33a/pi-extensions.git
cd pi-extensions
bun install
pi install "$PWD/packages/autofill-model-metadata"
For local packages, Pi records only the path and does not copy the source. After modifying local source, restart Pi or run /reload to load the new version.
Try without installing
pi -e /absolute/path/to/pi-extensions/packages/autofill-model-metadata --list-models
Configuration
The extension reads two files:
| File | Purpose |
|---|---|
~/.pi/agent/models.json |
Pi Providers, connection details, credentials, and model IDs |
~/.pi/agent/auto-models.jsonc |
Explicit Pi-model-to-models.dev or Codex mappings and cache/debug options |
1. Configure models.json
Example:
{
"providers": {
"my-proxy": {
"name": "My Proxy",
"baseUrl": "https://proxy.example.com/v1",
"apiKey": "$MY_PROXY_API_KEY",
"api": "openai-responses",
"models": [{ "id": "gpt-main" }, { "id": "claude-main" }]
}
}
}
Provider names and model IDs are local identifiers and may differ from their names in models.dev. Using an environment variable reference for apiKey is recommended; do not commit a real key to version control.
The extension reads these Provider fields:
namebaseUrlapiKeyapiauthHeaderheadersmodels
Entries in models can be strings or objects containing an id:
{
"models": [
"gpt-main",
{
"id": "claude-main",
"name": "Internal Claude",
"maxTokens": 8192
}
]
}
2. Configure auto-models.jsonc
Create ~/.pi/agent/auto-models.jsonc:
{
// Optional; supports http(s)://, socks://, and socks5://, including user:password@
"proxy": "socks5://username:password@127.0.0.1:1080",
// Unit: seconds; default 86400 (24 hours)
"cacheTTL": 86400,
// Optional; default ~/.pi/agent/models-dev-cache.json
"cachePath": "~/.pi/agent/models-dev-cache.json",
"mapping": {
"my-proxy": {
"gpt-main": "openai/gpt-5.4",
"claude-main": "anthropic/claude-sonnet-4-6",
},
},
}
proxy proxies only this extension's requests to the models.dev API; it does not change network requests from Pi's other Providers. The proxy address, username, and password all go in the same URL line. If the password contains special characters, percent-encode them according to URL rules (for example, write @ as %40). Omit this field when no proxy is needed.
The mapping structure is:
Pi Provider name
└── Pi model ID: metadata-source/model ID
For example:
{
"mapping": {
"company-gateway": {
"fast-model": "google/gemini-2.5-flash",
"reasoning-model": "openai/o3",
},
},
}
models.dev sources can be looked up at https://models.dev or https://models.dev/api.json.
For Codex GPT models not listed by models.dev, use codex/<model-id> directly:
{
"mapping": {
"my-responses-provider": {
"gpt-5.6-sol": "codex/gpt-5.6-sol",
},
},
}
The Codex source comes from the standalone pi-codex-gpt-metadata specification catalog package. That package maintains only a data catalog and does not register a Pi Provider; this extension's Codex adapter clones and normalizes its catalog values. If every mapping starts with codex/, initialization does not retrieve or download models.dev data. pi-autofill-model-metadata does not depend on pi-gpt-enhance; models.dev and Codex metadata filling both work when installed on their own.
pi-codex-gpt-metadata intentionally does not appear in the Pi package gallery because it is a regular npm dependency, not an installable Pi extension: it has no pi.extensions entry point and is not tagged with the pi-package keyword. Search for and install pi-autofill-model-metadata in Pi instead; npm installs the Codex catalog automatically through this extension's direct dependency.
For OpenAI Responses server-side compaction, you may also install pi-gpt-enhance. The two extensions separately register model metadata and request streams. Pi merges the Provider configuration, so installation and load order do not affect the final result.
Strict mapping policy
This extension uses a fail-closed policy. For every Provider appearing in mapping:
- Every model in
models.jsonmust have a mapping. - The mapping cannot contain a model not declared in
models.json. - Every mapped source must resolve in the specified models.dev Provider or the shared Codex catalog.
- It never searches another Provider for a same-named model.
- It never selects the “first match”: if case-insensitive matching produces multiple candidates, that source is considered unresolved.
- The mapped Provider and its model fields must pass type validation; validation failure aborts registration.
If any check fails, the extension aborts registration for the entire run and does not commit a partial Provider configuration. This prevents spelling mistakes, missing mappings, or remote data changes from making some models silently disappear.
Other Pi Providers not included in mapping are unaffected by this extension. Even if those Providers have malformed data in models.json, this extension ignores them and they do not affect registration of mapped Providers.
Filled fields and override rules
The extension fills these fields from models.dev or the shared Codex catalog:
| models.dev | Pi |
|---|---|
name |
name |
limit.context |
contextWindow |
limit.output |
maxTokens |
reasoning |
reasoning |
modalities.input |
input, keeping only text and image |
cost.input |
cost.input |
cost.output |
cost.output |
cost.cache_read |
cost.cacheRead |
cost.cache_write |
cost.cacheWrite |
The effort values in models.dev's reasoning_options populate thinkingLevelMap: supported levels map to Pi levels with the same names, none maps to off, and unsupported levels become null (Pi displays only [off]). A model without effort (only toggle or missing) receives an all-null map; Pi no longer falls back to a fabricated default level list.
The Codex source also fills the corresponding model's thinkingLevelMap, Responses compat capabilities, and tiered pricing.
If a model object in models.json explicitly sets any of the following fields, the user's value overrides the models.dev default:
namecontextWindowmaxTokensreasoninginput- Individual fields in
cost apibaseUrlheaderscompatthinkingLevelMap
This lets you use models.dev as the default metadata source while correcting values for the actual capabilities of a proxy service.
User overrides are type-checked while loading (for example, maxTokens must be a positive number, cost fields must be non-negative, and input may contain only text/image). If a type is invalid, the Provider is marked invalid; if it is also mapped, registration aborts for the entire run and reports the reason.
Cache
Default cache file:
~/.pi/agent/models-dev-cache.json
Default lifetime:
86400 seconds (24 hours)
Behavior:
- A fresh cache is used without accessing the network.
- When the cache is expired or absent, the extension downloads current data from models.dev; when
proxyis configured, the request uses the specified proxy. - After a successful download, it updates the cache with a temporary file and an atomic rename.
- If downloading fails and structurally valid stale cache data exists, it uses the stale cache and prints a warning.
- If downloading fails and no valid cache exists, it aborts registration.
To force a refresh, delete the cache and run Pi again:
rm ~/.pi/agent/models-dev-cache.json
pi --list-models
You can also set cacheTTL to 0 to attempt a refresh on every load; network failures still fall back to valid old cache data.
Debug output
Enable it in auto-models.jsonc:
{
"mapping": {
"my-proxy": {
"gpt-main": "openai/gpt-5.4",
},
},
"debug": {
"enabled": true,
"dumpPath": "~/.pi/agent/expanded-models.json",
"diffOnly": true,
},
}
Options:
| Option | Default value | Description |
|---|---|---|
debug.enabled |
false |
Whether to generate a debug file |
debug.dumpPath |
~/.pi/agent/expanded-models.json |
Output path; supports ~/ |
debug.diffOnly |
true |
Output only changed Providers; set to false for a full snapshot |
Debug output includes:
- Generation time;
- models.dev cache age;
- a summary of filled and failed models, including fields from models.dev for each model (
filledFields) and fields overridden by the user (overriddenFields); - Provider differences or the final snapshot.
Provider API keys, Provider headers, and model-level headers are replaced with <redacted>. Debug files may still contain internal Provider URLs, model names, and other information. Do not commit them publicly without inspecting their contents.
Verify the installation
Run:
pi --list-models
When the extension initializes normally, it stays quiet so that it does not bypass Pi's rendering layer by writing to the terminal in subagent, SDK-session, or other resource-reload scenarios. During verification, inspect the model list directly: the models' context windows, maximum outputs, reasoning, and image capabilities should use the completed data.
Only exceptional conditions such as invalid configuration, an unresolvable mapping, or a failed download with no usable cache write errors or warnings.
Common errors and troubleshooting
Configuration file not found
If the extension cannot find the mapping file, it silently skips registration (it is treated as disabled). Confirm that the file is located at:
~/.pi/agent/auto-models.jsonc
If the mapping file exists but models.json is missing or cannot be parsed, it prints:
auto-models.jsonc is configured but models.json could not be loaded; registration skipped
Check that ~/.pi/agent/models.json exists and is valid JSON.
Mapped Provider validation failed
Mapped provider "my-proxy" is invalid in models.json: providers.my-proxy.models[0].maxTokens must be a finite positive number
Following the message, correct the field type in the corresponding Provider in models.json. A validation failure in an unmapped Provider does not affect registration.
Explicit mapping missing
Missing explicit mapping for my-proxy/model-id
Add a mapping for every model in that Provider in models.json. The target Provider must be mapped completely; mapping only part of it is not allowed.
A local model that does not exist was mapped
my-proxy/model-id is mapped but absent from models.json
Remove the extra mapping, or declare the model in the corresponding Provider in models.json.
models.dev Provider or model not found
Source provider "..." not found
Source model "..." not found
Check that the right side of the mapping uses the real Provider ID and model ID from models.dev. The extension does not guess across Providers.
Failed to load models.dev data
Failed to load models.dev data: ...
Check the network connection, the proxy URL (it must use http://, https://, socks://, or socks5://), and the cache file. If the cache is corrupted, delete it:
rm ~/.pi/agent/models-dev-cache.json
Then run Pi again.
Changes did not appear after editing configuration
Restart Pi, or run this in an interactive session:
/reload
The extension does not write completed results back to models.json, so checking the file alone cannot show runtime enhancements. Use pi --list-models or the debug output to confirm them.
Update and uninstall
Update all installed extensions:
pi update --extensions
If installed from npm:
pi remove npm:pi-autofill-model-metadata
If installed from the GitHub monorepo:
pi remove git:github.com/peach0x33a/pi-extensions
If installed from a local path:
pi remove /absolute/path/to/pi-extensions/packages/autofill-model-metadata
Uninstalling the extension does not delete these user files:
~/.pi/agent/models.json~/.pi/agent/auto-models.jsonc~/.pi/agent/models-dev-cache.json- Custom debug output files
Delete them yourself if they are no longer needed.
Development
git clone https://github.com/peach0x33a/pi-extensions.git
cd pi-extensions
bun install
bun run check
Available commands:
| Command | Description |
|---|---|
bun run --filter pi-autofill-model-metadata test |
Run Vitest tests |
bun run --filter pi-autofill-model-metadata typecheck |
Run the TypeScript type check |
bun run --filter pi-autofill-model-metadata check |
Run type checking followed by tests |
pi -e ./packages/autofill-model-metadata --list-models |
Run real Pi acceptance using current source |
Project modules:
| File | Responsibility |
|---|---|
index.ts |
Extension entry point, mapping coverage checks, atomic Provider registration |
config.ts |
Read and validate Pi and mapping configuration |
cache.ts |
models.dev download, proxy, validation, caching, and fallback |
resolver.ts |
Resolve sources, static dispatch, and lazy/reused models.dev loading |
models-dev-adapter.ts |
models.dev selection, validation, reasoning-option interpretation, and normalization |
codex-adapter.ts |
Clone and normalize Codex catalog values from the standalone package |
field-mapper.ts |
Complete Pi model construction, user overrides, field provenance, and immutability boundary |
debug.ts |
Generate redacted debug snapshots |
types.ts |
Source-independent contracts, models.dev, configuration, and Pi input data types |
types-ext.ts |
Minimal Pi Provider types used by this extension |
util.ts |
Shared utilities (path expansion, log prefix, and type predicates) |
test/ |
Unit and integration tests |
Design principles
- Explicit over guessing: Same-named models can have different limits, prices, or capabilities in different Providers.
- Fail closed: Incomplete configuration must not produce an apparently successful partial registration.
- User configuration first: models.dev supplies defaults, which the user can override to match the proxy's actual capabilities.
- Do not write back configuration: The extension registers runtime state only, avoiding accidental changes to credentials or user files.
- External input is untrusted: Configuration, network responses, and cache data are validated before use.
Acknowledgements
This project's design and implementation were inspired by opencode-auto-model-config, a plugin that provides similar automatic model metadata filling for OpenCode. Thanks to the original author, chisaato, for the excellent work and inspiration.
Data source
Model metadata comes from models.dev. The accuracy and update frequency of the data are provided by models.dev; a proxy service's actual limits may differ. Refer to the service provider's documentation and use user override fields in models.json to correct them.
License
This project is released under the MIT License.