@howaboua/pi-codex-conversion 1.0.11 → 1.0.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@howaboua/pi-codex-conversion",
3
- "version": "1.0.11",
3
+ "version": "1.0.13",
4
4
  "description": "Codex-oriented tool and prompt adapter for pi coding agent",
5
5
  "type": "module",
6
6
  "repository": {
@@ -24,12 +24,12 @@ export function formatApplyPatchSummary(patchText: string, cwd = process.cwd()):
24
24
  try {
25
25
  actions = parsePatchActions({ text: patchText });
26
26
  } catch {
27
- return "apply_patch patch";
27
+ return "";
28
28
  }
29
29
 
30
30
  const files = actions.map((action) => buildFilePreview(action, cwd));
31
31
  if (files.length === 0) {
32
- return "apply_patch patch";
32
+ return "";
33
33
  }
34
34
 
35
35
  const totalAdded = files.reduce((sum, file) => sum + file.added, 0);
@@ -56,12 +56,12 @@ export function formatApplyPatchCall(patchText: string, cwd = process.cwd()): st
56
56
  try {
57
57
  actions = parsePatchActions({ text: patchText });
58
58
  } catch {
59
- return "apply_patch patch";
59
+ return "";
60
60
  }
61
61
 
62
62
  const files = actions.map((action) => buildFilePreview(action, cwd));
63
63
  if (files.length === 0) {
64
- return "apply_patch patch";
64
+ return "";
65
65
  }
66
66
 
67
67
  const totalAdded = files.reduce((sum, file) => sum + file.added, 0);
@@ -92,12 +92,12 @@ export function renderApplyPatchCall(patchText: string, cwd = process.cwd()): st
92
92
  try {
93
93
  actions = parsePatchActions({ text: patchText });
94
94
  } catch {
95
- return "apply_patch patch";
95
+ return "";
96
96
  }
97
97
 
98
98
  const files = actions.map((action) => buildFilePreview(action, cwd));
99
99
  if (files.length === 0) {
100
- return "apply_patch patch";
100
+ return "";
101
101
  }
102
102
 
103
103
  const totalAdded = files.reduce((sum, file) => sum + file.added, 0);
@@ -16,7 +16,7 @@ interface ApplyPatchRenderState {
16
16
  patchText: string;
17
17
  collapsed: string;
18
18
  expanded: string;
19
- status: "pending" | "partial_failure";
19
+ status: "pending" | "partial_failure" | "failed";
20
20
  failedTarget?: string;
21
21
  }
22
22
 
@@ -58,7 +58,7 @@ function setApplyPatchRenderState(
58
58
  toolCallId: string,
59
59
  patchText: string,
60
60
  cwd: string,
61
- status: "pending" | "partial_failure" = "pending",
61
+ status: "pending" | "partial_failure" | "failed" = "pending",
62
62
  failedTarget?: string,
63
63
  ): void {
64
64
  const collapsed = formatApplyPatchSummary(patchText, cwd);
@@ -74,13 +74,17 @@ function setApplyPatchRenderState(
74
74
  }
75
75
 
76
76
  function markApplyPatchPartialFailure(toolCallId: string, failedTarget?: string): void {
77
+ markApplyPatchFailure(toolCallId, "partial_failure", failedTarget);
78
+ }
79
+
80
+ function markApplyPatchFailure(toolCallId: string, status: "partial_failure" | "failed", failedTarget?: string): void {
77
81
  const existing = applyPatchRenderStates.get(toolCallId);
78
82
  if (!existing) {
79
83
  return;
80
84
  }
81
85
  applyPatchRenderStates.set(toolCallId, {
82
86
  ...existing,
83
- status: "partial_failure",
87
+ status,
84
88
  failedTarget,
85
89
  });
86
90
  }
@@ -118,6 +122,36 @@ function renderPartialFailureCall(
118
122
  .join("\n");
119
123
  }
120
124
 
125
+ function renderFailedCall(
126
+ text: string,
127
+ theme: { fg(role: string, text: string): string },
128
+ failedTarget?: string,
129
+ ): string {
130
+ const lines = text.split("\n");
131
+ if (lines.length === 0) {
132
+ return theme.fg("error", "• Edit failed");
133
+ }
134
+ lines[0] = lines[0].replace(/^• (Added|Edited|Deleted)\b/, "• Edit failed");
135
+ const failedLineIndexes = new Set<number>();
136
+ if (failedTarget) {
137
+ for (let i = 0; i < lines.length; i += 1) {
138
+ const failedLine = markFailedTargetLine(lines[i], failedTarget);
139
+ if (failedLine) {
140
+ lines[i] = failedLine;
141
+ failedLineIndexes.add(i);
142
+ }
143
+ }
144
+ }
145
+ return lines
146
+ .map((line, index) => {
147
+ if (failedLineIndexes.has(index) || index === 0) {
148
+ return theme.fg("error", line);
149
+ }
150
+ return line;
151
+ })
152
+ .join("\n");
153
+ }
154
+
121
155
  function markFailedTargetLine(line: string, failedTarget: string): string | undefined {
122
156
  const suffixMatch = line.match(/ \(\+\d+ -\d+\)$/);
123
157
  if (!suffixMatch) {
@@ -174,7 +208,18 @@ const renderApplyPatchCallWithOptionalContext: any = (
174
208
  const baseText = context?.expanded
175
209
  ? cached?.expanded ?? renderApplyPatchCall(effectivePatchText, cwd)
176
210
  : cached?.collapsed ?? formatApplyPatchSummary(effectivePatchText, cwd);
177
- const text = cached?.status === "partial_failure" ? renderPartialFailureCall(baseText, theme, cached.failedTarget) : baseText;
211
+ if (baseText.trim().length === 0) {
212
+ if (cached?.status === "failed") {
213
+ return new Text(theme.fg("error", "• Edit failed"), 0, 0);
214
+ }
215
+ return new Text(`${theme.fg("dim", "•")} ${theme.bold("Patching")}`, 0, 0);
216
+ }
217
+ const text =
218
+ cached?.status === "partial_failure"
219
+ ? renderPartialFailureCall(baseText, theme, cached.failedTarget)
220
+ : cached?.status === "failed"
221
+ ? renderFailedCall(baseText, theme, cached.failedTarget)
222
+ : baseText;
178
223
  return new Text(text, 0, 0);
179
224
  };
180
225
 
@@ -219,8 +264,10 @@ export function registerApplyPatchTool(pi: ExtensionAPI): void {
219
264
  } satisfies ApplyPatchPartialFailureDetails,
220
265
  };
221
266
  }
267
+ markApplyPatchFailure(toolCallId, "failed", failedTarget);
222
268
  throw new Error(message);
223
269
  }
270
+ markApplyPatchFailure(toolCallId, "failed");
224
271
  throw error;
225
272
  }
