dsh-macos-desktop
把 DeepSeek Harness (DSH) 的 Web 界面改造成一个 复古情怀 + 现代 macOS(Big Sur / Sonoma)质感 的桌面系统。它不替换官方界面,而是通过 DSH 官方 shell.overlay 槽位,在官方对话之上叠加一整块桌面:
- 左侧 = macOS 桌面(壁纸 / 图标 / 多窗口系统);
- 右侧 = DSH 原生对话界面(CSS 主题化成 macOS 浅色/深色风,功能全保留);
- 顶部菜单栏横跨全屏(时钟 / 天气 / 迷你日历 / Spotlight),底部 Dock 悬浮(分组 + 运行指示点 + 角标),中间可拖动分隔条。
一句话:把 DSH 装进一台「Mac」——文件、终端、文档、浏览器、知识库、便签、番茄钟、截图、AI 生图、AI 看图,都在同一个窗口系统里完成,同时官方对话能力一个不丢。
为什么做它
- 想让 DSH 用起来像一台「电脑」而不是一个聊天框:桌面图标、窗口、Dock、菜单栏、回收站这些熟悉的心智模型,让文件/终端/文档/对话能同屏协作。
- 官方 UI 功能一个不丢:右侧就是原生对话(实时 mux 流、工具轨迹、token 用量、权限、模型切换),只是被主题化;菜单栏「DSH ▸ 显示原始界面」一键切回,卸载插件后界面原样恢复。
- 纯前端 + 纯 JS 实现,无原生模块、无构建步骤;Windows / macOS / Linux 全兼容。
核心特性速览
| 类别 | 能力 |
|---|---|
| 桌面 | 左右分栏 + 毛玻璃、多窗口、Aero Snap 边缘吸附、Spotlight 搜索(⌘K)、迷你日历、天气、深色模式、开机蓝鲸动画 |
| 文件 | 隔离的 desktop/ 目录、回收站、便签(位置持久化)、拖拽上传、右键菜单(复制路径 / 设为壁纸 / 用 AI) |
| 应用 | 终端(Win powershell/cmd + POSIX PTY)、多标签浏览器、文档办公(docx/pdf/pptx + 富文本)、知识库、计算器、番茄钟 |
| AI | 原生对话、用 AI 看图(modlens)、截图→自动看图→发给 AI、@知识库引用、AI 生图(DashScope 通义万相)、进度条 + Token 组件 |
快速开始
# 安装(发布到 GitHub 后)
dsh plugin --profile web add github:你的用户名/dsh-macos-desktop
# 或本地开发(改代码重启即生效)
dsh plugin --profile web add link:../dsh-macos-desktop
dsh web # 重启后打开 http://127.0.0.1:3080,Ctrl/Cmd+Shift+R 硬刷新
详细安装方式、环境变量、验证步骤、安全边界见下文各节。
0. 这是什么 / 不是什么
是:一个符合 DSH 插件规范的 npm 包(dsh.bundle + dsh.client),宿主半侧跑在 DSH Node 进程里提供文件/终端/文档的 HTTP 面,浏览器半侧画出一整块复古桌面。
不是:不修改 DSH 框架源码;不引入 playwright/puppeteer/原生模块/构建步骤;不另起炉灶重写对话(对话复用官方 session 流)。
1. 前置环境
| 依赖 | 版本 | 说明 |
|---|---|---|
| Node.js | ≥ 22.19.0(本仓库在 v24.19.0 上验证过语法) | DSH 0.1.x 要求 Node 22+ |
| npm | ≥ 9 | 随 Node 附带 |
| pnpm | 任意较新版本 | dsh plugin 实际是转发给 pnpm |
安装 DSH 并启动 Web(首次会自动初始化 web profile):
# 全局安装 DSH 启动器(如已安装可跳过)
npm install -g @deepseek-ai/dsh
# 启动 Web 界面(默认 http://127.0.0.1:3080)
dsh web
# 换端口启动
dsh web --port 8080
说明:
dsh web是dsh --profile web的别名。启动器自己的 flag 要写在最前面;--port属于 web 应用,写在web之后。
2. 插件安装(以本机实际核实的 dsh plugin 子命令为准)
dsh plugin --profile <name> <pnpm 参数> 会在 profile 目录里把后面的参数原样转发给 pnpm,因此子命令就是 pnpm 的子命令。下面用绝对路径 <插件目录> 代指本仓库目录,例如 C:\Users\you\dsh-macos-desktop。
2.1 本地目录(file: 安装,复制)
dsh plugin --profile web add "C:\Users\you\dsh-macos-desktop"
等价于在 profile 里执行 pnpm add <绝对路径>。file: 安装是复制不是链接,之后改代码不会生效,需要 remove 再 add,或干脆重启 DSH。
2.2 tgz 包
# 先在本仓库目录打包(可选,直接 add 目录也行)
npm pack
# 安装 tgz(相对路径会被锚定到你执行命令的目录)
dsh plugin --profile web add ./dsh-macos-desktop-0.1.0.tgz
2.3 GitHub / git 仓库
dsh plugin --profile web add github:你的用户名/dsh-macos-desktop
# 或
dsh plugin --profile web add "git+https://github.com/你的用户名/dsh-macos-desktop.git"
git 托管的插件如果带
prepare构建脚本,pnpm 默认会拦截,按 pnpm 打印的提示在 profile 目录的pnpm-workspace.yaml里加入allowBuilds再重跑。本插件无构建步骤,直接可用。
2.4 link: 链接安装(开发时改代码即生效)
dsh plugin --profile web add link:../dsh-macos-desktop
link: 是软链接,改代码后重启 DSH 即生效(适合调试)。但注意 link 安装不经过 files 字段裁剪。
2.5 更新 / 查看 / 卸载
# 更新
dsh plugin --profile web update dsh-macos-desktop
# 查看已装依赖
dsh plugin --profile web list
# 卸载
dsh plugin --profile web remove dsh-macos-desktop
卸载后再重启 + 硬刷新,官方界面原样恢复。
3. 配置文件逐行解释
3.1 package.json 关键字段
{
"name": "dsh-macos-desktop", // 包名 = 插件 ID = 客户端 bundle id,三处必须一致
"type": "module", // 宿主半侧是 ESM(lib/index.js 用 named export)
"main": "lib/index.js", // 宿主半侧入口
"exports": {
".": { "default": "./lib/index.js" },
"./client": { "default": "./lib/client.js" }, // 浏览器半侧入口(client-modules 从这里读)
"./cordis.patch.yml": "./cordis.patch.yml", // bundle patch 导出
"./package.json": "./package.json"
},
"dsh": {
"bundle": { "patch": "./cordis.patch.yml" }, // 声明这是 bundle,patch 参与宿主组合层
"client": { "platform": "web" } // 声明这是 web 客户端插件,进 __DSH_BOOT__
}
}
关于字段的一点校正:DSH 0.1.x 的
dsh.client没有id字段——插件 ID 就是包名,客户端 bundle 的id也等于包名。字段只有platform(必填,"web")和可选的inject(跨包模块依赖边)、immediately。不要写"client": { "id": "..." },那样既无效还容易和真实包名不一致。
3.2 cordis.patch.yml
# 把本包作为一个宿主平面 row 插入组合:
- insert:
- id: dsh-macos-desktop # row id,与包名一致
name: 'dsh-macos-desktop' # 解析到本包(宿主半侧 lib/index.js)
- 这个 patch 在
dsh-base、dsh-web-app之后、profile 自己的cordis.patch.yml之前叠加。 client-modules的节点半侧会扫描带dsh.client声明的 row,把/plugins/dsh-macos-desktop/client.js注入window.__DSH_BOOT__。- row id 与包名一致是硬要求:客户端 bundle 的
id就是包名,模块表按这个 id 解析/plugins/<id>/client.js。
3.3 宿主半侧 lib/index.js 的注入
export const name = 'dsh-macos-desktop'
export const inject = ['webServer', 'fs', 'subprocess', 'workspaceRegistry'] // 硬依赖(宿主平面服务)
export function apply(ctx) { /* 注册 HTTP 路由 + 终端 + 文档 + 统计 */ }
webServer / fs / subprocess 都是 dsh-base + dsh-web-app 提供的宿主平面服务;sandboxPolicy / tokenMeter / sessions / sessionQuery 用 ctx.get() 可选读取,缺了也能启动(对应功能降级)。shell(bash executor)不再依赖:mkdir/rename/delete 改用跨平台的 node:fs,因为 Windows 上没有 bash,POSIX 的 mkdir -p/mv/rm -rf 走不通。
4. 环境变量
4.1 本插件自身
本插件没有密钥。它复用 DSH 自己的模型与凭据体系(对话走 DSH 官方 session.prompt),所以不需要也不接受任何私钥环境变量。文档、终端、文件都只在授权 workspace 内操作(见 §9 安全边界)。
4.2 DSH 官方环境变量(按需)
| 变量 | 作用 | 取值/默认 |
|---|---|---|
DSH_HOME |
DSH 数据根目录 | 默认 ~/.dsh |
DSH_PERMISSION_MODE |
权限预设(文件/终端操作权限) | workspace-write(默认)/ danger-full-access |
DSH_TOOLS_MODE |
工具呈现模式 | native / code / both,默认 native |
DEEPSEEK_API_KEY |
DeepSeek 模型 API 密钥 | 通过凭据 seam 解析,也可写入 $DSH_HOME/.credentials.yaml 或受信环境层 |
DSH_WEB_SEARCH_PROVIDER |
Web 搜索提供方 | 如 deepseek |
DSH_WEB_FETCH_PROVIDER |
Web 抓取提供方 | 按部署 |
DSH_WEB_URL |
本会话 Web GUI 地址 | 由 DSH 自动注入 |
DASHSCOPE_API_KEY |
「AI 生图」用,阿里云百炼(DashScope)密钥(可选,优先读环境变量) | 用户自备;设置后重启 dsh web |
DashScope Key 安全存放(不暴露给 AI):Key 存工作区之外的密钥文件
$DSH_HOME\secrets\dashscope.key(默认C:\Users\<你>\.dsh\secrets\dashscope.key),宿主进程启动/调用时读取,AI 会话受沙箱限制读不到、也不会被打印或回显。配置步骤(任选其一):① 环境变量set DASHSCOPE_API_KEY=sk-xxx后重启;② 密钥文件:mkdir "$env:USERPROFILE\.dsh\secrets"; Set-Content "$env:USERPROFILE\.dsh\secrets\dashscope.key" "sk-xxx"后重启。生图时自动读取,界面只显示「未配置」提示、不显示 Key。
关于默认模型:DSH 0.1.x 没有
DSH_MODEL环境变量。默认模型在设置里(agent-default-model),会话模型在 Web 界面右上角模型选择器里选。密钥用DEEPSEEK_API_KEY(或其它 provider 对应变量),不要写死在代码或 patch 里。
「用 AI 看图」依赖
modlensCLI:npm i -g @liustack/modlens(未装时该功能会给出安装提示,不影响其它功能)。Windows 下已修复「未安装」误报:调用改用node <modlens>/dist/main.js -i <图片>(不依赖modlens.cmd/PATH),找不到时才报安装提示;引擎未配置(Gemini key / Antigravity)会引导跑npx @liustack/modlens doctor。
5. 验证
# 1) 确认已安装
dsh plugin --profile web list
# 2) 确认组合进了配置树(应能看到 dsh-macos-desktop 这一 row)
dsh --profile web --dump-config
# 3) 重启 + 硬刷新
dsh web
# 浏览器打开 http://127.0.0.1:3080 后按 Ctrl/Cmd + Shift + R 硬刷新
预期:硬刷新后先看到深色开机画面(蓝鲸 + 进度条)→ 弹"开机统计"框 → 进入桌面(顶部菜单栏、底部 Dock、桌面文件图标)。Dock 点「AI 助手」开对话,点「文件」开文件管理器,「终端」「浏览器」「文档」「知识库」同理。菜单栏 "DSH ▸ 显示原始界面" 切回官方 UI,左上角会出现 "DSH 桌面" 按钮切回来。
5.1 开发期自检脚本(可选,本仓库自带)
# 结构自检(package.json + cordis.patch.yml + 入口文件)
node verify-structure.cjs .
# 宿主半侧冒烟(import + apply() 注册 33 条路由不抛错)
node smoke-host.cjs
6. 常见坑
| 现象 | 原因 | 解法 |
|---|---|---|
file: 安装改代码不生效 |
file: 是复制不是链接 | remove 再 add,或改用 link:,或重启 |
Cannot find package dsh-macos-desktop |
相对路径装到了 profile 目录里 | 用绝对路径,或让相对路径以 .//../ 开头(会被锚定到当前目录) |
| patch 没生效 | patch 路径写了相对路径 | dsh.bundle.patch 用 ./cordis.patch.yml 这种包内相对路径;profile 内引用用绝对路径 |
service "xxx" is not declared |
宿主/客户端用了 ctx.xxx 却没在 inject 声明 |
声明 inject,或用 ctx.get('xxx') 可选读取 |
| 客户端 bundle 加载但页面报错 | 客户端用了 JSX/TS/import | 客户端用 React.createElement + 纯 JS,只从平台模块表 require('react') |
| 插件 ID 不一致 | 包名 / bundle id / window.__ModuleLoader__.load({id}) 三处不一致 |
三处都写 dsh-macos-desktop |
| git 插件装不上 | pnpm 拦截了 prepare 构建 |
按提示在 profile 的 pnpm-workspace.yaml 加 allowBuilds |
| 文档功能报"依赖未安装" | doc 库懒加载失败 | 确认 dsh plugin --profile web list 里有 docx/mammoth/pdf-lib/pdf-parse |
7. 系统级依赖
无。 本插件文档处理全用纯 JS 库,不需要 LibreOffice、不需要系统字体、不需要原生模块。
- Windows / macOS / Linux:安装命令都是空的,装完 Node + pnpm + DSH 即可。
8. 文档处理依赖清单与选型理由
| 库 | 版本 | 用途 | 理由 |
|---|---|---|---|
docx |
^8.0.0 | 新建/生成 .docx |
纯 JS 生成 Word(OOXML),无原生依赖 |
mammoth |
^1.6.0 | 读取 .docx → 文本/HTML |
稳定、纯 JS,专注提取内容 |
pdf-lib |
^1.17.1 | 新建 .pdf |
零依赖纯 JS,save() 出字节流 |
pdf-parse |
^1.1.1 | 提取 .pdf 文本 |
轻量;代码里直接 import 'pdf-parse/lib/pdf-parse.js' 跳过其 CLI 守卫 |
pptxgenjs |
^3.12.0 | 新建/生成 .pptx |
纯 JS 生成 PowerPoint(OOXML),无原生依赖 |
预览策略(省依赖):
.pdf预览走浏览器原生渲染:宿主把文件以application/pdf原样返回,桌面用<iframe>展示(不需要任何 PDF 渲染库)。.docx预览走mammoth提取文本后展示。.pptx生成走pptxgenjs(标题页 + 每段一页),预览暂无内建渲染器(走「用外部程序打开」)。- 图片(png/jpg/gif/webp/svg)预览走
<img>。 - 这些依赖都是懒加载(
await import(...)),某个库没装上也不会拖垮插件启动。
9. 安全边界(重要)
- 只操作授权 workspace:宿主半侧对每个路径做
withinRoot(workspaceRoot, path)校验。workspaceRoot优先取workspaceRegistry.list()[0].path(dsh-workspace的持久化权威工作区,迁移改名后也正确),取不到才回退到sandboxPolicy.workspaceRoot(它默认是process.cwd(),即 DSH 启动目录,可能指向主目录而非真正工作区)。越界路径直接400 拒绝访问(Windows 下比较时不区分大小写)。 - 文本读写走沙箱
fs服务(fs.readText/fs.writeText/fs.listDir/fs.readBytes)。 - mkdir / rename / delete 用
node:fs(mkdir({recursive})/rename/rm({recursive,force})),在withinRoot校验通过之后才执行——这样 Windows 上也无需 bash 即可完成文件管理。delete 现在改为「移到回收站」(workspace/.trash/,带.meta.json记录原路径),可还原/清空;仅「清空回收站」才真正rm。 - 二进制写(docx/pdf 生成)用
node:fs,同样在withinRoot校验通过之后才落盘,因为fs服务只有文本写、没有字节写。 - 桌面图标区:只通过专用路由
/api/desktop列出 workspace 内desktop/文件夹的内容(该目录不存在时自动创建),绝不列出 workspace 根目录或任何真实系统目录(主目录 / AppData / NTUSER.DAT 等)。「此电脑」入口也只以 workspace 根目录为边界(withinRoot+ 前端根目录钳制双重限制)。 - 终端:只允许
cwd在 workspace 内;POSIX 走subprocess.spawnTerminal(/bin/bash --noprofile --norc -i),Windows 走subprocess.spawn起的持久powershell.exe/cmd.exe(受限模式下均经sandbox.confine包装)。 - 知识库 / 壁纸 / 便签:一律走
withinRoot校验的 workspace 内路径;知识库「任意本地目录」实际受沙箱限制为 workspace 内任意目录(workspace 外会被拒绝,这是安全边界,不是 bug)。
一句话:绝不触碰 workspace 之外的路径。
10. 内嵌浏览器(iframe)说明
「浏览器」应用是纯 iframe,不做服务端抓取(不引入 playwright/puppeteer)。
- 很多站点通过
X-Frame-Options: DENY/SAMEORIGIN或CSP frame-ancestors禁止被嵌入,iframe 会白屏或报错。本应用检测到加载失败会给出友好提示页:「该站点禁止被嵌入,可尝试在外部打开」,并提供"在外部打开"按钮。 - 常见可嵌入(或提供 embed 版)的站点:
https://example.com、维基百科、MDN、GitHub 的 embed 页、各大站点公开的 embed 页面等;常见禁止嵌入:google.com、facebook、银行等。 - 宿主端说明:iframe 的
sandbox设为allow-scripts allow-same-origin allow-forms allow-popups,没有放开allow-top-navigation等危险项;frame-src无需额外配置(同源 iframe 不受 DSH 自身 CSP 限制,因为内容是用户输入的第三方 URL)。 - 混合内容说明:若 DSH 跑在
http://127.0.0.1,嵌入https://站点没问题;反过来在https://页面嵌http://会被浏览器拦截(本插件不涉及)。
11. 对话界面怎么做的(复用官方能力)
「AI 助手」窗口完全复用 DSH 官方会话能力,不另造轮子:
- 通过客户端
ctx.sessions(官方SessionRuntime,它内部已持有官方 mux 事件流)拿到实时推送:session.getSnapshot()+session.subscribe()直接读组装好的对话快照,回复/工具调用逐块实时流出,不再轮询。 - 发送/停止/重命名走
session.prompt/session.cancel/session.rename;会话列表走sessions.list;新建走sessions.create;搜索走sessions.search。 - 工具调用轨迹来自快照里的
tool-result节点(默认收起,可展开看参数/结果),token 用量来自assistant节点的usage累加。 - 模型切换(deepseek-v4-pro/flash)与思考强度(Off/High/Max)通过
connection.api.sessions.selectModel写入当前会话。 - 权限设置、模式/工作区切换、更完整的轨迹/上下文占用等,走菜单栏 "DSH ▸ 显示原始界面" 切回官方 UI 操作——官方能力一个没丢,只是不重复实现。
@知识库 引用(B4)
在输入框里用 @知识库名 问题 发送,插件会:把知识库目录做关键词检索(文件名 + 文本内容 grep,不搞向量检索),取前 6 条片段拼接成 【知识库相关内容】+【用户问题】 一起 session.prompt 注入上下文。这是检索-注入(RAG 的朴素版),不是向量召回;@知识库名 来自「知识库」应用里自建的库。
12. 已实现 / 已知限制 / 后续建议
12.1 已实现
- 左右分栏布局(核心):左侧 = macOS 桌面(壁纸/桌面图标/窗口系统),右侧 = DSH 官方对话界面(CSS 覆盖成 macOS 风格,功能全保留),常驻右侧不再藏进「显示原始界面」。顶部菜单栏横跨全屏,Dock 悬浮于底部之上(不占空间,左右纵向都占满);中间可拖动分隔条调整两侧比例(20%–80%)。
- 底部 Dock(悬浮 + 精致图标):像素图标(此电脑/文件/文档/终端/浏览器/知识库/AI 生图/计算器/回收站/设置),已移除「AI 助手」重复入口(原生对话常驻右侧,是唯一对话入口);图标可添加/删除(右键移除,+号菜单加回,持久化到 localStorage)。图标用「圆角矩形 squircle + 上下渐变 + 居中像素 glyph + 顶部高光」重绘,参考 macOS 图标质感。
- 现代 macOS 风格(Big Sur / Sonoma 质感):更大圆角(窗口 16px/卡片/按钮 8–12px)、更高毛玻璃(blur 24–34px + saturate 170–185%)、蓝色 accent
#0a84ff、柔和渐变壁纸(内置 + 用户照片)、细腻双层阴影、系统字体(SF Pro/Segoe UI)、窗口红黄绿「交通灯」按钮、Dock squircle 图标带高光。 - 官方对话界面风格化(稳健版):用
body{--dsw-alias-*:...!important}覆盖 DSH 主题 token(背景/文字/边框/品牌/状态色全套),color-scheme:light,右侧真正变浅色 macOS 风,功能(对话/工具轨迹/token/权限/模式切换)全保留。分栏选择器改用结构选择器*:has(> [data-shell-overlay])(降级保留.pI_x6G_frame),不再依赖会随 DSH 构建变化的哈希类名。 - 桌面文件 =
desktop/文件夹内容(隔离目录,绝不显示真实系统目录);3 秒轮询 + 右上角「↻」手动刷新按钮,系统里放进/删除/重命名文件即时反映;每个文件浏览窗口独立维护 cwd + 乱序响应丢弃守卫,点不同文件夹/此电脑不会串目录;右键菜单(新建/排列/刷新 + 文件:打开/用 AI/重命名/删除/设为壁纸,文件窗口与桌面图标均可用)。 - 回收站(废纸篓):删除改为「移到回收站」(
workspace/.trash/),可还原/清空;宿主持久化映射元数据。 - 复古计算器:加减乘除,Dock 一键打开。
- 菜单栏像素数字时钟:HH:MM:SS 实时刷新。
- 顶栏 Big Sur 菜单 + 天气:菜单重构为「🍎 + DSH 桌面 + 文件/显示/窗口/帮助」分组(把新建/刷新/最近打开/排列方式/设置/关于本机/折叠桌面等合理归类,去掉重复标签);右侧显示郑州实时天气(Open-Meteo 免费 API,温度 + 天气图标,失败/离线优雅降级为「—」)。
- 浏览器外部打开:工具栏常驻「外部打开」按钮(当前 URL 一键唤起系统浏览器,弹确认防误触);被拒嵌入页的「在外部浏览器打开」同样确认后打开。
- 对话 @ 知识库弹窗:输入框输入
@弹出知识库选择列表,点选插入@库名;保留手动输入@库名方式兼容。 - 知识库管理修复:创建/删除/重命名/切换/搜索逻辑重构(
cur派生自 id 消除竞态),并修复「留空目录会错误建到 workspace 根」的宿主 bug(现在自动建到桌面子目录)。 - PDF/Word 预览增强:PDF 走 iframe + 顶部「在新窗口打开」;Word 用
mammoth.convertToHtml渲染可读 HTML(标题/列表/表格保留),不再是纯文本。 - 文档办公富文本:新建文档带格式工具栏(字号 12/14/16/18/20pt、加粗、斜体、自由换行),格式真实落盘——
.docx用 run 的bold/italics/size、.pdf用 Helvetica Bold/Oblique +fontSize内联排版、.pptx用 pptxgenjs 生成(标题页 + 每段一页),.txt纯文本丢格式(正常)。格式选择器新增「PPT (.pptx)」。 - 趣味彩蛋:开机加载随机复古梗(「正在转动 1.44MB 软盘…」「正在给鲸鱼喂鱼…」)、回收站俏皮文案、Dock hover 带梗提示、终端错误语气轻松化、开机鲸鱼连续点击冒泡吐梗。
- 用 AI 看图(3.1 已接入):右键图片 →「用 AI 看图」→ 宿主跑
modlens输出结构化 JSON(OCR/版面/语义)→ 弹窗展示 + 「发给 AI 助手」。需npm i -g @liustack/modlens。调用方式已修复:不再依赖 PATH 里的modlens.cmd(Windows 下找不到导致误报「未安装」),改为createRequire精确解析@liustack/modlens/dist/main.js后用node <main.js> -i <图片> --timeout 180000调用,并正确解包JSON.result;失败提示会引导你跑npx @liustack/modlens doctor检查视觉引擎(Gemini key / Antigravityagy)是否配好。 - AI 生图(3.2 已接入):Dock「AI 生图」app——提示词 + 比例(1:1/16:9/4:3)+ 风格(插画/像素/复古/写实)+ 可选参考图(经 modlens 视觉描述增强 prompt),走 DashScope 通义万相
wanx-v1文生图(异步任务轮询),需DASHSCOPE_API_KEY。 - 对话窗口(自定义 ChatApp)保留:官方 mux 事件流实时推送、Markdown、代码复制、工具折叠、会话重命名/搜索、模型切换、@知识库 注入、用 AI 处理。
- 任务进度条 + Token 组件数据源:直接从 DSH 官方
sessions服务的 mux 快照取数(订阅当前会话snapshot,累加 assistant 节点usage得 token、统计runningCalls/tool-result得进度),不再依赖自定义 ChatApp 窗口——原生对话常驻右侧后这两个小组件依然实时更新;进度条窗口只在「开机完成后且任务进行中」出现,不再在加载界面弹出。 - 桌面 3 秒轮询改为「变更检测」:
loadDesktop每次拿到目录列表后先算签名(type:path拼接),内容未变就不setState——避免每 3 秒整棵桌面子树重渲染,加载更顺、CPU 更低;文件增删/改名仍即时反映(签名变了才刷新)。 - whale-girl 宠物层级修复:桌面 overlay 与 whale-girl 宠物同处
z-index:2147483000,DOM 顺序可能把宠物埋到桌面下;本插件加[data-whale-girl]{z-index:2147483600!important}让宠物永远浮在最上层,无论拖到哪都可见、可点。 - Spotlight 搜索(⌘K / Ctrl+K 或菜单栏🔍):居中出现搜索框,搜 App + 搜文件(复用
/api/search),回车/点击直接打开,Esc 关闭。 - 深色模式:设置里新增「深色模式」主题,桌面与右侧官方对话一起变暗(
body.dsm-dark覆盖--dsw-alias-*+color-scheme:dark)。 - Dock 分组分隔线 + 回收站角标:此电脑与回收站/设置之间加竖分隔线;回收站非空时 Dock 图标右上角亮红点角标(10 秒轻轮询 + 删除/还原/清空即时刷新)。
- 迷你日历:点菜单栏时钟弹出当月日历(今天高亮、跨月灰显)。
- 窗口最小化动效:最小化时窗口缩放淡出「缩进 Dock」,点 Dock 图标弹回(
transition+dsm-minimized,关闭仍即时隐藏)。 - 拖拽上传到桌面/文件窗口:本地文件拖进桌面或文件窗口即上传(宿主新增
/api/upload,raw body 二进制 +dir/name查询参数,仍走withinRoot校验)。 - 多窗口:文件/浏览器/终端/编辑器/预览/文档等支持开多个窗口(双击不同文件夹/文件各自开新窗,标题带文件名、级联错位);设置/计算器/回收站/知识库/文档办公/生图/对话仍是单实例。
- 桌面图标拖动 + 网格吸附记忆:桌面右键「排列方式」关掉「自动排列」后,图标可拖动,松手吸附 96px 网格并记住位置(localStorage);重开「自动排列」恢复自动排序。
- 窗口边缘吸附(Aero Snap):拖动窗口到桌面区顶部=最大化、拖到左/右边缘=半屏。
- 便签增强:便签位置持久化(拖动后记住,刷新不丢);Dock 新增「便签」图标一键新建(原右键「新建便签」仍可用)。
- 番茄钟:Dock 新增「番茄钟」——25 分钟专注 / 5 分钟休息,开始/暂停/重置/切换,到点 Toast 提醒。
- 截图工具:Dock 新增「截图」——一键把桌面面板截成 PNG(存到
desktop/screenshots/),并自动「用 AI 看图」(modlens 描述 + 「发给 AI 助手」)。纯前端 DOM→canvas 实现,无新依赖。 - UI 更贴近现代 macOS:窗口圆角 16→18px、阴影更柔和、交通灯按钮加内描边/高光、毛玻璃 blur/saturate 微调。
- 其余原功能全保留:终端(Windows powershell/cmd 适配)、多标签浏览器、知识库、3 弹窗、Token 组件、设置、便利贴、关于本机、最近文件、8bit 鲸鱼、进度条、窗口拖动/缩放/最大化、开机流程。
12.2 已知限制
- 终端是 SSE + POST,不是 WebSocket;输出为纯文本(TERM=dumb),不做 xterm.js 的完整 ANSI 渲染。
- Windows 终端的平台限制(如实说明):① 官方
dsh-subprocess-local的spawnTerminal在 win32 上直接抛terminal inspection is unsupported on platform win32,因此本插件在 Windows 改用subprocess.spawn的管道终端(无真 PTY),不做 ANSI 渲染、无真前景进程组;② 管道模式下 Ctrl+C 无法中断正在运行的命令(0x03会被忽略,这是 Windows 管道终端的固有限制);③ Windows PowerShell 5.1(powershell.exe)非 ASCII 输出默认走 OEM 代码页,可能乱码,pwsh7 默认 UTF-8 无此问题。要完整终端体验仍建议在 Linux/macOS 上使用。 - 右侧官方界面的配色覆盖走
body{--dsw-alias-*:…!important}(DSH 主题 token 写在 body 内联,author-important 才能压过);分栏选择器已改为结构选择器*:has(> [data-shell-overlay])+.pI_x6G_frame双保险,升级 DSH 后哈希变化也能命中——功能不受影响,只影响样式。 - 壁纸/毛玻璃新方案:壁纸设为整个页面背景(
body,左右共享同一张),左桌面 overlay 透明、右官方界面的内部容器(侧边栏/聊天区列)的::before伪元素加backdrop-filter: blur半透明磨砂——不给 frame/列本身加 backdrop-filter(会建立 containing block 破坏左侧 overlay 的 fixed 定位、并困住设置弹窗),改在列的::before上做真模糊。官方设置弹窗保持全屏居中、z-index 高于桌面 overlay,不被 Dock/菜单栏/窗口遮挡、可正常点击。 - 进度条没有"总步骤数"权威来源,用"当前工具名 + 工具调用数"估计,跑到 90% 封顶直到结束。
- 余额/费用:token 单价是内置估算值(¥/百万 token,见
lib/client.js的PRICES),不是实时计价;/user/balance接口需要DEEPSEEK_API_KEY且主机能访问 api.deepseek.com,否则自动降级为手动初始余额。 - 模型切换的思考强度值(high/max)是 best-effort:真实取值是适配器自己的
reasoningEffortid,不同 provider 可能不同。 - 知识库「任意本地目录」受沙箱限制为 workspace 内目录。
- iframe 被拒站点只能外部打开,链接跳转拦截依赖 iframe
onError(跨域子页内的导航不会触发父页事件,属浏览器安全限制)。
12.3 后续迭代建议(本轮不做)
鲸鱼动画;更多弹窗;ima 联动;拖拽上传;目录实时刷新;xterm.js 完整终端渲染;壁纸轮播;斜杠快捷指令;现代 macOS 弹跳 Dock 动画;pptx 预览渲染器(当前生成后可「外部打开」,内嵌预览后续补)。
13. 1 分钟验证路径
# 30 秒装好
dsh plugin --profile web add "C:\你的路径\dsh-macos-desktop"
dsh plugin --profile web list # 应看到 dsh-macos-desktop
# 30 秒看效果
dsh web # 重启
# 打开 http://127.0.0.1:3080 → Ctrl/Cmd+Shift+R 硬刷新
# → 开机鲸鱼 + 进度条 → 进入复古桌面:
# 左侧 = 桌面,右侧 = DSH 原生对话界面(macOS 风),底部 Dock + 顶部菜单栏横跨全屏
验证清单:
- 分栏:拖动中间分隔条,左右比例联动;菜单栏「DSH ▸ 折叠桌面」→ 右侧全屏,「展开桌面」恢复。
- Dock:右键 Dock 图标「移除」,点 Dock 末尾「+」加回;配置在重启后保留。
- 毛玻璃:Dock/菜单栏/窗口标题栏/弹窗/Token 组件应呈半透明模糊。
- PDF/Word:双击
.pdf出 iframe 预览 + 「在新窗口打开」;双击.docx出可读 HTML(标题/表格),不再是纯文本。 - 回收站:删除一个文件 → Dock 点「回收站」→ 还原 / 清空。
- 计算器 / 时钟 / 设为壁纸:Dock 开计算器;菜单栏右上角像素时钟;右键图片 →「设为壁纸」。
13.1 壁纸替换
把 SVG/PNG/JPG/WebP 图片放进 workspace 的 desktop/wallpapers/ 文件夹(插件首次启动会自动创建该目录,文件名随意)。然后任选其一:
- 硬刷新(Ctrl/Cmd+Shift+R)后打开「设置」→「壁纸」下拉选择;
- 或在桌面/文件里右键图片 →「设为壁纸」(选「默认」回到内置纯色壁纸)。
壁纸读取走插件自带的 /dsh-macos-desktop/file 文件服务,不需要额外配置。
14. 目录结构
dsh-macos-desktop/
├── package.json # dsh.bundle + dsh.client 声明、文档依赖
├── cordis.patch.yml # 宿主组合 patch(插入本包 row)
├── lib/
│ ├── index.js # 宿主半侧:文件/终端/文档/统计/搜索/回收站/富文本文档
│ └── client.js # 浏览器半侧:整个复古桌面(React + 内联 CSS)
├── verify-structure.cjs # 结构自检脚本(可选)
├── smoke-host.cjs # 宿主半侧冒烟脚本(可选)
└── README.md
15. 生态调研结论(3.1 / 3.2 已确认并接入)
15.1 视觉/看图插件(已接入 modlens)
- modlens:CLI 工具,把图片转成结构化 JSON(OCR/版面/语义),给「纯文本模型」补视觉。已接入:宿主
/api/vision用subprocess跑modlens <图片>,前端右键图片 →「用 AI 看图」。需npm i -g @liustack/modlens。 - dsh-vision-complete:面向 DSH 的视觉 skill,可作后续补充(本轮未用)。
15.2 AI 生图插件(已接入 DashScope 文生图)
- Deepseek-omnimodal 证实 DashScope/Qwen 是现成生图路线。已接入:宿主
/api/gen-image直连 DashScopewanx-v1文生图(异步任务 + 轮询),前端「AI 生图」app(提示词/比例/风格/参考图)。需DASHSCOPE_API_KEY(阿里云百炼)。 - 注意:
wanx-v1是「文生图」,参考图以「modlens 视觉描述增强 prompt」的方式生效(非真图生图);要真·图生图需另接 DashScope 图生图模型,可后续迭代。
15.3 UI 魔改调研(供 2.2 参考,已落地)
- deepseek-harness-themes、dsh-skin、dsh-bg-image、DSH-Transparent-UI-Plugin 均采用
--dsw-alias-*token 覆盖实现主题/半透明磨砂,证实了本插件「body token !important 覆盖」是社区通用做法;其中 dsh-bg-image 做了「侧边栏/聊天区半透明磨砂」。分栏布局的position:fixedoverlay 是本插件的特有复杂度,社区无直接同款,故用「结构选择器 + 列级 ::before 磨砂」的稳健方案。
15.4 Office 文档处理(dsh-office → 实为 dsh-cowork)
- GitHub 上未找到名字恰好为
dsh-office的独立仓库。功能最接近的是 dsh-cowork:提供doc_read/doc_write系列工具,覆盖 xlsx / pdf / docx / pptx / ipynb 的读写。 - 与本插件的冲突点:本插件「文档办公」app 已自建 docx/pdf 读写 + 富文本(
docx/mammoth/pdf-lib/pdf-parse),dsh-cowork 若作为独立工具注册,会在对话里与自建文档能力重复(两套 docx/pdf 处理入口)。 - 整合方式(本插件方案):不把 dsh-cowork 的 docx/pdf 工具纳入桌面,只取其「pptx 能力」补位——本插件已在「文档办公」app 里直接加
pptxgenjs生成.pptx(格式选择器新增「PPT (.pptx)」),桌面只保留一个文档入口,不出现两套重复入口。若你更想要 dsh-cowork 在对话里的 xlsx/ipynb 工具(本插件没有),可另装它作为对话工具(与本插件文件管理器不冲突,因为它走对话工具面、不是 UI 面)。 - Windows 兼容:pptxgenjs 是纯 JS 库(零原生依赖),Windows/macOS/Linux 均可直接生成
.pptx。
15.5 对话图表/表格渲染(dsh-genui)
- dsh-genui:在 DSH 对话回复里渲染图表 / 表格 / 组件(AI 输出 Mermaid/表格/ECharts 等结构化标记时转成可视化组件),与本插件右侧「官方对话界面」是同一块区域。
- 冲突点与整合方式:dsh-genui 挂载在官方对话/消息渲染层,本插件右侧是「官方对话界面 CSS 化」而非自绘聊天(除进度条/Token 小组件外不接管消息渲染),因此两者在同一对话流里协同、互不替换。视觉一致性靠本插件已有的
body{--dsw-alias-*:…!important}主题覆盖 + 列级::before磨砂,dsh-genui 渲染出来的组件会自动继承 DSH 主题 token,跟随本插件的浅色 macOS 风。无需在本插件里重写 dsh-genui 的组件,只保证主题 token 覆盖兼容即可。 - Windows 兼容:dsh-genui 是纯前端渲染插件,无宿主原生依赖,Windows 下照常工作。
16. 社区插件安装(§四)
本环境(沙箱)无权限执行 dsh plugin add(PowerShell 执行策略 + 沙箱拦截外部写/网络),以下命令请在你本机手动执行。
本轮新增
pptxgenjs依赖(link: 安装不自动拉新依赖):请先在本仓库目录跑一次npm install(装进插件自己的node_modules),或dsh plugin --profile web update dsh-macos-desktop,再重启dsh web。否则「文档办公 → 新建 PPT」会因缺pptxgenjs报「依赖未安装」。
dsh-vision-toolkit(视觉工具,可选,与本插件「用 AI 看图」互补):
dsh plugin --profile web add github:Anionex/dsh-vision-toolkit # 或 dsh plugin --profile web add "@dsh-external/dsh-vision-toolkit"仓库:https://github.com/Anionex/dsh-vision-toolkit —— 装完重启
dsh web,它作为独立工具注册(图片问答/长截图 OCR),与本插件无冲突(不同功能面)。dsh-genui(对话里渲染图表/表格/组件):
dsh plugin --profile web add github:omdsh-dev/dsh-genui仓库:https://github.com/omdsh-dev/dsh-genui —— 装完重启
dsh web即生效(纯前端渲染插件)。它挂在右侧官方对话流里渲染图表/表格,与本插件右侧「官方界面 CSS 化」协同、互不替换,视觉继承本插件的 macOS 主题 token。若 pnpm 提示拦截prepare构建,按提示在 profile 的pnpm-workspace.yaml加入allowBuilds再重跑(见 §2.3)。dsh-cowork(Office 文档读写工具,xlsx/pdf/docx/pptx/ipynb,可选):
dsh plugin --profile web add github:Jesse-njx/dsh-cowork仓库:https://github.com/Jesse-njx/dsh-cowork —— 装完重启
dsh web,以「对话工具」形式注册(不是 UI 入口),与本插件「文档办公」app 的 docx/pdf 能力有部分重叠。默认不必装:本插件已用pptxgenjs补齐 pptx 生成,docx/pdf 读写 + 富文本也已自带;只有当你还需要对话里的 xlsx/ipynb 工具时才装它,桌面不会因此多出一套文档入口(它走工具面,本插件走 UI 面,互不打架)。dsh-plugin-add:GitHub 上未找到名为
dsh-plugin-add的独立仓库;它大概率指「插件市场/一键安装」类工具。可选用以下之一替代:# WhaleHub 插件市场(发现/搜索/一键安装) dsh plugin --profile web add github:vvlife/whalehub-dsh # 或 插件管理面板 dsh plugin --profile web add github:Noob-stupid/dsh-plugin-hub若你手头有确切的
dsh-plugin-add仓库地址,把命令里的github:作者/仓库换成该地址即可。
No comments yet. Be the first to write one.