Skip to content

Commit 54f3370

Browse files
feat: import DSH backgrounds from chat without launching dsh
Register /bg, /bg-theme, /bg-clear and beauticode_* tools on the user-started plugin. Reuse a live tray when present; otherwise apply in-process. beautiCode still never starts dsh web.
1 parent 46da96c commit 54f3370

13 files changed

Lines changed: 1494 additions & 61 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
beautiCode 是一个本地背景工具,**主要面向 DeepSeek Harness和Codex**
3030

31-
安装包已内置兼容的 DeepSeek Harness 运行时。启动 beautiCode,选中 DeepSeek Harness或Codex,就可以把电脑里的:
31+
它不包含、不安装、也不启动 DSH。请先自行安装 DeepSeek Harness 并运行 `dsh web`,再启动 beautiCode,选中 DeepSeek Harness 或 Codex,就可以把电脑里的:
3232

3333
* 图片
3434
* 动态壁纸
@@ -80,7 +80,7 @@ beautiCode 可以让你:
8080
想直接使用 beautiCode,可以下载 [Windows 安装包](https://github.com/starsstreaming/beautiCode/releases/tag/v1.0.0)
8181
安装包自带 Node.js,不需要另外安装 Node.js 或 npm。
8282
Codex Desktop 路径与原来一样:启动后选 **Codex Desktop**,托盘会按需拉起 Codex。
83-
DeepSeek Harness 由你自己运行:把插件装进 DSH profile,再启动 `dsh web`,然后在选择框里选 **DeepSeek Harness**
83+
DeepSeek Harness 由你自己运行:把插件装进 DSH profile,再启动 `dsh web`,然后在选择框里选 **DeepSeek Harness**beautiCode 绝不替你启动 DSH。页面打开后也可以用 `/bg``/bg-theme``/bg-clear`,或直接跟 AI 说把本机图片/视频设成背景。
8484
<img width="533" height="660" alt="image" src="https://github.com/user-attachments/assets/8c16eeb9-94d0-4f19-a816-b32fba8a110c" />
8585

8686

apps/tray/session-host.mjs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* GET /health
1111
* GET /status
1212
* POST /apply/image { "imagePath": "..." }
13-
* POST /apply/video { "videoPath": "...", "imagePath"?: "..." }
13+
* POST /apply/video { "videoPath": "...", "imagePath"?: "...", "startAt"?: number }
1414
* POST /apply/clear {}
1515
* POST /reapply {} // republish active background into live sessions
1616
* POST /theme/save { "name": "..." } // keep current image/video
@@ -27,6 +27,10 @@ import process from "node:process";
2727
import path from "node:path";
2828
import crypto from "node:crypto";
2929
import { fileURLToPath, pathToFileURL } from "node:url";
30+
import {
31+
removeDshControlFile,
32+
writeDshControlFile,
33+
} from "../../integrations/deepseek-harness/control-client.mjs";
3034

3135
if (Number(process.versions.node.split(".", 1)[0]) < 22) {
3236
console.error("session-host 需要 Node.js 22 或更高版本。");
@@ -186,7 +190,7 @@ function checkAuth(req) {
186190
}
187191

188192
const server = http.createServer(
189-
{ maxHeaderSize: 16 * 1024, requestTimeout: 30_000 },
193+
{ maxHeaderSize: 16 * 1024, requestTimeout: 180_000 },
190194
async (req, res) => {
191195
try {
192196
if (!checkAuth(req)) {
@@ -226,7 +230,7 @@ const server = http.createServer(
226230
? {
227231
title: "连接 DeepSeek Harness",
228232
steps: [
229-
"使用 integrations/deepseek-harness/cordis.patch.example.yml 启动 dsh web。",
233+
"自己运行 dsh web(需已加载 beautiCode 插件)。",
230234
"在浏览器中打开 DSH Web 页面。",
231235
"回到 beautiCode 托盘选择图片。",
232236
],
@@ -287,6 +291,14 @@ const server = http.createServer(
287291
if (typeof body.imagePath === "string" && body.imagePath) {
288292
videoInput.imagePath = path.resolve(body.imagePath);
289293
}
294+
if (body.startAt != null) {
295+
const startAt = Number(body.startAt);
296+
if (!Number.isFinite(startAt) || startAt < 0) {
297+
send(res, 400, { ok: false, error: "startAt 必须是非负数字(秒)。" });
298+
return;
299+
}
300+
videoInput.startAt = startAt;
301+
}
290302
const result = await session.apply(videoInput);
291303
send(res, result.ok ? 200 : 422, result);
292304
return;
@@ -404,12 +416,20 @@ const server = http.createServer(
404416
},
405417
);
406418
server.headersTimeout = 10_000;
419+
server.requestTimeout = 180_000;
407420
server.keepAliveTimeout = 5_000;
408421
server.maxRequestsPerSocket = 100;
409422

410423
async function shutdown(code) {
411424
if (shuttingDown) return;
412425
shuttingDown = true;
426+
if (hostKind === "dsh") {
427+
try {
428+
await removeDshControlFile({ dataRoot: session.dataRoot, pid: process.pid });
429+
} catch {
430+
/* ignore */
431+
}
432+
}
413433
const serverClosed = new Promise((resolve) => server.close(() => resolve()));
414434
server.closeIdleConnections?.();
415435
try {
@@ -441,6 +461,22 @@ process.on("SIGINT", () => void shutdown(0));
441461
process.on("SIGTERM", () => void shutdown(0));
442462
const addr = server.address();
443463
const listenPort = typeof addr === "object" && addr ? addr.port : 0;
464+
if (hostKind === "dsh") {
465+
try {
466+
await writeDshControlFile({
467+
dataRoot: session.dataRoot,
468+
url: `http://127.0.0.1:${listenPort}`,
469+
token,
470+
pid: process.pid,
471+
});
472+
} catch (error) {
473+
console.error(
474+
`session-host:无法发布 DSH 控制面,对话导入和斜杠命令将不可用:${
475+
error instanceof Error ? error.message : String(error)
476+
}`,
477+
);
478+
}
479+
}
444480
// Machine-readable ready line for the tray launcher (stdout).
445481
console.log(
446482
JSON.stringify({

docs/deepseek-harness.md

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ beautiCode 通过 DeepSeek Harness 的 Cordis 插件接口接入(`@beauticode/
55
## 已实现能力
66

77
- 图片背景、MP4 视频背景与清除。首页(`data-phase="hero"`)壁纸保持原亮度;进入会话(`active` / `settling`)后才压暗。
8+
- 对话工具与斜杠命令:在 DSH 里说「把某个本机 MP4 设成背景」,或输入 `/bg``/bg-theme``/bg-clear`。插件自己完成导入,不需要托盘。若托盘已经在跑,则复用托盘,避免两套写入打架。
89
- 视频默认静音;可请求开启声音。若浏览器自动播放策略阻止开启声音,会继续静音播放并返回 `blocked: true`
910
- 视频播放位置随已保存主题记录;切换主题、重新应用与页面恢复时从最近位置继续。
10-
- 摸鱼模式:隐藏 DSH 的 `#root`,背景舞台继续显示和播放;`Ctrl+Shift+Space` 可退出。属于实验性能力。
11+
- 摸鱼模式:隐藏 DSH 的 `#root`,背景舞台继续显示和播放;`Ctrl+Shift+Space` 可退出。
1112
- 深色、浅色、跟随系统三种背景色调。
1213
- 图片/视频主题的保存、切换和删除。
1314
- 页面刷新或稍后打开时,会恢复当前背景与模式。找不到 `#root` 时应用失败并回滚,不会静默画坏页。
@@ -30,7 +31,7 @@ dsh plugin --profile web add file:%LOCALAPPDATA%\Programs\beautiCode\integration
3031

3132
## 启用插件
3233

33-
把下面的条目加到 profile 自己的 patch 层(`~/.dsh/cordis.patch.yml` 或 profile 目录的 `cordis.patch.yml`),然后重启 `dsh web`
34+
把下面的条目加到 profile 自己的 patch 层(`~/.dsh/cordis.patch.yml` 或 profile 目录的 `cordis.patch.yml`),然后自己启动 `dsh web`
3435

3536
```yaml
3637
- insert:
@@ -43,7 +44,7 @@ dsh plugin --profile web add file:%LOCALAPPDATA%\Programs\beautiCode\integration
4344

4445
## 控制端
4546

46-
启动 beautiCode,在选择框里选 DeepSeek Harness(或直接 `start-tray.ps1 -TargetHost dsh`)。托盘连接你正在运行的 DSH 网页:
47+
启动 beautiCode,在选择框里选 DeepSeek Harness(或直接 `start-tray.ps1 -TargetHost dsh`)。托盘只连接你正在运行的 DSH 网页:
4748

4849
```powershell
4950
powershell -NoProfile -ExecutionPolicy Bypass -File apps\tray\start-tray.ps1 -TargetHost dsh -DshUrl http://127.0.0.1:3080
@@ -60,7 +61,23 @@ npm run bc -- clear --port 3080
6061

6162
自定义数据目录时,控制端与插件必须使用同一个 `BEAUTICODE_DATA_ROOT`,否则令牌文件不一致。未设置时两边都默认 `%LOCALAPPDATA%\beautiCode`。
6263

63-
> beautiCode 不会自动启动 DSH。若 `dsh web` 未运行或未加载插件,托盘会提示你先启动 DSH 网页,而不是替你拉起进程。
64+
> beautiCode 不会自动启动 DSH。若 `dsh web` 未运行或未加载插件,托盘会提示你先启动 DSH 网页,而不是替你拉起进程。网页已开但关掉时,「应用或重新应用」只会重新打开页面。
65+
66+
### 对话导入与斜杠命令
67+
68+
插件在 DSH 的 `tools` / `commands` 服务出现后注册(不把它们写成硬依赖,以免没有 agent 的 webServer 组合挂不上桥)。
69+
70+
| 入口 | 作用 |
71+
|---|---|
72+
| `beauticode_apply_video` / `beauticode_apply_image` | 按本机绝对路径导入 |
73+
| `beauticode_theme_list` / `beauticode_theme_use` | 列出或切换已保存主题 |
74+
| `beauticode_clear` / `beauticode_status` | 清除或查看当前背景 |
75+
| `beauticode_set_fish` / `beauticode_set_muted` | 摸鱼、背景声音 |
76+
| `/bg <绝对路径>` | 按扩展名导入图片或 MP4 |
77+
| `/bg-theme <名称>` | 切换已保存主题 |
78+
| `/bg-clear` | 清除背景 |
79+
80+
没有托盘时,插件在 DSH 进程里启动同一套 `DshSession`(校验、拷贝、媒体服务、live verify)。托盘若已在跑,则继续走 `dsh-control.json`,避免抢同一把写入锁。页面必须已打开,否则 verify 会失败并回滚。
6481

6582
## 安全边界
6683

integrations/deepseek-harness/README.zh-CN.md

Lines changed: 12 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,61 +2,22 @@
22

33
该 Cordis 插件向 DSH Web 注入 beautiCode 浏览器客户端,并提供本机鉴权接口。支持图片、MP4、播放位置、静音、摸鱼模式、深浅色调以及清除背景。
44

5-
插件以 `@beauticode/dsh-plugin` 的形态放在本仓库(安装包也会带上同一目录)。beautiCode **不附带、不启动** DeepSeek Harness;请用你自己的 `dsh` 装插件并启动网页
5+
插件会注册对话工具(`beauticode_*`)和斜杠命令(`/bg``/bg-theme``/bg-clear`),把本机文件导入为背景。不需要托盘;托盘若已在跑则复用它
66

7-
## 安装
7+
beautiCode **不启动** DeepSeek Harness。请先自己运行 `dsh web`,再打开 beautiCode 选择 DeepSeek Harness。
88

9-
```sh
10-
# 源码目录
11-
dsh plugin --profile web add file:<beautiCode 路径>/integrations/deepseek-harness
12-
13-
# Windows 安装包
14-
dsh plugin --profile web add file:%LOCALAPPDATA%\Programs\beautiCode\integrations\deepseek-harness
15-
```
16-
17-
包尚未发布到 npm,请按路径安装,不要用 `dsh plugin add @beauticode/dsh-plugin`
9+
安装包和托盘会把插件写入你的 DSH profile。源码环境也可以手动:
1810

19-
## 启用
20-
21-
把下面的条目加到 profile 自己的 patch 层(`~/.dsh/cordis.patch.yml` 或 profile 目录的 `cordis.patch.yml`),然后重启 `dsh web`
22-
23-
```yaml
24-
- insert:
25-
- id: beauticode-bridge
26-
name: '@beauticode/dsh-plugin'
27-
inject: [webServer]
11+
```sh
12+
dsh plugin --profile web add file:%CD%/integrations/deepseek-harness
13+
dsh web
2814
```
2915

30-
也可以参考 `cordis.patch.example.yml`。默认端口是 `3080`;托盘用 `-DshUrl` 才能连其他端口。
31-
32-
## 控制
33-
34-
插件只暴露本机接口。托盘 / CLI 与插件默认共用 `%LOCALAPPDATA%\beautiCode`(或 `BEAUTICODE_DATA_ROOT`)里的 `dsh-bridge.token`。自定义数据根时两边必须一致。
35-
36-
接口一览(均以 `/__beauticode/` 前缀):
37-
38-
| 路径 | 方法 | 鉴权 | 说明 |
39-
|---|---|---|---|
40-
| `/version` | GET/HEAD | 无 | 桥接协议与版本 |
41-
| `/client.js` | GET | 无 | 浏览器注入脚本 |
42-
| `/events` | GET (SSE) | 同源 | 浏览器客户端事件流 |
43-
| `/apply` | POST | Bearer | 应用图片/视频/清除 |
44-
| `/mode` | POST | Bearer | 摸鱼/静音/色调 |
45-
| `/status` | GET | Bearer | 当前状态与回执汇总 |
46-
| `/ack` | POST | 同源 | 浏览器渲染/模式回执 |
47-
48-
## 安全边界
49-
50-
- DSH Web 必须绑定本机回环地址。
51-
- 控制端点需要随机令牌;浏览器回执只接受同源请求。
52-
- 媒体 URL 仅允许带令牌的回环 HTTP 地址。
53-
- 插件只注入与鉴权,不改动 DSH 源码,也不结束/重启用户的 DSH 进程。
54-
55-
## DOM 契约与失败方式
56-
57-
背景舞台依赖 DSH 页面结构:`#root` 为硬依赖;`data-phase` 标记用于进入会话后压暗。
16+
手动接入时:
5817

59-
- 找不到 `#root` → 渲染回执返回明确错误,应用事务失败并回滚。
60-
- `data-phase` 缺失时不硬失败(首页无会话标记是正常的)。
18+
1. 修改 `cordis.patch.example.yml` 中的 `file:///.../index.mjs`
19+
2. 确保 DSH 和 beautiCode 使用相同的 `BEAUTICODE_DATA_ROOT`
20+
3. 自己运行 `dsh web`(或带 `--patch`)。
21+
4. 打开页面后输入 `/bg <本机绝对路径>`,或直接跟 AI 说把某个视频/图片设为背景。
6122

62-
摸鱼模式通过隐藏 `#root` 的 CSS 实现,属于实验性能力
23+
安全边界:DSH Web 必须绑定本机回环地址;控制端点需要随机令牌;媒体 URL 仅允许带令牌的回环 HTTP 地址;浏览器回执只接受同源请求

0 commit comments

Comments
 (0)