dsh-imagegen
Manifest validImage-generation plugin for dsh: one `imagegen` tool that renders images through any OpenAI-compatible image backend
dsh-imagegen
Image-generation plugin for dsh: one imagegen tool that renders images
through any OpenAI-compatible image backend, so agents can generate images
without per-backend glue. The same tool lists the configured routes, echoes
the declared model lists, and live-probes the backends.
Tool verbs
| verb | network | what it does |
|---|---|---|
generate | yes | Generates the requested images. The tool writes the image files to disk and runs magic-byte checks on them. |
providers | no | Lists the configured routes with their fields, the originating layer of each field, and the credential state. The verb reads the local configuration and makes no network request. |
models | no | Echoes the declared model list of each route from the config layer. The verb makes no network request; the live model listing is the status verb. |
status | yes | Probes each route's GET {baseURL}/models endpoint and reports reachability plus the live model list. |
Key generate behaviors:
- The
promptargument is required, and it is the only required argument. - When the call omits
model, the tool uses the route's single declared model. When a route declares no models, the tool resolves the model by a live/modelsprobe. When the declared or probed model list contains several models, the call fails and lists the candidates. - The tool sends
sizeandnegativePromptverbatim, and only when the call sets them. Theseedargument must be an integer, and the tool sends it only when the call sets it. Thenargument is an integer >= 1 with a default of 1, and a value greater than 1 requests a batch. - When the call sets
out, the output path is that argument (a file path forn = 1, or a directory marked by a trailing separator or by existing on disk). When the call omitsout, the tool writes the files to<process.cwd()>/images/<unixts>_<i>.<ext>. The file extension comes from the image magic bytes (png/jpg/webp). - The tool checks the written bytes for PNG, JPEG, or WebP magic. When the
payload is not a recognized image, the call fails with
code: output, and the tool keeps the file on disk. When the path cannot be written, the call fails the same way. - The generate timeout is 180 s by default, and a
timeoutargument of 1-3600 s overrides it per call. The probe timeout is 10 s.
The plugin ships a dsh-imagegen skill. The skill is the full tool reference
for agent contexts: it carries the parameter table, the env contract, and the
error codes.
Installation
dsh-imagegen is an out-of-tree plugin for a dsh profile. Install it with the dsh plugin command:
dsh plugin --profile <name> add dsh-imagegen
Configuration is layered: built-in defaults, the IMAGEGEN_* env contract, a
cordis patch file, a dsh-imagegen settings section (see below); the plugin
creates no config or state files.
Configuration
Providers are configured in any of four layers, lowest to highest priority;
the providers verb reports the originating layer of every field, so a
shadowed value is never silent:
- the built-in default (
api: openai-compatible), - the
IMAGEGEN_*env contract (static per process boot), - the cordis config layer (a patch entry with id
dsh-imagegenand aconfigobject, or profile-level patches), - the
dsh-imagegen:section in the user settings document ($DSH_HOME/settings.yaml), which the plugin re-reads on every call, so settings edits apply without a restart.
dsh-imagegen:
defaultProvider: local
providers:
local:
baseURL: http://<host>:<port>/v1
hosted:
baseURL: https://api.example.com/v1
apiKeyEnv: IMAGEGEN_HOSTED_KEY
models: [flux-1]
displayName: Hosted Images
The env contract mirrors the config fields 1:1: IMAGEGEN_DEFAULT_PROVIDER,
and per route <NAME> the variables IMAGEGEN_PROVIDER_<NAME>_BASEURL,
IMAGEGEN_PROVIDER_<NAME>_API, IMAGEGEN_PROVIDER_<NAME>_APIKEYENV,
IMAGEGEN_PROVIDER_<NAME>_HEADERS, IMAGEGEN_PROVIDER_<NAME>_MODELS,
IMAGEGEN_PROVIDER_<NAME>_DISPLAYNAME. The <NAME> segment is the route name
uppercased with - written as _. The headers value is a JSON object
string, and the models value is a comma-separated list of model ids. The
baseURL value is the OpenAI-compatible base URL including the /v1 prefix
(the same shape as an LLM provider base URL); the plugin appends
/images/generations and /models to it verbatim, and the image contract has
no server-root endpoints. The apiKeyEnv value is a reference to an
environment variable name, never a secret in config; per request the value
resolves from the process environment, then from
$DSH_HOME/.credentials.yaml.
Examples
// Generate with the default route and its single declared model.
{ "verb": "generate", "prompt": "a lighthouse in fog", "size": "1024x1024" }
// Pick a route and model explicitly, and keep the output name deterministic.
{ "verb": "generate", "provider": "hosted", "model": "flux-1",
"prompt": "an isometric pixel-art garden", "seed": 42, "out": "/tmp/garden.png" }
// Generate a batch into an existing directory.
{ "verb": "generate", "prompt": "three weather variations", "n": 3, "out": "renders/" }
// List what is configured, and where each field comes from.
{ "verb": "providers" }
// List the declared model lists per route (no network).
{ "verb": "models" }
// Probe the backend health (the live /models probe).
{ "verb": "status" }
Troubleshooting
A failing call returns the document { ok: false, error: { code, message, provider?, elapsed_ms } }. The code set is invalid_param / config /
network / timeout / http / protocol / output.
- When a
configerror carries the message "no provider route is configured", no route survived configuration. Check the base URLs; the tool reports each route that configuration drops as a warning in the log. - When a
configerror carries the message "credential missing: environment variable "X" is not set", the credential reference does not resolve. SetXin the environment or add it to$DSH_HOME/.credentials.yaml. - When a
configerror carries the message "unknown provider "x"", the route name matches no configured route. Route names match case-insensitively and treat_and-as the same separator; the error lists the configured names. - When a
configerror carries the message "multiple providers configured (...) and no default is set", pass theproviderargument explicitly, or setIMAGEGEN_DEFAULT_PROVIDER, or set the settingsdefaultProvider. - When an
outputerror carries the message "write failed", the tool could not write to theoutpath. Check the directory and its permissions. - When an
outputerror carries the message "not a recognized image", the backend returned bytes with no PNG, JPEG, or WebP magic. Inspect the kept file; the backend may return an unsupported container.
Build
pnpm install
pnpm run build # tsc -> lib/
pnpm run lint # eslint src/ test/
pnpm run selftest # in-process: HTTP stub + config matrix + magic-byte checks
Comments
Loading…