pi-cache-optimizer 2.1.1 → 2.2.1
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 +13 -0
- package/README.zh-CN.md +13 -0
- package/index.ts +85 -15
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -40,6 +40,19 @@ This release keeps the original DeepSeek behavior and adds read-only stats adapt
|
|
|
40
40
|
|
|
41
41
|
Generic OpenAI-compatible proxies are **not** treated as OpenAI-family just because they use an OpenAI-shaped API or provider id. If the active model id/name is ambiguous, the extension hides the footer stats instead of guessing.
|
|
42
42
|
|
|
43
|
+
## Platform support
|
|
44
|
+
|
|
45
|
+
This extension is pure Node.js — no shell exec, no native bindings, no platform-specific paths — so it runs on every OS Pi itself supports:
|
|
46
|
+
|
|
47
|
+
| OS | Notes |
|
|
48
|
+
|---|---|
|
|
49
|
+
| Linux | Native. |
|
|
50
|
+
| macOS | Native. |
|
|
51
|
+
| Windows | Works through the bash shell Pi requires on Windows (Git Bash, Cygwin, MSYS2, or WSL). See Pi's [Windows setup](https://github.com/earendil-works/pi-coding-agent/blob/main/docs/windows.md). |
|
|
52
|
+
| Termux / Android | Works inside Pi's Termux setup. |
|
|
53
|
+
|
|
54
|
+
State files under `~/.pi/agent/` are resolved via Node's `os.homedir()`, so on Windows the path automatically expands to `C:\Users\<you>\.pi\agent\...`. All shell snippets in this README are bash, matching the shell Pi runs in on every supported platform; no PowerShell or `cmd.exe` translation is needed when commands are executed inside (or for) Pi.
|
|
55
|
+
|
|
43
56
|
## Quickstart
|
|
44
57
|
|
|
45
58
|
1. (Optional but recommended) Read the official Pi + DeepSeek onboarding guide: [`pi_mono.zh-CN.md`](https://github.com/deepseek-ai/awesome-deepseek-agent/blob/main/docs/pi_mono.zh-CN.md). It covers Pi installation and core configuration.
|
package/README.zh-CN.md
CHANGED
|
@@ -43,6 +43,19 @@
|
|
|
43
43
|
|
|
44
44
|
Generic OpenAI-compatible 代理**不会**仅因为使用 OpenAI 形状 API 或 provider id 就被当作 OpenAI-family。如果当前 model id/name 语义不明确,扩展会隐藏底部统计,而不是猜测。
|
|
45
45
|
|
|
46
|
+
## 平台支持
|
|
47
|
+
|
|
48
|
+
本扩展是纯 Node.js 实现 —— 不调用 shell、没有原生绑定、不写死平台相关路径 —— 因此与 Pi 自身保持一致,支持以下系统:
|
|
49
|
+
|
|
50
|
+
| 操作系统 | 说明 |
|
|
51
|
+
|---|---|
|
|
52
|
+
| Linux | 原生支持。 |
|
|
53
|
+
| macOS | 原生支持。 |
|
|
54
|
+
| Windows | 通过 Pi 在 Windows 下要求的 bash shell 运行(Git Bash、Cygwin、MSYS2 或 WSL)。详见 Pi 的 [Windows setup](https://github.com/earendil-works/pi-coding-agent/blob/main/docs/windows.md)。 |
|
|
55
|
+
| Termux / Android | 在 Pi 的 Termux 环境中可用。 |
|
|
56
|
+
|
|
57
|
+
状态文件 `~/.pi/agent/` 通过 Node 的 `os.homedir()` 解析,所以在 Windows 上会自动展开为 `C:\Users\<你>\.pi\agent\...`。本文档中所有 shell 命令均使用 bash 语法,与 Pi 在每个受支持平台下运行的 shell 一致;只要在 Pi 内(或为 Pi 而执行)运行,就**不需要**改写为 PowerShell 或 `cmd.exe` 形式。
|
|
58
|
+
|
|
46
59
|
## 快速开始
|
|
47
60
|
|
|
48
61
|
1. (可选但推荐)先读一遍官方 Pi + DeepSeek 接入指南:[`pi_mono.zh-CN.md`](https://github.com/deepseek-ai/awesome-deepseek-agent/blob/main/docs/pi_mono.zh-CN.md)。它讲了 Pi 安装与基础配置。
|
package/index.ts
CHANGED
|
@@ -51,11 +51,12 @@ const NO_SKILL_COMPRESSION_ENV = "PI_CACHE_OPTIMIZER_NO_SKILL_COMPRESSION";
|
|
|
51
51
|
const DEEPSEEK_API_KEY_ENV = "DEEPSEEK_API_KEY";
|
|
52
52
|
|
|
53
53
|
// WORM-flag: if optimizeSystemPrompt ever detects that its blind-replace
|
|
54
|
-
// logic has accidentally truncated
|
|
55
|
-
//
|
|
56
|
-
// publishStatus reads it once, appends a footer warning, then
|
|
57
|
-
// The flag surface is kept separate from the regular
|
|
58
|
-
// so that a one-turn glitch doesn't poison the
|
|
54
|
+
// logic has accidentally truncated a structural marker (any XML tag or
|
|
55
|
+
// HTML comment boundary marker present in the original prompt), we flip
|
|
56
|
+
// this. publishStatus reads it once, appends a footer warning, then
|
|
57
|
+
// resets it. The flag surface is kept separate from the regular
|
|
58
|
+
// cache-stats counter so that a one-turn glitch doesn't poison the
|
|
59
|
+
// persisted metrics.
|
|
59
60
|
let promptTruncationDetected = false;
|
|
60
61
|
|
|
61
62
|
// Minimum count of skills before compression is worth applying.
|
|
@@ -387,6 +388,62 @@ function stripSessionOverviewChurn(prompt: string): string {
|
|
|
387
388
|
return before + cleaned + after;
|
|
388
389
|
}
|
|
389
390
|
|
|
391
|
+
/**
|
|
392
|
+
* Extract structural markers from a prompt for the integrity guard.
|
|
393
|
+
*
|
|
394
|
+
* The guard runs in `optimizeSystemPrompt` to catch cases where the
|
|
395
|
+
* blind `rest.replace(part, "")` reorder accidentally eats text inside
|
|
396
|
+
* an extension-injected structural block (e.g., trellis
|
|
397
|
+
* `<workflow-state>`, a hypothetical `<task-tracker>`, or AGENTS.md
|
|
398
|
+
* `<!-- TRELLIS:START -->` markers). When the original prompt contains
|
|
399
|
+
* a marker that the result is missing, we fall back to the original
|
|
400
|
+
* prompt rather than ship a corrupted one.
|
|
401
|
+
*
|
|
402
|
+
* Three marker categories are recognized (covers ~99% of real-world
|
|
403
|
+
* extension injection patterns in the pi ecosystem):
|
|
404
|
+
*
|
|
405
|
+
* 1. XML-style opening tags `<tagname>` (lowercase, alpha-num + `_`/`-`)
|
|
406
|
+
* 2. XML-style closing tags `</tagname>`
|
|
407
|
+
* 3. HTML comment START/END `<!-- NAME:START -->` / `<!-- NAME:END -->`
|
|
408
|
+
*
|
|
409
|
+
* Tags with attributes (e.g., `<task id="42">`) are not currently emitted
|
|
410
|
+
* by any pi extension we know of and are skipped to keep the regex tight.
|
|
411
|
+
* Markdown headers, horizontal rules, and timestamp patterns are not
|
|
412
|
+
* usable as guards because they have no closing form to verify.
|
|
413
|
+
*
|
|
414
|
+
* The check is deliberately set-based (presence/absence) rather than
|
|
415
|
+
* count-based: a single occurrence per request is the universal
|
|
416
|
+
* convention, and a count drop with the same set of unique tags would
|
|
417
|
+
* be a different class of bug not catchable here.
|
|
418
|
+
*/
|
|
419
|
+
function extractStructuralMarkers(prompt: string): {
|
|
420
|
+
openingTags: Set<string>;
|
|
421
|
+
closingTags: Set<string>;
|
|
422
|
+
commentMarkers: Set<string>;
|
|
423
|
+
} {
|
|
424
|
+
const openingTags = new Set<string>();
|
|
425
|
+
const closingTags = new Set<string>();
|
|
426
|
+
const commentMarkers = new Set<string>();
|
|
427
|
+
|
|
428
|
+
// Opening tags: <tagname> with no attributes and no leading slash.
|
|
429
|
+
// Tagname must start with a letter and contain only alpha-num, `-`, `_`.
|
|
430
|
+
for (const match of prompt.matchAll(/<([a-z][a-z0-9_-]*)>/gi)) {
|
|
431
|
+
openingTags.add(match[1].toLowerCase());
|
|
432
|
+
}
|
|
433
|
+
// Closing tags: </tagname>
|
|
434
|
+
for (const match of prompt.matchAll(/<\/([a-z][a-z0-9_-]*)>/gi)) {
|
|
435
|
+
closingTags.add(match[1].toLowerCase());
|
|
436
|
+
}
|
|
437
|
+
// HTML comments with NAME:START or NAME:END inside.
|
|
438
|
+
// Trellis emits `<!-- TRELLIS:START -->` / `<!-- TRELLIS:END -->` in
|
|
439
|
+
// the AGENTS.md managed block; other extensions follow this convention.
|
|
440
|
+
for (const match of prompt.matchAll(/<!--\s*([A-Z][A-Z0-9_-]*):(START|END)\s*-->/g)) {
|
|
441
|
+
commentMarkers.add(`${match[1]}:${match[2]}`);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return { openingTags, closingTags, commentMarkers };
|
|
445
|
+
}
|
|
446
|
+
|
|
390
447
|
function optimizeSystemPrompt(
|
|
391
448
|
original: string,
|
|
392
449
|
opts: BuildSystemPromptOptions,
|
|
@@ -420,17 +477,29 @@ function optimizeSystemPrompt(
|
|
|
420
477
|
stablePrefix +
|
|
421
478
|
(dynamicRemainder.length > 0 ? "\n\n---\n\n" + dynamicRemainder : "");
|
|
422
479
|
|
|
423
|
-
// Sanity check:
|
|
424
|
-
// markers
|
|
425
|
-
//
|
|
426
|
-
//
|
|
427
|
-
//
|
|
428
|
-
// trellis
|
|
480
|
+
// Sanity check: scan ALL structural markers (XML tags + HTML comment
|
|
481
|
+
// boundary markers) in the original and verify each one survives the
|
|
482
|
+
// reorder. If any marker drops, the blind `rest.replace(part, "")`
|
|
483
|
+
// logic ate something it shouldn't have — fall back to the original
|
|
484
|
+
// prompt and flag the footer warning. This is provider-agnostic and
|
|
485
|
+
// extension-agnostic: trellis `<workflow-state>`, a hypothetical
|
|
486
|
+
// `<task-tracker>`, AGENTS.md `<!-- TRELLIS:START -->`, etc., are all
|
|
487
|
+
// protected without code changes when new extensions ship.
|
|
429
488
|
//
|
|
430
|
-
//
|
|
431
|
-
//
|
|
432
|
-
//
|
|
433
|
-
|
|
489
|
+
// Our skills compression runs BEFORE optimizeSystemPrompt and replaces
|
|
490
|
+
// pi's verbose `<available_skills>` block with a compressed text
|
|
491
|
+
// section that has no XML tag. So `original` here (post-compression)
|
|
492
|
+
// does not contain `<available_skills>` and the result doesn't either
|
|
493
|
+
// — no false positive.
|
|
494
|
+
const originalMarkers = extractStructuralMarkers(original);
|
|
495
|
+
const resultMarkers = extractStructuralMarkers(systemPrompt);
|
|
496
|
+
|
|
497
|
+
const missing =
|
|
498
|
+
[...originalMarkers.openingTags].some((tag) => !resultMarkers.openingTags.has(tag)) ||
|
|
499
|
+
[...originalMarkers.closingTags].some((tag) => !resultMarkers.closingTags.has(tag)) ||
|
|
500
|
+
[...originalMarkers.commentMarkers].some((m) => !resultMarkers.commentMarkers.has(m));
|
|
501
|
+
|
|
502
|
+
if (missing) {
|
|
434
503
|
promptTruncationDetected = true;
|
|
435
504
|
return { systemPrompt: original, stablePrefix: "", changed: false };
|
|
436
505
|
}
|
|
@@ -1240,6 +1309,7 @@ export const __internals_for_tests = {
|
|
|
1240
1309
|
buildStableCandidates,
|
|
1241
1310
|
optimizeSystemPrompt,
|
|
1242
1311
|
stripSessionOverviewChurn,
|
|
1312
|
+
extractStructuralMarkers,
|
|
1243
1313
|
formatSkillsForPrompt,
|
|
1244
1314
|
formatSkillsForPromptCompressed,
|
|
1245
1315
|
compressSkillsInSystemPrompt,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-cache-optimizer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.1",
|
|
4
4
|
"description": "Pi extension that improves provider-side KV/prompt cache hit rates (DeepSeek, OpenAI, Claude, Gemini) by reordering the system prompt, requesting long retention, and showing footer cache stats. Renamed from pi-deepseek-cache-optimizer.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|