In a DeepSeek Harness (DSH) session, Agent-generated self-contained HTML usually flows only as a text stream. When explanation, marking, or interaction with the rendered view is needed, a dedicated plane is required. dsh-teaching-board provides this “teaching plane,” projecting the Agent’s HTML into an explainable board interface and allowing users to draw directly on the board and send screenshots back into the dialogue.

Installation and Activation

This is a profile-level bundle. After installing it once, all sessions under that profile gain the stage_* tools and the “teaching plane” tab.

dsh plugin --profile web add @arcaneorion/dsh-teaching-board
# 然后重启 dsh --profile web 并刷新页面

Note: The old package @arcaneorion/dsh-stage-panel@0.1.0 is deprecated. Do not continue using it.

Core Capabilities

The plugin provides the following core features:

  • Board display: Renders panel HTML inside an iframe with sandbox="allow-scripts".
  • Freehand marking: Supports pen, eraser, 4 colors, stroke width adjustment, undo, and clear. In pen mode, click events are not intercepted by default; when clicking controls, the click is forwarded instead of creating a stroke.
  • Built-in screenshot: Clones the document, composites Canvas layers, serializes SVG, and generates a dependency-free PNG.
  • Screenshot interaction:
    • User screenshot: Submits a draft image via inputActions.addAttachments.
    • Agent-initiated screenshot: Triggered by the stage_snapshot tool. The Agent can request to view the current panel snapshot.
  • Status and tools: Provides stage_status / stage_choice status bar tools, as well as the stage_panel board operation tool.
  • Self-contained manual: The plugin ships with skills/stage-panel; after mounting it, no preset needs to install the manual separately.

Board Model

stage_panel is not one call that generates a single image. Instead, a board can be written to multiple times. This is similar to a classroom blackboard: the teacher writes, erases a corner, and then writes again.

Parameter Purpose
board Board id. Consecutive calls with the same id = evolution of the same board; changing the id creates a new board (new topic). Omitting it = one-shot full replacement, without preserving strokes
op open (open board / full rewrite) / append (default, write another segment at the end of the board) / set (replace a specified region) / remove (erase that region)
region Target region name for set / remove operations

Data flow and incremental updates:
The client-side board content is the folded result of calls with the same board id in the session log. There is no private state. append, set, and remove update iframe content in place via postMessage, preserving scroll position, animations, and strokes. The document is rebuilt wholesale only on open or when switching board.

Stroke anchoring:
Stroke coordinates are stored as document coordinates. When scrolling or AI content edits cause reflow, strokes follow the corresponding text block (anchored to .stg-block) and do not stay pinned to the screen and detach as in older versions.

Architecture and Limitations

Sandbox and injection:
The panel iframe has sandbox="allow-scripts" (without allow-same-origin). The parent page cannot directly read the DOM or take screenshots, so annotation and rasterization must be completed inside the iframe. The plugin implements these features by injecting a runtime.

Screenshot limitations:
* Screenshots require the panel to be mounted (conversation.view must be the active tab). Users cannot take screenshots when switching to another tab.
* Screenshots include only the viewport area and are in PNG format. If a single image exceeds about 1.2 MB, it automatically degrades to JPEG.
* External fonts or images are not included in screenshots and are not rendered (the panel specification requires self-contained content).

Use Cases

  • Scenarios where the same “board” content must be maintained across multiple turns of dialogue.
  • Scenarios where users or Agents need to annotate HTML results and provide feedback.
  • Scenarios where the Agent’s stage_snapshot capability is needed to proactively view the current view.