🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

宠物乐园 BBDooooog/dsh-pet-market

DeepSeek Harness
BBDooooog7 天前有提交已提供中文文档扫描:含敏感能力

装素材包,让序列帧宠物住到 Windows 桌面上

30.5/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add BBDooooog/dsh-pet-market
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · market
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/03·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 7 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 73 处,展示前 66 条)
  • 发起网络请求
    client.js:239
    return fetch(urlFor(path), init).then((res) => res.text().then((text) => parseEnvelope(text, res.status)))
  • 发起网络请求
    client.js:243
    return fetch(urlFor(API + 'import?filename=' + encodeURIComponent(filename)), {
  • 写入本地文件
    lib/ledger.js:33
    mkdirSync(path, { recursive: true })
  • 读取本地文件
    lib/ledger.js:39
    if (!existsSync(path)) return fallback
  • 读取本地文件
    lib/ledger.js:40
    const text = readFileSync(path, 'utf8').replace(/^ FEFF/, '')
  • 写入本地文件
    lib/ledger.js:51
    writeFileSync(tmp, JSON.stringify(value, null, 2), 'utf8')
  • 写入本地文件
    lib/ledger.js:53
    renameSync(tmp, path)
  • 写入本地文件
    lib/ledger.js:56
    writeFileSync(path, JSON.stringify(value, null, 2), 'utf8')
  • 删除本地文件
    lib/ledger.js:57
    rmSync(tmp, { force: true })
  • 删除本地文件递归
    lib/ledger.js:190
    rmSync(entry.dir, { recursive: true, force: true })
  • 删除本地文件递归
    lib/ledger.js:213
    rmSync(entry.dir, { recursive: true, force: true })
  • 写入本地文件
    lib/ledger.js:224
    appendFileSync(join(store.paths.logs, 'market.log'), line + '\n', 'utf8')
  • 读取本地文件
    lib/ledger.js:234
    for (const petId of readdirSync(store.paths.packs)) {
  • 读取本地文件
    lib/ledger.js:236
    for (const version of readdirSync(packPath)) {
  • 读取本地文件
    lib/ledger.js:253
    const stat = statSync(path)
  • 读取本地文件
    lib/ledger.js:255
    for (const name of readdirSync(path)) total += dirSize(join(path, name))
  • 读取本地文件
    lib/runtime.js:14
    for (const name of readdirSync(rel ? join(dir, rel) : dir)) {
  • 读取本地文件
    lib/runtime.js:17
    const stat = statSync(full)
  • 读取本地文件
    lib/runtime.js:72
    for (const name of names) files[name] = readFileSync(join(descriptor.dir, name))
  • 读取本地文件
    lib/install.js:28
    for (const name of readdirSync(dir)) {
  • 读取本地文件
    lib/install.js:32
    const stat = statSync(full)
  • 读取本地文件
    lib/install.js:36
    collected[childRel] = readFileSync(full)
  • 删除本地文件递归
    lib/install.js:163
    rmSync(job.stageDir, { recursive: true, force: true })
  • 写入本地文件
    lib/install.js:193
    mkdirSync(store.tmpDir(job.jobId), { recursive: true })
  • 读取本地文件
    lib/install.js:217
    if (!existsSync(path)) throw new MarketError('source-invalid', 'no such file: ' + path)
  • 读取本地文件
    lib/install.js:218
    const stat = statSync(path)
  • 读取本地文件
    lib/install.js:222
    const buffer = readFileSync(path)
  • 删除本地文件递归
    lib/install.js:263
    rmSync(stageDir, { recursive: true, force: true })
  • 写入本地文件
    lib/install.js:264
    mkdirSync(stageDir, { recursive: true })
  • 写入本地文件
    lib/install.js:269
    mkdirSync(join(target, '..'), { recursive: true })
  • 写入本地文件
    lib/install.js:270
    writeFileSync(target, files[name])
  • 写入本地文件
    lib/install.js:272
    writeFileSync(
  • 写入本地文件
    lib/install.js:281
    mkdirSync(join(targetDir, '..'), { recursive: true })
  • 删除本地文件递归
    lib/install.js:288
    rmSync(targetDir, { recursive: true, force: true })
  • 删除本地文件递归
    lib/install.js:296
    rmSync(stageDir, { recursive: true, force: true })
  • 删除本地文件递归
    lib/install.js:302
    rmSync(backupDir, { recursive: true, force: true })
  • 读取本地文件
    lib/router.js:46
    if (!existsSync(uiPath)) return { positions: {}, names: {}, nameFonts: {}, nameStyles: {}, active: null }
  • 读取本地文件
    lib/router.js:47
    const value = JSON.parse(readFileSync(uiPath, 'utf8'))
  • 写入本地文件
    lib/router.js:56
    mkdirSync(store.root, { recursive: true })
  • 写入本地文件
    lib/router.js:57
    writeFileSync(uiPath, JSON.stringify(next, null, 2), 'utf8')
  • 读取本地文件
    lib/router.js:160
    if (!existsSync(full) || !statSync(full).isFile()) return sendFail(res, 404, 'asset-missing', clean)
  • 读取本地文件
    lib/router.js:160
    if (!existsSync(full) || !statSync(full).isFile()) return sendFail(res, 404, 'asset-missing', clean)
  • 读取本地文件
    lib/router.js:161
    const body = readFileSync(full)
  • 读取本地文件
    lib/desktop-stage.js:40
    if (!existsSync(full)) return null
  • 读取本地文件
    lib/desktop-stage.js:45
    const bytes = readFileSync(full)
  • 读取本地文件
    lib/desktop-stage-wpf.js:64
    const manifest = JSON.parse(readFileSync(join(dir, 'pet.json'), 'utf8'))
  • 读取本地文件
    lib/desktop-stage-wpf.js:178
    if (existsSync(file)) {
  • 读取本地文件
    lib/desktop-stage-wpf.js:179
    const existing = readFileSync(file, 'utf8').trim()
  • 写入本地文件
    lib/desktop-stage-wpf.js:187
    mkdirSync(dirname(file), { recursive: true })
  • 写入本地文件
    lib/desktop-stage-wpf.js:188
    writeFileSync(file, token, { mode: 0o600 })
  • 写入本地文件
    lib/desktop-stage-wpf.js:256
    mkdirSync(dirname(statePath), { recursive: true })
  • 写入本地文件
    lib/desktop-stage-wpf.js:260
    writeFileSync(statePath, wire, 'utf8')
  • 读取本地文件
    lib/desktop-stage-wpf.js:282
    if (!existsSync(pidFile)) return
  • 读取本地文件
    lib/desktop-stage-wpf.js:283
    const record = JSON.parse(readFileSync(pidFile, 'utf8'))
  • 写入本地文件
    lib/desktop-stage-wpf.js:353
    appendFileSync(errLog, String(chunk))
  • 读取本地文件
    lib/hash.js:11
    const stream = createReadStream(path)
  • 读取密钥环境变量
    lib/download.js:45
    const token = process.env.GITHUB_TOKEN || process.env.GH_TOKEN
  • 发起网络请求
    lib/download.js:59
    const response = await fetch(url, {
  • 写入本地文件
    lib/download.js:109
    mkdirSync(dirname(dest), { recursive: true })
  • 写入本地文件
    lib/download.js:128
    await pipeline(source, createWriteStream(dest))
  • 删除本地文件
    lib/download.js:131
    rmSync(dest, { force: true })
  • 删除本地文件
    lib/download.js:140
    rmSync(dest, { force: true })
  • 读取本地文件
    lib/github.js:44
    if (!existsSync(path)) return null
  • 读取本地文件
    lib/github.js:46
    const value = JSON.parse(readFileSync(path, 'utf8'))
  • 写入本地文件
    lib/github.js:58
    mkdirSync(cacheDir, { recursive: true })
  • 写入本地文件
    lib/github.js:59
    writeFileSync(join(cacheDir, key + '.json'), JSON.stringify({ fetchedAt: Date.now(), release }), 'utf8')
扫描于 2026/11/3(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DeepSeek Harness 的桌宠乐园:序列帧宠物包市场 + 系统桌面画家(WPF)。装素材包,宠物就住到 Windows 桌面上。

README

由 DeepSeek 最新模型翻译生成
宠物乐园 · dsh-pet-market DeepSeek Harness 的桌宠乐园:把一串 GitHub 链接(或者一个现成的 .dsppet)粘进面板,序列帧宠物就住到你的 Windows 桌面上——透明置顶、会走会停、能拖动、点一下会撒欢。 市场是分发管道,不是商店;格式是契约,不是审核。 宠物的长相、动作、脾气都归作者和素材包;市场只回答两个问题:文件合不合规、能不能跑起来。 它是什么 - 一个 DSH 插件(Host + Client 两半,零运行时依赖),装上后左侧栏出现「宠物乐园」入口,也出现在 设置 → 宠物乐园。 - 一个序列帧宠物市场:装的是素材包,不是程序。包是纯数据(zip + JSON + PNG/WebP),永不执行包里的 JS。 - 一个系统桌面画家:宠物画在真正的 Windows 桌面上(WPF 透明置顶窗口),不在 DSH 窗口里。DSH 关掉、页面刷新、换标签页,宠物都还在。 - 一套公开的包格式:sprite-sequence/v1。作者在自己的仓库发布 .dsppet,谁都可以装,不需要经过我们。
展开完整文档(README 剩余 1 节)
宠物乐园 · dsh-pet-market

DeepSeek Harness 的桌宠乐园:把一串 GitHub 链接(或者一个现成的 .dsppet)粘进面板,序列帧宠物就住到你的 Windows 桌面上——透明置顶、会走会停、能拖动、点一下会撒欢。

市场是分发管道,不是商店;格式是契约,不是审核。
宠物的长相、动作、脾气都归作者和素材包;市场只回答两个问题:文件合不合规、能不能跑起来。

它是什么

- 一个 DSH 插件(Host + Client 两半,零运行时依赖),装上后左侧栏出现「宠物乐园」入口,也出现在 设置 → 宠物乐园。
- 一个序列帧宠物市场:装的是素材包,不是程序。包是纯数据(zip + JSON + PNG/WebP),永不执行包里的 JS。
- 一个系统桌面画家:宠物画在真正的 Windows 桌面上(WPF 透明置顶窗口),不在 DSH 窗口里。DSH 关掉、页面刷新、换标签页,宠物都还在。
- 一套公开的包格式:sprite-sequence/v1。作者在自己的仓库发布 .dsppet,谁都可以装,不需要经过我们。

三分钟上手

一行装好(需要 pnpm 在 PATH 里,npm i -g pnpm 一行搞定):

dsh plugin --profile desktop add github:BBDooooog/dsh-pet-market#v0.1.6

然后完全退出 DSH 再启动(Host 半只在启动时挂载)。这条命令做完三件事:把插件写进 profile 的 dependencies、加进 dsh.profile.bundles、装好 node_modules。

想跟着 main 的最新提交走,去掉 #v0.1.6:dsh plugin --profile desktop add github:BBDooooog/dsh-pet-market。

改代码调试用 link::

git clone https://github.com/BBDooooog/dsh-pet-market.git
dsh plugin --profile desktop add link:D:/AI/dsh/dsh-pet-market
dsh plugin --profile desktop install

重启后:

1. 左侧栏点「宠物乐园」。
2. 输入 BBDooooog/dsh-pet-market —— 它会自己找到最新 release 里的 .dsppet,下载、校验、登记。
3. 宠物出现在列表里(默认在窝里,不占桌面),点「出来玩」它才上场。
4. 名字旁的 ✎ 可以改名(回车即存);「看看它」进详情页:契约、动作逐帧预览、右键菜单、事件反应、来源与 sha256。

只想知道后端在不在:http://127.0.0.1:<port>/petmarket/api/health,端口每次启动都可能变(看 DSH 窗口地址或启动日志)。

四条装宠物的路

| 你手上有什么 | 面板里怎么填 | 走哪条链路 |
| 一个 GitHub 仓库 | owner/repo、owner/repo@v1.2.0、owner/repo#pet.dsppet | 解析 release → 挑资产 → 下载 → 校验 digest → 校验格式 |
| 一条 release 直链 | https://github.com/OWNER/REPO/releases/download/v1.0.0/pet.dsppet | 不碰 GitHub API,直接下载(未认证 API 限流 60 次/小时时照样能用) |
| 已经下好的包 | 把 .dsppet / .zip 拖进面板,或点一下选文件 | 本地读取 → 校验 → 登记 |
| 正在开发的目录 | local:D:/packs/pixel-cat | 读目录 → 校验 → 登记(作者自测用) |

一个 release 带多只宠物时,用 owner/repo#pixel-cat-1.2.0.dsppet 指定装哪一只;给 DSH 配好环境变量 GITHUB_TOKEN 后,API 限额从 60 次/小时升到 5000 次/小时(token 只发给 api.github.com,资产走预签名链接时不带)。

装进市场 ≠ 上桌面:带一只回家 只登记素材,出来玩 才画窗口。想回到「装完直接出场」,把 config.activateOnInstall 设成 true。

桌面上的宠物会做什么

- 走路:待机 3–9 秒,随机朝左或朝右走 1.8–4.2 秒(46 dip/s),撞到屏幕边缘掉头,朝向不对时自动水平镜像(包里的 renderer.front 说了算)。
- 点一下:切到包里 states.happy 指向的动作(演示包都指向 run)并朝一边窜出去 140–230 px,跑完回待机。
- 拖动:按住走哪拖哪,松手记位置(ui.json),下次还在那儿。
- 缩放:面板上 − 4x +,以底边中点为锚点原地变大变小,1x–8x;不会把别的宠物挤走。
- 右键:固定一项「回窝睡觉」,下面跟「动作」子菜单(包里没有动作就不出现),样式是圆角的浅色小卡片。
- 名字:画在头顶,字号默认跟着缩放走;详情页可以调字号、底色、字体,底色深浅会自动决定文字黑白。
- 安全兜底:置顶每 180 ms 重新断言一次;画家意外退出按 min(30s, 1.5s × n) 退避重启;宿主没了画家自己退出(watchdog);只有一个画家进程能拿到 stage.lock。

做一个自己的宠物

宠物包就是一个 zip(后缀 .dsppet),最少这些文件:

pixel-cat/
├── pet.json # 身份 + 渲染 + 动作 + 状态 + 菜单 ├── manifest.json # 包描述(profile 版本、体积、文件表) ├── market.json # 商店里给人看的(标签、缩略图、changelog) ├── thumbnail.png # 列表缩略图 ├── animations/cat.png # 图集:3 行 × 6 列,单帧 40×34 └── checksums.json # 每个文件的 sha256(不含自己)

pet.json 的核心长这样:

{
"schema": 1,
"id": "pixel-cat",
"version": "1.2.0",
"name": "Pixel Cat",
"engines": { "petRuntime": "^1" },
"renderer": {
"type": "sprite",
"mode": "sheet",
"image": "animations/cat.png",
"frame": { "w": 40, "h": 34 },
"front": "left",
"animations": {
"idle": { "row": 0, "frames": 2, "fps": 6, "loop": true },
"walk": { "row": 1, "frames": 6, "fps": 10, "loop": true },
"run": { "row": 2, "frames": 6, "fps": 14, "loop": false, "next": "idle" }
},
"states": { "idle": "idle", "walk": "walk", "happy": "run" }
}
}

发布只要三步:仓库里放包源目录 → 打 tag(v1.2.0)→ CI 打出 pixel-cat-1.2.0.dsppet 附到 release。别人在面板里填 你的名字/你的仓库 就能装。完整字段、坐标公式、体积预算、错误码见 docs/PACK-FORMAT.md。

仓库自带的两个工作流可以直接抄:
- .github/workflows/release-packs.yml:打 tag 自动打包 + 跑测试 + 上传资产。

仓库里有什么

dsh-pet-market/
├── index.js # Host 半入口(cordis 插件:ctx.effect / ctx.provide) ├── client.js # Client 半:侧栏入口 + 主面板 + 详情页 + 页内舞台 ├── lib/ │ ├── router.js # /petmarket/api/(同源校验、SSE、台账读写、stage token) │ ├── install.js # 作业队列:解析 → 下载 → 校验 → 暂存 → 原子提交 → 注册 │ ├── pack.js # 包校验器(schema、图集几何、体积预算、错误码) │ ├── zip.js / hash.js # 纯 JS zip 读解 + sha256 │ ├── sources.js # 输入解析(owner/repo、release 链接、local: 路径) │ ├── github.js # release 解析、资产挑选、directAsset 免 API 路径 │ ├── download.js # 流式下载 + digest 比对 + 限流退避 │ ├── ledger.js # ~/.dsh/petmarket 下的台账与版本目录 │ ├── runtime.js # 宿主桥:pethost 契约 → 旧 dshpets → local │ └── desktop-stage-wpf.js # 系统桌面画家(state.json + token + powershell 进程) ├── stage/ # 画家的前端:desktop-pet.ps1(WPF)、stage.html/js(Electron 分支) ├── demo/ # 两个演示宠物 + 打包脚本(可复现 sha256) ├── docs/ # 架构、模块、包格式、来源解析、评审记录 └── test/run.mjs # 23 项测试(节点原生 test runner,零依赖)

演示宠物

| 宠物 | 包 | 体积 | sha256 |
| Pixel Cat(黑猫警长) | pixel-cat-1.2.0.dsppet | 5886 B | 653fd273f4409cb565dfcae98ed97095a786b9b850859a09055919aa618db202 |
| Yellow Dog | yellow-dog-1.1.0.dsppet | 6200 B | eaa376de55bcaa7c505e8c50510ce98def97cf8095d5743634b6dddba756a57d |
猫的素材来自 OpenGameArt 的 Cat sprites(Shepardskin,CC0 1.0),重新切成图集并补了 renderer.front;黄狗是用 Pillow 画出来的(二十行像素,随仓库授权)。demo/packs/yellow-dog-2/ 留作多宠共存测试,不发布。

python demo/tools/build-assets.py # GIF 帧 → 猫图集(作者侧依赖 Pillow)
python demo/tools/build-dog-assets.py # 画黄狗图集
node demo/build-demo-pack.mjs # 猫目录 → .dsppet(自校验)
node demo/build-dog-pack.mjs # 黄狗目录 → .dsppet
node test/run.mjs # 23 项测试

打包采用固定 UTC 时间戳(2020-01-01)+ 不压缩存储:同样源目录在任何机器、任何 Node 版本、任何时区打出来的 sha256 完全一致(CI 与本机逐字节相同)——release 的 digest、台账、安装时的比对才能串成一条链。

架构

flowchart LR
U[用户] --> P[宠物乐园面板sidebar.panellist + main]
P -->|/petmarket/api/| API[Host 半router + installer]
API --> GH[GitHub release]
API --> FS[(~/.dsh/petmarketpacks / ledger / ui.json)]
API -->|state.json + token| STAGE[桌面画家desktop-pet.ps1 · WPF]
STAGE --> OS[操作系统桌面]
API -.->|pethost 契约| HOST[宿主插件]

三层边界:core 是纯函数(校验、解析、哈希),Host 半是唯一碰网络和磁盘的地方,Client 半只走 HTTP + SSE。想细看:

- docs/ARCHITECTURE.md — 目标、非目标、信任边界、三条主流程、状态机、MVP 切分
- docs/MODULES.md — 模块职责、端口接口、Host API 全表、SSE 事件、DSH 插件形态的硬约束
- docs/PACK-FORMAT.md — sprite-sequence/v1 全部字段与播放语义
- docs/SOURCES.md — GitHub 输入形态、资产挑选、digest 链、限流与离线
- docs/REVIEW.md — 决策表与开放选择(含每条推荐)

出了状况先看这里

| 症状 | 原因 | 处理 |
| 面板一片空白 / 提示「后端未加载」 | Host 半还没挂载,/petmarket/api/* 全是 404 | 完全退出 DSH 再启动;curl .../petmarket/api/health 应返回 {"ok":true,...} |
| 桌面没有宠物,但列表里有 | 它还在窝里(active=false),或者画家退出了 | 点「出来玩」;看 health.desktop.reason(running / exited / storage-degraded) |
| 宠物被别的窗口盖住 | 对方也是置顶窗口 | 画家每 180 ms 重新置顶;极端情况重启 DSH |
| 走路方向反了 | 素材原生朝向和 renderer.front 不一致 | 包里的 renderer.front 写 left 或 right(台账缺字段时画家会直接读包内 pet.json) |
| 装 GitHub 链接报 github-rate-limited | 未认证 API 每小时 60 次 | 改用 release 直链(走 directAsset,不碰 API) |
| 装包报 digest-mismatch | 资产被重新上传过 | 让作者重打一次包;本仓的打包脚本已固定时间戳 |

更多排错路径:README 故障一节、docs/SOURCES.md 的失败表。

路线图

- [x] 序列帧包格式 v1 + 校验器 + 体积预算
- [x] GitHub 仓库 / release 直链 / 本地文件 / 本地目录 四条安装路径
- [x] 系统桌面画家(WPF),多宠共存、拖动、缩放锚点、右键菜单、改名
- [x] 详情页:契约、逐帧动作预览、菜单、事件反应、来源校验
- [ ] 包内多宠物(一个 release 带一套 collection)
- [ ] 可选 Ed25519 签名(现在只有哈希链)
- [ ] 目录索引仓库(dsh-pet-index)与可搜的发现页
- [ ] macOS / Linux 画家(现在只有 Windows 的 WPF 分支)

贡献

- 发现 bug、想要新字段、想加一种渲染 profile:开 issue,附上 health 输出与 <root>/stage/stage.log。
- 做了一只宠物想被收录:在 issue 里贴仓库链接 + release 链接 + 一张缩略图,我们只核对格式与可运行性。
- 提 PR 前跑 node test/run.mjs(23 项,零依赖,秒级)。

授权

- 代码:MIT(见 LICENSE)。
- 演示素材:pixel-cat 来自 OpenGameArt 的 CC0 作品;yellow-dog / yellow-dog-2 为本仓库原创,随仓库授权。
- 你的宠物:版权归你,授权由你在包里的 LICENSE.txt 写清楚——市场不替你决定。

给同路人:桌宠不该是「每只宠物一个独立程序」。宠物是数据,运行时是平台的,市场是管道。这个仓库就是那条管道的第一个实现。
预览分享卡片长什么样 ↓BBDooooog/dsh-pet-market
分享 · DeepSeek Harness Hub
BBDooooog/dsh-pet-market

装素材包,让序列帧宠物住到 Windows 桌面上

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部