dsh-openpencil README

The project's README from github.com/ZSeven-W/dsh-openpencil. As one markdown file: README.md.

DSH OpenPencil

DSH OpenPencil

The DeepSeek Harness plugin for OpenPencil — preview, inspect, and edit real .op documents inside a conversation.
Exact Multi-Frame Previews • Interactive Canvas • Managed Editor • Agent-Native Design Tools

npm: @zseven-w/dsh-openpencil · Current plugin release: 0.1.0-rc.7 · Tested through DSH 0.1.1-rc.2

English · 简体中文 · 繁體中文 · 日本語 · 한국어 · Français · Español · Deutsch · Português · Русский · हिन्दी · Türkçe · ไทย · Tiếng Việt · Bahasa Indonesia

npm CI Stars License Discord


DSH OpenPencil — multi-frame preview and sidebar editor

Exact multi-frame .op previews with an interactive canvas and the managed editor workbench

Why DSH OpenPencil

DSH OpenPencil connects DeepSeek Harness with OpenPencil so an Agent drives a real, editable, interactive design canvas instead of returning a generated image.

🖼️ Exact Multi-Frame Previews

The installed OpenPencil headless exporter renders design-faithful previews: the first top-level frame as a large replay-safe PNG, plus a horizontally scrollable thumbnail rail, click-to-select, and previous/next navigation for multi-frame documents.

🗺️ Interactive Canvas

"Open interactive canvas" lazily mounts the read-only OpenPencil Web SDK with pan, zoom, and fit — inspect any page, nested node, or inactive page without leaving the conversation.

✏️ Managed Editor

With editable: true, the edit action opens the managed OpenPencil editor — selection, layers, properties, drawing tools, undo/redo, and explicit save semantics — in a resizable right-hand workbench with a full-screen option.

🤖 Agent-Native Design Tools

Five direct-canvas tools plus six openpencil_pipeline_* tools let the Agent create, inspect, refine, publish, modify, and read a real canvas through managed OpenPencil runtimes.

🔐 Capability-Gated Grants

Image and document grants are signed, hash-bound capabilities. Browser metadata never exposes an arbitrary host path, and signed preview/editor capabilities never enter the canonical tool result or model context.

⚡ Transactional Safety

A full-pipeline document stays in a private unpublished draft until every native and DSH quality gate passes. Publication never overwrites an existing path, and aborts or failed batches leave no empty target behind.

🌍 Follows DSH Look & Feel

The tool card and managed editor follow DSH's Chinese/English locale and light/dark theme without reloading the editing session.

🎯 One Complete Workflow

"Requirement → private draft → semantic batches → live user previews → deterministic structure/layout/quality validation → exact-PNG-integrity atomic publish" — one complete loop inside DSH.

Install into DSH

DSH is a separate package. Install it once if you do not already have it:

npm install -g @deepseek-ai/dsh@latest

Then add the plugin to a profile and start the web app:

dsh plugin --profile web add @zseven-w/dsh-openpencil@next
dsh web

The plugin is still on a prerelease line, so install it from the npm next tag. The npm latest tag currently points to the older 0.1.0-rc.1 package.

For local development, build the checkout, link its absolute path into the Web profile, and then restart DSH:

pnpm run build
dsh plugin --profile web add link:/absolute/path/to/dsh-openpencil
dsh web

The link: dependency exposes subsequent rebuilds from this checkout, but DSH must be fully restarted after replacing the profile dependency because the shipped Web profile does not hot-reload host bundles by default.

Prefer not to install DSH globally? Run the same two steps through pnpm dlx:

pnpm dlx --package=@deepseek-ai/dsh@latest dsh plugin --profile web add @zseven-w/dsh-openpencil@next
pnpm dlx --package=@deepseek-ai/dsh@latest dsh web

The OpenPencil plugin is public and requires no npm token. If the DSH prerelease itself requires registry authentication, keep that credential in a user-level or temporary npm config outside the checkout. This repository intentionally contains no registry credentials.

Design Tools

