[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-105367":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":17,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":20,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":29,"readmeContent":30,"aiSummary":10,"trendingCount":15,"starSnapshotCount":15,"syncStatus":31,"lastSyncTime":32,"discoverSource":33},105367,"dsh-chat-wallpaper","LeeRolling\u002Fdsh-chat-wallpaper","LeeRolling","给 DeepSeek Harness 的开场视频 + 聊天底图插件","https:\u002F\u002Fwww.bilibili.com\u002Fvideo\u002FBV1wspE6EE8b",null,"JavaScript",65,6,54,0,5,15,51.54,"MIT License",false,"main",true,[24,25,26,27,28],"deepseek-harness","dsh","intro","plugin","wallpaper","2026-11-01 00:15:12","# dsh-chat-wallpaper\n\n[English](README.en.md) · **中文**\n\n> 给 [DeepSeek Harness](https:\u002F\u002Fgithub.com\u002Fdeepseek-ai) 的**开场视频 + 聊天底图**插件。\n>\n> 开机动画放完之后，全屏接一段你自己的视频当\"第二幕\"；放完淡出、交回聊天窗口。\n> 聊天窗口背后的底图由你自己定 —— 换图只要丢张图片进一个文件夹。\n\n🎬 **效果演示（B 站，37 秒）：\u003Chttps:\u002F\u002Fwww.bilibili.com\u002Fvideo\u002FBV1wspE6EE8b>**\n\n```\n   开机动画（你的 dsh-startup-screen）\n        ↓  交叉叠化（不是硬切，也不是闪一下）\n   全屏开场视频（盖住聊天窗口）\n        ↓  淡出\n   聊天窗口 + 你的底图\n```\n\n**面板、卡片、代码块全程保持不透明** —— 底图再花也不影响读字。\n\n---\n\n## 目录\n\n- [三个层，各管一件事](#三个层各管一件事)\n- [它怎么做到\"背景而不覆盖\"](#它怎么做到背景而不覆盖)\n- [交叉叠化：这个插件里最难的一段](#交叉叠化这个插件里最难的一段)\n- [安装](#安装)\n- [换视频 \u002F 换底图](#换视频--换底图)\n- [设置面板](#设置面板)\n- [配置项](#配置项)\n- [诊断与工具](#诊断与工具)\n- [测试](#测试)\n- [踩过的坑（都留了回归测试）](#踩过的坑都留了回归测试)\n- [致谢与来源](#致谢与来源) ⭐\n- [许可](#许可)\n\n---\n\n## 三个层，各管一件事\n\n```\n   z-index 2147482990  ┌─ #dsh-chat-wallpaper ─ 开场视频（placement=\"front\"）\n                       │   开机动画收场后的【第二幕】：全屏盖住聊天窗口\n                       │   播完 → 淡出 → 移除 → 进入聊天\n                       └───────────────────────────────────────────────\n         正常内容       │  聊天界面 \u002F 侧栏 \u002F 输入框\n                       └───────────────────────────────────────────────\n            z-index -1  ┌─ #dsh-cw-banner ─ 大字横幅（可选）\n                       │   铺满窗口的一行大字（矢量文字，不是图片）\n                       └───────────────────────────────────────────────\n            z-index -2  ┌─ #dsh-cw-bg ─ 聊天底图 + 纱（可选）\n                       │   你自己定的一张图，聊天就落在它上面\n                       └───────────────────────────────────────────────\n```\n\n**三层互不依赖**：\n\n| 你配了什么 | 结果 |\n|---|---|\n| 只配视频 | 开机 → 全屏开场演一遍 → 淡出 → 回到 DSH 默认底色 |\n| 只配底图 | 没有开场，聊天直接落在你那张图上 |\n| 只配大字 | 没有开场，聊天背后是铺满窗口的一行大字 |\n| 视频 + 底图 + 大字 | **开场在前演，演完淡出 → 露出\"聊天 + 你的底图 + 那行大字\"** |\n\n> 大字放在 `z-index:-1`（底图之上、聊天内容之下）—— 所以它**不挡聊天文字** ✓\n> 而且用的是**真文字**不是图片：矢量，放多大都不糊 ✓\n\n---\n\n## 它怎么做到\"背景而不覆盖\"\n\n只有两处\"魔法\"：\n\n```css\n\u002F* 1) 把外壳底色变量改透明。面板\u002F卡片\u002F代码块用的是**别的**变量，一律不动，\n      所以文字永远落在实心底上，可读性一点不损失。 *\u002F\nhtml body {\n  --dsw-alias-bg-base: transparent;\n  --dsw-specific-sidebar-fill: rgba(255, 255, 255, .78);   \u002F* 侧栏半透 *\u002F\n}\n\n\u002F* 2) 底图放 z-index:-1 —— 在所有正常流内容之下，且不拦点击 *\u002F\n#dsh-cw-bg { position: fixed; inset: 0; z-index: -1; pointer-events: none; }\n```\n\n上面再压一层**纱**（`linear-gradient`）：浅色主题压白纱、深色主题压深纱。\n\n> 主题判定**不猜 DSH 内部的标记名**：JS 先扫 `html`\u002F`body` 上所有属性找 `dark`，\n> 再兜底量一次外壳底色亮度，然后把结果写成**自己的 class**（`dsh-cw-dark` \u002F `dsh-cw-light`），\n> CSS 只读这个 class。这样 DSH 内部标记怎么改名都不影响。\n\n---\n\n## 交叉叠化：这个插件里最难的一段\n\n**问题**：开机动画的结尾是淡出，开场视频的开头如果也淡入，**两段淡的交界处两层都不够实**，\n中间就会闪出聊天窗口。\n\n**做法**：**让别人的淡出变成我的叠化** —— 在他开始淡的那一瞬间，我已经满不透明地待在他下面。\n\n这需要精确知道他什么时候开始淡。我们读了 `dsh-startup-screen` 的源码，它的收尾是**两步**：\n\n```js\n\u002F* dsh-startup-screen\u002Flib\u002Fsplash.js —— 揭幕 *\u002F\nroot.classList.add('dsu-handoff')   \u002F\u002F ★ 第 1 步：根元素【开始】淡出\nawait wait(780)                      \u002F\u002F   整整 780ms\nfinish()                             \u002F\u002F 第 2 步：这才加 dsu-gone（再淡 620ms）\n```\n\n```css\n\u002F* dsh-startup-screen\u002Flib\u002Fsplash.css:791 *\u002F\n#dsh-startup-root.dsu-handoff {\n  transform: scale(1.035);\n  filter: blur(5px);\n  opacity: 0;                                        \u002F* ★ 这里就开始透了 *\u002F\n  transition: opacity 780ms cubic-bezier(.4, 0, .2, 1), ...;\n}\n```\n\n**所以：**\n\n```\nt=0      dsu-handoff  → 开始淡出（780ms，带推进 + 失焦的运镜）↘\n                                                                ← 我已经满不透明地等在下面\nt=780    dsu-gone     → （此时早就透明了）\nt=1400   根元素被移除\n```\n\n> ⚠️ **只盯 `dsu-gone` 会晚 780ms** —— 那 780ms 里开机动画一路在变透明、\n> 已经在把聊天窗口透出来了，用户看到的就是\"闪一下\"。**这是我们踩过的坑。**\n\n信号 class 是可配置的（`bootLeaveClasses`），换别的开机动画插件时改这一行即可。\n\n**代价（诚实说明）**：叠化意味着视频在淡出过程中就已经开播，\n所以片头最前面约 0.4～0.7 秒会有部分被正在淡出的开机动画盖着。\n这是\"绝不闪屏\"的取舍 —— 我们认为值得。\n\n第二处衔接（视频 → 你的底图）同理：视频层淡出的**同时**底图在下面逐渐露出，\n本身就是叠化，不用额外处理。\n\n---\n\n## 安装\n\n```bash\n# 1) 装插件（把 \u003C本仓库路径> 换成你 clone 下来的位置）\ndsh plugin --profile \u003C你的 profile> add link:\u003C本仓库路径>\n\n# 2) 重启 DSH（见「踩过的坑」最后两条：改 lib\u002F*.js 之后必须重启，不能只刷新）\n```\n\n> 本插件**没有构建步骤**：`lib\u002Findex.js`（宿主半边）和 `lib\u002Fclient.js`（浏览器半边）\n> 都是手写的、直接可加载的文件。\n\n---\n\n## 换视频 \u002F 换底图\n\n**换视频** —— 丢进这个文件夹就会自动用（按修改时间，最新的赢）：\n\n```\n~\u002F.dsh\u002Fboot-animation\u002Fvideos\u002F\n```\n\n> ⚠️ **桌面版（Electron）用户请用 VP9\u002FWebM**。桌面版 Electron 不带 H.264 解码器，\n> 片库的 mp4 一放就是 `PIPELINE_ERROR_DECODE`（code 3）。插件现在的处理是：\n> 只撤视频层、保住底图\u002F横幅，并在日志里给出提示。转一遍即可：\n>\n> ```\n> ffmpeg -i in.mp4 -c:v libvpx-vp9 -b:v 0 -crf 30 -an out.webm\n> ```\n>\n> Web 端（浏览器）没有这个限制，mp4 \u002F webm 都能放。\n\n**换底图** —— 丢进这个文件夹就会自动用：\n\n```\n~\u002F.dsh\u002Fchat-wallpaper\u002F\n```\n\n支持 `jpg \u002F jpeg \u002F png \u002F webp \u002F gif \u002F avif \u002F bmp`。\n**不丢图** → 开场播完淡出后，回到 DSH 默认底色。\n\n也可以不用文件夹，两个都在配置里指定绝对路径（见下）。\n\n---\n\n## 设置面板\n\n**入口：设置 →「聊天背景」**（DSH 设置弹层左侧导航最后几项）—— 就是全部设置：\n\n```\n┌─ 聊天背景 ──────────────────────────────────┐\n│ 当前：我的背景.jpg                           │\n│ 丢图目录：…\u002F.dsh\u002Fchat-wallpaper              │\n│                                             │\n│ [缩略图][缩略图][缩略图]                      │  ← 点一下即换\n│                                             │\n│ [不用图片]   [打开图片文件夹]                 │  ← 后者直接弹资源管理器\n│                                             │\n│ 纱的浓度（深色主题）  50%                     │\n│ ▬▬▬▬▬●▬▬▬▬▬                                 │  ← 拖完立刻生效，不用刷新\n│                                             │\n│ 大字横幅（铺满窗口的一行字）                   │\n│ [人类与AI的日常              ]                │  ← 直接在这里改文字\n│ 横幅浓度  18%                                │\n│ ▬▬▬●▬▬▬▬▬▬▬                                 │\n│                                             │\n│ 开场视频：● 全屏开场：播一次 → 淡出 → 进聊天    │\n│           ○ 常驻背景：在聊天窗口后面一直循环    │\n└─────────────────────────────────────────────┘\n```\n\n**设置页独立于壁纸层**（自己的根元素 + 自己的 style 标签）——\n所以开场播完、视频层被移除之后，设置页照样能从「设置」打开；\n设置弹层关掉时页面 DOM 会卸载，下次打开原样接回，不会重建。\n\n---\n\n## 配置项\n\n`~\u002F.dsh\u002Fchat-wallpaper.json`（**改配置只需刷新页面**；改代码要重启）：\n\n```jsonc\n{\n  \"video\": \"\",                    \u002F\u002F 绝对路径；空 = 自动（扫 ~\u002F.dsh\u002Fboot-animation\u002Fvideos\u002F）\n  \"objectFit\": \"cover\",           \u002F\u002F 常驻背景模式下用；全屏开场固定 cover\n  \"opacity\": 1,                   \u002F\u002F 视频层不透明度\n  \"playbackRate\": 1,              \u002F\u002F 1 = 正常速度\n\n  \u002F\u002F 视频放哪\n  \"placement\": \"front\",           \u002F\u002F front = 全屏盖在最前面（第二幕）| behind = 放后面当背景\n\n  \u002F\u002F 播完之后\n  \"mode\": \"once\",                 \u002F\u002F once = 播一次 → 淡出 → 进聊天 | loop = 常驻循环（配 behind）\n  \"fadeOutMs\": 1200,              \u002F\u002F once 的淡出时长\n\n  \u002F\u002F 聊天底图（独立于视频）：留空 = 自动用 ~\u002F.dsh\u002Fchat-wallpaper\u002F 里最新那张\n  \"image\": \"\",\n  \"imageFit\": \"cover\",\n\n  \u002F\u002F 大字横幅：铺满窗口的一行大字（矢量文字，不是图片）。留空 = 不要\n  \u002F\u002F 字号自动算（先设 100px 量一次宽度，再按窗口等比放大），中英混排也准\n  \"banner\": \"人类与AI的日常\",\n  \"bannerOpacity\": 0.12,          \u002F\u002F 建议 0.08 ~ 0.25：够醒目，又不挡聊天文字\n\n  \u002F\u002F 只在 mode=\"loop\" 时用得上：第一次从头播完，之后只在 [loopStart, loopEnd] 里循环\n  \u002F\u002F loopStart 可以直接写剪辑软件的时间码，宿主按 fps 换算成秒\n  \"loopStart\": \"00:00:05:23\",\n  \"loopEnd\": \"\",                  \u002F\u002F 留空 = 到视频结尾\n  \"fps\": 24,\n\n  \u002F\u002F 什么时候开始播：等开机动画收场再播（否则片头会被开机动画盖过去）\n  \"waitForBoot\": true,\n  \u002F\u002F 一轮会话只放一次（和开机动画同一个策略，它也记 sessionStorage）。\n  \u002F\u002F 为什么需要：保存 client.js 会触发插件热重载 = 一次刷新，\n  \u002F\u002F 没这个标记的话开场会被反复重播。想再看 → 设置 →「聊天背景」→「🔁 重播开场」。\n  \"oncePerSession\": true,\n  \"bootOverlaySelectors\": [\"#dsh-startup-root\"],\n  \u002F\u002F 开机动画\"开始离场\"的信号 class —— 决定叠化时机，换插件时改这里\n  \"bootLeaveClasses\": [\"dsu-handoff\", \"dsu-gone\"],\n\n  \u002F\u002F 纱（底图上的可读性保险）：浅色主题压白纱、深色主题压深纱\n  \"veilLightA\": \"rgba(253,250,254,.80)\",\n  \"veilLightB\": \"rgba(250,247,253,.68)\",\n  \"sidebarLight\": \"rgba(255,255,255,.78)\",\n  \"fallbackLight\": \"#f7f1f8\",\n  \"veilDarkA\": \"rgba(8,10,16,.50)\",\n  \"veilDarkB\": \"rgba(6,8,14,.38)\",\n  \"sidebarDark\": \"rgba(22,24,32,.74)\",\n  \"fallbackDark\": \"#0b0d12\"\n}\n```\n\n> 只改配置 \u002F 换图 \u002F 用设置页 → **刷新页面即可**（但注意：在 Electron 的 DevTools 里\n> 要先按 `F12` 打开开发者工具，`Ctrl+R` 才会真正绕过缓存）。\n\n---\n\n## 诊断与工具\n\n| 端点 | 用途 |\n|---|---|\n| `GET \u002Fchat-wallpaper\u002Fstatus` | 现在解析到哪个视频\u002F哪张图、来源、丢图目录、循环时间码换算成多少秒 |\n| `GET \u002Fchat-wallpaper\u002Fconfig` | 客户端实际收到的配置 |\n| `GET \u002Fchat-wallpaper\u002Fimages` | 设置面板用：图清单 + 当前选中 |\n| `GET \u002Fchat-wallpaper\u002Fvideo` | 视频流（带 Range 支持 —— `\u003Cvideo>` 需要它） |\n| `GET \u002Fchat-wallpaper\u002Fimage` | 底图（`?name=xxx` 可指定丢图目录里的某一张） |\n\n浏览器控制台里所有日志都带 `[chat-wallpaper]` 前缀，第一行是 **`client build cw-N 已加载`**\n—— 出问题时先看这个号，一眼分清\"代码有问题\"还是\"浏览器跑的是旧包\"。\n\n**两个开箱可用的检查工具**（不需要装 ffmpeg）：\n\n```bash\n# 看视频规格：真实分辨率 \u002F 帧率 \u002F 时长 \u002F 是否 faststart \u002F 编码 \u002F 关键帧位置\nnode test\u002Finspect-mp4.mjs \"你的视频.mp4\"\n\n# 只看帧率（读 stts 表，判定是恒定帧率还是可变帧率）\nnode test\u002Fprobe-fps.mjs \"你的视频.mp4\"\n```\n\n> 这两个是纯 Node 的 MP4 盒解析器：分辨率取 `tkhd` \u002F `stsd`，帧率取 `stts`，\n> faststart 看 `moov` 是否在 `mdat` 之前，关键帧读 `stss`。\n> **循环点如果恰好落在关键帧上，跳转才是无缝的** —— 用它们查过再决定要不要用循环模式。\n\n---\n\n## 测试\n\n**九个测试套件，全部不需要启动 DSH**（用 `node:vm` + 手写的 DOM 桩）：\n\n```bash\nnpm test\n```\n\n| 套件 | 守什么 |\n|---|---|\n| `smoke-client` | CSS 生成、主题判定（含\"透明底不能当纯黑\"那条） |\n| `smoke-mount` | **挂载幂等**（防\"点一下窗口背景闪一下并从 0 重播\"）+ 循环区间 |\n| `smoke-start` | **起始时机闸门**：开机动画期间**层都不许挂**；`dsu-handoff` 一到就上场 |\n| `smoke-once` | `once` 播完 → 淡出 → 进聊天；两层解耦；**复活回归**；front 模式不吞点击 |\n| `smoke-decode` | **解码失败优雅降级**：code 3 只撤视频层、底图\u002F横幅留住；加载失败仍全撤 |\n| `smoke-timecode` | `HH:MM:SS:FF` → 秒的换算（含交叉验证） |\n| `smoke-panel` \u002F `smoke-panel-client` | 设置面板：列图、选中态、**面板不被壁纸收场带走** |\n| `smoke-host` | Cordis 契约（只认 `default` 导出） |\n\n### 红绿对照：怎么证明回归测试真的抓得住 bug\n\n**这一步是本仓库测试方法的重点。**\n\n写回归测试时最容易犯的错是：**测试通过，但其实根本没走到 bug 那条路上**。\n所以我们准备了一个对照工具：\n\n```bash\n# 造一个\"故意没修\"的副本（去掉 teardown 里的 current = null）\nnode test\u002Fmake-nofix.mjs\n\n# 拿它跑同一个测试 —— 应该【变红】\nnode test\u002Fsmoke-once.mjs test\u002Fclient.nofix.js\n```\n\n`test\u002Fmake-nofix.mjs` 会生成 `test\u002Fclient.nofix.js`（已被 `.gitignore` 忽略）。\n**如果它跑出来还是绿的，说明这条测试没在测它该测的东西** ——\n我们就是这样发现了两个\"看起来通过、其实什么都没证明\"的测试。\n\n---\n\n## 踩过的坑（都留了回归测试）\n\n| 坑 | 症状 | 根因 |\n|---|---|---|\n| **壁纸\"复活\"** | 淡出看到了，但动画还在后面**一直 loop**，而且不再跟在开机动画后面 | `teardown()` 没清 `current`；更根本的是主题观察者里那句 `if (!mounted) applyNow(current)` —— 层一被移除它就**把壁纸重新挂起来**。**现在观察者只许换主题 class，绝不许挂载。** |\n| **开机时机的几何误判** | 一进界面就在放，片头白做 | 用\"零尺寸就算已收场\"判断开机浮层 —— 而浮层刚插进 DOM 时往往就是零尺寸。改成只认它自己的 class。 |\n| **全屏层吞掉所有点击** | 点哪都在控制动画，界面没法操作 | 给全屏层加了 `click → 跳过`。**全屏层永远 `pointer-events: none`。** |\n| **点一下就开播** | 鼠标一点视频就播，用户没法操作 | 加了\"第一次用户手势补一次 `play()`\"。**全屏开场必须自动播、自动收，不能把点击当开关。** |\n| **对未加载的 video 设 currentTime** | 全屏层停在第一帧、不播、盖住界面，直到看门狗才收 | 对还没 `loadedmetadata` 的元素设 `currentTime` 会让它卡在 seek 状态、`play()` 永不生效。**只在 `readyState >= 1` 时设；并先预加载。** |\n| **叠化晚了 780ms** | 开机动画与视频之间闪一下聊天窗口 | 只盯 `dsu-gone`，而它**开始**淡出是更早的 `dsu-handoff`（780ms）。 |\n| **改代码之后只刷新** | `web boot: 1 entry did not activate`，应用起不来 | 在宿主**运行期间**改插件客户端文件 → 宿主登记表的 `rev` 过期 → 404 → 入口没激活 → DSH 拒绝启动。**改 `lib\u002F*.js` → 重启；改配置\u002F换图 → 刷新。** 启动失败时用对话框里的「禁用第三方插件、备份 profile patch 并重启」兜底。 |\n| **测试没在测该测的东西** | 回归测试全绿，但 bug 照样发作 | 测试直接调内部函数、绕过了真实入口（`applyNow` 才是设 `current` 的地方）。**红绿对照**才查出来。 |\n| **桌面版解码 H.264 失败，壁纸陪葬** | 日志一声\"视频解码失败（code 3）\"，视频和底图、横幅**一起消失** | 桌面版 Electron **不带 H.264 解码器**，片库的 mp4 一放就是 `PIPELINE_ERROR_DECODE`。旧实现对所有 `error` 无差别 `teardown()` —— 可底图和横幅是无辜的。**现在 code 3 只撤视频层**（复用 finishOnce 的\"有底图就留 CSS\"那套），日志给出转码命令；加载失败（文件真不在）仍是全撤。红绿对照：`git show v0.2.2:lib\u002Fclient.js > old.js && node test\u002Fsmoke-decode.mjs old.js` 应当变红。 |\n| **package.json 是 GBK 编码** | Node 24 下 `npm test` 直接 `ERR_INVALID_PACKAGE_CONFIG`，一个套件都跑不了 | 文件被某版工具按 GBK 写过，中文描述的字节不是合法 UTF-8，Node 的包配置读取器直接拒收。**整个文件重写为 UTF-8**（内容不变），顺手把测试链补上 `smoke-decode`。 |\n\n---\n\n## 致谢与来源\n\n这个插件的两个关键做法**不是我们想出来的**，而且它**依赖另一个插件的内部约定**。\n在此逐条说清楚：\n\n### 1. [`KylinQ01\u002Fdsh-startup-animation`](https:\u002F\u002Fgithub.com\u002FKylinQ01\u002Fdsh-startup-animation) — MIT\n\n**用到了：**「把外壳底色改透明，从而让背景露出来」这个核心手法。\n本插件的 `--dsw-alias-bg-base: transparent` + `--dsw-specific-sidebar-fill` 那套写法，\n以及\"面板\u002F卡片用的是别的变量、所以文字不受影响\"这个判断，都来自该项目已验证过的实现。\n\n**改动：** 我们没有复制它的代码，但**照搬了这个手法**，并在此基础上加了\n\"两套纱（浅色\u002F深色）\"和\"自己写主题 class 而不猜 DSH 的内部标记\"这两层。\n\n### 2. [`dsh-startup-screen`](https:\u002F\u002Fgithub.com\u002F6shenhonghong9\u002Fdsh-startup-screen) — 开机动画插件\n\n**用到了：** 它的**内部约定**。本插件通过观察 `#dsh-startup-root` 是否带有\n`dsu-handoff` \u002F `dsu-gone` 来判断\"开机动画什么时候开始收场\"，从而实现交叉叠化；\n`780ms` \u002F `620ms` 这两个时间常数也是读它的 `splash.js` \u002F `splash.css` 得到的。\n\n**这是耦合，不是复制。** 所以信号 class 做成了可配置项（`bootLeaveClasses`）——\n一旦上游改了这组 class 名，改配置即可，不必改代码。感谢作者把动画做得这么细，\n尤其是 `dsu-handoff` 那一步（推进 + 失焦）—— 叠化之所以好看，功劳在它。\n\n### 3. [`NativeDog1\u002Fdsh-boot-animation`](https:\u002F\u002Fgithub.com\u002FNativeDog1\u002Fdsh-boot-animation)\n\n**用到了：** 本项目开发过程中用作开场素材的那段赛博朋克视频**来自该项目的素材库**，\n并由使用者自行超分到 2560×1440。\n\n**⚠️ 本仓库不包含任何视频、音频、图片素材。** 想用哪段视频请自备。\n\n### 4. [DeepSeek Harness](https:\u002F\u002Fgithub.com\u002Fdeepseek-ai)\n\n宿主平台本身。宿主半边的写法（`ctx.webServer.register` 路由、`cordis.patch.yml` 的\nbundle patch 层、`dsh.client` 浏览器半边约定）都来自 DSH 的插件规范。\n\n### 声明\n\n- 本仓库**没有复制任何第三方代码**，全部实现为独立编写；\n- **零媒体**：不含任何视频 \u002F 音频 \u002F 图片 \u002F 字体 \u002F 二进制；\n- 上面每一条\"用到了\"都写进了 `lib\u002Fclient.js` 与 `lib\u002Findex.js` 的注释里 ——\n  改这些代码时请保留出处说明。\n\n**如果你要用这个项目里的做法，也请把上面这几位一起 @ 上。**\n用了别人的，就说出来。\n\n---\n\n## 许可\n\n[MIT](LICENSE) © 2026 LeeRolling\n",2,"2026-10-31 04:26:33","CREATED_QUERY"]