Pular para o conteúdo principal
C

dsh-cture-image

cikian/dsh-cture-image

Geração de imagens compatível com OpenAI nas conversas do DeepSeek Harness: texto para imagem, edição e geração em lote, diretamente na conversa.

Instalar

dsh plugin --profile web add github:cikian/dsh-cture-image

README

Cture Image

Image generation for DeepSeek Harness, without leaving the conversation.

Text-to-image · image editing · batch generation — through any OpenAI-compatible images API, rendered straight into the chat and saved to your workspace.

CI Release License: MIT Node

中文文档 · Changelog · Releases

Example output: an orange cat with glasses writing code, generated by this plugin

Prompt: “一只戴圆框眼镜的橘猫坐在书桌前敲代码…扁平化矢量插画风格” — generated by this plugin (gpt-image-2.5-sunburst, 2K, 16:9, high quality). It reported the real pixel size: 1672×941.


Features

  • Three tasks, one tool — generate (text-to-image), edit (image-to-image and inpainting, with an optional mask) and batch (many prompts in one call, bounded concurrency).
  • Pictures in the conversation — every result comes back as a real image content block backed by a durable attachment, so it displays inline and can be downloaded. The untouched original bytes are written to your workspace as well.
  • Full parameter control — model, quality, resolution tier, aspect ratio, count, save directory and whether to append rendering guidance.
  • Configured in the Plugins page — the bundle ships a settings form with a connectivity test that reports each step (✓ / ✕) before you save. The API key is stored on the host and never sent back to the browser.
  • Agent-drivable — an imagegen_config tool lets the model inspect and change the same configuration from the conversation.
  • A proper DSH bundle — appears under Installed in the Plugins page, can be toggled like any other bundle, and applies to every preset and session.

Requirements

DeepSeek Harness0.2.x (desktop app or dsh web); built against the 0.2 bundle + client-module API
Node.js≥ 20 (only for the development scripts — the plugin itself runs inside DSH)
An image endpointAny OpenAI-compatible images API (POST /images/generations, POST /images/edits) and a key for it

Install

From npm

# Desktop app (profile: desktop)
dsh plugin --profile desktop add @cikian/dsh-cture-image

# CLI web app (profile: web)
dsh plugin --profile web add @cikian/dsh-cture-image

From a release artifact (offline)

Download cikian-dsh-cture-image-1.0.0.tgz from the Releases page, then point the plugin manager at the file:

dsh plugin --profile desktop add .\cikian-dsh-cture-image-1.0.0.tgz

Both routes install the same package. The tarball carries the runtime files only — no API key, and nothing to configure before it runs.

Restart DSH after installing or moving the plugin. The host half mounts immediately, but a bundle's client half (the settings form, the image view) is composed into the page at boot. Installing into a page that is already open is the one situation where the plugin reports running while its UI is missing. See Troubleshooting.

Verify the install: open Plugins → Installed — Cture Image should be listed and switched on. Its detail page then shows the configuration form.

Configure

Open Plugins → Installed → Cture Image. The form is rendered between the description and the plugin's rows.

FieldMeaning
Base URLRoot of the OpenAI-compatible images API. Ships pointing at https://api.cikhub.com/v1; any compatible endpoint works
API keyYour key. Stored on the host, shown back only as ***set***
ModelDefault model; the dropdown is filled from GET /models, and free text is accepted
Qualitylow · medium · high · xhigh · max
Resolution1K · 2K · 4K (expressed as pixel sizes, see compatibility)
Aspect ratio1:1 · 2:3 · 4:3 · 3:4 · 16:9 · 9:16 · 21:9 · 9:21
CountImages per prompt, 1–8
Save directoryWorkspace-relative directory for the originals (default saved-images)
Test connectivityProbes the endpoint with the draft values and reports each step without saving
Test with one imageRenders one cheap 1024×1024 image to prove the model and quota work

Where the configuration lives. In config.json beside the installed package, written atomically. Precedence is config.json → the bundle patch row's config → the built-in defaults in lib/host.js. It is deliberately not part of the published package, so shipping the plugin never ships a key:

<profile>/node_modules/@cikian/dsh-cture-image/config.json

Three ways to change it: the settings form, the agent (imagegen_config action:"set" fields:{…}), or editing that file directly. The API key is never returned to the browser — the form only learns that one is set.

Usage

Talk to the agent; no commands to remember.

画一只戴眼镜的猫,插画风格
把 saved-images/20261014-085102-readme-1.png 的背景换成夜晚
批量出 3 个封面候选

generate_image

actionWhat it does
generate (default)Text-to-image: POST /images/generations
editImage-to-image / inpainting from local files (image_paths, optional mask_path): POST /images/edits as multipart
batchOne call, many prompts (prompts), concurrency from the concurrency setting
ParameterDefaultNotes
prompt—Any language; rendering guidance (ratio, pixels, quality, model strengths) is appended unless optimize_prompt is off
modelgpt-image-2.5-sunburstgpt-image-2.5-flare suits batch sketches and cover candidates; gpt-image-2.5 is general purpose
qualityhighlow · medium · high · xhigh · max
resolution1K1K · 2K · 4K, mapped to pixel sizes that are multiples of 16
aspect_ratio16:98 supported ratios
count11–8 per prompt
save_dirsaved-imagesWorkspace-relative
optimize_prompttrueAppend the rendering guidance to your prompt

