@mingxy/opencode-mascot 0.5.8 → 0.5.9

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 CHANGED
@@ -1,123 +1,127 @@
1
1
  # 🐱 opencode-mascot
2
2
 
3
- > OpenCode TUI 吉祥物插件框架让你的终端活起来
3
+ > OpenCode TUI mascot plugin framework bring your terminal to life
4
4
 
5
- 可自定义的 ASCII 吉祥物,在你的 OpenCode 终端里呼吸、走路、睡觉、被打飞、被炸碎,然后默默爬回来重新组装。
5
+ Customizable ASCII mascots that breathe, walk, sleep, get launched across the screen, blown up by falling bombs, then quietly reassemble themselves.
6
6
 
7
- ## 特色
7
+ [English](./README.md) | [简体中文](./README_zh-CN.md)
8
8
 
9
- ### 🎭 内置形象(2个)
9
+ ---
10
+
11
+ ## ✨ Features
12
+
13
+ ### 🎭 Built-in Characters (2)
10
14
 
11
- | 形象 | 描述 | 颜色 |
12
- |------|------|------|
13
- | **月儿** (yueer) | 紫发呆毛女孩,傲娇风格,默认形象 | `#8B7EB8` 淡紫 |
14
- | **包子** (baozi) | 热气腾腾的包子,温暖治愈 | `#D4885A` 暖橙 |
15
+ | Character | Description | Color |
16
+ |-----------|-------------|-------|
17
+ | **yueer** | Purple-haired girl with an ahoge, tsundere style, default mascot | `#8B7EB8` lavender |
18
+ | **baozi** | A steaming hot bun, warm and cozy | `#D4885A` warm orange |
15
19
 
16
- 每个形象包含 **5 种表情帧**:default / blink / happy / thinking / sleeping
20
+ Each character includes **5 expression frames**: default / blink / happy / thinking / sleeping
17
21
 
18
22
  ---
19
23
 
20
- ### 🎬 自动动画(16种)
24
+ ### 🎬 Automatic Animations (16)
21
25
 
22
- **Renderer 内置(所有形象共享):**
26
+ **Built-in (shared by all characters):**
23
27
 
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 |
28
+ | # | Animation | Trigger | Effect |
29
+ |---|-----------|---------|--------|
30
+ | 1 | Blink | Random (30% / 2.5s) | Switch to blink frame for 150ms |
31
+ | 2 | Random expression | Every 8s | Cycles expressions while idle |
32
+ | 3 | Breathing | Every 3s | Lines shift up one row, simulating breathing |
33
+ | 4 | Walking | Every 20-40s | Sways left and right (14-step path) |
34
+ | 5 | Jumping | Every 20-40s | Bounces -2 → -1 0 |
35
+ | 6 | Sleep | Idle 90-120s | Auto-closed eyes + alien-text Zzz |
32
36
 
33
- **月儿专属(yueer effects):**
37
+ **yueer exclusive:**
34
38
 
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 | 跳跃扇手 | 跳跃中 | 同上 |
39
+ | # | Animation | Trigger | Effect |
40
+ |---|-----------|---------|--------|
41
+ | 7 | Ahoge sparkle | Random (25% / 1.5s) | ☆ ↔ ★ |
42
+ | 8 | Happy head sway | happy state | Face sways left/right + ahoge synced |
43
+ | 9 | Thinking foot stomp | thinking state | Left foot fixed, right foot stomps ║↔_ |
44
+ | 10 | Thinking face shift | thinking state | 6 expressions rotate (o_o / O_O / >_o / o_< / ⊙_⊙ / ◔_◔) |
45
+ | 11 | Alien text bubble | busy/thinking | 12 alien-text phrases rotate |
46
+ | 12 | Drag arm flail | While dragging | Arms ┃███┃ ↔ ╱███╲ |
47
+ | 13 | Jump arm flail | While jumping | Same as above |
44
48
 
