opencode-visual-cache 1.6.2 → 1.7.0-beta.0

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.
Files changed (62) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +247 -247
  3. package/README_EN.md +247 -247
  4. package/dist/_version.d.ts +1 -1
  5. package/dist/_version.js +1 -1
  6. package/dist/core/color.d.ts +37 -0
  7. package/dist/core/color.js +108 -0
  8. package/dist/core/currency.d.ts +17 -0
  9. package/dist/core/currency.js +43 -0
  10. package/dist/core/estimate.d.ts +1 -0
  11. package/dist/core/estimate.js +40 -0
  12. package/dist/core/format.d.ts +15 -0
  13. package/dist/core/format.js +90 -0
  14. package/dist/core/index.d.ts +5 -0
  15. package/dist/core/index.js +5 -0
  16. package/dist/core/types.d.ts +17 -0
  17. package/dist/core/types.js +1 -0
  18. package/dist/index.js +12 -818
  19. package/dist/panel/TokenCachePanel.d.ts +10 -0
  20. package/dist/panel/TokenCachePanel.js +549 -0
  21. package/dist/panel/panel-api.d.ts +119 -0
  22. package/dist/panel/panel-api.js +1 -0
  23. package/dist/tui.js +223 -209
  24. package/dist/v2/commands.d.ts +10 -0
  25. package/dist/v2/commands.js +490 -0
  26. package/dist/v2/data.d.ts +27 -0
  27. package/dist/v2/data.js +103 -0
  28. package/dist/v2/index.d.ts +4 -0
  29. package/dist/v2/index.js +163 -0
  30. package/dist/v2/sidebar.d.ts +6 -0
  31. package/dist/v2/sidebar.js +36 -0
  32. package/dist/v2/status.d.ts +14 -0
  33. package/dist/v2/status.js +83 -0
  34. package/dist/v2/theme.d.ts +8 -0
  35. package/dist/v2/theme.js +16 -0
  36. package/dist/v2/types.d.ts +219 -0
  37. package/dist/v2/types.js +6 -0
  38. package/dist/v2/v2-panel-api.d.ts +8 -0
  39. package/dist/v2/v2-panel-api.js +176 -0
  40. package/dist/v2.js +2941 -0
  41. package/package.json +70 -67
  42. package/src/_version.ts +1 -1
  43. package/src/balance-providers.ts +153 -153
  44. package/src/core/color.ts +108 -0
  45. package/src/core/currency.ts +46 -0
  46. package/src/core/estimate.ts +36 -0
  47. package/src/core/format.ts +81 -0
  48. package/src/core/index.ts +5 -0
  49. package/src/core/types.ts +17 -0
  50. package/src/i18n.ts +380 -380
  51. package/src/index.tsx +1035 -2120
  52. package/src/panel/TokenCachePanel.tsx +776 -0
  53. package/src/panel/panel-api.ts +104 -0
  54. package/src/server.ts +10 -10
  55. package/src/v2/commands.ts +471 -0
  56. package/src/v2/data.ts +112 -0
  57. package/src/v2/index.tsx +184 -0
  58. package/src/v2/sidebar.tsx +69 -0
  59. package/src/v2/status.tsx +96 -0
  60. package/src/v2/theme.ts +19 -0
  61. package/src/v2/types.ts +159 -0
  62. package/src/v2/v2-panel-api.ts +177 -0
