@narumitw/pi-codex-compact 0.52.0 → 0.53.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/src/remote-v2.ts CHANGED
@@ -1,70 +1,66 @@
1
1
  import {
2
- CodexCompactionProtocolError,
3
- type CollectedCompaction,
4
- collectCompactionSse,
5
- prepareRemoteCompactionPayload,
2
+ CodexCompactionProtocolError,
3
+ type CollectedCompaction,
4
+ collectCompactionSse,
5
+ prepareRemoteCompactionPayload,
6
6
  } from "./protocol.js";
7
7
  import { collectProviderUsage } from "./remote-shared.js";
8
8
  import {
9
- abortError,
10
- assertPreparedInput,
11
- type RemoteCompactionRequest,
12
- type RemoteCompactionResponse,
9
+ abortError,
10
+ assertPreparedInput,
11
+ type RemoteCompactionRequest,
12
+ type RemoteCompactionResponse,
13
13
  } from "./remote-types.js";
14
14
 
15
- export async function requestRemoteCompactionV2(
16
- request: RemoteCompactionRequest,
17
- ): Promise<RemoteCompactionResponse> {
18
- if (request.signal.aborted) throw abortError();
19
- let sentInput: ReturnType<typeof assertPreparedInput> | undefined;
20
- const inspections: Promise<
21
- { ok: true; value: CollectedCompaction } | { ok: false; error: unknown }
22
- >[] = [];
23
- const baseFetch = request.fetch ?? globalThis.fetch;
24
- const inspectedFetch: typeof globalThis.fetch = async (input, init) => {
25
- const response = await baseFetch(input, init);
26
- if (!response.ok || !response.body) return response;
27
- const [providerBody, inspectionBody] = response.body.tee();
28
- const inspection = collectCompactionSse(inspectionBody, { signal: request.signal }).then(
29
- (value) => ({ ok: true as const, value }),
30
- (error: unknown) => ({ ok: false as const, error }),
31
- );
32
- inspections.push(inspection);
33
- return new Response(providerBody, {
34
- status: response.status,
35
- statusText: response.statusText,
36
- headers: response.headers,
37
- });
38
- };
15
+ export async function requestRemoteCompactionV2(request: RemoteCompactionRequest): Promise<RemoteCompactionResponse> {
16
+ if (request.signal.aborted) throw abortError();
17
+ let sentInput: ReturnType<typeof assertPreparedInput> | undefined;
18
+ const inspections: Promise<{ ok: true; value: CollectedCompaction } | { ok: false; error: unknown }>[] = [];
19
+ const baseFetch = request.fetch ?? globalThis.fetch;
20
+ const inspectedFetch: typeof globalThis.fetch = async (input, init) => {
21
+ const response = await baseFetch(input, init);
22
+ if (!response.ok || !response.body) return response;
23
+ const [providerBody, inspectionBody] = response.body.tee();
24
+ const inspection = collectCompactionSse(inspectionBody, { signal: request.signal }).then(
25
+ (value) => ({ ok: true as const, value }),
26
+ (error: unknown) => ({ ok: false as const, error }),
27
+ );
28
+ inspections.push(inspection);
29
+ return new Response(providerBody, {
30
+ status: response.status,
31
+ statusText: response.statusText,
32
+ headers: response.headers,
33
+ });
34
+ };
39
35
 
40
- const stream = request.provider.stream(request.model, request.context, {
41
- apiKey: request.apiKey,
42
- headers: request.headers,
43
- env: request.env,
44
- signal: request.signal,
45
- transport: "sse",
46
- cacheRetention: "none",
47
- timeoutMs: request.requestTimeoutMs ?? 5 * 60 * 1000,
48
- maxRetries: request.maxRetries ?? 2,
49
- fetch: inspectedFetch,
50
- onPayload: (payload) => {
51
- const prepared = prepareRemoteCompactionPayload(payload, request.priorCheckpoint);
52
- sentInput = assertPreparedInput(prepared).slice(0, -1);
53
- return prepared;
54
- },
55
- });
36
+ const stream = request.provider.stream(request.model, request.context, {
37
+ apiKey: request.apiKey,
38
+ headers: request.headers,
39
+ env: request.env,
40
+ signal: request.signal,
41
+ transport: "sse",
42
+ cacheRetention: "none",
43
+ timeoutMs: request.requestTimeoutMs ?? 5 * 60 * 1000,
44
+ maxRetries: request.maxRetries ?? 2,
45
+ fetch: inspectedFetch,
46
+ onPayload: (payload) => {
47
+ const prepared = prepareRemoteCompactionPayload(payload, request.priorCheckpoint);
48
+ sentInput = assertPreparedInput(prepared).slice(0, -1);
49
+ return prepared;
50
+ },
51
+ });
56
52
 
57
- const usage = await collectProviderUsage(stream, request.signal);
58
- if (!sentInput) {
59
- throw new CodexCompactionProtocolError("Provider did not expose a request payload");
60
- }
61
- if (inspections.length !== 1) {
62
- throw new CodexCompactionProtocolError(
63
- `Provider exposed ${inspections.length} successful SSE responses; expected exactly one`,
64
- );
65
- }
66
- const inspection = await inspections[0];
67
- if (request.signal.aborted) throw abortError();
68
- if (!inspection.ok) throw inspection.error;
69
- return { item: inspection.value.item, promptInput: sentInput, usage };
53
+ const usage = await collectProviderUsage(stream, request.signal);
54
+ if (!sentInput) {
55
+ throw new CodexCompactionProtocolError("Provider did not expose a request payload");
56
+ }
57
+ if (inspections.length !== 1) {
58
+ throw new CodexCompactionProtocolError(
59
+ `Provider exposed ${inspections.length} successful SSE responses; expected exactly one`,
60
+ );
61
+ }
62
+ const inspection = await inspections[0];
63
+ if (request.signal.aborted) throw abortError();
64
+ if (!inspection.ok) throw inspection.error;
65
+ return { item: inspection.value.item, promptInput: sentInput, usage };
70
66
  }
package/src/remote.ts CHANGED
@@ -3,15 +3,13 @@ import type { RemoteCompactionRequest, RemoteCompactionResponse } from "./remote
3
3
  import { requestRemoteCompactionV2 } from "./remote-v2.js";
4
4
 
5
5
  export type {
6
- PriorCheckpointPayload,
7
- RemoteCompactionRequest,
8
- RemoteCompactionResponse,
6
+ PriorCheckpointPayload,
7
+ RemoteCompactionRequest,
8
+ RemoteCompactionResponse,
9
9
  } from "./remote-types.js";
10
10
 
11
- export function requestRemoteCompaction(
12
- request: RemoteCompactionRequest,
13
- ): Promise<RemoteCompactionResponse> {
14
- return request.protocol === "responses-compact"
15
- ? requestResponsesCompact(request)
16
- : requestRemoteCompactionV2(request);
11
+ export function requestRemoteCompaction(request: RemoteCompactionRequest): Promise<RemoteCompactionResponse> {
12
+ return request.protocol === "responses-compact"
13
+ ? requestResponsesCompact(request)
14
+ : requestRemoteCompactionV2(request);
17
15
  }
@@ -2,269 +2,246 @@ import type { Api } from "@earendil-works/pi-ai";
2
2
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
3
3
  import type { MenuDefinition } from "@narumitw/pi-tui-kit";
4
4
  import { resolveCompactionRouteForApi } from "./model-api.js";
5
- import type {
6
- CodexCompactSettings,
7
- CodexCompactSettingsRuntime,
8
- CodexCompactSettingsState,
9
- } from "./settings.js";
5
+ import type { CodexCompactSettings, CodexCompactSettingsRuntime, CodexCompactSettingsState } from "./settings.js";
10
6
  import { terminalText as safeText } from "./terminal.js";
11
7
 
12
8
  type Screen = "main" | "settings" | "invalid";
13
9
  type Action =
14
- | "compact-now"
15
- | "set-enabled"
16
- | "set-protocol"
17
- | "set-timeout"
18
- | "set-retries"
19
- | "set-retention"
20
- | "set-notify";
10
+ | "compact-now"
11
+ | "set-enabled"
12
+ | "set-protocol"
13
+ | "set-timeout"
14
+ | "set-retries"
15
+ | "set-retention"
16
+ | "set-notify";
21
17
 
22
18
  export interface SettingsMenuOwner {
23
- signal: AbortSignal;
24
- isCurrent(): boolean;
19
+ signal: AbortSignal;
20
+ isCurrent(): boolean;
25
21
  }
26
22
 
27
23
  interface CompactMenuStatus {
28
- model: string;
29
- api?: Api;
24
+ model: string;
25
+ api?: Api;
30
26
  }
31
27
 
32
28
  function timeoutLabel(milliseconds: number): string {
33
- return `${milliseconds / 60_000} min`;
29
+ return `${milliseconds / 60_000} min`;
34
30
  }
35
31
 
36
32
  function retentionLabel(tokens: number): string {
37
- return `${tokens / 1000}K tokens`;
33
+ return `${tokens / 1000}K tokens`;
38
34
  }
39
35
 
40
36
  function protocolLabel(protocol: CodexCompactSettings["protocol"]): string {
41
- switch (protocol) {
42
- case "auto":
43
- return "Auto";
44
- case "remote-v2":
45
- return "Remote V2";
46
- case "responses-compact":
47
- return "Responses Compact";
48
- }
37
+ switch (protocol) {
38
+ case "auto":
39
+ return "Auto";
40
+ case "remote-v2":
41
+ return "Remote V2";
42
+ case "responses-compact":
43
+ return "Responses Compact";
44
+ }
49
45
  }
50
46
 
51
47
  async function update(
52
- runtime: CodexCompactSettingsRuntime,
53
- ctx: ExtensionCommandContext,
54
- patch: Partial<CodexCompactSettings>,
55
- signal: AbortSignal,
48
+ runtime: CodexCompactSettingsRuntime,
49
+ ctx: ExtensionCommandContext,
50
+ patch: Partial<CodexCompactSettings>,
51
+ signal: AbortSignal,
56
52
  ) {
57
- try {
58
- await runtime.update(patch, signal);
59
- if (signal.aborted) return { kind: "rejected" as const };
60
- ctx.ui.notify("Responses compaction settings saved.", "info");
61
- return { kind: "stay" as const };
62
- } catch (error) {
63
- if (signal.aborted) return { kind: "rejected" as const };
64
- ctx.ui.notify(
65
- `Could not save pi-codex-compact.json: ${safeText(error instanceof Error ? error.message : String(error))}`,
66
- "error",
67
- );
68
- return { kind: "rejected" as const };
69
- }
53
+ try {
54
+ await runtime.update(patch, signal);
55
+ if (signal.aborted) return { kind: "rejected" as const };
56
+ ctx.ui.notify("Responses compaction settings saved.", "info");
57
+ return { kind: "stay" as const };
58
+ } catch (error) {
59
+ if (signal.aborted) return { kind: "rejected" as const };
60
+ ctx.ui.notify(
61
+ `Could not save pi-codex-compact.json: ${safeText(error instanceof Error ? error.message : String(error))}`,
62
+ "error",
63
+ );
64
+ return { kind: "rejected" as const };
65
+ }
70
66
  }
71
67
 
72
68
  export function createCodexCompactMenu(
73
- runtime: CodexCompactSettingsRuntime,
74
- options: { onCompactRequested?: () => void; status?: CompactMenuStatus } = {},
69
+ runtime: CodexCompactSettingsRuntime,
70
+ options: { onCompactRequested?: () => void; status?: CompactMenuStatus } = {},
75
71
  ): MenuDefinition<CodexCompactSettingsState, Screen, Action, ExtensionCommandContext> {
76
- return {
77
- start: "main",
78
- screens: {
79
- main: ({ state }) => ({
80
- kind: "actions",
81
- title: "Responses Compaction",
82
- lines: [
83
- `Remote compaction: ${state.settings.enabled ? "On" : "Off"}`,
84
- `Protocol setting: ${protocolLabel(state.settings.protocol)}`,
85
- `Active model: ${safeText(options.status?.model ?? "none")}`,
86
- `Compact route: ${safeText(compactRoute(state, options.status))}`,
87
- ],
88
- items: [
89
- {
90
- id: "compact-now",
91
- label: "Compact now",
92
- description: "Close this menu and compact the active session immediately.",
93
- action: "compact-now",
94
- },
95
- state.kind === "invalid"
96
- ? {
97
- id: "settings",
98
- label: "Settings",
99
- description: "Read-only until the invalid settings file is repaired.",
100
- to: "invalid" as const,
101
- }
102
- : { id: "settings", label: "Settings", to: "settings" as const },
103
- { id: "close", label: "Close", close: true },
104
- ],
105
- hint: "close",
106
- }),
107
- settings: ({ state }) => ({
108
- kind: "settings",
109
- title: "Responses Compaction Settings",
110
- lines: [`User settings · ${safeText(state.path)}`],
111
- items: [
112
- {
113
- id: "enabled",
114
- label: "Remote compaction",
115
- description: "Use a supported Responses compaction protocol.",
116
- currentValue: state.settings.enabled ? "On" : "Off",
117
- values: ["On", "Off"],
118
- action: "set-enabled",
119
- },
120
- {
121
- id: "protocol",
122
- label: "Protocol",
123
- description: "Choose automatically or force one supported remote protocol.",
124
- currentValue: protocolLabel(state.settings.protocol),
125
- values: ["Auto", "Remote V2", "Responses Compact"],
126
- action: "set-protocol",
127
- },
128
- {
129
- id: "requestTimeoutMs",
130
- label: "Request timeout",
131
- description: "Maximum time for the extension-owned remote compaction request.",
132
- currentValue: timeoutLabel(state.settings.requestTimeoutMs),
133
- values: ["2 min", "5 min", "10 min"],
134
- action: "set-timeout",
135
- },
136
- {
137
- id: "maxRetries",
138
- label: "Transport retries",
139
- description: "Retry transient provider failures before falling back to Pi.",
140
- currentValue: String(state.settings.maxRetries),
141
- values: ["0", "1", "2"],
142
- action: "set-retries",
143
- },
144
- {
145
- id: "replacementTokenBudget",
146
- label: "Retained user history",
147
- description: "Approximate user-message budget kept beside the opaque checkpoint.",
148
- currentValue: retentionLabel(state.settings.replacementTokenBudget),
149
- values: ["32K tokens", "64K tokens", "96K tokens", "128K tokens"],
150
- action: "set-retention",
151
- },
152
- {
153
- id: "notifyOnFallback",
154
- label: "Fallback notifications",
155
- description: "Warn when remote compaction fails and Pi native takes over.",
156
- currentValue: state.settings.notifyOnFallback ? "On" : "Off",
157
- values: ["On", "Off"],
158
- action: "set-notify",
159
- },
160
- ],
161
- }),
162
- invalid: ({ state }) => ({
163
- kind: "detail",
164
- title: "Codex Compact Settings · Read only",
165
- lines: [
166
- `Invalid settings file: ${safeText(state.path)}`,
167
- `Issue: ${safeText(state.issue ?? "unknown validation error")}`,
168
- "Built-in defaults are active. Repair the file and run /reload; it will not be overwritten.",
169
- ],
170
- hint: "back",
171
- }),
172
- },
173
- actions: {
174
- "compact-now": async () => {
175
- options.onCompactRequested?.();
176
- return { kind: "close" };
177
- },
178
- "set-enabled": ({ ctx, value, signal }) =>
179
- update(runtime, ctx, { enabled: value === "On" }, signal),
180
- "set-protocol": ({ ctx, value, signal }) =>
181
- update(
182
- runtime,
183
- ctx,
184
- {
185
- protocol:
186
- value === "Remote V2"
187
- ? "remote-v2"
188
- : value === "Responses Compact"
189
- ? "responses-compact"
190
- : "auto",
191
- },
192
- signal,
193
- ),
194
- "set-timeout": ({ ctx, value, signal }) =>
195
- update(
196
- runtime,
197
- ctx,
198
- { requestTimeoutMs: Number.parseInt(value ?? "5", 10) * 60_000 },
199
- signal,
200
- ),
201
- "set-retries": ({ ctx, value, signal }) =>
202
- update(runtime, ctx, { maxRetries: Number.parseInt(value ?? "2", 10) }, signal),
203
- "set-retention": ({ ctx, value, signal }) =>
204
- update(
205
- runtime,
206
- ctx,
207
- { replacementTokenBudget: Number.parseInt(value ?? "64", 10) * 1000 },
208
- signal,
209
- ),
210
- "set-notify": ({ ctx, value, signal }) =>
211
- update(runtime, ctx, { notifyOnFallback: value === "On" }, signal),
212
- },
213
- };
72
+ return {
73
+ start: "main",
74
+ screens: {
75
+ main: ({ state }) => ({
76
+ kind: "actions",
77
+ title: "Responses Compaction",
78
+ lines: [
79
+ `Remote compaction: ${state.settings.enabled ? "On" : "Off"}`,
80
+ `Protocol setting: ${protocolLabel(state.settings.protocol)}`,
81
+ `Active model: ${safeText(options.status?.model ?? "none")}`,
82
+ `Compact route: ${safeText(compactRoute(state, options.status))}`,
83
+ ],
84
+ items: [
85
+ {
86
+ id: "compact-now",
87
+ label: "Compact now",
88
+ description: "Close this menu and compact the active session immediately.",
89
+ action: "compact-now",
90
+ },
91
+ state.kind === "invalid"
92
+ ? {
93
+ id: "settings",
94
+ label: "Settings",
95
+ description: "Read-only until the invalid settings file is repaired.",
96
+ to: "invalid" as const,
97
+ }
98
+ : { id: "settings", label: "Settings", to: "settings" as const },
99
+ { id: "close", label: "Close", close: true },
100
+ ],
101
+ hint: "close",
102
+ }),
103
+ settings: ({ state }) => ({
104
+ kind: "settings",
105
+ title: "Responses Compaction Settings",
106
+ lines: [`User settings · ${safeText(state.path)}`],
107
+ items: [
108
+ {
109
+ id: "enabled",
110
+ label: "Remote compaction",
111
+ description: "Use a supported Responses compaction protocol.",
112
+ currentValue: state.settings.enabled ? "On" : "Off",
113
+ values: ["On", "Off"],
114
+ action: "set-enabled",
115
+ },
116
+ {
117
+ id: "protocol",
118
+ label: "Protocol",
119
+ description: "Choose automatically or force one supported remote protocol.",
120
+ currentValue: protocolLabel(state.settings.protocol),
121
+ values: ["Auto", "Remote V2", "Responses Compact"],
122
+ action: "set-protocol",
123
+ },
124
+ {
125
+ id: "requestTimeoutMs",
126
+ label: "Request timeout",
127
+ description: "Maximum time for the extension-owned remote compaction request.",
128
+ currentValue: timeoutLabel(state.settings.requestTimeoutMs),
129
+ values: ["2 min", "5 min", "10 min"],
130
+ action: "set-timeout",
131
+ },
132
+ {
133
+ id: "maxRetries",
134
+ label: "Transport retries",
135
+ description: "Retry transient provider failures before falling back to Pi.",
136
+ currentValue: String(state.settings.maxRetries),
137
+ values: ["0", "1", "2"],
138
+ action: "set-retries",
139
+ },
140
+ {
141
+ id: "replacementTokenBudget",
142
+ label: "Retained user history",
143
+ description: "Approximate user-message budget kept beside the opaque checkpoint.",
144
+ currentValue: retentionLabel(state.settings.replacementTokenBudget),
145
+ values: ["32K tokens", "64K tokens", "96K tokens", "128K tokens"],
146
+ action: "set-retention",
147
+ },
148
+ {
149
+ id: "notifyOnFallback",
150
+ label: "Fallback notifications",
151
+ description: "Warn when remote compaction fails and Pi native takes over.",
152
+ currentValue: state.settings.notifyOnFallback ? "On" : "Off",
153
+ values: ["On", "Off"],
154
+ action: "set-notify",
155
+ },
156
+ ],
157
+ }),
158
+ invalid: ({ state }) => ({
159
+ kind: "detail",
160
+ title: "Codex Compact Settings · Read only",
161
+ lines: [
162
+ `Invalid settings file: ${safeText(state.path)}`,
163
+ `Issue: ${safeText(state.issue ?? "unknown validation error")}`,
164
+ "Built-in defaults are active. Repair the file and run /reload; it will not be overwritten.",
165
+ ],
166
+ hint: "back",
167
+ }),
168
+ },
169
+ actions: {
170
+ "compact-now": async () => {
171
+ options.onCompactRequested?.();
172
+ return { kind: "close" };
173
+ },
174
+ "set-enabled": ({ ctx, value, signal }) => update(runtime, ctx, { enabled: value === "On" }, signal),
175
+ "set-protocol": ({ ctx, value, signal }) =>
176
+ update(
177
+ runtime,
178
+ ctx,
179
+ {
180
+ protocol:
181
+ value === "Remote V2" ? "remote-v2" : value === "Responses Compact" ? "responses-compact" : "auto",
182
+ },
183
+ signal,
184
+ ),
185
+ "set-timeout": ({ ctx, value, signal }) =>
186
+ update(runtime, ctx, { requestTimeoutMs: Number.parseInt(value ?? "5", 10) * 60_000 }, signal),
187
+ "set-retries": ({ ctx, value, signal }) =>
188
+ update(runtime, ctx, { maxRetries: Number.parseInt(value ?? "2", 10) }, signal),
189
+ "set-retention": ({ ctx, value, signal }) =>
190
+ update(runtime, ctx, { replacementTokenBudget: Number.parseInt(value ?? "64", 10) * 1000 }, signal),
191
+ "set-notify": ({ ctx, value, signal }) => update(runtime, ctx, { notifyOnFallback: value === "On" }, signal),
192
+ },
193
+ };
214
194
  }
215
195
 
216
196
  export async function showCodexCompactMenu(
217
- runtime: CodexCompactSettingsRuntime,
218
- ctx: ExtensionCommandContext,
219
- owner: SettingsMenuOwner,
197
+ runtime: CodexCompactSettingsRuntime,
198
+ ctx: ExtensionCommandContext,
199
+ owner: SettingsMenuOwner,
220
200
  ): Promise<void> {
221
- if (ctx.mode === "rpc" && ctx.hasUI) {
222
- ctx.ui.notify(`Edit Responses compaction settings at ${safeText(runtime.get().path)}.`, "info");
223
- return;
224
- }
225
- if (ctx.mode !== "tui") {
226
- throw new Error("/codex-compact requires TUI or RPC UI support");
227
- }
228
- const { runMenu } = await import("@narumitw/pi-tui-kit");
229
- if (owner.signal.aborted || !owner.isCurrent()) return;
230
- let compactRequested = false;
231
- await runMenu(
232
- ctx,
233
- createCodexCompactMenu(runtime, {
234
- onCompactRequested: () => {
235
- compactRequested = true;
236
- },
237
- status: compactMenuStatus(ctx),
238
- }),
239
- {
240
- getState: () => runtime.get(),
241
- signal: owner.signal,
242
- isCurrent: owner.isCurrent,
243
- },
244
- );
245
- if (!compactRequested || owner.signal.aborted || !owner.isCurrent()) return;
246
- ctx.compact({
247
- onError: (error) => {
248
- if (!owner.signal.aborted && owner.isCurrent()) {
249
- ctx.ui.notify(`Compaction failed: ${safeText(error.message)}`, "error");
250
- }
251
- },
252
- });
201
+ if (ctx.mode === "rpc" && ctx.hasUI) {
202
+ ctx.ui.notify(`Edit Responses compaction settings at ${safeText(runtime.get().path)}.`, "info");
203
+ return;
204
+ }
205
+ if (ctx.mode !== "tui") {
206
+ throw new Error("/codex-compact requires TUI or RPC UI support");
207
+ }
208
+ const { runMenu } = await import("@narumitw/pi-tui-kit");
209
+ if (owner.signal.aborted || !owner.isCurrent()) return;
210
+ let compactRequested = false;
211
+ await runMenu(
212
+ ctx,
213
+ createCodexCompactMenu(runtime, {
214
+ onCompactRequested: () => {
215
+ compactRequested = true;
216
+ },
217
+ status: compactMenuStatus(ctx),
218
+ }),
219
+ {
220
+ getState: () => runtime.get(),
221
+ signal: owner.signal,
222
+ isCurrent: owner.isCurrent,
223
+ },
224
+ );
225
+ if (!compactRequested || owner.signal.aborted || !owner.isCurrent()) return;
226
+ ctx.compact({
227
+ onError: (error) => {
228
+ if (!owner.signal.aborted && owner.isCurrent()) {
229
+ ctx.ui.notify(`Compaction failed: ${safeText(error.message)}`, "error");
230
+ }
231
+ },
232
+ });
253
233
  }
254
234
 
255
235
  export function compactMenuStatus(ctx: ExtensionCommandContext): CompactMenuStatus {
256
- const model = ctx.model;
257
- return {
258
- model: model ? `${model.provider}/${model.id}` : "none",
259
- api: model?.api,
260
- };
236
+ const model = ctx.model;
237
+ return {
238
+ model: model ? `${model.provider}/${model.id}` : "none",
239
+ api: model?.api,
240
+ };
261
241
  }
262
242
 
263
- function compactRoute(
264
- state: Readonly<CodexCompactSettingsState>,
265
- status: CompactMenuStatus | undefined,
266
- ): string {
267
- const route = resolveCompactionRouteForApi(status?.api, state.settings);
268
- if (route.kind === "native") return `Pi native (${route.reason})`;
269
- return route.protocol === "remote-v2" ? "Responses Remote V2" : "Responses Compact API";
243
+ function compactRoute(state: Readonly<CodexCompactSettingsState>, status: CompactMenuStatus | undefined): string {
244
+ const route = resolveCompactionRouteForApi(status?.api, state.settings);
245
+ if (route.kind === "native") return `Pi native (${route.reason})`;
246
+ return route.protocol === "remote-v2" ? "Responses Remote V2" : "Responses Compact API";
270
247
  }