📑 目录(点击展开 / 收起)dsh-openmaic 使用说明书目录一、这个项目是什么二、它能帮你做什么(30 秒速览)三、整体架构:它是怎么工作的四、四个工具(Tools)详解五、四个技能(Skills)详解六、安装与配置七、安全性:沙箱是怎么保护你的八、代码结构导读九、开发与测试十、已知限制与规划十一、常见问题 FAQ

dsh-openmaic 使用说明书

把 OpenMAIC 带进 DeepSeek Harness —— 一个让 AI 助手能 "上课、出幻灯片、做互动小游戏、随手画教学卡片" 的插件。


目录

  1. 这个项目是什么

  2. 它能帮你做什么(30 秒速览)

  3. 整体架构:它是怎么工作的

  4. 四个工具(Tools)详解

  5. 四个技能(Skills)详解

  6. 安装与配置

  7. 安全性:沙箱是怎么保护你的

  8. 代码结构导读

  9. 开发与测试

  10. 已知限制与规划

  11. 常见问题 FAQ


一、这个项目是什么

一句话概括

dsh-openmaic(全名 @openmaic/dsh-openmaic,当前版本 0.4.0)是一个 DeepSeek Harness(简称 dsh)插件。它把清华开源项目 OpenMAIC(AI 智能课堂平台,线上服务在 open.maic.chat)的能力接进了 dsh 这个 AI 智能体框架里,让 AI 助手不再只会 "打字回复",还能直接生成课堂、渲染幻灯片、制作可交互的教学组件、画出教学卡片

打个比方

项目基本信息

项目 内容
包名 @openmaic/dsh-openmaic
版本 0.4.0
许可证 MIT
入口文件 lib/index.js(编译产物,随插件分发)
源码位置 src/(TypeScript 编写)
技术底座 DeepSeek Harness(dsh)+ Cordis 插件框架
官方安装源 git+https://github.com/THU-MAIC/dsh-openmaic.git

设计理念(一句话)

"所有能力都是插件" —— 这是 dsh 的核心哲学。本插件把 "生成课堂、渲染幻灯片、渲染互动组件、渲染教学卡片、苏格拉底式教学" 这五件事,全部以 ** 工具(Tool)+ 技能(Skill)+ 界面组件(Toolview)** 的形式贡献给 dsh,即插即用、互不干扰。


二、它能帮你做什么(30 秒速览)

装上这个插件后,AI 助手会获得 4 个工具4 个技能

4 个工具(AI 可以自动调用的 "动作")

工具名 干什么 典型用法
openmaic_generate 把一个教学需求提交给 open.maic.chat,异步生成一整套可播放的在线课堂,返回课堂链接 用户:"帮我做一节量子物理入门课"
openmaic_render 把 AI 手写的一小段内联 HTML(概念卡、小测验、步骤讲解)渲染成聊天框里的沙箱卡片 用户:"用卡片解释一下什么是光合作用"
openmaic_widget 把 AI 手写的完整交互组件 HTML(模拟器 / 小游戏 / 代码练习)渲染成可交互的沙箱卡片 用户:"做一个抛体运动模拟器"
openmaic_slide 把 AI 写的 OpenMAIC 幻灯片 JSON(PPT 风格的页面)渲染成一页幻灯片 用户:"把这几个要点做成一张幻灯片"

4 个技能(给 AI 的 "写作规范手册")

技能名 作用
openmaic-render 教 AI 怎么写 "教学卡片" 的 HTML 片段(格式、尺寸、样式类、范例)
openmaic-widget 教 AI 怎么写 "互动组件" 的完整 HTML(带 3 种模板:模拟器 / 游戏 / 代码)
openmaic-slide 教 AI 怎么写 "幻灯片" 的 JSON(画布规格、元素类型、排版规则)
openmaic-teach 把一次对话变成苏格拉底式教学:一步步引导提问,配合上面工具做教学辅助

简单记忆:

工具 = AI 的 "手"(做什么)

技能 = AI 的 "说明书"(怎么做、按什么规范做)