45
- **包子专属(baozi effects):**
49
+ **baozi exclusive:**
46
50
 
47
- | # | 动画 | 触发 | 效果 |
48
- |---|------|------|------|
49
- | 14 | 冒热气 | 持续 | 4种蒸汽图案轮换 |
50
- | 15 | 火星文气泡 | busy/thinking | 12条上标火星文轮换 |
51
- | 16 | 拖拽惊恐 | 拖拽中 | `( °□° )` |
51
+ | # | Animation | Trigger | Effect |
52
+ |---|-----------|---------|--------|
53
+ | 14 | Steam | Continuous | 4 steam patterns rotate |
54
+ | 15 | Alien text bubble | busy/thinking | 12 alien-text phrases rotate |
55
+ | 16 | Drag panic | While dragging | `( °□° )` |
52
56
 
53
57
  ---
54
58
 
55
- ### 🖱️ 交互能力(5种)
59
+ ### 🖱️ Interactions (5)
56
60
 
57
- | # | 操作 | 效果 |
58
- |---|------|------|
59
- | 1 | **Alt + 鼠标拖拽** | 自由移动吉祥物位置(首页 + 工作页) |
60
- | 2 | **双击切换** | 300ms 内双击 循环切换形象 |
61
- | 3 | **拖拽变色** | 拖拽时身体 8 种高亮色 100ms 快速闪换,松手定格 |
62
- | 4 | **拖拽火星文** | 拖拽时头顶粉色"放开我"火星文轮换(ᶠᵃⁿᵍ/ᵏᵃⁱ/ᵇᵘᶠᵃⁿᵍ...) |
63
- | 5 | **拖拽惊恐** | 拖拽时 `( °□° )` 表情 + 手臂疯狂扇动 |
61
+ | # | Action | Effect |
62
+ |---|--------|--------|
63
+ | 1 | **Alt + drag** | Freely move the mascot anywhere |
64
+ | 2 | **Double-click** | Cycle through characters (within 300ms) |
65
+ | 3 | **Drag color flash** | Body flashes through 8 highlight colors at 100ms, locks on release |
66
+ | 4 | **Drag alien text** | Pink "let go of me" alien text appears above head while dragging |
67
+ | 5 | **Drag panic** | `( °□° )` face + arms flailing while dragging |
64
68
 
65
69
  ---
66
70
 
67
- ### 🫣 躲猫猫系统(工作页)
71
+ ### 🫣 Peek-a-Boo System (Work Page)
68
72
 
69
- | # | 动作 | 效果 |
70
- |---|------|------|
71
- | 1 | 拖到左边缘 | 吉祥物藏起来,只露 2 |
72
- | 2 | 松手贴边 | 自动进入探头循环(每 1.2s 偷偷多露 2 格再缩回) |
73
- | 3 | 点击 / 开始工作 | 从边界滑回 + bounce 弹跳归位 |
73
+ | # | Action | Effect |
74
+ |---|--------|--------|
75
+ | 1 | Drag to left edge | Mascot hides, only 2 rows visible |
76
+ | 2 | Release at edge | Auto peek cycle (peeks 2 more rows every 1.2s, then retreats) |
77
+ | 3 | Click / start working | Slides back from edge + bounce |
74
78
 
75
79
  ---
76
80
 
77
- ### 💥 随机意外事件(3种)
81
+ ### 💥 Random Events (3)
78
82
 
