diff --git a/README.md b/README.md index 0007a48..48d856c 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,8 @@ Load errors: `~/.local/share/opencode/log/` (search `cache-hit` or `failed to lo ## Configuration +Configuration files accept JSONC (line/block comments and trailing commas). `cache-hit.config.example.json` ships as strict JSON so it stays tool-friendly (jq, editors). + ### Cost display (USD → CNY example) ```json @@ -105,7 +107,7 @@ Load errors: `~/.local/share/opencode/log/` (search `cache-hit` or `failed to lo | `currency` | Sidebar display currency | | `rate` | Multiply `costUnit` → `currency` | -Use `"currency": "USD", "costUnit": "USD"` when no conversion is needed. +`rate` is a **manual snapshot** — the `6.77` in the example is the USD→CNY rate at the time it was written and does not auto-update. Omitting `rate` falls back to the same built-in default, so it only needs to be set when you display a non-USD currency and want a current rate (e.g. from [Xe](https://www.xe.com/currencyconverter/), [Wise](https://wise.com/currency-converter), or [OANDA](https://www.oanda.com/currency-converter/)). Use `"currency": "USD", "costUnit": "USD"` when no conversion is needed. Supported display currencies in config: `USD`, `CNY`, `EUR`, `GBP`, `JPY` (see `cache-hit.config.example.json`). Runtime slash switching like visual-cache’s `/cache-currency` is **not** implemented yet. @@ -271,7 +273,7 @@ Then reinstall via `Ctrl+P` → install plugin, and **restart OpenCode**. To avoid the pinning issue entirely, install a **pinned version** instead of `@latest`: ```jsonc -{ "plugin": ["opencode-cache-hit@0.7.0"] } +{ "plugin": ["opencode-cache-hit@0.7.1"] } ``` ## Compatibility diff --git a/README.zh-CN.md b/README.zh-CN.md index 68bc8d6..8799132 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -89,6 +89,8 @@ OpenCode **TUI 侧边栏插件**:展示 prompt cache 命中率、token 用量 ## 配置 +配置文件支持 JSONC(行注释、块注释、尾逗号)。`cache-hit.config.example.json` 保持严格 JSON,便于 jq、编辑器等外部工具使用。 + ### 成本展示(USD → CNY 示例) ```json @@ -105,7 +107,7 @@ OpenCode **TUI 侧边栏插件**:展示 prompt cache 命中率、token 用量 | `currency` | 侧边栏展示币种 | | `rate` | `costUnit` → `currency` 的汇率 | -当无需换算时使用 `"currency": "USD", "costUnit": "USD"`。 +`rate` 是**手动维护的快照值**——示例中的 `6.77` 是当时 USD→CNY 的汇率,不会自动更新。省略 `rate` 时回落到内置默认值 6.77,因此只有在展示非 USD 币种且希望汇率准确时才需要设置(可到 [Xe](https://www.xe.com/currencyconverter/)、[Wise](https://wise.com/currency-converter) 或 [OANDA](https://www.oanda.com/currency-converter/) 查询最新汇率)。当无需换算时使用 `"currency": "USD", "costUnit": "USD"`。 支持的展示币种:`USD`、`CNY`、`EUR`、`GBP`、`JPY`(见 `cache-hit.config.example.json`)。暂未实现类似 visual-cache 的 `/cache-currency` 斜杠命令。 diff --git a/cache-hit.config.example.json b/cache-hit.config.example.json index 01ddc7d..2299fe3 100644 --- a/cache-hit.config.example.json +++ b/cache-hit.config.example.json @@ -3,6 +3,7 @@ "currency": "CNY", "costUnit": "USD", "rate": 6.77, + "$comment-rate": "Manual exchange-rate snapshot USD→currency (6.77 = USD→CNY at the time this was written; does not auto-update). Omit to keep the built-in default 6.77, or set \"currency\": \"USD\" to skip conversion. Current rates: xe.com, wise.com, oanda.com.", "display": { "lang": "en", "panelBorder": true, diff --git a/package.json b/package.json index cba7ba7..f2c2351 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "opencode-cache-hit", - "version": "0.7.0", + "version": "0.7.1", "description": "OpenCode TUI sidebar: prompt cache hit rate, tokens & cost with sub-agent rollup. Works with opencode-visual-cache; optional per-call JSONL timeline.", "type": "module", "license": "MIT", diff --git a/src/format-cost.ts b/src/format-cost.ts index 16addb2..41d86f7 100644 --- a/src/format-cost.ts +++ b/src/format-cost.ts @@ -26,6 +26,7 @@ export const CURRENCY_PRESETS: Record { @@ -44,4 +45,42 @@ describe("load-config paths", () => { expect(DEFAULT_PLUGIN_CONFIG.timeline.toolSummary).toEqual({ allTools: true, bash: false }) expect(DEFAULT_PLUGIN_CONFIG.display.lang).toBe("en") }) + + test("parses JSONC configs — comments and trailing commas", () => { + const dir = mkdtempSync(join(tmpdir(), "cache-hit-")) + const path = join(dir, "cache-hit.json") + writeFileSync( + path, + [ + "{", + ' // line comment', + ' "currency": "USD",', + ' "costUnit": "USD",', + ' "display": { "lang": "zh" }, // trailing comma + comment', + ' /* block comment */ "timeline": { "enabled": false },', + "}", + ].join("\n"), + ) + try { + const cfg = tryRead(path) + expect(cfg).not.toBeNull() + expect(cfg?.cost.currency).toBe("USD") + expect(cfg?.cost.costUnit).toBe("USD") + expect(cfg?.display.lang).toBe("zh") + expect(cfg?.timeline.enabled).toBe(false) + } finally { + rmSync(dir, { recursive: true, force: true }) + } + }) + + test("returns null for malformed config content", () => { + const dir = mkdtempSync(join(tmpdir(), "cache-hit-")) + const path = join(dir, "bad.json") + writeFileSync(path, "{ nope") + try { + expect(tryRead(path)).toBeNull() + } finally { + rmSync(dir, { recursive: true, force: true }) + } + }) })