Request headers, omp model discovery and compat options now sit in a
collapsed "Advanced Options" section below the model list, matching the
Claude Code and Codex forms. It stays collapsed even when a preset fills
compat values.
The compat and discovery hints are rewritten in plain language, and the
discovery types get readable labels instead of raw omp identifiers. The
discovery select ignores an empty value, which Radix can report when it
mounts inside a form.
Checked against omp 18.12.6 with real DeepSeek and PackyCode requests:
- Usage queries sent an omp apiKey verbatim. omp reads it as an
environment variable name first (process environment, then .env in the
agent dir, the config root and home) and falls back to the literal, with
no $NAME syntax, so "apiKey: DEEPSEEK_API_KEY" reached the balance API as
"Bearer DEEPSEEK_API_KEY" and got 401. Resolve it the same way; names
match exactly, and "!command" values are still never run.
- With only a legacy models.json present, adding a provider created
models.yml, which stops omp from migrating models.json and drops the
user's providers. Refuse instead and ask the user to run omp once.
- omp disables every custom provider when one models.yml node fails its
schema. Reject the enum values it rejects before writing: compat
thinkingFormat, maxTokensField and the other enumerated fields
(including whenThinking), reasoningEffortMap levels, auth, authHeader,
and discovery type, injectV1 and timeoutMs.
- The form kept discovery.injectV1 when switching away from
openai-models-list, which omp allows only there. Drop it on switch.
Anthropic-protocol presets still omit auth on purpose: omp then shapes
requests like Claude Code, which relays such as PackyCode require (they
answer 403 to auth: apiKey).
The Pi form is shared with omp, but its duplicate-key check always
queried Pi's providers. Adding an omp provider whose key already
existed in Pi was flagged as a duplicate and blocked, even though the
backend keeps the two apps apart (each checks only its own rows and
its own models file). The check now follows the current app.
The Pi form (also used by omp) only filled a per-row dropdown after
"Fetch models", so models had to be added one row at a time, unlike the
OpenCode, Codex and Kimi Code forms. Use the shared FetchedModelPicker:
a successful fetch opens the dialog, checked models are added as rows
and filled from presets or models.dev (thinking level maps only for Pi),
and unchecking a configured model removes its row. Fetched IDs are
de-duplicated and the success toast is dropped since the dialog opens.
The per-row dropdown stays.
Drop the copied OmpProviderForm and the YAML editor; Oh My Pi now uses
PiProviderForm with an omp mode (no provider-level name, no
thinkingLevelMap, plus a discovery type selector). Presets are derived
from the Pi catalog. Pi-family helpers (isPiFamilyApp, parametrized
current-state queries and usage-script command) replace the scattered
pi/omp branches, and omp error keys reuse the Pi error translator.
Co-authored-by: allenxu09 <s23372.xu@stu.scie.com.cn>
The provider key, the model ID and display name column headings, and
the context window and max output labels now use REQUIRED_LABEL like
the rest of the provider forms, instead of a hand-written "*" span.
The asterisk is drawn by CSS, so it no longer becomes part of the
label text that screen readers and tests read.
The provider key names the provider node in models.json, so it is now
shown for presets too (prefilled, editable) instead of only for custom
and edited providers, matching Kimi Code. A key that is already used
by another Pi card is flagged under the field and blocks saving, so
adding the same preset twice no longer fails only at the backend.
The 272K GPT cap (v4.0.13) applied to every window the metadata lookup
returned, so platforms that really serve the 1.05M OpenAI API window
(OpenRouter and other providers models.dev recognizes by address) were
capped too. The risk the cap guards against is narrower: a relay that
models.dev does not know falls back to the vendor's own entry, and its
1.05M lands on a model that is often served from a ChatGPT subscription
with a 272K window.
- Same-endpoint presets and the models.dev provider matched by address
keep their own windows; only the window borrowed from the vendor entry
(including when the matched provider lists none) is capped at 272K.
- A window the user types is kept as is. When a GPT model's window is
above 272K, the Codex, Hermes, OpenClaw, OpenCode and Pi forms show a
note under the field: relay GPT usually has the subscription window, and
an oversized one delays compaction until the upstream rejects the turn.
Text added in zh / en / ja / zh-TW.
Existing rows are not migrated. Codex GPT rows saved before v4.0.13 with
an auto-filled 1.05M now take effect since #8385; the note shows when the
form is opened.
models.dev lists the OpenAI API window for GPT models (1.05M for the
GPT-5.6 and GPT-6 families), but many relays serve GPT through ChatGPT
subscriptions, whose Codex backend catalogs these models at 272K. The
base URL cannot tell the two apart. An overstated window keeps clients
from compacting until the upstream rejects the prompt and the turn
fails, while an understated one only compacts earlier.
- Cap every GPT window resolveModelMetadata returns at 272K, whether it
comes from a preset, the recognized models.dev provider or the vendor
fallback; smaller windows such as gpt-4o's are left alone
- Lower the GPT windows in the Hermes, OpenClaw, OpenCode, Pi and Codex
presets to the same cap, with a test guarding every preset source
- Pin the Claude Code ChatGPT subscription preset's context and
auto-compact windows to 272K; the 372K it used was the backend's
mid-2026 value and now sits above the backend's limit
Pages (phase 4):
- Usage: v7 layout (filter row, four metrics with more on demand,
switchable trend, request log / provider / model / pricing tabs, data
sources sheet). Latency becomes output speed: output / (duration -
first token), shown only for requests with at least 100 output tokens;
provider totals sum output and generation time instead of averaging.
- Sessions: single-column list grouped by project or time, drilling into
a reader with resume, find, question jump and copy actions.
- MCP and Skills share one app matrix (neutral checks, retry on failed
writes, column bulk actions with undo); MCP add/edit moves into a
drawer with form/JSON modes; Skills merges installed and discover and
always shows a Pi column.
- Prompts: one page for eight apps including Hermes SOUL.md, enable and
disable as buttons, delete with undo instead of a confirm, copy to
other apps, import existing files; app pages show the active prompt.
- Add provider is two steps: pick a preset (always-on search including
Chinese names and domains, categories inferred for display, sorted by
name with no promoted entries), then fill the form. Edit pages name
the provider and warn when it is the one in use.
- App page menu links to that app's usage.
Visual pass (phase 6):
- Secondary pages cover only the content area so the sidebar stays.
- Cmd/Ctrl+K jumps to apps, pages and settings sections.
- Legacy button variants, primary color, dialogs, toasts and sheets
follow v7 tokens; hard-coded palette classes and 10px text across
the remaining components are replaced with tokens.
Without a thinking map, Pi shows off..high for a custom model and hides
xhigh and max, even when the upstream supports them. When a fetched
model is picked and has no map yet, fill one:
- Use the reviewed map of the Pi preset at the same endpoint, but only
under the same API and when the compat it relies on does not conflict
with what the user wrote. Missing compat keys are added to the model,
and for openai-completions the thinking format and reasoning_effort
support that Pi detects must match the preset's.
- Otherwise, when Pi sends levels verbatim as reasoning_effort
(openai-responses, or openai-completions detected as the OpenAI
thinking format), derive the map from models.dev effort levels using
Pi's own getEffortThinkingLevelMap rule.
A model with its own baseUrl is now looked up by that address. Update
the Pi design docs accordingly.
Apply the same lookup to Pi custom providers: picking a fetched model
fills contextWindow, maxTokens, reasoning, and image input when they are
still empty. thinkingLevelMap is left untouched.
Update the Pi design docs, which previously forbade inferring model
capabilities. That rule came from an earlier implementation that voted
across providers by model name and produced wrong values; the docs now
keep the lesson as constraints (match the provider by endpoint first,
fill only empty fields, never generate a thinking map).
* feat: Add new AI models and update presets
- Introduced new models in piModelCatalog including:
- DeepSeek V4.1 Flash
- Step 5 Preview
- Step 3.7 Flash
- Claude Opus 5.5
- Claude Fable 5.1
- GPT-6 variants (Sol, Luna, Astra)
- Gemini 3.8 Flash
- MiMo V2.6 variants (Pro, Flash, Pro UltraSpeed)
- Updated piProviderPresets to include new models and their configurations.
- Enhanced piThinkingProfiles with new response mappings for GPT-6 Astra and other models.
- Adjusted tests to reflect new models and their expected behaviors in PiProviderForm and other configurations.
- Updated reasoning level presets for Xiaomi MiMo models to include new categories.
- Added new test cases for xAI OAuth provider presets to validate new model configurations.
* fix: 保留历史定价并修正供应商预设
* fix: 补回 MiMo Codex 官方系统提示词