pi-cache-optimizer 2.8.2 → 2.8.4

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 (4) hide show
  1. package/README.md +24 -18
  2. package/README.zh-CN.md +24 -17
  3. package/index.ts +915 -435
  4. package/package.json +4 -4
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Pi Cache Optimizer
2
2
 
3
+ [![CI](https://github.com/jiangge/pi-cache-optimizer/actions/workflows/ci.yml/badge.svg)](https://github.com/jiangge/pi-cache-optimizer/actions/workflows/ci.yml)
3
4
  [![npm version](https://img.shields.io/npm/v/pi-cache-optimizer.svg)](https://www.npmjs.com/package/pi-cache-optimizer)
4
5
  [![npm downloads](https://img.shields.io/npm/dm/pi-cache-optimizer.svg)](https://www.npmjs.com/package/pi-cache-optimizer)
5
6
  [![license](https://img.shields.io/npm/l/pi-cache-optimizer.svg)](./LICENSE)
@@ -34,7 +35,8 @@ Pi extension for improving provider-side KV / prompt cache hit rates. It keeps s
34
35
  - Adds a session-id `prompt_cache_key` fallback for `openai-completions` / `openai-responses` payloads when no effective key exists, including Pi's built-in `llama.cpp` provider as Pi 0.82+ core does.
35
36
  - Warns once for third-party OpenAI-compatible proxies missing cache/session-affinity compat flags.
36
37
  - Detects adaptive-thinking compat for Claude (opus-4.6+ including Opus 5, sonnet-4.6+ including Sonnet 5, fable-5+) and Kimi Coding K3 / `kimi-for-coding` custom channels.
37
- - Shows daily cumulative provider/model footer stats by default, with an opt-in current-session display mode.
38
+ - Stores cache statistics in per-extension-instance atomic shards, so parent sessions, child Pi agents, and parallel Pi processes cannot overwrite one another.
39
+ - Shows current conversation-session provider/model footer stats by default; `total` aggregates all valid local shards for the exact provider/model.
38
40
  - Supports optional router-extension integration through versioned global protocols (`Symbol.for("pi.routing.registry.v1")` and `Symbol.for("pi.cache.hints.v1")`) without importing router packages.
39
41
 
40
42
  Caching is provider-side and best-effort. Third-party proxies and router extensions can still hide cache usage, reject unsupported parameters, or route requests across multiple upstreams.
@@ -55,7 +57,7 @@ Run `/reload` in Pi after install/update/remove so extension hooks refresh.
55
57
 
56
58
  On Pi 0.79.7 and newer, `pi update` updates Pi itself only. To update installed Pi packages such as this extension, run `pi update --extensions` (packages only) or `pi update --all` (Pi + packages).
57
59
 
58
- This extension is validated against Pi 0.84.1 and remains designed for Pi 0.82+. It uses the existing extension hooks, `getAgentDir()`, and prompt options shared by those versions; it does not depend on Pi 0.83+ APIs such as `ctx.scopedModels` or the bundled TypeBox 1.3 aliases.
60
+ This extension requires Pi 0.82+ and is validated against Pi 0.84.2. It uses the official Pi package types directly for type-checking, along with extension hooks, `getAgentDir()`, and prompt options shared by those versions; it does not depend on Pi 0.83+ APIs such as `ctx.scopedModels` or the bundled TypeBox 1.3 aliases.
59
61
 
60
62
  ## Commands
61
63
 
@@ -66,12 +68,14 @@ This extension is validated against Pi 0.84.1 and remains designed for Pi 0.82+.
66
68
  | `/cache-optimizer disable` | Disables optimization for the current Pi process, resets local footer stats, and keeps collecting footer stats in disabled comparison mode. Run `/reload` or restart Pi to return to startup behavior. |
67
69
  | `/cache-optimizer doctor` | Shows active model/provider/API/base URL/compat plus low-hit diagnosis. |
68
70
  | `/cache-optimizer compat` | Shows copyable compat advice for the active model, if applicable. |
69
- | `/cache-optimizer stats` | Shows today's local provider/model counters and recent trend for the active model. |
71
+ | `/cache-optimizer stats` | Shows detailed counters for every cache-adapter-matched model used by the current conversation session today. |
72
+ | `/cache-optimizer stats all` | Shows detailed per-model totals across all valid local sessions/shards today, including request and token counts. |
73
+ | `/cache-optimizer stats contributors` | Shows current/other contributing sessions for the active exact provider/model without exposing session ids. |
70
74
  | `/cache-optimizer reset` | Resets local footer stats for the active provider/model; upstream provider cache is not modified. |
71
75
  | `/cache-optimizer config footer-mode total\|session\|process` | Persist the footer stats mode. Persistent command configuration overrides the environment variable. |
72
76
  | `/cache-optimizer fix` | Auto-repairs safe compat issues for the active model (adaptive thinking, DeepSeek reasoning, OpenAI proxy session affinity). Shows preview + risk warning, requires confirmation. **Only modifies `models.json` after explicit user approval.** |
73
77
 
74
- `/cache-optimizer` uses Pi's native Tab completion. Type `/cache-optimizer <Tab>` for the supported subcommands, `/cache-optimizer c<Tab>` for `config`, `/cache-optimizer config <Tab>` for `footer-mode`, and `/cache-optimizer config footer-mode <Tab>` for `total`, `session`, or `process`. Suggestions are prefix-filtered and invalid prefixes are left to Pi's normal fallback behavior.
78
+ `/cache-optimizer` uses Pi's native Tab completion. Type `/cache-optimizer <Tab>` for the supported subcommands, `/cache-optimizer stats <Tab>` for `all` or `contributors`, `/cache-optimizer c<Tab>` for `config`, `/cache-optimizer config <Tab>` for `footer-mode`, and `/cache-optimizer config footer-mode <Tab>` for `total`, `session`, or `process`. Suggestions are prefix-filtered and invalid prefixes are left to Pi's normal fallback behavior.
75
79
 
76
80
  The interactive `/cache-optimizer` menu includes `Footer mode`, where you can choose `total`, `session`, or `process`. `enable` / `disable` are current-process switches. For a persistent opt-out, use environment variables below.
77
81
 
@@ -86,14 +90,15 @@ The interactive `/cache-optimizer` menu includes `Footer mode`, where you can ch
86
90
 
87
91
  ## Footer cache stats mode
88
92
 
89
- **v2.7.0+** supports daily cumulative and conversation-session footer scopes. **v2.7.1** adds the Footer mode option to the interactive `/cache-optimizer` menu. **v2.8.0+** also supports process-scoped counters. The footer defaults to `total`, which shows the provider/model's local counters for the current day across Pi sessions and process restarts. Use either the command or environment variable to select the scope:
93
+ Current versions store stats under `pi-cache-optimizer-stats.d/shards/` in Pi's agent directory. Each loaded extension instance owns one UUID-named shard and writes it through temp-file + atomic rename. This prevents parent/child/parallel Pi processes from overwriting one another. Upgrading from the old v6 single-file format deletes the old local stats files and starts footer counters from zero; upstream provider caches are not affected.
94
+
95
+ The footer defaults to `session`, which reflects the current Pi conversation rather than another parallel Pi terminal using the same provider/model. Use either the command or environment variable to select the scope:
90
96
 
91
97
  | Value | Effect |
92
98
  |---|---|
93
- | `total` (default) | Show today's restart-persistent provider/model totals across sessions. Local day rollover resets the counters. |
94
- | `session` | Show only the current hashed Pi conversation session's counters. A fresh conversation session starts at `0/0`; restarting Pi while resuming the same session restores that session bucket. |
95
-
96
- | `process` | Show only counters collected by the current Pi process. It starts at `0/0` after Pi restart or extension reload and is never restored from disk. |
99
+ | `session` (default) | Aggregate today's shards carrying the current hashed Pi conversation session id and exact provider/model. A reload creates a new instance shard but remains in the same session scope. |
100
+ | `total` | Aggregate today's valid local shards for the exact provider/model across sessions, including child Pi agents that load this extension and share the same agent directory. |
101
+ | `process` | Show only counters collected by the current extension instance. It starts at `0/0` after Pi restart or extension reload. |
97
102
 
98
103
  Persistent command configuration takes precedence over the environment variable:
99
104
 
@@ -103,7 +108,7 @@ Persistent command configuration takes precedence over the environment variable:
103
108
  /cache-optimizer config footer-mode process
104
109
  ```
105
110
 
106
- The explicit setting is stored in `pi-cache-optimizer-config.json` under Pi's agent directory. If no command override exists, `PI_CACHE_OPTIMIZER_FOOTER_MODE=total|session|process` is used; values are case-insensitive, and missing or invalid values fall back to `total`. To return an existing installation to environment-controlled behavior, manually delete `pi-cache-optimizer-config.json` and run `/reload`.
111
+ The explicit setting is stored in `pi-cache-optimizer-config.json` under Pi's agent directory. If no command override exists, `PI_CACHE_OPTIMIZER_FOOTER_MODE=total|session|process` is used; values are case-insensitive, and missing or invalid values fall back to `session`. To return an existing installation to environment-controlled behavior, manually delete `pi-cache-optimizer-config.json` and run `/reload`.
107
112
 
108
113
  ## OpenAI-compatible proxy setup
109
114
 
@@ -135,7 +140,7 @@ Notes:
135
140
 
136
141
  - `sendSessionAffinityHeaders: true` is the safe default when your proxy supports sticky routing.
137
142
  - `supportsLongCacheRetention: true` is optional. Add it only when the endpoint explicitly supports OpenAI long prompt cache retention.
138
- - If you see `400 Unsupported parameter: prompt_cache_retention`, remove/avoid `supportsLongCacheRetention` for that channel. Keep `sendSessionAffinityHeaders` if supported.
143
+ - If you see `400 Unsupported parameter: prompt_cache_retention`, remove/avoid `supportsLongCacheRetention` for that channel. Keep `sendSessionAffinityHeaders` if supported. The extension detects the explicit error from response headers or the finalized assistant error message and strips the parameter from subsequent requests in the current process.
139
144
  - Use `/cache-optimizer compat` or `/cache-optimizer doctor` to see model-specific advice.
140
145
  - For DeepSeek models, the Pi Mono guidance expects `compat.requiresReasoningContentOnAssistantMessages: true` and `compat.thinkingFormat: "deepseek"` alongside cache/session-affinity flags when the endpoint supports them.
141
146
  - This extension's `doctor` and `compat` commands only advise; they do not modify `models.json`.
@@ -229,8 +234,9 @@ Pi 0.80.9+ already includes Kimi K3 in built-in Kimi Coding, Moonshot AI / China
229
234
  2. Warns: ① changes affect all sessions using that channel, ② automatic backup created at `models.json.backup-cache-optimizer-<timestamp>`, ③ Pi reload required
230
235
  3. Uses comment-preserving surgical editor — existing comments, indentation, and existing key order are preserved
231
236
  4. Requires explicit user confirmation (interactive prompt or `ui.select`)
232
- 5. Writes atomically (temp + rename); self-validates after write
233
- 6. Falls back to manual guidance if JSONC scanner cannot confidently locate the target
237
+ 5. Writes and restores atomically (temp + rename); self-validates after write
238
+ 6. Preserves the existing `models.json` access mode exactly — it does not tighten or loosen permissions (for example, `0600` stays `0600`, `0644` stays `0644`)
239
+ 7. Uses unique, non-overwriting backup names and falls back to manual guidance if the JSONC scanner cannot confidently locate the target
234
240
 
235
241
  Existing `modelOverrides[modelId]` entries have Pi's highest precedence, so `fix` repairs them directly. For built-in or API-login models without a custom `models[]` entry, `fix` creates a compat-only `modelOverrides` entry instead of inventing a custom model definition. Self-validation checks the effective three-layer compat result, so a lower-level edit shadowed by an override is rejected.
236
242
 
@@ -276,7 +282,7 @@ If only one model should change, use `modelOverrides`:
276
282
 
277
283
  ## Footer stats
278
284
 
279
- Stats are read-only local counters stored in Pi's agent directory (default: `~/.pi/agent/pi-cache-optimizer-stats.json`; custom agent dirs use `PI_CODING_AGENT_DIR`). Both today's provider/model totals and hashed session buckets are maintained. The footer shows daily totals by default, the conversation-session bucket in `session` mode, or the in-memory process bucket in `process` mode. The stats file contains only dates and numeric counters — no API keys, prompts, payloads, headers, responses, or model output. Footer mode configuration is stored separately in `pi-cache-optimizer-config.json`. Process-mode counters are memory-only and are intentionally absent from that file.
285
+ Stats are read-only local counters stored as UUID-owned shards under `pi-cache-optimizer-stats.d/shards/` in Pi's agent directory (custom agent dirs use `PI_CODING_AGENT_DIR`). Shards contain only dates, opaque session hashes, exact provider/model counters, reset epochs, and process lifecycle metadata — no API keys, prompts, payloads, headers, responses, or model output. The footer defaults to the current conversation session; `total` aggregates all valid current-day shards for the exact provider/model, and `process` shows only the current extension instance. Footer mode configuration is stored separately in `pi-cache-optimizer-config.json`. Upgrading from the old v6 shared stats files deletes those local counters instead of migrating them.
280
286
 
281
287
  Pi 0.79+ also includes a built-in footer `CH` marker for the latest prompt cache hit rate. This extension complements that marker with persisted provider/model counters plus proxy compat diagnostics.
282
288
 
@@ -286,7 +292,7 @@ Example footer:
286
292
  · OpenAI cache 3/10·0.002M/0.005M 40.0% ⚠️ compat
287
293
  ```
288
294
 
289
- The leading `· ` is owned by this extension and separates its status from statuses published by other extensions in the same footer. It is present for normal, disabled, router-restored, and warning-suffixed statuses. The compact footer format is `<label> <hit requests>/<total requests>·<cached input tokens>/<total input tokens> <token hit rate>`; token hit rate keeps one decimal place and the footer omits the redundant `tok` suffix. `/cache-optimizer stats` output is unchanged. Some adapters may also append `·write <tokens>`, and runtime diagnostics may append `⚠️ compat` or `⚠️ integrity`.
295
+ The leading `· ` is owned by this extension and separates its status from statuses published by other extensions in the same footer. It is present for normal, disabled, router-restored, and warning-suffixed statuses. The compact footer format is `<label> <hit requests>/<total requests>·<cached input tokens>/<total input tokens> <token hit rate>`; token hit rate keeps one decimal place and the footer omits the redundant `tok` suffix. `/cache-optimizer stats` lists detailed current-session models; `/cache-optimizer stats all` lists all local models and includes compact summaries such as `4/5·0.66M/0.84M 78.7%`. Some adapters may also append `·write <tokens>`, and runtime diagnostics may append `⚠️ compat` or `⚠️ integrity`.
290
296
 
291
297
  Supported footer labels include: DS, Claude, OpenAI, Gemini, Kimi, Qwen, GLM, MiniMax, Mimo, Hunyuan, Mistral, Grok, Llama, Nemotron, Cohere, Yi, Doubao, ERNIE, Baichuan, StepFun, Spark, InternLM, Gemma, Phi, Jamba, Solar, Sonar, Nova, Reka, Falcon, DBRX, MPT, StableLM, Aquila, EXAONE, HyperCLOVA, Luminous, Hermes, Granite, Arctic, Pangu, SenseNova, Zhinao, MiniCPM, XVERSE, Orion, OpenChat, Vicuna, Wizard, Zephyr, Dolphin, OpenOrca, Starling, BLOOM, RWKV, and Aya.
292
298
 
@@ -409,9 +415,9 @@ Then run `/reload` or restart Pi. Optional local state cleanup (if you use `PI_C
409
415
 
410
416
  | Platform | Delete local state files |
411
417
  |---|---|
412
- | Linux / macOS / WSL | `rm -f ~/.pi/agent/pi-cache-optimizer-stats.json ~/.pi/agent/pi-cache-optimizer-config.json ~/.pi/agent/deepseek-cache-optimizer-stats.json` |
413
- | Windows PowerShell | `Remove-Item -Force "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-stats.json", "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-config.json", "$env:USERPROFILE\.pi\agent\deepseek-cache-optimizer-stats.json" -ErrorAction SilentlyContinue` |
414
- | Windows Command Prompt | `del /f /q "%USERPROFILE%\.pi\agent\pi-cache-optimizer-stats.json" "%USERPROFILE%\.pi\agent\pi-cache-optimizer-config.json" "%USERPROFILE%\.pi\agent\deepseek-cache-optimizer-stats.json" 2>nul` |
418
+ | Linux / macOS / WSL | `rm -rf ~/.pi/agent/pi-cache-optimizer-stats.d ~/.pi/agent/pi-cache-optimizer-stats.json ~/.pi/agent/deepseek-cache-optimizer-stats.json ~/.pi/agent/pi-cache-optimizer-config.json` |
419
+ | Windows PowerShell | `Remove-Item -Recurse -Force "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-stats.d", "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-stats.json", "$env:USERPROFILE\.pi\agent\deepseek-cache-optimizer-stats.json", "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-config.json" -ErrorAction SilentlyContinue` |
420
+ | Windows Command Prompt | `rmdir /s /q "%USERPROFILE%\.pi\agent\pi-cache-optimizer-stats.d" & del /f /q "%USERPROFILE%\.pi\agent\pi-cache-optimizer-stats.json" "%USERPROFILE%\.pi\agent\deepseek-cache-optimizer-stats.json" "%USERPROFILE%\.pi\agent\pi-cache-optimizer-config.json" 2>nul` |
415
421
 
416
422
  Do not delete `models.json` during cleanup; it contains your Pi model/provider configuration and is not owned by this package.
417
423
 
package/README.zh-CN.md CHANGED
@@ -1,5 +1,6 @@
1
1
  # Pi Cache Optimizer
2
2
 
3
+ [![CI](https://github.com/jiangge/pi-cache-optimizer/actions/workflows/ci.yml/badge.svg)](https://github.com/jiangge/pi-cache-optimizer/actions/workflows/ci.yml)
3
4
  [![npm version](https://img.shields.io/npm/v/pi-cache-optimizer.svg)](https://www.npmjs.com/package/pi-cache-optimizer)
4
5
  [![npm downloads](https://img.shields.io/npm/dm/pi-cache-optimizer.svg)](https://www.npmjs.com/package/pi-cache-optimizer)
5
6
  [![license](https://img.shields.io/npm/l/pi-cache-optimizer.svg)](./LICENSE)
@@ -34,7 +35,8 @@
34
35
  - 对 `openai-completions` / `openai-responses` 请求,在没有有效 key 时使用 Pi session id 补 `prompt_cache_key`;Pi 0.82+ core 对内置 `llama.cpp` 也使用这一语义。
35
36
  - 对缺少缓存 / session-affinity compat 的第三方 OpenAI-compatible 代理给出一次性提醒。
36
37
  - 检测 Claude(opus-4.6+ 含 Opus 5、sonnet-4.6+ 含 Sonnet 5、fable-5+)以及 Kimi Coding K3 / `kimi-for-coding` 自定义渠道的 adaptive-thinking compat。
37
- - 默认显示按本地日期累计的 provider/model footer 缓存统计,也可切换为仅显示当前 session。
38
+ - 使用每个 extension instance 独占的原子 shard 保存缓存统计,避免父会话、子 Pi agent 和并行 Pi 进程互相覆盖。
39
+ - Footer 默认显示当前 conversation session 的 provider/model 统计;`total` 可聚合同一精确 provider/model 的所有有效本地 shard。
38
40
  - 通过版本化全局协议(`Symbol.for("pi.routing.registry.v1")` 与 `Symbol.for("pi.cache.hints.v1")`)支持可选的 router extension 集成,而不导入任何 router 包。
39
41
 
40
42
  缓存是 provider 侧的 best-effort 行为。第三方代理和 router extension 仍可能隐藏缓存 usage、拒绝不支持的参数,或把请求路由到多个上游。
@@ -55,7 +57,7 @@ pi remove npm:pi-deepseek-cache-optimizer && pi install npm:pi-cache-optimizer
55
57
 
56
58
  Pi 0.79.7 及之后,`pi update` 默认只更新 Pi 本体。若要更新已安装的 Pi package(包括本扩展),请运行 `pi update --extensions`(只更新 packages)或 `pi update --all`(Pi 与 packages 一起更新)。
57
59
 
58
- 本扩展已使用 Pi 0.84.1 验证,并继续面向 Pi 0.82+ 设计。它使用这些版本共有的 extension hooks、`getAgentDir()` 和 prompt options,不依赖 Pi 0.83+ 专有 API(例如 `ctx.scopedModels` 或 bundled TypeBox 1.3 aliases)。
60
+ 本扩展要求 Pi 0.82+,并已使用 Pi 0.84.2 验证。TypeScript 校验直接使用官方 Pi package 类型,同时只使用这些版本共有的 extension hooks、`getAgentDir()` 和 prompt options;不依赖 Pi 0.83+ 专有 API(例如 `ctx.scopedModels` 或 bundled TypeBox 1.3 aliases)。
59
61
 
60
62
  ## 命令
61
63
 
@@ -66,12 +68,14 @@ Pi 0.79.7 及之后,`pi update` 默认只更新 Pi 本体。若要更新已安
66
68
  | `/cache-optimizer disable` | 在当前 Pi 进程中关闭优化,清零本地 footer 统计,并继续以 disabled 对比模式采集 footer 统计。运行 `/reload` 或重启 Pi 后回到启动时行为。 |
67
69
  | `/cache-optimizer doctor` | 显示当前模型 / provider / API / base URL / compat 与低命中诊断。 |
68
70
  | `/cache-optimizer compat` | 对当前模型显示可复制的 compat 建议(如适用)。 |
69
- | `/cache-optimizer stats` | 显示当前模型今天的本地 provider/model 统计和近期趋势。 |
71
+ | `/cache-optimizer stats` | 显示当前 conversation session 今天使用过的各 cache-adapter-matched 模型详细统计。 |
72
+ | `/cache-optimizer stats all` | 显示所有有效本地 session/shard 今天的逐模型详细总计,包括请求数与 token 数。 |
73
+ | `/cache-optimizer stats contributors` | 显示当前精确 provider/model 的当前/其他贡献 session,不暴露 session id。 |
70
74
  | `/cache-optimizer reset` | 重置当前 provider/model 的本地 footer 统计;不会修改上游 provider 缓存。 |
71
75
  | `/cache-optimizer config footer-mode total\|session\|process` | 持久设置 footer 统计模式;持久命令配置优先于环境变量。 |
72
76
  | `/cache-optimizer fix` | 为当前模型自动修复安全的 compat 问题(adaptive thinking、DeepSeek reasoning、OpenAI proxy session affinity)。展示预览 + 风险提示,需要用户确认。**仅在用户明确批准后才修改 `models.json`。** |
73
77
 
74
- `/cache-optimizer` 使用 Pi 原生 Tab 补全:输入 `/cache-optimizer <Tab>` 查看支持的子命令,输入 `/cache-optimizer c<Tab>` 补全 `config`,输入 `/cache-optimizer config <Tab>` 补全 `footer-mode`,输入 `/cache-optimizer config footer-mode <Tab>` 补全 `total`、`session` 或 `process`。建议会按当前前缀过滤;无效前缀返回空结果,由 Pi 正常回退处理。
78
+ `/cache-optimizer` 使用 Pi 原生 Tab 补全:输入 `/cache-optimizer <Tab>` 查看支持的子命令,输入 `/cache-optimizer stats <Tab>` 补全 `all` 或 `contributors`,输入 `/cache-optimizer c<Tab>` 补全 `config`,输入 `/cache-optimizer config <Tab>` 补全 `footer-mode`,输入 `/cache-optimizer config footer-mode <Tab>` 补全 `total`、`session` 或 `process`。建议会按当前前缀过滤;无效前缀返回空结果,由 Pi 正常回退处理。
75
79
 
76
80
  交互式 `/cache-optimizer` 菜单包含 `Footer mode`,可以选择 `total`、`session` 或 `process`。`enable` / `disable` 是当前进程内开关。若要持久关闭某些能力,请使用下面的环境变量。
77
81
 
@@ -86,13 +90,15 @@ Pi 0.79.7 及之后,`pi update` 默认只更新 Pi 本体。若要更新已安
86
90
 
87
91
  ## Footer 缓存统计模式
88
92
 
89
- **v2.7.0+** 支持每日累计和 conversation session 两种 footer 统计范围。**v2.7.1** 在交互式 `/cache-optimizer` 菜单中加入了 Footer mode 选项。**v2.8.0+** 另外支持进程级统计。Footer 默认使用 `total`,显示当前本地日期内、跨 Pi session 和进程重启延续的 provider/model 统计。可以通过命令或环境变量切换显示范围:
93
+ 当前版本把统计保存在 Pi agent 目录的 `pi-cache-optimizer-stats.d/shards/` 下。每个已加载的 extension instance 独占一个 UUID 命名 shard,并通过临时文件 + 原子 rename 写入,因此父/子/并行 Pi 进程不会互相覆盖。旧 v6 单文件统计在升级时直接删除,本地 footer 计数从零开始;不会影响上游 provider 的实际缓存。
94
+
95
+ Footer 默认使用 `session`,避免另一个并行 Pi 终端使用相同 provider/model 时污染当前窗口。可以通过命令或环境变量切换显示范围:
90
96
 
91
97
  | 值 | 作用 |
92
98
  |---|---|
93
- | `total`(默认) | 显示今天跨 session 持久延续的 provider/model 累计统计;本地日期切换时重置。 |
94
- | `session` | 仅显示当前 hashed Pi conversation session 的统计。新 conversation session 从 `0/0` 开始;重启 Pi 后如果恢复同一 session,会恢复该 session 桶。 |
95
- | `process` | 仅显示当前 Pi 进程采集的统计。Pi 重启或 extension reload 后从 `0/0` 开始,且不会从磁盘恢复。 |
99
+ | `session`(默认) | 聚合今天携带当前 hashed Pi conversation session id 且精确 provider/model 相同的 shard。Extension reload 会产生新 instance shard,但仍属于同一 session 范围。 |
100
+ | `total` | 聚合今天同一精确 provider/model 的全部有效本地 shard,包括加载本扩展并共享同一 agent 目录的子 Pi agent。 |
101
+ | `process` | 仅显示当前 extension instance 采集的统计。Pi 重启或 extension reload 后从 `0/0` 开始。 |
96
102
 
97
103
  持久命令配置优先于环境变量:
98
104
 
@@ -102,7 +108,7 @@ Pi 0.79.7 及之后,`pi update` 默认只更新 Pi 本体。若要更新已安
102
108
  /cache-optimizer config footer-mode process
103
109
  ```
104
110
 
105
- 显式设置保存在 Pi agent 目录下的 `pi-cache-optimizer-config.json`。没有命令覆盖时,读取 `PI_CACHE_OPTIMIZER_FOOTER_MODE=total|session|process`;值不区分大小写,缺失或非法值均回退到 `total`。如需让已有安装重新由环境变量控制,请手动删除 `pi-cache-optimizer-config.json`,然后运行 `/reload`。
111
+ 显式设置保存在 Pi agent 目录下的 `pi-cache-optimizer-config.json`。没有命令覆盖时,读取 `PI_CACHE_OPTIMIZER_FOOTER_MODE=total|session|process`;值不区分大小写,缺失或非法值均回退到 `session`。如需让已有安装重新由环境变量控制,请手动删除 `pi-cache-optimizer-config.json`,然后运行 `/reload`。
106
112
 
107
113
  ## OpenAI-compatible 代理配置
108
114
 
@@ -134,7 +140,7 @@ Pi 0.84.1 还修复了内置 Fireworks 渠道对拒绝 `prompt_cache_retention`
134
140
 
135
141
  - `sendSessionAffinityHeaders: true` 是安全默认项,前提是你的代理支持 sticky routing。
136
142
  - `supportsLongCacheRetention: true` 是可选项。只有 endpoint 明确支持 OpenAI long prompt cache retention 时才添加。
137
- - 如果出现 `400 Unsupported parameter: prompt_cache_retention`,请为该渠道移除 / 避免 `supportsLongCacheRetention`;如支持,可保留 `sendSessionAffinityHeaders`。
143
+ - 如果出现 `400 Unsupported parameter: prompt_cache_retention`,请为该渠道移除 / 避免 `supportsLongCacheRetention`;如支持,可保留 `sendSessionAffinityHeaders`。扩展会从响应头或最终 assistant error message 中识别这条明确错误,并在当前进程的后续请求中移除该参数。
138
144
  - 使用 `/cache-optimizer compat` 或 `/cache-optimizer doctor` 查看当前模型的具体建议。
139
145
  - 对 DeepSeek 模型,Pi Mono 指南期望在支持时同时设置 `compat.requiresReasoningContentOnAssistantMessages: true` 和 `compat.thinkingFormat: "deepseek"`,再配合缓存 / session-affinity 相关 compat。
140
146
  - 本扩展的 `doctor` 和 `compat` 命令只给建议,不会修改 `models.json`。
@@ -228,8 +234,9 @@ Pi 0.80.9+ 已在内置 Kimi Coding、Moonshot AI / 中国区、OpenRouter 和 V
228
234
  2. 警告:① 修改影响使用该渠道的所有 session,② 自动备份到 `models.json.backup-cache-optimizer-<timestamp>`,③ 需重启 Pi 或 reload
229
235
  3. 使用保留注释的精确编辑器 —— 现有注释、缩进和已有 key 顺序都会保留
230
236
  4. 需要用户明确确认(交互式提示或 `ui.select`)
231
- 5. 原子写入(temp + rename);写入后自我验证
232
- 6. 如果 JSONC 扫描器无法置信定位目标,回退到手动修改指引
237
+ 5. 写入与失败恢复都使用原子替换(temp + rename);写入后自我验证
238
+ 6. 完全保留 `models.json` 原有访问权限,不主动收紧或放宽(例如 `0600` 保持 `0600`,`0644` 保持 `0644`)
239
+ 7. 备份名唯一且不会覆盖已有备份;如果 JSONC 扫描器无法置信定位目标,则回退到手动修改指引
233
240
 
234
241
  已有的 `modelOverrides[modelId]` 具有 Pi 的最高优先级,因此 `fix` 会直接修复该 entry。对于没有自定义 `models[]` entry 的内置模型或 API-login 模型,`fix` 会创建仅含 compat 的 `modelOverrides` entry,而不会凭空添加自定义模型定义。自检会验证三层合并后的有效 compat,因此被更高层 override 遮蔽的低层修改会被拒绝。
235
242
 
@@ -275,7 +282,7 @@ Provider 级最小 override:
275
282
 
276
283
  ## Footer 统计
277
284
 
278
- 统计是只读本地计数,保存在 Pi agent 目录(默认 `~/.pi/agent/pi-cache-optimizer-stats.json`;自定义 agent 目录使用 `PI_CODING_AGENT_DIR`)。扩展同时维护当天的 provider/model totals 和 hashed session buckets。Footer 默认显示每日 totals;选择 `session` 模式后显示当前 conversation session 桶,选择 `process` 模式后显示当前进程内存桶。统计文件只包含日期和数字计数,不包含 API key、prompt、payload、headers、响应或模型输出。Footer 模式配置单独保存在 `pi-cache-optimizer-config.json`。Process 模式统计只存在内存中,不会写入该文件。
285
+ 统计是只读本地计数,保存在 Pi agent 目录的 UUID shard(`pi-cache-optimizer-stats.d/shards/`;自定义 agent 目录使用 `PI_CODING_AGENT_DIR`)。Shard 只包含日期、opaque session hash、精确 provider/model 计数、reset epoch 和进程生命周期元数据,不包含 API key、prompt、payload、headers、响应或模型输出。Footer 默认显示当前 conversation session;`total` 聚合同一精确 provider/model 的所有有效本地 shard,`process` 只显示当前 extension instance。旧 v6 共享统计文件升级时直接删除,不迁移旧计数。
279
286
 
280
287
  Pi 0.79+ 已内置 footer `CH` 标记,用于显示最近一次 prompt cache hit rate。本扩展在此基础上补充持久化的 provider/model 计数,以及代理 compat 诊断。
281
288
 
@@ -285,7 +292,7 @@ Pi 0.79+ 已内置 footer `CH` 标记,用于显示最近一次 prompt cache hi
285
292
  · OpenAI cache 3/10·0.002M/0.005M 40.0% ⚠️ compat
286
293
  ```
287
294
 
288
- 开头的 `· ` 由本扩展负责,用于把本扩展状态与同一 footer 中其他扩展发布的状态隔开。普通、disabled、router 恢复以及带 warning 的状态都会保留此前缀。紧凑 footer 格式为 `<label> <命中请求数>/<总请求数>·<cached input tokens>/<total input tokens> <token 命中率>`;token 命中率保留一位小数,并去掉多余的 `tok` 后缀。`/cache-optimizer stats` 的输出不变。部分 adapter 还可能追加 `·write <tokens>`,运行时诊断可能追加 `⚠️ compat` 或 `⚠️ integrity`。
295
+ 开头的 `· ` 由本扩展负责,用于把本扩展状态与同一 footer 中其他扩展发布的状态隔开。普通、disabled、router 恢复以及带 warning 的状态都会保留此前缀。紧凑 footer 格式为 `<label> <命中请求数>/<总请求数>·<cached input tokens>/<total input tokens> <token 命中率>`;token 命中率保留一位小数,并去掉多余的 `tok` 后缀。`/cache-optimizer stats` 显示当前 session 的各模型详细统计;`/cache-optimizer stats all` 显示所有本地模型,并包含 `4/5·0.66M/0.84M 78.7%` 这样的紧凑摘要。部分 adapter 还可能追加 `·write <tokens>`,运行时诊断可能追加 `⚠️ compat` 或 `⚠️ integrity`。
289
296
 
290
297
  支持的 footer label 包括:DS、Claude、OpenAI、Gemini、Kimi、Qwen、GLM、MiniMax、Mimo、Hunyuan、Mistral、Grok、Llama、Nemotron、Cohere、Yi、Doubao、ERNIE、Baichuan、StepFun、Spark、InternLM、Gemma、Phi、Jamba、Solar、Sonar、Nova、Reka、Falcon、DBRX、MPT、StableLM、Aquila、EXAONE、HyperCLOVA、Luminous、Hermes、Granite、Arctic、Pangu、SenseNova、Zhinao、MiniCPM、XVERSE、Orion、OpenChat、Vicuna、Wizard、Zephyr、Dolphin、OpenOrca、Starling、BLOOM、RWKV、Aya。
291
298
 
@@ -408,9 +415,9 @@ pi remove npm:pi-cache-optimizer
408
415
 
409
416
  | 平台 | 删除本地状态文件 |
410
417
  |---|---|
411
- | Linux / macOS / WSL | `rm -f ~/.pi/agent/pi-cache-optimizer-stats.json ~/.pi/agent/pi-cache-optimizer-config.json ~/.pi/agent/deepseek-cache-optimizer-stats.json` |
412
- | Windows PowerShell | `Remove-Item -Force "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-stats.json", "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-config.json", "$env:USERPROFILE\.pi\agent\deepseek-cache-optimizer-stats.json" -ErrorAction SilentlyContinue` |
413
- | Windows 命令提示符 | `del /f /q "%USERPROFILE%\.pi\agent\pi-cache-optimizer-stats.json" "%USERPROFILE%\.pi\agent\pi-cache-optimizer-config.json" "%USERPROFILE%\.pi\agent\deepseek-cache-optimizer-stats.json" 2>nul` |
418
+ | Linux / macOS / WSL | `rm -rf ~/.pi/agent/pi-cache-optimizer-stats.d ~/.pi/agent/pi-cache-optimizer-stats.json ~/.pi/agent/deepseek-cache-optimizer-stats.json ~/.pi/agent/pi-cache-optimizer-config.json` |
419
+ | Windows PowerShell | `Remove-Item -Recurse -Force "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-stats.d", "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-stats.json", "$env:USERPROFILE\.pi\agent\deepseek-cache-optimizer-stats.json", "$env:USERPROFILE\.pi\agent\pi-cache-optimizer-config.json" -ErrorAction SilentlyContinue` |
420
+ | Windows 命令提示符 | `rmdir /s /q "%USERPROFILE%\.pi\agent\pi-cache-optimizer-stats.d" & del /f /q "%USERPROFILE%\.pi\agent\pi-cache-optimizer-stats.json" "%USERPROFILE%\.pi\agent\deepseek-cache-optimizer-stats.json" "%USERPROFILE%\.pi\agent\pi-cache-optimizer-config.json" 2>nul` |
414
421
 
415
422
  清理时不要删除 `models.json`;它保存你的 Pi 模型 / provider 配置,不属于本包。
416
423