79
- | # | 事件 | 触发 | 效果 |
80
- |---|------|------|------|
81
- | 1 | **摔坏** | 跳跃落地 40% / bounce 归位 50% | 行散开倒地 → 1.5s 后自动重组 |
82
- | 2 | **天降炸弹** | idle 时 10% 概率替代走路 | 引线 ✦/◌ 燃烧 + 倒计时 ³·→²·→¹· → 白闪爆炸 + `ᵇᵒᵒᵐ~` → 重组 |
83
- | 3 | **打散聚合** | 启动 / 切到工作页 | 行从随机位置 15 帧线性插值聚合归位 |
83
+ | # | Event | Trigger | Effect |
84
+ |---|-------|---------|--------|
85
+ | 1 | **Fall apart** | Jump landing 40% / bounce 50% | Lines scatter reassemble after 1.5s |
86
+ | 2 | **Bomb drop** | 10% chance replacing walk (idle) | Fuse burns ✦/◌ + countdown ³·→²·→¹· → white flash explosion + `ᵇᵒᵒᵐ~` → reassemble |
87
+ | 3 | **Scatter & assemble** | Startup / switch to work page | Lines start from random positions, 15-frame linear interpolation to home |
84
88
 
85
89
  ---
86
90
 
87
- ### 🔄 自动更新
91
+ ### 🔄 Auto-Update
88
92
 
89
- - 启动时检测 npm 最新版 → semver 比较 → `npm pack` 下载 → `tar` 解压覆盖
90
- - 文件锁防并发(30s 过期自动清理)
91
- - 同步更新 opencode 插件管理清单版本号,防止重启回滚
92
- - 更新成功后吉祥物跳跃庆祝 + 火星文版本号 `ᵘᵖ→⁰·⁵·¹`
93
+ - Checks npm latest version on startup → semver compare → `npm pack` download → `tar` extract overwrite
94
+ - File lock prevents concurrency (30s expiry auto-cleanup)
95
+ - Syncs opencode plugin manifest version to prevent rollback on restart
96
+ - On successful update: mascot jumps to celebrate + alien-text version number `ᵘᵖ→⁰·⁵·¹`
93
97
 
94
98
  ---
95
99
 
96
- ### 🎵 状态联动
100
+ ### 🎵 State Sync
97
101
 
98
- | 触发 | 效果 |
99
- |------|------|
100
- | session busy | 火星文气泡 + 8色高亮闪烁 |
101
- | session thinking | 跺脚 + 变脸 + 火星文气泡 |
102
- | session happy | 晃头庆祝 3s |
103
- | session idle 超时 | 自动睡觉 + 火星文 Zzz(`zᶻ...` → `zᶻᶻ...` → `zᶻᶻᶻ...`) |
104
- | 拖拽睡眠中 | 惊醒到 idle + 扇手惊恐 |
102
+ | Trigger | Effect |
103
+ |---------|--------|
104
+ | session busy | Alien text bubble + 8-color highlight flash |
105
+ | session thinking | Foot stomp + face shift + alien text |
106
+ | session happy | Head sway celebration 3s |
107
+ | session idle timeout | Auto-sleep + alien-text Zzz (`zᶻ...` → `zᶻᶻ...` → `zᶻᶻᶻ...`) |
108
+ | Drag while sleeping | Startles awake to idle + arm flail panic |
105
109
 
106
- > 默认所有状态使用月儿形象。可通过右键双击手动切换包子。
110
+ > All states default to yueer. Double-click to manually switch to baozi.
107
111
 
108
112
  ---
109
113
 
110
- ### 🚀 启动效果
114
+ ### 🚀 Startup Effects
111
115
 
112
- - 启动 2s 后头顶显示火星文版本号 `ᵛ⁰·⁵·¹`(3秒)
113
- - 首页吉祥物水平随机位置出现
114
- - 工作页首次对话 / `opencode -c` 时打散聚合动画
116
+ - Version number shown 2s after startup as alien-text `ᵛ⁰·⁵·¹` (3s duration)
117
+ - Home page mascot appears at random horizontal position
118
+ - Work page scatter-assemble animation on first message / `opencode -c`
115
119
 
116
120
  ---
117
121
 
118
- ## 📦 安装
122
+ ## 📦 Installation
119
123
 
120
- `~/.config/opencode/tui.json` 中添加插件:
124
+ Add to `~/.config/opencode/tui.json`:
121
125
 
122
126
  ```json
123
127
  {
@@ -125,51 +129,47 @@
125
129
  }
126
130
  ```