package/README_EN.md CHANGED
@@ -1,247 +1,247 @@
1
- <div align="center">
2
- <strong>
3
- <h1>OpenCode Visual Cache</h1>
4
- Real-time Token Cache Hit Rate · TUI Sidebar Visualization<br>
5
- Adaptive Theme Colors · Auto-desaturated · Chinese / English
6
- </strong>
7
- <br>
8
- <br>
9
- If you find this plugin useful, a ⭐ would mean a lot — thank you!<br>
10
- <br>
11
-
12
- [![GitHub](https://img.shields.io/badge/GitHub-Repository-black?style=flat-square&logo=github)](https://github.com/Hotakus/opencode-visual-cache)
13
- [![Stars](https://img.shields.io/github/stars/Hotakus/opencode-visual-cache?style=flat-square)](https://github.com/Hotakus/opencode-visual-cache/stargazers)
14
- [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)
15
- [![中文](https://img.shields.io/badge/中文-README-blue?style=flat-square)](https://github.com/Hotakus/opencode-visual-cache/blob/master/README.md)
16
- ![NPM Version](https://img.shields.io/npm/v/opencode-visual-cache?style=flat-square)
17
-
18
- </div>
19
-
20
- ---
21
-
22
- Interested in sub-agent monitoring? Check out [opencode-subagent-magazine](https://github.com/Hotakus/opencode-subagent-magazine)!
23
-
24
- ---
25
-
26
- ## 1. Screenshots
27
-
28
- <div align="center">
29
- <strong>Collapsed 👇</strong> <br>
30
- <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/collapse.png"></img>
31
- <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/collapse_en.png"></img>
32
- </div>
33
- <div align="center">
34
- <strong>Expanded 👇</strong> <br>
35
- <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/expand.png"></img>
36
- <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/expand_en.png"></img>
37
- </div>
38
-
39
- ---
40
-
41
- ## 2. Features
42
-
43
- - **Cache Hit Rate**: Real-time hit rate with adaptive-width progress bar and trend indicator
44
- - **Token Detail**: Cache read / write / miss / output, left-aligned labels, right-aligned values
45
- - **Cost & Savings**: Session cumulative cost plus cache-hit savings
46
- - **Model Pricing**: Input / cache-read / cache-write per-million rates (read from provider config dynamically)
47
- - **Collapsible**: Main title collapsed by default; click to expand. Detail, model, and distribution sections fold independently
48
- - **Adaptive Colors**: ≥85% green · ≥70% orange · <70% red, auto-desaturated from current theme
49
- - **Token Distribution**: Per-role (system / user / sub-agent instr / tool call / tool result) estimated token breakdown
50
- - **Persistent State**: Fold preferences and config remembered across restarts via api.kv
51
- - **Language**: Chinese / English / 日本語 / 한국어, auto-detects system locale, with `/cache-lang` for runtime switching — user preference takes priority over auto-detection
52
- - **Multi-currency**: Switch via `/cache-currency` — costs, savings, and per-million rates convert in real time
53
- - **Balance Query**: Query account balance across multiple AI providers, with auto-switch following the current session's provider
54
- - **Slash Commands**: `/cache-session` `/cache-session-back` `/cache-rate` `/cache-section` `/cache-config` `/cache-lang` for live panel configuration
55
- - **Sub-Agent Cache View**: `/cache-session` auto-scans and lists sub-agents; select one to switch the panel stats. Use `/cache-session-back` to return to the main session
56
- - **Loaded Skills**: Detects `skill` tool calls in the session and displays loaded skill names with estimated token footprint
57
- - **Bottom Status Bar**: single-line hit rate (with trend) · Tokens · Balance in the prompt hint row — visible even with the sidebar closed; hide it anytime via `/cache-section`
58
-
59
- ---
60
-
61
- ## 3. Installation
62
-
63
- ### 3.1 Option 1: OpenCode Command (recommended)
64
-
65
- Press **`Ctrl + P`** in OpenCode to open the command palette, search **`install plugin`**, then type:
66
-
67
- ```
68
- opencode-visual-cache@latest
69
- ```
70
-
71
- Press Enter to install and configure automatically.
72
-
73
- ### 3.2 Option 2: Manual
74
-
75
- **1. Install the plugin**
76
-
77
- ```bash
78
- npm install -g opencode-visual-cache@latest
79
- ```
80
-
81
- **2. Configure TUI plugin**
82
-
83
- Create or edit `~/.config/opencode/tui.jsonc`:
84
-
85
- ```jsonc
86
- {
87
- "$schema": "https://opencode.ai/tui.json",
88
- "plugin": ["opencode-visual-cache@latest"]
89
- }
90
- ```
91
-
92
- ### 3.3 Restart OpenCode
93
-
94
- Open any session — the cache stats panel appears in the sidebar.
95
-
96
- ---
97
-
98
- ## 4. Usage Guide
99
-
100
- ### 4.1 Slash Commands
101
-
102
- The plugin supports slash commands and command palette (`Ctrl + P`) for runtime configuration. All changes take effect immediately and are persisted:
103
-
104
- | Command | Function | How to use |
105
- |---------|----------|------------|
106
- | `/cache-session` | View sub-agent cache stats | Lists sub-agents automatically, or paste a Session ID to switch the panel data source |
107
- | `/cache-session-back` | Return to main session | Switch back to main session from sub-agent cache view |
108
- | `/cache-currency` | Switch currency | Pick from a list (USD / CNY / EUR / JPY / GBP / KRW); default exchange rate auto-filled |
109
- | `/cache-rate` | Adjust exchange rate | Enter a custom rate (e.g. `7.2` for CNY) |
110
- | `/cache-section` | Toggle sections & border | Independently show/hide Detail, Model & Pricing, Token Distribution, Loaded Skills, Balance, Bottom Bar, or the panel border |
111
- | `/cache-config` | View current config | Displays currency, rate, and section visibility |
112
- | `/cache-lang` | Switch display language | Pick Chinese or English from the dialog — takes effect immediately, no restart needed |
113
- | `/cache-balance` | Balance query settings | Pick a balance provider (menu shows key source: user key / OpenCode / not set) / toggle auto-switch |
114
- | `/cache-balance-key` | Set balance API key | Two-step flow: pick a provider → enter the API key |
115
-
116
- <div align="center">
117
- <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/splash_cmd.png" alt="Slash command" width="49%"></img>
118
- <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/ctrlP_cmd.png" alt="Ctrl+P command palette" width="49%"></img>
119
- </div>
120
-
121
- Switching currency automatically applies a built-in approximate exchange rate (USD-based). Override it anytime with `/cache-rate`.
122
-
123
- ### 4.2 Currency & Exchange Rate
124
-
125
- Cost display supports multiple currencies:
126
-
127
- | Code | Symbol | Default rate (1 USD = ?) |
128
- |------|--------|-------------------------|
129
- | USD | `$` | 1 |
130
- | CNY | `¥` | 7.2 |
131
- | EUR | `€` | 0.92 |
132
- | JPY | `JP¥` | 150 |
133
- | GBP | `£` | 0.79 |
134
- | KRW | `₩` | 1350 |
135
-
136
- > The rate applies to session cost, cache savings, and per-million pricing — consistently across the panel.
137
- >
138
- > **Base currency**: The plugin assumes all provider pricing is in USD. Major AI APIs (OpenAI / Anthropic / Google / DeepSeek / xAI etc.) use USD for their international endpoints. If your provider bills in CNY or another currency, set the exchange rate to `1`.
139
-
140
- ### 4.3 Section Visibility
141
-
142
- Three sub-sections can be toggled independently to save sidebar space:
143
-
144
- - **Token Detail**: cache read / write / miss / output
145
- - **Model & Pricing**: cost / provider / model name / per-million rates
146
- - **Estimated Token Dist.**: per-role token breakdown
147
- - **Loaded Skills**: skill names the LLM actually loaded via the `skill` tool, with estimated token counts
148
- - **Balance**: the selected provider's account balance (multi-provider with auto-switch)
149
- - **Bottom Status Bar**: the single-line hit rate · Tokens · Balance stats in the prompt hint row
150
-
151
- Toggled via `/cache-section` — takes effect instantly, no restart required. The same command also toggles the panel **border**; turning it off removes the outline and padding so content fills the full width.
152
-
153
- > **About Token Dist. values**: "Reasoning" is an exact value from the API; the other rows (system / user / sub-agent instr / tool call / tool result) are **estimates** — the API only reports total token counts, not how they split across content types, so the plugin collects text per content type and approximates via character counting. Values are indicative only. OpenCode runtime-injected system prompt content (environment info, skill catalog, tool schema definitions — see [`system.ts`](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/session/system.ts), [`tools.ts`](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/session/tools.ts)) is not covered by these estimates.
154
-
155
- ### 4.4 Balance Query
156
-
157
- The panel can display account balance from multiple AI providers. With **auto-switch** enabled, the balance query follows the model provider of the current session automatically.
158
-
159
- Supported balance providers:
160
-
161
- | Provider | Balance endpoint | Currency | Key prefix | Status |
162
- |----------|-----------------|----------|------------|--------|
163
- | DeepSeek | `https://api.deepseek.com/user/balance` | CNY / USD | `sk-` | ✅ Supported |
164
- | SiliconFlow | `https://api.siliconflow.cn/v1/user/info` | CNY | `sk-` | ✅ Supported |
165
- | OpenRouter | `https://openrouter.ai/api/v1/credits` | USD | `sk-or-` | ✅ Supported |
166
- | Moonshot | `https://api.moonshot.cn/v1/users/me/balance` | CNY | `sk-` | ✅ Supported |
167
- | Zhipu GLM | Pending (community-reversed endpoint, unofficial) | CNY | — | ⏳ Planned |
168
- | xAI | Pending (requires Management Key + Team ID) | USD | — | ⏳ Planned |
169
-
170
- > **Key source**: a key set manually via `/cache-balance-key` takes priority; otherwise the plugin reuses the credential OpenCode already authenticated (`/connect`-configured providers). Providers with neither cannot show a balance.
171
- >
172
- > **Key storage**: manually configured API keys are stored in plaintext in the plugin's persistent KV — avoid using on shared devices.
173
- >
174
- > **Auto-switch**: enabled by default; picking a provider manually disables it — re-enable anytime via `/cache-balance`. Auto-switch matches the current session's model provider; a provider without a key shows a "not set" hint when selected.
175
- >
176
- > **Planned**: candidates confirmed feasible by research, not yet implemented. Zhipu GLM only has a community-reversed unofficial endpoint (no stability guarantee).
177
- >
178
- > **Metric semantics**: hit rate = cache read / (fresh input + cache read + cache write), consistent with the industry (OpenAI / Anthropic / Bedrock). "Miss" in the detail view = fresh input + cache write. The bottom-bar Tokens is the input-side total (output excluded). Providers that do not report cache writes separately (e.g. DeepSeek) automatically fall back to the hit/miss formula.
179
- >
180
- > **Balance display**: the sidebar and bottom bar share the same balance data, so both show identical values. When the current provider has no balance adapter, the sidebar shows a hint and the bottom bar hides the balance segment.
181
-
182
- ---
183
-
184
- ## 5. Update
185
-
186
- Due to a [known OpenCode issue #6774](https://github.com/anomalyco/opencode/issues/6774), the plugin cache locks to the version installed at first setup and does **not** auto-detect newer releases on npm.
187
-
188
- To update:
189
-
190
- **1. Clear the OpenCode plugin cache**
191
-
192
- ```powershell
193
- # Windows
194
- Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\packages\opencode-visual-cache@latest"
195
- ```
196
-
197
- ```bash
198
- # macOS / Linux
199
- rm -rf ~/.cache/opencode/packages/opencode-visual-cache@latest
200
- ```
201
-
202
- **2. Re-install the plugin**
203
-
204
- Press **`Ctrl + P`** in OpenCode → `install plugin` → `opencode-visual-cache@latest` → Enter
205
-
206
- **3. Restart OpenCode**
207
-
208
- ---
209
-
210
- ## 6. Language Settings
211
-
212
- The plugin provides three ways to control the display language, listed by priority (highest first):
213
-
214
- ### 6.1 Runtime Switching (recommended)
215
-
216
- Type `/cache-lang` in the TUI and select Chinese / English / 日本語 / 한국어 from the dialog. The panel switches immediately without restarting. Your preference is persisted and takes priority over auto-detection on the next launch.
217
-
218
- ### 6.2 Environment Variable Override
219
-
220
- Set the `CACHE_TUI_LANG` environment variable before launching to force a specific language (`zh` / `en` / `ja` / `ko`):
221
-
222
- ```powershell
223
- # Windows PowerShell
224
- $env:CACHE_TUI_LANG="en"; opencode
225
- ```
226
-
227
- ```bash
228
- # macOS / Linux
229
- CACHE_TUI_LANG=en opencode
230
- ```
231
-
232
- ### 6.3 Auto Detection
233
-
234
- Defaults to the system locale automatically. If it doesn't match, switch once with `/cache-lang` and the preference will be remembered.
235
-
236
- ---
237
-
238
- ## 7. Compatibility
239
-
240
- Model-agnostic — works with all OpenCode-compatible AI models (DeepSeek / Claude / GPT etc.).
241
- Token data and pricing are read via OpenCode SDK standard interfaces.
242
-
243
- ---
244
-
245
- ## 8. License
246
-
247
- MIT
1
+ <div align="center">
2
+ <strong>
3
+ <h1>OpenCode Visual Cache</h1>
4
+ Real-time Token Cache Hit Rate · TUI Sidebar Visualization<br>
5
+ Adaptive Theme Colors · Auto-desaturated · Chinese / English
6
+ </strong>
7
+ <br>
8
+ <br>
9
+ If you find this plugin useful, a ⭐ would mean a lot — thank you!<br>
10
+ <br>
11
+
12
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-black?style=flat-square&logo=github)](https://github.com/Hotakus/opencode-visual-cache)
13
+ [![Stars](https://img.shields.io/github/stars/Hotakus/opencode-visual-cache?style=flat-square)](https://github.com/Hotakus/opencode-visual-cache/stargazers)
14
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE)
15
+ [![中文](https://img.shields.io/badge/中文-README-blue?style=flat-square)](https://github.com/Hotakus/opencode-visual-cache/blob/master/README.md)
16
+ ![NPM Version](https://img.shields.io/npm/v/opencode-visual-cache?style=flat-square)
17
+
18
+ </div>
19
+
20
+ ---
21
+
22
+ Interested in sub-agent monitoring? Check out [opencode-subagent-magazine](https://github.com/Hotakus/opencode-subagent-magazine)!
23
+
24
+ ---
25
+
26
+ ## 1. Screenshots
27
+
28
+ <div align="center">
29
+ <strong>Collapsed 👇</strong> <br>
30
+ <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/collapse.png"></img>
31
+ <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/collapse_en.png"></img>
32
+ </div>
33
+ <div align="center">
34
+ <strong>Expanded 👇</strong> <br>
35
+ <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/expand.png"></img>
36
+ <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/expand_en.png"></img>
37
+ </div>
38
+
39
+ ---
40
+
41
+ ## 2. Features
42
+
43
+ - **Cache Hit Rate**: Real-time hit rate with adaptive-width progress bar and trend indicator
44
+ - **Token Detail**: Cache read / write / miss / output, left-aligned labels, right-aligned values
45
+ - **Cost & Savings**: Session cumulative cost plus cache-hit savings
46
+ - **Model Pricing**: Input / cache-read / cache-write per-million rates (read from provider config dynamically)
47
+ - **Collapsible**: Main title collapsed by default; click to expand. Detail, model, and distribution sections fold independently
48
+ - **Adaptive Colors**: ≥85% green · ≥70% orange · <70% red, auto-desaturated from current theme
49
+ - **Token Distribution**: Per-role (system / user / sub-agent instr / tool call / tool result) estimated token breakdown
50
+ - **Persistent State**: Fold preferences and config remembered across restarts via api.kv
51
+ - **Language**: Chinese / English / 日本語 / 한국어, auto-detects system locale, with `/cache-lang` for runtime switching — user preference takes priority over auto-detection
52
+ - **Multi-currency**: Switch via `/cache-currency` — costs, savings, and per-million rates convert in real time
53
+ - **Balance Query**: Query account balance across multiple AI providers, with auto-switch following the current session's provider
54
+ - **Slash Commands**: `/cache-session` `/cache-session-back` `/cache-rate` `/cache-section` `/cache-config` `/cache-lang` for live panel configuration
55
+ - **Sub-Agent Cache View**: `/cache-session` auto-scans and lists sub-agents; select one to switch the panel stats. Use `/cache-session-back` to return to the main session
56
+ - **Loaded Skills**: Detects `skill` tool calls in the session and displays loaded skill names with estimated token footprint
57
+ - **Bottom Status Bar**: single-line hit rate (with trend) · Tokens · Balance in the prompt hint row — visible even with the sidebar closed; hide it anytime via `/cache-section`
58
+
59
+ ---
60
+
61
+ ## 3. Installation
62
+
63
+ ### 3.1 Option 1: OpenCode Command (recommended)
64
+
65
+ Press **`Ctrl + P`** in OpenCode to open the command palette, search **`install plugin`**, then type:
66
+
67
+ ```
68
+ opencode-visual-cache@latest
69
+ ```
70
+
71
+ Press Enter to install and configure automatically.
72
+
73
+ ### 3.2 Option 2: Manual
74
+
75
+ **1. Install the plugin**
76
+
77
+ ```bash
78
+ npm install -g opencode-visual-cache@latest
79
+ ```
80
+
81
+ **2. Configure TUI plugin**
82
+
83
+ Create or edit `~/.config/opencode/tui.jsonc`:
84
+
85
+ ```jsonc
86
+ {
87
+ "$schema": "https://opencode.ai/tui.json",
88
+ "plugin": ["opencode-visual-cache@latest"]
89
+ }
90
+ ```
91
+
92
+ ### 3.3 Restart OpenCode
93
+
94
+ Open any session — the cache stats panel appears in the sidebar.
95
+
96
+ ---
97
+
98
+ ## 4. Usage Guide
99
+
100
+ ### 4.1 Slash Commands
101
+
102
+ The plugin supports slash commands and command palette (`Ctrl + P`) for runtime configuration. All changes take effect immediately and are persisted:
103
+
104
+ | Command | Function | How to use |
105
+ |---------|----------|------------|
106
+ | `/cache-session` | View sub-agent cache stats | Lists sub-agents automatically, or paste a Session ID to switch the panel data source |
107
+ | `/cache-session-back` | Return to main session | Switch back to main session from sub-agent cache view |
108
+ | `/cache-currency` | Switch currency | Pick from a list (USD / CNY / EUR / JPY / GBP / KRW); default exchange rate auto-filled |
109
+ | `/cache-rate` | Adjust exchange rate | Enter a custom rate (e.g. `7.2` for CNY) |
110
+ | `/cache-section` | Toggle sections & border | Independently show/hide Detail, Model & Pricing, Token Distribution, Loaded Skills, Balance, Bottom Bar, or the panel border |
111
+ | `/cache-config` | View current config | Displays currency, rate, and section visibility |
112
+ | `/cache-lang` | Switch display language | Pick Chinese or English from the dialog — takes effect immediately, no restart needed |
113
+ | `/cache-balance` | Balance query settings | Pick a balance provider (menu shows key source: user key / OpenCode / not set) / toggle auto-switch |
114
+ | `/cache-balance-key` | Set balance API key | Two-step flow: pick a provider → enter the API key |
115
+
116
+ <div align="center">
117
+ <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/splash_cmd.png" alt="Slash command" width="49%"></img>
118
+ <img src="https://raw.githubusercontent.com/Hotakus/opencode-visual-cache/master/assets/ctrlP_cmd.png" alt="Ctrl+P command palette" width="49%"></img>
119
+ </div>
120
+
121
+ Switching currency automatically applies a built-in approximate exchange rate (USD-based). Override it anytime with `/cache-rate`.
122
+
123
+ ### 4.2 Currency & Exchange Rate
124
+
125
+ Cost display supports multiple currencies:
126
+
127
+ | Code | Symbol | Default rate (1 USD = ?) |
128
+ |------|--------|-------------------------|
129
+ | USD | `$` | 1 |
130
+ | CNY | `¥` | 7.2 |
131
+ | EUR | `€` | 0.92 |
132
+ | JPY | `JP¥` | 150 |
133
+ | GBP | `£` | 0.79 |
134
+ | KRW | `₩` | 1350 |
135
+
136
+ > The rate applies to session cost, cache savings, and per-million pricing — consistently across the panel.
137
+ >
138
+ > **Base currency**: The plugin assumes all provider pricing is in USD. Major AI APIs (OpenAI / Anthropic / Google / DeepSeek / xAI etc.) use USD for their international endpoints. If your provider bills in CNY or another currency, set the exchange rate to `1`.
139
+
140
+ ### 4.3 Section Visibility
141
+
142
+ Three sub-sections can be toggled independently to save sidebar space:
143
+
144
+ - **Token Detail**: cache read / write / miss / output
145
+ - **Model & Pricing**: cost / provider / model name / per-million rates
146
+ - **Estimated Token Dist.**: per-role token breakdown
147
+ - **Loaded Skills**: skill names the LLM actually loaded via the `skill` tool, with estimated token counts
148
+ - **Balance**: the selected provider's account balance (multi-provider with auto-switch)
149
+ - **Bottom Status Bar**: the single-line hit rate · Tokens · Balance stats in the prompt hint row
150
+
151
+ Toggled via `/cache-section` — takes effect instantly, no restart required. The same command also toggles the panel **border**; turning it off removes the outline and padding so content fills the full width.
152
+
153
+ > **About Token Dist. values**: "Reasoning" is an exact value from the API; the other rows (system / user / sub-agent instr / tool call / tool result) are **estimates** — the API only reports total token counts, not how they split across content types, so the plugin collects text per content type and approximates via character counting. Values are indicative only. OpenCode runtime-injected system prompt content (environment info, skill catalog, tool schema definitions — see [`system.ts`](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/session/system.ts), [`tools.ts`](https://github.com/anomalyco/opencode/blob/dev/packages/opencode/src/session/tools.ts)) is not covered by these estimates.
154
+
155
+ ### 4.4 Balance Query
156
+
157
+ The panel can display account balance from multiple AI providers. With **auto-switch** enabled, the balance query follows the model provider of the current session automatically.
158
+
159
+ Supported balance providers:
160
+
161
+ | Provider | Balance endpoint | Currency | Key prefix | Status |
162
+ |----------|-----------------|----------|------------|--------|
163
+ | DeepSeek | `https://api.deepseek.com/user/balance` | CNY / USD | `sk-` | ✅ Supported |
164
+ | SiliconFlow | `https://api.siliconflow.cn/v1/user/info` | CNY | `sk-` | ✅ Supported |
165
+ | OpenRouter | `https://openrouter.ai/api/v1/credits` | USD | `sk-or-` | ✅ Supported |
166
+ | Moonshot | `https://api.moonshot.cn/v1/users/me/balance` | CNY | `sk-` | ✅ Supported |
167
+ | Zhipu GLM | Pending (community-reversed endpoint, unofficial) | CNY | — | ⏳ Planned |
168
+ | xAI | Pending (requires Management Key + Team ID) | USD | — | ⏳ Planned |
169
+
170
+ > **Key source**: a key set manually via `/cache-balance-key` takes priority; otherwise the plugin reuses the credential OpenCode already authenticated (`/connect`-configured providers). Providers with neither cannot show a balance.
171
+ >
172
+ > **Key storage**: manually configured API keys are stored in plaintext in the plugin's persistent KV — avoid using on shared devices.
173
+ >
174
+ > **Auto-switch**: enabled by default; picking a provider manually disables it — re-enable anytime via `/cache-balance`. Auto-switch matches the current session's model provider; a provider without a key shows a "not set" hint when selected.
175
+ >
176
+ > **Planned**: candidates confirmed feasible by research, not yet implemented. Zhipu GLM only has a community-reversed unofficial endpoint (no stability guarantee).
177
+ >
178
+ > **Metric semantics**: hit rate = cache read / (fresh input + cache read + cache write), consistent with the industry (OpenAI / Anthropic / Bedrock). "Miss" in the detail view = fresh input + cache write. The bottom-bar Tokens is the input-side total (output excluded). Providers that do not report cache writes separately (e.g. DeepSeek) automatically fall back to the hit/miss formula.
179
+ >
180
+ > **Balance display**: the sidebar and bottom bar share the same balance data, so both show identical values. When the current provider has no balance adapter, the sidebar shows a hint and the bottom bar hides the balance segment.
181
+
182
+ ---
183
+
184
+ ## 5. Update
185
+
186
+ Due to a [known OpenCode issue #6774](https://github.com/anomalyco/opencode/issues/6774), the plugin cache locks to the version installed at first setup and does **not** auto-detect newer releases on npm.
187
+
188
+ To update:
189
+
190
+ **1. Clear the OpenCode plugin cache**
191
+
192
+ ```powershell
193
+ # Windows
194
+ Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\packages\opencode-visual-cache@latest"
195
+ ```
196
+
197
+ ```bash
198
+ # macOS / Linux
199
+ rm -rf ~/.cache/opencode/packages/opencode-visual-cache@latest
200
+ ```
201
+
202
+ **2. Re-install the plugin**
203
+
204
+ Press **`Ctrl + P`** in OpenCode → `install plugin` → `opencode-visual-cache@latest` → Enter
205
+
206
+ **3. Restart OpenCode**
207
+
208
+ ---
209
+
210
+ ## 6. Language Settings
211
+
212
+ The plugin provides three ways to control the display language, listed by priority (highest first):
213
+
214
+ ### 6.1 Runtime Switching (recommended)
215
+
216
+ Type `/cache-lang` in the TUI and select Chinese / English / 日本語 / 한국어 from the dialog. The panel switches immediately without restarting. Your preference is persisted and takes priority over auto-detection on the next launch.
217
+
218
+ ### 6.2 Environment Variable Override
219
+
220
+ Set the `CACHE_TUI_LANG` environment variable before launching to force a specific language (`zh` / `en` / `ja` / `ko`):
221
+
222
+ ```powershell
223
+ # Windows PowerShell
224
+ $env:CACHE_TUI_LANG="en"; opencode
225
+ ```
226
+
227
+ ```bash
228
+ # macOS / Linux
229
+ CACHE_TUI_LANG=en opencode
230
+ ```
231
+
232
+ ### 6.3 Auto Detection
233
+
234
+ Defaults to the system locale automatically. If it doesn't match, switch once with `/cache-lang` and the preference will be remembered.
235
+
236
+ ---
237
+
238
+ ## 7. Compatibility
239
+
240
+ Model-agnostic — works with all OpenCode-compatible AI models (DeepSeek / Claude / GPT etc.).
241
+ Token data and pricing are read via OpenCode SDK standard interfaces.
242
+
243
+ ---
244
+
245
+ ## 8. License
246
+
247
+ MIT
@@ -1 +1 @@
1
- export declare const PLUGIN_VERSION = "1.6.2";
1
+ export declare const PLUGIN_VERSION = "1.7.0-beta.0";
package/dist/_version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  // auto-generated
2
- export const PLUGIN_VERSION = "1.6.2";
2
+ export const PLUGIN_VERSION = "1.7.0-beta.0";
@@ -0,0 +1,37 @@
1
+ /** Extract { r, g, b } (0–255) from a hex string or RGBA-like object. */
2
+ export declare function rgb(raw: unknown): {
3
+ r: number;
4
+ g: number;
5
+ b: number;
6
+ } | null;
7
+ /** HSL saturation of an RGB color (0–1). */
8
+ export declare function saturation(r: number, g: number, b: number): number;
9
+ /**
10
+ * If the colour's saturation exceeds `maxSat`, pull it toward grey
11
+ * until saturation drops to maxSat. Returns a hex string.
12
+ */
13
+ export declare function desaturateTo(raw: unknown, maxSat: number, fallback: string): string;
14
+ /** Darken a hex colour by multiplying each channel by `factor` (0–1). */
15
+ export declare function dimColor(hex: string, factor?: number): string;
16
+ export declare const FALLBACK: {
17
+ readonly primary: "#8B9DAF";
18
+ readonly text: "#C5C5BB";
19
+ readonly muted: "#7A7A72";
20
+ readonly success: "#9CAF8B";
21
+ readonly warning: "#C5B88D";
22
+ readonly error: "#B08A8A";
23
+ readonly border: "#6B6B63";
24
+ };
25
+ /**
26
+ * Desaturation ceiling for the Morandi-style palette.
27
+ *
28
+ * Morandi colours float around 0.15–0.30 saturation in HSL space.
29
+ * 0.28 sits near the upper end of that range: it strips the aggressive
30
+ * punch from high-saturation themes (Dracula, Solarized …) while
31
+ * preserving enough colour identity that green / orange / red hit-rate
32
+ * coding stays distinguishable.
33
+ *
34
+ * Lower → more grey, harder to tell colours apart.
35
+ * Higher → bright themes bleed through and defeat the muted look.
36
+ */
37
+ export declare const MAX_SAT = 0.28;
@@ -0,0 +1,108 @@
1
+ /** Extract { r, g, b } (0–255) from a hex string or RGBA-like object. */
2
+ export function rgb(raw) {
3
+ if (typeof raw === "string" && raw.startsWith("#")) {
4
+ const h = raw.slice(1);
5
+ return {
6
+ r: parseInt(h.slice(0, 2), 16),
7
+ g: parseInt(h.slice(2, 4), 16),
8
+ b: parseInt(h.slice(4, 6), 16),
9
+ };
10
+ }
11
+ if (raw && typeof raw === "object") {
12
+ const o = raw;
13
+ if (typeof o.r === "number" && typeof o.g === "number" && typeof o.b === "number") {
14
+ // RGBA channels may be 0-1 floats; detect and upscale.
15
+ const scale = o.r > 1 || o.g > 1 || o.b > 1 ? 1 : 255;
16
+ return {
17
+ r: Math.round(o.r * scale),
18
+ g: Math.round(o.g * scale),
19
+ b: Math.round(o.b * scale),
20
+ };
21
+ }
22
+ }
23
+ return null;
24
+ }
25
+ /** HSL saturation of an RGB color (0–1). */
26
+ export function saturation(r, g, b) {
27
+ const max = Math.max(r, g, b) / 255;
28
+ const min = Math.min(r, g, b) / 255;
29
+ const delta = max - min;
30
+ if (delta === 0)
31
+ return 0;
32
+ const L = (max + min) / 2;
33
+ return L <= 0.5 ? delta / (max + min) : delta / (2 - max - min);
34
+ }
35
+ /**
36
+ * If the colour's saturation exceeds `maxSat`, pull it toward grey
37
+ * until saturation drops to maxSat. Returns a hex string.
38
+ */
39
+ export function desaturateTo(raw, maxSat, fallback) {
40
+ const c = rgb(raw);
41
+ if (!c)
42
+ return fallback;
43
+ const sat = saturation(c.r, c.g, c.b);
44
+ if (sat <= maxSat) {
45
+ // already muted — return as hex
46
+ return "#" + [c.r, c.g, c.b].map((v) => v.toString(16).padStart(2, "0")).join("");
47
+ }
48
+ /**
49
+ * Binary search for the optimal grey-mix ratio α (0…1).
50
+ *
51
+ * 12 iterations → 1/2^12 ≈ 1/4096 resolution. The downstream RGB
52
+ * channels are only 0–255 (8 bit), so 8 iterations (1/256) would
53
+ * technically suffice; 12 is intentionally over-budget — the extra
54
+ * precision costs almost nothing and guarantees the saturation probe
55
+ * converges to within a fraction of an 8‑bit step, eliminating
56
+ * colour banding in edge cases.
57
+ */
58
+ // Bt.601 luma (perceptual brightness used as the grey anchor)
59
+ const luma = c.r * 0.299 + c.g * 0.587 + c.b * 0.114;
60
+ let lo = 0, hi = 1;
61
+ for (let i = 0; i < 12; i++) {
62
+ const mid = (lo + hi) / 2;
63
+ const nr = Math.round(c.r + (luma - c.r) * mid);
64
+ const ng = Math.round(c.g + (luma - c.g) * mid);
65
+ const nb = Math.round(c.b + (luma - c.b) * mid);
66
+ if (saturation(nr, ng, nb) > maxSat)
67
+ lo = mid;
68
+ else
69
+ hi = mid;
70
+ }
71
+ const nr = Math.round(c.r + (luma - c.r) * hi);
72
+ const ng = Math.round(c.g + (luma - c.g) * hi);
73
+ const nb = Math.round(c.b + (luma - c.b) * hi);
74
+ return "#" + [nr, ng, nb].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
75
+ }
76
+ /** Darken a hex colour by multiplying each channel by `factor` (0–1). */
77
+ export function dimColor(hex, factor = 0.5) {
78
+ const c = rgb(hex);
79
+ if (!c)
80
+ return hex;
81
+ const r = Math.round(c.r * factor);
82
+ const g = Math.round(c.g * factor);
83
+ const b = Math.round(c.b * factor);
84
+ return "#" + [r, g, b].map((v) => Math.max(0, Math.min(255, v)).toString(16).padStart(2, "0")).join("");
85
+ }
86
+ // Morandi fallbacks — used when a theme colour cannot be resolved
87
+ export const FALLBACK = {
88
+ primary: "#8B9DAF",
89
+ text: "#C5C5BB",
90
+ muted: "#7A7A72",
91
+ success: "#9CAF8B",
92
+ warning: "#C5B88D",
93
+ error: "#B08A8A",
94
+ border: "#6B6B63",
95
+ };
96
+ /**
97
+ * Desaturation ceiling for the Morandi-style palette.
98
+ *
99
+ * Morandi colours float around 0.15–0.30 saturation in HSL space.
100
+ * 0.28 sits near the upper end of that range: it strips the aggressive
101
+ * punch from high-saturation themes (Dracula, Solarized …) while
102
+ * preserving enough colour identity that green / orange / red hit-rate
103
+ * coding stays distinguishable.
104
+ *
105
+ * Lower → more grey, harder to tell colours apart.
106
+ * Higher → bright themes bleed through and defeat the muted look.
107
+ */
108
+ export const MAX_SAT = 0.28;