Tool What it does
openpencil_new Compatible fast path for simple jobs: runs one transactional QuickJS batch_design script, publishes with create-if-absent semantics, and returns an editable presentation. Prefer the full pipeline below for production design.
openpencil_pipeline_begin Starts an owner-scoped private draft, internally seeds its only root, returns rootNodeId, continuationStyle, and the compact runtime-matched canvas/build contract, then immediately opens the same live draft in the sidebar; the target .op remains unpublished.
openpencil_pipeline_context Loads one bounded guideline, style, theme, or UI-kit detail that is genuinely missing from the begin contract; it is not a startup-context refresh loop.
openpencil_pipeline_batch Runs at most two direct native I(...)/K(...) generation scripts: the bounded first-visible-viewport script returned by begin's next, then one script for every remaining region. Before exposing the second preview, an authored-structure gate rejects empty category/product helpers, atomically restores the first-batch snapshot, and permits one corrected second script without consuming the two-script budget. Each successful transaction attempts an exact user-facing PNG and must be followed immediately, without narration, by its returned next. A third generation script is rejected; only the complete repair gate returned by finish may authorize one bounded U(...) QuickJS repair script.
openpencil_pipeline_inspect Provides manual diagnostics only when the user explicitly requests them; ordinary generation never uses it as a preview or model-inspection step.
openpencil_pipeline_finish In one healthy call, finalizes and validates the document, automatically renders the exact post-final root preview, and atomically publishes with createIfAbsent. One U(...)-only repair and one final finish are authorized only when the result is needs_correction, canContinue: true, and contains a complete non-empty repairTargets array with omitted: 0; every other non-published result is terminal.
openpencil_pipeline_abort Discards the unpublished draft without creating the target file.
openpencil_create Applies a transactional batch_design program to generate or restructure nodes on an existing live canvas.
openpencil_edit Modifies an explicit node or the single node selected by the user.
openpencil_render Creates an immutable, content-addressed .op snapshot and renders every top-level frame on the active page — optional scale and editable.
openpencil_selection Reads the exact nodes selected in the live editor canvas.

Agent Design Workflow

Model tier for design turns

Generation quality tracks the model driving the pipeline turns. The two-batch contract works on fast tiers, but layout judgment, copywriting, and contract adherence improve markedly on a stronger or reasoning-enabled model. For design-heavy profiles, prefer a non-flash tier (for example deepseek-v4 with reasoningEffort enabled over deepseek-v4-flash) in the profile's agent-default-model; keep the fast tier for chat-only profiles where design output is incidental.

Desktop commerce Hero geometry is validated before batch two: every right-side visual child and layered shape must stay inside the fixed Hero inner width and height. An oversized visual is rolled back with the entire first batch instead of inflating the live canvas or reaching final publication. Generation receipts expose only committed node mappings and previews; native diagnostics are deferred to finish so they produce one exact repair transaction instead of a speculative mid-generation loop.

For an ordinary one-line request, call openpencil_pipeline_begin immediately without spending a model step loading the optional skill, then use the fixed fast path: the bounded first direct-JS batch from begin's next → a second and final direct-JS batch containing every remaining region → one openpencil_pipeline_finish. The current first batch renders only the first visible viewport: a complete navigation/header plus a polished primary hero/content selected from the brief, capped at 32 I/K calls and 8 KiB. This budget preserves real structure and visual hierarchy without reopening an unbounded generation loop; secondary cards, detail, and below-fold content wait for the second batch. For commerce, begin now selects the concrete App-aligned ecommerce-modern-light recipe before drawing: a white base with warm-tinted section rhythm, restrained orange actions, 1120px centered content, a 56px Hero display, and visible copy in the language of the user's request (a Chinese request keeps Chinese copy, except for an optional short ASCII brand). A desktop commerce Hero is a full-width horizontal frame with padding:[64,160]; its inner content is copy 512px + gap 64px + product visual 448px, and both headline and subtitle use width:"fill_container". Never combine a fixed 1120px Hero width with that padding. Generic commerce creates the visual directly under Hero as I(hero,{type:"image",name:"Hero product image",width:448,height:360,imageSearchQuery:"gray loveseat isolated photo"}): imageSearchQuery is a direct node field, never an image:{...} object, and the image is neither wrapped nor mixed with decorative shapes or reused by a product card. It is enriched as soon as the first batch commits. An explicit layout:"none" stack of 4–6 positioned layers, including at least one ellipse/path, is allowed only when the user explicitly requests illustration or no photos. Plain stacked rounded rectangles, an empty right field, overflow, or an undersized decorative tile are rejected and atomically rolled back before batch two. Platform and viewport come from the latest direct user request: a model-expanded brief cannot silently turn an unspecified request into a mobile canvas. When the brief provides no brand, immediately use a neutral shop name or short placeholder that fits its context, without comparing naming options. When no logo asset is supplied, use a text-only brand; do not invent a letter badge or give a text node a background, fixed height, or effects. Begin creates the only root and opens the private live canvas immediately. After every successful begin or batch call, make the next required call immediately without narration, planning, comparison, inspection, or any unrelated tool call. A healthy finish runs native finalization first, enriches the canonical image slots, renders the post-final user preview, and publishes in that same call.

