dsh-ark9canvas
aik358/dsh-ark9canvas
DSH 이미지 생성 워크벤치와 agent 도구입니다. ark9_generate_image 하나로 모든 OpenAI 호환 API에서 text-to-image/image-to-image 지원. 사용자가 연결을 설정하며 endpoint는 포함되지 않습니다(baseURL/key/model 제공 또는 직접 입력). agent 생성은 기본 승인 필수: 플로팅 패널에서 대기하고 승인 전 과금되지 않습니다. agent는 즉시 “awaiting your approval”로 응답하며 결과·거부·시간 초과는 다음 턴에 전달됩니다. 5개 탭, 품질 예산과 16px 정렬을 반영한 비율·크기, 투명 배경, 최대 10장 일괄 생성, host proxy를 거치는 사용자 JSON prompt source, 영구 로그·재시도, 채널별 모델 조회·집계, zh/en UI, 설정 가져오기/내보내기를 제공합니다. dsh-better-sidebar가 있으면 탭 등록, dsh-cua도 있으면 해당 FAB 위에 배치됩니다.
설치
dsh plugin --profile web add github:aik358/dsh-ark9canvasREADME
dsh-ark9canvas — Image Generation Workbench & Agent Tool for DeepSeek Harness
中文 · English · License BSD-3-Clause · pnpm add @a9i5k4/dsh-ark9canvas
v0.4.0 UPDATE — Bilingual UI (Chinese/English, one-tap switch in the panel header and Settings) and a full stroke-SVG icon set replacing emoji, matching the DeepSeek Harness visual language. Evolution roadmap: docs/ROADMAP.md. — The image workbench is now feature-complete against the reference design: aspect-ratio grid with the same quality-budget + 16px-alignment formula, transparent background, batch generation up to 10 images (independent sub-tasks, partial success still returns what finished), a prompt library with custom JSON sources, multi-channel aggregation, persistent generation logs with retry, and config import/export.
An image-generation plugin for the DeepSeek Harness Web GUI: the agent paints on request via one tool, you paint on demand in a floating workbench — and every agent-initiated generation waits for your approval by default, so nothing bills without a human nod.
The problem it solves: image APIs bill per call, yet agent-initiated generation usually runs blind — a bad prompt retries itself, a loop burns your balance. This plugin puts a human gate in the loop: the tool blocks until you approve in the panel (or denies/timeouts with a clear message and zero cost), while the workbench itself stays one click away for your own un-gated use.
Highlights in 30 seconds
| Approval gate by default | Every agent generation waits in the panel's Approvals tab — approve, deny, or let it time out; denial and timeout never bill |
| One workbench, two homes | Floating FAB + glass panel out of the box; auto-registers as a Better Sidebar tab when dsh-better-sidebar is installed; stacks above dsh-cua's FAB when both exist |
| Full size system | Aspect-ratio grid (12 presets + auto) computed with the quality-budget + 16px-alignment formula; manual W×H with 16-multiple snapping; gpt-image models auto-snap to the three native sizes |
| Batch up to 10 | Each image runs as an independent sub-task aggregated into one batch — partial success still returns what finished, with per-batch ok/fail counts |
| Transparent background | One toggle sends background:"transparent" (supported by gpt-image family) |
| Prompt library | Local favorites (☆) + custom JSON sources fetched through a host-side proxy — no CORS, no bundled third-party content |
| Multi-channel aggregation | Keep several OpenAI-compatible relays (baseURL + key + model each), switch the active one, fetch model lists per channel |
| Persistent generation logs | Every batch is recorded with params and outcomes; failed batches retry with one click; multi-select delete |
| Bilingual UI | One-tap Chinese/English switch (panel header + Settings), initialized from your browser language |
| AI-friendly by design | Tool results return saved file paths + dimensions — never base64 blobs — unless you explicitly ask for them; references accept dataURLs or previous output paths for iterative editing |
Feature tour
Approval gate — human in the loop, by default
When the agent calls ark9_generate_image, the request appears in the panel's Approvals tab with the prompt, parameters, and elapsed wait time. Approve → generation starts and bills; Deny → the tool returns a clear "user denied" message and the agent asks what to change instead of retrying; Timeout (configurable, 5–600 s) → cancelled, nothing billed. Set Settings → Ark9 生图 → 安全 to never if you want unattended auto-generation.
Workbench — five tabs
- 生成 Generate: prompt, reference images (upload or clipboard paste), model dropdown with per-channel fetch, aspect-ratio grid / manual W×H, quality, transparent toggle, 1–10 count
- 审批 Approvals: pending agent requests with one-click approve/deny
- 提示词 Prompts: search, click to apply, ☆ to favorite locally; custom JSON sources (
[{title, prompt, tags?}]) proxied through the host to bypass browser CSP/CORS - 记录 Logs: every generation with status pills (成功 / 部分成功 / 失败), retry, multi-select delete, click-to-preview
- 说明 About: quick reference
Size system — faithful to the reference formula
Ratios compute their pixel dimensions from a quality budget (low 1K² / medium 2K² / high 4K²) with 16-pixel alignment, exactly like the reference workbench. Because the gpt-image family only accepts three native sizes (1024×1024, 1536×1024, 1024×1536), gpt-image models automatically snap the computed size to the nearest native one; other models send the raw computed size. Manual W×H with a 16-multiple alignment toggle is always available.
Iterative editing — paths, not blobs
ark9_generate_image returns saved file paths with dimensions. Pass any previous output path back via images and the plugin reads the file and runs an /images/edits multipart call — multi-turn "make the robot red" works without ever stuffing base64 into the conversation. returnDataUrl: true opts into inline base64 when a client truly needs it.
Channels — aggregate your relays
Configure multiple OpenAI-compatible channels (name + baseURL + key + default model), mark one active, fetch each channel's model list from its own /models. The active channel serves both the agent tools and the workbench; single-channel setups from older versions migrate automatically.
Engineering core (restraint by design)
- Zero runtime dependencies beyond Node built-ins
- Batch aggregation: count N → N independent sub-tasks (n:1 each), merged into one batch view with ok/fail counts — one slow image never blocks the others
- Durable state: tasks and logs persist to
~/.dsh/ark9-canvas-*.json; a server restart never orphans a poll - Loopback-only routes: every API route rejects non-localhost callers; file routes are name-sanitized against path traversal
- No third-party prompt content bundled: sources are user-provided URLs
Install (one command)
Prerequisite: install DeepSeek Harness and start
dsh webat least once.
Run in the profile directory (~/.dsh/profiles/web):
cd ~/.dsh/profiles/web
pnpm add @a9i5k4/dsh-ark9canvas
Then edit package.json in that directory and append to the dsh.profile.bundles array:
"@a9i5k4/dsh-ark9canvas"
Restart dsh web — the 🖼️ floating button appears (or a sidebar tab, with Better Sidebar installed). Open Settings → Ark9 生图 once to add a channel (baseURL with /v1, API key, model such as gpt-image-2).
No pnpm?
npm install @a9i5k4/dsh-ark9canvasworks the same. pnpm v11 blocks packages published <1 day ago: setminimumReleaseAge: 0in pnpm-workspace.yaml or pin an explicit version for same-day updates.
AI-era installation
Copy this to the AI assistant you're already using:
Install the npm package @a9i5k4/dsh-ark9canvas in the DeepSeek Harness web profile
directory ~/.dsh/profiles/web (pnpm add or npm install),
append "@a9i5k4/dsh-ark9canvas" to the dsh.profile.bundles array in package.json,
then restart dsh web. After that, open Settings → Ark9 生图 and add an
OpenAI-compatible image channel (baseURL with /v1, API key, model).
Updating
cd ~/.dsh/profiles/web && pnpm up @a9i5k4/dsh-ark9canvas
Configuration
Config file ~/.dsh/ark9-canvas.json (everything adjustable in the Settings GUI):
{
"baseURL": "https://your-relay.example/v1",
"apiKey": "sk-...",
"model": "gpt-image-2",
"quality": "high",
"size": "1536x1024",
"count": 1,
"agentApproval": "always",
"approvalTimeoutSec": 120,
"channels": [
{ "id": "c1", "name": "relay-a", "baseURL": "https://your-relay.example/v1", "apiKey": "sk-...", "model": "gpt-image-2" }
],
"activeChannelId": "c1",
"promptSources": [
{ "id": "ps1", "name": "my prompts", "url": "https://example.com/prompts.json" }
],
"outputDir": ""
}
| Key | Meaning |
|---|---|
agentApproval | always (default) — agent generations need panel approval; never — unattended |
approvalTimeoutSec | 5–600 s; timeout cancels without billing |
channels / activeChannelId | Multi-channel aggregation; falls back to the top-level baseURL/apiKey/model when empty |
outputDir | Where images are saved; empty = ~/Pictures/ark9-canvas |
Tasks persist to ~/.dsh/ark9-canvas-tasks.json, generation logs to ~/.dsh/ark9-canvas-logs.json.
Structure
lib/index.js— Host half: two agent tools, eleven routes, OpenAI-compatible image proxy (async task protocol + batch aggregation), approval queue, persistent logs (zero runtime deps, Node built-ins only)lib/client.js— Browser half: floating FAB + glass workbench (shared vanilla-DOM implementation for floating panel and sidebar tab), settings pagecordis.patch.yml— plugin registration rowdocs/ROADMAP.md— evolution roadmap: DSH-host synergies (AI prompt enhancement, memory-driven styles), cost dashboard, capability registry, mask editingsmoke-test.mjs— offline integration test (tools / routes / approval paths, no API calls)e2e-approval-test.mjs— real end-to-end generation test (bills!)
Known limitations
- Video generation, mask/inpainting painting UI, Gemini-format calls, the infinite-canvas node editor, and WebDAV sync are out of scope (backend has no video model; config import/export stands in for sync).
- The prompt library ships without any third-party content — add your own sources.
- Panel-initiated (manual) generations are never approval-gated: pressing the button is the approval, and it bills.
- Plugin-set changes require a dsh restart.
Credits
This project is built human-machine collaboratively:
- Aik358 — project owner: product direction and engineering.
- ZCode (GLM, Z.ai) — autonomous engineering agent: plugin implementation, protocol reverse-engineering of the async-task/media-upload relay protocol, test suites.
Release
- GitHub: https://github.com/Aik358/dsh-ark9canvas
- npm:
@a9i5k4/dsh-ark9canvas - License: BSD-3-Clause · Independent implementation, contains no WorldCodes Canvas code or branding