> 🇨🇳 简体中文 | 🇬🇧 [English](./README.md)

# dsh-plugin-ascension

一个悬浮在 dsh web 界面里的《仙逆》王林修炼伙伴。它**实时监控 LLM 会话状态并驱动动画**（思考 = 掐诀推演，工具调用 = 施展神通，回复 = 凝神书字，完成 = 突破飞跃，失败 = 反噬受伤），并且**随你的使用一路修炼升境**（凝气 → 筑基 → 结丹 → 元婴 → 化神 → 婴变 → 问鼎），境界越高皮肤越华丽。

> 状态监控、状态机、亲和力/修为经济三个纯逻辑模块，移植并重新主题化自 [`@linxin666/dsh-pet`](https://www.npmjs.com/package/@linxin666/dsh-pet)（MIT）。

## 安装

```bash
# 方式一（推荐）：从 npm 安装
dsh plugin --profile web add dsh-plugin-ascension

# 方式二：从 GitHub 安装
dsh plugin --profile web add github:d-ouyang/dsh-plugin-ascension

# 本地开发：dsh plugin --profile web add ./dsh-plugin-ascension
```

安装后重启 web 服务（`:3080`）。

## 功能

### 状态监控（宠物把 LLM 正在做什么"演"出来）

宿主订阅官方会话事件流（`ctx.on('session/event')`），映射为 7 个相位、驱动 9 条动画轨道：

| 相位 | 触发 | 气泡文案 | 动画轨道 | 雪碧图行号 | 帧 |
|---|---|---|---|---|---|
| idle | 停止 / 无会话 | 停止修炼 | stand | 6 | 雪碧图（站姿占位） |
| waiting | 开始/入定/等待输入/被阻断 | 凝神入定 · 静待机缘 | meditation | — | meditation.webp（✅ 真实） |
| thinking | LLM 推理 | 掐诀推演 · 参悟神通结果 | running | 7 | 雪碧图（✅ 真实） |
| tool | 工具调用 | 正在施展神通 · 还有 N 道神通未了 | running | 7 | 雪碧图（占位） |
| review | 流式回复 | 凝神书字 · 整理心得 | running | 8 | 雪碧图（占位） |
| done | 一轮完成 | 圆满出关！ | running-right | — | dragon.webp（✅ 真实，雷龙庆祝） |
| failed | 工具报错 / 中断 / token 耗尽 | 神通反噬 · 心魔反噬 · 灵力枯竭 | stand | 6 | 雪碧图（站姿占位） |

- 相位持续期间动画**乒乓循环**（0→1→…→n→…→1→0）
- done 庆祝窗口：普通完成 **3 秒**、突破境界 **6 秒**（`celebrateMs`，由 `onStatus` 的 opts 传入）

### 修为与境界

- 每完成一轮对话 +1（修炼）；点击宠物 +1（论道，3 分钟冷却）；喂丹药 +1（30 秒冷却）
- 7 重境界（凝气 → 筑基 → 结丹 → 元婴 → 化神 → 婴变 → 问鼎），阈值在 `ascension-core.js` 的 `REALMS` 里可配
- **升境触发突破动画并自动切换到下一境皮肤**；缺皮肤的境回退到上一境皮肤

### 交互与效果

| 交互 | 效果 |
|---|---|
| 点击宠物 | 论道（+修为，上方或左侧弹出反馈气泡） |
| 拖拽宠物 | 移动位置（持久化到配置） |
| 悬停宠物 | 古风面板：境界徽章 + 修为进度条 + 丹药/隐藏按钮 |
| 点击隐藏 | 王林**缩入天逆珠**（右下角）；珠子循环播放金木水火土旋转渐变 |
| 点击珠子 | 王林**从珠中重新现身**（先播动画，配置异步同步） |

- 悬停时气泡移到宠物**左侧**，不与面板重叠
- 所有过渡乐观渲染，不等待 API 返回

### 设置分区（设置 → 渡劫飞升）

底部带**保存 / 取消**的整宽表单（保存时生效）：

- **启动**：总开关，关闭后停止监控与动画
- **隐藏宠物**：显示/隐藏宠物本体
- 称呼、皮肤、尺寸（60–400 px）、距右侧 / 距底部

### 工具

在对话里问：*"王林现在什么境界？"* → `ascension_status` 返回境界 / 修为 / 距下一境 / 论道与丹药次数 / 当前动画。

## 制作皮肤（重要）

一套皮肤 = 一个目录（`pet.json` + 一张雪碧图），**固定 9 行动作顺序**：

| 行 | 动作 | 帧 | 王林姿态 |
|---|---|---|---|
| 0 | idle | 6 | 垂手站立（占位） |
| 1 | sword | 4 | 御剑 |
| 2 | running-left | 8 | 御剑向左 |
| 3 | waving | 4 | 抱拳行礼 |
| 4 | jumping | 5 | 突破飞跃 |
| 5 | failed | 8 | 受伤姿态（占位） |
| 6 | stand | 6 | 静立凝神（idle/failed 站姿） |
| 7 | running | 6 | 掐诀 |
| 8 | review | 6 | 以气书字 |

- **格子尺寸**：当前皮肤为 `768×832`（4× 高清），由 `pet.json` 的 `cell` 字段声明——任意尺寸皆可
- **推荐流程**：用即梦生成一段循环动作视频，**逐帧拆分**（同一视频拆帧能保证人物位置稳定），导出逐帧 PNG
- **抠图**：纯色背景用色度键 + 补洞 + 边缘羽化（保留灵光特效、去灰边）；银白发丝自动提亮以消除灰色闪烁
- **打包**（需要 sharp）：
  ```bash
  cd dsh-plugin-ascension
  pnpm install
  node skin-pack.js <skin-id> --name "王林·凝气期"
  ```
  → 输出 `assets/<id>/`（spritesheet.webp + pet.json + previews/）
- **免改代码热插拔**：把打包好的皮肤目录拷到 `~/.dsh/ascension/skins/<id>/`（用户目录皮肤优先）
- 境界 ↔ 皮肤 id：`wang-lin-1`..`wang-lin-7` 对应 7 重境界

## 数据与 API

- 持久化：`~/.dsh/ascension/`（state.json / settings.json）
- RPC：`/api/ascension/{state, interact, set-enabled, set-visible, set-config, set-skin}`、`/api/ascension/skins/<id>/*`（皮肤资源）、`/api/ascension/tiannizhu/*`（天逆珠动画）

## 开发

```
dsh-plugin-ascension/
├── index.js           # 宿主：会话事件订阅 + 修为服务 + RPC + 皮肤注册表
├── ascension-core.js  # 纯逻辑：境界 / 修为 / 事件投影 / 状态机
├── client/client.js   # 客户端：设置分区 + 悬浮宠物 + 天逆珠（手写 bundle）
├── skin-pack.js       # 皮肤打包器：帧 → 雪碧图 + pet.json + previews
├── assets/            # 内置皮肤（wang-lin-1）+ 天逆珠动画
└── cordis.patch.yml / package.json
```

> 注：npm 包与 git 仓库只收录运行时必需资源。皮肤源帧（`skins/`）、天逆珠源视频与源 PNG 属制作素材，未纳入分发。

## 致谢

状态监控 / 状态机 / 修为经济移植自 [`@linxin666/dsh-pet`](https://www.npmjs.com/package/@linxin666/dsh-pet)（MIT License）。

## 许可

MIT © ouyangding
