dsh-omni-modal
Adds an "Omni-modal settings" section to DeepSeek Harness: configure OpenAI-compatible image / video generation endpoints with switchable config profiles, and exposes generate_image / generate_video / check_video tools to the model. 适合需要配置OpenAI兼容的图像和视频生成端点并让模型直接调用生成工具的用户。
インストール
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:yzhclcl/dsh-omni-modalドキュメント
README 全文を読む ↗Usage
Once installed, just talk to the agent:
- "Draw a strawberry on a pale blue plate." →
generate_image - "Make a short video of a paper boat drifting down a stream." →
generate_video, thencheck_video
Settings page
| Section | Contents |
|---|---|
| Config profiles | Pick the active profile, rename it, add one (copied from the current) / delete one |
| Image | Base URL, API key, model, request path, default size, extra request params |
| Video | Base URL, API key, model, submit path, query path, default resolution, default duration, extra request params |
| Task records | Submitted video tasks with their status and artifact path |
Notes:
-
Saving takes effect immediately for the tools — no restart.
-
The base URL must be the address alone. Documentation examples are easy to copy verbatim as
POST https://api.example.com/v1; the plugin strips a leadingPOST/GET/… automatically, but writing justhttps://api.example.com/v1is safer. -
The query path accepts two forms: a relative path (
/videos/generations/{id}) appended to the base URL, or a full URL (https://api.example.com/agnesapi?video_id={id}&model_name={model}) used as-is. The full form is necessary when the query endpoint does not live under the base URL. -
Placeholders available in the query path:
Placeholder Replaced with {id}the task id returned by the submit call {model}the model name configured in that profile -
The tools always use the active profile unless you pass
profileexplicitly.
Tools
generate_image(prompt, size?, model?, profile?, save_to?)
generate_video(prompt, model?, profile?, size?, seconds?, image_url?)
check_video(task_id, profile?, save_to?)
generate_imagereturns synchronously. The file lands in the plugin data directory'smedia/and, if the attachment service is available, an image attachment is produced so the picture shows up in the conversation. The model itself cannot see the pixels — to actually look at the image, callread_imageon the returned path.generate_videois asynchronous: it returns ataskIdright away. Callcheck_video(task_id)later; when the status becomessucceededthe artifact is downloaded intomedia/automatically.- Passing a non-existent profile is a hard error that lists the available profiles, rather than silently falling back to another one — otherwise the model would quietly use the wrong endpoint and model while the result still claims the profile it asked for.
check_videofailures are soft failures: a missing task (404), an unreachable download URL or a failed download returnstatus: "failed"/"succeeded"plus amessage, instead of throwing. These are expected business outcomes, and throwing would abort the whole tool-calling round.- Video URL extraction covers the common response shapes:
video_url/videoUrl/url, nestedvideo.url,data.*,output.*,result.*,videos[0].url, and more. - Task id extraction prefers
video_id/videoIdoverid/task_id— some services (Agnes, for instance) return an internal id that cannot be used for polling. - 429 (rate limit) / 503 (busy, queue full) responses come back with a "retry in a moment" hint: they are retryable server states, not configuration errors.