@lll9p/pi-better-compaction 0.2.0 → 0.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 CHANGED
@@ -54,6 +54,12 @@ On the next supported Responses request after a native `/responses/compact`, the
54
54
  Requests produced by the native-method fallback carry Pi's standard `{readFiles, modifiedFiles}`
55
55
  details, so they replay through Pi's default path — no rewrite, no special handling.
56
56
 
57
+ By default, a session whose latest compaction is not a stored native opaque window does not attempt
58
+ `/responses/compact`, preserving strict replay continuity. Set `allowCompactionContinuityBreak` to
59
+ `true` to restart native compaction from Pi's current effective context instead. Any information
60
+ already omitted by Pi's text summary cannot be recovered, but the successful compact response
61
+ becomes the new opaque replay checkpoint for later turns.
62
+
57
63
  ### Selection is by API, not provider
58
64
 
59
65
  Any provider speaking a Responses API gets a native compact attempt, including OpenAI-compatible
@@ -98,6 +104,7 @@ A missing file silently uses the defaults below. The extension never writes this
98
104
  ```json
99
105
  {
100
106
  "enabled": true,
107
+ "allowCompactionContinuityBreak": false,
101
108
 
102
109
  "compactionModel": "openai/gpt-5.1-mini",
103
110
  "compactionThinkingLevel": "off",
@@ -116,6 +123,7 @@ A missing file silently uses the defaults below. The extension never writes this
116
123
  | Key | Default | Description |
117
124
  |-----|---------|-------------|
118
125
  | `enabled` | `true` | Master switch. `false` → Pi default compaction everywhere. |
126
+ | `allowCompactionContinuityBreak` | `false` | Opt in to native compact recovery when the latest session compaction was created by Pi or another non-native path. The extension serializes `buildSessionContext().messages`, including Pi's text summary, into a new `/responses/compact` request. This sacrifices strict opaque-window continuity at that boundary; a successful response establishes a new native replay chain. |
119
127
  | `compactionModel` | *(unset)* | `"provider/model-id"` used for native-method fallback (non-Responses APIs, or when the compact endpoint fails). `null`/unset → use the current model via Pi's default path. The provider is split on the first `/`, so model ids may contain slashes (e.g. `"openrouter/deepseek/deepseek-chat"`). |
120
128
  | `compactionThinkingLevel` | `"off"` | Thinking level passed to the native `compact()` fallback. One of `off, minimal, low, medium, high, xhigh, max`. |
121
129
  | `responsesCompactApis` | both Responses APIs | Which Responses APIs use the compact endpoint. May only narrow the built-in set; unknown entries are ignored with a warning. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lll9p/pi-better-compaction",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "type": "module",
5
5
  "description": "Better compaction for pi: native /responses/compact replay for OpenAI Responses APIs, plus a configurable compaction model driving pi's native summarization everywhere else.",
6
6
  "author": "Lilin Lao",
@@ -14,7 +14,8 @@
14
14
  },
15
15
  "homepage": "https://github.com/lll9p/pi-better-compaction#readme",
16
16
  "publishConfig": {
17
- "access": "public"
17
+ "access": "public",
18
+ "registry": "https://registry.npmjs.org/"
18
19
  },
19
20
  "keywords": [
20
21
  "pi-package",
package/src/config.ts CHANGED
@@ -117,6 +117,9 @@ export function loadExtensionConfig(configPath: string = CONFIG_PATH): LoadedExt
117
117
  source = configPath;
118
118
 
119
119
  resolved.enabled = toBoolean(raw.enabled, "enabled", warnings) ?? resolved.enabled;
120
+ resolved.allowCompactionContinuityBreak =
121
+ toBoolean(raw.allowCompactionContinuityBreak, "allowCompactionContinuityBreak", warnings) ??
122
+ resolved.allowCompactionContinuityBreak;
120
123
  resolved.notifyOnLoad = toBoolean(raw.notifyOnLoad, "notifyOnLoad", warnings) ?? resolved.notifyOnLoad;
121
124
  resolved.debug = toBoolean(raw.debug, "debug", warnings) ?? resolved.debug;
122
125
  resolved.logProviderPayloads =
@@ -105,7 +105,7 @@ async function runResponsesNativeCompact(
105
105
  baseUrl: runtime.baseUrl,
106
106
  });
107
107
 
108
- let requestSource: "session-context" | "latest-native-replay";
108
+ let requestSource: "session-context" | "non-native-session-context" | "latest-native-replay";
109
109
  let request: NativeCompactionRequestBody;
110
110
  if (latestNativeCompaction.ok) {
111
111
  const liveTailEntries = branchEntries.slice(latestNativeCompaction.index + 1);
@@ -119,8 +119,13 @@ async function runResponsesNativeCompact(
119
119
  input,
120
120
  instructions,
121
121
  };
122
- } else if (latestNativeCompaction.reason === "no-compaction") {
123
- requestSource = "session-context";
122
+ } else if (
123
+ latestNativeCompaction.reason === "no-compaction" ||
124
+ (latestNativeCompaction.reason === "latest-compaction-not-native" &&
125
+ config.allowCompactionContinuityBreak)
126
+ ) {
127
+ requestSource =
128
+ latestNativeCompaction.reason === "no-compaction" ? "session-context" : "non-native-session-context";
124
129
  request = serializeMessagesToCompactRequest({
125
130
  model: runtime.currentModel,
126
131
  messages: ctx.sessionManager.buildSessionContext().messages,
package/src/types.ts CHANGED
@@ -31,6 +31,11 @@ export type DebugArtifactKind =
31
31
 
32
32
  export type ExtensionConfig = {
33
33
  enabled: boolean;
34
+ /**
35
+ * Allow a Responses session whose latest compaction was not created by this extension
36
+ * to restart native compaction from Pi's current serialized session context.
37
+ */
38
+ allowCompactionContinuityBreak: boolean;
34
39
  /**
35
40
  * "provider/model-id" used for native-method fallback compaction (non-Responses APIs,
36
41
  * or when the compact endpoint fails). Unset = current model via pi's default path.
@@ -284,6 +289,7 @@ export function createNativeCompactionResult(
284
289
 
285
290
  export const DEFAULT_EXTENSION_CONFIG: ExtensionConfig = {
286
291
  enabled: true,
292
+ allowCompactionContinuityBreak: false,
287
293
  compactionModel: undefined,
288
294
  compactionThinkingLevel: "off",
289
295
  responsesCompactApis: [...RESPONSES_COMPACT_CAPABLE_APIS],