pi-smart-compact 9.2.0 → 9.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/ARCHITECTURE.md +6 -3
- package/CHANGELOG.md +6 -0
- package/README.md +12 -7
- package/dist/app/steps/window.d.ts.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/index.js +38 -3
- package/dist/provider-eval.js +1 -1
- package/dist/provider-scenario-eval.js +1 -1
- package/dist/telemetry-report.js +1 -1
- package/package.json +1 -1
package/ARCHITECTURE.md
CHANGED
|
@@ -147,9 +147,12 @@ The same pure planner powers manual preflight and execution. A soft boundary is
|
|
|
147
147
|
recorded as relaxed rather than silently overriding the target. Long turns may
|
|
148
148
|
be summarized through their older prefix; if the nominal cut lands inside a
|
|
149
149
|
tool exchange, the planner either retains the complete pair within budget or
|
|
150
|
-
advances past it so the complete exchange is summarized.
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
advances past it so the complete exchange is summarized. It also advances past
|
|
151
|
+
complete historical exchanges whose tool names violate the portable provider
|
|
152
|
+
contract; this keeps model switches from exposing an unsendable raw tail. If no
|
|
153
|
+
provider-safe hard boundary can meet the target, automatic/tool runs normally
|
|
154
|
+
return control to Pi's native compactor before any LLM call. An
|
|
155
|
+
already-overflowed context is
|
|
153
156
|
the safety exception: measured usage is mapped across active messages and EESV
|
|
154
157
|
keeps chunked recovery instead of sending an oversized one-shot prompt to
|
|
155
158
|
native summarization. Manual runs use the profile's absolute adaptive tail, so
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [9.2.1] - 2026-08-11
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Retained tails now summarize complete historical tool exchanges whose names are not portable across providers, preventing dotted wrapper or MCP names from making the first post-compaction turn fail provider validation.
|
|
8
|
+
|
|
3
9
|
## [9.2.0] - 2026-08-11
|
|
4
10
|
|
|
5
11
|
### Added
|
package/README.md
CHANGED
|
@@ -168,8 +168,10 @@ and reports final success only after Pi confirms the matching
|
|
|
168
168
|
`session_compact` run ID. A single long user turn may be
|
|
169
169
|
split at a safe message boundary: its older prefix is verified into the summary
|
|
170
170
|
while the budgeted working tail stays raw. Tool exchanges remain complete
|
|
171
|
-
call/result pairs
|
|
172
|
-
|
|
171
|
+
call/result pairs. Historical exchanges with names outside the portable
|
|
172
|
+
provider contract are summarized instead of leaving an unusable raw tail;
|
|
173
|
+
oversized result evidence is head/tail bounded only in the synthesis prompt
|
|
174
|
+
after deterministic extraction has consumed the full input.
|
|
173
175
|
If Verify, yield, provider, or native apply fails, the UI shows one bounded actionable line without evidence text or a
|
|
174
176
|
JavaScript stack. A successful `100/100` is labeled **verification coverage**;
|
|
175
177
|
the source score and deterministic/LLM/fallback provenance remain visible so
|
|
@@ -448,11 +450,14 @@ Automatic and tool-triggered runs operate on Pi's current active context, not
|
|
|
448
450
|
the append-only session history. A same-session staged summary is reused, the
|
|
449
451
|
exploration loop is limited to three rounds, provider and outer retries are
|
|
450
452
|
disabled, and every mode has finite call plus aggregate prompt-token budgets.
|
|
451
|
-
Complete tool-call/result pairs are the hard window boundary.
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
453
|
+
Complete tool-call/result pairs are the hard window boundary. Provider-incompatible
|
|
454
|
+
historical tool names move the boundary past their complete exchanges so a
|
|
455
|
+
provider switch cannot leave an unsendable raw tail. Recent user turns,
|
|
456
|
+
pi-toolkit checkpoints, and topical grouping are soft and may expand the raw
|
|
457
|
+
tail only while remaining inside the selected budget. Automatic/tool runs
|
|
458
|
+
normally return to Pi's native compactor without an LLM call when no
|
|
459
|
+
provider-safe hard boundary can meet the target. Overflow is the safety
|
|
460
|
+
exception: EESV keeps
|
|
456
461
|
chunked recovery rather than resending an oversized one-shot prompt to native
|
|
457
462
|
compaction. Manual `/smart-compact` uses an absolute adaptive tail rather than
|
|
458
463
|
a percentage of a large model window. A plan below 10% projected savings never
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/app/steps/window.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,KAAK,EACV,oBAAoB,EAAE,oBAAoB,EAAE,UAAU,EAAuB,UAAU,EACxF,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,uBAAuB,EAAc,aAAa,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAKpI,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGhF,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,EAAE,aAAa,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,6EAA6E;IAC7E,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,+DAA+D;AAC/D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAS7E;AAED,oFAAoF;AACpF,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,aAAa,EACzB,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,oBAAoB,GAAG,SAAS,GAC7C,MAAM,CAYR;
|
|
1
|
+
{"version":3,"file":"window.d.ts","sourceRoot":"","sources":["../../../src/app/steps/window.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAE1E,OAAO,KAAK,EACV,oBAAoB,EAAE,oBAAoB,EAAE,UAAU,EAAuB,UAAU,EACxF,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,uBAAuB,EAAc,aAAa,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAKpI,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGhF,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,mBAAmB,EAAE,CAAC;IAC5B,MAAM,EAAE,OAAO,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,EAAE,aAAa,CAAC;IAC1B,KAAK,EAAE,OAAO,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,6EAA6E;IAC7E,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,+DAA+D;AAC/D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAS7E;AAED,oFAAoF;AACpF,wBAAgB,6BAA6B,CAC3C,UAAU,EAAE,aAAa,EACzB,SAAS,EAAE,cAAc,EACzB,YAAY,EAAE,oBAAoB,GAAG,SAAS,GAC7C,MAAM,CAYR;AA8CD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,GAAG,oBAAoB,CAiI3F;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAqEzE"}
|
package/dist/constants.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import type { CompressionProfile, ProfileConfig } from "./types.ts";
|
|
|
8
8
|
* `package.json#version`. Do not hand-edit this line for releases; bump
|
|
9
9
|
* package.json and run `bun run sync-version`.
|
|
10
10
|
*/
|
|
11
|
-
export declare const VERSION = "9.2.
|
|
11
|
+
export declare const VERSION = "9.2.1";
|
|
12
12
|
export declare const CHARS_PER_TOKEN = 3.8;
|
|
13
13
|
export declare const MIN_COMPACTION_SAVING_RATIO = 0.1;
|
|
14
14
|
export declare const ESTIMATOR_ROUNDING_TOLERANCE_TOKENS = 1;
|
package/dist/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import { StringEnum } from "@earendil-works/pi-ai";
|
|
|
7
7
|
import { Type as Type2 } from "typebox";
|
|
8
8
|
|
|
9
9
|
// src/constants.ts
|
|
10
|
-
var VERSION = "9.2.
|
|
10
|
+
var VERSION = "9.2.1";
|
|
11
11
|
var CHARS_PER_TOKEN = 3.8;
|
|
12
12
|
var MIN_COMPACTION_SAVING_RATIO = 0.1;
|
|
13
13
|
var ESTIMATOR_ROUNDING_TOLERANCE_TOKENS = 1;
|
|
@@ -5589,7 +5589,7 @@ function compactionPlanReasonText(reason) {
|
|
|
5589
5589
|
case "no-eligible-prefix":
|
|
5590
5590
|
return "no older prefix is available";
|
|
5591
5591
|
case "unsafe-tool-boundary":
|
|
5592
|
-
return "no complete tool-call boundary is available";
|
|
5592
|
+
return "no provider-safe complete tool-call boundary is available";
|
|
5593
5593
|
case "retention-target-exceeded":
|
|
5594
5594
|
return "a complete tool pair exceeds the tail target";
|
|
5595
5595
|
case "mode-target-not-met":
|
|
@@ -5606,6 +5606,35 @@ function estimateFinalSummaryAllowance(profileCfg, estimator, providerCaps) {
|
|
|
5606
5606
|
const legacyFloor = profileCfg.summaryBudgetTokens + Math.ceil(profileCfg.summaryBudgetTokens * POST_SUMMARY_RESERVE_RATIO);
|
|
5607
5607
|
return Math.max(legacyFloor, calibratedOutput + calibratedPostProcessing);
|
|
5608
5608
|
}
|
|
5609
|
+
var PORTABLE_TOOL_NAME_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
5610
|
+
function advancePastNonPortableToolExchanges(msgs, keepFrom, toolCallIndex) {
|
|
5611
|
+
if (keepFrom < 0 || keepFrom >= msgs.length)
|
|
5612
|
+
return keepFrom;
|
|
5613
|
+
const exchangeEnds = new Map;
|
|
5614
|
+
for (let index = keepFrom;index < msgs.length; index++) {
|
|
5615
|
+
const message = msgs[index].message;
|
|
5616
|
+
if (!isRecord(message) || message.role !== "toolResult" || typeof message.toolCallId !== "string")
|
|
5617
|
+
continue;
|
|
5618
|
+
const callIndex = toolCallIndex.get(message.toolCallId);
|
|
5619
|
+
if (callIndex === undefined || callIndex < keepFrom)
|
|
5620
|
+
continue;
|
|
5621
|
+
exchangeEnds.set(callIndex, Math.max(exchangeEnds.get(callIndex) ?? 0, index + 1));
|
|
5622
|
+
}
|
|
5623
|
+
let adjusted = keepFrom;
|
|
5624
|
+
for (let index = keepFrom;index < msgs.length; index++) {
|
|
5625
|
+
const message = msgs[index].message;
|
|
5626
|
+
if (!isRecord(message))
|
|
5627
|
+
continue;
|
|
5628
|
+
if (message.role === "assistant" && Array.isArray(message.content)) {
|
|
5629
|
+
const nonPortable = message.content.some((block) => isRecord(block) && block.type === "toolCall" && (typeof block.name !== "string" || !PORTABLE_TOOL_NAME_RE.test(block.name)));
|
|
5630
|
+
if (nonPortable)
|
|
5631
|
+
adjusted = Math.max(adjusted, exchangeEnds.get(index) ?? index + 1);
|
|
5632
|
+
} else if (message.role === "toolResult" && typeof message.toolName === "string" && !PORTABLE_TOOL_NAME_RE.test(message.toolName)) {
|
|
5633
|
+
adjusted = Math.max(adjusted, index + 1);
|
|
5634
|
+
}
|
|
5635
|
+
}
|
|
5636
|
+
return adjusted;
|
|
5637
|
+
}
|
|
5609
5638
|
function planCompactionWindow(input) {
|
|
5610
5639
|
const {
|
|
5611
5640
|
msgs,
|
|
@@ -5682,6 +5711,12 @@ function planCompactionWindow(input) {
|
|
|
5682
5711
|
const forwardBoundary = retainedAt(backwardBoundary) > effectiveRetentionCeiling ? advancePastToolCallBoundary(msgs, keepFrom, toolCallIndex) : keepFrom;
|
|
5683
5712
|
keepFrom = forwardBoundary > keepFrom && forwardBoundary < msgs.length && retainedAt(forwardBoundary) <= effectiveRetentionCeiling ? forwardBoundary : backwardBoundary;
|
|
5684
5713
|
hardBoundaryAdjusted ||= keepFrom !== boundaryBeforeHardGuard;
|
|
5714
|
+
const providerSafeBoundary = advancePastNonPortableToolExchanges(msgs, keepFrom, toolCallIndex);
|
|
5715
|
+
const nonPortableTailBlocked = providerSafeBoundary >= msgs.length;
|
|
5716
|
+
if (!nonPortableTailBlocked && providerSafeBoundary > keepFrom) {
|
|
5717
|
+
keepFrom = providerSafeBoundary;
|
|
5718
|
+
hardBoundaryAdjusted = true;
|
|
5719
|
+
}
|
|
5685
5720
|
const compactTokens = Math.round(tokenPrefix[keepFrom] * messageScale);
|
|
5686
5721
|
const retainedTokens = retainedAt(keepFrom);
|
|
5687
5722
|
const projectedAfterTokens = fixedContextTokens + retainedTokens + finalSummaryAllowance;
|
|
@@ -5690,7 +5725,7 @@ function planCompactionWindow(input) {
|
|
|
5690
5725
|
const targetAfterTokens = !force && modelContextWindow ? modelContextWindow * targetPercent / 100 : fixedContextTokens + effectiveRetentionCeiling + finalSummaryAllowance;
|
|
5691
5726
|
let reason = "viable";
|
|
5692
5727
|
const firstKeptMessage = msgs[keepFrom]?.message;
|
|
5693
|
-
if (isRecord(firstKeptMessage) && firstKeptMessage.role === "toolResult")
|
|
5728
|
+
if (nonPortableTailBlocked || isRecord(firstKeptMessage) && firstKeptMessage.role === "toolResult")
|
|
5694
5729
|
reason = "unsafe-tool-boundary";
|
|
5695
5730
|
else if (keepFrom <= 0)
|
|
5696
5731
|
reason = "no-eligible-prefix";
|
package/dist/provider-eval.js
CHANGED
|
@@ -156,7 +156,7 @@ function formatProviderEvaluation(report) {
|
|
|
156
156
|
import fs2 from "fs";
|
|
157
157
|
|
|
158
158
|
// src/constants.ts
|
|
159
|
-
var VERSION = "9.2.
|
|
159
|
+
var VERSION = "9.2.1";
|
|
160
160
|
var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
|
|
161
161
|
var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
|
|
162
162
|
var PROFILES = {
|
|
@@ -169,7 +169,7 @@ function getLlmClient() {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// src/constants.ts
|
|
172
|
-
var VERSION = "9.2.
|
|
172
|
+
var VERSION = "9.2.1";
|
|
173
173
|
var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
|
|
174
174
|
var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
|
|
175
175
|
var PROFILES = {
|
package/dist/telemetry-report.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var __require = import.meta.require;
|
|
3
3
|
|
|
4
4
|
// src/constants.ts
|
|
5
|
-
var VERSION = "9.2.
|
|
5
|
+
var VERSION = "9.2.1";
|
|
6
6
|
var SETTLED_TRIGGER_COOLDOWN_MS = 10 * 60000;
|
|
7
7
|
var COMPACT_SYSTEM_PREFIX = "You are an expert conversation summarizer for a coding agent. " + "Produce structured markdown summaries. " + "Follow output format exactly. " + "Use EXACT names \u2014 never paraphrase code identifiers. " + "Trust deterministic extraction data over intuition.";
|
|
8
8
|
var PROFILES = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-smart-compact",
|
|
3
|
-
"version": "9.2.
|
|
3
|
+
"version": "9.2.1",
|
|
4
4
|
"description": "Verification-oriented smart compaction extension for Pi Coding Agent — deterministic extraction, exploration, synthesis, verification, metrics, and safety checks.",
|
|
5
5
|
"packageManager": "bun@1.3.14",
|
|
6
6
|
"engines": {
|