opencode-visual-cache 1.1.0 → 1.1.5
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 +29 -3
- package/README_EN.md +29 -3
- package/dist/_version.d.ts +1 -0
- package/dist/_version.js +2 -0
- package/dist/index.js +2 -1
- package/package.json +2 -1
- package/src/_version.ts +2 -0
- package/src/index.tsx +8 -1
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
在 OpenCode 中按 **`Ctrl + P`** 打开命令面板,搜索 **`install plugin`**,输入:
|
|
46
46
|
|
|
47
47
|
```
|
|
48
|
-
opencode-visual-cache
|
|
48
|
+
opencode-visual-cache@latest
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
回车即可完成安装与配置。
|
|
@@ -55,7 +55,7 @@ opencode-visual-cache
|
|
|
55
55
|
**1. 安装插件**
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
npm install -g opencode-visual-cache
|
|
58
|
+
npm install -g opencode-visual-cache@latest
|
|
59
59
|
```
|
|
60
60
|
|
|
61
61
|
**2. 配置 TUI 插件**
|
|
@@ -65,7 +65,7 @@ npm install -g opencode-visual-cache
|
|
|
65
65
|
```jsonc
|
|
66
66
|
{
|
|
67
67
|
"$schema": "https://opencode.ai/tui.json",
|
|
68
|
-
"plugin": ["opencode-visual-cache"]
|
|
68
|
+
"plugin": ["opencode-visual-cache@latest"]
|
|
69
69
|
}
|
|
70
70
|
```
|
|
71
71
|
|
|
@@ -75,6 +75,32 @@ npm install -g opencode-visual-cache
|
|
|
75
75
|
|
|
76
76
|
---
|
|
77
77
|
|
|
78
|
+
## 更新
|
|
79
|
+
|
|
80
|
+
由于 [OpenCode 已知问题 #6774](https://github.com/anomalyco/opencode/issues/6774),插件缓存会锁死在首次安装时的版本,不会自动检测 npm 上的新版本。
|
|
81
|
+
|
|
82
|
+
更新步骤:
|
|
83
|
+
|
|
84
|
+
**1. 清除 OpenCode 插件缓存**
|
|
85
|
+
|
|
86
|
+
```powershell
|
|
87
|
+
# Windows
|
|
88
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\packages\opencode-visual-cache@latest"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# macOS / Linux
|
|
93
|
+
rm -rf ~/.cache/opencode/packages/opencode-visual-cache@latest
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**2. 重新安装插件**
|
|
97
|
+
|
|
98
|
+
在 OpenCode 中按 **`Ctrl + P`** → `install plugin` → `opencode-visual-cache@latest` → 回车
|
|
99
|
+
|
|
100
|
+
**3. 重启 OpenCode**
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
78
104
|
## 调试
|
|
79
105
|
|
|
80
106
|
强制英文(Windows PowerShell):
|
package/README_EN.md
CHANGED
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
Press **`Ctrl + P`** in OpenCode to open the command palette, search **`install plugin`**, then type:
|
|
47
47
|
|
|
48
48
|
```
|
|
49
|
-
opencode-visual-cache
|
|
49
|
+
opencode-visual-cache@latest
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
Press Enter to install and configure automatically.
|
|
@@ -56,7 +56,7 @@ Press Enter to install and configure automatically.
|
|
|
56
56
|
**1. Install the plugin**
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
npm install -g opencode-visual-cache
|
|
59
|
+
npm install -g opencode-visual-cache@latest
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
**2. Configure TUI plugin**
|
|
@@ -66,7 +66,7 @@ Create or edit `~/.config/opencode/tui.jsonc`:
|
|
|
66
66
|
```jsonc
|
|
67
67
|
{
|
|
68
68
|
"$schema": "https://opencode.ai/tui.json",
|
|
69
|
-
"plugin": ["opencode-visual-cache"]
|
|
69
|
+
"plugin": ["opencode-visual-cache@latest"]
|
|
70
70
|
}
|
|
71
71
|
```
|
|
72
72
|
|
|
@@ -76,6 +76,32 @@ Open any session — the cache stats panel appears in the sidebar.
|
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
|
+
## Update
|
|
80
|
+
|
|
81
|
+
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.
|
|
82
|
+
|
|
83
|
+
To update:
|
|
84
|
+
|
|
85
|
+
**1. Clear the OpenCode plugin cache**
|
|
86
|
+
|
|
87
|
+
```powershell
|
|
88
|
+
# Windows
|
|
89
|
+
Remove-Item -Recurse -Force "$env:USERPROFILE\.cache\opencode\packages\opencode-visual-cache@latest"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# macOS / Linux
|
|
94
|
+
rm -rf ~/.cache/opencode/packages/opencode-visual-cache@latest
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**2. Re-install the plugin**
|
|
98
|
+
|
|
99
|
+
Press **`Ctrl + P`** in OpenCode → `install plugin` → `opencode-visual-cache@latest` → Enter
|
|
100
|
+
|
|
101
|
+
**3. Restart OpenCode**
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
79
105
|
## Debug
|
|
80
106
|
|
|
81
107
|
Force English:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const PLUGIN_VERSION = "1.1.5";
|
package/dist/_version.js
ADDED
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@opentui/solid/jsx-runtime";
|
|
2
2
|
import { createMemo, createSignal, Show } from "solid-js";
|
|
3
|
+
import { PLUGIN_VERSION } from "./_version";
|
|
3
4
|
// ── terminal-width helpers ────────────────────────────────────────
|
|
4
5
|
// CJK characters occupy 2 terminal columns; padEnd/padStart count
|
|
5
6
|
// string length (=1 per char), which breaks alignment with mixed text.
|
|
@@ -331,7 +332,7 @@ function TokenCachePanel(props) {
|
|
|
331
332
|
// 通过 ref 获取 Renderable 实例宽度
|
|
332
333
|
const w = boxEl ? Math.max(MIN_PANEL_WIDTH, boxEl.width) : DEFAULT_PANEL_WIDTH;
|
|
333
334
|
setPanelWidth((prev) => (prev === w ? prev : w));
|
|
334
|
-
}, children: [_jsxs("text", { onMouseUp: () => setOpen((o) => !o), children: [_jsx("span", { style: { fg: pal().muted }, children: open() ? "\u25bc " : "\u25b6 " }),
|
|
335
|
+
}, children: [_jsxs("text", { onMouseUp: () => setOpen((o) => !o), children: [_jsx("span", { style: { fg: pal().muted }, children: open() ? "\u25bc " : "\u25b6 " }), _jsxs("span", { style: { fg: pal().primary }, children: [_jsx("b", { children: T.title }), _jsx(Show, { when: open(), children: _jsxs("span", { style: { fg: pal().muted }, children: [" (v", PLUGIN_VERSION, ")"] }) })] }), _jsxs(Show, { when: !open() && data().hasData, children: [_jsxs(Show, { when: data().hasTrendData, children: [_jsx("span", { children: " ".repeat(Math.max(1, panelWidth() - GUTTER - HEADER_PREFIX - visualWidth(T.title) - visualWidth(pct() + " " + T.hitFolded + " " + trendLabel(data().trend)))) }), _jsxs("span", { style: { fg: hitColor() }, children: [pct(), " ", T.hitFolded] }), _jsxs("span", { style: { fg: data().trend !== 0 ? (data().trend > 0 ? pal().success : pal().error) : pal().text }, children: [" ", trendLabel(data().trend)] })] }), _jsxs(Show, { when: !data().hasTrendData, children: [_jsx("span", { children: " ".repeat(Math.max(1, panelWidth() - GUTTER - HEADER_PREFIX - visualWidth(T.title) - visualWidth(pct() + " " + T.hitFolded))) }), _jsxs("span", { style: { fg: hitColor() }, children: [pct(), " ", T.hitFolded] })] })] })] }), _jsx(Show, { when: open(), children: _jsxs(Show, { when: data().hasData, fallback: _jsxs(_Fragment, { children: [_jsx("text", { fg: pal().muted, children: sep() }), _jsxs("text", { children: [_jsx("span", { style: { fg: pal().muted }, children: "> " }), _jsx("span", { style: { fg: pal().muted }, children: T.noData })] })] }), children: [_jsx("text", { fg: pal().muted, children: sep() }), _jsxs("text", { children: [_jsxs("span", { style: { fg: pal().text }, children: [T.hit, " "] }), _jsxs("span", { style: { fg: hitColor() }, children: ["[", bar(), "] "] }), _jsx("span", { style: { fg: pal().text }, children: pct() }), _jsx(Show, { when: data().hasTrendData, children: _jsxs("span", { style: { fg: data().trend !== 0 ? (data().trend > 0 ? pal().success : pal().error) : pal().text }, children: [" ", trendLabel(data().trend)] }) })] }), _jsx("text", { fg: pal().muted, children: justify(T.totalHit, data().sessionHitRate.toFixed(1) + "%") }), _jsx(Show, { when: data().read > 0, children: _jsx("text", { fg: pal().muted, children: justify(T.read, fmt(data().read), T.tok) }) }), _jsx(Show, { when: data().write > 0, children: _jsx("text", { fg: pal().muted, children: justify(T.write, fmt(data().write), T.tok) }) }), _jsx("text", { fg: pal().muted, children: justify(T.miss, fmt(data().freshInput), T.tok) }), _jsx("text", { fg: pal().muted, children: justify(T.out, fmt(data().output), T.tok) }), _jsx("text", { fg: pal().muted, children: sep() }), _jsx("text", { fg: pal().text, children: justify(T.cost, fmtCost(data().cost)) }), _jsx(Show, { when: data().saved > 0, children: _jsxs("text", { children: [_jsx("span", { style: { fg: pal().muted }, children: T.saved }), _jsx("span", { children: " ".repeat(Math.max(1, panelWidth() - GUTTER - visualWidth(T.saved) - visualWidth("~" + fmtCost(data().saved)))) }), _jsxs("span", { style: { fg: pal().success }, children: ["~", fmtCost(data().saved)] })] }) }), _jsx(Show, { when: data().providerName, children: _jsx("text", { fg: pal().muted, children: justify(T.provider, data().providerName) }) }), _jsx("text", { fg: pal().muted, children: justify(T.model, data().model) }), _jsxs(Show, { when: data().hasPricing, children: [_jsx("text", { fg: pal().muted, children: justify(T.rate, "$" + data().inputRate.toFixed(2) + "/M " + T.inputRate) }), _jsx(Show, { when: data().cacheReadRate > 0, children: _jsx("text", { fg: pal().muted, children: justify("", "$" + data().cacheReadRate.toFixed(2) + "/M " + T.cacheRate) }) }), _jsx(Show, { when: data().cacheWriteRate > 0, children: _jsx("text", { fg: pal().muted, children: justify("", "$" + data().cacheWriteRate.toFixed(2) + "/M " + T.writeRate) }) })] })] }) })] }));
|
|
335
336
|
}
|
|
336
337
|
// ---------------------------------------------------------------------------
|
|
337
338
|
// Plugin entry
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-visual-cache",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "OpenCode TUI plugin displaying real-time token cache hit rate in the sidebar",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"scripts": {
|
|
31
31
|
"build": "tsc",
|
|
32
32
|
"typecheck": "tsc --noEmit",
|
|
33
|
+
"version": "node -e \"require('fs').writeFileSync('src/_version.ts','// auto-generated\\nexport const PLUGIN_VERSION='+JSON.stringify(require('./package.json').version)+';\\n')\"",
|
|
33
34
|
"prepublishOnly": "tsc"
|
|
34
35
|
},
|
|
35
36
|
"keywords": [
|
package/src/_version.ts
ADDED
package/src/index.tsx
CHANGED
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
} from "@opencode-ai/plugin/tui"
|
|
12
12
|
import type { AssistantMessage, Message } from "@opencode-ai/sdk"
|
|
13
13
|
import { createMemo, createSignal, Show } from "solid-js"
|
|
14
|
+
import { PLUGIN_VERSION } from "./_version"
|
|
14
15
|
|
|
15
16
|
// ---------------------------------------------------------------------------
|
|
16
17
|
// Helpers
|
|
@@ -223,6 +224,7 @@ const PCT_FIXED_WIDTH = 5 // "XX.X%" 固定 5 字符宽度
|
|
|
223
224
|
const HEADER_PREFIX = 2 // 折叠态标题行:▶/▼ 图标 + 后面的空格
|
|
224
225
|
const UNIT_GAP = 1 // 计量单位前的空格(如 "tok")
|
|
225
226
|
|
|
227
|
+
|
|
226
228
|
function TokenCachePanel(props: {
|
|
227
229
|
theme: TuiThemeCurrent
|
|
228
230
|
api: TuiPluginApi
|
|
@@ -381,7 +383,12 @@ function TokenCachePanel(props: {
|
|
|
381
383
|
{/* collapsible header */}
|
|
382
384
|
<text onMouseUp={() => setOpen((o) => !o)}>
|
|
383
385
|
<span style={{ fg: pal().muted }}>{open() ? "\u25bc " : "\u25b6 "}</span>
|
|
384
|
-
<span style={{ fg: pal().primary }}
|
|
386
|
+
<span style={{ fg: pal().primary }}>
|
|
387
|
+
<b>{T.title}</b>
|
|
388
|
+
<Show when={open()}>
|
|
389
|
+
<span style={{ fg: pal().muted }}> (v{PLUGIN_VERSION})</span>
|
|
390
|
+
</Show>
|
|
391
|
+
</span>
|
|
385
392
|
<Show when={!open() && data().hasData}>
|
|
386
393
|
<Show when={data().hasTrendData}>
|
|
387
394
|
<span>
|