Skip to content

Commit 748daa5

Browse files
Merge pull request #33 from starsstreaming/codex/dsh-1.0.14
DSH 1.0.22 发布配套 + 仓库工程整理
2 parents 7edea84 + c6b2080 commit 748daa5

53 files changed

Lines changed: 7247 additions & 723 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitignore‎

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
1+
# Dependencies & build output
12
node_modules/
23
dist/
3-
*.log
4+
packages/*/dist/
5+
packages/*/node_modules/
6+
apps/tray/node_modules/
7+
8+
# Runtime / local build artifacts (npm pack & windows installer output)
9+
artifacts/
10+
*.tsbuildinfo
11+
12+
# Env & OS noise
413
.env
514
.env.*
615
!.env.example
716
.DS_Store
17+
*.log
18+
19+
# Local reference / prototype work
820
.ref/
921
design-demos/
22+
23+
# Test coverage
1024
coverage/
11-
*.tsbuildinfo
12-
apps/tray/node_modules/
13-
packages/*/dist/
14-
packages/*/node_modules/
15-
artifacts/
25+
26+
# Local agent/tool scratch directories (not part of the project)
27+
.mimosa/
28+
.workbuddy/
29+
.cache/
30+
.tmp/

‎THIRD_PARTY_NOTICES.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
- License: MIT, Copyright (c) 2026 DeepSeek
77
- Upstream project: https://github.com/deepseek-ai/deepseek-harness
88
- Distribution: beautiCode no longer ships a private DSH runtime. Users install
9-
DSH themselves and add the `@beauticode/dsh-plugin` files from
9+
DSH themselves and add the `beauticode-dsh` plugin files from
1010
`integrations/deepseek-harness`.
1111

1212
## Fei-Away/Codex-Dream-Skin (media server lineage)

‎apps/tray/session-host.mjs‎

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
* Protocol (JSON):
1010
* GET /health
1111
* GET /status
12-
* POST /apply/image { "imagePath": "..." }
13-
* POST /apply/video { "videoPath": "...", "imagePath"?: "...", "startAt"?: number }
12+
* POST /apply/image { "imagePath": "...", "source"?: "managed"|"local" }
13+
* POST /apply/video { "videoPath": "...", "imagePath"?: "...", "source"?: "managed"|"local", "startAt"?: number }
1414
* POST /apply/clear {}
1515
* POST /reapply {} // republish active background into live sessions
16+
* POST /theme/apply { "name": "...", "input": ApplyInput }
1617
* POST /theme/save { "name": "..." } // keep current image/video
1718
* GET /theme/list
1819
* POST /theme/use { "id": "..." }
@@ -51,6 +52,60 @@ function argValue(name) {
5152
return value && !value.startsWith("--") ? value : null;
5253
}
5354