127
131
 
128
- 重启 opencode 即可。插件会自动更新到最新版。
132
+ Restart opencode. The plugin auto-updates to the latest version.
129
133
 
130
- ## 🛠️ 技术栈
134
+ ## 🛠️ Tech Stack
131
135
 
132
136
  - **TypeScript** ESM
133
- - **@opentui/solid** — SolidJS 响应式 TUI 渲染
134
- - **@opencode-ai/plugin** — OpenCode 插件 API
135
- - 零运行时依赖(peer dep only
136
- - TypeScript 类型检查通过
137
+ - **@opentui/solid** — SolidJS reactive TUI rendering
138
+ - **@opencode-ai/plugin** — OpenCode plugin API
139
+ - Zero runtime dependencies (peer dep only)
140
+ - TypeScript type-checked
137
141
 
138
- ## 📂 项目结构
142
+ ## 📂 Project Structure
139
143
 
140
144
  ```
141
145
  opencode-mascot/
142
- ├── tui.tsx # 插件入口,注册 slots + 启动逻辑
146
+ ├── tui.tsx # Plugin entry, registers slots + startup
143
147
  ├── src/
144
148
  │ ├── core/
145
- │ │ ├── types.ts # MascotPack / MascotState / Effect 类型
146
- │ │ ├── ascii-renderer.tsx # 核心渲染引擎(574行,16+ 动画)
147
- │ │ ├── mascot-loader.ts # 内置形象加载器
148
- │ │ ├── celebration-bus.ts # 模块级事件总线(celebrate/version/scatter)
149
- │ │ ├── updater.ts # npm 自动更新(pack + tar + 版本同步)
150
- │ │ └── logger.ts # 文件日志(~/.cache/opencode/logs/mascot.log)
149
+ │ │ ├── types.ts # MascotPack / MascotState / Effect types
150
+ │ │ ├── ascii-renderer.tsx # Core rendering engine (574 lines, 16+ animations)
151
+ │ │ ├── mascot-loader.ts # Built-in character loader
152
+ │ │ ├── celebration-bus.ts # Module-level event bus
153
+ │ │ ├── updater.ts # npm auto-update
154
+ │ │ └── logger.ts # File logger
151
155
  │ ├── components/
152
- │ │ ├── home-mascot.tsx # 首页吉祥物(随机位置 + translate 拖拽)
153
- │ │ └── sidebar-mascot.tsx # 工作页吉祥物(absolute 定位 + 躲猫猫)
156
+ │ │ ├── home-mascot.tsx # Home page mascot
157
+ │ │ └── sidebar-mascot.tsx # Work page mascot (peek-a-boo)
154
158
  │ └── builtins/
155
- │ ├── yueer/ # 月儿形象(frames + effects
156
- │ ├── frames.ts # 5 ASCII art
157
- │ │ └── index.ts # 专属动画(呆毛/晃头/跺脚/变脸/气泡/扇手)
158
- │ └── baozi/ # 包子形象(frames + effects)
159
- │ ├── frames.ts # 5 帧 ASCII art
160
- │ └── index.ts # 专属动画(蒸汽/气泡/惊恐)
159
+ │ ├── yueer/ # yueer (frames + effects)
160
+ └── baozi/ # baozi (frames + effects)
161
161
  ```
162
162
 
163
- ## 🎨 自定义形象
163
+ ## 🎨 Custom Characters
164
164
 
165
- 创建新的吉祥物只需定义一个 `MascotPack`:
165
+ Define a `MascotPack`:
166
166
 
167
167
  ```typescript
168
168
  import type { MascotPack } from "@mingxy/opencode-mascot/types";
169
169
 
170
170
  const myMascot: MascotPack = {
171
171
  name: "@mingxy/mascot-custom",
172
- displayName: "小猫",
172
+ displayName: "Kitty",
173
173
  version: "0.1.0",
174
174
  author: "you",
175
175
  description: "My custom mascot",
@@ -191,22 +191,22 @@ const myMascot: MascotPack = {
191
191
  };
192
192
  ```
193
193
 
194
- 所有内置动画(眨眼/呼吸/走路/跳跃/睡眠/拖拽/变色/炸弹/摔坏/重组)**自动生效**。
194
+ All built-in animations (blink/breath/walk/jump/sleep/drag/color-flash/bomb/fall-apart/reassemble) **work automatically**.
195
195
 
196
- ## 📊 能力统计
196
+ ## 📊 Capabilities
197
197
 
198
- | 类别 | 数量 |
199
- |------|------|
200
- | 内置形象 | 2 |
201
- | 表情帧 | 5 / 形象 |
202
- | 自动动画 | 16 |
203
- | 交互操作 | 5 |
204
- | 躲猫猫行为 | 3 |
205
- | 随机意外 | 3 |
206
- | 火星文气泡 | 2412/形象) |
207
- | 闪色颜色 | 8 |
208
- | 拖拽火星文 | 6 |
209
- | **总能力** | **33+** |
198
+ | Category | Count |
199
+ |----------|-------|
200
+ | Built-in characters | 2 |
201
+ | Expression frames | 5 / character |
202
+ | Auto animations | 16 |
203
+ | Interactions | 5 |
204
+ | Peek-a-boo behaviors | 3 |
205
+ | Random events | 3 |
206
+ | Alien text phrases | 24 (12/character) |
207
+ | Flash colors | 8 |
208
+ | Drag alien text | 6 |
209
+ | **Total** | **33+** |
210
210
 
