pi-openai-codex-compat 0.0.7-alpha.0 → 0.0.8

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.
@@ -141,11 +141,6 @@ function appendCustomInput(
141
141
  return delta;
142
142
  }
143
143
 
144
- function responseItems(value: unknown): JsonRecord[] {
145
- if (!Array.isArray(value)) return [];
146
- return value.filter(isObject);
147
- }
148
-
149
144
  function itemContentText(item: JsonRecord): string {
150
145
  if (!Array.isArray(item.content)) return "";
151
146
  return item.content
@@ -209,7 +204,8 @@ export async function processCodexStream(
209
204
  ): Promise<void> {
210
205
  let terminal = false;
211
206
  const slots = new Map<number, OutputSlot>();
212
- const reasoningById = new Map<string, ThinkingContent>();
207
+ const completedOutputItems = new Set<string>();
208
+ const completedToolCallContentIndexes = new Set<number>();
213
209
  const applyMessagePhaseStopReason = (item: JsonRecord): void => {
214
210
  if (item.type === "message" && item["phase"] === "final_answer") {
215
211
  output.stopReason = "stop";
@@ -318,6 +314,80 @@ export async function processCodexStream(
318
314
  const slotFor = (index: number, item: JsonRecord): OutputSlot | undefined =>
319
315
  slots.get(index) ?? createSlot(index, item);
320
316
 
317
+ const outputItemKey = (index: number, item: JsonRecord): string => {
318
+ if (typeof item.id === "string") return `id:${item.id}`;
319
+ if (typeof item["call_id"] === "string") {
320
+ return `call:${String(item.type)}:${item["call_id"]}`;
321
+ }
322
+ return `index:${String(index)}:${String(item.type)}`;
323
+ };
324
+
325
+ const completeOutputItem = (index: number, item: JsonRecord): void => {
326
+ const key = outputItemKey(index, item);
327
+ if (completedOutputItems.has(key)) return;
328
+ completedOutputItems.add(key);
329
+ applyMessagePhaseStopReason(item);
330
+ const slot = slotFor(index, item);
331
+ if (item.type === "reasoning" && slot?.type === "thinking") {
332
+ slot.block.thinking = reasoningText(item) || slot.block.thinking;
333
+ slot.block.thinkingSignature = JSON.stringify(item);
334
+ stream.push({
335
+ type: "thinking_end",
336
+ contentIndex: slot.contentIndex,
337
+ content: slot.block.thinking,
338
+ partial: output,
339
+ });
340
+ trackCompleted(slot);
341
+ slots.delete(index);
342
+ } else if (item.type === "message" && slot?.type === "text") {
343
+ slot.block.text = itemContentText(item);
344
+ if (typeof item.id === "string") {
345
+ slot.block.textSignature = encodeTextSignature(item.id, item["phase"]);
346
+ }
347
+ stream.push({
348
+ type: "text_end",
349
+ contentIndex: slot.contentIndex,
350
+ content: slot.block.text,
351
+ partial: output,
352
+ });
353
+ trackCompleted(slot);
354
+ slots.delete(index);
355
+ } else if (
356
+ item.type === "function_call" &&
357
+ slot?.type === "toolCall" &&
358
+ slot.block.partialJson !== undefined
359
+ ) {
360
+ slot.block.name = piToolCallName(item);
361
+ const argumentsJson =
362
+ typeof item.arguments === "string" ? item.arguments : slot.block.partialJson || "{}";
363
+ slot.block.arguments = parseStreamingJson(argumentsJson);
364
+ delete slot.block.partialJson;
365
+ stream.push({
366
+ type: "toolcall_end",
367
+ contentIndex: slot.contentIndex,
368
+ toolCall: slot.block,
369
+ partial: output,
370
+ });
371
+ trackCompleted(slot);
372
+ completedToolCallContentIndexes.add(slot.contentIndex);
373
+ slots.delete(index);
374
+ } else if (item.type === "custom_tool_call" && slot?.type === "toolCall") {
375
+ slot.block.name = piToolCallName(item);
376
+ const input = typeof item["input"] === "string" ? item["input"] : customInput(slot.block);
377
+ pushToolDelta(slot, appendCustomInput(slot.block, input, true));
378
+ delete slot.block.customInput;
379
+ stream.push({
380
+ type: "toolcall_end",
381
+ contentIndex: slot.contentIndex,
382
+ toolCall: slot.block,
383
+ partial: output,
384
+ });
385
+ trackCompleted(slot);
386
+ completedToolCallContentIndexes.add(slot.contentIndex);
387
+ slots.delete(index);
388
+ }
389
+ };
390
+
321
391
  const finalize = (response: JsonRecord): void => {
322
392
  terminal = true;
323
393
  if (typeof response.id === "string") output.responseId = response.id;
@@ -350,18 +420,6 @@ export async function processCodexStream(
350
420
  output.usage,
351
421
  typeof response.service_tier === "string" ? response.service_tier : undefined,
352
422
  );
353
- for (const item of responseItems(response["output"])) {
354
- if (item.type !== "reasoning" || typeof item.id !== "string") continue;
355
- const block = reasoningById.get(item.id);
356
- if (!block?.thinkingSignature || typeof item.encrypted_content !== "string") continue;
357
- const stored = JSON.parse(block.thinkingSignature) as JsonRecord;
358
- if (typeof stored.encrypted_content !== "string") {
359
- block.thinkingSignature = JSON.stringify({
360
- ...stored,
361
- encrypted_content: item.encrypted_content,
362
- });
363
- }
364
- }
365
423
  const status = normalizeCodexStatus(response["status"]);
366
424
  const incompleteDetails = isObject(response["incomplete_details"])
367
425
  ? response["incomplete_details"]
@@ -376,7 +434,12 @@ export async function processCodexStream(
376
434
  output.stopReason = mappedStop.stopReason;
377
435
  if (mappedStop.errorMessage === undefined) delete output.errorMessage;
378
436
  else output.errorMessage = mappedStop.errorMessage;
379
- if (output.stopReason === "stop" && output.content.some((block) => block.type === "toolCall")) {
437
+ if (
438
+ output.stopReason === "stop" &&
439
+ [...completedToolCallContentIndexes].some(
440
+ (contentIndex) => output.content[contentIndex]?.type === "toolCall",
441
+ )
442
+ ) {
380
443
  output.stopReason = "toolUse";
381
444
  }
382
445
  };
@@ -455,66 +518,7 @@ export async function processCodexStream(
455
518
  if (!slot || typeof event["input"] !== "string") continue;
456
519
  pushToolDelta(slot, appendCustomInput(slot.block, event["input"], true));
457
520
  } else if (event.type === "response.output_item.done" && isObject(event.item)) {
458
- const item = event.item;
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
- }
521
+ completeOutputItem(index, event.item);
518
522
  } else if (
519
523
  (event.type === "response.completed" || event.type === "response.incomplete") &&
520
524
  isObject(event.response)
@@ -1910,16 +1910,6 @@ async function* requestWebSocket(
1910
1910
  responseCompleted = true;
1911
1911
  }
1912
1912
  if (typeof event.response.id === "string") responseId = event.response.id;
1913
- if (Array.isArray(event.response["output"])) {
1914
- const terminalItems = event.response["output"].filter(isObject);
1915
- if (terminalItems.length > 0) {
1916
- responseItems.splice(
1917
- 0,
1918
- responseItems.length,
1919
- ...terminalItems.map((item) => structuredClone(item)),
1920
- );
1921
- }
1922
- }
1923
1913
  }
1924
1914
  const normalized = normalizeEvent(event);
1925
1915
  if (!normalized) continue;
@@ -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, TUI } from "@earendil-works/pi-tui";
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
- this.unsubscribe = footerData.onBranchChange(() => tui.requestRender());
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.7-alpha.0",
3
+ "version": "0.0.8",
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",
@@ -38,15 +39,19 @@
38
39
  "lint": "oxlint",
39
40
  "lint:fix": "oxlint --fix"
40
41
  },
42
+ "dependencies": {
43
+ "@2h2d/tree-sitter-wasms": "0.2.1",
44
+ "web-tree-sitter": "0.26.11"
45
+ },
41
46
  "devDependencies": {
42
47
  "@earendil-works/pi-ai": "0.84.1",
43
48
  "@earendil-works/pi-coding-agent": "0.84.1",
44
49
  "@earendil-works/pi-tui": "0.84.1",
45
50
  "@types/node": "22.20.1",
46
- "oxfmt": "0.60.0",
47
- "oxlint": "1.75.0",
51
+ "oxfmt": "0.62.0",
52
+ "oxlint": "1.77.0",
48
53
  "oxlint-tsgolint": "7.0.2001",
49
- "typebox": "1.3.7",
54
+ "typebox": "1.3.11",
50
55
  "typescript": "7.0.2"
51
56
  },
52
57
  "peerDependencies": {