deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:houdinicc/dsh-todos
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
dsh-todos)一个 DeepSeek Harness 插件:类 Todoist 的待办管理 + 仪表盘,挂在 DSH Web GUI 的 侧边栏与主面板上,并把待办开放给 Agent(DeepSeek 能直接读写你的待办)。
明天下午3点 交报告 #Q4汇报 @写作 p1shell.overlay 全局浮层,可一键完成 / 推迟到明天todos_list / todos_create / todos_update / todos_complete / todos_delete / todos_stats / todos_projects给别人用:让 TA 打开 设置 → 插件 → 插件市场,搜 dsh-todos(需先装 dshmarket),
或让 TA 的 Agent 执行下面的 install_bundle。分发渠道与发布踩坑记录不在本仓库内。
本机开发安装:用 plugin_manager 工具(或 Web 的 Plugins 页)指向本目录:
plugin_manager install_bundle target=<本目录的绝对路径>
读返回值的 application 与 warnings 判断是否真的生效——不要靠日志或页面 boot payload。
全新安装需要用 cordis_inspect_query(host Config.listConfigs、client Slots.listSubTree)复核。
⚠️ 改包名必须同时改三处,漏一处 DSH 就会加载失败:
package.json的name、 客户端 bundle 自注册的id(lib/client.js里的window.__ModuleLoader__.load({ id }))、 以及 profile 里的依赖与dsh.profile.bundles条目(后两处只能靠卸载再重装更新)。 loader 要求 bundle 的id与条目名完全一致,不一致时报loaded without registering "…" via __ModuleLoader__.load。scripts/preflight.mjs会替你检查前两处,但它不会替你重装。
安装后,本 bundle 的 cordis.patch.yml 会插入插件行 id: todos
(config 里可调 weekGoal / remindEnabled / dailyDigest)。
package.json 清单:dsh.bundle.patch + dsh.client(platform=web) + exports["./client"]
cordis.patch.yml 本 bundle 贡献的配置层(只插入插件行;分发文件,不含本机路径)
icon.svg 插件卡片图标
LICENSE 许可证
locale/{en,zh}.json 插件在 Plugins 页的显示名与描述
lib/index.js 宿主半入口:apply(ctx, config)
lib/store.js 数据层:单文件 JSON 持久化 + 规范化 + 迁移钩子
lib/select.js 派生视图:侧边栏计数、仪表盘统计(纯函数)
lib/quickadd.js 自然语言解析(纯函数,中英双语语法)
lib/actions.js 界面与工具共用的写动作 + Markdown 渲染
lib/tools.js 七个 todos_* Agent 工具(原始 JSON Schema,零 import)
lib/routes.js Web GUI 的 HTTP 路由 + 回环信任围栏
lib/remind.js 到点提醒的判定(纯函数)
lib/client.js 客户端半:手写的 window.__ModuleLoader__ bundle(唯一构建产物)
scripts/preflight.mjs 发布前自检(npm pack/publish 自动跑)
test/ 四套测试,见下
dev/ 开发期可选配置(不随插件分发)
零依赖、零 import。 宿主半不 import 任何 @deepseek-ai/* 包,客户端半只
require('react')(平台冻结模块表里的)。因此这个包没有 dependencies、
没有 peerDependencies、不需要构建工具链,也不会因为 DSH 升级而链接失败。
代价是数据层自己写(store.js),而不是用 ctx.storageDomain。
数据是单个 JSON 文件。 落在 $DSH_HOME/dsh-todos/todos.json,写入是「临时文件 +
rename」的原子替换,读坏时先备份现场再重开。单文件让「整库导出/导入」退化成一次文件拷贝。
提醒不往会话里注入消息。 宿主确实可以 agent.inject() / agent.followup() 把提醒
塞进会话,但那会让模型在没有用户输入的情况下自己发起一轮。改为渲染到官方
shell.overlay 浮层:DSH 开着就能看到,一键完成或推迟,不产生模型开销。
客户端 bundle 是手写的,没有构建步骤。 产物格式是
window.__ModuleLoader__.load({ id, factory }),用 React.createElement 而不是 JSX。
主机端的客户端 HMR 每 500ms 轮询 bundle 的 mtime/ctime/size,所以改
lib/client.js 即时生效、不必重启。
样式只引用真实存在的主题 token——这一条会咬人。 主题包
(@deepseek-ai/dsh-client-ui-theme)只声明 token(400 多个),真实定义在 shell
的样式表里,而 shell 只定义了 95 个。引用一个不存在的 token 不会报错:那条声明
静默失效并回退继承,于是可能得到「浅底浅字」这种完全看不见的按钮(本项目真的踩过)。
所以:
test/theme-tokens.json(从 shell CSS 抽出的真实名单)当唯一依据;test/client-render.mjs 会扫描 lib/client.js 里所有 var(--dsw-*) 引用并逐个比对,
引用不存在的 token 直接让测试失败;--dsw-alias-button-primary-fill + --dsw-alias-label-primary-foreground 就是宿主
主按钮的固定搭配),照抄它的 token 组合最稳。客户端半(lib/client.js)天生是热的:dsh-client-hmr 每 500ms 轮询每个 bundle 的
mtime/ctime/size,改完约 1 秒生效,不用重启、不用刷新。
宿主半(lib/*.js)是 ESM,Node 按 URL 永久缓存模块,而 plugin_manager 的
disable/enable 只重挂 loader 行、不会重新 import —— 所以默认改一行就要重启整个 DSH。
想让宿主半也热起来,把 dev/cordis.patch.dev.yml 那段追加到你自己的 profile 补丁层
($DSH_HOME/profiles/<profile>/cordis.patch.yml)并改成你的检出路径,重启一次即可。
那一段刻意不放在插件自己的 cordis.patch.yml 里:那是要分发给别人的文件,
写死某个人的本机绝对路径没有意义。
改 package.json、改包名、或替换已安装的包,一定需要重启 DSH。
node test/quickadd.mjs # 自然语言解析:26 例
node test/smoke.mjs # 数据层 + 路由处理函数(假 req/res):25 例
node test/tools.mjs # 七个 Agent 工具:19 例
node test/client-render.mjs # jsdom + 真实 React 渲染客户端半:49 例
node scripts/preflight.mjs # 发布前自检(不跑测试,只查分发契约)
前三套零依赖。第四套需要 jsdom 与 React,装在插件包之外的
../dsh-todos-dev/(插件本身保持零依赖):
cd ../dsh-todos-dev && pnpm install
client-render.mjs 会真的把面板渲染进 jsdom、真的点击、断言发出的 HTTP 请求——
「面板点开是空白」这类问题因此能在本地抓到,而不必靠目视。
YYYY-MM-DD;全天任务视为当天 00:00 到期。CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。