The App-aligned commerce preset fixes the 64px Header at padding:[0,160]: the Header is a navbar, its Nav is one nav-links collection of 44px nav-link items, and Header actions are a toolbar of 44×44 icon-button frames rather than bare icons. The 160×48 primary CTA is a button, contains its own label, and uses the AA pair #C2410C/#FFFFFF. All three product cards stay in one coherent collection. For a generic home brief, the exact runtime-validated set is gray armchair isolated photo, artemide tolomeo lamp photo, and potted plant isolated photo; the last card must be labeled as a potted plant rather than a vase.

The begin result is the compact authoritative run contract. Omit path unless the user explicitly named one; the plugin creates the concrete collision-resistant .op filename, avoiding template syntax or a retrying begin/abort loop. Preserve its exact rootNodeId, continuationStyle, canvas, and buildContract, then implement the bounded first script exactly as next specifies without broadening its scope or inserting a user-facing reasoning message. After its automatic preview, write the second and final script for all remaining regions with arrays and loops. This direct two-script flow keeps execution bounded and responsive.

Both generation scripts use direct I(...)/K(...) QuickJS plus begin's exact rootNodeId, continuationStyle, and buildContract. Inside run_code, construct the embedded source with a String.raw tagged template so escapes and intended text newlines reach QuickJS unchanged. Use this exact multiline wrapper:

const draftId = "<exact begin.draftId>";
const script = String.raw`...`;
const r = await tools.openpencil_pipeline_batch({ draftId, script });
return r;

Quote the exact begin.draftId into the standalone draftId string first, then declare script. The fixed tool argument object contains only draftId and script; never append canvasWidth, another field, or return inside it. Return only r without logging, printing, or stringifying it. Each QuickJS batch has a fresh scope: local bindings do not cross batches. I and K return opaque node-id strings, not mutable nodes: use a binding only as a later I/K parent and never assign binding.x, binding.y, or any other member. In batch 2, never recreate Page, App Content, Header, or Hero. Prefer attaching each new bound section rail directly to begin's rootNodeId. If batch 1 created a shared content wrapper, reuse it only through the exact nodeId returned by batch 1; never rebuild another wrapper with the same name.

rootNodeId is already the page frame: attach top-level regions directly, never create another Page/root wrapper. Only frame/group bindings may parent children; round artwork containing an icon uses a frame plus cornerRadius, never an ellipse parent. Every semantic container—Header, Nav, Search, Hero, Card, Section, Toolbar, Button, or CTA—must be assigned from I/K and immediately receive all intended visible children through that binding; never leave it empty or place its intended children as siblings. A minimal valid header is const h=I(root,{type:"frame",name:"Header",layout:"horizontal"}); I(h,{type:"text",content:"Shop",fontFamily:"Inter, system-ui, sans-serif"});. On mobile, only full-width chrome/full-bleed sections attach directly to root; bare text, icons, small controls, and section titles must be inside a bound rail/section with a 24px left/right gutter. Every category card contains a real visual tile plus its label; a mobile category item uses a 56×56 tile frame. Heterogeneous product cards never reuse one glyph as fake product art: use a matching distinct icon/shape or omit that media wrapper. A desktop commerce category rail spans the 1120px content width with justifyContent:"space_between"; its product rail contains exactly three equal fill_container cards with 24px gaps and no unused right tail. Every Button/CTA frame must immediately receive its visible text/icon child through the binding returned when that frame is created, never as a sibling. The minimum icon is {type:'icon_font',name:'Search icon',iconFontName:'search',width:20,height:20}: name is the layer label, while iconFontName selects the glyph and must come from the verified Lucide set, including smartphone/camera for electronics and utensils/sandwich/croissant for food; never substitute lamp for electronics or coffee for food. The broader verified set also includes home, search, shopping-bag, shopping-cart, user, heart, star, plus, arrow-right, sparkles, sun, apple, snowflake, droplet, cookie, leaf, coffee, package, gift, baby, spray-can, lamp, sofa, armchair, shirt, headphones, laptop, monitor, gamepad-2, watch, palette, and cake; compose shapes when none fits. Outside commerce, default to exactly one type:"image" leaf unless the user explicitly requests multiple images. Commerce uses exactly three distinct product images. Every query stays at four English words or fewer, names one concrete product, and never requests a lifestyle, collection, or broad category; generic home uses the exact validated set above. Isolated queries require positive isolated/cutout/white-background metadata rather than merely accepting a photograph. Multi-word queries must match at least two meaningful metadata tokens. Never put a lone small icon inside a large fixed product-media frame. Every Hero/Product/Art/Media frame has exactly one primary visual—one image with a concrete English imageSearchQuery, or one substantial composed-shape visual—never an image plus an icon placeholder; image nodes are leaves, never parents. Every generated text node explicitly uses fontFamily: "Inter, system-ui, sans-serif"; ordinary values are fontSize: 16 and lineHeight: 1.5. Desktop keeps its bundled Inter, while the web host—which deliberately does not bundle Inter—uses the generic fallback without a missing-font prompt. Never use bare Inter. A CJK lineHeight < 1.3 is raised to 1.5, and a numeric text height becomes fit_content unless textGrowth explicitly requests fixed-width-height. Override size and line height only for headings or special typography. The runtime contract remains the single source for every other current node, style, script, and repair rule. A third generation script is rejected. Only the complete repair gate described below may authorize one third and final bounded QuickJS repair script, using U(...) only for the named targets.

