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

Live2D 桌宠 cyanfish-x/dsh-live2d-pets

DeepSeek Harnessv0.3.0
cyanfish-x40 天前有提交已提供中文文档扫描:含敏感能力

Live2D 桌宠插件,用于 DeepSeek Harness:镜像智能体状态 + 互动陪伴,内置宽松许可预设模型

45.5/100
综合分
26
GitHub 星标
1,152
npm 周下载
—/5
用户评分

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-live2d-pets
npm 源 · dsh-live2d-pets 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · ui
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 40 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-live2d-pets @ 0.3.0
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/30 04:31:56

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

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

读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 92 处,展示前 77 条)
  • 读取本地文件
    lib/index.js:126
    const st = statSync(p);
  • 读取本地文件
    lib/index.js:128
    const files = readdirSync(p).filter((f) => f.toLowerCase().endsWith(".model3.json"));
  • 读取本地文件
    lib/index.js:158
    if (!existsSync(file)) return null;
  • 读取本地文件
    lib/index.js:209
    const presetsData = parseJsonc(readFileSync(join(packageRoot(), "src/presets/presets.jsonc"), "utf8"));
  • 写入本地文件
    lib/index.js:428
    mkdirSync(dirname(this.path), { recursive: true });
  • 写入本地文件
    lib/index.js:432
    if (!existsSync(this.path) && existsSync(legacyPath)) copyFileSync(legacyPath, this.path);
  • 读取本地文件
    lib/index.js:432
    if (!existsSync(this.path) && existsSync(legacyPath)) copyFileSync(legacyPath, this.path);
  • 读取本地文件
    lib/index.js:435
    if (!existsSync(this.path)) writeFileSync(this.path, PERSONAS_TEMPLATE, "utf8");
  • 写入本地文件
    lib/index.js:435
    if (!existsSync(this.path)) writeFileSync(this.path, PERSONAS_TEMPLATE, "utf8");
  • 写入本地文件
    lib/index.js:545
    mkdirSync(dirname(this.path), { recursive: true });
  • 写入本地文件
    lib/index.js:548
    if (!existsSync(this.path)) writeFileSync(this.path, CUSTOM_MODELS_TEMPLATE, "utf8");
  • 写入本地文件
    lib/index.js:607
    writeFileSync(this.path, serializeCustomModels(normalized), "utf8");
  • 发起网络请求
    lib/client.js:543
    const res = await fetch(url);
  • 发起网络请求
    lib/client.js:1114
    const response = await fetch(SETTINGS_API);
  • 发起网络请求
    lib/client.js:1124
    const response = await fetch(SETTINGS_API, {
  • 发起网络请求
    lib/client.js:1138
    const response = await fetch(CUSTOM_MODELS_API);
  • 发起网络请求
    lib/client.js:1148
    const response = await fetch(CUSTOM_MODELS_API, {
  • 发起网络请求
    lib/client.js:1191
    const response = await fetch(STATE_API);
  • 写入剪贴板
    lib/client.js:1201
    await navigator.clipboard.writeText(text);
  • 发起网络请求
    src/client/index.ts:260
    state: (): Promise<PetStateView> => fetch(`${PET_API}/state`).then((res) => readJson<PetStateView>(res)),
  • 发起网络请求
    src/client/index.ts:276
    fetch(`${PET_API}/set-display`, {
  • 发起网络请求
    src/client/index.ts:978
    const res = await fetch(url)
  • 发起网络请求
    src/client/settings.ts:125
    const res = await fetch(url)
  • 发起网络请求
    src/client/settings.ts:745
    const response = await fetch(SETTINGS_API)
  • 发起网络请求
    src/client/settings.ts:756
    const response = await fetch(SETTINGS_API, {
  • 发起网络请求
    src/client/settings.ts:775
    const response = await fetch(CUSTOM_MODELS_API)
  • 发起网络请求
    src/client/settings.ts:790
    const response = await fetch(CUSTOM_MODELS_API, {
  • 发起网络请求
    src/client/settings.ts:842
    const response = await fetch(STATE_API)
  • 写入剪贴板
    src/client/settings.ts:853
    await navigator.clipboard.writeText(text)
  • 写入本地文件
    src/custom-models.ts:86
    mkdirSync(dirname(this.path), { recursive: true })
  • 读取本地文件
    src/custom-models.ts:91
    if (!existsSync(this.path)) writeFileSync(this.path, CUSTOM_MODELS_TEMPLATE, 'utf8')
  • 写入本地文件
    src/custom-models.ts:91
    if (!existsSync(this.path)) writeFileSync(this.path, CUSTOM_MODELS_TEMPLATE, 'utf8')
  • 读取本地文件
    src/custom-models.ts:101
    text = readFileSync(this.path, 'utf8')
  • 写入本地文件
    src/custom-models.ts:138
    writeFileSync(this.path, serializeCustomModels(normalized), 'utf8')
  • 写入本地文件
    src/local-models.test.ts:27
    writeFileSync(model, '{}', 'utf8')
  • 删除本地文件递归
    src/local-models.test.ts:32
    rmSync(dir, { recursive: true, force: true })
  • 写入本地文件
    src/local-models.test.ts:39
    writeFileSync(join(dir, 'a.model3.json'), '{}', 'utf8')
  • 写入本地文件
    src/local-models.test.ts:40
    writeFileSync(join(dir, 'b.model3.json'), '{}', 'utf8')
  • 删除本地文件递归
    src/local-models.test.ts:45
    rmSync(dir, { recursive: true, force: true })
  • 写入本地文件
    src/local-models.test.ts:54
    writeFileSync(model, '{}', 'utf8')
  • 写入本地文件
    src/local-models.test.ts:55
    writeFileSync(secret, 'secret', 'utf8')
  • 删除本地文件递归
    src/local-models.test.ts:60
    rmSync(dir, { recursive: true, force: true })
  • 写入本地文件
    src/local-models.test.ts:68
    writeFileSync(model, '{}', 'utf8')
  • 删除本地文件递归
    src/local-models.test.ts:71
    rmSync(dir, { recursive: true, force: true })
  • 读取本地文件
    src/local-models.ts:26
    const st = statSync(p)
  • 读取本地文件
    src/local-models.ts:28
    const files = readdirSync(p).filter((f) => f.toLowerCase().endsWith('.model3.json'))
  • 读取本地文件
    src/local-models.ts:56
    if (!existsSync(file)) return null
  • 读取本地文件
    src/models-host.ts:67
    readFileSync(join(packageRoot(), 'src/presets/presets.jsonc'), 'utf8'),
  • 删除本地文件递归
    src/persist.test.ts:16
    rmSync(dir, { recursive: true, force: true })
  • 写入本地文件
    src/persist.test.ts:25
    writeFileSync(join(dir, 'live2d-pet.json'), JSON.stringify({ right: 100, bottom: 50, size: 220 }))
  • 写入本地文件
    src/persist.test.ts:30
    writeFileSync(join(dir, 'live2d-pet.json'), JSON.stringify({ right: -10, bottom: 99999, size: 1e9 }))
  • 写入本地文件
    src/persist.test.ts:35
    writeFileSync(join(dir, 'live2d-pet.json'), '{oops')
  • 读取本地文件
    src/persist.test.ts:44
    expect(JSON.parse(readFileSync(join(dir, 'live2d-pet.json'), 'utf8'))).toEqual({ right: 30, bottom: 40, size: 180 })
  • 读取本地文件
    src/persist.ts:48
    const raw = JSON.parse(readFileSync(petFile(), 'utf8')) as Partial<PetDisplay>
  • 写入本地文件
    src/persist.ts:62
    writeFileSync(petFile(), JSON.stringify(display, null, 2), 'utf8')
  • 写入本地文件
    src/personas.test.ts:13
    mkdirSync(join(home, 'live2d-pet'), { recursive: true })
  • 删除本地文件递归
    src/personas.test.ts:17
    rmSync(home, { recursive: true, force: true })
  • 读取本地文件
    src/personas.test.ts:61
    expect(existsSync(file)).toBe(true)
  • 读取本地文件
    src/personas.test.ts:62
    const text1 = readFileSync(file, 'utf8')
  • 写入本地文件
    src/personas.test.ts:66
    writeFileSync(file, '{"personas":[{"id":"mine","name":"我"}]}', 'utf8')
  • 读取本地文件
    src/personas.test.ts:68
    expect(readFileSync(file, 'utf8')).toBe('{"personas":[{"id":"mine","name":"我"}]}')
  • 写入本地文件
    src/personas.test.ts:73
    writeFileSync(join(home, 'live2d-pet', 'personas.jsonc'), JSON.stringify({
  • 写入本地文件
    src/personas.test.ts:89
    writeFileSync(file, '{"personas":[{"id":"good"}]}', 'utf8')
  • 写入本地文件
    src/personas.test.ts:92
    writeFileSync(file, '{ 坏掉的 json', 'utf8')
  • 写入本地文件
    src/personas.test.ts:99
    writeFileSync(join(home, 'live2d-pet', 'personas.jsonc'), '{"personas": 42}', 'utf8')
  • 写入本地文件
    src/personas.ts:145
    mkdirSync(dirname(this.path), { recursive: true })
  • 写入本地文件
    src/personas.ts:152
    if (!existsSync(this.path) && existsSync(legacyPath)) copyFileSync(legacyPath, this.path)
  • 读取本地文件
    src/personas.ts:152
    if (!existsSync(this.path) && existsSync(legacyPath)) copyFileSync(legacyPath, this.path)
  • 读取本地文件
    src/personas.ts:158
    if (!existsSync(this.path)) writeFileSync(this.path, PERSONAS_TEMPLATE, 'utf8')
  • 写入本地文件
    src/personas.ts:158
    if (!existsSync(this.path)) writeFileSync(this.path, PERSONAS_TEMPLATE, 'utf8')
  • 读取本地文件
    src/personas.ts:168
    text = readFileSync(this.path, 'utf8')
  • 写入本地文件
    src/routes.test.ts:48
    mkdirSync(join(dir, 'assets', 'vendor'), { recursive: true })
  • 写入本地文件
    src/routes.test.ts:49
    writeFileSync(join(dir, 'assets', 'vendor', 'pixi.min.js'), 'fake-pixi-js')
  • 删除本地文件递归
    src/routes.test.ts:74
    const cleanup = () => { delete process.env.DSH_HOME; rmSync(dir, { recursive: true, force: true }) }
  • 读取本地文件
    src/routes.ts:293
    return readFile(file).then((body) => {
  • 读取本地文件
    src/routes.ts:320
    return readFile(join(packageRoot, 'assets', file.name)).then((body) => {
  • 删除本地文件递归
    src/service.test.ts:44
    rmSync(process.env.DSH_HOME!, { recursive: true, force: true })
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

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

依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-host-webserver@deepseek-ai/dsh-session@deepseek-ai/dsh-settings@deepseek-ai/dsh-tool-present@deepseek-ai/dsh-user-approval
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

2 张 · 点击查看大图

功能亮点

  • Agent状态镜像
  • 互动陪伴
  • 内置预设模型
v0.3.02026-09-24
· Highlights · 适配 DSH 0.1.5 系列(rc.1–rc.3):依赖矩阵对齐官方插件模式;DSH ≤0.1.0-rc.6 不再受支持 · 恢复「↗ 一键直达打开」:自定义人设 / 内置模型清单 / 自定义模型文件三处入口,经 DSH 0.1.5 会话远程面(session/openWorkspacePath)用系统默认程序打开;能力被部署策略关闭时自动回退「复制路径/模板」弹层 · 新增「交付庆祝」状态:模型通过 present 工具交付文件时,宠物播放庆祝动画并说人设化交付台词(约 3.5 秒后回到空闲);交付后紧随的轮次结束不会打断庆祝 · 动画映射新增「交付庆祝」槽位(9→10)、台词池新增 delivered(13→14):六种内置人设各配交付台词,自定义人设与动画映射无需迁移 · 调试面板「演示状态」新增 delivered 按钮 · 兼容版本 · 要求 DSH ≥ 0.1.5-rc.1,在 0.1.5-rc.3(当前 latest)上验证通过 · DSH ≤ 0.1.0-rc.6 不再受支持(dsh-client-runtime 已随包移除,peer 解析与类型检查均失败) · 升级 DSH 后执行 dsh --profile web update dsh-live2d-pets(或重新 add)即可 Full Changelog:
v0.2.22026-08-16
· Highlights · 新增自定义模型「动画映射」:可把模型原生动作组挂到状态/互动部位 · 新增开发者选项总开关与调试面板改进 · 内置模型配置改为 JSONC(presets.jsonc),支持注释 · 自定义人设迁移到 $DSH_HOME/live2d-pet/personas.jsonc`n- 自定义模型迁移到 $DSH_HOME/live2d-pet/custom-models.jsonc,不再写入 settings.yaml · 修复动作播放优先级与 focus 抑制问题 · 调试面板支持模型原生动画列表预览(逐条播放) · 设置面板布局优化:组标题右侧链接、动画映射双列、tab 式展开
v0.2.12026-08-16
· ✨ 核心特性 · 鼠标跟随:宠物会平滑看向页面上的鼠标位置,头部、眼睛和身体都会跟随;鼠标移出页面后回到正视前方。拖拽时不会乱转,隐藏或页面失焦时自动停止跟随。 · 🔧 问题修复 无用户可见问题修复。 · 📦 其他 · README 与英文版更新:补充插件定位、徽标与引导截图;压缩主视觉图片。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-live2d-pets 🐾 给 DeepSeek Harness 请了个看板娘:你思考它歪头,你完成它撒花,还能摸头! 特性 - 模型加载:内置 5 条策展模型(Hiyori / Haru / Mao / Mark / Natori)+ 自定义条目;可用任意 .model3.json 的 https / http URL,或填写本机绝对路径(如 C:/models/foo/foo.model3.json,由插件 Host 转成同源 HTTP 加载);自定义模型可配置动画映射,把模型原生动作组挂到状态/互动部位 - 状态镜像:宠物实时反映 agent 思考 / 空闲 / 出错 / 完成 / 交付 / 等审批(动画 + 气泡,SSE 推送) - 人设台词:内置六种人设(傲娇 / 元气 / 天然呆 / 三无 / 温柔治愈 / 病娇),可在插件独有 JSONC 中自定义并热切换 - 互动陪伴:分部位触摸反应 / 鼠标跟随(头、眼、身体看向鼠标)/ 拖动停靠,任务完成庆祝;HitArea 不足时按包围盒五矩形空间回退分档
展开完整文档(README 剩余 1 节)
dsh-live2d-pets 🐾

给 DeepSeek Harness 请了个看板娘:你思考它歪头,你完成它撒花,还能摸头!

特性

- 模型加载:内置 5 条策展模型(Hiyori / Haru / Mao / Mark / Natori)+ 自定义条目;可用任意 .model3.json 的 https / http URL,或填写本机绝对路径(如 C:/models/foo/foo.model3.json,由插件 Host 转成同源 HTTP 加载);自定义模型可配置动画映射,把模型原生动作组挂到状态/互动部位
- 状态镜像:宠物实时反映 agent 思考 / 空闲 / 出错 / 完成 / 交付 / 等审批(动画 + 气泡,SSE 推送)
- 人设台词:内置六种人设(傲娇 / 元气 / 天然呆 / 三无 / 温柔治愈 / 病娇),可在插件独有 JSONC 中自定义并热切换
- 互动陪伴:分部位触摸反应 / 鼠标跟随(头、眼、身体看向鼠标)/ 拖动停靠,任务完成庆祝;HitArea 不足时按包围盒五矩形空间回退分档
- 桌宠配置设置面板:DSH 设置 →「桌宠配置」,开关 / 尺寸 / 渲染帧率 / 人设 / 模型列表 / 开发者选项;标量设置写入 ~/.dsh/settings.yaml,自定义人设与自定义模型存于 ~/.dsh/live2d-pet/ 插件私有 JSONC 文件,即时生效
- 不打扰:默认右下角、小尺寸、可拖动、可隐藏、标签页隐藏暂停渲染、限帧渲染、低配降级静态头像

快速开始

方式一:复制提示词让 agent 安装(推荐)

把下面这段提示词复制给你的 DSH agent(在 Web GUI 对话中直接粘贴即可),它会自己安装并验证:

请帮我安装 dsh-live2d-pets 插件(DSH 的 Live2D 桌宠插件):
1. 执行 dsh plugin --profile web add dsh-live2d-pets 安装
2. 执行 dsh plugin --profile web list,确认 dsh-live2d-pets 出现在已安装列表中
3. 告诉我安装结果;如果失败,请附上错误信息

方式二:手动安装

在终端执行(web profile 首次使用时自动初始化):

dsh plugin --profile web add dsh-live2d-pets

安装后插件默认启用。启动 DSH:

dsh web

浏览器打开后,右下角会出现默认宠物(尺寸 160px)。当前默认模型为 Hiyori(Live2D 官方示例模型),首次加载需联网。

互动

- 鼠标跟随:默认开启。鼠标在页面任意位置移动时,宠物的头、眼睛、身体会平滑看向鼠标;鼠标移出页面后复位正视前方。拖拽中不跟随,隐藏或页面失焦时自动暂停。
- 触摸互动:摸头 / 摸腿 / 摸手 / 摸身体各有专属台词与动作;模型 HitArea 不足时按包围盒空间分区回退。
- 拖动:按住宠物拖动到任意位置,松手后停靠并持久化。

自定义模型:打开设置 →「桌宠配置」→「我的模型」,填写名称与 .model3.json 地址(外网 CDN、自建静态站、本机 HTTP 服务,或本机绝对路径如 C:/models/foo/foo.model3.json 均可;本地路径由插件 Host 通过 /pet-local-models/... 同源路由加载)。可展开 「空间分区覆盖」 按字段微调五矩形(头/身/腿居中列 + 左右臂;0–1,留空用默认),或展开 「动画映射」 实时解析模型动作组,为状态/互动部位选择动作组;建议配合开发者选项「显示点击分区」对照色块。内置 Hiyori 已带居中分区预设。

配置设置

打开 DSH 设置 →「桌宠配置」,改完立刻生效,无需重启。

- 显示:开关宠物
- 尺寸:40–400px(默认 160)
- 渲染帧率:30 / 60 / 不限制(默认 30)
- 人设台词:切换内置或自定义人设;「自定义人设 ↗」编辑 $DSH_HOME/live2d-pet/personas.jsonc,改完点「↻ 重新读取」
- 模型:选内置策展模型,或在「我的模型」添加名称 + .model3.json URL(可选空间分区覆盖 / 动画映射);自定义模型存于 $DSH_HOME/live2d-pet/custom-models.jsonc
- 开发者选项:总开关(默认关);开启后可显示调试面板(含模型原生动画列表预览)、显示点击分区色块

卸载

dsh plugin --profile web remove dsh-live2d-pets

文档

| 需求 | 文档 |
| 英文 README | README.en.md |
| 产品意图 | docs/intent/live2d-pet-plugin.md |
| 行为规格 | docs/spec/live2d-pet-v01.md |
| 架构决策 | docs/adr/(渲染栈见 ADR-003) |
| 调研记录 | docs/research/(设置面板接入机制见 settings-tab.md) |

技术栈

- pixi-live2d-display 0.4.0 + PixiJS 6.5.10 + Cubism Core 4(ADR-003)
- 客户端渲染在 DSH Web GUI 的 shell.overlay 悬浮层(视觉层 Popover 顶层,ADR-005),设置页注册在 settings.section(ADR-002)
- 状态推送:Host 订阅 agent/* 事件 → 同源 SSE /api/live2d-pet/events(ADR-006);标签页隐藏 / 失焦暂停渲染
- 设置持久化:标量设置走 Host ctx.settings(~/.dsh/settings.yaml 用户层覆盖 base);自定义人设 ~/.dsh/live2d-pet/personas.jsonc、自定义模型 ~/.dsh/live2d-pet/custom-models.jsonc 由插件直接读写;传输走插件自身 API /api/live2d-pet/settings(settingsScope wire 白名单限制,见 research 3.4/3.5)

许可

- 插件代码:MIT
- 模型清单:模型一律 URL 直载、不随包分发;清单门槛为「许可可标注」——每条记录许可类型与链接,NC(禁止商用)模型标注"仅限非商用"(清单见 src/presets/presets.jsonc)
- 内置模型 Hiyori / Haru / Mao / Mark / Natori:Live2D 官方示例模型,按示例模型条款使用(免费商用可,需标注著作权)
- Live2D SDK:按 Live2D 官方条款(免费商用,需遵守版权声明等)
预览分享卡片长什么样 ↓cyanfish-x/dsh-live2d-pets
分享 · DeepSeek Harness Hub
cyanfish-x/dsh-live2d-pets

Live2D 桌宠插件,用于 DeepSeek Harness:镜像智能体状态 + 互动陪伴,内置宽松许可预设模型

这是你的仓库?认领条目

回到顶部