55+
function badRequest(message) {
56+
const error = new Error(message);
57+
error.statusCode = 400;
58+
return error;
59+
}
60+
61+
function parseImportMode(value) {
62+
if (value == null) return undefined;
63+
if (value === "managed" || value === "local") return value;
64+
throw badRequest("source 必须是 managed 或 local。");
65+
}
66+
67+
function parseThemeApplyInput(value) {
68+
if (!value || typeof value !== "object" || Array.isArray(value)) {
69+
throw badRequest("input 必须是图片或视频导入参数。");
70+
}
71+
if (value.type === "image") {
72+
if (typeof value.imagePath !== "string" || !value.imagePath) {
73+
throw badRequest("图片主题必须提供 imagePath。");
74+
}
75+
const input = {
76+
type: "image",
77+
imagePath: path.resolve(value.imagePath),
78+
source: parseImportMode(value.source),
79+
};
80+
if (value.effects && typeof value.effects === "object") {
81+
input.effects = value.effects;
82+
}
83+
return input;
84+
}
85+
if (value.type === "video") {
86+
if (typeof value.videoPath !== "string" || !value.videoPath) {
87+
throw badRequest("视频主题必须提供 videoPath。");
88+
}
89+
const input = {
90+
type: "video",
91+
videoPath: path.resolve(value.videoPath),
92+
source: parseImportMode(value.source),
93+
};
94+
if (typeof value.imagePath === "string" && value.imagePath) {
95+
input.imagePath = path.resolve(value.imagePath);
96+
}
97+
if (value.startAt != null) {
98+
const startAt = Number(value.startAt);
99+
if (!Number.isFinite(startAt) || startAt < 0) {
100+
throw badRequest("startAt 必须是非负数字(秒)。");
101+
}
102+
input.startAt = startAt;
103+
}
104+
return input;
105+
}
106+
throw badRequest("input.type 必须是 image 或 video。");
107+
}
108+
54109
const hostKind = argValue("--host") ?? "codex";
55110
if (hostKind !== "codex" && hostKind !== "dsh") {
56111
console.error("--host 必须是 codex 或 dsh。");
@@ -192,6 +247,9 @@ function publicTheme(theme) {
192247
name: theme.name,
193248
type: theme.type,
194249
savedAt: theme.savedAt,
250+
...(typeof theme.sourceMode === "string"
251+
? { sourceMode: theme.sourceMode }
252+
: {}),
195253
...(theme.bundled ? { bundled: true } : {}),
196254
...(typeof theme.videoPositionSec === "number"
197255
? { videoPositionSec: theme.videoPositionSec }
@@ -312,6 +370,7 @@ const server = http.createServer(
312370
type: "image",
313371
imagePath: path.resolve(body.imagePath),
314372
};
373+
imageInput.source = parseImportMode(body.source);
315374
if (body.effects && typeof body.effects === "object") {
316375
imageInput.effects = body.effects;
317376
}
@@ -332,6 +391,7 @@ const server = http.createServer(
332391
type: "video",
333392
videoPath: path.resolve(body.videoPath),
334393
};
394+
videoInput.source = parseImportMode(body.source);
335395
if (typeof body.imagePath === "string" && body.imagePath) {
336396
videoInput.imagePath = path.resolve(body.imagePath);
337397
}
@@ -357,6 +417,25 @@ const server = http.createServer(
357417
send(res, result.ok ? 200 : 422, result);
358418
return;
359419
}
420+
if (req.method === "POST" && url === "/theme/apply") {
421+
const body = await readBody(req);
422+
if (typeof body.name !== "string" || !body.name.trim()) {
423+
send(res, 400, { ok: false, error: "必须提供主题名称。" });
424+
return;
425+
}
426+
if (typeof session.applyAndSaveTheme !== "function") {
427+
send(res, 501, { ok: false, error: "当前会话不支持应用并保存主题。" });
428+
return;
429+
}
430+
const input = parseThemeApplyInput(body.input);
431+
const result = await session.applyAndSaveTheme(input, body.name.trim());
432+
send(
433+
res,
434+
result.ok ? 200 : 422,
435+
result.ok ? { ...result, theme: publicTheme(result.theme) } : result,
436+
);
437+
return;
438+
}
360439
if (req.method === "POST" && url === "/theme/save") {
361440
const body = await readBody(req);
362441
if (typeof body.name !== "string" || !body.name.trim()) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# DSH 背景栏视觉方向说明
2+
3+
本次不是重做 DSH,也不是把背景功能扩张成独立的素材管理器。目标是让侧边栏里的「背景」入口更像一个稳定、可信、长期使用的本地工具:用户能在几秒内完成图片导入、视频导入、声音控制、清除背景和已保存主题切换;正在处理时知道系统在做什么;发生错误或超时时按钮一定恢复;同时不把绝对路径、技术协议或多余统计暴露给普通用户。背景栏仍然依附 DSH 左侧栏,不能抢过会话、模型和输入区的主层级。
4+
5+
受众是主要在 Windows 本机使用 DSH 的用户。观看距离约为普通笔记本 60–90 厘米,面板宽度应控制在 224–272 像素,正文不低于 13 像素,辅助标签不低于 11 像素。视觉温度需要冷静、可靠、轻微有人味,避免常见 AI 产品的紫蓝渐变、发光描边、Bento 卡片堆叠、每个动作都配一个装饰图标,以及过度圆润的胶囊按钮。颜色从真实「画窗」背景里的雨蓝、雾灰和 DSH 现有深色侧栏采样,收敛为一组中性灰阶加一个低饱和蓝;错误只在发生时使用克制的红色。字体沿用 DSH 系统字体,不额外下载字体。
6+
7+
内容结构固定为四层:第一层是当前背景和来源状态;第二层是最常用的图片、视频导入;第三层是声音、清除、皮肤中心等次级操作;第四层是已保存主题。主题列表只使用现有名称、媒体类型、来源类型和选中状态,不新增缩略图接口,不把本地路径送到网页。忙碌状态必须局部化:当前操作显示进度文本,其余按钮暂时不可用,但面板仍可关闭;45 秒客户端上限后恢复交互并说明原背景保持不变。原生文件选择器是用户控制的系统窗口,不套用该操作超时。
8+
9+
三个方向共享以上功能,但构图互异。方向 A 用包豪斯式规则线和编号建立明确秩序,强调“工具盒”;方向 B 最大程度融入 DSH 本体,把状态和动作做成低噪声的原生侧栏;方向 C 借鉴纸质媒体清单,把导入动作和已保存主题放在一条连续的纵向轨道里,强调主题切换效率。三版都不依赖新增后端能力,选定后只改 `console.js` 的结构和样式,不动 local 导入、事务或媒体服务协议。
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# DSH 背景栏方向确认
2+
3+
- 已评审:A「网格工具盒」、B「原生侧栏」、C「媒体清单」
4+
- 最终设计:`direction-c-media-ledger.html`、`direction-c-media-ledger.png`
5+
- 用户选择原话:`C吧`
6+
- 结论:正式背景栏采用 C「媒体清单」方向;保持现有 DSH 侧栏位置、local 零复制导入、主题切换和超时恢复语义。
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<!doctype html>
2+
<html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>方向 C · 媒体清单</title><style>
3+
*{box-sizing:border-box}html,body{margin:0;height:100%;font-family:"Segoe UI","Microsoft YaHei",sans-serif;color:#f1f3f4}body{overflow:hidden;background:#172231 url("../../integrations/deepseek-harness/themes/internal-beyond/bg-canvas-4k.png") center/cover no-repeat}.sidebar{position:absolute;inset:0 auto 0 0;width:274px;padding:18px 12px;background:rgba(15,24,35,.68);border-right:1px solid rgba(255,255,255,.13);backdrop-filter:blur(12px)}.brand{font-size:17px;font-weight:700}.brand small{font:9px ui-monospace,monospace;border:1px solid currentColor;padding:2px 4px}.new{margin-top:24px;width:100%;height:40px;border:1px solid rgba(255,255,255,.13);border-radius:5px;background:rgba(40,44,51,.76);color:inherit;font:600 14px inherit}.section{margin:20px 8px 8px;color:#bac3cc;font-size:13px}.session{height:34px;padding:7px 10px}.session.active{background:rgba(255,255,255,.09)}.bottom{position:absolute;left:8px;right:8px;bottom:12px}.panel{padding:0 14px 12px;background:#ece9e2;color:#202327;border-top:4px solid #252a30;box-shadow:0 16px 32px rgba(0,0,0,.3)}.head{display:flex;align-items:end;justify-content:space-between;padding:13px 0 11px;border-bottom:1px solid #b9b6af}.head h2{margin:0;font:650 16px Georgia,"Songti SC",serif}.head span{font:10px ui-monospace,monospace;color:#696d70}.import{display:grid;grid-template-columns:34px 1fr auto;align-items:center;min-height:48px;border-bottom:1px solid #c8c5be;background:transparent;color:inherit;width:100%;padding:0;text-align:left}.num{font:10px ui-monospace,monospace;color:#74787b}.import strong{display:block;font-size:13px}.import small{font-size:10px;color:#717579}.arrow{font-size:16px}.controls{display:flex;gap:12px;padding:9px 0;border-bottom:1px solid #c8c5be}.controls button{border:0;padding:0;background:transparent;color:#595e62;font:11px inherit;text-decoration:underline;text-underline-offset:3px}.label{padding:11px 0 5px;font:10px ui-monospace,monospace;color:#686d71;letter-spacing:.08em}.theme{display:grid;grid-template-columns:16px 1fr auto;align-items:center;height:31px;border-bottom:1px dotted #bbb8b1;font-size:12px}.theme:last-child{border:0}.theme .dot{font-size:10px}.theme.on{font-weight:650}.theme em{font:normal 9px ui-monospace,monospace;color:#777b7e}.nav{height:38px;margin-top:7px;padding:9px 11px;border-radius:7px;font-size:14px}.nav.on{background:rgba(255,255,255,.12);outline:1px solid rgba(255,255,255,.5)}.hero{position:absolute;left:52%;top:48%;transform:translate(-50%,-50%);font-size:24px;font-weight:650;text-shadow:0 1px 10px rgba(0,0,0,.5)}button{cursor:pointer}button:hover{opacity:.65}
4+
</style></head><body><aside class="sidebar"><div class="brand">deepseek <small>HARNESS</small></div><button class="new">+ 新会话</button><div class="section">工作区</div><div class="session active">新会话</div><div class="session">Session Title</div><div class="session">WoRk</div><div class="bottom"><section class="panel"><header class="head"><h2>背景清单</h2><span>画窗 / 已应用</span></header><button class="import"><span class="num">01</span><span><strong>导入图片</strong><small>直接引用本地文件</small></span><span class="arrow">→</span></button><button class="import"><span class="num">02</span><span><strong>导入视频</strong><small>MP4 · 零复制播放</small></span><span class="arrow">→</span></button><div class="controls"><button>声音已关</button><button>清除背景</button><button>打开皮肤中心</button></div><div class="label">SAVED / 03</div><div class="theme on"><span class="dot">●</span>画窗<em>内置</em></div><div class="theme"><span></span>芙莉莲 第一集<em>本地</em></div><div class="theme"><span></span>雨夜<em>本地</em></div></section><div class="nav on">▧ 背景</div><div class="nav">⚙ 设置</div></div></aside><div class="hero">探索未至之境</div></body></html>
113 KB
Loading

‎docs/deepseek-harness.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# DeepSeek Harness 集成
22

3-
beautiCode 通过 DeepSeek Harness 的 Cordis 插件接口接入(`@beauticode/dsh-plugin`),不修改 DSH 源码,也不依赖 Chromium 调试端口。DSH 由你自己启动;beautiCode 只挂插件、不替代、不重启你的 DSH。Codex Desktop 仍由托盘按原路径拉起,与本节无关。
3+
beautiCode 通过 DeepSeek Harness 的 Cordis 插件接口接入(`beauticode-dsh`),不修改 DSH 源码,也不依赖 Chromium 调试端口。DSH 由你自己启动;beautiCode 只挂插件、不替代、不重启你的 DSH。Codex Desktop 仍由托盘按原路径拉起,与本节无关。
44

55
## 已实现能力
66

@@ -57,7 +57,7 @@ npx @deepseek-ai/dsh plugin --profile web add file:%LOCALAPPDATA%\Programs\beaut
5757
```yaml
5858
- insert:
5959
- id: beauticode-bridge
60-
name: '@beauticode/dsh-plugin'
60+
name: 'beauticode-dsh'
6161
inject: [webServer]
6262
```
6363

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

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

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

5-
装好插件并运行 `dsh web` 后,侧栏「设置」上方会出现「背景」:可从文件夹选图片或 MP4、清除、开关声音、切换已保存主题。网页控制台没有摸鱼;浅色/深色跟 DSH 自己的外观走。下次打开会恢复上次背景。
5+
装好插件并运行 `dsh web` 后,侧栏「设置」上方会出现「背景」:在 Windows 上点击图片或视频会打开系统文件选择器,选好后在页面内命名,背景立即应用并进入已保存主题;也可以清除、开关声音、切换或删除主题,以及打开「皮肤中心」安装已审核的社区皮肤。本地导入只在 Node 端保存绝对路径,并通过带 Range 支持的回环媒体服务读取原文件,不复制用户选择的图片或整段视频主文件。Windows 强制使用本地引用;原生选择器不可用时会明确报错,不会静默上传或复制媒体。非 Windows 环境保留兼容上传,并明确提示该模式会保存托管副本。网页控制台没有摸鱼;浅色/深色跟 DSH 自己的外观走。下次打开会恢复上次背景。设置 `BEAUTICODE_SKIN_CENTER` 或填写 `skin-center.json` 后,皮肤中心才会显示远程目录。
66

77
插件也会注册对话工具(`beauticode_*`)和斜杠命令(`/bg`、`/bg-theme`、`/bg-clear`)。不需要托盘;托盘若已在跑则复用它。
88

@@ -40,7 +40,7 @@ npx @deepseek-ai/dsh web
4040

4141
手动接入时:
4242

43-
1. 修改 `cordis.patch.example.yml` 中的 `file:///.../index.mjs`。
43+
1. 修改 `cordis.patch.yml` 中的插件接入项;优先使用上面的安装命令自动完成接线。
4444
2. 确保 DSH 和 beautiCode 使用相同的 `BEAUTICODE_DATA_ROOT`。
4545
3. 自己运行 `dsh web`(或带 `--patch`)。
4646
4. 打开页面后用侧栏「背景」,或输入 `/bg <本机绝对路径>`,或直接跟 AI 说把某个视频/图片设为背景。

0 commit comments

Comments
 (0)