。AI 在第一次调用某个工具前,会先读取对应的技能规范。

一个完整的体验示例

用户:帮我做一节量子物理入门课

AI  → 调用 openmaic_generate(requirement="量子物理入门课", language="zh-CN")

     ← 得到: Classroom ID: class-abc123

            Classroom URL: https://open.maic.chat/classroom/class-abc123

AI  → 展示给用户: 课堂已经生成好了,点开就能上课:

            https://open.maic.chat/classroom/class-abc123

用户:做一个抛体运动模拟器

AI  → 按 openmaic-widget 模板边写边流式输出完整 HTML

     → 调用 openmaic_widget(html="<!doctype html>…", widgetType="simulation", title="抛体运动")

     → 聊天框里就地出现一个可拖动、可交互的抛体运动模拟器

三、整体架构:它是怎么工作的

这个插件在 dsh 里分成两个 "半边"工作,再加上一段共享契约一个外部服务

┌─────────────────────────────────────────────────────────────────┐

│                    DeepSeek Harness(dsh)                        │

│                                                                   │

│  ┌──────────────────────┐          ┌───────────────────────────┐ │

│  │   Node 端(服务端半边)  │          │   浏览器端(UI 半边)        │ │

│  │                      │          │                           │ │

│  │ 注册 4 个工具          │  ──────► │  OpenmaicCard(教学卡片)    │ │

│  │ 注册 4 个技能(资产目录)  │  meta   │  WidgetCard(互动组件)      │ │

│  │ 注入 4 段系统提示       │  传递    │  SlideCard(幻灯片)        │ │

│  │ openmaic_generate     │          │  StreamingWidgetPreview  │ │

│  │ 的 API 客户端          │          │  (写代码时实时预览)        │ │

│  └──────────────────────┘          └───────────────────────────┘ │

│          │   ▲                                    │              │

│          │   │ 轮询作业                            │ 沙箱 iframe    │

│          ▼   │                                    ▼              │

│  ┌──────────────────────┐          ┌───────────────────────────┐ │

│  │  共享契约模块(纯函数)   │          │  沙箱渲染(iframe+CSP)      │ │

│  │ fragment/slide-meta/ │          │  只有内联脚本+白名单 CDN     │ │

│  │ widget-meta          │          │  不联网、不访问宿主页面       │ │

│  └──────────────────────┘          └───────────────────────────┘ │

└─────────────────────┬─────────────────────────────────────────────┘

                      │ HTTP(生成课堂)

                      ▼

          ┌─────────────────────────┐

          │   OpenMAIC 服务          │

          │  open.maic.chat          │

          │  (异步生成可播放的课堂)    │

          └─────────────────────────┘

各部件分工

