Commit Graph
22 Commits
Author SHA1 Message Date
yetone 2bb10bca6f providers: Command Code's balance is asked for with its key, as DeepSeek's and OpenRouter's are — how much of the plan's 5-hour and weekly windows is used, then the dollars left on it; and a model list's context_length (Command Code, OpenRouter) is kept as the model's context window, so the agents are told each one's real size 2026-09-27 19:45:18 +08:00
yetone ab7dd01506 codex: /fast works on a routing group too — a group with a ChatGPT account's GPT model in it is listed to Codex with the Fast tier, and the service_tier Codex then sends is kept through the group's routing and passed on to OpenAI's own backends (a ChatGPT account, api.openai.com) only; before, the request was rebuilt without it and Fast did nothing 2026-09-27 17:51:38 +08:00
yetone 7c4a5d114c providers: an OpenCode model is sent on the API models.dev says it's served on — Grok and GPT on /responses, Claude and MiniMax on /messages — so Claude Code asking OpenCode Go for Grok goes straight to /responses; OpenCode's "Model does not support this protocol" is also taken as the model being served elsewhere 2026-09-27 12:51:43 +08:00
yetone a5a8d29ba4 providers: a model list that says which endpoints each model is served on (supported_endpoints, as Command Code's does) is heeded for every provider, not Copilot's alone — a live-fetched list left it out, so Claude Code's request for Command Code's deepseek went to its /messages, which serves only its Claude models, and was turned away; it now goes to /chat/completions, translated, and a Claude model asked for over Chat goes to /messages. /messages and /v1/messages both name Anthropic's. Issue #93 2026-09-27 01:29:33 +08:00
yetone ea5d089b4a gui: the Agents and Providers pages open at once again — the Providers page worked out each agent's model and routing group again for every provider (every provider's models read again each time, Alma asked over HTTP each time), so it took 25s with many providers; now once per page. What is parsed from a file is kept until the file changes (Codex's models cache, the vendors' model lists, ~/.claude.json's account, and an agent's TOML config — Codex's can run to megabytes of trusted projects, and was parsed again for every field); and what Alma answers when magpie only shows what it is on is reused for five seconds, as its providers take most of a second each time, while a change and what it reads first still ask Alma. /api/providers 25s → 0.02s, /api/state 7s → 0.1s 2026-09-26 22:25:28 +08:00
yetone 7174df1932 dsh: each magpie model says its context window, longest reply and whether it takes images — dsh otherwise takes a million tokens of context, 256K out and text only for every model, so a 128K model overflowed and a vision model was sent no images (#81); the longest reply comes from the catalog's output limit, a group's is its members' least; older dsh ignores the fields it doesn't know 2026-09-26 12:42:11 +08:00
yetone 81342b1b05 provider: a custom provider can list its models from a URL of its own — Xiaomi MiMo's plans are served at their own hosts while the list is at api.xiaomimimo.com/v1/models, so fetching models from the base URL found nothing; More endpoints has a Models URL (模型列表地址), asked with the key and nowhere else, and magpie provider set <id> models.url=… sets it (#67) 2026-09-25 22:16:11 +08:00
yetone aedf23abc5 provider: a relay given without its /v1 — one that lists its models at base/v1/models but not at the base — has /v1 added to its chat and responses bases when its models are fetched, since the gateway sends chat to the base as written and its requests 404'd while its models showed; and an Antigravity account Google gave no project says so plainly (with Google's reason, when it gives one) instead of "Usage unavailable" alone 2026-09-25 16:51:26 +08:00
herrkaefer b5d47ca5e7 gateway: an image sent to a model that can't see is dealt with before it goes out, and one a tool returned no longer ends the chat (#56)
A model's image input is taken from models.dev and the provider's own list, and a group's from its members: only a model known to be text-only is refused an image — one whose support is unknown still gets it, and Codex, OpenCode and Pi are told which models take images. An image the user attaches for a text-only model answers 400 in the client's own format before the upstream is asked; an image earlier in the chat, or one a tool returned (Claude Code's Read, Codex's view_image, a Chat tool message), becomes a short text note, so a chat that met a picture carries on after a switch to a text-only model. Thanks @herrkaefer.
2026-09-25 15:39:56 +08:00
yetone d6784bd114 codex: a model a custom provider serves takes the reasoning levels models.dev gives it from the others serving it, so the Codex app offers an effort for it (a Volcengine endpoint's glm-5.3-flash showed 中 with nothing to pick, and magpie's effort control a "none" Codex never used) — levels were only taken from models.dev's entry for the vendor itself, and a vendor it doesn't list (a custom provider, a proxy) had none, so Codex's catalog carried no supported_reasoning_levels; a model models.dev doesn't list for its vendor now takes, by bare id as the context window is found, the levels most of the providers giving any give it (glm-5.3-flash: low, high, max, default high), one no one gives levels for keeps none. Codex's effort is settled on one the model takes when a model is picked and when the catalog is synced, magpie shows the catalog's default where none is set, and the gateway sends a Chat vendor reasoning_effort at the model's nearest level (Codex's medium goes to glm-5.3-flash as high), as asked where the model's are not known 2026-09-25 14:54:47 +08:00
yetone 09c635cf03 agents: a model through magpie tells Pi, Crush, omp and Codex how much it holds, and a provider added, edited or removed reaches the model lists agents keep in files of their own — the catalog carried no context window, so Pi took every model through magpie for a 128K one (a CLIProxyAPI's gpt-5.5 holds 922K) and Crush for a 200K one; each model now carries models.dev's input limit, else its context, looked up by bare id as most of the providers serving it give it (a proxy's "openai/gpt-5.4", "gpt-5.4(high)", "glm-4.6:free" find it too; a group holds the least of its members'). And those lists were written only when a model was picked: Codex's magpie-models.json, Pi's models.json, OpenCode's, Crush's, Command Code's, omp's and Hermes' provider blocks and dsh's llm-deepseek entry kept the catalog as it was then, so a provider added later never showed. Saving a provider, a vendor's list fetched anew or models.dev synced now rewrites each one magpie wrote, where it differs, and the app does once at start-up; a Codex signed in to ChatGPT, which asks the gateway, kept its cached list under the backend's ETag, which a change of magpie's never changed — the ETag (and a reply's X-Models-Etag) now carries a tag of magpie's models, and a cache from before a change is aged so the next Codex asks again 2026-09-25 12:32:14 +08:00
yetone 626933ff2b codex: a magpie model that takes images says so in the catalog magpie gives Codex, which otherwise drops an attached image before sending — every magpie model was listed as text-only, so a picture pasted into Codex never reached a vision model; whether a model takes images is what its vendor's models.dev entry says, or for one served by a vendor models.dev doesn't list, what most of the providers serving that model say, and a routing group takes them only when every member does 2026-09-25 06:59:45 +08:00
yetone 6f19f60b08 provider(copilot) + gateway: each request goes straight to an API its model is served on, as the provider's model list says, rather than being learned from a refusal — Copilot's list gives every model its endpoints (GPT-6 and 5.5 on /responses alone, Claude on /v1/messages and /chat/completions, Gemini and Kimi on /chat/completions), they are kept with the cached list, and the gateway picks among them, relaying the agent's own API when it is one and translating otherwise; a refusal is still caught for a provider that doesn't say. Copilot's Anthropic endpoint is used too, so Claude Code reaches Copilot's Claude models without translation; a turn that only returns tool results is counted as the agent's (X-Initiator) in Anthropic's format as in the others, and images in Anthropic and Responses requests are flagged as Copilot asks. The provider test asks each endpoint with a model served there 2026-09-25 05:22:52 +08:00
yetone ad421374d8 agent(picker): a provider an agent is signed in to on its own is named and shown as itself — "GitHub Copilot" with Copilot's logo in OpenCode's picker rather than "github-copilot" under the first model's Claude logo, "Anthropic" rather than "anthropic" 2026-09-25 04:48:12 +08:00
yetone ecaaf888b5 providers: a provider with several keys has its models asked with each key, and each model remembers which keys see it — a relay that hands out a key per group lists each group's models to its key only; requests go to a key that lists the model (every key when none does), and Test signs each endpoint with a key made for it and asks for a model that key sees 2026-09-25 01:15:02 +08:00
yetone 829d52f75a provider: a custom provider can name several catalogs (catalog=openai, deepseek) — a gateway reselling many vendors gets names and reasoning levels for all of them, prefixed ids like deepseek/deepseek-chat included (#17) 2026-09-24 14:10:53 +08:00
elonnzhang 3ffebeebb6 provider: custom request headers for custom providers
Extra HTTP headers, typed by the user, ride on every request magpie makes
to a plain key+URL provider — forwarded calls, connectivity tests, and
model-list fetches — applied after the auth headers. Presets and signed-in
agent accounts ignore them. Editable in the GUI (with a JSON value mode) and
via the CLI as header.X-Foo=bar.
2026-09-24 12:50:51 +08:00
yetone 9f678458b9 catalog: ask a relay for its chat models without the anthropic header
OpenRouter serves a second, namespaced catalogue from /v1/models as
soon as it sees anthropic-version, so sending that header on the chat
fetch cached ids like anthropic/xiaomi/mimo-v2.6-pro-ultraspeed[1m]
that the chat endpoint then rejected. Send it only when the fetch is
for the Anthropic protocol, where the official API requires it.
2026-09-24 02:27:06 +08:00
yetone 702477525a Claude subscription as a provider; model lists fetched, never compiled in
A signed-in Claude Code is now offered as a provider (claude/…) like Codex
and Copilot. Anthropic classifies another agent's system prompt as
third-party traffic even over Claude Code's OAuth, so magpie drives the
real local claude binary for every generation: the caller's tools are
bridged in over MCP (magpie claude-mcp-helper), and tool results resume
the same Claude Code turn. Token counting is estimated locally so the
OAuth token takes no side path.

No model list is compiled in any more. The built-in catalog, preset
defaults and Claude Code's alias list are gone; the picker shows the
models.dev catalog (refreshed in the background when stale) layered with
each vendor's own /models answer, and signed-in accounts fetch theirs at
start-up. Whether a model rejects temperature/top_p now comes from
models.dev rather than a name prefix.

The gateway retries a Chat request on the Responses endpoint when the
model is Responses-only, and remembers that. Recent calls keep the first
256 KB of request and response bodies, viewable in the call list. The
Usage tab shows subscription allowances (Claude, Codex, Copilot) as the
vendors report them.
2026-09-24 00:20:59 +08:00
yetone 402a96c39d Rename dial to magpie, with a magpie for a logo
The product, module path (github.com/yetone/magpie), binaries, env vars
(MAGPIE_ADDR, MAGPIE_DEV_UI, MAGPIE_THEME, MAGPIE_DEBUG), config and cache
folders (~/.config/magpie, ~/.cache/magpie), bundle id (com.yetone.magpie),
gateway provider id and token, and every UI string now say magpie.

On first run magpie copies ~/.config/dial and ~/.cache/dial to the new
folders when they don't exist yet (copy, not move, so a still-running dial
keeps working; the old folders can be deleted by hand later).

The logo is a small round magpie in profile: one path for the header and
the tray, and the app tile adds the white belly and the blue-green tail.
The header mark is drawn in ink rather than the accent colour, which
fought the text in light mode.
2026-09-23 23:55:11 +08:00
yetone 30c489a000 usage: a token statistics page
The gateway now records every call's token counts (read from the provider's
own usage block, in both the translated and the pass-through paths) with the
calling agent taken from the client's User-Agent, into
~/.config/dial/usage.jsonl. A Usage tab sums them by period, agent and
model, with a per-hour/day/week timeline and cost at models.dev list
prices; dial usage does the same in the terminal.

Also nudges the window header 1pt up so the brand sits level with the
traffic lights, and lets ?view= open the window on a tab.
2026-09-23 03:16:33 +08:00
yetoneandClaude 0a234ce41d dial: one dial for every coding agent's model
Wails v3 tray panel and window, TUI and CLI. Switches model, effort and
provider for Claude Code, Codex, Gemini CLI, OpenCode, Pi, Goose, Cursor,
Copilot CLI and Crush with format-preserving config edits. Providers page
and registry, stored keys, live vendor model lists, profiles.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-09-22 21:47:29 +08:00