Files
magpie/internal/library
ArvakandClaude Sonnet 5.5 f1906bca6a gateway: draw and film through a Grok subscription (Grok Imagine) (#360)
* gateway: draw through a Grok subscription (Grok Imagine)

A Grok subscription (SuperGrok, X Premium+) could not draw: Drawers() returned
nothing for it and draw() refused with "Grok (SuperGrok) can't draw: magpie
draws only through an OpenAI-compatible API, and Grok (SuperGrok) has none".
Grok Build's own image_gen / image_edit tools call the backend's Imagine API
at <cli-chat-proxy.grok.com/v1>/images/generations and /images/edits with the
CLI's sign-in, which magpie already uses for chat.

- drawsGrok / grokDrawers: a Grok account draws with grok-imagine-image and
  grok-imagine-image-quality, like a ChatGPT account does with GPT Image
- the Imagine API takes an aspect ratio, not a size or quality: size
  WIDTHxHEIGHT is matched to the nearest ratio it accepts (aspectAmong,
  aspectOf is unchanged); the image is asked for as base64
- an edit is JSON with the images as data URLs
- a plan's images cost nothing extra, so AutoDrawer ranks Grok with ChatGPT
  (ChatGPT still wins a tie on release date)
- provider.grokBase is exported as GrokBase, like CodexBase, for the test

Tested against a real SuperGrok account through the gateway: generation,
16:9, the quality model and an edit. Video is not covered: the Grok CLI's
video tools need zero data retention off or a storage bucket.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gateway: film through a Grok subscription, and a generate_video tool for agents

A Grok account that draws (c6578bc) can make videos too: Grok Imagine's
video endpoints sit behind the same sign-in.

The gateway speaks OpenAI's Videos API, so its SDK works as it is:
POST /v1/videos, GET /v1/videos/{id}, GET /v1/videos/{id}/content. A
request is taken on at once and polled; the id carries the provider and
the vendor's request id, so nothing is kept in the gateway and a restart
loses no video. Status is mapped (pending at 0% -> queued, pending ->
in_progress, done -> completed, failed/expired -> failed, with why).
seconds (1-15, the vendor's limit, which it says when exceeded), size
(-> aspect ratio and 480p/720p/1080p by the shorter side), input_reference
for image-to-video (URL, data URL, {image_url}, or a multipart file) and
reference_images are taken; a model that isn't a Grok video model is
refused by name. /content answers 409 until the video is ready.

`magpie mcp image` lists a second tool, generate_video: it starts the
video, waits (up to 10 minutes), saves the mp4 into the project
(generated-videos/ unless path says where, never over a file) and says
where, so an agent can animate an image it just drew by passing its path.

Checked against a real SuperGrok account: text-to-video, image-to-video
(input_reference), reference_images, both video models, the OpenAI
Python SDK (videos.create/retrieve/download_content), the MCP tool end to
end with two videos at once, and the error paths. Unit tests use a fake
Grok upstream.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gateway: videos follow the Settings' off switch, and an id can't change the vendor's path

Review of the video change:

- Image generation "off" turns off the video a request that names no model
  gets (videomaker, beside drawer), so generate_video says it is off too.
- A video id is put in the vendor's URL with the account's token: its parts
  must be [A-Za-z0-9_-]+ (parseVideoID) and the vendor id is path-escaped, so
  video_grok.x%3Fa=1.1 and %2F answer 404 and ask the vendor nothing.
- The id carries a short mark of the account that started it; after a switch
  the video says it was started with another account instead of the vendor's
  not-found.
- generate_video waits up to ten minutes, and Codex gives a tool a minute:
  magpie-image's Codex entry gets tool_timeout_sec (Goose's timeout) of
  eleven minutes, the user's own value kept.
- grok-imagine-video stops at 720p (the vendor turns 1080p away for it; 1.5
  makes 1080p), so a 1080p size is asked at 720p there.
- A model may be named without its provider (grok-imagine-video).
- "seconds": 6.0 is 6; 6.5 is still refused.
- completed_at is left out: the vendor doesn't say when a video finished,
  and a time made up at each poll changed each time.

Checked against a real SuperGrok account: bare model name, seconds 2.0,
1080p on the base model asked at 720p (the mp4 is 1280x720), 1080p accepted
on 1.5, both malformed ids, no completed_at.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* gateway: TestVideoModelByItsBareName asks its two models in a fixed order

It checked the body of the second request the upstream got, but asked the
two models by ranging over a map, so it failed about one run in seven
(Ubuntu CI). Ask them from a slice.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

* library: an installed magpie-image gets the longer tool timeout on the next sync

magpie-image already ships, so many users have it in Codex and Goose as it was
written before: no tool_timeout_sec in Codex, and the timeout: 300 every Goose
server was given. syncMCP skipped an entry whose command, args and env were
unchanged, so an upgrade left Codex at its one-minute default, and Goose kept
300 as if the user had chosen it.

- mcpFile.behind says an entry lacks the timeout magpie gives the server now:
  Codex's tool_timeout_sec is missing, or Goose's timeout is still exactly the
  300 magpie wrote. syncMCP rewrites such an entry; merged() doesn't keep that
  300 as the user's. A value the user chose (any other number) is left alone.
- Test: an entry as main wrote it is given 660 in both, one the user set stays,
  and a second sync changes nothing. It fails without the change ("changed []").

Also, from the review:
- seconds is validated once in readFilming: a decimal number that is whole and
  at least 1 (hex, inf, nan, underscores, negatives and 0 are refused), and the
  object echoes 6 for 6.0.
- imagemcp: Run's doc comment is above Run again.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 04:59:22 +08:00
..
library: an agent whose folder is a file isn't written, and skills reach 13 more agents with one link in ~/.agents/skills for those that share it (neiko on Discord: with DeepSeek Harness not installed the Library kept failing on "open ~/.dsh/AGENTS.md: not a directory" and ~/.dsh/config.yaml; inaction: the skills list is short of the Agents page, Kimi Code has none). An agent counted as there when its folder path existed or its command was on PATH, never asking whether the path was a folder — a file at ~/.dsh, or another dsh, made DeepSeek Harness look installed. Now an agent whose folder is a file (or under one) isn't detected (agent.Taken; Goose's, Cindy's and Claude Desktop's own checks want a folder too), a Library target leaves out each place a file stands in the way of, one with none left isn't listed, and an agent given no MCP server with none of magpie's isn't read. Skills: Kimi Code, Goose and Cindy get ~/.agents/skills (Kimi's ~/.config/agents/skills when there, as Kimi reads it first; never ~/.kimi/skills, which would hide Claude Code's from it); Command Code, Devin, Hermes, Droid, Cline, Qoder, Qoder CN, Grok, WorkBuddy, Hanako and fx their own skills folder; Kimi, Goose and Grok a project's .agents/skills. The shared folder is filled first, and an agent that reads ~/.agents/skills besides its own (Codex, Gemini CLI, OpenCode, Crush, DeepSeek Harness and those above) gets no second link to a skill already there. Tested with new taken_test.go (neiko's two errors without the change) and agent_skills_test.go (skills folders, written once, a shared skill imported for Kimi), in sandbox HOMEs; library-items and shared-skills 24/24 in Chromium and WebKit; go vet, go build (-tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. Not tried with real Kimi Code, Goose or Cindy.
2026-09-30 14:40:41 +08:00
library: MCP servers, skills and instructions are kept once in magpie and given to any agent from one place, with a market to find and add them (#29). Each agent reads MCP servers and skills from files of its own and in a format of its own, so one server was set up again in Claude Code, Codex, Gemini CLI, OpenCode, Pi, Goose, Cursor, Copilot CLI and Crush. The Library view keeps each once: a server is added (stdio, http or sse, its env and headers) and switched on per agent with its icon, and magpie writes it into each agent's config in that agent's format, leaving what the agent has of its own as it is; a server or skill an agent already has is shown, to bring into the library. A skill is a folder with a SKILL.md, kept in the library from GitHub (owner/repo, or a link to a folder in one; updated from it later) or linked from a folder on this machine, and linked into each agent's skills folder. The instructions every agent reads (CLAUDE.md, AGENTS.md, GEMINI.md…) can be kept as one too. The market offers checked MCP servers first, then the official MCP Registry's, filled in from what the registry says each needs (keys asked for in a form, never guessed), and skills.sh's most installed skills with what each says it is for; each shows its real icon (the vendor's own, else its GitHub owner's), fetched through magpie only for the icons the market or the library gave out, and an added server or skill keeps its icon in the library. What magpie changes in an agent's files is backed up first
2026-09-25 14:11:17 +08:00
images: agents can generate and edit images with a model set in Magpie (让Magpie支持配置图像识别模型以及生图模型, part 2) — the gateway answers /v1/images/generations and /v1/images/edits for any model that draws: an images-API model (gpt-image-1, dall-e, imagen, a relay's) is sent the vendor's own images request (an edit as multipart, image[] per reference); a chat model that answers with images (OpenRouter's Nano Banana and GPT-5 Image, gpt-5-image) is asked with modalities ["image","text"], the size given as an aspect ratio, once per image asked for; Gemini's own image models over generateContent. Either way the answer is the images API's (b64_json with its mime_type, the model's text, usage), recorded in usage like any request. The model is Settings → Images → Image generation: Automatic (a model that draws among the providers set up, from the catalog's image-output models), Off, or any model; a request that names none is drawn by it, and with it Off is refused saying where to set one. Subscriptions draw nothing yet. magpie mcp image is a stdio MCP server with one tool, generate_image (prompt, size, n, path, reference_images): it asks the agent for its roots, saves each image in the project (assets/ by default, a name from the prompt, never over a file, the extension of what came back — a JPEG asked for as hero.png is hero.jpg), and says where; reference images are read from the project and sent as an edit. Its requests carry the agent's own name (claude-code/… magpie-image/1) so usage says which agent drew. Library → MCP servers → Discover has it as Magpie Image, opt-in: no agent is given it until picked, since every image costs what the model charges. Checked in a sandbox HOME against real vendors: OpenRouter's gemini-3.1-flash-lite-image drew a 3:2 magpie over MCP as Claude Code and edited it from the saved file as Codex (usage: claude, codex), AIHubMix's gpt-image-1 answered /v1/images/generations with a 1024² PNG; the Settings row and picker in light and dark, the Library card and its opt-in sheet
2026-09-29 01:52:53 +08:00
library: an agent's own copy of a library skill gives way to it, and one that differs is settled from the warning (StringKe, JasonLeeForOnly on Discord: after Bring in all, "Claude Code already has a skill of its own called impeccable", 这里没有强制覆盖的能力) — a skill is brought in from the agent with the very folder and given to the agents that had that folder; another agent's copy (CC Switch copies a skill into each agent) was listed as "differs in" and left out, and giving the skill to it, or a copy put back into an agent after its folder became magpie's link (by CC Switch or whatever installed it), was a hard failure with no way out. A folder there holding the same files as the library's (bytes compared; .DS_Store, .git and magpie's copy mark aside) is now set aside into backups/<when>/<agent>/skills and the library's linked in its place; a skill brought in takes the agents with such a copy too, which are no longer said to differ; a move that copied it all but couldn't remove the folder brings it in all the same, what was left set aside. One that differs keeps the warning, now in the reader's language with "Use the library's" (the agent's set aside, the library's linked) and "Keep <agent>'s" (the agent, and any reading the same folder, taken off the skill) on its row — skills/use-library and skills/keep-own, magpie library skill use-library|keep-own <name> <agent>, which the CLI suggests under the problem. Backups holding a skill set aside are never pruned. TestOwnSkillInTheWay, TestSameTree, TestPruneKeepsSkillsSetAside and own-skill.test.cjs (Chromium, WebKit, en/zh) fail without the change; TestSharedAgentsSkills now expects the byte copy to be the library's. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; own-skill, import-all-skills, library-items, shared-skills, market-have, click-scroll, old-webkit pass.
2026-09-30 19:42:43 +08:00
library: an agent whose folder is a file isn't written, and skills reach 13 more agents with one link in ~/.agents/skills for those that share it (neiko on Discord: with DeepSeek Harness not installed the Library kept failing on "open ~/.dsh/AGENTS.md: not a directory" and ~/.dsh/config.yaml; inaction: the skills list is short of the Agents page, Kimi Code has none). An agent counted as there when its folder path existed or its command was on PATH, never asking whether the path was a folder — a file at ~/.dsh, or another dsh, made DeepSeek Harness look installed. Now an agent whose folder is a file (or under one) isn't detected (agent.Taken; Goose's, Cindy's and Claude Desktop's own checks want a folder too), a Library target leaves out each place a file stands in the way of, one with none left isn't listed, and an agent given no MCP server with none of magpie's isn't read. Skills: Kimi Code, Goose and Cindy get ~/.agents/skills (Kimi's ~/.config/agents/skills when there, as Kimi reads it first; never ~/.kimi/skills, which would hide Claude Code's from it); Command Code, Devin, Hermes, Droid, Cline, Qoder, Qoder CN, Grok, WorkBuddy, Hanako and fx their own skills folder; Kimi, Goose and Grok a project's .agents/skills. The shared folder is filled first, and an agent that reads ~/.agents/skills besides its own (Codex, Gemini CLI, OpenCode, Crush, DeepSeek Harness and those above) gets no second link to a skill already there. Tested with new taken_test.go (neiko's two errors without the change) and agent_skills_test.go (skills folders, written once, a shared skill imported for Kimi), in sandbox HOMEs; library-items and shared-skills 24/24 in Chromium and WebKit; go vet, go build (-tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. Not tried with real Kimi Code, Goose or Cindy.
2026-09-30 14:40:41 +08:00
library: an agent's own copy of a library skill gives way to it, and one that differs is settled from the warning (StringKe, JasonLeeForOnly on Discord: after Bring in all, "Claude Code already has a skill of its own called impeccable", 这里没有强制覆盖的能力) — a skill is brought in from the agent with the very folder and given to the agents that had that folder; another agent's copy (CC Switch copies a skill into each agent) was listed as "differs in" and left out, and giving the skill to it, or a copy put back into an agent after its folder became magpie's link (by CC Switch or whatever installed it), was a hard failure with no way out. A folder there holding the same files as the library's (bytes compared; .DS_Store, .git and magpie's copy mark aside) is now set aside into backups/<when>/<agent>/skills and the library's linked in its place; a skill brought in takes the agents with such a copy too, which are no longer said to differ; a move that copied it all but couldn't remove the folder brings it in all the same, what was left set aside. One that differs keeps the warning, now in the reader's language with "Use the library's" (the agent's set aside, the library's linked) and "Keep <agent>'s" (the agent, and any reading the same folder, taken off the skill) on its row — skills/use-library and skills/keep-own, magpie library skill use-library|keep-own <name> <agent>, which the CLI suggests under the problem. Backups holding a skill set aside are never pruned. TestOwnSkillInTheWay, TestSameTree, TestPruneKeepsSkillsSetAside and own-skill.test.cjs (Chromium, WebKit, en/zh) fail without the change; TestSharedAgentsSkills now expects the byte copy to be the library's. go vet, go build -tags nogui (darwin, GOOS=linux), GOOS=windows go build, go test -tags nogui ./... pass; own-skill, import-all-skills, library-items, shared-skills, market-have, click-scroll, old-webkit pass.
2026-09-30 19:42:43 +08:00
library: an agent whose folder is a file isn't written, and skills reach 13 more agents with one link in ~/.agents/skills for those that share it (neiko on Discord: with DeepSeek Harness not installed the Library kept failing on "open ~/.dsh/AGENTS.md: not a directory" and ~/.dsh/config.yaml; inaction: the skills list is short of the Agents page, Kimi Code has none). An agent counted as there when its folder path existed or its command was on PATH, never asking whether the path was a folder — a file at ~/.dsh, or another dsh, made DeepSeek Harness look installed. Now an agent whose folder is a file (or under one) isn't detected (agent.Taken; Goose's, Cindy's and Claude Desktop's own checks want a folder too), a Library target leaves out each place a file stands in the way of, one with none left isn't listed, and an agent given no MCP server with none of magpie's isn't read. Skills: Kimi Code, Goose and Cindy get ~/.agents/skills (Kimi's ~/.config/agents/skills when there, as Kimi reads it first; never ~/.kimi/skills, which would hide Claude Code's from it); Command Code, Devin, Hermes, Droid, Cline, Qoder, Qoder CN, Grok, WorkBuddy, Hanako and fx their own skills folder; Kimi, Goose and Grok a project's .agents/skills. The shared folder is filled first, and an agent that reads ~/.agents/skills besides its own (Codex, Gemini CLI, OpenCode, Crush, DeepSeek Harness and those above) gets no second link to a skill already there. Tested with new taken_test.go (neiko's two errors without the change) and agent_skills_test.go (skills folders, written once, a shared skill imported for Kimi), in sandbox HOMEs; library-items and shared-skills 24/24 in Chromium and WebKit; go vet, go build (-tags nogui, GOOS=linux, GOOS=windows), go test -tags nogui ./... pass. Not tried with real Kimi Code, Goose or Cindy.
2026-09-30 14:40:41 +08:00