Every generated image is (1) written to <workspace>/saved-images/<timestamp>-<slug>-<n>.png as the exact bytes the endpoint returned, (2) attached as a durable attachment and returned as an image content block, and (3) reported in the result with its real pixel size, byte size, attachment id and workspace path.

imagegen_config

actionWhat it does
getShow the effective configuration
setValidate, persist and apply new values (fields: { … })
modelsList the image models the endpoint advertises

Endpoint compatibility

The plugin targets the OpenAI images API, but the details vary between providers and relays. What has been observed in practice, and how the plugin reacts:

  • Pixel sizes, not tier names. Some endpoints ignore size: "1K" and aspect_ratio entirely, so the plugin always sends concrete pixel dimensions (1024x1024, 1536x1024, 1024x1536, …) and expresses the ratio that way.
  • Some providers cap resolution around 1.6 MP and silently scale a large request down (2560×1440 → 1672×941). The tool reports the actual size it received, so a capped result is visible instead of implied.
  • Extreme ratios may be clamped server-side; 21:9 can come back close to 2:1.
  • edit needs an endpoint that accepts multipart uploads at /images/edits. If yours does not, generate still works.
  • Models are whatever your endpoint exposes. The built-in list is a hint, not a constraint — use imagegen_config action:"models" to see the real list.

Architecture

conversation
   │
   ├── generate_image / imagegen_config            (host half · lib/host.js)
   │        └── OpenAI-compatible images API
   │              ├── original bytes ──► <workspace>/saved-images/
   │              └── attachment ─────► image content block (inline + downloadable)
   │
   └── Plugins page: settings form + image view    (client half · lib/client.js)
            └── fetch /api/imagegen/{config,test,models}
                     └── same-origin routes registered by the host half

The client half has no host.call — that builtin belongs to dynamic plugins — so the settings page talks to the host over plain same-origin fetch against routes the host registers via ctx.webServer. Each route answers { ok, value } or { ok: false, error }, so a failure renders as text instead of an empty form.

.
├── package.json          # dsh.bundle.patch + dsh.client: what makes this a bundle
├── cordis.patch.yml      # bundle patch layer: inserts the `tool-imagegen` row
├── lib/
│   ├── index.js          # host entry (re-exports)
│   ├── host.js           # tools, configuration, HTTP routes
│   └── client.js         # image view + settings form
├── locale/               # display name and description (en, zh)
├── tools/                # development and release scripts
└── .github/workflows/    # CI

Development

git clone https://github.com/Cikian/dsh-cture-image.git
cd dsh-cture-image

# Everything that can be checked without a profile: package consistency, the
# client bundle really executed against a module-loader stub, a host smoke run,
# and the configuration routes driven over real HTTP.
node tools/preflight.mjs

# Same checks plus agreement with an installed profile
node tools/preflight.mjs --profile desktop

Two install shapes, and they are not interchangeable:

# Development loop — a junction into the checkout, so edits take effect on restart
node tools/install.mjs --profile desktop

# Release verification — the packed artifact as a real directory: exactly what a
# user receives, at the cost of repacking after every change
node tools/pack-install.mjs --profile desktop
ScriptPurpose
tools/preflight.mjsAll checks, plus profile agreement (install shape, lockfile, stale names)
tools/verify-bundle.mjsPackage consistency, and the client bundle executed for real
tools/smoke-host.mjsRuns the host half against a stub context
tools/check-config-roundtrip.mjsConfiguration read/write against a real file
tools/check-routes.mjsThe settings routes over real HTTP
tools/install.mjs / pack-install.mjsInstall (junction, or the packed artifact)
tools/uninstall.mjsOne-command rollback that never follows a link into your sources
tools/publish-check.mjs / publish.mjsRelease gate (secret scan) and npm publish

Maintainer notes — including how the DSH bundle, client-module and lockfile machinery behave, and the failure modes each guard exists for — are in PUBLISHING.md.

Troubleshooting

The settings form is missing while the plugin says “running”. The page was open before the bundle was mounted; a bundle's client half is composed at boot. Restart DSH.

The whole app fails to boot after a rename. client-modules: duplicate factory registration for "<old name>" means a bundle row from a previous package name is still mounted. The client bundle's __ModuleLoader__.load({ id }) must equal the package name, and any stale row must be removed. node tools/preflight.mjs --profile <name> fails loudly on this.

The settings page shows unavailable: …. The text after the colon is the reason: HTTP 404 means the host routes were not registered (the web carrier had not mounted yet), no API key is configured means exactly that, HTTP 401 means the key was rejected, and anything else is the endpoint's own error.

dsh plugin add fails with ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION. pnpm verifies the publish time of every entry in the profile's lockfile, so one recently published unrelated dependency blocks every install in that profile — this one included. Wait until the flagged entry is older than minimumReleaseAge (24 hours by default) and retry.

Generation fails with a model error. Run the connectivity test in the settings form; it separates a bad base URL, a bad key, a missing model and exhausted quota.

Security

  • The API key lives in config.json beside the installed package and is excluded from the published tarball; tools/publish-check.mjs scans the shipped files for key literals, bearer tokens and absolute local paths before any release.
  • The settings form never receives the key — the host reports only ***set***.
  • Found a problem? Please open an issue rather than posting a key. If a key is ever exposed, rotate it — repository history and chat logs are forever.

Contributing

Issues and pull requests are welcome. Before opening a PR, run node tools/preflight.mjs — CI runs the same checks on Windows and Linux.

License

MIT © 2026 cikian

Plugins relacionados