@mingxy/opencode-mascot 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # 🐱 opencode-mascot
2
+
3
+ > OpenCode TUI 吉祥物插件框架 — 让你的终端活起来
4
+
5
+ 可自定义的 ASCII 吉祥物,在你的 OpenCode 终端里呼吸、走路、睡觉、被打飞、被炸碎,然后默默爬回来重新组装。
6
+
7
+ ## ✨ 特色
8
+
9
+ ### 🎭 内置形象(2个)
10
+
11
+ | 形象 | 描述 | 颜色 |
12
+ |------|------|------|
13
+ | **月儿** (yueer) | 九天玄域女帝,紫发呆毛,傲娇可靠 | `#8B7EB8` 淡紫 |
14
+ | **包子** (baozi) | 热气腾腾的包子,温暖治愈 | `#D4885A` 暖橙 |
15
+
16
+ 每个形象包含 **5 种表情帧**:default / blink / happy / thinking / sleeping
17
+
18
+ ---
19
+
20
+ ### 🎬 自动动画(16种)
21
+
22
+ **Renderer 内置(所有形象共享):**
23
+
24
+ | # | 动画 | 触发 | 效果 |
25
+ |---|------|------|------|
26
+ | 1 | 眨眼 | 随机(30%概率/2.5s) | 切换 blink 帧 150ms |
27
+ | 2 | 随机表情 | 每 8s | idle 时随机切换表情 |
28
+ | 3 | 呼吸 | 每 3s | 行向上偏移一格,模拟呼吸起伏 |
29
+ | 4 | 走路 | 每 20-40s | 左右晃动(14步路径) |
30
+ | 5 | 跳跃 | 每 20-40s | 弹跳 -2→-1→0 |
31
+ | 6 | 睡眠 | idle 90-120s | 自动闭眼 + 火星文 Zzz |
32
+
33
+ **月儿专属(yueer effects):**
34
+
35
+ | # | 动画 | 触发 | 效果 |
36
+ |---|------|------|------|
37
+ | 7 | 呆毛闪烁 | 随机(25%/1.5s) | ☆ ↔ ★ |
38
+ | 8 | 开心晃头 | happy 状态 | 脸左右摆 + 呆毛同步偏移 |
39
+ | 9 | 思考跺脚 | thinking 状态 | 腿交替 ╲╱ ↔ ╱╲ |
40
+ | 10 | 思考变脸 | thinking 状态 | 6种表情轮换(o_o / O_O / >_o / o_< / ⊙_⊙ / ◔_◔) |
41
+ | 11 | 火星文气泡 | busy/thinking | 12条上标火星文轮换 |
42
+ | 12 | 拖拽扇手 | 拖拽中 | 手臂 ┃███┃ ↔ ╱███╲ |
43
+ | 13 | 跳跃扇手 | 跳跃中 | 同上 |
44
+
45
+ **包子专属(baozi effects):**
46
+
47
+ | # | 动画 | 触发 | 效果 |
48
+ |---|------|------|------|
49
+ | 14 | 冒热气 | 持续 | 4种蒸汽图案轮换 |
50
+ | 15 | 火星文气泡 | busy/thinking | 12条上标火星文轮换 |
51
+ | 16 | 拖拽惊恐 | 拖拽中 | `( °□° )` |
52
+
53
+ ---
54
+
55
+ ### 🖱️ 交互能力(5种)
56
+
57
+ | # | 操作 | 效果 |
58
+ |---|------|------|
59
+ | 1 | **Alt + 鼠标拖拽** | 自由移动吉祥物位置(首页 + 工作页) |
60
+ | 2 | **双击切换** | 300ms 内双击 → 循环切换形象 |
61
+ | 3 | **拖拽变色** | 拖拽时身体 8 种高亮色 100ms 快速闪换,松手定格 |
62
+ | 4 | **拖拽火星文** | 拖拽时头顶粉色"放开我"火星文轮换(ᶠᵃⁿᵍ/ᵏᵃⁱ/ᵇᵘᶠᵃⁿᵍ...) |
63
+ | 5 | **拖拽惊恐** | 拖拽时 `( °□° )` 表情 + 手臂疯狂扇动 |
64
+
65
+ ---
66
+
67
+ ### 🫣 躲猫猫系统(工作页)
68
+
69
+ | # | 动作 | 效果 |
70
+ |---|------|------|
71
+ | 1 | 拖到左边缘 | 吉祥物藏起来,只露 2 格 |
72
+ | 2 | 松手贴边 | 自动进入探头循环(每 1.2s 偷偷多露 2 格再缩回) |
73
+ | 3 | 点击 / 开始工作 | 从边界滑回 + bounce 弹跳归位 |
74
+
75
+ ---
76
+
77
+ ### 💥 随机意外事件(3种)
78
+
79
+ | # | 事件 | 触发 | 效果 |
80
+ |---|------|------|------|
81
+ | 1 | **摔坏** | 跳跃落地 40% / bounce 归位 50% | 行散开倒地 → 1.5s 后自动重组 |
82
+ | 2 | **天降炸弹** | idle 时 10% 概率替代走路 | 引线 ✦/◌ 燃烧 + 倒计时 ³·→²·→¹· → 白闪爆炸 + `ᵇᵒᵒᵐ~` → 重组 |
83
+ | 3 | **打散聚合** | 启动 / 切到工作页 | 行从随机位置 15 帧线性插值聚合归位 |
84
+
85
+ ---
86
+
87
+ ### 🔄 自动更新
88
+
89
+ - 启动时检测 npm 最新版 → semver 比较 → `npm pack` 下载 → `tar` 解压覆盖
90
+ - 文件锁防并发(30s 过期自动清理)
91
+ - 同步更新 opencode 插件管理清单版本号,防止重启回滚
92
+ - 更新成功后吉祥物跳跃庆祝 + 火星文版本号 `ᵘᵖ→⁰·⁵·¹`
93
+
94
+ ---
95
+
96
+ ### 🎵 状态联动
97
+
98
+ | 触发 | 效果 |
99
+ |------|------|
100
+ | session busy | 切到包子 + 8色高亮闪烁 + 火星文气泡 |
101
+ | session idle | 切到月儿 + happy 庆祝 3s |
102
+ | session idle 超时 | 自动睡觉 + 火星文 Zzz(`zᶻ...` → `zᶻᶻ...` → `zᶻᶻᶻ...`) |
103
+ | 拖拽睡眠中 | 惊醒到 idle + 扇手惊恐 |
104
+
105
+ ---
106
+
107
+ ### 🚀 启动效果
108
+
109
+ - 启动 2s 后头顶显示火星文版本号 `ᵛ⁰·⁵·¹`(3秒)
110
+ - 首页吉祥物水平随机位置出现
111
+ - 工作页首次对话 / `opencode -c` 时打散聚合动画
112
+
113
+ ---
114
+
115
+ ## 📦 安装
116
+
117
+ 在 `~/.config/opencode/tui.json` 中添加插件:
118
+
119
+ ```json
120
+ {
121
+ "plugin": ["@mingxy/opencode-mascot@latest"]
122
+ }
123
+ ```
124
+
125
+ 重启 opencode 即可。插件会自动更新到最新版。
126
+
127
+ ## 🛠️ 技术栈
128
+
129
+ - **TypeScript** ESM
130
+ - **@opentui/solid** — SolidJS 响应式 TUI 渲染
131
+ - **@opencode-ai/plugin** — OpenCode 插件 API
132
+ - 零运行时依赖(peer dep only)
133
+
134
+ ## 📂 项目结构
135
+
136
+ ```
137
+ opencode-mascot/
138
+ ├── tui.tsx # 插件入口,注册 slots + 启动逻辑
139
+ ├── src/
140
+ │ ├── core/
141
+ │ │ ├── types.ts # MascotPack / MascotState / Effect 类型
142
+ │ │ ├── ascii-renderer.tsx # 核心渲染引擎(574行,16+ 动画)
143
+ │ │ ├── mascot-loader.ts # 内置形象加载器
144
+ │ │ ├── celebration-bus.ts # 模块级事件总线(celebrate/version/scatter)
145
+ │ │ ├── updater.ts # npm 自动更新(pack + tar + 版本同步)
146
+ │ │ └── logger.ts # 文件日志(~/.cache/opencode/logs/mascot.log)
147
+ │ ├── components/
148
+ │ │ ├── home-mascot.tsx # 首页吉祥物(随机位置 + translate 拖拽)
149
+ │ │ └── sidebar-mascot.tsx # 工作页吉祥物(absolute 定位 + 躲猫猫)
150
+ │ └── builtins/
151
+ │ ├── yueer/ # 月儿形象(frames + effects)
152
+ │ │ ├── frames.ts # 5 帧 ASCII art
153
+ │ │ └── index.ts # 专属动画(呆毛/晃头/跺脚/变脸/气泡/扇手)
154
+ │ └── baozi/ # 包子形象(frames + effects)
155
+ │ ├── frames.ts # 5 帧 ASCII art
156
+ │ └── index.ts # 专属动画(蒸汽/气泡/惊恐)
157
+ ```
158
+
159
+ ## 🎨 自定义形象
160
+
161
+ 创建新的吉祥物只需定义一个 `MascotPack`:
162
+
163
+ ```typescript
164
+ import type { MascotPack } from "@mingxy/opencode-mascot/types";
165
+
166
+ const myMascot: MascotPack = {
167
+ name: "@mingxy/mascot-custom",
168
+ displayName: "小猫",
169
+ version: "0.1.0",
170
+ author: "you",
171
+ description: "My custom mascot",
172
+
173
+ frames: {
174
+ default: [" /\\_/\\ ", " ( o.o ) ", " > ^ < "],
175
+ blink: [" /\\_/\\ ", " ( -.- ) ", " > ^ < "],
176
+ happy: [" /\\_/\\ ", " ( ^ω^ ) ", " > ^ < "],
177
+ sleeping:[" /\\_/\\ ", " ( -.- ) ", " > z z "],
178
+ },
179
+
180
+ colors: { defaultFg: "#FFB6C1" },
181
+
182
+ effects: {
183
+ signals: [],
184
+ timers: [],
185
+ render(lines, ctx) { return lines; },
186
+ },
187
+ };
188
+ ```
189
+
190
+ 所有内置动画(眨眼/呼吸/走路/跳跃/睡眠/拖拽/变色/炸弹/摔坏/重组)**自动生效**。
191
+
192
+ ## 📊 能力统计
193
+
194
+ | 类别 | 数量 |
195
+ |------|------|
196
+ | 内置形象 | 2 |
197
+ | 表情帧 | 5 / 形象 |
198
+ | 自动动画 | 16 |
199
+ | 交互操作 | 5 |
200
+ | 躲猫猫行为 | 3 |
201
+ | 随机意外 | 3 |
202
+ | 火星文气泡 | 24(12/形象) |
203
+ | 闪色颜色 | 8 |
204
+ | 拖拽火星文 | 6 |
205
+ | **总能力** | **33+** |
206
+
207
+ ## 📄 License
208
+
209
+ MIT © [mingxy](https://github.com/mengfanbo123)
210
+
211
+ ## 🔗 Links
212
+
213
+ - [GitHub](https://github.com/mengfanbo123/opencode-mascot)
214
+ - [npm](https://www.npmjs.com/package/@mingxy/opencode-mascot)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mingxy/opencode-mascot",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "OpenCode TUI mascot plugin framework - customizable ASCII mascots for your terminal",
5
5
  "author": "mingxy",
6
6
  "license": "MIT",
@@ -35,10 +35,7 @@ const yueerEffects: MascotPack["effects"] = {
35
35
  {
36
36
  interval: 200,
37
37
  update(ctx) {
38
- if (
39
- ctx.state === "thinking" &&
40
- ctx.frameOverride === null
41
- ) {
38
+ if (ctx.state === "thinking" || ctx.state === "busy") {
42
39
  ctx.set("stompActive", true);
43
40
  ctx.set("stompAlt", !(ctx.get("stompAlt") as boolean));
44
41
  } else {