部件 位置 职责
Node 端 src/index.tssrc/tool.tssrc/widget.tssrc/slide.tssrc/client.tssrc/skill.ts 跑在 dsh 的 Node 进程里,负责注册工具、注册技能、注入系统提示、发起 HTTP 请求(课堂生成)
浏览器端 src/client/* 跑在网页 UI 里,负责把工具返回的内容渲染成漂亮的交互卡片
共享契约模块 src/fragment.tssrc/slide-meta.tssrc/widget-meta.ts 纯函数、不碰 I/O 和 DOM,Node 端、浏览器端、测试三方共用同一套校验逻辑
OpenMAIC 服务 外部(open.maic.chat) 只有 openmaic_generate 会调用它;其余三个工具都在本地渲染,不上传任何内容

一次调用的完整生命周期(以 openmaic_render 为例)

  1. 用户在对话框提出需求 → AI 判断适合用教学卡片。

  2. AI 先加载 openmaic-render 技能,拿到 "怎么写片段" 的规范。

  3. AI 按规范写好一小段内联 HTML,调用 openmaic_render 工具,把 fragment 作为参数传入。

  4. Node 端校验片段(非空、≤256KB、不得包含文档骨架标签)。

  5. 校验通过后,Node 端把片段写入持久化的 tool/result meta,返回一行简短确认文字给 AI(避免把大段 HTML 再喂回上下文浪费 token)。

  6. 浏览器端监听到该工具的调用,用 OpenmaicCard 组件把 meta 里的片段包进沙箱 iframe,在聊天框就地渲染成卡片。

  7. 因为内容来自持久化 meta,回放历史对话时卡片能一模一样地重现(replay-stable)。

openmaic_widget

/

openmaic_slide

的过程类似,只是渲染的组件不同。


四、四个工具(Tools)详解

4.1 openmaic_generate —— 生成整套在线课堂

把教学需求变成一整套可点开上课的 AI 课堂(含讲解、互动、测验的网页)。这是唯一一个调用外部服务(open.maic.chat)的工具。

参数:

参数 必填 类型 说明
requirement string 要教什么,自然语言描述,如 "量子物理入门课"
language enum 生成课堂的语言:zh-CNen-US
enableWebSearch boolean 是否允许生成管线联网搜索最新资料
enableImageGeneration boolean 是否生成配图
enableVideoGeneration boolean 是否生成视频
enableTTS boolean 是否启用课堂 Agent 的语音朗读
agentMode enum 生成模式:defaultgenerate

工作流程(异步作业 + 轮询):

  1. 如果配置了 accessCode(邀请码):先 POST /api/access-code/verify 验证,把返回的 openmaic_access Cookie 记下来,后续请求带上。

  2. POST /api/generate-classroom,提交需求(只提交用户确实要求的可选开关),得到 jobIdpollUrl

  3. pollIntervalMs 间隔轮询 pollUrl,直到:

返回给 AI 的格式:

Classroom ID: class-abc123

Classroom URL:

https://open.maic.chat/classroom/class-abc123

注意事项:


4.2 openmaic_render —— 渲染教学卡片

把 AI 手写的一小段内联 HTML 片段渲染成聊天框里的卡片。适合:概念讲解、小测验、算法 / 多步过程逐步讲解、简易图示。

参数:

参数 必填 类型 说明
fragment string 内联 HTML 片段(只能有标签 + <style> + 可选 <script>禁止 <!doctype>/<html>/<head>/<body>
title string 卡片标题,默认 "OpenMAIC 课堂"

校验规则(写错会被工具报错拒绝):

写作要点(技能会教 AI):


4.3 openmaic_widget —— 渲染互动组件

把 AI 手写的完整 HTML 文档(模拟器 / 小游戏 / 代码练习)渲染成沙箱卡片。这是三种里最 "重"、最 "好玩" 的一个。

参数:

参数 必填 类型 说明
html string 完整 HTML 文档(<!doctype html></html>
widgetType enum simulation(模拟器,默认)/ game(游戏)/ code(代码练习)
title string 组件标题,默认 "OpenMAIC 课堂"

三种组件类型:

类型 用途 对应模板
simulation 可交互画布:物理、系统、过程模拟 assets/widget-templates/simulation.md
game 带计分 / 成就的小游戏(物理动作类、拖拽拼图、卡片配对等) assets/widget-templates/game.md
code 可运行的代码练习(Python/JS/TS,带测试用例) assets/widget-templates/code.md

特色功能:


4.4 openmaic_slide —— 渲染幻灯片

把 AI 写的 OpenMAIC 幻灯片 JSON(PPT 风格的单页)渲染成一页幻灯片。支持文本、图形、连线、图片、表格、图表、公式(LaTeX)、代码等元素。

参数:

参数 必填 类型 说明
slide object 幻灯片 JSON:必须有非空 elements 数组,background 可选
title string 标题,默认 "OpenMAIC 幻灯片"

工具替你做的事:

元素类型一览(来自 slide 生成契约):

类型 作用
text 文本(HTML 内容),高度必须查官方 "高度速查表"
shape 矩形 / 圆形等矢量图形(SVG path)
line 直线 / 箭头 / 折线 / 曲线(注意 width线宽不是长度)
image 图片
table 表格(单元格文本是纯文本,不支持 LaTeX)
chart 图表(bar/column/line/pie/ring/area/radar/scatter)
latex LaTeX 公式(KaTeX 渲染,自动按比例缩放)
code 代码块

排版规则要点(契约里非常详细):


五、四个技能(Skills)详解

技能是打包进插件的(bundled),模型可调用、用户也可调用。它们的正文存放在 assets/ 目录。

5.1 openmaic-render —— 教学卡片写作规范

5.2 openmaic-widget —— 互动组件写作规范

  1. 输出恰好一个完整 HTML 文档(<!doctype html></html>),不许套 markdown 代码块;

  2. 嵌入 <script type="application/json" id="widget-config"> 描述组件;

  3. 必须包含 postMessage 监听器(SET_WIDGET_STATE / HIGHLIGHT_ELEMENT / ANNOTATE_ELEMENT / REVEAL_ELEMENT),方便将来 "教学代理" 驱动组件;

  4. 元素命名规范:{变量}-slider{动作}-btn{变量}-display

  5. 移动端适配、触控目标 ≥ 44px、有明确的运行 / 结束状态。

三个模板(

simulation.md

/

game.md

/

code.md

)非常详尽,包含了大量 "常见坑": 重置按钮必须真的重置所有状态; 模拟器必须有

肉眼可见的动画

(不是只变个数字); 游戏

不能开局就失败

(前 3-5 秒安全期 + 合理初值); 代码练习用 Pyodide 时,必须

import sys

import io

才能捕获输出,且用

runPythonAsync

; 游戏开始按钮用

内联 onclick

(比 addEventListener 可靠); 不要用 Tailwind CDN 的

@layer utilities

(可能编译失败)。

5.3 openmaic-slide —— 幻灯片写作规范

5.4 openmaic-teach —— 苏格拉底式教学

把当前会话变成 "引导式教学":

  1. 摸底:先问用户对这个主题已了解多少,据此调整起点;

  2. 切块:把主题拆成 3-6 个小步骤;

  3. 每步循环:先提问 → 等用户尝试 → 卡住就给提示 / 更小的子问题 → 确认或纠正 → 等用户真正接触概念后再用一张视觉辅助 "确认"(而不是 "剧透");

  4. 小测验:一个简短的自判小测验确认理解;

  5. 总结:用用户自己的话复述思路链。

辅助工具的使用原则:


六、安装与配置

6.1 安装

在 dsh 环境里执行:

dsh plugin --profile web add git+https://github.com/THU-MAIC/dsh-openmaic.git

然后重启 dsh web 并刷新页面。

插件

**自带编译好的 **

lib/

** 目录**

,所以通过 git 安装

不需要再构建

,装上就能用。

6.2 配置项

dsh-openmaic:

  baseUrl: https://open.maic.chat

  accessCode: ""     # 邀请码;线上暂未强制,留空即可

  pollIntervalMs: 5000

  maxWaitMs: 600000
配置项 默认值 说明
baseUrl https://open.maic.chat OpenMAIC API 地址。想对接本地 OpenMAIC 实例可改成 http://localhost:3000
accessCode "" open.maic.chat 的邀请码。线上尚未启用,留空;启用后再填
pollIntervalMs 5000 课堂生成作业的轮询间隔(毫秒)。生成很慢,建议调到 60000
maxWaitMs 600000 单个作业最长等待时间(毫秒),默认 10 分钟

七、安全性:沙箱是怎么保护你的

所有由 AI 生成的内容(卡片、组件、幻灯片)都在受限的沙箱里渲染,这是本插件最看重的设计之一:

沙箱层级

  1. <iframe sandbox="allow-scripts">:只允许脚本运行;iframe 是 opaque origin(与宿主页面完全隔离),里面的脚本无法访问 dsh 页面本身。

  2. 自带的 CSP(内容安全策略):每个卡片文档都带一个强 CSP:

  1. 主题桥接只读:宿主把配色设计 token 以 CSS 变量形式传入 iframe,不回传任何数据

效果

即使 AI 生成的 HTML 里夹带了恶意脚本(例如想偷数据、弹窗、跳转),在沙箱里也:

一句话:AI 可以随便写,但只能在自己的 "小黑屋" 里跑。


八、代码结构导读

dsh-openmaic-main/

├── package.json              # 包定义:入口、导出、依赖、工具/技能清单

├── dsh.plugin.json           # dsh 插件清单(工具 + 技能列表)

├── cordis.patch.yml          # 构建时把插件插入 dsh 配置层的补丁

├── tsdown.config.ts          # 双端打包配置(Node 端 + 浏览器端)

├── tsconfig.json             # Node 端 TypeScript 配置

├── tsconfig.client.json      # 浏览器端 TypeScript 配置

├── README.md                 # 英文简介

├── LICENSE                   # MIT 协议

│

├── src/                      # ★ 源码(TypeScript)

│   ├── index.ts              # 插件入口:注册 4 工具 + 4 技能 + 4 段系统提示 + 配置定义

│   ├── client.ts             # openmaic_generate 的 API 客户端(提交作业 + 轮询)

│   ├── tool.ts               # openmaic_render 工具定义

│   ├── widget.ts             # openmaic_widget 工具定义

│   ├── slide.ts              # openmaic_slide 工具定义(画布固定 1280×720)

│   ├── skill.ts              # 4 个 bundled 技能的提供者(从 assets/ 读正文)

│   ├── fragment.ts           # ★ 共享契约:片段校验 + meta 类型(纯函数)

│   ├── slide-meta.ts         # ★ 共享契约:幻灯片 meta

│   ├── widget-meta.ts        # ★ 共享契约:组件 meta + 流式解析

│   └── client/               # ★ 浏览器端(React 组件)

│       ├── index.tsx         # 注册 toolview(卡片/组件/幻灯片)+ 流式预览 dock

│       ├── OpenmaicCard.tsx  # 教学卡片渲染组件

│       ├── WidgetCard.tsx    # 互动组件渲染组件(含展开大窗)

│       ├── SlideCard.tsx     # 幻灯片渲染组件(用 @openmaic/renderer)

│       ├── StreamingWidgetPreview.tsx  # 写代码时的实时预览

│       ├── shell.ts          # 沙箱 iframe 文档 + CSP 组装

│       ├── frame-css.ts      # 卡片内置样式表(card/btn/viz-* 类)

│       ├── theme.ts          # 宿主主题 → 卡片主题桥接

│       └── shiki-stub.ts     # 代码高亮库 shiki 的桩(浏览器里不可用,降级纯文本)

│

├── assets/                   # ★ 技能正文与模板(打包进插件)

│   ├── openmaic-render.md    # render 技能正文

│   ├── openmaic-widget.md    # widget 技能正文

│   ├── openmaic-slide.md     # slide 技能正文

│   ├── openmaic-teach.md     # teach 技能正文

│   ├── slide-template/       # 幻灯片生成契约(system.md + user.md)

│   └── widget-templates/     # 组件模板(simulation / game / code)

│

├── lib/                      # 编译产物(随插件分发,git 安装无需构建)

│   ├── index.js              # Node 端产物

│   ├── client.js             # 浏览器端产物(单文件经典脚本)

│   └── index.d.ts            # 类型声明

│

├── scripts/

│   ├── build.sh              # 构建脚本(链接 dsh 依赖 + tsdown 打包 + 产物校验)

│   └── test.sh               # 测试脚本(链接依赖 + 跑 vitest)

│

└── tests/                    # ★ 测试

    ├── plugin.spec.ts        # 集成测试:真实 Cordis 组合下注册/系统提示/技能

    ├── client.spec.ts        # openmaic_generate 客户端测试

    ├── fragment.spec.ts      # 片段契约测试

    ├── widget.spec.ts        # 组件 meta + 流式解析测试

    └── slide.spec.ts         # 幻灯片 meta 测试

看懂源码的三个 "钥匙"

  1. src/index.ts** 是总开关**:apply() 函数里 ctx.effect(...) 依次注册了工具、技能、系统提示段落。看懂了它就看懂了插件贡献了什么。

  2. "meta 传递" 机制:Node 端把内容写进 tool/result 的 meta,浏览器端从 meta 取内容渲染。内容不通过 "文本流" 回传给模型(省 token),也保证回放一致性

  3. 共享契约模块是纯函数fragment.ts / slide-meta.ts / widget-meta.ts 无 I/O、无 DOM、不引入宿主包的值,所以 Node 端、浏览器端、vitest 都能直接加载 —— 这是构建约束(浏览器 bundle 不能 require 宿主模块)逼出来的优雅设计。


九、开发与测试

前置条件

构建

./scripts/build.sh          # 或 npm run build

脚本做的事:

  1. 定位 harness checkout;

  2. 把 dsh 的宿主依赖软链接进本项目的 node_modules(保证用同一份 vendored 包编译);

  3. tsdown 分别打包:

  1. 产物自检:校验 lib/client.jsrequire() 的模块全在白名单内、没有遗留动态 import()、没有拆分成多个 chunk—— 任何一条不满足就报错退出(因为浏览器加载器只能加载一个经典脚本)。

类型检查

npm run typecheck            # tsc -p tsconfig.json && tsc -p tsconfig.client.json

测试

./scripts/test.sh            # 或 npm test(链接依赖后跑 vitest)

测试覆盖:

常见构建报错与含义

报错 含义
cannot locate the harness checkout 没找到 dsh 源码;设置 DSH_CHECKOUT 或把 dsh 放进 PATH
lib/client.js requires modules the loader module table cannot answer 浏览器端引入了不该引入的 Node 端模块(比如 import 了宿主包的值);把共享逻辑挪进纯模块
kept dynamic imports the browser cannot resolve 浏览器产物里残留动态 import;要内联或用本地 stub 替换
browser bundle split into chunks 打包被拆成多文件;浏览器加载器无法拉取,需要内联

十、已知限制与规划

当前状态

Roadmap(项目计划)


十一、常见问题 FAQ

Q1:装上插件后为什么 AI 会 "突然" 开始做卡片 / 幻灯片?

A:这是正常的。插件给 dsh 注入了 4 段系统提示,教会模型 "什么场景该用哪个工具";模型判断可视化更有帮助时就会自动调用。

Q2:openmaic_generate** 生成课堂要等多久?**

A:异步作业 + 轮询,默认最长等 10 分钟(maxWaitMs),轮询间隔默认 5 秒。官方建议把 pollIntervalMs 调到 60000,更省资源。

Q3:AI 生成的 HTML 安全吗?会不会偷我的数据?

A:渲染在 <iframe sandbox="allow-scripts"> + 强 CSP 的沙箱里,opaque origin、不能联网、不能访问宿主页面,详见第七章

Q4:为什么我的 openmaic_render 调用报 "document-skeleton" 错误?

A:你把 <!doctype> / <html> / <head> / <body> 写进 fragment 了。卡片自己会提供文档骨架,你只需要写正文片段(标签 + 样式 + 可选脚本)。

Q5:组件里的代码为什么没有语法高亮?

A:shiki 在浏览器端插件环境里无法打包,项目用一个 stub 让它降级为纯文本渲染(有代码框、行号、内容,只是没有配色)。这是已知取舍。

Q6:我想对接自己部署的 OpenMAIC,怎么改?

A:把配置 baseUrl 指向你的实例(如 http://localhost:3000)即可,其余流程不变。

Q7:改完源码怎么让改动生效?

A:运行 ./scripts/build.sh 重新打包到 lib/,然后重启 dsh web。注意需要能定位到 harness checkout。

Q8:这个插件能离线使用吗?

A:部分可以。openmaic_render / openmaic_widget / openmaic_slide 全部本地渲染、无需联网(沙箱本身也禁止联网);只有 openmaic_generate 需要访问 open.maic.chat 服务。


本说明书基于项目源码(v0.4.0)整理,涵盖全部 4 个工具、4 个技能、双端架构、安全机制、构建与测试流程。如有疑问,可对照 README.mdsrc/ 源码进一步阅读。