pi-openai-codex-compat 0.0.6 → 0.0.7
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/APPLY_PATCH_INSTRUCTION_FEEDBACK.md +617 -0
- package/CHANGELOG.md +44 -0
- package/LICENSES/tree-sitter-wasms-MIT.txt +21 -0
- package/LICENSES/web-tree-sitter-MIT.txt +21 -0
- package/README.md +37 -9
- package/THIRD_PARTY_NOTICES.md +26 -0
- package/extensions/openai-codex-compat/apply-patch-diff-render.ts +499 -20
- package/extensions/openai-codex-compat/apply-patch-engine.ts +4085 -491
- package/extensions/openai-codex-compat/apply-patch-matcher.ts +1535 -0
- package/extensions/openai-codex-compat/apply-patch-render.ts +85 -19
- package/extensions/openai-codex-compat/apply-patch.ts +41 -5
- package/extensions/openai-codex-compat/codex-provider.ts +252 -14
- package/extensions/openai-codex-compat/codex-stream.ts +78 -61
- package/extensions/openai-codex-compat/compaction-checkpoint.ts +28 -0
- package/extensions/openai-codex-compat/config.ts +18 -0
- package/extensions/openai-codex-compat/footer.ts +4 -8
- package/extensions/openai-codex-compat/index.ts +4 -1
- package/extensions/openai-codex-compat/remote-compaction.ts +4 -0
- package/extensions/openai-codex-compat/settings-pane.ts +11 -0
- package/extensions/openai-codex-compat/tools.ts +2 -1
- package/package.json +10 -4
|
@@ -209,6 +209,7 @@ export async function processCodexStream(
|
|
|
209
209
|
): Promise<void> {
|
|
210
210
|
let terminal = false;
|
|
211
211
|
const slots = new Map<number, OutputSlot>();
|
|
212
|
+
const completedOutputItems = new Set<string>();
|
|
212
213
|
const reasoningById = new Map<string, ThinkingContent>();
|
|
213
214
|
const applyMessagePhaseStopReason = (item: JsonRecord): void => {
|
|
214
215
|
if (item.type === "message" && item["phase"] === "final_answer") {
|
|
@@ -318,6 +319,79 @@ export async function processCodexStream(
|
|
|
318
319
|
const slotFor = (index: number, item: JsonRecord): OutputSlot | undefined =>
|
|
319
320
|
slots.get(index) ?? createSlot(index, item);
|
|
320
321
|
|
|
322
|
+
const outputItemKey = (index: number, item: JsonRecord): string => {
|
|
323
|
+
if (typeof item.id === "string") return `id:${item.id}`;
|
|
324
|
+
if (typeof item["call_id"] === "string") {
|
|
325
|
+
return `call:${String(item.type)}:${item["call_id"]}`;
|
|
326
|
+
}
|
|
327
|
+
return `index:${String(index)}:${String(item.type)}`;
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
const completeOutputItem = (index: number, item: JsonRecord): void => {
|
|
331
|
+
const key = outputItemKey(index, item);
|
|
332
|
+
if (completedOutputItems.has(key)) return;
|
|
333
|
+
completedOutputItems.add(key);
|
|
334
|
+
applyMessagePhaseStopReason(item);
|
|
335
|
+
const slot = slotFor(index, item);
|
|
336
|
+
if (item.type === "reasoning" && slot?.type === "thinking") {
|
|
337
|
+
slot.block.thinking = reasoningText(item) || slot.block.thinking;
|
|
338
|
+
slot.block.thinkingSignature = JSON.stringify(item);
|
|
339
|
+
if (typeof item.id === "string") reasoningById.set(item.id, slot.block);
|
|
340
|
+
stream.push({
|
|
341
|
+
type: "thinking_end",
|
|
342
|
+
contentIndex: slot.contentIndex,
|
|
343
|
+
content: slot.block.thinking,
|
|
344
|
+
partial: output,
|
|
345
|
+
});
|
|
346
|
+
trackCompleted(slot);
|
|
347
|
+
slots.delete(index);
|
|
348
|
+
} else if (item.type === "message" && slot?.type === "text") {
|
|
349
|
+
slot.block.text = itemContentText(item);
|
|
350
|
+
if (typeof item.id === "string") {
|
|
351
|
+
slot.block.textSignature = encodeTextSignature(item.id, item["phase"]);
|
|
352
|
+
}
|
|
353
|
+
stream.push({
|
|
354
|
+
type: "text_end",
|
|
355
|
+
contentIndex: slot.contentIndex,
|
|
356
|
+
content: slot.block.text,
|
|
357
|
+
partial: output,
|
|
358
|
+
});
|
|
359
|
+
trackCompleted(slot);
|
|
360
|
+
slots.delete(index);
|
|
361
|
+
} else if (
|
|
362
|
+
item.type === "function_call" &&
|
|
363
|
+
slot?.type === "toolCall" &&
|
|
364
|
+
slot.block.partialJson !== undefined
|
|
365
|
+
) {
|
|
366
|
+
slot.block.name = piToolCallName(item);
|
|
367
|
+
const argumentsJson =
|
|
368
|
+
typeof item.arguments === "string" ? item.arguments : slot.block.partialJson || "{}";
|
|
369
|
+
slot.block.arguments = parseStreamingJson(argumentsJson);
|
|
370
|
+
delete slot.block.partialJson;
|
|
371
|
+
stream.push({
|
|
372
|
+
type: "toolcall_end",
|
|
373
|
+
contentIndex: slot.contentIndex,
|
|
374
|
+
toolCall: slot.block,
|
|
375
|
+
partial: output,
|
|
376
|
+
});
|
|
377
|
+
trackCompleted(slot);
|
|
378
|
+
slots.delete(index);
|
|
379
|
+
} else if (item.type === "custom_tool_call" && slot?.type === "toolCall") {
|
|
380
|
+
slot.block.name = piToolCallName(item);
|
|
381
|
+
const input = typeof item["input"] === "string" ? item["input"] : customInput(slot.block);
|
|
382
|
+
pushToolDelta(slot, appendCustomInput(slot.block, input, true));
|
|
383
|
+
delete slot.block.customInput;
|
|
384
|
+
stream.push({
|
|
385
|
+
type: "toolcall_end",
|
|
386
|
+
contentIndex: slot.contentIndex,
|
|
387
|
+
toolCall: slot.block,
|
|
388
|
+
partial: output,
|
|
389
|
+
});
|
|
390
|
+
trackCompleted(slot);
|
|
391
|
+
slots.delete(index);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
|
|
321
395
|
const finalize = (response: JsonRecord): void => {
|
|
322
396
|
terminal = true;
|
|
323
397
|
if (typeof response.id === "string") output.responseId = response.id;
|
|
@@ -350,7 +424,9 @@ export async function processCodexStream(
|
|
|
350
424
|
output.usage,
|
|
351
425
|
typeof response.service_tier === "string" ? response.service_tier : undefined,
|
|
352
426
|
);
|
|
353
|
-
|
|
427
|
+
const terminalItems = responseItems(response["output"]);
|
|
428
|
+
terminalItems.forEach((item, index) => completeOutputItem(index, item));
|
|
429
|
+
for (const item of terminalItems) {
|
|
354
430
|
if (item.type !== "reasoning" || typeof item.id !== "string") continue;
|
|
355
431
|
const block = reasoningById.get(item.id);
|
|
356
432
|
if (!block?.thinkingSignature || typeof item.encrypted_content !== "string") continue;
|
|
@@ -455,66 +531,7 @@ export async function processCodexStream(
|
|
|
455
531
|
if (!slot || typeof event["input"] !== "string") continue;
|
|
456
532
|
pushToolDelta(slot, appendCustomInput(slot.block, event["input"], true));
|
|
457
533
|
} else if (event.type === "response.output_item.done" && isObject(event.item)) {
|
|
458
|
-
|
|
459
|
-
applyMessagePhaseStopReason(item);
|
|
460
|
-
const slot = slotFor(index, item);
|
|
461
|
-
if (item.type === "reasoning" && slot?.type === "thinking") {
|
|
462
|
-
slot.block.thinking = reasoningText(item) || slot.block.thinking;
|
|
463
|
-
slot.block.thinkingSignature = JSON.stringify(item);
|
|
464
|
-
if (typeof item.id === "string") reasoningById.set(item.id, slot.block);
|
|
465
|
-
stream.push({
|
|
466
|
-
type: "thinking_end",
|
|
467
|
-
contentIndex: slot.contentIndex,
|
|
468
|
-
content: slot.block.thinking,
|
|
469
|
-
partial: output,
|
|
470
|
-
});
|
|
471
|
-
trackCompleted(slot);
|
|
472
|
-
slots.delete(index);
|
|
473
|
-
} else if (item.type === "message" && slot?.type === "text") {
|
|
474
|
-
slot.block.text = itemContentText(item);
|
|
475
|
-
if (typeof item.id === "string") {
|
|
476
|
-
slot.block.textSignature = encodeTextSignature(item.id, item["phase"]);
|
|
477
|
-
}
|
|
478
|
-
stream.push({
|
|
479
|
-
type: "text_end",
|
|
480
|
-
contentIndex: slot.contentIndex,
|
|
481
|
-
content: slot.block.text,
|
|
482
|
-
partial: output,
|
|
483
|
-
});
|
|
484
|
-
trackCompleted(slot);
|
|
485
|
-
slots.delete(index);
|
|
486
|
-
} else if (
|
|
487
|
-
item.type === "function_call" &&
|
|
488
|
-
slot?.type === "toolCall" &&
|
|
489
|
-
slot.block.partialJson !== undefined
|
|
490
|
-
) {
|
|
491
|
-
slot.block.name = piToolCallName(item);
|
|
492
|
-
const argumentsJson =
|
|
493
|
-
typeof item.arguments === "string" ? item.arguments : slot.block.partialJson || "{}";
|
|
494
|
-
slot.block.arguments = parseStreamingJson(argumentsJson);
|
|
495
|
-
delete slot.block.partialJson;
|
|
496
|
-
stream.push({
|
|
497
|
-
type: "toolcall_end",
|
|
498
|
-
contentIndex: slot.contentIndex,
|
|
499
|
-
toolCall: slot.block,
|
|
500
|
-
partial: output,
|
|
501
|
-
});
|
|
502
|
-
trackCompleted(slot);
|
|
503
|
-
slots.delete(index);
|
|
504
|
-
} else if (item.type === "custom_tool_call" && slot?.type === "toolCall") {
|
|
505
|
-
slot.block.name = piToolCallName(item);
|
|
506
|
-
const input = typeof item["input"] === "string" ? item["input"] : customInput(slot.block);
|
|
507
|
-
pushToolDelta(slot, appendCustomInput(slot.block, input, true));
|
|
508
|
-
delete slot.block.customInput;
|
|
509
|
-
stream.push({
|
|
510
|
-
type: "toolcall_end",
|
|
511
|
-
contentIndex: slot.contentIndex,
|
|
512
|
-
toolCall: slot.block,
|
|
513
|
-
partial: output,
|
|
514
|
-
});
|
|
515
|
-
trackCompleted(slot);
|
|
516
|
-
slots.delete(index);
|
|
517
|
-
}
|
|
534
|
+
completeOutputItem(index, event.item);
|
|
518
535
|
} else if (
|
|
519
536
|
(event.type === "response.completed" || event.type === "response.incomplete") &&
|
|
520
537
|
isObject(event.response)
|
|
@@ -25,11 +25,17 @@ import { convertResponsesMessages } from "./vendor/pi-ai/openai-responses-serial
|
|
|
25
25
|
export const CHECKPOINT_ENTRY_TYPE = "openai-codex-compat-remote-compaction";
|
|
26
26
|
export const CHECKPOINT_FORMAT_VERSION = 1;
|
|
27
27
|
|
|
28
|
+
export type CompactionDecision = {
|
|
29
|
+
reason: "manual" | "threshold" | "overflow" | "provider-boundary";
|
|
30
|
+
willRetry: boolean;
|
|
31
|
+
};
|
|
32
|
+
|
|
28
33
|
export type CheckpointData = {
|
|
29
34
|
kind: typeof CHECKPOINT_ENTRY_TYPE;
|
|
30
35
|
version: typeof CHECKPOINT_FORMAT_VERSION;
|
|
31
36
|
modelId: string;
|
|
32
37
|
history: ResponsesItem[];
|
|
38
|
+
compactionDecision?: CompactionDecision;
|
|
33
39
|
};
|
|
34
40
|
|
|
35
41
|
export type CheckpointSearch =
|
|
@@ -180,11 +186,31 @@ export function parseCheckpoint(value: unknown): CheckpointData | undefined {
|
|
|
180
186
|
return undefined;
|
|
181
187
|
}
|
|
182
188
|
|
|
189
|
+
const rawDecision = value["compactionDecision"];
|
|
190
|
+
let compactionDecision: CompactionDecision | undefined;
|
|
191
|
+
if (rawDecision !== undefined) {
|
|
192
|
+
if (
|
|
193
|
+
!isObject(rawDecision) ||
|
|
194
|
+
(rawDecision["reason"] !== "manual" &&
|
|
195
|
+
rawDecision["reason"] !== "threshold" &&
|
|
196
|
+
rawDecision["reason"] !== "overflow" &&
|
|
197
|
+
rawDecision["reason"] !== "provider-boundary") ||
|
|
198
|
+
typeof rawDecision["willRetry"] !== "boolean"
|
|
199
|
+
) {
|
|
200
|
+
return undefined;
|
|
201
|
+
}
|
|
202
|
+
compactionDecision = {
|
|
203
|
+
reason: rawDecision["reason"],
|
|
204
|
+
willRetry: rawDecision["willRetry"],
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
183
208
|
return {
|
|
184
209
|
kind: CHECKPOINT_ENTRY_TYPE,
|
|
185
210
|
version: CHECKPOINT_FORMAT_VERSION,
|
|
186
211
|
modelId: value.modelId,
|
|
187
212
|
history,
|
|
213
|
+
...(compactionDecision ? { compactionDecision } : {}),
|
|
188
214
|
};
|
|
189
215
|
}
|
|
190
216
|
|
|
@@ -229,6 +255,7 @@ export function checkpointData(
|
|
|
229
255
|
inputHistory: readonly ResponsesItem[],
|
|
230
256
|
compactionItem: ResponsesItem,
|
|
231
257
|
postCompactionTail: readonly ResponsesItem[] = [],
|
|
258
|
+
compactionDecision?: CompactionDecision,
|
|
232
259
|
): CheckpointData {
|
|
233
260
|
return {
|
|
234
261
|
kind: CHECKPOINT_ENTRY_TYPE,
|
|
@@ -238,6 +265,7 @@ export function checkpointData(
|
|
|
238
265
|
...installCompactionItem(inputHistory, compactionItem),
|
|
239
266
|
...postCompactionTail.map((item) => structuredClone(item)),
|
|
240
267
|
],
|
|
268
|
+
...(compactionDecision ? { compactionDecision: { ...compactionDecision } } : {}),
|
|
241
269
|
};
|
|
242
270
|
}
|
|
243
271
|
|
|
@@ -20,6 +20,8 @@ export interface CodexCompatConfig {
|
|
|
20
20
|
responsesLite: boolean;
|
|
21
21
|
/** Replace Pi's active edit and write tools with the extension's apply_patch tool. */
|
|
22
22
|
applyPatch: boolean;
|
|
23
|
+
/** Show exact model-facing apply_patch feedback while its TUI result is collapsed. */
|
|
24
|
+
applyPatchDebug: boolean;
|
|
23
25
|
/** Select the shared background surface for extension-owned Codex tools. */
|
|
24
26
|
toolBackground: CodexToolBackground;
|
|
25
27
|
/** Expose the standalone Codex image-generation namespace tool. */
|
|
@@ -44,6 +46,7 @@ export const CONFIG_ENVIRONMENT_VARIABLES = {
|
|
|
44
46
|
fastMode: `${ENV_PREFIX}FAST_MODE`,
|
|
45
47
|
responsesLite: `${ENV_PREFIX}RESPONSES_LITE`,
|
|
46
48
|
applyPatch: `${ENV_PREFIX}APPLY_PATCH`,
|
|
49
|
+
applyPatchDebug: `${ENV_PREFIX}APPLY_PATCH_DEBUG`,
|
|
47
50
|
toolBackground: `${ENV_PREFIX}TOOL_BACKGROUND`,
|
|
48
51
|
imageGeneration: `${ENV_PREFIX}IMAGE_GENERATION`,
|
|
49
52
|
imageDetail: `${ENV_PREFIX}IMAGE_DETAIL`,
|
|
@@ -59,6 +62,7 @@ export type ConfigLayer = {
|
|
|
59
62
|
fastMode?: boolean;
|
|
60
63
|
responsesLite?: boolean;
|
|
61
64
|
applyPatch?: boolean;
|
|
65
|
+
applyPatchDebug?: boolean;
|
|
62
66
|
toolBackground?: CodexToolBackground;
|
|
63
67
|
imageGeneration?: boolean;
|
|
64
68
|
imageDetail?: ImageDetail;
|
|
@@ -75,6 +79,7 @@ export const DEFAULT_CONFIG: CodexCompatConfig = {
|
|
|
75
79
|
fastMode: false,
|
|
76
80
|
responsesLite: false,
|
|
77
81
|
applyPatch: true,
|
|
82
|
+
applyPatchDebug: false,
|
|
78
83
|
toolBackground: "subtle",
|
|
79
84
|
imageGeneration: true,
|
|
80
85
|
imageDetail: "auto",
|
|
@@ -152,6 +157,12 @@ export function parseEnvironmentConfig(environment: Environment = process.env):
|
|
|
152
157
|
const applyPatch = environmentBoolean(environment, CONFIG_ENVIRONMENT_VARIABLES.applyPatch);
|
|
153
158
|
if (applyPatch !== undefined) layer.applyPatch = applyPatch;
|
|
154
159
|
|
|
160
|
+
const applyPatchDebug = environmentBoolean(
|
|
161
|
+
environment,
|
|
162
|
+
CONFIG_ENVIRONMENT_VARIABLES.applyPatchDebug,
|
|
163
|
+
);
|
|
164
|
+
if (applyPatchDebug !== undefined) layer.applyPatchDebug = applyPatchDebug;
|
|
165
|
+
|
|
155
166
|
const toolBackground = environmentEnum(
|
|
156
167
|
environment,
|
|
157
168
|
CONFIG_ENVIRONMENT_VARIABLES.toolBackground,
|
|
@@ -239,6 +250,9 @@ export function parseConfig(value: unknown): ConfigLayer {
|
|
|
239
250
|
const applyPatch = value["applyPatch"];
|
|
240
251
|
if (typeof applyPatch === "boolean") layer.applyPatch = applyPatch;
|
|
241
252
|
|
|
253
|
+
const applyPatchDebug = value["applyPatchDebug"];
|
|
254
|
+
if (typeof applyPatchDebug === "boolean") layer.applyPatchDebug = applyPatchDebug;
|
|
255
|
+
|
|
242
256
|
const toolBackground = value["toolBackground"];
|
|
243
257
|
if (
|
|
244
258
|
typeof toolBackground === "string" &&
|
|
@@ -318,6 +332,9 @@ export function resolveConfig(
|
|
|
318
332
|
...(typeof merged.fastMode === "boolean" ? { fastMode: merged.fastMode } : {}),
|
|
319
333
|
...(typeof merged.responsesLite === "boolean" ? { responsesLite: merged.responsesLite } : {}),
|
|
320
334
|
...(typeof merged.applyPatch === "boolean" ? { applyPatch: merged.applyPatch } : {}),
|
|
335
|
+
...(typeof merged.applyPatchDebug === "boolean"
|
|
336
|
+
? { applyPatchDebug: merged.applyPatchDebug }
|
|
337
|
+
: {}),
|
|
321
338
|
...(merged.toolBackground ? { toolBackground: merged.toolBackground } : {}),
|
|
322
339
|
...(typeof merged.imageGeneration === "boolean"
|
|
323
340
|
? { imageGeneration: merged.imageGeneration }
|
|
@@ -363,6 +380,7 @@ export function configLayer(config: CodexCompatConfig): ConfigLayer {
|
|
|
363
380
|
fastMode: config.fastMode,
|
|
364
381
|
responsesLite: config.responsesLite,
|
|
365
382
|
applyPatch: config.applyPatch,
|
|
383
|
+
applyPatchDebug: config.applyPatchDebug,
|
|
366
384
|
toolBackground: config.toolBackground,
|
|
367
385
|
imageGeneration: config.imageGeneration,
|
|
368
386
|
imageDetail: config.imageDetail,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
type ExtensionContext,
|
|
5
5
|
type ReadonlyFooterDataProvider,
|
|
6
6
|
} from "@earendil-works/pi-coding-agent";
|
|
7
|
-
import type { Component
|
|
7
|
+
import type { Component } from "@earendil-works/pi-tui";
|
|
8
8
|
import type { CodexCompatConfig } from "./config.ts";
|
|
9
9
|
import { isCodexModel } from "./request-options.ts";
|
|
10
10
|
|
|
@@ -74,16 +74,15 @@ function footerSession(ctx: ExtensionContext, resolveConfig: ConfigResolver): Fo
|
|
|
74
74
|
|
|
75
75
|
class CodexFooter implements Component {
|
|
76
76
|
private readonly footer: FooterComponent;
|
|
77
|
-
private readonly unsubscribe: () => void;
|
|
78
77
|
|
|
79
78
|
constructor(
|
|
80
|
-
tui: TUI,
|
|
81
79
|
footerData: ReadonlyFooterDataProvider,
|
|
82
80
|
ctx: ExtensionContext,
|
|
83
81
|
resolveConfig: ConfigResolver,
|
|
84
82
|
) {
|
|
85
83
|
this.footer = new FooterComponent(footerSession(ctx, resolveConfig), footerData);
|
|
86
|
-
|
|
84
|
+
// Pi does not expose its live auto-compaction state to extension footers.
|
|
85
|
+
this.footer.setAutoCompactEnabled(false);
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
render(width: number): string[] {
|
|
@@ -95,14 +94,11 @@ class CodexFooter implements Component {
|
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
dispose(): void {
|
|
98
|
-
this.unsubscribe();
|
|
99
97
|
this.footer.dispose();
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
100
|
|
|
103
101
|
export function installCodexFooter(ctx: ExtensionContext, resolveConfig: ConfigResolver): void {
|
|
104
102
|
if (ctx.mode !== "tui") return;
|
|
105
|
-
ctx.ui.setFooter(
|
|
106
|
-
(tui, _theme, footerData) => new CodexFooter(tui, footerData, ctx, resolveConfig),
|
|
107
|
-
);
|
|
103
|
+
ctx.ui.setFooter((_tui, _theme, footerData) => new CodexFooter(footerData, ctx, resolveConfig));
|
|
108
104
|
}
|
|
@@ -32,6 +32,7 @@ function settingsSummary(ctx: ExtensionContext, config: CodexCompatConfig): stri
|
|
|
32
32
|
`reasoning mode: ${config.reasoningMode}`,
|
|
33
33
|
`Codex tool background: ${config.toolBackground}`,
|
|
34
34
|
`apply_patch: ${config.applyPatch ? "on" : "off"}`,
|
|
35
|
+
`apply_patch debug output: ${config.applyPatchDebug ? "on" : "off"}`,
|
|
35
36
|
`image_gen.imagegen: ${config.imageGeneration ? "on" : "off"}`,
|
|
36
37
|
`image result detail: ${config.imageDetail}`,
|
|
37
38
|
`web.run: ${config.webRun ? "on" : "off"}`,
|
|
@@ -51,6 +52,8 @@ export default function registerOpenAICodexCompat(pi: ExtensionAPI): void {
|
|
|
51
52
|
return activeConfig;
|
|
52
53
|
};
|
|
53
54
|
const resolveToolBackground = () => activeConfig?.toolBackground ?? DEFAULT_CONFIG.toolBackground;
|
|
55
|
+
const resolveApplyPatchDebug = () =>
|
|
56
|
+
activeConfig?.applyPatchDebug ?? DEFAULT_CONFIG.applyPatchDebug;
|
|
54
57
|
|
|
55
58
|
pi.on("session_start", (event, ctx) => {
|
|
56
59
|
activeConfig = loadConfig(ctx.cwd, ctx.isProjectTrusted());
|
|
@@ -60,7 +63,7 @@ export default function registerOpenAICodexCompat(pi: ExtensionAPI): void {
|
|
|
60
63
|
}
|
|
61
64
|
});
|
|
62
65
|
|
|
63
|
-
registerCodexTools(pi, resolveConfig, resolveToolBackground);
|
|
66
|
+
registerCodexTools(pi, resolveConfig, resolveToolBackground, resolveApplyPatchDebug);
|
|
64
67
|
registerCodexThreadLineage(pi);
|
|
65
68
|
const codexProvider = registerCodexProvider(pi, resolveConfig);
|
|
66
69
|
registerCodexRequestOptions(pi, resolveConfig);
|
|
@@ -188,6 +188,10 @@ export default function registerRemoteCompaction(
|
|
|
188
188
|
template,
|
|
189
189
|
priority: config.fastMode,
|
|
190
190
|
compactionMetadata: compactionMetadata(event.reason),
|
|
191
|
+
compactionDecision: {
|
|
192
|
+
reason: event.reason,
|
|
193
|
+
willRetry: event.willRetry,
|
|
194
|
+
},
|
|
191
195
|
});
|
|
192
196
|
|
|
193
197
|
return {
|
|
@@ -34,6 +34,7 @@ type SettingId =
|
|
|
34
34
|
| "reasoningMode"
|
|
35
35
|
| "toolBackground"
|
|
36
36
|
| "applyPatch"
|
|
37
|
+
| "applyPatchDebug"
|
|
37
38
|
| "imageGeneration"
|
|
38
39
|
| "imageDetail"
|
|
39
40
|
| "webRun"
|
|
@@ -108,6 +109,13 @@ export function settingItems(
|
|
|
108
109
|
currentValue: toggleValue(config.applyPatch),
|
|
109
110
|
values: ["off", "on"],
|
|
110
111
|
},
|
|
112
|
+
{
|
|
113
|
+
id: "applyPatchDebug",
|
|
114
|
+
label: "apply_patch debug output",
|
|
115
|
+
description: "Show exact model feedback while apply_patch output is collapsed.",
|
|
116
|
+
currentValue: toggleValue(config.applyPatchDebug),
|
|
117
|
+
values: ["off", "on"],
|
|
118
|
+
},
|
|
111
119
|
{
|
|
112
120
|
id: "imageGeneration",
|
|
113
121
|
label: "image_gen.imagegen tool",
|
|
@@ -185,6 +193,8 @@ export function settingPatch(id: string, value: string): ConfigLayer | undefined
|
|
|
185
193
|
return undefined;
|
|
186
194
|
case "applyPatch":
|
|
187
195
|
return value === "on" || value === "off" ? { applyPatch: value === "on" } : undefined;
|
|
196
|
+
case "applyPatchDebug":
|
|
197
|
+
return value === "on" || value === "off" ? { applyPatchDebug: value === "on" } : undefined;
|
|
188
198
|
case "imageGeneration":
|
|
189
199
|
return value === "on" || value === "off" ? { imageGeneration: value === "on" } : undefined;
|
|
190
200
|
case "imageDetail":
|
|
@@ -214,6 +224,7 @@ function applySettingPatch(config: CodexCompatConfig, patch: ConfigLayer): Codex
|
|
|
214
224
|
if (typeof patch.fastMode === "boolean") next.fastMode = patch.fastMode;
|
|
215
225
|
if (typeof patch.responsesLite === "boolean") next.responsesLite = patch.responsesLite;
|
|
216
226
|
if (typeof patch.applyPatch === "boolean") next.applyPatch = patch.applyPatch;
|
|
227
|
+
if (typeof patch.applyPatchDebug === "boolean") next.applyPatchDebug = patch.applyPatchDebug;
|
|
217
228
|
if (patch.toolBackground) next.toolBackground = patch.toolBackground;
|
|
218
229
|
if (typeof patch.imageGeneration === "boolean") {
|
|
219
230
|
next.imageGeneration = patch.imageGeneration;
|
|
@@ -63,8 +63,9 @@ export default function registerCodexTools(
|
|
|
63
63
|
pi: ExtensionAPI,
|
|
64
64
|
resolveConfig: ConfigResolver,
|
|
65
65
|
resolveToolBackground: CodexToolBackgroundResolver = () => DEFAULT_CONFIG.toolBackground,
|
|
66
|
+
resolveApplyPatchDebug: () => boolean = () => DEFAULT_CONFIG.applyPatchDebug,
|
|
66
67
|
): void {
|
|
67
|
-
registerApplyPatch(pi, resolveToolBackground);
|
|
68
|
+
registerApplyPatch(pi, resolveToolBackground, resolveApplyPatchDebug);
|
|
68
69
|
registerImageGeneration(pi, resolveConfig, resolveToolBackground);
|
|
69
70
|
registerWebRun(pi, resolveConfig, resolveToolBackground);
|
|
70
71
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-openai-codex-compat",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "OpenAI Codex compatibility for Pi with native compaction, fast mode, and Codex-optimized capabilities",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"extensions",
|
|
24
|
+
"APPLY_PATCH_INSTRUCTION_FEEDBACK.md",
|
|
24
25
|
"README.md",
|
|
25
26
|
"CHANGELOG.md",
|
|
26
27
|
"LICENSE",
|
|
@@ -33,19 +34,24 @@
|
|
|
33
34
|
"test": "node --test --test-concurrency=1 test/*.test.ts",
|
|
34
35
|
"test:live:codex": "PI_CODEX_LIVE_TEST=1 node --test --test-concurrency=1 test/codex-host.live.test.ts",
|
|
35
36
|
"pack:dry": "npm pack --dry-run --allow-directory=all",
|
|
37
|
+
"release": "node scripts/release.ts",
|
|
36
38
|
"fmt": "oxfmt",
|
|
37
39
|
"lint": "oxlint",
|
|
38
40
|
"lint:fix": "oxlint --fix"
|
|
39
41
|
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@2h2d/tree-sitter-wasms": "0.2.1",
|
|
44
|
+
"web-tree-sitter": "0.26.11"
|
|
45
|
+
},
|
|
40
46
|
"devDependencies": {
|
|
41
47
|
"@earendil-works/pi-ai": "0.84.1",
|
|
42
48
|
"@earendil-works/pi-coding-agent": "0.84.1",
|
|
43
49
|
"@earendil-works/pi-tui": "0.84.1",
|
|
44
50
|
"@types/node": "22.20.1",
|
|
45
|
-
"oxfmt": "0.
|
|
46
|
-
"oxlint": "1.
|
|
51
|
+
"oxfmt": "0.62.0",
|
|
52
|
+
"oxlint": "1.77.0",
|
|
47
53
|
"oxlint-tsgolint": "7.0.2001",
|
|
48
|
-
"typebox": "1.3.
|
|
54
|
+
"typebox": "1.3.11",
|
|
49
55
|
"typescript": "7.0.2"
|
|
50
56
|
},
|
|
51
57
|
"peerDependencies": {
|