211
211
  ## 📄 License
212
212
 
@@ -216,3 +216,4 @@ MIT © [mingxy](https://github.com/mengfanbo123)
216
216
 
217
217
  - [GitHub](https://github.com/mengfanbo123/opencode-mascot)
218
218
  - [npm](https://www.npmjs.com/package/@mingxy/opencode-mascot)
219
+ - [中文文档](./README_zh-CN.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mingxy/opencode-mascot",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "OpenCode TUI mascot plugin framework - customizable ASCII mascots for your terminal",
5
5
  "author": "mingxy",
6
6
  "license": "MIT",
@@ -117,6 +117,7 @@ export function SidebarMascot(props: SidebarMascotProps): JSX.Element {
117
117
  const returnToView = () => {
118
118
  if (!hideSide) return;
119
119
  stopPeek();
120
+ stopReturn();
120
121
  const cw = getCw();
121
122
  const cur = posX();
122
123
  const targetX = hideSide === "left" ? 0 : Math.max(0, cw - MASCOT_WIDTH);
@@ -128,7 +129,10 @@ export function SidebarMascot(props: SidebarMascotProps): JSX.Element {
128
129
  setPosX(targetX);
129
130
  stopReturn();
130
131
  hideSide = null;
131
- renderers[currentName()].bounce();
132
+ const r = renderers[currentName()];
133
+ if (r.getState() === "idle") {
134
+ r.bounce();
135
+ }
132
136
  return;
133
137
  }
134
138
  setPosX(now + step);
@@ -46,6 +46,7 @@ function getFrameLines(pack: MascotPack, frameName: string): string[] {
46
46
 
47
47
  export function createAnimatedRenderer(pack: MascotPack): {
48
48
  element: () => JSX.Element;
49
+ getState: () => MascotState;
49
50
  setState: (s: MascotState) => void;
50
51
  toggleWalk: () => void;
51
52
  setDragging: (v: boolean) => void;
@@ -573,5 +574,5 @@ export function createAnimatedRenderer(pack: MascotPack): {
573
574
  }, 700);
574
575
  };
575
576
 
576
- return { element, setState, toggleWalk, setDragging, celebrateUpdate, bounce, showVersion, scatterIn, explode };
577
+ return { element, getState: currentState, setState, toggleWalk, setDragging, celebrateUpdate, bounce, showVersion, scatterIn, explode };
577
578
  }