pi-condense 2.11.0 → 2.11.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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/context-metrics.test.ts +16 -0
- package/src/context-metrics.ts +10 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ Published to npm as [`pi-condense`](https://www.npmjs.com/package/pi-condense) (
|
|
|
7
7
|
Pushing a `vX.Y.Z` tag triggers `.github/workflows/release.yml`, which runs the tests and
|
|
8
8
|
publishes via OIDC trusted publishing. See `.agents/skills/release/SKILL.md`.
|
|
9
9
|
|
|
10
|
+
## [2.11.1] - 2026-09-29
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- The frontier-gap metric prices image blocks at a flat estimate instead of counting base64 as text, so screenshot reads no longer trigger a premature frontier-gap flush that prunes images before the model sees them.
|
|
15
|
+
|
|
10
16
|
## [2.11.0] - 2026-09-24
|
|
11
17
|
|
|
12
18
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-condense",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.1",
|
|
4
4
|
"description": "Pi coding-agent extension that summarizes completed tool-call batches, replaces raw outputs with short stubs, compresses closed tool-call chains, and recovers any original on demand via context_tree_query.",
|
|
5
5
|
"author": "Jacek Juraszek",
|
|
6
6
|
"license": "MIT",
|
|
@@ -260,6 +260,22 @@ describe("computeContextMetrics", () => {
|
|
|
260
260
|
expect(result.frontierGapTokens).toBe(expected);
|
|
261
261
|
});
|
|
262
262
|
|
|
263
|
+
test("frontierGapTokens: image blocks use a flat estimate instead of base64 length", () => {
|
|
264
|
+
const msgs = [userMsg(100), assistantWithTools(200, ["tc1", "tc2", "tc3"])];
|
|
265
|
+
for (let i = 0; i < 3; i++) {
|
|
266
|
+
const result = toolResult(300 + i, `tc${i + 1}`, "read", "screenshot");
|
|
267
|
+
result.content.push({ type: "image", data: "A".repeat(137000), mimeType: "image/png" });
|
|
268
|
+
msgs.push(result);
|
|
269
|
+
}
|
|
270
|
+
const expected = msgs.slice(2).reduce((sum, msg) => {
|
|
271
|
+
const stub = { ...msg, content: msg.content.map((block: any) => block.type === "image" ? { type: "image" } : block) };
|
|
272
|
+
return sum + Math.round((JSON.stringify(stub).length + 1600 * 4) / 4);
|
|
273
|
+
}, 0);
|
|
274
|
+
const result = computeContextMetrics(msgs, null, noSummarized, noProtected);
|
|
275
|
+
expect(result.frontierGapTokens).toBe(expected);
|
|
276
|
+
expect(result.frontierGapTokens).toBeLessThan(20000);
|
|
277
|
+
});
|
|
278
|
+
|
|
263
279
|
test("frontierGapTokens: boundary mid-turn split excludes at-or-before calls, includes later calls in same turn", () => {
|
|
264
280
|
const msgs = [userMsg(100), assistantWithTools(200, ["tc1", "tc2"]), toolResult(300, "tc1"), toolResult(310, "tc2")];
|
|
265
281
|
const frontier = fullFrontier({ lastAttemptedToolCallId: "tc1", lastAttemptedTurnIndex: 0 });
|
package/src/context-metrics.ts
CHANGED
|
@@ -2,8 +2,17 @@ import { detectChains, isChainAnchorCustom } from "./chain-detector.js";
|
|
|
2
2
|
import { occKey, resultTimestampOf } from "./occurrence-key.js";
|
|
3
3
|
import type { ContextMetricsSnapshot, PruneFrontier } from "./types.js";
|
|
4
4
|
|
|
5
|
+
const IMAGE_TOKEN_ESTIMATE = 1600;
|
|
6
|
+
|
|
5
7
|
function charsOf(msg: any): number {
|
|
6
|
-
return JSON.stringify(msg).length;
|
|
8
|
+
if (!Array.isArray(msg.content)) return JSON.stringify(msg).length;
|
|
9
|
+
let imageCount = 0;
|
|
10
|
+
const content = msg.content.map((block: any) => {
|
|
11
|
+
if (block?.type !== "image") return block;
|
|
12
|
+
imageCount++;
|
|
13
|
+
return { type: "image" };
|
|
14
|
+
});
|
|
15
|
+
return JSON.stringify({ ...msg, content }).length + imageCount * IMAGE_TOKEN_ESTIMATE * 4;
|
|
7
16
|
}
|
|
8
17
|
|
|
9
18
|
function tokensOf(msg: any): number {
|