Category rails use one distinct matching icon per label. Each <label> icon tile card contains a nested 56×56 Category glyph surface frame, then the icon_font inside that surface and the text label directly under the card; wrapper names must never contain art, media, or image, so nativ

dsh-openpencil (ZSeven-W/dsh-openpencil)

Searching Database…

Что это?DSH OpenPencil — плагин, соединяющий DeepSeek Harness (DSH) с OpenPencil: он позволяет ИИ-агенту управлять настоящим, редактируемым, интерактивным дизайн-холстом, а не просто возвращать сгенерированную картинку.
Это отдельное приложение или плагин к чему-то?Это плагин, а не отдельное приложение — он добавляет дизайн-инструменты OpenPencil и интерфейс холста/редактора в существующий профиль DeepSeek Harness (DSH).
Нужно ли уже настроенный DeepSeek Harness (DSH)?Да, DSH — отдельный пакет, который сначала нужно установить и запустить; этот плагин лишь расширяет существующий профиль DSH дизайн-инструментами OpenPencil.
Он уже достаточно стабилен, чтобы на него полагаться, или всё ещё экспериментальный?Он явно находится на пререлизной npm-ветке (0.1.0-rc.7, тестировался с DSH 0.1.1-rc.2), а локальные сборки для разработки требуют полного перезапуска DSH, поскольку поставляемый Web-профиль не умеет горячо перезагружать хостовые бандлы.
Кто реально будет этим пользоваться?Разработчики, работающие с DeepSeek Harness, которые хотят, чтобы их агент создавал и редактировал настоящие интерактивные дизайн-документы (UI-макеты, презентации, страницы продуктов), а не статичные изображения.
Какие дизайн-инструменты реально получает агент?Пять инструментов прямой работы с холстом (create, edit, render, selection и др.) плюс шесть инструментов «openpencilpipeline», с помощью которых агент может начать приватный черновик, генерировать ограниченными порциями, проверять, завершать/публиковать или прерывать документ.
Что будет, если генерация агента оборвётся на середине?Документ остаётся приватным неопубликованным черновиком, пока не пройдут все проверки качества, а неудавшиеся или прерванные порции откатываются атомарно, так что наполовину опубликованный файл не останется никогда.
Можно ли редактировать документ вручную, а не только через агента?Да — установка editable: true открывает управляемый редактор OpenPencil (выделение, слои, свойства, инструменты рисования, undo/redo) в изменяющей размер рабочей области рядом с чатом.
Зачем живой холст вместо сгенерированного скриншота?Потому что результат — настоящий редактируемый документ .op с интерактивным предпросмотром нескольких кадров (панорамирование, зум, вписать в экран, навигация по миниатюрам), а не статичная картинка, так что и агент, и пользователь могут продолжать его дорабатывать.
Creator
ZSeven-W
Size
6.3 MB
Stars
186
Updated
CommitOct 06
Age
2mo
Commits · 90 Days