226
273
  const summary = [
@@ -70,6 +70,7 @@ export interface ExecSessionManagerOptions {
70
70
  defaultWriteYieldTimeMs?: number;
71
71
  minNonInteractiveExecYieldTimeMs?: number;
72
72
  minEmptyWriteYieldTimeMs?: number;
73
+ maxSessionBufferChars?: number;
73
74
  }
74
75
 
75
76
  const DEFAULT_EXEC_YIELD_TIME_MS = 10_000;
@@ -80,6 +81,7 @@ const MIN_NON_INTERACTIVE_EXEC_YIELD_TIME_MS = 5_000;
80
81
  const MIN_EMPTY_WRITE_YIELD_TIME_MS = 5_000;
81
82
  const MAX_YIELD_TIME_MS = 30_000;
82
83
  const MAX_COMMAND_HISTORY = 256;
84
+ const DEFAULT_MAX_SESSION_BUFFER_CHARS = 256 * 1024 * 1024;
83
85
 
84
86
  function resolveWorkdir(baseCwd: string, workdir?: string): string {
85
87
  if (!workdir) return baseCwd;
@@ -359,6 +361,7 @@ export function createExecSessionManager(options: ExecSessionManagerOptions = {}
359
361
  MAX_YIELD_TIME_MS,
360
362
  Math.max(MIN_YIELD_TIME_MS, options.minEmptyWriteYieldTimeMs ?? MIN_EMPTY_WRITE_YIELD_TIME_MS),
361
363
  );
364
+ const maxSessionBufferChars = Math.max(1024, options.maxSessionBufferChars ?? DEFAULT_MAX_SESSION_BUFFER_CHARS);
362
365
 
363
366
  function rememberCommand(sessionId: number, command: string): void {
364
367
  commandHistory.set(sessionId, command);
@@ -388,6 +391,10 @@ export function createExecSessionManager(options: ExecSessionManagerOptions = {}
388
391
  if (text.length === 0) return;
389
392
  session.buffer =
390
393
  session.kind === "pty" ? applyTerminalOutput(session, text) : `${session.buffer}${normalizePipeOutput(text)}`;
394
+ if (session.buffer.length > maxSessionBufferChars) {
395
+ session.buffer = session.buffer.slice(-maxSessionBufferChars);
396
+ session.emittedBuffer = "";
397
+ }
391
398
  notify(session);
392
399
  }
393
400