deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
一个运行在 DeepSeek Harness 工作台(DSH Worktable) 上的课件生产工作台: 把课本(.md / .docx / .pdf)快速变成教案,再一键生成 / 导出演示文稿(.pptx)。 全程浏览器端自包含、零第三方 CDN、可离线使用。
项目名:
dsh-worktable-notebook-to-ppt· MIT License · GitHub 仓库 上游依赖:dsh-worktable(DeepSeek Harness 工作台插件)
本项目是一组自定义工作台窗口(4 个 HTML 单文件应用)与配套数据文件。它模拟了一条完整的教学备课流水线:
课本(课本源文 / 本地文件)
│ 窗口2 · 课本预览(打开、提取、预览、生成教案)
▼
lesson-plan.md(教案,可由 AI 生成)
│ 窗口3 · 教案编辑器(采用、编辑、保存、生成 PPT)
▼
ppt-data.json(课件数据,与窗口1/窗口4 共享同一模型)
│ 窗口1 · PPT 编辑器 / 窗口4 · 幻灯片树(编辑、预览、放映)
▼
.pptx(浏览器端生成的真实 PowerPoint 文件,可下载 / 另存)
四个窗口可同时打开、实时联动,数据通过「项目文件夹文件 + localStorage + BroadcastChannel」三条通道同步。
| 文件 | 角色 | 说明 |
|---|---|---|
ppt-source.html |
窗口2 · 课本预览 | 打开/提取/预览课本,生成教案(AI 或本地),写入 lesson-plan.md |
ppt-builder.html |
窗口3 · 教案编辑器 | 编辑教案,接收窗口2 推送,一键生成 PPT(AI 或本地 .pptx) |
ppt-editor.html |
窗口1 · PPT 编辑器 | 所见即所得编辑课件(元素/版式/背景/预览),导出 .pptx |
ppt-slide-tree.html |
窗口4 · PPT 幻灯片树 | 解析/预览课件数据(含从 .pptx 导入),编辑备注、另存 .pptx |
ppt-data.json |
课件数据 | 与窗口1/窗口4 共享的 deck 数据模型(主数据源) |
lesson-plan.md |
教案文件 | 教案主数据:窗口3 保存;窗口2「生成教案」也写入此文件(# 课题 + 元信息行 + Markdown 正文) |
textbook-source.md |
课本文本 | 窗口2 提取的课本文本,供绑定对话的 AI 读取 |
widget-result.json |
窗口注册表 | 声明四个窗口的 id / 文件 / 类型(工作台自定义窗口配置) |
deploy.ps1 |
部署脚本 | 新设备一键部署:安装 dsh-worktable、注册 bundle、对齐路径、校验路由(见 §十) |
package.json / package-lock.json |
空壳 | 纯前端项目,无 npm 依赖 |
ppt-editor.html)所见即所得的课件编辑器,三栏布局:
标题 / 正文 / 项目符号 / 图片 / 矩形 / 分割线,并提供 封面页 / 目录页 / 内容页 / 结束页 四种页模板。画布上支持拖拽移动、四角/边中点缩放、双击进入行内文字编辑;选中元素出现 8 个控制手柄。ppt-source.html)课本的「打开 → 提取 → 预览 → 生成教案」入口:
.md / .txt:内置 Markdown 渲染预览;.docx:内联 fflate(MIT)解压 OOXML,提取正文与表格渲染预览;.pdf:浏览器原生 PDF 渲染;无内嵌 PDF 时用内置解析器提取文本;.doc:旧版二进制格式,给出「另存为 .docx/.pdf」指引。📖 课本预览:大纲 + 预览;✏️ 教案提示词:可编辑发给绑定对话的「生成教案」提示词模板(占位符 {ROOT} {SRC_FILE} {FILE_NAME} {KIND} {WENAN_PATH},localStorage 持久化,可恢复默认)。textbook-source.md,通过工作台全局桥(window.__dshSessions / __dshPromptIntoSession)把任务注入绑定到本项目的对话(不新建会话);AI 完成后把教案写入 lesson-plan.md,窗口3 自动提示「采用」。AI 通道不可用时自动退回本地文本提取并直接写入 lesson-plan.md + localStorage 推送。ppt-builder.html)教案的编辑与「生成 PPT」中枢:
dsh.wt.lessonplan.inbox.v1,每 1.5s 检测,ts 越大越新;lesson-plan.md 内容变化,每 2.5s 比对(窗口2「生成教案」写入同一文件);lesson-plan.md + 系统保存对话框)、导入 .md/.txt、历史版本(localStorage 最多 20 条,记录生成记录)。lesson-plan.md → 注入绑定对话 → AI 依据数据模型生成 deck 写入 ppt-data.json,窗口4 每 1.5s 轮询自动更新;任务模板可在「课件提示词」选项卡编辑(占位符 {PROJECT} {LESSON_FILE} {PPT_DATA_FILE})。封面 → 各节(教学过程 ### 子环节各自成页)→ 谢谢聆听,弹出系统保存框下载 .pptx。ppt-slide-tree.html)课件的结构化检视与最后交付:
ppt-data.json(与窗口1 同一 deck 模型),每 1.5s 轮询文件自动更新;也可「本地打开」导入任意 .pptx 完整解析。分区 → 页面 → 元素 三级树,可全部展开/收起;节点支持新增、复制、删除、移动页、删除/复制元素。ppt-data.json。窗口1 与窗口4 共享同一 deck 结构,也是 AI 生成 PPT 时被要求遵循的模板:
{
"version": 1,
"name": "课件标题",
"source": "lesson-plan.md", // 数据来源
"slideW": 960, "slideH": 540, // 画布尺寸(像素)
"sections": [ { "name": "分区名", "start": 0, "end": 3 } ], // 幻灯片分区
"slides": [
{
"id": "s_xxx",
"name": "第1页标题",
"bg": "#ffffff", // 纯色背景
"bgGrad": { "angle": 45, "radial": false,
"stops": [ { "pos": 0, "color": "#0F172A" }, ... ] }, // 渐变背景(可选)
"notes": "演讲者备注",
"elements": [
{
"id": "e_xxx",
"type": "heading | text | bullets | rect | line | image",
"x": 120, "y": 48, "w": 720, "h": 62, // 位置与尺寸
// 文字类:text、fontSize、bold、italic、underline、color、align、lineHeight
// 形状类:bg、radius、border、borderWidth
// 图片类:src、alt
}
]
}
]
}
| 通道 | 用途 | 说明 |
|---|---|---|
BroadcastChannel: dsh-worktable-ppt-sync |
窗口1 ⇄ 窗口4 实时同步 | 保存成功即广播 deck,收到即采纳(不回环) |
文件 ppt-data.json |
窗口1/4 主数据 + 窗口3 写 | 经 /api/worktable/write 写回项目文件夹;窗口4 每 1.5s 轮询 |
文件 lesson-plan.md |
窗口2 → 窗口3 | 窗口3 每 2.5s 比对内容变化,提示「采用 / 忽略」 |
localStorage dsh.wt.lessonplan.inbox.v1 |
窗口2 → 窗口3 推送 | {"title","subject","grade","period","teacher","body","from","ts"},ts 越大越新,每 1.5s 检测 |
localStorage dsh.worktable.projects.v1 |
项目 → 会话绑定 | 定位绑定到本项目的对话 id,供 AI 任务注入 |
全局桥 window.__dshSessions / __dshPromptIntoSession |
窗口 → 绑定对话 | 注入任务不新建会话,AI 结果写回项目文件后自动被轮询捕获 |
关键约定:AI 任务都不在窗口内等待对话返回,而是「发任务 → 轮询目标文件(lesson-plan.md / ppt-data.json)内容变化」,因此多窗口实时联动。
/api/worktable/template/dshell.css;PPTX 生成/解析(CRC32 + ZIP + OOXML)全部手写;窗口2 仅内联 fflate(MIT)用于 docx 解压。DecompressionStream('deflate-raw') 压缩、手写 ZIP(stored/deflate),产出标准 OOXML(含 [Content_Types].xml、关系文件、主题、母版、版式、备注页),可直接被 PowerPoint / WPS 打开。/api/worktable/write(写项目文件)、/api/worktable/file(读文件)、/api/worktable/fs(列目录);项目目录从挂载 URL /api/worktable/site/<目录>/<文件> 反解——全项目无硬编码绝对路径,随部署目录自适应;未挂载时退化为相对文件名 + localStorage + 下载保存。widget-result.json 打开四个自定义窗口(窗口1/2/3/4)。lesson-plan.md → 点「生成 PPT」。ppt-data.json 的课件 → 预览、微调、编辑演讲者备注 → 「另存为 .pptx」或「导出 .pptx」下载。离线 / 无 AI 时:窗口2 本地提取生成文案 → 窗口3 本地生成 .pptx 下载,流程依然完整可用。
{ROOT} {SRC_FILE} {FILE_NAME} {KIND} {WENAN_PATH}。{PROJECT} {LESSON_FILE} {PPT_DATA_FILE},提示词中要求 AI 严格沿用 ppt-data.json 的 deck 数据模型结构。两者均 localStorage 持久化,可「恢复默认」。
textbook-source.md:研究生课程《PISA 与全球教育改革》小组报告(中英双语)——同学A 开场与总论 / 同学B 积极贡献 / 同学C 批判性分析 / 同学D 总结与展望。lesson-plan.md:第1课《PISA 与全球教育改革:比较工具抑或治理技术?》完整教案(目标 / 重难点 / 准备 / 过程 / 板书 / 作业 / 反思)。ppt-data.json:由教案生成的第1课课件(封面、目录、知识讲解、例题与练习、重难点与小结、作业与结束 共 6 个分区、18 页)。本节是机器可执行的部署 runbook:在另一台 Windows 设备上,AI(或运维)读取 本节 +
deploy.ps1后,即可把本工作台完整装进该设备的 DeepSeek Harness Desktop。
| 验收项 | 检查方式 | 期望结果 |
|---|---|---|
| dsh-worktable 插件在线 | GET http://127.0.0.1:43120/api/worktable/health |
{"plugin":"dsh-worktable","version":"0.2.0","ok":true} |
| 项目文件可访问 | GET /api/worktable/site/<URL编码的项目绝对路径>/ppt-editor.html |
200 text/html |
| 侧栏出现「工作台」 | 打开 Web GUI,左侧栏 | 有「工作台」区块与固定的 🖥️ 控制室卡片 |
| 项目卡片出现 | 侧栏工作台区块 | 本项目卡片可见,可打开 |
| 四窗自动挂载 | 打开项目 | 窗口1-4 分别显示编辑器/课本预览/教案编辑器/幻灯片树 |
https://github.com/Aisland-SJL/dsh-worktable.git(分支 main,插件包根 = 仓库下的 01_content/)。/api/worktable/{health, file, fs, write, mkdir, git, workspaces, site, template} + WebSocket /api/worktable/term。/api/worktable/site/<URL编码的绝对目录>/<相对文件> 把任意项目目录静态托管为站点;本项目 4 个窗口即挂在此路由下。/api/worktable/template/dshell.css 由插件内嵌下发(本项目 4 个窗口引用的正是它)。dsh.worktable.view.v1 / dsh.worktable.projects.v1),
不跨设备同步——所以新设备必须重新注册项目(见 10.6)。widget-result.json,按其清单
{window, path, kind} 把产物锁进对应窗格(kind:html 本地页面 / url 外链 / file 文件)。项目根目录已提供 deploy.ps1:
# 在项目根目录执行(默认把脚本所在目录当作项目文件夹)
powershell -ExecutionPolicy Bypass -File .\deploy.ps1
# 显式指定项目文件夹与 profile(本机复刻版用 -ProfileName worktable;路径支持相对写法,部署时按实际目录填写)
powershell -ExecutionPolicy Bypass -File .\deploy.ps1 -ProjectDir ..\dsh-worktable-notebook-to-ppt -ProfileName web
脚本依次完成:
/api/worktable/health;dsh plugin --profile <p> add "link:<…>\01_content";dsh-worktable 注册进 profile 的 package.json → dsh.profile.bundles;widget-result.json 与 4 个窗口文件;/api/worktable/site/<目录> 反解,随部署目录自适应);/api/worktable/site/<dir>/<每个窗口>.html 均 200;
dsh plugin add会写~/.dsh(需用户授权),且 DSH Desktop 的受保护安装机制要求 重启后健康验证通过才正式提交——所以安装后必须重启 DSH Desktop。
方法 A:CLI link 安装(本机已验证)
git clone https://github.com/Aisland-SJL/dsh-worktable.git # 得到 <clone>\01_content
dsh plugin --profile web add "link:<clone绝对路径>\01_content" # 等价 pnpm add,写 profile
然后编辑 %USERPROFILE%\.dsh\profiles\web\package.json,把 dsh-worktable 加进
dsh.profile.bundles 数组(profile 文件结构见下方示例)。
方法 B:DSH Desktop 内置市场(仅当插件已发布到 npm)
侧栏市场 → 发现/可安装 → 选择 dsh-worktable → 官方 npm 复核 → 确认 → 立即重启。 注意:内置市场只接受精确 npm 包,GitHub 目标会被拒绝;本机以方法 A 的 link 方式为准。
方法 C:复刻本机独立 profile(可选)
本机是把插件装在独立 profile worktable(DSH_DESKTOP_DEFAULT_PROFILE=worktable)。
若想完全复刻,可新建 %USERPROFILE%\.dsh\profiles\worktable\ 并写入:
// %USERPROFILE%\.dsh\profiles\worktable\package.json
{
"name": "dsh-profile-worktable",
"private": true,
"dependencies": { "dsh-worktable": "link:<clone绝对路径>\\01_content" },
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "dsh-worktable"] } }
}
并配 pnpm-workspace.yaml(packages: [.]、nodeLinker: hoisted)与
cordis.patch.yml(- id: dsh-worktable / disabled: false),之后用
dsh --profile worktable 启动,或让 DSH Desktop 以该 profile 为默认。
工作台项目 = dsh.worktable.projects.v1(localStorage)里的一条 layout(决定窗格布局)
方式 1:GUI(最稳)
侧栏「工作台」→ + → 布局预设选 g4(田字格 4 窗) → 项目名 + 项目文件夹(必填,
填实际项目目录) → 保存并打开。打开后客户端 4 秒内自动把 widget-result.json 声明的
4 个窗口挂进窗口1-4(g4 中窗口1/2 = 顶行左右、窗口3/4 = 底行左右)。
方式 2:DevTools 注入(AI 有浏览器控制权时)
在 Web GUI 页面(http://127.0.0.1:43120)按 F12 → Console 粘贴以下片段后刷新。
项目文件夹不做硬编码:若当前页面正挂在 /api/worktable/site/<目录>/… 下会自动反解,
否则弹窗询问(按实际部署目录填写):
const KEY = 'dsh.worktable.projects.v1';
// 项目文件夹:当前页面若正挂在 /api/worktable/site/<目录>/… 下则自动反解;
// 否则弹窗输入本机绝对路径(部署时按实际目录填写,示例不写死任何路径)
const mo = location.pathname.match(/\/api\/worktable\/site\/([^/]+)/);
const PROJECT_FOLDER = (mo ? decodeURIComponent(mo[1]).replace(/[\\/]+$/, '')
: (prompt('请输入项目文件夹的绝对路径(部署时按实际目录填写)') || '').trim());
if (!PROJECT_FOLDER) throw new Error('未提供项目文件夹,注册中止');
const PROJECT_NAME = '课本·教案·PPT';
const SESSION_ID = null; // ← 可选:绑定会话 id(可留空,随后 GUI 绑定)
const mk = (i) => ({ id: 'p' + i, title: '窗口' + i, min: 200, content: null });
const layout = {
id: 'layout-' + Date.now().toString(36), title: PROJECT_NAME,
left: null, top: [mk(1), mk(2)], main: [mk(3), mk(4)], // g4 田字格
leftWidth: { default: 260, min: 160, max: 480 },
chatWidth: { default: 360, min: 240, max: 600 },
topHeight: { default: 200, min: 120, max: 480 }, topHeightRatio: 0.5,
chatSide: 'right', chatFullHeight: true,
};
const prev = (() => { try { return JSON.parse(localStorage.getItem(KEY) || 'null'); } catch (e) { return null; } })() || {};
prev.layouts = [...(prev.layouts || []).filter((l) => l.id !== layout.id), layout];
prev.folders = { ...(prev.folders || {}), [layout.id]: PROJECT_FOLDER };
if (SESSION_ID) prev.bindings = { ...(prev.bindings || {}), [layout.id]: SESSION_ID };
localStorage.setItem(KEY, JSON.stringify(prev));
location.reload();
刷新后侧栏出现项目卡片,打开即可看到四个自动挂载的窗口。
四个窗口的「AI 通道」通过全局桥 window.__dshSessions / __dshPromptIntoSession 向
绑定到本项目的会话注入任务(不新建会话),再从
dsh.worktable.projects.v1.bindings[项目id] 反查会话——必须绑定:
SESSION_ID 填会话 id(即 DSH 会话 id,AI 自身可用
$env:DSH_SESSION_ID 获取)。| 现象 | 处理 |
|---|---|
/api/worktable/health 404 |
插件未加载:检查 profile dsh.profile.bundles 是否含 dsh-worktable,重启 DSH Desktop |
| 侧栏没有「工作台」区块 | bundle 未生效:确认重启的是启动 bundle 的 profile;cordis.patch.yml 中 - id: dsh-worktable / disabled: false |
| 项目打开后窗口空白 | 确认项目文件夹路径正确、widget-result.json 存在且 path 相对于项目文件夹;客户端 4s 轮询会自动重试 |
| 窗口2「生成教案」写到了旧路径 | 窗口2 的 root 优先取 URL ?root=,否则从挂载地址 /api/worktable/site/<目录>/... 自动反解(无硬编码路径);确认窗口是通过工作台站点路由打开的,目录即项目文件夹 |
| 窗口3「生成 PPT」后窗口4 无更新 | 窗口4 每 1.5s 轮询 ppt-data.json;确认窗口3 已写入该文件(AI 通道不可用时用本地生成兜底) |
dsh plugin add 后启动崩溃(rc.2 link 回归) |
见 dsh-worktable 仓库 AGENTS.md「宿主升级事故」:在 link 插件的共同祖先目录建 node_modules junction 解决 |
本机部署形态(仅供参考):插件经 link:C:/Users/12345/dsh-worktable/01_content 装入
独立 profile worktable(bundle:dsh-base + dsh-web-app + dsh-worktable + usage-stats),
dsh.cmd 包装器设置 DSH_DESKTOP_DEFAULT_PROFILE=worktable 与 DSH_HOME 后启动
DSH Desktop.exe。新设备不必照搬——用默认 web profile + 方法 A 即可。
本项目以 MIT License 开源,完整协议见 LICENSE。
lesson-plan.md、textbook-source.md、ppt-data.json、*.pptx)由工作台运行时生成,已加入 .gitignore,不入库。DecompressionStream。CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。