@narumitw/pi-codex-compact 0.52.0 → 0.53.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -46
- package/dist/chunks/{chunk-JYXZMCXD.js → chunk-7H7JJ7ZV.js} +9 -15
- package/dist/chunks/chunk-7H7JJ7ZV.js.map +7 -0
- package/dist/chunks/{settings-menu-VYQ6ABCP.js → settings-menu-OAWFW2PH.js} +5 -15
- package/dist/chunks/settings-menu-OAWFW2PH.js.map +7 -0
- package/dist/index.ts +91 -94
- package/dist/index.ts.map +2 -2
- package/package.json +53 -54
- package/src/checkpoint.ts +261 -249
- package/src/codex-compact.ts +250 -254
- package/src/model-api.ts +40 -29
- package/src/protocol.ts +293 -312
- package/src/remote-compact.ts +230 -252
- package/src/remote-shared.ts +12 -15
- package/src/remote-types.ts +27 -26
- package/src/remote-v2.ts +57 -61
- package/src/remote.ts +7 -9
- package/src/settings-menu.ts +207 -231
- package/src/settings.ts +227 -190
- package/src/terminal.ts +4 -4
- package/dist/chunks/chunk-JYXZMCXD.js.map +0 -7
- package/dist/chunks/settings-menu-VYQ6ABCP.js.map +0 -7
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Pi still decides when compaction runs and keeps its normal `/compact`, threshold
|
|
|
8
8
|
|
|
9
9
|
## ✨ Features
|
|
10
10
|
|
|
11
|
-
- Supports `openai-codex-responses`, `openai-responses`, and `azure-openai-responses
|
|
11
|
+
- Supports `openai-codex-responses`, `openai-responses`, and `azure-openai-responses`, plus explicitly profiled custom APIs.
|
|
12
12
|
- Uses Remote V2 or same-origin unary `responses/compact` through the active provider and credentials.
|
|
13
13
|
- Handles manual, threshold, and overflow compaction through Pi's existing lifecycle.
|
|
14
14
|
- Validates and persists one bounded opaque checkpoint that survives compatible reloads, resumes, and forks.
|
|
@@ -49,36 +49,24 @@ Review third-party extension source before installing it.
|
|
|
49
49
|
|
|
50
50
|
1. Sign in through Pi's built-in OpenAI, OpenAI Codex, or Azure OpenAI provider, or configure a compatible custom provider.
|
|
51
51
|
2. Select a model using `openai-codex-responses`, `openai-responses`, or `azure-openai-responses`.
|
|
52
|
-
3. Work normally.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
52
|
+
3. Work normally; Pi's automatic compaction and built-in `/compact` continue to operate.
|
|
53
|
+
|
|
54
|
+
Run `/codex-compact` when you want to inspect the effective route or choose **Compact now**.
|
|
55
|
+
After compaction, compatible requests replay the opaque checkpoint automatically.
|
|
56
56
|
|
|
57
57
|
With the default `auto` protocol, Codex Responses uses Remote V2 while OpenAI and Azure OpenAI Responses use unary `responses/compact`.
|
|
58
58
|
When the active model uses another API, compaction remains entirely Pi-native.
|
|
59
|
+
To opt in a compatible custom API, add it to `apiProfiles` as described below.
|
|
59
60
|
|
|
60
61
|
## 💬 Commands
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
Run `/codex-compact` to inspect the effective compaction path, change settings, or request manual compaction in TUI mode.
|
|
64
|
+
It accepts no arguments.
|
|
65
|
+
RPC reports the manual settings path without compacting; print and JSON modes reject the command.
|
|
66
|
+
Closing the menu with Escape or Ctrl+C does not compact the session.
|
|
65
67
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
```text
|
|
70
|
-
Compact now
|
|
71
|
-
Settings
|
|
72
|
-
Close
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
**Compact now** closes the menu before asking Pi to compact the active session.
|
|
76
|
-
Escape or Ctrl+C closes without compacting, and an obsolete menu cannot trigger work after session replacement or shutdown.
|
|
77
|
-
**Settings** opens the bounded settings editor.
|
|
78
|
-
In RPC mode, the command reports the manual settings path instead of opening custom UI or compacting.
|
|
79
|
-
Print and JSON modes reject the command explicitly because they cannot open the menu or safely replace their normal output with an interactive result.
|
|
80
|
-
|
|
81
|
-
Pi's built-in `/compact` remains available and follows the same extension hook for all three supported Responses APIs.
|
|
68
|
+
Manual compaction uses **Responses Remote V2**, **Responses Compact API**, or **Pi native**, as described in [Settings](#-settings).
|
|
69
|
+
Pi's built-in `/compact` remains available and follows the same extension hook.
|
|
82
70
|
|
|
83
71
|
## ⚙️ Settings
|
|
84
72
|
|
|
@@ -95,6 +83,9 @@ There is no environment-variable or project-level override.
|
|
|
95
83
|
{
|
|
96
84
|
"enabled": true,
|
|
97
85
|
"protocol": "auto",
|
|
86
|
+
"apiProfiles": {
|
|
87
|
+
"custom-responses": "codex-responses-v1"
|
|
88
|
+
},
|
|
98
89
|
"requestTimeoutMs": 300000,
|
|
99
90
|
"maxRetries": 2,
|
|
100
91
|
"replacementTokenBudget": 64000,
|
|
@@ -106,6 +97,7 @@ There is no environment-variable or project-level override.
|
|
|
106
97
|
| --- | ---: | --- | --- | --- |
|
|
107
98
|
| `enabled` | `true` | Boolean | Attempt a supported remote compaction route. | Keep enabled unless diagnosing provider behavior. |
|
|
108
99
|
| `protocol` | `"auto"` | `"auto"`, `"remote-v2"`, or `"responses-compact"` | Select by API or force one remote protocol. | Keep `auto`; force a route only when diagnosing a compatible backend. |
|
|
100
|
+
| `apiProfiles` | `{}` | Object mapping a custom API id to `"codex-responses-v1"` | Explicitly opts a non-built-in API into Codex-compatible request fields and replay. | Leave empty unless the provider documents Codex Responses compatibility. |
|
|
109
101
|
| `requestTimeoutMs` | `300000` | Integer from 30,000 to 600,000 ms | Bound one extension-owned remote request. | Keep five minutes; increase only for a consistently slow connection. |
|
|
110
102
|
| `maxRetries` | `2` | Integer from 0 to 2 | Retry transient provider transport failures before Pi fallback. | Keep two; use zero when diagnosing the first failure. |
|
|
111
103
|
| `replacementTokenBudget` | `64000` | Integer from 8,000 to 128,000 tokens | Bound approximate retained user-message text beside the opaque item. | Keep 64K; lower it to reduce session size or raise it only when recent user context is being lost. |
|
|
@@ -135,7 +127,7 @@ This extension does **not** read `~/.codex/config.toml`.
|
|
|
135
127
|
## ✅ Requirements and compatibility
|
|
136
128
|
|
|
137
129
|
- Pi APIs compatible with the package's declared peer dependencies.
|
|
138
|
-
- One of `openai-codex-responses`, `openai-responses`, or `azure-openai-responses` on the active model.
|
|
130
|
+
- One of `openai-codex-responses`, `openai-responses`, or `azure-openai-responses` on the active model, or an explicit `apiProfiles` entry for a custom Codex-compatible API.
|
|
139
131
|
- A provider whose HTTP Responses adapter honors Pi's public `onPayload` and injected `fetch` options.
|
|
140
132
|
- A backend supporting the selected protocol and opaque `compaction` replay.
|
|
141
133
|
- Working credentials and any required compaction entitlement.
|
|
@@ -148,10 +140,12 @@ This extension does **not** read `~/.codex/config.toml`.
|
|
|
148
140
|
|
|
149
141
|
The installed built-in adapters are covered by deterministic transport tests.
|
|
150
142
|
A custom provider or proxy is eligible when its model explicitly uses one of these APIs, but its backend still owns compatible routing, authentication, request transforms, and opaque replay.
|
|
143
|
+
For a custom API label, eligibility is opt-in: `apiProfiles` must map that exact non-built-in label to `"codex-responses-v1"`. The default is empty, and an unconfigured custom API remains Pi-native.
|
|
144
|
+
`codex-responses-v1` uses Remote V2 in `auto` mode. With `responses-compact` explicitly selected, it retains the Codex Compact request fields, including tools and reasoning. The provider must honor Pi's public `transport: "sse"`, `onPayload`, and injected `fetch` options, and its backend must support the selected compaction protocol and opaque item replay. The profile declares compatibility; it does not probe the backend.
|
|
151
145
|
The extension does not send a separate capability probe or automatically retry a failed billable request through the other protocol.
|
|
152
146
|
A failed remote attempt falls back to Pi native, but an ordinary request cannot transparently recover after an incompatible provider has already received an existing opaque checkpoint.
|
|
153
147
|
Provider provenance is stored for diagnosis but is not a replay gate.
|
|
154
|
-
Switching providers can replay a checkpoint only when the API label and exact model ID still match;
|
|
148
|
+
Switching providers can replay a checkpoint only when the API label, compatibility profile, and exact model ID still match. Custom API checkpoints also require a current matching `apiProfiles` entry; removing or changing it leaves Pi's visible fallback marker plus retained recent messages in context.
|
|
155
149
|
|
|
156
150
|
## 🔄 How it works
|
|
157
151
|
|
|
@@ -160,11 +154,12 @@ Switching providers can replay a checkpoint only when the API label and exact mo
|
|
|
160
154
|
3. Remote V2 projects that checkpoint into a normal Responses SSE request and appends exactly one final `compaction_trigger`.
|
|
161
155
|
4. Unary compact captures the provider-built payload and authentication, rewrites only the same-origin `/responses` path to `/responses/compact`, and requests JSON without making a normal inference call.
|
|
162
156
|
5. It requires one bounded non-empty opaque `compaction` item; unary output may precede it only with user-role retained messages.
|
|
163
|
-
6. It constructs bounded replacement history and stores it with Pi suffix fingerprints in versioned `CompactionEntry.details`.
|
|
157
|
+
6. It constructs bounded replacement history and stores it with Pi suffix fingerprints, the real API label, and the resolved compatibility profile in versioned `CompactionEntry.details`.
|
|
164
158
|
7. On later compatible requests, it replaces an exactly validated marker with the persisted replacement history immediately before provider dispatch.
|
|
165
159
|
|
|
166
160
|
The persisted entry remains the summary identity source, so replay does not depend on the wording generated by the currently installed extension version.
|
|
167
161
|
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.
|
|
162
|
+
Older v1 and v2 checkpoints are normalized to the current checkpoint format when read; their built-in API label determines the profile. They still replay only when the current route authorizes that API/profile/model combination.
|
|
168
163
|
|
|
169
164
|
## 🔒 Security and privacy
|
|
170
165
|
|
|
@@ -189,7 +184,7 @@ These hard byte ceilings are intentionally not configurable.
|
|
|
189
184
|
## 🚧 Limitations
|
|
190
185
|
|
|
191
186
|
- Codex Remote V2 remains an undocumented hosted contract and can change independently of Pi or this package; keep backups of important sessions.
|
|
192
|
-
- Full older history depends on this extension, the checkpoint API label, the exact checkpoint model ID, and a provider route whose backend accepts the opaque item.
|
|
187
|
+
- Full older history depends on this extension, the checkpoint API label and compatibility profile, the exact checkpoint model ID, and a provider route whose backend accepts the opaque item.
|
|
193
188
|
Removing the extension exposes only the portability fallback marker and Pi-retained recent messages.
|
|
194
189
|
- 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.
|
|
195
190
|
- Pi's public `getAllTools()` metadata does not expose `constrainedSampling`; Remote V2 preserves active tool order, names, descriptions, and parameter schemas but cannot reproduce that optional field.
|
|
@@ -223,30 +218,23 @@ npm test
|
|
|
223
218
|
npm run package:pack -- codex-compact
|
|
224
219
|
```
|
|
225
220
|
|
|
226
|
-
See [
|
|
221
|
+
See the [Codex compaction mechanism notes](https://github.com/narumiruna/pi-extensions/blob/main/docs/implementation-notes/codex-compaction-mechanism.md) for the underlying Codex mechanism research and the extension boundary.
|
|
227
222
|
|
|
228
223
|
## 🗂️ Package layout
|
|
229
224
|
|
|
230
225
|
```text
|
|
231
|
-
|
|
232
|
-
src/
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
src/checkpoint.ts Replacement history, fingerprints, persistence, and replay projection
|
|
240
|
-
src/model-api.ts Responses API and protocol route selection
|
|
241
|
-
src/settings.ts Global settings validation and atomic persistence
|
|
242
|
-
src/settings-menu.ts First-use manual compaction and settings TUI
|
|
243
|
-
|
|
244
|
-
dist/ Generated source-mapped Jiti runtime and lazy menu chunk
|
|
245
|
-
scripts/ Runtime builder
|
|
246
|
-
benchmark/ Three-arm compaction benchmark, self-test, and methodology
|
|
247
|
-
test/ Protocol, checkpoint, lifecycle, remote, settings, menu, and builder coverage
|
|
226
|
+
packages/pi-codex-compact/
|
|
227
|
+
├── src/ # Authoritative implementation and helpers
|
|
228
|
+
│ ├── index.ts # Thin Pi entrypoint
|
|
229
|
+
│ └── codex-compact.ts # Compaction routing, replay, and fallback
|
|
230
|
+
├── dist/ # Generated Jiti runtime
|
|
231
|
+
├── scripts/build-runtime.mjs # Runtime builder
|
|
232
|
+
├── benchmark/ # Repository-only benchmark and methodology
|
|
233
|
+
└── test/ # Behavior and lifecycle coverage
|
|
248
234
|
```
|
|
249
235
|
|
|
236
|
+
The generated runtime is built from `src/index.ts` and does not import back into `src`.
|
|
237
|
+
|
|
250
238
|
## 🔎 Keywords
|
|
251
239
|
|
|
252
240
|
Pi extension, Pi coding agent, OpenAI Codex, Azure OpenAI, custom provider, proxy, Remote Compaction V2, Responses Compact API, opaque checkpoint, Responses API, context compaction.
|
|
@@ -2,24 +2,20 @@
|
|
|
2
2
|
// @ts-nocheck -- the generated entry uses a .ts extension for Pi's Jiti loader.
|
|
3
3
|
|
|
4
4
|
// src/model-api.ts
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
"openai-
|
|
8
|
-
"
|
|
9
|
-
"azure-openai-responses"
|
|
10
|
-
];
|
|
11
|
-
function usesResponsesCompactionApi(model) {
|
|
12
|
-
return model !== void 0 && RESPONSES_COMPACTION_APIS.some((api) => hasApi(model, api));
|
|
5
|
+
function resolveResponsesCompactionProfile(api, apiProfiles = {}) {
|
|
6
|
+
if (api === "openai-codex-responses") return "codex-responses-v1";
|
|
7
|
+
if (api === "openai-responses" || api === "azure-openai-responses") return "openai-responses-v1";
|
|
8
|
+
return api && Object.hasOwn(apiProfiles, api) && apiProfiles[api] === "codex-responses-v1" ? "codex-responses-v1" : void 0;
|
|
13
9
|
}
|
|
14
10
|
function resolveCompactionRouteForApi(api, options) {
|
|
15
11
|
if (!options.enabled) return { kind: "native", reason: "remote compaction is disabled" };
|
|
16
12
|
if (!api) return { kind: "native", reason: "no active model" };
|
|
17
|
-
|
|
13
|
+
const profile = resolveResponsesCompactionProfile(api, options.apiProfiles);
|
|
14
|
+
if (!profile) {
|
|
18
15
|
return { kind: "native", reason: `API ${api} does not support Responses compaction` };
|
|
19
16
|
}
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
return { kind: "remote", protocol, api: supportedApi };
|
|
17
|
+
const protocol = options.protocol === "auto" ? profile === "codex-responses-v1" ? "remote-v2" : "responses-compact" : options.protocol;
|
|
18
|
+
return { kind: "remote", protocol, api, profile };
|
|
23
19
|
}
|
|
24
20
|
function resolveCompactionRoute(model, options) {
|
|
25
21
|
return resolveCompactionRouteForApi(model?.api, options);
|
|
@@ -34,10 +30,8 @@ function terminalText(value) {
|
|
|
34
30
|
}
|
|
35
31
|
|
|
36
32
|
export {
|
|
37
|
-
RESPONSES_COMPACTION_APIS,
|
|
38
|
-
usesResponsesCompactionApi,
|
|
39
33
|
resolveCompactionRouteForApi,
|
|
40
34
|
resolveCompactionRoute,
|
|
41
35
|
terminalText
|
|
42
36
|
};
|
|
43
|
-
//# sourceMappingURL=chunk-
|
|
37
|
+
//# sourceMappingURL=chunk-7H7JJ7ZV.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/model-api.ts", "../../src/terminal.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Api, Model } from \"@earendil-works/pi-ai\";\nimport type { CodexCompactSettings } from \"./settings.js\";\n\nexport const RESPONSES_COMPACTION_APIS = [\n \"openai-codex-responses\",\n \"openai-responses\",\n \"azure-openai-responses\",\n] as const;\n\nexport type BuiltInResponsesCompactionApi = (typeof RESPONSES_COMPACTION_APIS)[number];\nexport type ResponsesCompactionApi = BuiltInResponsesCompactionApi;\nexport type ResponsesCompactionProfile = \"codex-responses-v1\" | \"openai-responses-v1\";\nexport type RemoteCompactionProtocol = \"remote-v2\" | \"responses-compact\";\nexport type RemoteCompactionProtocolSetting = \"auto\" | RemoteCompactionProtocol;\n\nexport type CompactionRoute =\n | { kind: \"remote\"; protocol: RemoteCompactionProtocol; api: Api; profile: ResponsesCompactionProfile }\n | { kind: \"native\"; reason: string };\n\nfunction resolveResponsesCompactionProfile(\n api: Api | undefined,\n apiProfiles: Readonly<Record<string, \"codex-responses-v1\">> = {},\n): ResponsesCompactionProfile | undefined {\n if (api === \"openai-codex-responses\") return \"codex-responses-v1\";\n if (api === \"openai-responses\" || api === \"azure-openai-responses\") return \"openai-responses-v1\";\n return api && Object.hasOwn(apiProfiles, api) && apiProfiles[api] === \"codex-responses-v1\"\n ? \"codex-responses-v1\"\n : undefined;\n}\n\nexport function resolveCompactionRouteForApi(\n api: Api | undefined,\n options: Pick<CodexCompactSettings, \"enabled\" | \"protocol\"> & {\n apiProfiles?: Readonly<Record<string, \"codex-responses-v1\">>;\n },\n): CompactionRoute {\n if (!options.enabled) return { kind: \"native\", reason: \"remote compaction is disabled\" };\n if (!api) return { kind: \"native\", reason: \"no active model\" };\n const profile = resolveResponsesCompactionProfile(api, options.apiProfiles);\n if (!profile) {\n return { kind: \"native\", reason: `API ${api} does not support Responses compaction` };\n }\n const protocol =\n options.protocol === \"auto\"\n ? profile === \"codex-responses-v1\"\n ? \"remote-v2\"\n : \"responses-compact\"\n : options.protocol;\n return { kind: \"remote\", protocol, api, profile };\n}\n\nexport function resolveCompactionRoute(\n model: Model<Api> | undefined,\n options: Pick<CodexCompactSettings, \"enabled\" | \"protocol\"> & {\n apiProfiles?: Readonly<Record<string, \"codex-responses-v1\">>;\n },\n): CompactionRoute {\n return resolveCompactionRouteForApi(model?.api, options);\n}\n", "export function terminalText(value: string): string {\n return Array.from(value, (character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint < 32 || (codePoint >= 127 && codePoint <= 159) ? \" \" : character;\n }).join(\"\");\n}\n"],
|
|
5
|
+
"mappings": ";;;;AAmBA,SAAS,kCACP,KACA,cAA8D,CAAC,GACvB;AACxC,MAAI,QAAQ,yBAA0B,QAAO;AAC7C,MAAI,QAAQ,sBAAsB,QAAQ,yBAA0B,QAAO;AAC3E,SAAO,OAAO,OAAO,OAAO,aAAa,GAAG,KAAK,YAAY,GAAG,MAAM,uBAClE,uBACA;AACN;AAEO,SAAS,6BACd,KACA,SAGiB;AACjB,MAAI,CAAC,QAAQ,QAAS,QAAO,EAAE,MAAM,UAAU,QAAQ,gCAAgC;AACvF,MAAI,CAAC,IAAK,QAAO,EAAE,MAAM,UAAU,QAAQ,kBAAkB;AAC7D,QAAM,UAAU,kCAAkC,KAAK,QAAQ,WAAW;AAC1E,MAAI,CAAC,SAAS;AACZ,WAAO,EAAE,MAAM,UAAU,QAAQ,OAAO,GAAG,yCAAyC;AAAA,EACtF;AACA,QAAM,WACJ,QAAQ,aAAa,SACjB,YAAY,uBACV,cACA,sBACF,QAAQ;AACd,SAAO,EAAE,MAAM,UAAU,UAAU,KAAK,QAAQ;AAClD;AAEO,SAAS,uBACd,OACA,SAGiB;AACjB,SAAO,6BAA6B,OAAO,KAAK,OAAO;AACzD;;;AC1DO,SAAS,aAAa,OAAuB;AAClD,SAAO,MAAM,KAAK,OAAO,CAAC,cAAc;AACtC,UAAM,YAAY,UAAU,YAAY,CAAC,KAAK;AAC9C,WAAO,YAAY,MAAO,aAAa,OAAO,aAAa,MAAO,MAAM;AAAA,EAC1E,CAAC,EAAE,KAAK,EAAE;AACZ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
import {
|
|
4
4
|
resolveCompactionRouteForApi,
|
|
5
5
|
terminalText
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7H7JJ7ZV.js";
|
|
7
7
|
|
|
8
8
|
// src/settings-menu.ts
|
|
9
|
+
import { runMenu } from "@narumitw/pi-tui-kit";
|
|
9
10
|
function timeoutLabel(milliseconds) {
|
|
10
11
|
return `${milliseconds / 6e4} min`;
|
|
11
12
|
}
|
|
@@ -147,19 +148,9 @@ function createCodexCompactMenu(runtime, options = {}) {
|
|
|
147
148
|
},
|
|
148
149
|
signal
|
|
149
150
|
),
|
|
150
|
-
"set-timeout": ({ ctx, value, signal }) => update(
|
|
151
|
-
runtime,
|
|
152
|
-
ctx,
|
|
153
|
-
{ requestTimeoutMs: Number.parseInt(value ?? "5", 10) * 6e4 },
|
|
154
|
-
signal
|
|
155
|
-
),
|
|
151
|
+
"set-timeout": ({ ctx, value, signal }) => update(runtime, ctx, { requestTimeoutMs: Number.parseInt(value ?? "5", 10) * 6e4 }, signal),
|
|
156
152
|
"set-retries": ({ ctx, value, signal }) => update(runtime, ctx, { maxRetries: Number.parseInt(value ?? "2", 10) }, signal),
|
|
157
|
-
"set-retention": ({ ctx, value, signal }) => update(
|
|
158
|
-
runtime,
|
|
159
|
-
ctx,
|
|
160
|
-
{ replacementTokenBudget: Number.parseInt(value ?? "64", 10) * 1e3 },
|
|
161
|
-
signal
|
|
162
|
-
),
|
|
153
|
+
"set-retention": ({ ctx, value, signal }) => update(runtime, ctx, { replacementTokenBudget: Number.parseInt(value ?? "64", 10) * 1e3 }, signal),
|
|
163
154
|
"set-notify": ({ ctx, value, signal }) => update(runtime, ctx, { notifyOnFallback: value === "On" }, signal)
|
|
164
155
|
}
|
|
165
156
|
};
|
|
@@ -172,7 +163,6 @@ async function showCodexCompactMenu(runtime, ctx, owner) {
|
|
|
172
163
|
if (ctx.mode !== "tui") {
|
|
173
164
|
throw new Error("/codex-compact requires TUI or RPC UI support");
|
|
174
165
|
}
|
|
175
|
-
const { runMenu } = await import("@narumitw/pi-tui-kit");
|
|
176
166
|
if (owner.signal.aborted || !owner.isCurrent()) return;
|
|
177
167
|
let compactRequested = false;
|
|
178
168
|
await runMenu(
|
|
@@ -215,4 +205,4 @@ export {
|
|
|
215
205
|
createCodexCompactMenu,
|
|
216
206
|
showCodexCompactMenu
|
|
217
207
|
};
|
|
218
|
-
//# sourceMappingURL=settings-menu-
|
|
208
|
+
//# sourceMappingURL=settings-menu-OAWFW2PH.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/settings-menu.ts"],
|
|
4
|
+
"sourcesContent": ["import type { Api } from \"@earendil-works/pi-ai\";\nimport type { ExtensionCommandContext } from \"@earendil-works/pi-coding-agent\";\nimport { type MenuDefinition, runMenu } from \"@narumitw/pi-tui-kit\";\nimport { resolveCompactionRouteForApi } from \"./model-api.js\";\nimport type { CodexCompactSettings, CodexCompactSettingsRuntime, CodexCompactSettingsState } from \"./settings.js\";\nimport { terminalText as safeText } from \"./terminal.js\";\n\ntype Screen = \"main\" | \"settings\" | \"invalid\";\ntype Action =\n | \"compact-now\"\n | \"set-enabled\"\n | \"set-protocol\"\n | \"set-timeout\"\n | \"set-retries\"\n | \"set-retention\"\n | \"set-notify\";\n\nexport interface SettingsMenuOwner {\n signal: AbortSignal;\n isCurrent(): boolean;\n}\n\ninterface CompactMenuStatus {\n model: string;\n api?: Api;\n}\n\nfunction timeoutLabel(milliseconds: number): string {\n return `${milliseconds / 60_000} min`;\n}\n\nfunction retentionLabel(tokens: number): string {\n return `${tokens / 1000}K tokens`;\n}\n\nfunction protocolLabel(protocol: CodexCompactSettings[\"protocol\"]): string {\n switch (protocol) {\n case \"auto\":\n return \"Auto\";\n case \"remote-v2\":\n return \"Remote V2\";\n case \"responses-compact\":\n return \"Responses Compact\";\n }\n}\n\nasync function update(\n runtime: CodexCompactSettingsRuntime,\n ctx: ExtensionCommandContext,\n patch: Partial<CodexCompactSettings>,\n signal: AbortSignal,\n) {\n try {\n await runtime.update(patch, signal);\n if (signal.aborted) return { kind: \"rejected\" as const };\n ctx.ui.notify(\"Responses compaction settings saved.\", \"info\");\n return { kind: \"stay\" as const };\n } catch (error) {\n if (signal.aborted) return { kind: \"rejected\" as const };\n ctx.ui.notify(\n `Could not save pi-codex-compact.json: ${safeText(error instanceof Error ? error.message : String(error))}`,\n \"error\",\n );\n return { kind: \"rejected\" as const };\n }\n}\n\nexport function createCodexCompactMenu(\n runtime: CodexCompactSettingsRuntime,\n options: { onCompactRequested?: () => void; status?: CompactMenuStatus } = {},\n): MenuDefinition<CodexCompactSettingsState, Screen, Action, ExtensionCommandContext> {\n return {\n start: \"main\",\n screens: {\n main: ({ state }) => ({\n kind: \"actions\",\n title: \"Responses Compaction\",\n lines: [\n `Remote compaction: ${state.settings.enabled ? \"On\" : \"Off\"}`,\n `Protocol setting: ${protocolLabel(state.settings.protocol)}`,\n `Active model: ${safeText(options.status?.model ?? \"none\")}`,\n `Compact route: ${safeText(compactRoute(state, options.status))}`,\n ],\n items: [\n {\n id: \"compact-now\",\n label: \"Compact now\",\n description: \"Close this menu and compact the active session immediately.\",\n action: \"compact-now\",\n },\n state.kind === \"invalid\"\n ? {\n id: \"settings\",\n label: \"Settings\",\n description: \"Read-only until the invalid settings file is repaired.\",\n to: \"invalid\" as const,\n }\n : { id: \"settings\", label: \"Settings\", to: \"settings\" as const },\n { id: \"close\", label: \"Close\", close: true },\n ],\n hint: \"close\",\n }),\n settings: ({ state }) => ({\n kind: \"settings\",\n title: \"Responses Compaction Settings\",\n lines: [`User settings \u00B7 ${safeText(state.path)}`],\n items: [\n {\n id: \"enabled\",\n label: \"Remote compaction\",\n description: \"Use a supported Responses compaction protocol.\",\n currentValue: state.settings.enabled ? \"On\" : \"Off\",\n values: [\"On\", \"Off\"],\n action: \"set-enabled\",\n },\n {\n id: \"protocol\",\n label: \"Protocol\",\n description: \"Choose automatically or force one supported remote protocol.\",\n currentValue: protocolLabel(state.settings.protocol),\n values: [\"Auto\", \"Remote V2\", \"Responses Compact\"],\n action: \"set-protocol\",\n },\n {\n id: \"requestTimeoutMs\",\n label: \"Request timeout\",\n description: \"Maximum time for the extension-owned remote compaction request.\",\n currentValue: timeoutLabel(state.settings.requestTimeoutMs),\n values: [\"2 min\", \"5 min\", \"10 min\"],\n action: \"set-timeout\",\n },\n {\n id: \"maxRetries\",\n label: \"Transport retries\",\n description: \"Retry transient provider failures before falling back to Pi.\",\n currentValue: String(state.settings.maxRetries),\n values: [\"0\", \"1\", \"2\"],\n action: \"set-retries\",\n },\n {\n id: \"replacementTokenBudget\",\n label: \"Retained user history\",\n description: \"Approximate user-message budget kept beside the opaque checkpoint.\",\n currentValue: retentionLabel(state.settings.replacementTokenBudget),\n values: [\"32K tokens\", \"64K tokens\", \"96K tokens\", \"128K tokens\"],\n action: \"set-retention\",\n },\n {\n id: \"notifyOnFallback\",\n label: \"Fallback notifications\",\n description: \"Warn when remote compaction fails and Pi native takes over.\",\n currentValue: state.settings.notifyOnFallback ? \"On\" : \"Off\",\n values: [\"On\", \"Off\"],\n action: \"set-notify\",\n },\n ],\n }),\n invalid: ({ state }) => ({\n kind: \"detail\",\n title: \"Codex Compact Settings \u00B7 Read only\",\n lines: [\n `Invalid settings file: ${safeText(state.path)}`,\n `Issue: ${safeText(state.issue ?? \"unknown validation error\")}`,\n \"Built-in defaults are active. Repair the file and run /reload; it will not be overwritten.\",\n ],\n hint: \"back\",\n }),\n },\n actions: {\n \"compact-now\": async () => {\n options.onCompactRequested?.();\n return { kind: \"close\" };\n },\n \"set-enabled\": ({ ctx, value, signal }) => update(runtime, ctx, { enabled: value === \"On\" }, signal),\n \"set-protocol\": ({ ctx, value, signal }) =>\n update(\n runtime,\n ctx,\n {\n protocol:\n value === \"Remote V2\" ? \"remote-v2\" : value === \"Responses Compact\" ? \"responses-compact\" : \"auto\",\n },\n signal,\n ),\n \"set-timeout\": ({ ctx, value, signal }) =>\n update(runtime, ctx, { requestTimeoutMs: Number.parseInt(value ?? \"5\", 10) * 60_000 }, signal),\n \"set-retries\": ({ ctx, value, signal }) =>\n update(runtime, ctx, { maxRetries: Number.parseInt(value ?? \"2\", 10) }, signal),\n \"set-retention\": ({ ctx, value, signal }) =>\n update(runtime, ctx, { replacementTokenBudget: Number.parseInt(value ?? \"64\", 10) * 1000 }, signal),\n \"set-notify\": ({ ctx, value, signal }) => update(runtime, ctx, { notifyOnFallback: value === \"On\" }, signal),\n },\n };\n}\n\nexport async function showCodexCompactMenu(\n runtime: CodexCompactSettingsRuntime,\n ctx: ExtensionCommandContext,\n owner: SettingsMenuOwner,\n): Promise<void> {\n if (ctx.mode === \"rpc\" && ctx.hasUI) {\n ctx.ui.notify(`Edit Responses compaction settings at ${safeText(runtime.get().path)}.`, \"info\");\n return;\n }\n if (ctx.mode !== \"tui\") {\n throw new Error(\"/codex-compact requires TUI or RPC UI support\");\n }\n if (owner.signal.aborted || !owner.isCurrent()) return;\n let compactRequested = false;\n await runMenu(\n ctx,\n createCodexCompactMenu(runtime, {\n onCompactRequested: () => {\n compactRequested = true;\n },\n status: compactMenuStatus(ctx),\n }),\n {\n getState: () => runtime.get(),\n signal: owner.signal,\n isCurrent: owner.isCurrent,\n },\n );\n if (!compactRequested || owner.signal.aborted || !owner.isCurrent()) return;\n ctx.compact({\n onError: (error) => {\n if (!owner.signal.aborted && owner.isCurrent()) {\n ctx.ui.notify(`Compaction failed: ${safeText(error.message)}`, \"error\");\n }\n },\n });\n}\n\nexport function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {\n const model = ctx.model;\n return {\n model: model ? `${model.provider}/${model.id}` : \"none\",\n api: model?.api,\n };\n}\n\nfunction compactRoute(state: Readonly<CodexCompactSettingsState>, status: CompactMenuStatus | undefined): string {\n const route = resolveCompactionRouteForApi(status?.api, state.settings);\n if (route.kind === \"native\") return `Pi native (${route.reason})`;\n return route.protocol === \"remote-v2\" ? \"Responses Remote V2\" : \"Responses Compact API\";\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|