@narumitw/pi-codex-compact 0.50.2 → 0.51.0

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@narumitw/pi-codex-compact)](https://www.npmjs.com/package/@narumitw/pi-codex-compact) [![Pi extension](https://img.shields.io/badge/Pi-extension-blue)](https://pi.dev) [![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](./LICENSE)
4
4
 
5
- Use OpenAI Codex Remote Compaction V2 in Pi instead of generating a local plaintext summary for compatible `openai-codex` sessions.
5
+ Use Codex Remote Compaction V2 in Pi instead of generating a local plaintext summary for models that use the `openai-codex-responses` API.
6
6
 
7
7
  The extension requests and stores an opaque server-generated checkpoint, then safely replays it in later Codex Responses requests.
8
8
 
@@ -10,7 +10,7 @@ Pi still decides when compaction runs and retains its normal `/compact`, thresho
10
10
 
11
11
  ## ✨ Features
12
12
 
13
- - Uses the active `openai-codex` OAuth credentials without persisting tokens or request headers.
13
+ - Uses the active Codex Responses provider and credentials without persisting secrets or request headers.
14
14
  - Handles manual, threshold, and overflow compaction through Pi's existing lifecycle.
15
15
  - Validates and persists one bounded opaque checkpoint that survives compatible reloads, resumes, and forks.
16
16
  - Replays the latest checkpoint while preserving newer conversation and extension context.
@@ -45,14 +45,14 @@ Avoid loading a global npm installation and the local workspace at the same time
45
45
 
46
46
  ## 🚀 Quick start
47
47
 
48
- 1. Sign in through Pi's built-in OpenAI Codex OAuth provider.
49
- 2. Select a model whose provider is `openai-codex` and API is `openai-codex-responses`.
48
+ 1. Sign in through Pi's built-in OpenAI Codex provider, or configure a custom provider that routes to a compatible Codex backend.
49
+ 2. Select a model whose API is `openai-codex-responses`.
50
50
  3. Work normally.
51
51
  Pi's automatic compaction and built-in `/compact` continue to operate.
52
52
  4. Run `/codex-compact` to inspect the effective route or choose **Compact now**.
53
53
  5. After compaction, continue the session normally; compatible requests replay the opaque checkpoint.
54
54
 
55
- When the active model is unsupported, compaction remains entirely Pi-native.
55
+ When the active model uses another API, compaction remains entirely Pi-native.
56
56
 
57
57
  ## 💬 Commands
58
58
 
@@ -129,31 +129,35 @@ This extension does **not** read `~/.codex/config.toml`.
129
129
  ## ✅ Requirements and compatibility
130
130
 
131
131
  - Pi APIs compatible with the package's declared peer dependencies.
132
- - The built-in provider `openai-codex`.
133
132
  - API `openai-codex-responses` on the active model.
134
- - A working OpenAI Codex OAuth login and Remote V2 entitlement.
133
+ - A built-in or custom provider that routes that API to a backend supporting `compaction_trigger` and opaque `compaction` replay.
134
+ - Working credentials and Remote V2 entitlement for that backend.
135
135
 
136
- OpenAI API-key, Azure, GitHub Copilot, proxies, and arbitrary Responses-compatible providers are not supported.
137
- Switching to another provider or model leaves Pi's visible fallback marker plus retained recent messages in context.
138
- Switching back to the checkpoint's original compatible model restores opaque replay.
136
+ The built-in `openai-codex` provider is supported, and a custom provider or proxy is eligible when its model explicitly uses `openai-codex-responses`.
137
+ Generic `openai-responses`, `azure-openai-responses`, GitHub Copilot, and other merely Responses-compatible API labels are not eligible.
138
+ The extension does not probe provider capabilities before compaction; a provider that declares `openai-codex-responses` owns compatible routing, authentication, request transforms, SSE transport, and opaque replay.
139
+ A failed Remote V2 compaction attempt falls back to Pi native, but an ordinary request cannot transparently recover after an incompatible provider has already received an existing opaque checkpoint.
140
+ Provider provenance is stored for diagnosis but is not a replay gate.
141
+ Switching providers can replay a checkpoint only when the API and exact model ID still match; switching model IDs leaves Pi's visible fallback marker plus retained recent messages in context.
139
142
 
140
143
  ## 🔄 How it works
141
144
 
142
145
  1. Pi prepares compaction and selects the recent message suffix it will retain.
143
- 2. The extension projects an earlier compatible checkpoint, if present, into the current Responses input.
144
- 3. It appends exactly one final `compaction_trigger` and sends a normal authenticated Codex Responses SSE request with cache retention disabled.
146
+ 2. If an earlier compatible checkpoint is present, the extension identifies its boundary from the summary persisted on the active `CompactionEntry` and validates the retained suffix fingerprints.
147
+ 3. It projects that checkpoint into the current Responses input, appends exactly one final `compaction_trigger`, and sends a normal authenticated Codex Responses SSE request with cache retention disabled.
145
148
  4. It requires a completed response containing exactly one non-empty opaque `compaction` item.
146
149
  5. It constructs bounded replacement history from recent raw user-role Responses items followed by the opaque item.
147
150
  6. It stores that history and fingerprints of Pi's retained suffix in versioned `CompactionEntry.details`.
148
151
  7. On later compatible requests, it replaces an exactly validated marker with the persisted replacement history immediately before provider dispatch.
149
152
 
150
- If fingerprints, model identity, payload shape, or marker count do not match exactly, the extension leaves Pi's visible fallback context unchanged instead of guessing.
153
+ The persisted entry remains the summary identity source, so replay does not depend on the wording generated by the currently installed extension version.
154
+ If persisted summary identity, fingerprints, model identity, payload shape, or marker count do not match exactly, the extension leaves Pi's visible fallback context unchanged instead of guessing.
151
155
 
152
156
  ## 🔒 Security and privacy
153
157
 
154
- Remote compaction sends the active conversation context, system prompt, and active tool schemas to the same OpenAI Codex backend used by the selected model.
155
- The Pi session stores the encrypted compaction item and bounded recent user-role Responses items.
156
- It does not store OAuth tokens, authorization headers, or request headers in checkpoint details.
158
+ Remote compaction sends the active conversation context, system prompt, and active tool schemas to the configured backend used by the selected Codex Responses provider.
159
+ The Pi session stores the producing provider ID, encrypted compaction item, and bounded recent user-role Responses items.
160
+ It does not store credentials, authorization headers, or request headers in checkpoint details.
157
161
 
158
162
  | Boundary | Limit |
159
163
  | --- | ---: |
@@ -173,7 +177,7 @@ These hard byte ceilings are intentionally not configurable.
173
177
 
174
178
  - The wire contract is undocumented and can change independently of Pi or this package.
175
179
  Keep backups of important sessions.
176
- - Full older history depends on this extension and the same compatible model.
180
+ - Full older history depends on this extension, the `openai-codex-responses` API, the exact checkpoint model ID, and a provider route whose backend accepts the opaque item.
177
181
  Removing the extension exposes only the portability fallback marker and Pi-retained recent messages.
178
182
  - The package does not reproduce Codex core's context-window UUID/number lineage, previous-model compatibility fallback, exact pre-turn ordering, or exact mid-turn model-session ownership.
179
183
  - Remote failure falls back to Pi's plaintext summary, so a session can contain both remote opaque and native compaction entries over time.
@@ -187,6 +191,7 @@ src/codex-compact.ts Pi lifecycle, command, provider projection, and fallback
187
191
  src/remote.ts Provider stream invocation, auth payload, timeout, and retry controls
188
192
  src/protocol.ts Bounded SSE parsing and Remote V2 payload/output validation
189
193
  src/checkpoint.ts Replacement history, fingerprints, persistence, and replay projection
194
+ src/model-compatibility.ts API-based Remote V2 model eligibility
190
195
  src/settings.ts Global settings validation and atomic persistence
191
196
  src/settings-menu.ts First-use manual compaction and settings TUI
192
197
 
@@ -232,7 +237,7 @@ See [`docs/implementation-notes/codex-compaction-mechanism.md`](../../docs/imple
232
237
 
233
238
  ## 🔎 Keywords
234
239
 
235
- Pi extension, Pi coding agent, OpenAI Codex, OAuth, Remote Compaction V2, opaque checkpoint, Responses API, context compaction.
240
+ Pi extension, Pi coding agent, OpenAI Codex, custom provider, proxy, Remote Compaction V2, opaque checkpoint, Responses API, context compaction.
236
241
 
237
242
  ## 📄 License
238
243
 
@@ -0,0 +1,13 @@
1
+ // @generated by scripts/build-runtime.mjs; do not edit.
2
+ // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+
4
+ // src/model-compatibility.ts
5
+ import { hasApi } from "@earendil-works/pi-ai";
6
+ function isCodexRemoteCompactionModel(model) {
7
+ return model !== void 0 && hasApi(model, "openai-codex-responses");
8
+ }
9
+
10
+ export {
11
+ isCodexRemoteCompactionModel
12
+ };
13
+ //# sourceMappingURL=chunk-3WRPJHG2.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/model-compatibility.ts"],
4
+ "sourcesContent": ["import type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { hasApi } from \"@earendil-works/pi-ai\";\n\nexport function isCodexRemoteCompactionModel(\n\tmodel: Model<Api> | undefined,\n): model is Model<\"openai-codex-responses\"> {\n\treturn model !== undefined && hasApi(model, \"openai-codex-responses\");\n}\n"],
5
+ "mappings": ";;;;AACA,SAAS,cAAc;AAEhB,SAAS,6BACf,OAC2C;AAC3C,SAAO,UAAU,UAAa,OAAO,OAAO,wBAAwB;AACrE;",
6
+ "names": []
7
+ }
@@ -1,5 +1,8 @@
1
1
  // @generated by scripts/build-runtime.mjs; do not edit.
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+ import {
4
+ isCodexRemoteCompactionModel
5
+ } from "./chunk-3WRPJHG2.js";
3
6
 
4
7
  // src/settings-menu.ts
5
8
  function safeText(value) {
@@ -173,7 +176,7 @@ function compactMenuStatus(ctx) {
173
176
  const model = ctx.model;
174
177
  return {
175
178
  model: model ? `${model.provider}/${model.id}` : "none",
176
- remoteCompatible: model?.provider === "openai-codex" && model.api === "openai-codex-responses"
179
+ remoteCompatible: isCodexRemoteCompactionModel(model)
177
180
  };
178
181
  }
179
182
  function compactRoute(state, status) {
@@ -181,7 +184,8 @@ function compactRoute(state, status) {
181
184
  return status?.remoteCompatible ? "Codex Remote V2" : "Pi native (model not compatible)";
182
185
  }
183
186
  export {
187
+ compactMenuStatus,
184
188
  createCodexCompactMenu,
185
189
  showCodexCompactMenu
186
190
  };
187
- //# sourceMappingURL=settings-menu-BLWCLVPZ.ts.map
191
+ //# sourceMappingURL=settings-menu-4YW2GOKW.ts.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/settings-menu.ts"],
4
+ "sourcesContent": ["import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport type { MenuDefinition } from \"@narumitw/pi-tui-kit\";\nimport { isCodexRemoteCompactionModel } from \"./model-compatibility.js\";\nimport type {\n\tCodexCompactSettings,\n\tCodexCompactSettingsRuntime,\n\tCodexCompactSettingsState,\n} from \"./settings.js\";\n\ntype Screen = \"main\" | \"settings\" | \"invalid\";\ntype Action =\n\t| \"compact-now\"\n\t| \"set-enabled\"\n\t| \"set-timeout\"\n\t| \"set-retries\"\n\t| \"set-retention\"\n\t| \"set-notify\";\n\nexport interface SettingsMenuOwner {\n\tsignal: AbortSignal;\n\tisCurrent(): boolean;\n}\n\ninterface CompactMenuStatus {\n\tmodel: string;\n\tremoteCompatible: boolean;\n}\n\nfunction safeText(value: string): string {\n\treturn Array.from(value, (character) => {\n\t\tconst codePoint = character.codePointAt(0) ?? 0;\n\t\treturn codePoint < 32 || (codePoint >= 127 && codePoint <= 159) ? \" \" : character;\n\t}).join(\"\");\n}\n\nfunction timeoutLabel(milliseconds: number): string {\n\treturn `${milliseconds / 60_000} min`;\n}\n\nfunction retentionLabel(tokens: number): string {\n\treturn `${tokens / 1000}K tokens`;\n}\n\nasync function update(\n\truntime: CodexCompactSettingsRuntime,\n\tctx: ExtensionCommandContext,\n\tpatch: Partial<CodexCompactSettings>,\n\tsignal: AbortSignal,\n) {\n\ttry {\n\t\tawait runtime.update(patch, signal);\n\t\tctx.ui.notify(\"Codex compaction settings saved.\", \"info\");\n\t\treturn { kind: \"stay\" as const };\n\t} catch (error) {\n\t\tif (signal.aborted) return { kind: \"rejected\" as const };\n\t\tctx.ui.notify(\n\t\t\t`Could not save pi-codex-compact.json: ${safeText(error instanceof Error ? error.message : String(error))}`,\n\t\t\t\"error\",\n\t\t);\n\t\treturn { kind: \"rejected\" as const };\n\t}\n}\n\nexport function createCodexCompactMenu(\n\truntime: CodexCompactSettingsRuntime,\n\toptions: { onCompactRequested?: () => void; status?: CompactMenuStatus } = {},\n): MenuDefinition<CodexCompactSettingsState, Screen, Action, ExtensionCommandContext> {\n\treturn {\n\t\tstart: \"main\",\n\t\tscreens: {\n\t\t\tmain: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: \"Codex Remote Compaction\",\n\t\t\t\tlines: [\n\t\t\t\t\t`Remote V2: ${state.settings.enabled ? \"On\" : \"Off\"}`,\n\t\t\t\t\t`Active model: ${safeText(options.status?.model ?? \"none\")}`,\n\t\t\t\t\t`Compact route: ${safeText(compactRoute(state, options.status))}`,\n\t\t\t\t],\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"compact-now\",\n\t\t\t\t\t\tlabel: \"Compact now\",\n\t\t\t\t\t\tdescription: \"Close this menu and compact the active session immediately.\",\n\t\t\t\t\t\taction: \"compact-now\",\n\t\t\t\t\t},\n\t\t\t\t\tstate.kind === \"invalid\"\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: \"settings\",\n\t\t\t\t\t\t\t\tlabel: \"Settings\",\n\t\t\t\t\t\t\t\tdescription: \"Read-only until the invalid settings file is repaired.\",\n\t\t\t\t\t\t\t\tto: \"invalid\" as const,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: { id: \"settings\", label: \"Settings\", to: \"settings\" as const },\n\t\t\t\t\t{ id: \"close\", label: \"Close\", close: true },\n\t\t\t\t],\n\t\t\t\thint: \"close\",\n\t\t\t}),\n\t\t\tsettings: ({ state }) => ({\n\t\t\t\tkind: \"settings\",\n\t\t\t\ttitle: \"Codex Remote Compaction Settings\",\n\t\t\t\tlines: [`User settings \u00B7 ${safeText(state.path)}`],\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"enabled\",\n\t\t\t\t\t\tlabel: \"Remote compaction\",\n\t\t\t\t\t\tdescription: \"Use Codex Remote V2 when the active model is compatible.\",\n\t\t\t\t\t\tcurrentValue: state.settings.enabled ? \"On\" : \"Off\",\n\t\t\t\t\t\tvalues: [\"On\", \"Off\"],\n\t\t\t\t\t\taction: \"set-enabled\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"requestTimeoutMs\",\n\t\t\t\t\t\tlabel: \"Request timeout\",\n\t\t\t\t\t\tdescription: \"Maximum time for the extension-owned remote compaction request.\",\n\t\t\t\t\t\tcurrentValue: timeoutLabel(state.settings.requestTimeoutMs),\n\t\t\t\t\t\tvalues: [\"2 min\", \"5 min\", \"10 min\"],\n\t\t\t\t\t\taction: \"set-timeout\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"maxRetries\",\n\t\t\t\t\t\tlabel: \"Transport retries\",\n\t\t\t\t\t\tdescription: \"Retry transient provider failures before falling back to Pi.\",\n\t\t\t\t\t\tcurrentValue: String(state.settings.maxRetries),\n\t\t\t\t\t\tvalues: [\"0\", \"1\", \"2\"],\n\t\t\t\t\t\taction: \"set-retries\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"replacementTokenBudget\",\n\t\t\t\t\t\tlabel: \"Retained user history\",\n\t\t\t\t\t\tdescription: \"Approximate user-message budget kept beside the opaque checkpoint.\",\n\t\t\t\t\t\tcurrentValue: retentionLabel(state.settings.replacementTokenBudget),\n\t\t\t\t\t\tvalues: [\"32K tokens\", \"64K tokens\", \"96K tokens\", \"128K tokens\"],\n\t\t\t\t\t\taction: \"set-retention\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"notifyOnFallback\",\n\t\t\t\t\t\tlabel: \"Fallback notifications\",\n\t\t\t\t\t\tdescription: \"Warn when Remote V2 fails and native Pi compaction takes over.\",\n\t\t\t\t\t\tcurrentValue: state.settings.notifyOnFallback ? \"On\" : \"Off\",\n\t\t\t\t\t\tvalues: [\"On\", \"Off\"],\n\t\t\t\t\t\taction: \"set-notify\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}),\n\t\t\tinvalid: ({ state }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: \"Codex Compact Settings \u00B7 Read only\",\n\t\t\t\tlines: [\n\t\t\t\t\t`Invalid settings file: ${safeText(state.path)}`,\n\t\t\t\t\t`Issue: ${safeText(state.issue ?? \"unknown validation error\")}`,\n\t\t\t\t\t\"Built-in defaults are active. Repair the file and run /reload; it will not be overwritten.\",\n\t\t\t\t],\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\t\"compact-now\": async () => {\n\t\t\t\toptions.onCompactRequested?.();\n\t\t\t\treturn { kind: \"close\" };\n\t\t\t},\n\t\t\t\"set-enabled\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(runtime, ctx, { enabled: value === \"On\" }, signal),\n\t\t\t\"set-timeout\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(\n\t\t\t\t\truntime,\n\t\t\t\t\tctx,\n\t\t\t\t\t{ requestTimeoutMs: Number.parseInt(value ?? \"5\", 10) * 60_000 },\n\t\t\t\t\tsignal,\n\t\t\t\t),\n\t\t\t\"set-retries\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(runtime, ctx, { maxRetries: Number.parseInt(value ?? \"2\", 10) }, signal),\n\t\t\t\"set-retention\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(\n\t\t\t\t\truntime,\n\t\t\t\t\tctx,\n\t\t\t\t\t{ replacementTokenBudget: Number.parseInt(value ?? \"64\", 10) * 1000 },\n\t\t\t\t\tsignal,\n\t\t\t\t),\n\t\t\t\"set-notify\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(runtime, ctx, { notifyOnFallback: value === \"On\" }, signal),\n\t\t},\n\t};\n}\n\nexport async function showCodexCompactMenu(\n\truntime: CodexCompactSettingsRuntime,\n\tctx: ExtensionCommandContext,\n\towner: SettingsMenuOwner,\n): Promise<void> {\n\tif (ctx.mode !== \"tui\") {\n\t\tctx.ui.notify(`Edit Codex compaction settings at ${safeText(runtime.get().path)}.`, \"info\");\n\t\treturn;\n\t}\n\tconst { runMenu } = await import(\"@narumitw/pi-tui-kit\");\n\tif (owner.signal.aborted || !owner.isCurrent()) return;\n\tlet compactRequested = false;\n\tawait runMenu(\n\t\tctx,\n\t\tcreateCodexCompactMenu(runtime, {\n\t\t\tonCompactRequested: () => {\n\t\t\t\tcompactRequested = true;\n\t\t\t},\n\t\t\tstatus: compactMenuStatus(ctx),\n\t\t}),\n\t\t{\n\t\t\tgetState: () => runtime.get(),\n\t\t\tsignal: owner.signal,\n\t\t\tisCurrent: owner.isCurrent,\n\t\t},\n\t);\n\tif (!compactRequested || owner.signal.aborted || !owner.isCurrent()) return;\n\tctx.compact({\n\t\tonError: (error) => {\n\t\t\tif (!owner.signal.aborted && owner.isCurrent()) {\n\t\t\t\tctx.ui.notify(`Compaction failed: ${safeText(error.message)}`, \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n\nexport function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {\n\tconst model = ctx.model;\n\treturn {\n\t\tmodel: model ? `${model.provider}/${model.id}` : \"none\",\n\t\tremoteCompatible: isCodexRemoteCompactionModel(model),\n\t};\n}\n\nfunction compactRoute(\n\tstate: Readonly<CodexCompactSettingsState>,\n\tstatus: CompactMenuStatus | undefined,\n): string {\n\tif (!state.settings.enabled) return \"Pi native (Remote V2 off)\";\n\treturn status?.remoteCompatible ? \"Codex Remote V2\" : \"Pi native (model not compatible)\";\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
package/dist/index.ts CHANGED
@@ -1,8 +1,10 @@
1
1
  // @generated by scripts/build-runtime.mjs; do not edit.
2
2
  // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader.
3
+ import {
4
+ isCodexRemoteCompactionModel
5
+ } from "./chunks/chunk-3WRPJHG2.js";
3
6
 
4
7
  // src/codex-compact.ts
5
- import { hasApi } from "@earendil-works/pi-ai";
6
8
  import {
7
9
  buildContextEntries,
8
10
  buildSessionContext,
@@ -150,7 +152,7 @@ function markerTextFromItem(item) {
150
152
  }
151
153
  function rewriteCheckpointMarker(payload, marker, replacementHistory) {
152
154
  if (!isObject(payload) || !Array.isArray(payload.input)) {
153
- throw new CodexCompactionProtocolError("OpenAI Codex payload is missing an input array");
155
+ throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
154
156
  }
155
157
  const matches = payload.input.map((item, index2) => markerTextFromItem(item) === marker ? index2 : -1).filter((index2) => index2 >= 0);
156
158
  if (matches.length !== 1) {
@@ -170,7 +172,7 @@ function rewriteCheckpointMarker(payload, marker, replacementHistory) {
170
172
  }
171
173
  function appendCompactionTrigger(payload) {
172
174
  if (!isObject(payload) || !Array.isArray(payload.input)) {
173
- throw new CodexCompactionProtocolError("OpenAI Codex payload is missing an input array");
175
+ throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
174
176
  }
175
177
  if (payload.input.some((item) => isObject(item) && item.type === "compaction_trigger")) {
176
178
  throw new CodexCompactionProtocolError(
@@ -193,6 +195,7 @@ var CHECKPOINT_VERSION = 1;
193
195
  var REPLACEMENT_TOKEN_BUDGET = 64e3;
194
196
  var REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;
195
197
  var MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;
198
+ var MAX_PROVIDER_ID_LENGTH = 256;
196
199
  function isObject2(value) {
197
200
  return typeof value === "object" && value !== null && !Array.isArray(value);
198
201
  }
@@ -213,13 +216,13 @@ function checkpointMarker(checkpointId) {
213
216
  return [
214
217
  `[PI_CODEX_REMOTE_CHECKPOINT:${checkpointId}]`,
215
218
  "Opaque checkpoint injection failed. Do not infer missing history; tell the user to re-enable",
216
- "@narumitw/pi-codex-compact with an openai-codex model."
219
+ "@narumitw/pi-codex-compact with a model using the openai-codex-responses API."
217
220
  ].join(" ");
218
221
  }
219
222
  function fallbackSummary(checkpointId) {
220
223
  return [
221
224
  `OpenAI Codex Remote Compaction V2 checkpoint ${checkpointId} stores the older history opaquely.`,
222
- "Full replay requires @narumitw/pi-codex-compact and an openai-codex model.",
225
+ "Full replay requires @narumitw/pi-codex-compact and the same model through a compatible Codex Responses provider.",
223
226
  "Without them, only Pi's retained recent messages remain available."
224
227
  ].join(" ");
225
228
  }
@@ -232,7 +235,7 @@ function markerMessage(checkpointId, timestamp) {
232
235
  }
233
236
  function parseCheckpointDetails(value) {
234
237
  if (!isObject2(value)) return void 0;
235
- if (value.kind !== CHECKPOINT_KIND || value.version !== CHECKPOINT_VERSION || typeof value.checkpointId !== "string" || value.checkpointId.length < 8 || value.provider !== "openai-codex" || value.api !== "openai-codex-responses" || typeof value.modelId !== "string" || value.protocol !== "remote-compaction-v2" || !Array.isArray(value.replacementHistory) || !Array.isArray(value.keptMessageFingerprints) || typeof value.createdAt !== "string") {
238
+ if (value.kind !== CHECKPOINT_KIND || value.version !== CHECKPOINT_VERSION || typeof value.checkpointId !== "string" || value.checkpointId.length < 8 || typeof value.provider !== "string" || value.provider.length === 0 || value.provider.length > MAX_PROVIDER_ID_LENGTH || value.api !== "openai-codex-responses" || typeof value.modelId !== "string" || value.protocol !== "remote-compaction-v2" || !Array.isArray(value.replacementHistory) || !Array.isArray(value.keptMessageFingerprints) || typeof value.createdAt !== "string") {
236
239
  return void 0;
237
240
  }
238
241
  if (value.replacementHistory.length === 0 || !value.replacementHistory.every(isObject2) || !value.keptMessageFingerprints.every(
@@ -260,10 +263,9 @@ function latestCheckpoint(entries) {
260
263
  function isOlderCompactionSummary(message, timestamp) {
261
264
  return message.role === "compactionSummary" && Number.isFinite(message.timestamp) && Number.isFinite(timestamp) && message.timestamp < timestamp;
262
265
  }
263
- function projectCheckpointContext(messages, details) {
264
- const summary = fallbackSummary(details.checkpointId);
266
+ function projectCheckpointContext(messages, details, checkpointSummary) {
265
267
  const summaryIndex = messages.findIndex(
266
- (message) => message.role === "compactionSummary" && message.summary === summary
268
+ (message) => message.role === "compactionSummary" && message.summary === checkpointSummary
267
269
  );
268
270
  if (summaryIndex < 0) return void 0;
269
271
  const timestamp = messages[summaryIndex].timestamp;
@@ -359,7 +361,7 @@ function createCheckpointDetails(input) {
359
361
  kind: CHECKPOINT_KIND,
360
362
  version: CHECKPOINT_VERSION,
361
363
  checkpointId: input.checkpointId ?? randomUUID(),
362
- provider: "openai-codex",
364
+ provider: input.provider,
363
365
  api: "openai-codex-responses",
364
366
  modelId: input.modelId,
365
367
  protocol: "remote-compaction-v2",
@@ -432,7 +434,7 @@ async function requestRemoteCompaction(request) {
432
434
  for await (const event of stream) {
433
435
  if (request.signal.aborted) throw abortError();
434
436
  if (event.type === "error") {
435
- throw new Error(event.error.errorMessage ?? "OpenAI Codex compaction request failed");
437
+ throw new Error(event.error.errorMessage ?? "Codex remote compaction request failed");
436
438
  }
437
439
  if (event.type === "done") usage = event.message.usage;
438
440
  }
@@ -602,14 +604,11 @@ function isNodeError(error) {
602
604
 
603
605
  // src/codex-compact.ts
604
606
  var STATUS_KEY = "codex-compact";
605
- function isSupportedModel(model) {
606
- return model?.provider === "openai-codex" && hasApi(model, "openai-codex-responses");
607
- }
608
607
  function activeCheckpoint(ctx) {
609
608
  return latestCheckpoint(ctx.sessionManager.getBranch());
610
609
  }
611
610
  function isCheckpointCompatible(details, model) {
612
- return isSupportedModel(model) && model.id === details.modelId;
611
+ return isCodexRemoteCompactionModel(model) && model.id === details.modelId;
613
612
  }
614
613
  function keptMessages(event) {
615
614
  const leafId = event.branchEntries.at(-1)?.id ?? null;
@@ -633,16 +632,16 @@ function activeTools(pi) {
633
632
  function projectedCurrentMessages(event, model) {
634
633
  const leafId = event.branchEntries.at(-1)?.id ?? null;
635
634
  const session = buildSessionContext(event.branchEntries, leafId);
636
- const prior = latestCheckpoint(event.branchEntries)?.details;
635
+ const prior = latestCheckpoint(event.branchEntries);
637
636
  if (!prior) return { messages: session.messages };
638
- if (prior.modelId !== model.id) {
637
+ if (prior.details.modelId !== model.id) {
639
638
  throw new Error("The active opaque checkpoint belongs to a different Codex model");
640
639
  }
641
- const projected = projectCheckpointContext(session.messages, prior);
640
+ const projected = projectCheckpointContext(session.messages, prior.details, prior.entry.summary);
642
641
  if (!projected) {
643
642
  throw new Error("The previous opaque checkpoint could not be projected safely");
644
643
  }
645
- return { messages: projected, prior };
644
+ return { messages: projected, prior: prior.details };
646
645
  }
647
646
  function notifyFailure(ctx, error, settings) {
648
647
  if (!ctx.hasUI || !settings.notifyOnFallback) return;
@@ -654,17 +653,15 @@ function sessionStillOwned(ctx, sessionId, signal) {
654
653
  }
655
654
  async function compactRemotely(pi, event, ctx, settings, fetch) {
656
655
  const model = ctx.model;
657
- if (!settings.enabled || !isSupportedModel(model)) return void 0;
656
+ if (!settings.enabled || !isCodexRemoteCompactionModel(model)) return void 0;
658
657
  const sessionId = ctx.sessionManager.getSessionId();
659
658
  ctx.ui.setStatus(STATUS_KEY, "Codex remote compaction\u2026");
660
659
  try {
661
660
  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
662
661
  if (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };
663
- if (!auth.ok || !auth.apiKey) {
664
- throw new Error(auth.ok ? "OpenAI Codex OAuth token is unavailable" : auth.error);
665
- }
662
+ if (!auth.ok) throw new Error(auth.error);
666
663
  const provider = ctx.modelRegistry.getProvider(model.provider);
667
- if (!provider) throw new Error("OpenAI Codex provider is unavailable");
664
+ if (!provider) throw new Error("The active Codex Responses provider is unavailable");
668
665
  const current = projectedCurrentMessages(event, model);
669
666
  const context = {
670
667
  systemPrompt: ctx.getSystemPrompt(),
@@ -692,6 +689,7 @@ async function compactRemotely(pi, event, ctx, settings, fetch) {
692
689
  tokenBudget: settings.replacementTokenBudget
693
690
  });
694
691
  const details = createCheckpointDetails({
692
+ provider: model.provider,
695
693
  modelId: model.id,
696
694
  replacementHistory,
697
695
  keptMessages: keptMessages(event)
@@ -726,7 +724,7 @@ function createCodexCompactExtension(options = {}) {
726
724
  handler: async (_args, ctx) => {
727
725
  const ownerGeneration = generation;
728
726
  const controller = sessionController;
729
- const { showCodexCompactMenu } = await import("./chunks/settings-menu-BLWCLVPZ.js");
727
+ const { showCodexCompactMenu } = await import("./chunks/settings-menu-4YW2GOKW.js");
730
728
  if (ownerGeneration !== generation || controller.signal.aborted) return;
731
729
  await showCodexCompactMenu(settingsRuntime, ctx, {
732
730
  signal: controller.signal,
@@ -772,7 +770,11 @@ function createCodexCompactExtension(options = {}) {
772
770
  if (!settingsRuntime.get().settings.enabled) return void 0;
773
771
  const checkpoint = activeCheckpoint(ctx);
774
772
  if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return void 0;
775
- const messages = projectCheckpointContext(event.messages, checkpoint.details);
773
+ const messages = projectCheckpointContext(
774
+ event.messages,
775
+ checkpoint.details,
776
+ checkpoint.entry.summary
777
+ );
776
778
  return messages ? { messages } : void 0;
777
779
  });
778
780
  pi.on("before_provider_request", (event, ctx) => {
package/dist/index.ts.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/codex-compact.ts", "../src/checkpoint.ts", "../src/protocol.ts", "../src/remote.ts", "../src/settings.ts"],
4
- "sourcesContent": ["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Context, Model, Tool } from \"@earendil-works/pi-ai\";\nimport { hasApi } from \"@earendil-works/pi-ai\";\nimport {\n\tbuildContextEntries,\n\tbuildSessionContext,\n\tconvertToLlm,\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\ttype SessionBeforeCompactEvent,\n\tsessionEntryToContextMessages,\n} from \"@earendil-works/pi-coding-agent\";\nimport {\n\tbuildReplacementHistory,\n\ttype CodexCheckpointDetails,\n\tcheckpointMarker,\n\tcreateCheckpointDetails,\n\tfallbackSummary,\n\tlatestCheckpoint,\n\tprojectCheckpointContext,\n} from \"./checkpoint.js\";\nimport { hasCheckpointMarker, rewriteCheckpointMarker } from \"./protocol.js\";\nimport { requestRemoteCompaction } from \"./remote.js\";\nimport {\n\ttype CodexCompactSettings,\n\ttype CodexCompactSettingsRuntime,\n\ttype CodexCompactSettingsState,\n\tcreateCodexCompactSettingsRuntime,\n} from \"./settings.js\";\n\nconst STATUS_KEY = \"codex-compact\";\n\nfunction isSupportedModel(model: Model<Api> | undefined): model is Model<\"openai-codex-responses\"> {\n\treturn model?.provider === \"openai-codex\" && hasApi(model, \"openai-codex-responses\");\n}\n\nfunction activeCheckpoint(ctx: ExtensionContext) {\n\treturn latestCheckpoint(ctx.sessionManager.getBranch());\n}\n\nfunction isCheckpointCompatible(\n\tdetails: CodexCheckpointDetails,\n\tmodel: Model<Api> | undefined,\n): model is Model<\"openai-codex-responses\"> {\n\treturn isSupportedModel(model) && model.id === details.modelId;\n}\n\nfunction keptMessages(event: SessionBeforeCompactEvent): AgentMessage[] {\n\tconst leafId = event.branchEntries.at(-1)?.id ?? null;\n\tconst contextEntries = buildContextEntries(event.branchEntries, leafId);\n\tconst keptIndex = contextEntries.findIndex(\n\t\t(entry) => entry.id === event.preparation.firstKeptEntryId,\n\t);\n\tif (keptIndex < 0) {\n\t\tthrow new Error(\"Pi compaction cut point is not present in the active context\");\n\t}\n\treturn contextEntries.slice(keptIndex).flatMap(sessionEntryToContextMessages);\n}\n\nfunction activeTools(pi: ExtensionAPI): Tool[] {\n\tconst enabled = new Set(pi.getActiveTools());\n\treturn pi\n\t\t.getAllTools()\n\t\t.filter((tool) => enabled.has(tool.name))\n\t\t.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.parameters,\n\t\t}));\n}\n\nfunction projectedCurrentMessages(\n\tevent: SessionBeforeCompactEvent,\n\tmodel: Model<\"openai-codex-responses\">,\n): { messages: AgentMessage[]; prior?: CodexCheckpointDetails } {\n\tconst leafId = event.branchEntries.at(-1)?.id ?? null;\n\tconst session = buildSessionContext(event.branchEntries, leafId);\n\tconst prior = latestCheckpoint(event.branchEntries)?.details;\n\tif (!prior) return { messages: session.messages };\n\tif (prior.modelId !== model.id) {\n\t\tthrow new Error(\"The active opaque checkpoint belongs to a different Codex model\");\n\t}\n\tconst projected = projectCheckpointContext(session.messages, prior);\n\tif (!projected) {\n\t\tthrow new Error(\"The previous opaque checkpoint could not be projected safely\");\n\t}\n\treturn { messages: projected, prior };\n}\n\nfunction notifyFailure(\n\tctx: ExtensionContext,\n\terror: unknown,\n\tsettings: CodexCompactSettings,\n): void {\n\tif (!ctx.hasUI || !settings.notifyOnFallback) return;\n\tconst message = error instanceof Error ? error.message : String(error);\n\tctx.ui.notify(`Codex remote compaction failed; using Pi compaction. ${message}`, \"warning\");\n}\n\nfunction sessionStillOwned(ctx: ExtensionContext, sessionId: string, signal: AbortSignal): boolean {\n\treturn !signal.aborted && ctx.sessionManager.getSessionId() === sessionId;\n}\n\nasync function compactRemotely(\n\tpi: ExtensionAPI,\n\tevent: SessionBeforeCompactEvent,\n\tctx: ExtensionContext,\n\tsettings: CodexCompactSettings,\n\tfetch?: typeof globalThis.fetch,\n) {\n\tconst model = ctx.model;\n\tif (!settings.enabled || !isSupportedModel(model)) return undefined;\n\tconst sessionId = ctx.sessionManager.getSessionId();\n\tctx.ui.setStatus(STATUS_KEY, \"Codex remote compaction\u2026\");\n\ttry {\n\t\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\t\tif (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };\n\t\tif (!auth.ok || !auth.apiKey) {\n\t\t\tthrow new Error(auth.ok ? \"OpenAI Codex OAuth token is unavailable\" : auth.error);\n\t\t}\n\t\tconst provider = ctx.modelRegistry.getProvider(model.provider);\n\t\tif (!provider) throw new Error(\"OpenAI Codex provider is unavailable\");\n\t\tconst current = projectedCurrentMessages(event, model);\n\t\tconst context: Context = {\n\t\t\tsystemPrompt: ctx.getSystemPrompt(),\n\t\t\tmessages: convertToLlm(current.messages),\n\t\t\ttools: activeTools(pi),\n\t\t};\n\t\tconst response = await requestRemoteCompaction({\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t\tcontext,\n\t\t\tapiKey: auth.apiKey,\n\t\t\theaders: auth.headers,\n\t\t\tenv: auth.env,\n\t\t\tsignal: event.signal,\n\t\t\tpriorCheckpoint: current.prior\n\t\t\t\t? {\n\t\t\t\t\t\tmarker: checkpointMarker(current.prior.checkpointId),\n\t\t\t\t\t\treplacementHistory: current.prior.replacementHistory,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\trequestTimeoutMs: settings.requestTimeoutMs,\n\t\t\tmaxRetries: settings.maxRetries,\n\t\t\tfetch,\n\t\t});\n\t\tif (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };\n\t\tconst replacementHistory = buildReplacementHistory(response.promptInput, response.item, {\n\t\t\ttokenBudget: settings.replacementTokenBudget,\n\t\t});\n\t\tconst details = createCheckpointDetails({\n\t\t\tmodelId: model.id,\n\t\t\treplacementHistory,\n\t\t\tkeptMessages: keptMessages(event),\n\t\t});\n\t\treturn {\n\t\t\tcompaction: {\n\t\t\t\tsummary: fallbackSummary(details.checkpointId),\n\t\t\t\tfirstKeptEntryId: event.preparation.firstKeptEntryId,\n\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\tusage: response.usage,\n\t\t\t\tdetails,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (event.signal.aborted || ctx.sessionManager.getSessionId() !== sessionId) {\n\t\t\treturn { cancel: true };\n\t\t}\n\t\tnotifyFailure(ctx, error, settings);\n\t\treturn undefined;\n\t} finally {\n\t\tif (ctx.sessionManager.getSessionId() === sessionId) ctx.ui.setStatus(STATUS_KEY, undefined);\n\t}\n}\n\nexport function createCodexCompactExtension(\n\toptions: { fetch?: typeof globalThis.fetch; settingsRuntime?: CodexCompactSettingsRuntime } = {},\n): (pi: ExtensionAPI) => void {\n\treturn (pi) => {\n\t\tconst providerWarnings = new Set<string>();\n\t\tconst settingsRuntime = options.settingsRuntime ?? createCodexCompactSettingsRuntime();\n\t\tlet sessionController = new AbortController();\n\t\tlet generation = 0;\n\n\t\tpi.registerCommand(\"codex-compact\", {\n\t\t\tdescription: \"Compact now or configure Codex Remote Compaction V2\",\n\t\t\thandler: async (_args, ctx) => {\n\t\t\t\tconst ownerGeneration = generation;\n\t\t\t\tconst controller = sessionController;\n\t\t\t\tconst { showCodexCompactMenu } = await import(\"./settings-menu.js\");\n\t\t\t\tif (ownerGeneration !== generation || controller.signal.aborted) return;\n\t\t\t\tawait showCodexCompactMenu(settingsRuntime, ctx, {\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tisCurrent: () => ownerGeneration === generation && !controller.signal.aborted,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\t\tsessionController.abort();\n\t\t\tsessionController = new AbortController();\n\t\t\tgeneration += 1;\n\t\t\tconst ownerGeneration = generation;\n\t\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\t\tproviderWarnings.clear();\n\t\t\tlet state: Readonly<CodexCompactSettingsState>;\n\t\t\ttry {\n\t\t\t\tstate = await settingsRuntime.reload(sessionController.signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (sessionController.signal.aborted || ownerGeneration !== generation) return;\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Could not load pi-codex-compact.json; using defaults. ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tsessionController.signal.aborted ||\n\t\t\t\townerGeneration !== generation ||\n\t\t\t\tctx.sessionManager.getSessionId() !== sessionId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx.hasUI && state.kind === \"invalid\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Invalid pi-codex-compact.json; using defaults without overwriting it. ${state.issue}`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"session_before_compact\", (event, ctx) =>\n\t\t\tcompactRemotely(pi, event, ctx, settingsRuntime.get().settings, options.fetch),\n\t\t);\n\n\t\tpi.on(\"context\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return undefined;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;\n\t\t\tconst messages = projectCheckpointContext(event.messages, checkpoint.details);\n\t\t\treturn messages ? { messages } : undefined;\n\t\t});\n\n\t\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return undefined;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;\n\t\t\tconst marker = checkpointMarker(checkpoint.details.checkpointId);\n\t\t\tif (!hasCheckpointMarker(event.payload, marker)) return undefined;\n\t\t\treturn rewriteCheckpointMarker(event.payload, marker, checkpoint.details.replacementHistory);\n\t\t});\n\n\t\tpi.on(\"model_select\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || isCheckpointCompatible(checkpoint.details, event.model)) return;\n\t\t\tconst key = `${ctx.sessionManager.getSessionId()}:${event.model.provider}:${event.model.id}`;\n\t\t\tif (providerWarnings.has(key)) return;\n\t\t\tproviderWarnings.add(key);\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"The active Codex checkpoint cannot replay on this model; Pi will expose only its fallback marker and retained recent messages.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tgeneration += 1;\n\t\t\tsessionController.abort();\n\t\t\tproviderWarnings.clear();\n\t\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\t\tawait settingsRuntime.flush();\n\t\t});\n\t};\n}\n\nexport default createCodexCompactExtension();\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { CompactionEntry, SessionEntry } from \"@earendil-works/pi-coding-agent\";\nimport { type JsonObject, validateCompactionItem } from \"./protocol.js\";\n\nexport const CHECKPOINT_KIND = \"pi-codex-remote-compaction\";\nexport const CHECKPOINT_VERSION = 1;\nexport const REPLACEMENT_TOKEN_BUDGET = 64_000;\nexport const REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;\nconst MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;\n\nexport interface CodexCheckpointDetails {\n\tkind: typeof CHECKPOINT_KIND;\n\tversion: typeof CHECKPOINT_VERSION;\n\tcheckpointId: string;\n\tprovider: \"openai-codex\";\n\tapi: \"openai-codex-responses\";\n\tmodelId: string;\n\tprotocol: \"remote-compaction-v2\";\n\treplacementHistory: JsonObject[];\n\tkeptMessageFingerprints: string[];\n\tcreatedAt: string;\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stableValue(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(stableValue);\n\tif (!isObject(value)) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.sort(([left], [right]) => left.localeCompare(right))\n\t\t\t.map(([key, child]) => [key, stableValue(child)]),\n\t);\n}\n\nfunction serializedBytes(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nexport function fingerprintMessage(message: AgentMessage): string {\n\treturn createHash(\"sha256\")\n\t\t.update(JSON.stringify(stableValue(message)))\n\t\t.digest(\"hex\");\n}\n\nexport function checkpointMarker(checkpointId: string): string {\n\treturn [\n\t\t`[PI_CODEX_REMOTE_CHECKPOINT:${checkpointId}]`,\n\t\t\"Opaque checkpoint injection failed. Do not infer missing history; tell the user to re-enable\",\n\t\t\"@narumitw/pi-codex-compact with an openai-codex model.\",\n\t].join(\" \");\n}\n\nexport function fallbackSummary(checkpointId: string): string {\n\treturn [\n\t\t`OpenAI Codex Remote Compaction V2 checkpoint ${checkpointId} stores the older history opaquely.`,\n\t\t\"Full replay requires @narumitw/pi-codex-compact and an openai-codex model.\",\n\t\t\"Without them, only Pi's retained recent messages remain available.\",\n\t].join(\" \");\n}\n\nfunction markerMessage(checkpointId: string, timestamp: number): AgentMessage {\n\treturn {\n\t\trole: \"user\",\n\t\tcontent: [{ type: \"text\", text: checkpointMarker(checkpointId) }],\n\t\ttimestamp,\n\t};\n}\n\nexport function parseCheckpointDetails(value: unknown): CodexCheckpointDetails | undefined {\n\tif (!isObject(value)) return undefined;\n\tif (\n\t\tvalue.kind !== CHECKPOINT_KIND ||\n\t\tvalue.version !== CHECKPOINT_VERSION ||\n\t\ttypeof value.checkpointId !== \"string\" ||\n\t\tvalue.checkpointId.length < 8 ||\n\t\tvalue.provider !== \"openai-codex\" ||\n\t\tvalue.api !== \"openai-codex-responses\" ||\n\t\ttypeof value.modelId !== \"string\" ||\n\t\tvalue.protocol !== \"remote-compaction-v2\" ||\n\t\t!Array.isArray(value.replacementHistory) ||\n\t\t!Array.isArray(value.keptMessageFingerprints) ||\n\t\ttypeof value.createdAt !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\tif (\n\t\tvalue.replacementHistory.length === 0 ||\n\t\t!value.replacementHistory.every(isObject) ||\n\t\t!value.keptMessageFingerprints.every(\n\t\t\t(fingerprint) => typeof fingerprint === \"string\" && /^[a-f0-9]{64}$/.test(fingerprint),\n\t\t) ||\n\t\tserializedBytes(value.replacementHistory) > REPLACEMENT_BYTE_BUDGET\n\t) {\n\t\treturn undefined;\n\t}\n\tconst last = value.replacementHistory.at(-1);\n\ttry {\n\t\tvalidateCompactionItem(last);\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn structuredClone(value) as unknown as CodexCheckpointDetails;\n}\n\nexport function latestCheckpoint(entries: readonly SessionEntry[]):\n\t| {\n\t\t\tentry: CompactionEntry<CodexCheckpointDetails>;\n\t\t\tdetails: CodexCheckpointDetails;\n\t }\n\t| undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry.type !== \"compaction\") continue;\n\t\tconst details = parseCheckpointDetails(entry.details);\n\t\treturn details\n\t\t\t? { entry: entry as CompactionEntry<CodexCheckpointDetails>, details }\n\t\t\t: undefined;\n\t}\n\treturn undefined;\n}\n\nfunction isOlderCompactionSummary(message: AgentMessage, timestamp: number): boolean {\n\treturn (\n\t\tmessage.role === \"compactionSummary\" &&\n\t\tNumber.isFinite(message.timestamp) &&\n\t\tNumber.isFinite(timestamp) &&\n\t\tmessage.timestamp < timestamp\n\t);\n}\n\nexport function projectCheckpointContext(\n\tmessages: readonly AgentMessage[],\n\tdetails: CodexCheckpointDetails,\n): AgentMessage[] | undefined {\n\tconst summary = fallbackSummary(details.checkpointId);\n\tconst summaryIndex = messages.findIndex(\n\t\t(message) => message.role === \"compactionSummary\" && message.summary === summary,\n\t);\n\tif (summaryIndex < 0) return undefined;\n\tconst timestamp = messages[summaryIndex].timestamp;\n\tlet messageIndex = summaryIndex + 1;\n\tlet fingerprintIndex = 0;\n\twhile (fingerprintIndex < details.keptMessageFingerprints.length) {\n\t\tif (messageIndex >= messages.length) return undefined;\n\t\tconst message = messages[messageIndex];\n\t\tif (fingerprintMessage(message) === details.keptMessageFingerprints[fingerprintIndex]) {\n\t\t\tmessageIndex += 1;\n\t\t\tfingerprintIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isOlderCompactionSummary(message, timestamp)) {\n\t\t\tmessageIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\treturn undefined;\n\t}\n\twhile (\n\t\tmessageIndex < messages.length &&\n\t\tisOlderCompactionSummary(messages[messageIndex], timestamp)\n\t) {\n\t\tmessageIndex += 1;\n\t}\n\treturn [\n\t\t...messages.slice(0, summaryIndex),\n\t\tmarkerMessage(details.checkpointId, timestamp),\n\t\t...messages.slice(messageIndex),\n\t];\n}\n\nfunction rawText(item: JsonObject): string {\n\tif (!Array.isArray(item.content)) return \"\";\n\treturn item.content\n\t\t.flatMap((part) =>\n\t\t\tisObject(part) && typeof part.text === \"string\" && part.type === \"input_text\"\n\t\t\t\t? [part.text]\n\t\t\t\t: [],\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nfunction hasMedia(item: JsonObject): boolean {\n\treturn (\n\t\tArray.isArray(item.content) &&\n\t\titem.content.some((part) => isObject(part) && part.type === \"input_image\")\n\t);\n}\n\nfunction truncateTextItem(item: JsonObject, maxChars: number): JsonObject | undefined {\n\tif (!Array.isArray(item.content) || maxChars <= 32) return undefined;\n\tlet remaining = maxChars - 16;\n\tconst content = [...item.content].reverse().flatMap((part) => {\n\t\tif (\n\t\t\t!isObject(part) ||\n\t\t\tpart.type !== \"input_text\" ||\n\t\t\ttypeof part.text !== \"string\" ||\n\t\t\tremaining <= 0\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\tconst text = part.text.slice(-remaining);\n\t\tremaining -= text.length;\n\t\treturn [{ ...part, text: `[truncated]\\n${text}` }];\n\t});\n\tif (content.length === 0) return undefined;\n\treturn { ...item, content: content.reverse() };\n}\n\nexport function buildReplacementHistory(\n\tinput: readonly unknown[],\n\tcompactionItem: JsonObject,\n\toptions: { tokenBudget?: number; byteBudget?: number } = {},\n): JsonObject[] {\n\tconst tokenBudget = options.tokenBudget ?? REPLACEMENT_TOKEN_BUDGET;\n\tconst byteBudget = options.byteBudget ?? REPLACEMENT_BYTE_BUDGET;\n\tconst opaque = validateCompactionItem(compactionItem);\n\tlet remainingBytes = byteBudget - serializedBytes(opaque);\n\tlet remainingChars = tokenBudget * 4;\n\tif (remainingBytes <= 0)\n\t\tthrow new Error(\"Opaque compaction item exceeds replacement history budget\");\n\tconst retainedNewestFirst: JsonObject[] = [];\n\tconst candidates = input.filter(\n\t\t(item): item is JsonObject =>\n\t\t\tisObject(item) && item.role === \"user\" && item.type !== \"compaction_trigger\",\n\t);\n\tfor (let index = candidates.length - 1; index >= 0; index--) {\n\t\tconst candidate = candidates[index];\n\t\tconst bytes = serializedBytes(candidate);\n\t\tif (hasMedia(candidate) && bytes > MAX_MEDIA_ITEM_BYTES) continue;\n\t\tconst text = rawText(candidate);\n\t\tlet retained = candidate;\n\t\tif (text.length > remainingChars) {\n\t\t\tif (hasMedia(candidate)) continue;\n\t\t\tconst truncated = truncateTextItem(candidate, remainingChars);\n\t\t\tif (!truncated) continue;\n\t\t\tretained = truncated;\n\t\t}\n\t\tif (serializedBytes(retained) > remainingBytes) {\n\t\t\tif (hasMedia(retained)) continue;\n\t\t\tconst maxCharsByBytes = Math.max(0, remainingBytes - 128);\n\t\t\tconst truncated = truncateTextItem(retained, Math.min(remainingChars, maxCharsByBytes));\n\t\t\tif (!truncated || serializedBytes(truncated) > remainingBytes) continue;\n\t\t\tretained = truncated;\n\t\t}\n\t\tretainedNewestFirst.push(structuredClone(retained));\n\t\tremainingBytes -= serializedBytes(retained);\n\t\tremainingChars -= Math.min(remainingChars, rawText(retained).length);\n\t\tif (remainingBytes <= 128 || remainingChars <= 32) break;\n\t}\n\treturn [...retainedNewestFirst.reverse(), opaque];\n}\n\nexport function createCheckpointDetails(input: {\n\tmodelId: string;\n\treplacementHistory: JsonObject[];\n\tkeptMessages: readonly AgentMessage[];\n\tcheckpointId?: string;\n\tcreatedAt?: string;\n}): CodexCheckpointDetails {\n\tconst details: CodexCheckpointDetails = {\n\t\tkind: CHECKPOINT_KIND,\n\t\tversion: CHECKPOINT_VERSION,\n\t\tcheckpointId: input.checkpointId ?? randomUUID(),\n\t\tprovider: \"openai-codex\",\n\t\tapi: \"openai-codex-responses\",\n\t\tmodelId: input.modelId,\n\t\tprotocol: \"remote-compaction-v2\",\n\t\treplacementHistory: structuredClone(input.replacementHistory),\n\t\tkeptMessageFingerprints: input.keptMessages.map(fingerprintMessage),\n\t\tcreatedAt: input.createdAt ?? new Date().toISOString(),\n\t};\n\tconst parsed = parseCheckpointDetails(details);\n\tif (!parsed) throw new Error(\"Created an invalid Codex checkpoint\");\n\treturn parsed;\n}\n", "export const MAX_SSE_BYTES = 8 * 1024 * 1024;\nexport const MAX_COMPACTION_ITEM_BYTES = 2 * 1024 * 1024;\n\nexport type JsonObject = Record<string, unknown>;\n\nexport class CodexCompactionProtocolError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CodexCompactionProtocolError\";\n\t}\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction byteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nexport function isCompactionItem(value: unknown): value is JsonObject {\n\treturn (\n\t\tisObject(value) &&\n\t\tvalue.type === \"compaction\" &&\n\t\ttypeof value.encrypted_content === \"string\" &&\n\t\tvalue.encrypted_content.length > 0\n\t);\n}\n\nexport function validateCompactionItem(\n\tvalue: unknown,\n\tmaxBytes = MAX_COMPACTION_ITEM_BYTES,\n): JsonObject {\n\tif (!isCompactionItem(value)) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Remote response did not contain a valid compaction item\",\n\t\t);\n\t}\n\tif (byteLength(value) > maxBytes) {\n\t\tthrow new CodexCompactionProtocolError(\"Remote compaction item exceeded the size limit\");\n\t}\n\treturn structuredClone(value);\n}\n\nexport interface CollectedCompaction {\n\titem: JsonObject;\n\tcompletedResponse?: JsonObject;\n}\n\nfunction compactionItemsFromEvent(event: JsonObject): unknown[] {\n\tconst items: unknown[] = [];\n\tif (event.type === \"response.output_item.done\" && isObject(event.item)) {\n\t\titems.push(event.item);\n\t}\n\tif (event.type === \"response.completed\" && isObject(event.response)) {\n\t\tconst output = event.response.output;\n\t\tif (Array.isArray(output)) items.push(...output);\n\t}\n\treturn items.filter((item) => isObject(item) && item.type === \"compaction\");\n}\n\nexport async function collectCompactionSse(\n\tstream: ReadableStream<Uint8Array>,\n\toptions: {\n\t\tsignal?: AbortSignal;\n\t\tmaxBytes?: number;\n\t\tmaxItemBytes?: number;\n\t} = {},\n): Promise<CollectedCompaction> {\n\tconst maxBytes = options.maxBytes ?? MAX_SSE_BYTES;\n\tconst reader = stream.getReader();\n\tconst onAbort = () => {\n\t\tvoid reader.cancel(new DOMException(\"Compaction aborted\", \"AbortError\")).catch(() => undefined);\n\t};\n\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\tconst decoder = new TextDecoder();\n\tlet bytes = 0;\n\tlet pending = \"\";\n\tlet dataLines: string[] = [];\n\tlet completedResponse: JsonObject | undefined;\n\tconst items = new Map<string, JsonObject>();\n\n\tconst checkAbort = () => {\n\t\tif (options.signal?.aborted) throw new DOMException(\"Compaction aborted\", \"AbortError\");\n\t};\n\tconst dispatch = () => {\n\t\tif (dataLines.length === 0) return;\n\t\tconst data = dataLines.join(\"\\n\");\n\t\tdataLines = [];\n\t\tif (data === \"[DONE]\") return;\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(data);\n\t\t} catch {\n\t\t\tthrow new CodexCompactionProtocolError(\"Remote compaction returned malformed SSE JSON\");\n\t\t}\n\t\tif (!isObject(parsed)) return;\n\t\tif (parsed.type === \"response.completed\") {\n\t\t\tcompletedResponse = isObject(parsed.response) ? parsed.response : {};\n\t\t}\n\t\tfor (const candidate of compactionItemsFromEvent(parsed)) {\n\t\t\tconst item = validateCompactionItem(candidate, options.maxItemBytes);\n\t\t\titems.set(JSON.stringify(item), item);\n\t\t}\n\t};\n\tconst processLine = (line: string) => {\n\t\tif (line === \"\") {\n\t\t\tdispatch();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return;\n\t\tif (line === \"data\") dataLines.push(\"\");\n\t\telse if (line.startsWith(\"data:\")) dataLines.push(line.slice(5).replace(/^ /, \"\"));\n\t};\n\n\ttry {\n\t\twhile (true) {\n\t\t\tcheckAbort();\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbytes += value.byteLength;\n\t\t\tif (bytes > maxBytes) {\n\t\t\t\tthrow new CodexCompactionProtocolError(\"Remote compaction stream exceeded the size limit\");\n\t\t\t}\n\t\t\tpending += decoder.decode(value, { stream: true });\n\t\t\tlet newline = pending.indexOf(\"\\n\");\n\t\t\twhile (newline !== -1) {\n\t\t\t\tconst rawLine = pending.slice(0, newline);\n\t\t\t\tpending = pending.slice(newline + 1);\n\t\t\t\tprocessLine(rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine);\n\t\t\t\tnewline = pending.indexOf(\"\\n\");\n\t\t\t}\n\t\t}\n\t\tpending += decoder.decode();\n\t\tif (pending.length > 0) processLine(pending.endsWith(\"\\r\") ? pending.slice(0, -1) : pending);\n\t\tdispatch();\n\t\tcheckAbort();\n\t} catch (error) {\n\t\tawait reader.cancel(error).catch(() => undefined);\n\t\tthrow error;\n\t} finally {\n\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\treader.releaseLock();\n\t}\n\n\tif (!completedResponse) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Remote compaction stream ended without response.completed\",\n\t\t);\n\t}\n\tif (items.size !== 1) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t`Remote compaction returned ${items.size} distinct compaction items; expected exactly one`,\n\t\t);\n\t}\n\treturn { item: [...items.values()][0], completedResponse };\n}\n\nfunction markerTextFromItem(item: unknown): string | undefined {\n\tif (!isObject(item) || item.role !== \"user\" || !Array.isArray(item.content)) return undefined;\n\tif (item.content.length !== 1) return undefined;\n\tconst content = item.content[0];\n\tif (!isObject(content) || content.type !== \"input_text\" || typeof content.text !== \"string\") {\n\t\treturn undefined;\n\t}\n\treturn content.text;\n}\n\nexport function rewriteCheckpointMarker(\n\tpayload: unknown,\n\tmarker: string,\n\treplacementHistory: readonly unknown[],\n): JsonObject {\n\tif (!isObject(payload) || !Array.isArray(payload.input)) {\n\t\tthrow new CodexCompactionProtocolError(\"OpenAI Codex payload is missing an input array\");\n\t}\n\tconst matches = payload.input\n\t\t.map((item, index) => (markerTextFromItem(item) === marker ? index : -1))\n\t\t.filter((index) => index >= 0);\n\tif (matches.length !== 1) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t`Provider payload contained ${matches.length} checkpoint markers; expected exactly one`,\n\t\t);\n\t}\n\tconst index = matches[0];\n\treturn {\n\t\t...payload,\n\t\tinput: [\n\t\t\t...payload.input.slice(0, index),\n\t\t\t...structuredClone(replacementHistory),\n\t\t\t...payload.input.slice(index + 1),\n\t\t],\n\t};\n}\n\nexport function appendCompactionTrigger(payload: unknown): JsonObject {\n\tif (!isObject(payload) || !Array.isArray(payload.input)) {\n\t\tthrow new CodexCompactionProtocolError(\"OpenAI Codex payload is missing an input array\");\n\t}\n\tif (payload.input.some((item) => isObject(item) && item.type === \"compaction_trigger\")) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Provider payload already contains a compaction trigger\",\n\t\t);\n\t}\n\treturn { ...payload, input: [...payload.input, { type: \"compaction_trigger\" }] };\n}\n\nexport function prepareRemoteCompactionPayload(\n\tpayload: unknown,\n\tcheckpoint?: { marker: string; replacementHistory: readonly unknown[] },\n): JsonObject {\n\tconst expanded = checkpoint\n\t\t? rewriteCheckpointMarker(payload, checkpoint.marker, checkpoint.replacementHistory)\n\t\t: payload;\n\treturn appendCompactionTrigger(expanded);\n}\n\nexport function hasCheckpointMarker(payload: unknown, marker: string): boolean {\n\treturn (\n\t\tisObject(payload) &&\n\t\tArray.isArray(payload.input) &&\n\t\tpayload.input.some((item) => markerTextFromItem(item) === marker)\n\t);\n}\n", "import type { Context, Model, Provider, ProviderHeaders, Usage } from \"@earendil-works/pi-ai\";\nimport {\n\tCodexCompactionProtocolError,\n\ttype CollectedCompaction,\n\tcollectCompactionSse,\n\ttype JsonObject,\n\tprepareRemoteCompactionPayload,\n} from \"./protocol.js\";\n\ninterface PriorCheckpointPayload {\n\tmarker: string;\n\treplacementHistory: readonly unknown[];\n}\n\nexport interface RemoteCompactionRequest {\n\tprovider: Provider;\n\tmodel: Model<\"openai-codex-responses\">;\n\tcontext: Context;\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tenv?: Record<string, string>;\n\tsignal: AbortSignal;\n\tpriorCheckpoint?: PriorCheckpointPayload;\n\trequestTimeoutMs?: number;\n\tmaxRetries?: number;\n\tfetch?: typeof globalThis.fetch;\n}\n\nexport interface RemoteCompactionResponse {\n\titem: JsonObject;\n\tpromptInput: JsonObject[];\n\tusage: Usage;\n}\n\nconst EMPTY_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction abortError(): DOMException {\n\treturn new DOMException(\"Compaction aborted\", \"AbortError\");\n}\n\nexport async function requestRemoteCompaction(\n\trequest: RemoteCompactionRequest,\n): Promise<RemoteCompactionResponse> {\n\tif (request.signal.aborted) throw abortError();\n\tlet sentInput: JsonObject[] | undefined;\n\tconst inspections: Promise<\n\t\t{ ok: true; value: CollectedCompaction } | { ok: false; error: unknown }\n\t>[] = [];\n\tconst baseFetch = request.fetch ?? globalThis.fetch;\n\tconst inspectedFetch: typeof globalThis.fetch = async (input, init) => {\n\t\tconst response = await baseFetch(input, init);\n\t\tif (!response.ok || !response.body) return response;\n\t\tconst [providerBody, inspectionBody] = response.body.tee();\n\t\tconst inspection = collectCompactionSse(inspectionBody, { signal: request.signal }).then(\n\t\t\t(value) => ({ ok: true as const, value }),\n\t\t\t(error: unknown) => ({ ok: false as const, error }),\n\t\t);\n\t\tinspections.push(inspection);\n\t\treturn new Response(providerBody, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: response.headers,\n\t\t});\n\t};\n\n\tconst stream = request.provider.stream(request.model, request.context, {\n\t\tapiKey: request.apiKey,\n\t\theaders: request.headers,\n\t\tenv: request.env,\n\t\tsignal: request.signal,\n\t\ttransport: \"sse\",\n\t\tcacheRetention: \"none\",\n\t\ttimeoutMs: request.requestTimeoutMs ?? 5 * 60 * 1000,\n\t\tmaxRetries: request.maxRetries ?? 2,\n\t\tfetch: inspectedFetch,\n\t\tonPayload: (payload) => {\n\t\t\tconst prepared = prepareRemoteCompactionPayload(payload, request.priorCheckpoint);\n\t\t\tif (!Array.isArray(prepared.input) || !prepared.input.every(isObject)) {\n\t\t\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\t\t\"Prepared compaction payload has invalid input items\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tsentInput = structuredClone(prepared.input.slice(0, -1)) as JsonObject[];\n\t\t\treturn prepared;\n\t\t},\n\t});\n\n\tlet usage = EMPTY_USAGE;\n\tfor await (const event of stream) {\n\t\tif (request.signal.aborted) throw abortError();\n\t\tif (event.type === \"error\") {\n\t\t\tthrow new Error(event.error.errorMessage ?? \"OpenAI Codex compaction request failed\");\n\t\t}\n\t\tif (event.type === \"done\") usage = event.message.usage;\n\t}\n\tif (request.signal.aborted) throw abortError();\n\tif (!sentInput)\n\t\tthrow new CodexCompactionProtocolError(\"Provider did not expose a request payload\");\n\tif (inspections.length === 0) {\n\t\tthrow new CodexCompactionProtocolError(\"Provider response did not expose an SSE body\");\n\t}\n\tconst inspection = await inspections.at(-1);\n\tif (request.signal.aborted) throw abortError();\n\tif (!inspection?.ok) throw inspection?.error ?? new Error(\"Remote compaction inspection failed\");\n\treturn { item: inspection.value.item, promptInput: sentInput, usage };\n}\n", "import { randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { mkdir, open, rename, rm, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join } from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\n\nexport const CODEX_COMPACT_SETTINGS_FILE = \"pi-codex-compact.json\";\nexport const MAX_SETTINGS_BYTES = 64 * 1024;\n\nexport interface CodexCompactSettings {\n\tenabled: boolean;\n\trequestTimeoutMs: number;\n\tmaxRetries: number;\n\treplacementTokenBudget: number;\n\tnotifyOnFallback: boolean;\n}\n\nexport const DEFAULT_CODEX_COMPACT_SETTINGS: Readonly<CodexCompactSettings> = Object.freeze({\n\tenabled: true,\n\trequestTimeoutMs: 300_000,\n\tmaxRetries: 2,\n\treplacementTokenBudget: 64_000,\n\tnotifyOnFallback: true,\n});\n\nconst LIMITS = Object.freeze({\n\trequestTimeoutMs: { minimum: 30_000, maximum: 600_000 },\n\tmaxRetries: { minimum: 0, maximum: 2 },\n\treplacementTokenBudget: { minimum: 8_000, maximum: 128_000 },\n});\n\nexport interface CodexCompactSettingsState {\n\tkind: \"missing\" | \"loaded\" | \"invalid\";\n\tpath: string;\n\tsettings: CodexCompactSettings;\n\tdocument?: Record<string, unknown>;\n\tissue?: string;\n}\n\nexport interface CodexCompactSettingsRuntime {\n\tget(): Readonly<CodexCompactSettingsState>;\n\treload(signal?: AbortSignal): Promise<Readonly<CodexCompactSettingsState>>;\n\tupdate(\n\t\tpatch: Partial<CodexCompactSettings>,\n\t\tsignal?: AbortSignal,\n\t): Promise<Readonly<CodexCompactSettingsState>>;\n\tflush(): Promise<void>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validInteger(value: unknown, minimum: number, maximum: number): value is number {\n\treturn (\n\t\ttypeof value === \"number\" && Number.isSafeInteger(value) && value >= minimum && value <= maximum\n\t);\n}\n\nexport function normalizeCodexCompactSettings(value: unknown): CodexCompactSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (Object.hasOwn(value, \"enabled\") && typeof value.enabled !== \"boolean\") return undefined;\n\tif (Object.hasOwn(value, \"notifyOnFallback\") && typeof value.notifyOnFallback !== \"boolean\") {\n\t\treturn undefined;\n\t}\n\tfor (const [field, limits] of Object.entries(LIMITS) as Array<\n\t\t[keyof typeof LIMITS, { minimum: number; maximum: number }]\n\t>) {\n\t\tif (\n\t\t\tObject.hasOwn(value, field) &&\n\t\t\t!validInteger(value[field], limits.minimum, limits.maximum)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn {\n\t\tenabled:\n\t\t\ttypeof value.enabled === \"boolean\" ? value.enabled : DEFAULT_CODEX_COMPACT_SETTINGS.enabled,\n\t\trequestTimeoutMs:\n\t\t\ttypeof value.requestTimeoutMs === \"number\"\n\t\t\t\t? value.requestTimeoutMs\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.requestTimeoutMs,\n\t\tmaxRetries:\n\t\t\ttypeof value.maxRetries === \"number\"\n\t\t\t\t? value.maxRetries\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.maxRetries,\n\t\treplacementTokenBudget:\n\t\t\ttypeof value.replacementTokenBudget === \"number\"\n\t\t\t\t? value.replacementTokenBudget\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.replacementTokenBudget,\n\t\tnotifyOnFallback:\n\t\t\ttypeof value.notifyOnFallback === \"boolean\"\n\t\t\t\t? value.notifyOnFallback\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.notifyOnFallback,\n\t};\n}\n\nexport function codexCompactSettingsPath(): string {\n\treturn join(getAgentDir(), CODEX_COMPACT_SETTINGS_FILE);\n}\n\nfunction aborted(signal?: AbortSignal): void {\n\tif (signal?.aborted) throw new DOMException(\"Settings operation aborted\", \"AbortError\");\n}\n\nexport async function loadCodexCompactSettings(\n\tpath = codexCompactSettingsPath(),\n\tsignal?: AbortSignal,\n): Promise<CodexCompactSettingsState> {\n\taborted(signal);\n\ttry {\n\t\tconst handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);\n\t\tlet text: string;\n\t\ttry {\n\t\t\tconst stats = await handle.stat();\n\t\t\taborted(signal);\n\t\t\tif (!stats.isFile()) throw new Error(\"settings path is not a regular file\");\n\t\t\tif (stats.size > MAX_SETTINGS_BYTES) throw new Error(\"settings file exceeds 64 KiB\");\n\t\t\ttext = await handle.readFile(\"utf8\");\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\taborted(signal);\n\t\tconst document = JSON.parse(text) as unknown;\n\t\tconst settings = normalizeCodexCompactSettings(document);\n\t\tif (!settings || !isRecord(document)) throw new Error(\"invalid settings shape or bounds\");\n\t\treturn { kind: \"loaded\", path, settings, document };\n\t} catch (error) {\n\t\tif (signal?.aborted) throw error;\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\treturn {\n\t\t\t\tkind: \"missing\",\n\t\t\t\tpath,\n\t\t\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\t\t\tdocument: {},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tkind: \"invalid\",\n\t\t\tpath,\n\t\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\t\tissue:\n\t\t\t\tisNodeError(error) && error.code === \"ELOOP\"\n\t\t\t\t\t? \"symbolic links are not accepted\"\n\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: String(error),\n\t\t};\n\t}\n}\n\nasync function savePatch(\n\tpath: string,\n\tpatch: Partial<CodexCompactSettings>,\n\tsignal?: AbortSignal,\n): Promise<CodexCompactSettingsState> {\n\tconst latest = await loadCodexCompactSettings(path, signal);\n\tif (latest.kind === \"invalid\") {\n\t\tthrow new Error(\n\t\t\t\"Cannot overwrite an invalid pi-codex-compact.json; repair it and reload first\",\n\t\t);\n\t}\n\tconst document = { ...latest.document, ...patch };\n\tconst settings = normalizeCodexCompactSettings(document);\n\tif (!settings) throw new Error(\"Refusing to save invalid Codex compaction settings\");\n\tconst temporaryPath = join(dirname(path), `.${basename(path)}.${randomUUID()}.tmp`);\n\tawait mkdir(dirname(path), { recursive: true });\n\taborted(signal);\n\ttry {\n\t\tawait writeFile(temporaryPath, `${JSON.stringify(document, null, 2)}\\n`, {\n\t\t\tencoding: \"utf8\",\n\t\t\tflag: \"wx\",\n\t\t\tmode: 0o600,\n\t\t});\n\t\taborted(signal);\n\t\tconst current = await loadCodexCompactSettings(path, signal);\n\t\tif (\n\t\t\tcurrent.kind === \"invalid\" ||\n\t\t\tcurrent.kind !== latest.kind ||\n\t\t\tJSON.stringify(current.document) !== JSON.stringify(latest.document)\n\t\t) {\n\t\t\tthrow new Error(\"pi-codex-compact.json changed while saving; reopen settings and retry\");\n\t\t}\n\t\tawait rename(temporaryPath, path);\n\t} finally {\n\t\tawait rm(temporaryPath, { force: true }).catch(() => undefined);\n\t}\n\treturn { kind: \"loaded\", path, settings, document };\n}\n\nexport function createCodexCompactSettingsRuntime(\n\tpath = codexCompactSettingsPath(),\n): CodexCompactSettingsRuntime {\n\tlet state: CodexCompactSettingsState = {\n\t\tkind: \"missing\",\n\t\tpath,\n\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\tdocument: {},\n\t};\n\tlet queue = Promise.resolve();\n\tconst enqueue = <T>(operation: () => Promise<T>): Promise<T> => {\n\t\tconst result = queue.then(operation, operation);\n\t\tqueue = result.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn result;\n\t};\n\treturn {\n\t\tget: () => structuredClone(state),\n\t\treload: (signal) =>\n\t\t\tenqueue(async () => {\n\t\t\t\tstate = await loadCodexCompactSettings(path, signal);\n\t\t\t\treturn structuredClone(state);\n\t\t\t}),\n\t\tupdate: (patch, signal) =>\n\t\t\tenqueue(async () => {\n\t\t\t\tstate = await savePatch(path, patch, signal);\n\t\t\t\treturn structuredClone(state);\n\t\t\t}),\n\t\tflush: () => queue,\n\t};\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Context, Model, Tool } from \"@earendil-works/pi-ai\";\nimport {\n\tbuildContextEntries,\n\tbuildSessionContext,\n\tconvertToLlm,\n\ttype ExtensionAPI,\n\ttype ExtensionContext,\n\ttype SessionBeforeCompactEvent,\n\tsessionEntryToContextMessages,\n} from \"@earendil-works/pi-coding-agent\";\nimport {\n\tbuildReplacementHistory,\n\ttype CodexCheckpointDetails,\n\tcheckpointMarker,\n\tcreateCheckpointDetails,\n\tfallbackSummary,\n\tlatestCheckpoint,\n\tprojectCheckpointContext,\n} from \"./checkpoint.js\";\nimport { isCodexRemoteCompactionModel } from \"./model-compatibility.js\";\nimport { hasCheckpointMarker, rewriteCheckpointMarker } from \"./protocol.js\";\nimport { requestRemoteCompaction } from \"./remote.js\";\nimport {\n\ttype CodexCompactSettings,\n\ttype CodexCompactSettingsRuntime,\n\ttype CodexCompactSettingsState,\n\tcreateCodexCompactSettingsRuntime,\n} from \"./settings.js\";\n\nconst STATUS_KEY = \"codex-compact\";\n\nfunction activeCheckpoint(ctx: ExtensionContext) {\n\treturn latestCheckpoint(ctx.sessionManager.getBranch());\n}\n\nfunction isCheckpointCompatible(\n\tdetails: CodexCheckpointDetails,\n\tmodel: Model<Api> | undefined,\n): model is Model<\"openai-codex-responses\"> {\n\treturn isCodexRemoteCompactionModel(model) && model.id === details.modelId;\n}\n\nfunction keptMessages(event: SessionBeforeCompactEvent): AgentMessage[] {\n\tconst leafId = event.branchEntries.at(-1)?.id ?? null;\n\tconst contextEntries = buildContextEntries(event.branchEntries, leafId);\n\tconst keptIndex = contextEntries.findIndex(\n\t\t(entry) => entry.id === event.preparation.firstKeptEntryId,\n\t);\n\tif (keptIndex < 0) {\n\t\tthrow new Error(\"Pi compaction cut point is not present in the active context\");\n\t}\n\treturn contextEntries.slice(keptIndex).flatMap(sessionEntryToContextMessages);\n}\n\nfunction activeTools(pi: ExtensionAPI): Tool[] {\n\tconst enabled = new Set(pi.getActiveTools());\n\treturn pi\n\t\t.getAllTools()\n\t\t.filter((tool) => enabled.has(tool.name))\n\t\t.map((tool) => ({\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tparameters: tool.parameters,\n\t\t}));\n}\n\nfunction projectedCurrentMessages(\n\tevent: SessionBeforeCompactEvent,\n\tmodel: Model<\"openai-codex-responses\">,\n): { messages: AgentMessage[]; prior?: CodexCheckpointDetails } {\n\tconst leafId = event.branchEntries.at(-1)?.id ?? null;\n\tconst session = buildSessionContext(event.branchEntries, leafId);\n\tconst prior = latestCheckpoint(event.branchEntries);\n\tif (!prior) return { messages: session.messages };\n\tif (prior.details.modelId !== model.id) {\n\t\tthrow new Error(\"The active opaque checkpoint belongs to a different Codex model\");\n\t}\n\tconst projected = projectCheckpointContext(session.messages, prior.details, prior.entry.summary);\n\tif (!projected) {\n\t\tthrow new Error(\"The previous opaque checkpoint could not be projected safely\");\n\t}\n\treturn { messages: projected, prior: prior.details };\n}\n\nfunction notifyFailure(\n\tctx: ExtensionContext,\n\terror: unknown,\n\tsettings: CodexCompactSettings,\n): void {\n\tif (!ctx.hasUI || !settings.notifyOnFallback) return;\n\tconst message = error instanceof Error ? error.message : String(error);\n\tctx.ui.notify(`Codex remote compaction failed; using Pi compaction. ${message}`, \"warning\");\n}\n\nfunction sessionStillOwned(ctx: ExtensionContext, sessionId: string, signal: AbortSignal): boolean {\n\treturn !signal.aborted && ctx.sessionManager.getSessionId() === sessionId;\n}\n\nasync function compactRemotely(\n\tpi: ExtensionAPI,\n\tevent: SessionBeforeCompactEvent,\n\tctx: ExtensionContext,\n\tsettings: CodexCompactSettings,\n\tfetch?: typeof globalThis.fetch,\n) {\n\tconst model = ctx.model;\n\tif (!settings.enabled || !isCodexRemoteCompactionModel(model)) return undefined;\n\tconst sessionId = ctx.sessionManager.getSessionId();\n\tctx.ui.setStatus(STATUS_KEY, \"Codex remote compaction\u2026\");\n\ttry {\n\t\tconst auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);\n\t\tif (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };\n\t\tif (!auth.ok) throw new Error(auth.error);\n\t\tconst provider = ctx.modelRegistry.getProvider(model.provider);\n\t\tif (!provider) throw new Error(\"The active Codex Responses provider is unavailable\");\n\t\tconst current = projectedCurrentMessages(event, model);\n\t\tconst context: Context = {\n\t\t\tsystemPrompt: ctx.getSystemPrompt(),\n\t\t\tmessages: convertToLlm(current.messages),\n\t\t\ttools: activeTools(pi),\n\t\t};\n\t\tconst response = await requestRemoteCompaction({\n\t\t\tprovider,\n\t\t\tmodel,\n\t\t\tcontext,\n\t\t\tapiKey: auth.apiKey,\n\t\t\theaders: auth.headers,\n\t\t\tenv: auth.env,\n\t\t\tsignal: event.signal,\n\t\t\tpriorCheckpoint: current.prior\n\t\t\t\t? {\n\t\t\t\t\t\tmarker: checkpointMarker(current.prior.checkpointId),\n\t\t\t\t\t\treplacementHistory: current.prior.replacementHistory,\n\t\t\t\t\t}\n\t\t\t\t: undefined,\n\t\t\trequestTimeoutMs: settings.requestTimeoutMs,\n\t\t\tmaxRetries: settings.maxRetries,\n\t\t\tfetch,\n\t\t});\n\t\tif (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };\n\t\tconst replacementHistory = buildReplacementHistory(response.promptInput, response.item, {\n\t\t\ttokenBudget: settings.replacementTokenBudget,\n\t\t});\n\t\tconst details = createCheckpointDetails({\n\t\t\tprovider: model.provider,\n\t\t\tmodelId: model.id,\n\t\t\treplacementHistory,\n\t\t\tkeptMessages: keptMessages(event),\n\t\t});\n\t\treturn {\n\t\t\tcompaction: {\n\t\t\t\tsummary: fallbackSummary(details.checkpointId),\n\t\t\t\tfirstKeptEntryId: event.preparation.firstKeptEntryId,\n\t\t\t\ttokensBefore: event.preparation.tokensBefore,\n\t\t\t\tusage: response.usage,\n\t\t\t\tdetails,\n\t\t\t},\n\t\t};\n\t} catch (error) {\n\t\tif (event.signal.aborted || ctx.sessionManager.getSessionId() !== sessionId) {\n\t\t\treturn { cancel: true };\n\t\t}\n\t\tnotifyFailure(ctx, error, settings);\n\t\treturn undefined;\n\t} finally {\n\t\tif (ctx.sessionManager.getSessionId() === sessionId) ctx.ui.setStatus(STATUS_KEY, undefined);\n\t}\n}\n\nexport function createCodexCompactExtension(\n\toptions: { fetch?: typeof globalThis.fetch; settingsRuntime?: CodexCompactSettingsRuntime } = {},\n): (pi: ExtensionAPI) => void {\n\treturn (pi) => {\n\t\tconst providerWarnings = new Set<string>();\n\t\tconst settingsRuntime = options.settingsRuntime ?? createCodexCompactSettingsRuntime();\n\t\tlet sessionController = new AbortController();\n\t\tlet generation = 0;\n\n\t\tpi.registerCommand(\"codex-compact\", {\n\t\t\tdescription: \"Compact now or configure Codex Remote Compaction V2\",\n\t\t\thandler: async (_args, ctx) => {\n\t\t\t\tconst ownerGeneration = generation;\n\t\t\t\tconst controller = sessionController;\n\t\t\t\tconst { showCodexCompactMenu } = await import(\"./settings-menu.js\");\n\t\t\t\tif (ownerGeneration !== generation || controller.signal.aborted) return;\n\t\t\t\tawait showCodexCompactMenu(settingsRuntime, ctx, {\n\t\t\t\t\tsignal: controller.signal,\n\t\t\t\t\tisCurrent: () => ownerGeneration === generation && !controller.signal.aborted,\n\t\t\t\t});\n\t\t\t},\n\t\t});\n\n\t\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\t\tsessionController.abort();\n\t\t\tsessionController = new AbortController();\n\t\t\tgeneration += 1;\n\t\t\tconst ownerGeneration = generation;\n\t\t\tconst sessionId = ctx.sessionManager.getSessionId();\n\t\t\tproviderWarnings.clear();\n\t\t\tlet state: Readonly<CodexCompactSettingsState>;\n\t\t\ttry {\n\t\t\t\tstate = await settingsRuntime.reload(sessionController.signal);\n\t\t\t} catch (error) {\n\t\t\t\tif (sessionController.signal.aborted || ownerGeneration !== generation) return;\n\t\t\t\tif (ctx.hasUI) {\n\t\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\t`Could not load pi-codex-compact.json; using defaults. ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\t\"warning\",\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tsessionController.signal.aborted ||\n\t\t\t\townerGeneration !== generation ||\n\t\t\t\tctx.sessionManager.getSessionId() !== sessionId\n\t\t\t) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (ctx.hasUI && state.kind === \"invalid\") {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t`Invalid pi-codex-compact.json; using defaults without overwriting it. ${state.issue}`,\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"session_before_compact\", (event, ctx) =>\n\t\t\tcompactRemotely(pi, event, ctx, settingsRuntime.get().settings, options.fetch),\n\t\t);\n\n\t\tpi.on(\"context\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return undefined;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;\n\t\t\tconst messages = projectCheckpointContext(\n\t\t\t\tevent.messages,\n\t\t\t\tcheckpoint.details,\n\t\t\t\tcheckpoint.entry.summary,\n\t\t\t);\n\t\t\treturn messages ? { messages } : undefined;\n\t\t});\n\n\t\tpi.on(\"before_provider_request\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return undefined;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;\n\t\t\tconst marker = checkpointMarker(checkpoint.details.checkpointId);\n\t\t\tif (!hasCheckpointMarker(event.payload, marker)) return undefined;\n\t\t\treturn rewriteCheckpointMarker(event.payload, marker, checkpoint.details.replacementHistory);\n\t\t});\n\n\t\tpi.on(\"model_select\", (event, ctx) => {\n\t\t\tif (!settingsRuntime.get().settings.enabled) return;\n\t\t\tconst checkpoint = activeCheckpoint(ctx);\n\t\t\tif (!checkpoint || isCheckpointCompatible(checkpoint.details, event.model)) return;\n\t\t\tconst key = `${ctx.sessionManager.getSessionId()}:${event.model.provider}:${event.model.id}`;\n\t\t\tif (providerWarnings.has(key)) return;\n\t\t\tproviderWarnings.add(key);\n\t\t\tif (ctx.hasUI) {\n\t\t\t\tctx.ui.notify(\n\t\t\t\t\t\"The active Codex checkpoint cannot replay on this model; Pi will expose only its fallback marker and retained recent messages.\",\n\t\t\t\t\t\"warning\",\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tpi.on(\"session_shutdown\", async (_event, ctx) => {\n\t\t\tgeneration += 1;\n\t\t\tsessionController.abort();\n\t\t\tproviderWarnings.clear();\n\t\t\tctx.ui.setStatus(STATUS_KEY, undefined);\n\t\t\tawait settingsRuntime.flush();\n\t\t});\n\t};\n}\n\nexport default createCodexCompactExtension();\n", "import { createHash, randomUUID } from \"node:crypto\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { CompactionEntry, SessionEntry } from \"@earendil-works/pi-coding-agent\";\nimport { type JsonObject, validateCompactionItem } from \"./protocol.js\";\n\nexport const CHECKPOINT_KIND = \"pi-codex-remote-compaction\";\nexport const CHECKPOINT_VERSION = 1;\nexport const REPLACEMENT_TOKEN_BUDGET = 64_000;\nexport const REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;\nconst MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;\nconst MAX_PROVIDER_ID_LENGTH = 256;\n\nexport interface CodexCheckpointDetails {\n\tkind: typeof CHECKPOINT_KIND;\n\tversion: typeof CHECKPOINT_VERSION;\n\tcheckpointId: string;\n\tprovider: string;\n\tapi: \"openai-codex-responses\";\n\tmodelId: string;\n\tprotocol: \"remote-compaction-v2\";\n\treplacementHistory: JsonObject[];\n\tkeptMessageFingerprints: string[];\n\tcreatedAt: string;\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stableValue(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(stableValue);\n\tif (!isObject(value)) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value)\n\t\t\t.sort(([left], [right]) => left.localeCompare(right))\n\t\t\t.map(([key, child]) => [key, stableValue(child)]),\n\t);\n}\n\nfunction serializedBytes(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nexport function fingerprintMessage(message: AgentMessage): string {\n\treturn createHash(\"sha256\")\n\t\t.update(JSON.stringify(stableValue(message)))\n\t\t.digest(\"hex\");\n}\n\nexport function checkpointMarker(checkpointId: string): string {\n\treturn [\n\t\t`[PI_CODEX_REMOTE_CHECKPOINT:${checkpointId}]`,\n\t\t\"Opaque checkpoint injection failed. Do not infer missing history; tell the user to re-enable\",\n\t\t\"@narumitw/pi-codex-compact with a model using the openai-codex-responses API.\",\n\t].join(\" \");\n}\n\nexport function fallbackSummary(checkpointId: string): string {\n\treturn [\n\t\t`OpenAI Codex Remote Compaction V2 checkpoint ${checkpointId} stores the older history opaquely.`,\n\t\t\"Full replay requires @narumitw/pi-codex-compact and the same model through a compatible Codex Responses provider.\",\n\t\t\"Without them, only Pi's retained recent messages remain available.\",\n\t].join(\" \");\n}\n\nfunction markerMessage(checkpointId: string, timestamp: number): AgentMessage {\n\treturn {\n\t\trole: \"user\",\n\t\tcontent: [{ type: \"text\", text: checkpointMarker(checkpointId) }],\n\t\ttimestamp,\n\t};\n}\n\nexport function parseCheckpointDetails(value: unknown): CodexCheckpointDetails | undefined {\n\tif (!isObject(value)) return undefined;\n\tif (\n\t\tvalue.kind !== CHECKPOINT_KIND ||\n\t\tvalue.version !== CHECKPOINT_VERSION ||\n\t\ttypeof value.checkpointId !== \"string\" ||\n\t\tvalue.checkpointId.length < 8 ||\n\t\ttypeof value.provider !== \"string\" ||\n\t\tvalue.provider.length === 0 ||\n\t\tvalue.provider.length > MAX_PROVIDER_ID_LENGTH ||\n\t\tvalue.api !== \"openai-codex-responses\" ||\n\t\ttypeof value.modelId !== \"string\" ||\n\t\tvalue.protocol !== \"remote-compaction-v2\" ||\n\t\t!Array.isArray(value.replacementHistory) ||\n\t\t!Array.isArray(value.keptMessageFingerprints) ||\n\t\ttypeof value.createdAt !== \"string\"\n\t) {\n\t\treturn undefined;\n\t}\n\tif (\n\t\tvalue.replacementHistory.length === 0 ||\n\t\t!value.replacementHistory.every(isObject) ||\n\t\t!value.keptMessageFingerprints.every(\n\t\t\t(fingerprint) => typeof fingerprint === \"string\" && /^[a-f0-9]{64}$/.test(fingerprint),\n\t\t) ||\n\t\tserializedBytes(value.replacementHistory) > REPLACEMENT_BYTE_BUDGET\n\t) {\n\t\treturn undefined;\n\t}\n\tconst last = value.replacementHistory.at(-1);\n\ttry {\n\t\tvalidateCompactionItem(last);\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn structuredClone(value) as unknown as CodexCheckpointDetails;\n}\n\nexport function latestCheckpoint(entries: readonly SessionEntry[]):\n\t| {\n\t\t\tentry: CompactionEntry<CodexCheckpointDetails>;\n\t\t\tdetails: CodexCheckpointDetails;\n\t }\n\t| undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry.type !== \"compaction\") continue;\n\t\tconst details = parseCheckpointDetails(entry.details);\n\t\treturn details\n\t\t\t? { entry: entry as CompactionEntry<CodexCheckpointDetails>, details }\n\t\t\t: undefined;\n\t}\n\treturn undefined;\n}\n\nfunction isOlderCompactionSummary(message: AgentMessage, timestamp: number): boolean {\n\treturn (\n\t\tmessage.role === \"compactionSummary\" &&\n\t\tNumber.isFinite(message.timestamp) &&\n\t\tNumber.isFinite(timestamp) &&\n\t\tmessage.timestamp < timestamp\n\t);\n}\n\nexport function projectCheckpointContext(\n\tmessages: readonly AgentMessage[],\n\tdetails: CodexCheckpointDetails,\n\tcheckpointSummary: string,\n): AgentMessage[] | undefined {\n\tconst summaryIndex = messages.findIndex(\n\t\t(message) => message.role === \"compactionSummary\" && message.summary === checkpointSummary,\n\t);\n\tif (summaryIndex < 0) return undefined;\n\tconst timestamp = messages[summaryIndex].timestamp;\n\tlet messageIndex = summaryIndex + 1;\n\tlet fingerprintIndex = 0;\n\twhile (fingerprintIndex < details.keptMessageFingerprints.length) {\n\t\tif (messageIndex >= messages.length) return undefined;\n\t\tconst message = messages[messageIndex];\n\t\tif (fingerprintMessage(message) === details.keptMessageFingerprints[fingerprintIndex]) {\n\t\t\tmessageIndex += 1;\n\t\t\tfingerprintIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\tif (isOlderCompactionSummary(message, timestamp)) {\n\t\t\tmessageIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\t\treturn undefined;\n\t}\n\twhile (\n\t\tmessageIndex < messages.length &&\n\t\tisOlderCompactionSummary(messages[messageIndex], timestamp)\n\t) {\n\t\tmessageIndex += 1;\n\t}\n\treturn [\n\t\t...messages.slice(0, summaryIndex),\n\t\tmarkerMessage(details.checkpointId, timestamp),\n\t\t...messages.slice(messageIndex),\n\t];\n}\n\nfunction rawText(item: JsonObject): string {\n\tif (!Array.isArray(item.content)) return \"\";\n\treturn item.content\n\t\t.flatMap((part) =>\n\t\t\tisObject(part) && typeof part.text === \"string\" && part.type === \"input_text\"\n\t\t\t\t? [part.text]\n\t\t\t\t: [],\n\t\t)\n\t\t.join(\"\\n\");\n}\n\nfunction hasMedia(item: JsonObject): boolean {\n\treturn (\n\t\tArray.isArray(item.content) &&\n\t\titem.content.some((part) => isObject(part) && part.type === \"input_image\")\n\t);\n}\n\nfunction truncateTextItem(item: JsonObject, maxChars: number): JsonObject | undefined {\n\tif (!Array.isArray(item.content) || maxChars <= 32) return undefined;\n\tlet remaining = maxChars - 16;\n\tconst content = [...item.content].reverse().flatMap((part) => {\n\t\tif (\n\t\t\t!isObject(part) ||\n\t\t\tpart.type !== \"input_text\" ||\n\t\t\ttypeof part.text !== \"string\" ||\n\t\t\tremaining <= 0\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\tconst text = part.text.slice(-remaining);\n\t\tremaining -= text.length;\n\t\treturn [{ ...part, text: `[truncated]\\n${text}` }];\n\t});\n\tif (content.length === 0) return undefined;\n\treturn { ...item, content: content.reverse() };\n}\n\nexport function buildReplacementHistory(\n\tinput: readonly unknown[],\n\tcompactionItem: JsonObject,\n\toptions: { tokenBudget?: number; byteBudget?: number } = {},\n): JsonObject[] {\n\tconst tokenBudget = options.tokenBudget ?? REPLACEMENT_TOKEN_BUDGET;\n\tconst byteBudget = options.byteBudget ?? REPLACEMENT_BYTE_BUDGET;\n\tconst opaque = validateCompactionItem(compactionItem);\n\tlet remainingBytes = byteBudget - serializedBytes(opaque);\n\tlet remainingChars = tokenBudget * 4;\n\tif (remainingBytes <= 0)\n\t\tthrow new Error(\"Opaque compaction item exceeds replacement history budget\");\n\tconst retainedNewestFirst: JsonObject[] = [];\n\tconst candidates = input.filter(\n\t\t(item): item is JsonObject =>\n\t\t\tisObject(item) && item.role === \"user\" && item.type !== \"compaction_trigger\",\n\t);\n\tfor (let index = candidates.length - 1; index >= 0; index--) {\n\t\tconst candidate = candidates[index];\n\t\tconst bytes = serializedBytes(candidate);\n\t\tif (hasMedia(candidate) && bytes > MAX_MEDIA_ITEM_BYTES) continue;\n\t\tconst text = rawText(candidate);\n\t\tlet retained = candidate;\n\t\tif (text.length > remainingChars) {\n\t\t\tif (hasMedia(candidate)) continue;\n\t\t\tconst truncated = truncateTextItem(candidate, remainingChars);\n\t\t\tif (!truncated) continue;\n\t\t\tretained = truncated;\n\t\t}\n\t\tif (serializedBytes(retained) > remainingBytes) {\n\t\t\tif (hasMedia(retained)) continue;\n\t\t\tconst maxCharsByBytes = Math.max(0, remainingBytes - 128);\n\t\t\tconst truncated = truncateTextItem(retained, Math.min(remainingChars, maxCharsByBytes));\n\t\t\tif (!truncated || serializedBytes(truncated) > remainingBytes) continue;\n\t\t\tretained = truncated;\n\t\t}\n\t\tretainedNewestFirst.push(structuredClone(retained));\n\t\tremainingBytes -= serializedBytes(retained);\n\t\tremainingChars -= Math.min(remainingChars, rawText(retained).length);\n\t\tif (remainingBytes <= 128 || remainingChars <= 32) break;\n\t}\n\treturn [...retainedNewestFirst.reverse(), opaque];\n}\n\nexport function createCheckpointDetails(input: {\n\tprovider: string;\n\tmodelId: string;\n\treplacementHistory: JsonObject[];\n\tkeptMessages: readonly AgentMessage[];\n\tcheckpointId?: string;\n\tcreatedAt?: string;\n}): CodexCheckpointDetails {\n\tconst details: CodexCheckpointDetails = {\n\t\tkind: CHECKPOINT_KIND,\n\t\tversion: CHECKPOINT_VERSION,\n\t\tcheckpointId: input.checkpointId ?? randomUUID(),\n\t\tprovider: input.provider,\n\t\tapi: \"openai-codex-responses\",\n\t\tmodelId: input.modelId,\n\t\tprotocol: \"remote-compaction-v2\",\n\t\treplacementHistory: structuredClone(input.replacementHistory),\n\t\tkeptMessageFingerprints: input.keptMessages.map(fingerprintMessage),\n\t\tcreatedAt: input.createdAt ?? new Date().toISOString(),\n\t};\n\tconst parsed = parseCheckpointDetails(details);\n\tif (!parsed) throw new Error(\"Created an invalid Codex checkpoint\");\n\treturn parsed;\n}\n", "export const MAX_SSE_BYTES = 8 * 1024 * 1024;\nexport const MAX_COMPACTION_ITEM_BYTES = 2 * 1024 * 1024;\n\nexport type JsonObject = Record<string, unknown>;\n\nexport class CodexCompactionProtocolError extends Error {\n\tconstructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = \"CodexCompactionProtocolError\";\n\t}\n}\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction byteLength(value: unknown): number {\n\treturn Buffer.byteLength(JSON.stringify(value), \"utf8\");\n}\n\nexport function isCompactionItem(value: unknown): value is JsonObject {\n\treturn (\n\t\tisObject(value) &&\n\t\tvalue.type === \"compaction\" &&\n\t\ttypeof value.encrypted_content === \"string\" &&\n\t\tvalue.encrypted_content.length > 0\n\t);\n}\n\nexport function validateCompactionItem(\n\tvalue: unknown,\n\tmaxBytes = MAX_COMPACTION_ITEM_BYTES,\n): JsonObject {\n\tif (!isCompactionItem(value)) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Remote response did not contain a valid compaction item\",\n\t\t);\n\t}\n\tif (byteLength(value) > maxBytes) {\n\t\tthrow new CodexCompactionProtocolError(\"Remote compaction item exceeded the size limit\");\n\t}\n\treturn structuredClone(value);\n}\n\nexport interface CollectedCompaction {\n\titem: JsonObject;\n\tcompletedResponse?: JsonObject;\n}\n\nfunction compactionItemsFromEvent(event: JsonObject): unknown[] {\n\tconst items: unknown[] = [];\n\tif (event.type === \"response.output_item.done\" && isObject(event.item)) {\n\t\titems.push(event.item);\n\t}\n\tif (event.type === \"response.completed\" && isObject(event.response)) {\n\t\tconst output = event.response.output;\n\t\tif (Array.isArray(output)) items.push(...output);\n\t}\n\treturn items.filter((item) => isObject(item) && item.type === \"compaction\");\n}\n\nexport async function collectCompactionSse(\n\tstream: ReadableStream<Uint8Array>,\n\toptions: {\n\t\tsignal?: AbortSignal;\n\t\tmaxBytes?: number;\n\t\tmaxItemBytes?: number;\n\t} = {},\n): Promise<CollectedCompaction> {\n\tconst maxBytes = options.maxBytes ?? MAX_SSE_BYTES;\n\tconst reader = stream.getReader();\n\tconst onAbort = () => {\n\t\tvoid reader.cancel(new DOMException(\"Compaction aborted\", \"AbortError\")).catch(() => undefined);\n\t};\n\toptions.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\tconst decoder = new TextDecoder();\n\tlet bytes = 0;\n\tlet pending = \"\";\n\tlet dataLines: string[] = [];\n\tlet completedResponse: JsonObject | undefined;\n\tconst items = new Map<string, JsonObject>();\n\n\tconst checkAbort = () => {\n\t\tif (options.signal?.aborted) throw new DOMException(\"Compaction aborted\", \"AbortError\");\n\t};\n\tconst dispatch = () => {\n\t\tif (dataLines.length === 0) return;\n\t\tconst data = dataLines.join(\"\\n\");\n\t\tdataLines = [];\n\t\tif (data === \"[DONE]\") return;\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(data);\n\t\t} catch {\n\t\t\tthrow new CodexCompactionProtocolError(\"Remote compaction returned malformed SSE JSON\");\n\t\t}\n\t\tif (!isObject(parsed)) return;\n\t\tif (parsed.type === \"response.completed\") {\n\t\t\tcompletedResponse = isObject(parsed.response) ? parsed.response : {};\n\t\t}\n\t\tfor (const candidate of compactionItemsFromEvent(parsed)) {\n\t\t\tconst item = validateCompactionItem(candidate, options.maxItemBytes);\n\t\t\titems.set(JSON.stringify(item), item);\n\t\t}\n\t};\n\tconst processLine = (line: string) => {\n\t\tif (line === \"\") {\n\t\t\tdispatch();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return;\n\t\tif (line === \"data\") dataLines.push(\"\");\n\t\telse if (line.startsWith(\"data:\")) dataLines.push(line.slice(5).replace(/^ /, \"\"));\n\t};\n\n\ttry {\n\t\twhile (true) {\n\t\t\tcheckAbort();\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbytes += value.byteLength;\n\t\t\tif (bytes > maxBytes) {\n\t\t\t\tthrow new CodexCompactionProtocolError(\"Remote compaction stream exceeded the size limit\");\n\t\t\t}\n\t\t\tpending += decoder.decode(value, { stream: true });\n\t\t\tlet newline = pending.indexOf(\"\\n\");\n\t\t\twhile (newline !== -1) {\n\t\t\t\tconst rawLine = pending.slice(0, newline);\n\t\t\t\tpending = pending.slice(newline + 1);\n\t\t\t\tprocessLine(rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine);\n\t\t\t\tnewline = pending.indexOf(\"\\n\");\n\t\t\t}\n\t\t}\n\t\tpending += decoder.decode();\n\t\tif (pending.length > 0) processLine(pending.endsWith(\"\\r\") ? pending.slice(0, -1) : pending);\n\t\tdispatch();\n\t\tcheckAbort();\n\t} catch (error) {\n\t\tawait reader.cancel(error).catch(() => undefined);\n\t\tthrow error;\n\t} finally {\n\t\toptions.signal?.removeEventListener(\"abort\", onAbort);\n\t\treader.releaseLock();\n\t}\n\n\tif (!completedResponse) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Remote compaction stream ended without response.completed\",\n\t\t);\n\t}\n\tif (items.size !== 1) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t`Remote compaction returned ${items.size} distinct compaction items; expected exactly one`,\n\t\t);\n\t}\n\treturn { item: [...items.values()][0], completedResponse };\n}\n\nfunction markerTextFromItem(item: unknown): string | undefined {\n\tif (!isObject(item) || item.role !== \"user\" || !Array.isArray(item.content)) return undefined;\n\tif (item.content.length !== 1) return undefined;\n\tconst content = item.content[0];\n\tif (!isObject(content) || content.type !== \"input_text\" || typeof content.text !== \"string\") {\n\t\treturn undefined;\n\t}\n\treturn content.text;\n}\n\nexport function rewriteCheckpointMarker(\n\tpayload: unknown,\n\tmarker: string,\n\treplacementHistory: readonly unknown[],\n): JsonObject {\n\tif (!isObject(payload) || !Array.isArray(payload.input)) {\n\t\tthrow new CodexCompactionProtocolError(\"Codex Responses payload is missing an input array\");\n\t}\n\tconst matches = payload.input\n\t\t.map((item, index) => (markerTextFromItem(item) === marker ? index : -1))\n\t\t.filter((index) => index >= 0);\n\tif (matches.length !== 1) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t`Provider payload contained ${matches.length} checkpoint markers; expected exactly one`,\n\t\t);\n\t}\n\tconst index = matches[0];\n\treturn {\n\t\t...payload,\n\t\tinput: [\n\t\t\t...payload.input.slice(0, index),\n\t\t\t...structuredClone(replacementHistory),\n\t\t\t...payload.input.slice(index + 1),\n\t\t],\n\t};\n}\n\nexport function appendCompactionTrigger(payload: unknown): JsonObject {\n\tif (!isObject(payload) || !Array.isArray(payload.input)) {\n\t\tthrow new CodexCompactionProtocolError(\"Codex Responses payload is missing an input array\");\n\t}\n\tif (payload.input.some((item) => isObject(item) && item.type === \"compaction_trigger\")) {\n\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\"Provider payload already contains a compaction trigger\",\n\t\t);\n\t}\n\treturn { ...payload, input: [...payload.input, { type: \"compaction_trigger\" }] };\n}\n\nexport function prepareRemoteCompactionPayload(\n\tpayload: unknown,\n\tcheckpoint?: { marker: string; replacementHistory: readonly unknown[] },\n): JsonObject {\n\tconst expanded = checkpoint\n\t\t? rewriteCheckpointMarker(payload, checkpoint.marker, checkpoint.replacementHistory)\n\t\t: payload;\n\treturn appendCompactionTrigger(expanded);\n}\n\nexport function hasCheckpointMarker(payload: unknown, marker: string): boolean {\n\treturn (\n\t\tisObject(payload) &&\n\t\tArray.isArray(payload.input) &&\n\t\tpayload.input.some((item) => markerTextFromItem(item) === marker)\n\t);\n}\n", "import type { Context, Model, Provider, ProviderHeaders, Usage } from \"@earendil-works/pi-ai\";\nimport {\n\tCodexCompactionProtocolError,\n\ttype CollectedCompaction,\n\tcollectCompactionSse,\n\ttype JsonObject,\n\tprepareRemoteCompactionPayload,\n} from \"./protocol.js\";\n\ninterface PriorCheckpointPayload {\n\tmarker: string;\n\treplacementHistory: readonly unknown[];\n}\n\nexport interface RemoteCompactionRequest {\n\tprovider: Provider;\n\tmodel: Model<\"openai-codex-responses\">;\n\tcontext: Context;\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tenv?: Record<string, string>;\n\tsignal: AbortSignal;\n\tpriorCheckpoint?: PriorCheckpointPayload;\n\trequestTimeoutMs?: number;\n\tmaxRetries?: number;\n\tfetch?: typeof globalThis.fetch;\n}\n\nexport interface RemoteCompactionResponse {\n\titem: JsonObject;\n\tpromptInput: JsonObject[];\n\tusage: Usage;\n}\n\nconst EMPTY_USAGE: Usage = {\n\tinput: 0,\n\toutput: 0,\n\tcacheRead: 0,\n\tcacheWrite: 0,\n\ttotalTokens: 0,\n\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n};\n\nfunction isObject(value: unknown): value is JsonObject {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction abortError(): DOMException {\n\treturn new DOMException(\"Compaction aborted\", \"AbortError\");\n}\n\nexport async function requestRemoteCompaction(\n\trequest: RemoteCompactionRequest,\n): Promise<RemoteCompactionResponse> {\n\tif (request.signal.aborted) throw abortError();\n\tlet sentInput: JsonObject[] | undefined;\n\tconst inspections: Promise<\n\t\t{ ok: true; value: CollectedCompaction } | { ok: false; error: unknown }\n\t>[] = [];\n\tconst baseFetch = request.fetch ?? globalThis.fetch;\n\tconst inspectedFetch: typeof globalThis.fetch = async (input, init) => {\n\t\tconst response = await baseFetch(input, init);\n\t\tif (!response.ok || !response.body) return response;\n\t\tconst [providerBody, inspectionBody] = response.body.tee();\n\t\tconst inspection = collectCompactionSse(inspectionBody, { signal: request.signal }).then(\n\t\t\t(value) => ({ ok: true as const, value }),\n\t\t\t(error: unknown) => ({ ok: false as const, error }),\n\t\t);\n\t\tinspections.push(inspection);\n\t\treturn new Response(providerBody, {\n\t\t\tstatus: response.status,\n\t\t\tstatusText: response.statusText,\n\t\t\theaders: response.headers,\n\t\t});\n\t};\n\n\tconst stream = request.provider.stream(request.model, request.context, {\n\t\tapiKey: request.apiKey,\n\t\theaders: request.headers,\n\t\tenv: request.env,\n\t\tsignal: request.signal,\n\t\ttransport: \"sse\",\n\t\tcacheRetention: \"none\",\n\t\ttimeoutMs: request.requestTimeoutMs ?? 5 * 60 * 1000,\n\t\tmaxRetries: request.maxRetries ?? 2,\n\t\tfetch: inspectedFetch,\n\t\tonPayload: (payload) => {\n\t\t\tconst prepared = prepareRemoteCompactionPayload(payload, request.priorCheckpoint);\n\t\t\tif (!Array.isArray(prepared.input) || !prepared.input.every(isObject)) {\n\t\t\t\tthrow new CodexCompactionProtocolError(\n\t\t\t\t\t\"Prepared compaction payload has invalid input items\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tsentInput = structuredClone(prepared.input.slice(0, -1)) as JsonObject[];\n\t\t\treturn prepared;\n\t\t},\n\t});\n\n\tlet usage = EMPTY_USAGE;\n\tfor await (const event of stream) {\n\t\tif (request.signal.aborted) throw abortError();\n\t\tif (event.type === \"error\") {\n\t\t\tthrow new Error(event.error.errorMessage ?? \"Codex remote compaction request failed\");\n\t\t}\n\t\tif (event.type === \"done\") usage = event.message.usage;\n\t}\n\tif (request.signal.aborted) throw abortError();\n\tif (!sentInput)\n\t\tthrow new CodexCompactionProtocolError(\"Provider did not expose a request payload\");\n\tif (inspections.length === 0) {\n\t\tthrow new CodexCompactionProtocolError(\"Provider response did not expose an SSE body\");\n\t}\n\tconst inspection = await inspections.at(-1);\n\tif (request.signal.aborted) throw abortError();\n\tif (!inspection?.ok) throw inspection?.error ?? new Error(\"Remote compaction inspection failed\");\n\treturn { item: inspection.value.item, promptInput: sentInput, usage };\n}\n", "import { randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { mkdir, open, rename, rm, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join } from \"node:path\";\nimport { getAgentDir } from \"@earendil-works/pi-coding-agent\";\n\nexport const CODEX_COMPACT_SETTINGS_FILE = \"pi-codex-compact.json\";\nexport const MAX_SETTINGS_BYTES = 64 * 1024;\n\nexport interface CodexCompactSettings {\n\tenabled: boolean;\n\trequestTimeoutMs: number;\n\tmaxRetries: number;\n\treplacementTokenBudget: number;\n\tnotifyOnFallback: boolean;\n}\n\nexport const DEFAULT_CODEX_COMPACT_SETTINGS: Readonly<CodexCompactSettings> = Object.freeze({\n\tenabled: true,\n\trequestTimeoutMs: 300_000,\n\tmaxRetries: 2,\n\treplacementTokenBudget: 64_000,\n\tnotifyOnFallback: true,\n});\n\nconst LIMITS = Object.freeze({\n\trequestTimeoutMs: { minimum: 30_000, maximum: 600_000 },\n\tmaxRetries: { minimum: 0, maximum: 2 },\n\treplacementTokenBudget: { minimum: 8_000, maximum: 128_000 },\n});\n\nexport interface CodexCompactSettingsState {\n\tkind: \"missing\" | \"loaded\" | \"invalid\";\n\tpath: string;\n\tsettings: CodexCompactSettings;\n\tdocument?: Record<string, unknown>;\n\tissue?: string;\n}\n\nexport interface CodexCompactSettingsRuntime {\n\tget(): Readonly<CodexCompactSettingsState>;\n\treload(signal?: AbortSignal): Promise<Readonly<CodexCompactSettingsState>>;\n\tupdate(\n\t\tpatch: Partial<CodexCompactSettings>,\n\t\tsignal?: AbortSignal,\n\t): Promise<Readonly<CodexCompactSettingsState>>;\n\tflush(): Promise<void>;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction validInteger(value: unknown, minimum: number, maximum: number): value is number {\n\treturn (\n\t\ttypeof value === \"number\" && Number.isSafeInteger(value) && value >= minimum && value <= maximum\n\t);\n}\n\nexport function normalizeCodexCompactSettings(value: unknown): CodexCompactSettings | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (Object.hasOwn(value, \"enabled\") && typeof value.enabled !== \"boolean\") return undefined;\n\tif (Object.hasOwn(value, \"notifyOnFallback\") && typeof value.notifyOnFallback !== \"boolean\") {\n\t\treturn undefined;\n\t}\n\tfor (const [field, limits] of Object.entries(LIMITS) as Array<\n\t\t[keyof typeof LIMITS, { minimum: number; maximum: number }]\n\t>) {\n\t\tif (\n\t\t\tObject.hasOwn(value, field) &&\n\t\t\t!validInteger(value[field], limits.minimum, limits.maximum)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn {\n\t\tenabled:\n\t\t\ttypeof value.enabled === \"boolean\" ? value.enabled : DEFAULT_CODEX_COMPACT_SETTINGS.enabled,\n\t\trequestTimeoutMs:\n\t\t\ttypeof value.requestTimeoutMs === \"number\"\n\t\t\t\t? value.requestTimeoutMs\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.requestTimeoutMs,\n\t\tmaxRetries:\n\t\t\ttypeof value.maxRetries === \"number\"\n\t\t\t\t? value.maxRetries\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.maxRetries,\n\t\treplacementTokenBudget:\n\t\t\ttypeof value.replacementTokenBudget === \"number\"\n\t\t\t\t? value.replacementTokenBudget\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.replacementTokenBudget,\n\t\tnotifyOnFallback:\n\t\t\ttypeof value.notifyOnFallback === \"boolean\"\n\t\t\t\t? value.notifyOnFallback\n\t\t\t\t: DEFAULT_CODEX_COMPACT_SETTINGS.notifyOnFallback,\n\t};\n}\n\nexport function codexCompactSettingsPath(): string {\n\treturn join(getAgentDir(), CODEX_COMPACT_SETTINGS_FILE);\n}\n\nfunction aborted(signal?: AbortSignal): void {\n\tif (signal?.aborted) throw new DOMException(\"Settings operation aborted\", \"AbortError\");\n}\n\nexport async function loadCodexCompactSettings(\n\tpath = codexCompactSettingsPath(),\n\tsignal?: AbortSignal,\n): Promise<CodexCompactSettingsState> {\n\taborted(signal);\n\ttry {\n\t\tconst handle = await open(path, constants.O_RDONLY | constants.O_NOFOLLOW);\n\t\tlet text: string;\n\t\ttry {\n\t\t\tconst stats = await handle.stat();\n\t\t\taborted(signal);\n\t\t\tif (!stats.isFile()) throw new Error(\"settings path is not a regular file\");\n\t\t\tif (stats.size > MAX_SETTINGS_BYTES) throw new Error(\"settings file exceeds 64 KiB\");\n\t\t\ttext = await handle.readFile(\"utf8\");\n\t\t} finally {\n\t\t\tawait handle.close();\n\t\t}\n\t\taborted(signal);\n\t\tconst document = JSON.parse(text) as unknown;\n\t\tconst settings = normalizeCodexCompactSettings(document);\n\t\tif (!settings || !isRecord(document)) throw new Error(\"invalid settings shape or bounds\");\n\t\treturn { kind: \"loaded\", path, settings, document };\n\t} catch (error) {\n\t\tif (signal?.aborted) throw error;\n\t\tif (isNodeError(error) && error.code === \"ENOENT\") {\n\t\t\treturn {\n\t\t\t\tkind: \"missing\",\n\t\t\t\tpath,\n\t\t\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\t\t\tdocument: {},\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\tkind: \"invalid\",\n\t\t\tpath,\n\t\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\t\tissue:\n\t\t\t\tisNodeError(error) && error.code === \"ELOOP\"\n\t\t\t\t\t? \"symbolic links are not accepted\"\n\t\t\t\t\t: error instanceof Error\n\t\t\t\t\t\t? error.message\n\t\t\t\t\t\t: String(error),\n\t\t};\n\t}\n}\n\nasync function savePatch(\n\tpath: string,\n\tpatch: Partial<CodexCompactSettings>,\n\tsignal?: AbortSignal,\n): Promise<CodexCompactSettingsState> {\n\tconst latest = await loadCodexCompactSettings(path, signal);\n\tif (latest.kind === \"invalid\") {\n\t\tthrow new Error(\n\t\t\t\"Cannot overwrite an invalid pi-codex-compact.json; repair it and reload first\",\n\t\t);\n\t}\n\tconst document = { ...latest.document, ...patch };\n\tconst settings = normalizeCodexCompactSettings(document);\n\tif (!settings) throw new Error(\"Refusing to save invalid Codex compaction settings\");\n\tconst temporaryPath = join(dirname(path), `.${basename(path)}.${randomUUID()}.tmp`);\n\tawait mkdir(dirname(path), { recursive: true });\n\taborted(signal);\n\ttry {\n\t\tawait writeFile(temporaryPath, `${JSON.stringify(document, null, 2)}\\n`, {\n\t\t\tencoding: \"utf8\",\n\t\t\tflag: \"wx\",\n\t\t\tmode: 0o600,\n\t\t});\n\t\taborted(signal);\n\t\tconst current = await loadCodexCompactSettings(path, signal);\n\t\tif (\n\t\t\tcurrent.kind === \"invalid\" ||\n\t\t\tcurrent.kind !== latest.kind ||\n\t\t\tJSON.stringify(current.document) !== JSON.stringify(latest.document)\n\t\t) {\n\t\t\tthrow new Error(\"pi-codex-compact.json changed while saving; reopen settings and retry\");\n\t\t}\n\t\tawait rename(temporaryPath, path);\n\t} finally {\n\t\tawait rm(temporaryPath, { force: true }).catch(() => undefined);\n\t}\n\treturn { kind: \"loaded\", path, settings, document };\n}\n\nexport function createCodexCompactSettingsRuntime(\n\tpath = codexCompactSettingsPath(),\n): CodexCompactSettingsRuntime {\n\tlet state: CodexCompactSettingsState = {\n\t\tkind: \"missing\",\n\t\tpath,\n\t\tsettings: { ...DEFAULT_CODEX_COMPACT_SETTINGS },\n\t\tdocument: {},\n\t};\n\tlet queue = Promise.resolve();\n\tconst enqueue = <T>(operation: () => Promise<T>): Promise<T> => {\n\t\tconst result = queue.then(operation, operation);\n\t\tqueue = result.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn result;\n\t};\n\treturn {\n\t\tget: () => structuredClone(state),\n\t\treload: (signal) =>\n\t\t\tenqueue(async () => {\n\t\t\t\tstate = await loadCodexCompactSettings(path, signal);\n\t\t\t\treturn structuredClone(state);\n\t\t\t}),\n\t\tupdate: (patch, signal) =>\n\t\t\tenqueue(async () => {\n\t\t\t\tstate = await savePatch(path, patch, signal);\n\t\t\t\treturn structuredClone(state);\n\t\t\t}),\n\t\tflush: () => queue,\n\t};\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n\treturn error instanceof Error && \"code\" in error;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["index", "isObject", "isObject", "inspection", "randomUUID"]
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@narumitw/pi-codex-compact",
3
- "version": "0.50.2",
4
- "description": "Codex Remote Compaction V2 for Pi's OpenAI Codex provider.",
3
+ "version": "0.51.0",
4
+ "description": "Codex Remote Compaction V2 for compatible Pi providers.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "private": false,
package/src/checkpoint.ts CHANGED
@@ -8,12 +8,13 @@ export const CHECKPOINT_VERSION = 1;
8
8
  export const REPLACEMENT_TOKEN_BUDGET = 64_000;
9
9
  export const REPLACEMENT_BYTE_BUDGET = 8 * 1024 * 1024;
10
10
  const MAX_MEDIA_ITEM_BYTES = 2 * 1024 * 1024;
11
+ const MAX_PROVIDER_ID_LENGTH = 256;
11
12
 
12
13
  export interface CodexCheckpointDetails {
13
14
  kind: typeof CHECKPOINT_KIND;
14
15
  version: typeof CHECKPOINT_VERSION;
15
16
  checkpointId: string;
16
- provider: "openai-codex";
17
+ provider: string;
17
18
  api: "openai-codex-responses";
18
19
  modelId: string;
19
20
  protocol: "remote-compaction-v2";
@@ -50,14 +51,14 @@ export function checkpointMarker(checkpointId: string): string {
50
51
  return [
51
52
  `[PI_CODEX_REMOTE_CHECKPOINT:${checkpointId}]`,
52
53
  "Opaque checkpoint injection failed. Do not infer missing history; tell the user to re-enable",
53
- "@narumitw/pi-codex-compact with an openai-codex model.",
54
+ "@narumitw/pi-codex-compact with a model using the openai-codex-responses API.",
54
55
  ].join(" ");
55
56
  }
56
57
 
57
58
  export function fallbackSummary(checkpointId: string): string {
58
59
  return [
59
60
  `OpenAI Codex Remote Compaction V2 checkpoint ${checkpointId} stores the older history opaquely.`,
60
- "Full replay requires @narumitw/pi-codex-compact and an openai-codex model.",
61
+ "Full replay requires @narumitw/pi-codex-compact and the same model through a compatible Codex Responses provider.",
61
62
  "Without them, only Pi's retained recent messages remain available.",
62
63
  ].join(" ");
63
64
  }
@@ -77,7 +78,9 @@ export function parseCheckpointDetails(value: unknown): CodexCheckpointDetails |
77
78
  value.version !== CHECKPOINT_VERSION ||
78
79
  typeof value.checkpointId !== "string" ||
79
80
  value.checkpointId.length < 8 ||
80
- value.provider !== "openai-codex" ||
81
+ typeof value.provider !== "string" ||
82
+ value.provider.length === 0 ||
83
+ value.provider.length > MAX_PROVIDER_ID_LENGTH ||
81
84
  value.api !== "openai-codex-responses" ||
82
85
  typeof value.modelId !== "string" ||
83
86
  value.protocol !== "remote-compaction-v2" ||
@@ -135,10 +138,10 @@ function isOlderCompactionSummary(message: AgentMessage, timestamp: number): boo
135
138
  export function projectCheckpointContext(
136
139
  messages: readonly AgentMessage[],
137
140
  details: CodexCheckpointDetails,
141
+ checkpointSummary: string,
138
142
  ): AgentMessage[] | undefined {
139
- const summary = fallbackSummary(details.checkpointId);
140
143
  const summaryIndex = messages.findIndex(
141
- (message) => message.role === "compactionSummary" && message.summary === summary,
144
+ (message) => message.role === "compactionSummary" && message.summary === checkpointSummary,
142
145
  );
143
146
  if (summaryIndex < 0) return undefined;
144
147
  const timestamp = messages[summaryIndex].timestamp;
@@ -254,6 +257,7 @@ export function buildReplacementHistory(
254
257
  }
255
258
 
256
259
  export function createCheckpointDetails(input: {
260
+ provider: string;
257
261
  modelId: string;
258
262
  replacementHistory: JsonObject[];
259
263
  keptMessages: readonly AgentMessage[];
@@ -264,7 +268,7 @@ export function createCheckpointDetails(input: {
264
268
  kind: CHECKPOINT_KIND,
265
269
  version: CHECKPOINT_VERSION,
266
270
  checkpointId: input.checkpointId ?? randomUUID(),
267
- provider: "openai-codex",
271
+ provider: input.provider,
268
272
  api: "openai-codex-responses",
269
273
  modelId: input.modelId,
270
274
  protocol: "remote-compaction-v2",
@@ -1,6 +1,5 @@
1
1
  import type { AgentMessage } from "@earendil-works/pi-agent-core";
2
2
  import type { Api, Context, Model, Tool } from "@earendil-works/pi-ai";
3
- import { hasApi } from "@earendil-works/pi-ai";
4
3
  import {
5
4
  buildContextEntries,
6
5
  buildSessionContext,
@@ -19,6 +18,7 @@ import {
19
18
  latestCheckpoint,
20
19
  projectCheckpointContext,
21
20
  } from "./checkpoint.js";
21
+ import { isCodexRemoteCompactionModel } from "./model-compatibility.js";
22
22
  import { hasCheckpointMarker, rewriteCheckpointMarker } from "./protocol.js";
23
23
  import { requestRemoteCompaction } from "./remote.js";
24
24
  import {
@@ -30,10 +30,6 @@ import {
30
30
 
31
31
  const STATUS_KEY = "codex-compact";
32
32
 
33
- function isSupportedModel(model: Model<Api> | undefined): model is Model<"openai-codex-responses"> {
34
- return model?.provider === "openai-codex" && hasApi(model, "openai-codex-responses");
35
- }
36
-
37
33
  function activeCheckpoint(ctx: ExtensionContext) {
38
34
  return latestCheckpoint(ctx.sessionManager.getBranch());
39
35
  }
@@ -42,7 +38,7 @@ function isCheckpointCompatible(
42
38
  details: CodexCheckpointDetails,
43
39
  model: Model<Api> | undefined,
44
40
  ): model is Model<"openai-codex-responses"> {
45
- return isSupportedModel(model) && model.id === details.modelId;
41
+ return isCodexRemoteCompactionModel(model) && model.id === details.modelId;
46
42
  }
47
43
 
48
44
  function keptMessages(event: SessionBeforeCompactEvent): AgentMessage[] {
@@ -75,16 +71,16 @@ function projectedCurrentMessages(
75
71
  ): { messages: AgentMessage[]; prior?: CodexCheckpointDetails } {
76
72
  const leafId = event.branchEntries.at(-1)?.id ?? null;
77
73
  const session = buildSessionContext(event.branchEntries, leafId);
78
- const prior = latestCheckpoint(event.branchEntries)?.details;
74
+ const prior = latestCheckpoint(event.branchEntries);
79
75
  if (!prior) return { messages: session.messages };
80
- if (prior.modelId !== model.id) {
76
+ if (prior.details.modelId !== model.id) {
81
77
  throw new Error("The active opaque checkpoint belongs to a different Codex model");
82
78
  }
83
- const projected = projectCheckpointContext(session.messages, prior);
79
+ const projected = projectCheckpointContext(session.messages, prior.details, prior.entry.summary);
84
80
  if (!projected) {
85
81
  throw new Error("The previous opaque checkpoint could not be projected safely");
86
82
  }
87
- return { messages: projected, prior };
83
+ return { messages: projected, prior: prior.details };
88
84
  }
89
85
 
90
86
  function notifyFailure(
@@ -109,17 +105,15 @@ async function compactRemotely(
109
105
  fetch?: typeof globalThis.fetch,
110
106
  ) {
111
107
  const model = ctx.model;
112
- if (!settings.enabled || !isSupportedModel(model)) return undefined;
108
+ if (!settings.enabled || !isCodexRemoteCompactionModel(model)) return undefined;
113
109
  const sessionId = ctx.sessionManager.getSessionId();
114
110
  ctx.ui.setStatus(STATUS_KEY, "Codex remote compaction…");
115
111
  try {
116
112
  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
117
113
  if (!sessionStillOwned(ctx, sessionId, event.signal)) return { cancel: true };
118
- if (!auth.ok || !auth.apiKey) {
119
- throw new Error(auth.ok ? "OpenAI Codex OAuth token is unavailable" : auth.error);
120
- }
114
+ if (!auth.ok) throw new Error(auth.error);
121
115
  const provider = ctx.modelRegistry.getProvider(model.provider);
122
- if (!provider) throw new Error("OpenAI Codex provider is unavailable");
116
+ if (!provider) throw new Error("The active Codex Responses provider is unavailable");
123
117
  const current = projectedCurrentMessages(event, model);
124
118
  const context: Context = {
125
119
  systemPrompt: ctx.getSystemPrompt(),
@@ -149,6 +143,7 @@ async function compactRemotely(
149
143
  tokenBudget: settings.replacementTokenBudget,
150
144
  });
151
145
  const details = createCheckpointDetails({
146
+ provider: model.provider,
152
147
  modelId: model.id,
153
148
  replacementHistory,
154
149
  keptMessages: keptMessages(event),
@@ -239,7 +234,11 @@ export function createCodexCompactExtension(
239
234
  if (!settingsRuntime.get().settings.enabled) return undefined;
240
235
  const checkpoint = activeCheckpoint(ctx);
241
236
  if (!checkpoint || !isCheckpointCompatible(checkpoint.details, ctx.model)) return undefined;
242
- const messages = projectCheckpointContext(event.messages, checkpoint.details);
237
+ const messages = projectCheckpointContext(
238
+ event.messages,
239
+ checkpoint.details,
240
+ checkpoint.entry.summary,
241
+ );
243
242
  return messages ? { messages } : undefined;
244
243
  });
245
244
 
@@ -0,0 +1,8 @@
1
+ import type { Api, Model } from "@earendil-works/pi-ai";
2
+ import { hasApi } from "@earendil-works/pi-ai";
3
+
4
+ export function isCodexRemoteCompactionModel(
5
+ model: Model<Api> | undefined,
6
+ ): model is Model<"openai-codex-responses"> {
7
+ return model !== undefined && hasApi(model, "openai-codex-responses");
8
+ }
package/src/protocol.ts CHANGED
@@ -172,7 +172,7 @@ export function rewriteCheckpointMarker(
172
172
  replacementHistory: readonly unknown[],
173
173
  ): JsonObject {
174
174
  if (!isObject(payload) || !Array.isArray(payload.input)) {
175
- throw new CodexCompactionProtocolError("OpenAI Codex payload is missing an input array");
175
+ throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
176
176
  }
177
177
  const matches = payload.input
178
178
  .map((item, index) => (markerTextFromItem(item) === marker ? index : -1))
@@ -195,7 +195,7 @@ export function rewriteCheckpointMarker(
195
195
 
196
196
  export function appendCompactionTrigger(payload: unknown): JsonObject {
197
197
  if (!isObject(payload) || !Array.isArray(payload.input)) {
198
- throw new CodexCompactionProtocolError("OpenAI Codex payload is missing an input array");
198
+ throw new CodexCompactionProtocolError("Codex Responses payload is missing an input array");
199
199
  }
200
200
  if (payload.input.some((item) => isObject(item) && item.type === "compaction_trigger")) {
201
201
  throw new CodexCompactionProtocolError(
package/src/remote.ts CHANGED
@@ -100,7 +100,7 @@ export async function requestRemoteCompaction(
100
100
  for await (const event of stream) {
101
101
  if (request.signal.aborted) throw abortError();
102
102
  if (event.type === "error") {
103
- throw new Error(event.error.errorMessage ?? "OpenAI Codex compaction request failed");
103
+ throw new Error(event.error.errorMessage ?? "Codex remote compaction request failed");
104
104
  }
105
105
  if (event.type === "done") usage = event.message.usage;
106
106
  }
@@ -1,5 +1,6 @@
1
1
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
2
  import type { MenuDefinition } from "@narumitw/pi-tui-kit";
3
+ import { isCodexRemoteCompactionModel } from "./model-compatibility.js";
3
4
  import type {
4
5
  CodexCompactSettings,
5
6
  CodexCompactSettingsRuntime,
@@ -217,11 +218,11 @@ export async function showCodexCompactMenu(
217
218
  });
218
219
  }
219
220
 
220
- function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {
221
+ export function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {
221
222
  const model = ctx.model;
222
223
  return {
223
224
  model: model ? `${model.provider}/${model.id}` : "none",
224
- remoteCompatible: model?.provider === "openai-codex" && model.api === "openai-codex-responses",
225
+ remoteCompatible: isCodexRemoteCompactionModel(model),
225
226
  };
226
227
  }
227
228
 
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/settings-menu.ts"],
4
- "sourcesContent": ["import type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport type { MenuDefinition } from \"@narumitw/pi-tui-kit\";\nimport type {\n\tCodexCompactSettings,\n\tCodexCompactSettingsRuntime,\n\tCodexCompactSettingsState,\n} from \"./settings.js\";\n\ntype Screen = \"main\" | \"settings\" | \"invalid\";\ntype Action =\n\t| \"compact-now\"\n\t| \"set-enabled\"\n\t| \"set-timeout\"\n\t| \"set-retries\"\n\t| \"set-retention\"\n\t| \"set-notify\";\n\nexport interface SettingsMenuOwner {\n\tsignal: AbortSignal;\n\tisCurrent(): boolean;\n}\n\ninterface CompactMenuStatus {\n\tmodel: string;\n\tremoteCompatible: boolean;\n}\n\nfunction safeText(value: string): string {\n\treturn Array.from(value, (character) => {\n\t\tconst codePoint = character.codePointAt(0) ?? 0;\n\t\treturn codePoint < 32 || (codePoint >= 127 && codePoint <= 159) ? \" \" : character;\n\t}).join(\"\");\n}\n\nfunction timeoutLabel(milliseconds: number): string {\n\treturn `${milliseconds / 60_000} min`;\n}\n\nfunction retentionLabel(tokens: number): string {\n\treturn `${tokens / 1000}K tokens`;\n}\n\nasync function update(\n\truntime: CodexCompactSettingsRuntime,\n\tctx: ExtensionCommandContext,\n\tpatch: Partial<CodexCompactSettings>,\n\tsignal: AbortSignal,\n) {\n\ttry {\n\t\tawait runtime.update(patch, signal);\n\t\tctx.ui.notify(\"Codex compaction settings saved.\", \"info\");\n\t\treturn { kind: \"stay\" as const };\n\t} catch (error) {\n\t\tif (signal.aborted) return { kind: \"rejected\" as const };\n\t\tctx.ui.notify(\n\t\t\t`Could not save pi-codex-compact.json: ${safeText(error instanceof Error ? error.message : String(error))}`,\n\t\t\t\"error\",\n\t\t);\n\t\treturn { kind: \"rejected\" as const };\n\t}\n}\n\nexport function createCodexCompactMenu(\n\truntime: CodexCompactSettingsRuntime,\n\toptions: { onCompactRequested?: () => void; status?: CompactMenuStatus } = {},\n): MenuDefinition<CodexCompactSettingsState, Screen, Action, ExtensionCommandContext> {\n\treturn {\n\t\tstart: \"main\",\n\t\tscreens: {\n\t\t\tmain: ({ state }) => ({\n\t\t\t\tkind: \"actions\",\n\t\t\t\ttitle: \"Codex Remote Compaction\",\n\t\t\t\tlines: [\n\t\t\t\t\t`Remote V2: ${state.settings.enabled ? \"On\" : \"Off\"}`,\n\t\t\t\t\t`Active model: ${safeText(options.status?.model ?? \"none\")}`,\n\t\t\t\t\t`Compact route: ${safeText(compactRoute(state, options.status))}`,\n\t\t\t\t],\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"compact-now\",\n\t\t\t\t\t\tlabel: \"Compact now\",\n\t\t\t\t\t\tdescription: \"Close this menu and compact the active session immediately.\",\n\t\t\t\t\t\taction: \"compact-now\",\n\t\t\t\t\t},\n\t\t\t\t\tstate.kind === \"invalid\"\n\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\tid: \"settings\",\n\t\t\t\t\t\t\t\tlabel: \"Settings\",\n\t\t\t\t\t\t\t\tdescription: \"Read-only until the invalid settings file is repaired.\",\n\t\t\t\t\t\t\t\tto: \"invalid\" as const,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: { id: \"settings\", label: \"Settings\", to: \"settings\" as const },\n\t\t\t\t\t{ id: \"close\", label: \"Close\", close: true },\n\t\t\t\t],\n\t\t\t\thint: \"close\",\n\t\t\t}),\n\t\t\tsettings: ({ state }) => ({\n\t\t\t\tkind: \"settings\",\n\t\t\t\ttitle: \"Codex Remote Compaction Settings\",\n\t\t\t\tlines: [`User settings \u00B7 ${safeText(state.path)}`],\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"enabled\",\n\t\t\t\t\t\tlabel: \"Remote compaction\",\n\t\t\t\t\t\tdescription: \"Use Codex Remote V2 when the active model is compatible.\",\n\t\t\t\t\t\tcurrentValue: state.settings.enabled ? \"On\" : \"Off\",\n\t\t\t\t\t\tvalues: [\"On\", \"Off\"],\n\t\t\t\t\t\taction: \"set-enabled\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"requestTimeoutMs\",\n\t\t\t\t\t\tlabel: \"Request timeout\",\n\t\t\t\t\t\tdescription: \"Maximum time for the extension-owned remote compaction request.\",\n\t\t\t\t\t\tcurrentValue: timeoutLabel(state.settings.requestTimeoutMs),\n\t\t\t\t\t\tvalues: [\"2 min\", \"5 min\", \"10 min\"],\n\t\t\t\t\t\taction: \"set-timeout\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"maxRetries\",\n\t\t\t\t\t\tlabel: \"Transport retries\",\n\t\t\t\t\t\tdescription: \"Retry transient provider failures before falling back to Pi.\",\n\t\t\t\t\t\tcurrentValue: String(state.settings.maxRetries),\n\t\t\t\t\t\tvalues: [\"0\", \"1\", \"2\"],\n\t\t\t\t\t\taction: \"set-retries\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"replacementTokenBudget\",\n\t\t\t\t\t\tlabel: \"Retained user history\",\n\t\t\t\t\t\tdescription: \"Approximate user-message budget kept beside the opaque checkpoint.\",\n\t\t\t\t\t\tcurrentValue: retentionLabel(state.settings.replacementTokenBudget),\n\t\t\t\t\t\tvalues: [\"32K tokens\", \"64K tokens\", \"96K tokens\", \"128K tokens\"],\n\t\t\t\t\t\taction: \"set-retention\",\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"notifyOnFallback\",\n\t\t\t\t\t\tlabel: \"Fallback notifications\",\n\t\t\t\t\t\tdescription: \"Warn when Remote V2 fails and native Pi compaction takes over.\",\n\t\t\t\t\t\tcurrentValue: state.settings.notifyOnFallback ? \"On\" : \"Off\",\n\t\t\t\t\t\tvalues: [\"On\", \"Off\"],\n\t\t\t\t\t\taction: \"set-notify\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t}),\n\t\t\tinvalid: ({ state }) => ({\n\t\t\t\tkind: \"detail\",\n\t\t\t\ttitle: \"Codex Compact Settings \u00B7 Read only\",\n\t\t\t\tlines: [\n\t\t\t\t\t`Invalid settings file: ${safeText(state.path)}`,\n\t\t\t\t\t`Issue: ${safeText(state.issue ?? \"unknown validation error\")}`,\n\t\t\t\t\t\"Built-in defaults are active. Repair the file and run /reload; it will not be overwritten.\",\n\t\t\t\t],\n\t\t\t\thint: \"back\",\n\t\t\t}),\n\t\t},\n\t\tactions: {\n\t\t\t\"compact-now\": async () => {\n\t\t\t\toptions.onCompactRequested?.();\n\t\t\t\treturn { kind: \"close\" };\n\t\t\t},\n\t\t\t\"set-enabled\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(runtime, ctx, { enabled: value === \"On\" }, signal),\n\t\t\t\"set-timeout\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(\n\t\t\t\t\truntime,\n\t\t\t\t\tctx,\n\t\t\t\t\t{ requestTimeoutMs: Number.parseInt(value ?? \"5\", 10) * 60_000 },\n\t\t\t\t\tsignal,\n\t\t\t\t),\n\t\t\t\"set-retries\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(runtime, ctx, { maxRetries: Number.parseInt(value ?? \"2\", 10) }, signal),\n\t\t\t\"set-retention\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(\n\t\t\t\t\truntime,\n\t\t\t\t\tctx,\n\t\t\t\t\t{ replacementTokenBudget: Number.parseInt(value ?? \"64\", 10) * 1000 },\n\t\t\t\t\tsignal,\n\t\t\t\t),\n\t\t\t\"set-notify\": ({ ctx, value, signal }) =>\n\t\t\t\tupdate(runtime, ctx, { notifyOnFallback: value === \"On\" }, signal),\n\t\t},\n\t};\n}\n\nexport async function showCodexCompactMenu(\n\truntime: CodexCompactSettingsRuntime,\n\tctx: ExtensionCommandContext,\n\towner: SettingsMenuOwner,\n): Promise<void> {\n\tif (ctx.mode !== \"tui\") {\n\t\tctx.ui.notify(`Edit Codex compaction settings at ${safeText(runtime.get().path)}.`, \"info\");\n\t\treturn;\n\t}\n\tconst { runMenu } = await import(\"@narumitw/pi-tui-kit\");\n\tif (owner.signal.aborted || !owner.isCurrent()) return;\n\tlet compactRequested = false;\n\tawait runMenu(\n\t\tctx,\n\t\tcreateCodexCompactMenu(runtime, {\n\t\t\tonCompactRequested: () => {\n\t\t\t\tcompactRequested = true;\n\t\t\t},\n\t\t\tstatus: compactMenuStatus(ctx),\n\t\t}),\n\t\t{\n\t\t\tgetState: () => runtime.get(),\n\t\t\tsignal: owner.signal,\n\t\t\tisCurrent: owner.isCurrent,\n\t\t},\n\t);\n\tif (!compactRequested || owner.signal.aborted || !owner.isCurrent()) return;\n\tctx.compact({\n\t\tonError: (error) => {\n\t\t\tif (!owner.signal.aborted && owner.isCurrent()) {\n\t\t\t\tctx.ui.notify(`Compaction failed: ${safeText(error.message)}`, \"error\");\n\t\t\t}\n\t\t},\n\t});\n}\n\nfunction compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {\n\tconst model = ctx.model;\n\treturn {\n\t\tmodel: model ? `${model.provider}/${model.id}` : \"none\",\n\t\tremoteCompatible: model?.provider === \"openai-codex\" && model.api === \"openai-codex-responses\",\n\t};\n}\n\nfunction compactRoute(\n\tstate: Readonly<CodexCompactSettingsState>,\n\tstatus: CompactMenuStatus | undefined,\n): string {\n\tif (!state.settings.enabled) return \"Pi native (Remote V2 off)\";\n\treturn status?.remoteCompatible ? \"Codex Remote V2\" : \"Pi native (model not compatible)\";\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }