pi-openai-codex-compat 0.0.10-alpha.5 → 0.0.10-alpha.6
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/CHANGELOG.md
CHANGED
|
@@ -21,7 +21,10 @@
|
|
|
21
21
|
- Show effective unified-exec yield durations beside accent-colored command
|
|
22
22
|
tool titles, include explicit working directories, emphasize commands on
|
|
23
23
|
their own separated rows, separate `apply_patch` results, and mute command
|
|
24
|
-
output and protocol metadata.
|
|
24
|
+
output and protocol metadata. Show yielded `exec_command` session IDs on
|
|
25
|
+
their title line, and identify `write_stdin` polls in the title and with the
|
|
26
|
+
original command, working directory, and session ID without repeating that
|
|
27
|
+
context for writes.
|
|
25
28
|
- Stream live `exec_command`, `write_stdin`, and `shell_command` output in the
|
|
26
29
|
TUI while each tool call is running instead of hiding updates until it exits
|
|
27
30
|
or yields.
|
|
@@ -6,12 +6,12 @@ import {
|
|
|
6
6
|
} from "./codex-tool-surface.ts";
|
|
7
7
|
import { DEFAULT_CONFIG } from "./config.ts";
|
|
8
8
|
|
|
9
|
-
type CommandRenderContext = {
|
|
9
|
+
export type CommandRenderContext = {
|
|
10
10
|
isError: boolean;
|
|
11
11
|
isPartial: boolean;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
type CommandCallRenderContext = CommandRenderContext & {
|
|
14
|
+
export type CommandCallRenderContext = CommandRenderContext & {
|
|
15
15
|
executionStarted: boolean;
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -19,6 +19,12 @@ type CommandRenderResult = {
|
|
|
19
19
|
content: Array<{ type: string; text?: string }>;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
type CommandCallMetadata = {
|
|
23
|
+
sessionId?: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
type CommandCallMetadataSource = CommandCallMetadata | (() => CommandCallMetadata);
|
|
27
|
+
|
|
22
28
|
type CommandOutputPreviewLine = {
|
|
23
29
|
text: string;
|
|
24
30
|
sourceLine?: number;
|
|
@@ -145,6 +151,59 @@ class CommandResultComponent implements Component {
|
|
|
145
151
|
}
|
|
146
152
|
}
|
|
147
153
|
|
|
154
|
+
class CommandCallComponent implements Component {
|
|
155
|
+
private readonly text: Text;
|
|
156
|
+
private readonly title: string;
|
|
157
|
+
private readonly yieldLabel: string;
|
|
158
|
+
private readonly workdirLabel: string;
|
|
159
|
+
private readonly summary: string;
|
|
160
|
+
private readonly theme: RenderTheme;
|
|
161
|
+
private readonly metadata: CommandCallMetadataSource;
|
|
162
|
+
private renderedSessionId: number | undefined;
|
|
163
|
+
|
|
164
|
+
constructor(
|
|
165
|
+
title: string,
|
|
166
|
+
yieldLabel: string,
|
|
167
|
+
workdirLabel: string,
|
|
168
|
+
summary: string,
|
|
169
|
+
theme: RenderTheme,
|
|
170
|
+
metadata: CommandCallMetadataSource,
|
|
171
|
+
) {
|
|
172
|
+
this.title = title;
|
|
173
|
+
this.yieldLabel = yieldLabel;
|
|
174
|
+
this.workdirLabel = workdirLabel;
|
|
175
|
+
this.summary = summary;
|
|
176
|
+
this.theme = theme;
|
|
177
|
+
this.metadata = metadata;
|
|
178
|
+
this.renderedSessionId = this.resolveSessionId();
|
|
179
|
+
this.text = new Text(this.renderText(this.renderedSessionId), 0, 0);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
render(width: number): string[] {
|
|
183
|
+
const sessionId = this.resolveSessionId();
|
|
184
|
+
if (sessionId !== this.renderedSessionId) {
|
|
185
|
+
this.renderedSessionId = sessionId;
|
|
186
|
+
this.text.setText(this.renderText(sessionId));
|
|
187
|
+
}
|
|
188
|
+
return this.text.render(width);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
invalidate(): void {
|
|
192
|
+
this.text.invalidate();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private resolveSessionId(): number | undefined {
|
|
196
|
+
const metadata = typeof this.metadata === "function" ? this.metadata() : this.metadata;
|
|
197
|
+
return metadata.sessionId;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private renderText(sessionId: number | undefined): string {
|
|
201
|
+
const sessionLabel =
|
|
202
|
+
sessionId === undefined ? "" : ` ${this.theme.fg("muted", `[session id: ${sessionId}]`)}`;
|
|
203
|
+
return `${this.title}${sessionLabel}${this.yieldLabel}${this.workdirLabel}\n\n${this.summary}`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
148
207
|
export function renderCommandCall(
|
|
149
208
|
toolName: string,
|
|
150
209
|
command: string,
|
|
@@ -153,13 +212,14 @@ export function renderCommandCall(
|
|
|
153
212
|
theme: RenderTheme,
|
|
154
213
|
context: CommandCallRenderContext,
|
|
155
214
|
resolveBackground: CodexToolBackgroundResolver = () => DEFAULT_CONFIG.toolBackground,
|
|
215
|
+
metadata: CommandCallMetadataSource = {},
|
|
156
216
|
): Component {
|
|
157
217
|
const title = theme.fg("accent", theme.bold(toolName));
|
|
158
218
|
const yieldLabel = yieldDuration ? ` ${theme.fg("muted", `[yield: ${yieldDuration}]`)}` : "";
|
|
159
219
|
const workdirLabel = workdir ? ` ${theme.fg("muted", `[workdir: ${workdir}]`)}` : "";
|
|
160
220
|
const summary = theme.fg("text", command || "…");
|
|
161
221
|
return new CodexToolSurfaceComponent(
|
|
162
|
-
new
|
|
222
|
+
new CommandCallComponent(title, yieldLabel, workdirLabel, summary, theme, metadata),
|
|
163
223
|
theme,
|
|
164
224
|
{
|
|
165
225
|
background: resolveBackground,
|
|
@@ -10,14 +10,19 @@ import {
|
|
|
10
10
|
type WriteStdinRequest,
|
|
11
11
|
} from "./command-runtime.ts";
|
|
12
12
|
import type { CommandProcessSpawner } from "./command-process.ts";
|
|
13
|
+
import type { CommandOutputDetails } from "./command-output.ts";
|
|
13
14
|
import {
|
|
14
15
|
commandShellDisplayName,
|
|
15
16
|
resolveCommandShellCatalog,
|
|
16
17
|
type CommandShellCatalog,
|
|
17
18
|
} from "./command-shell.ts";
|
|
18
|
-
import type { CodexToolBackgroundResolver } from "./codex-tool-surface.ts";
|
|
19
|
+
import type { CodexToolBackgroundResolver, RenderTheme } from "./codex-tool-surface.ts";
|
|
19
20
|
import { DEFAULT_CONFIG } from "./config.ts";
|
|
20
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
renderCommandCall,
|
|
23
|
+
renderCommandResult,
|
|
24
|
+
type CommandCallRenderContext,
|
|
25
|
+
} from "./command-render.ts";
|
|
21
26
|
import {
|
|
22
27
|
EXEC_COMMAND_PARAMETERS,
|
|
23
28
|
EXEC_COMMAND_TOOL_NAME,
|
|
@@ -57,6 +62,20 @@ export type CommandToolsController = {
|
|
|
57
62
|
terminateUnifiedExecSessions: () => void;
|
|
58
63
|
};
|
|
59
64
|
|
|
65
|
+
export type WriteStdinRenderProcess = {
|
|
66
|
+
sessionId: number;
|
|
67
|
+
command: string;
|
|
68
|
+
workdir: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
type WriteStdinRenderState = {
|
|
72
|
+
polledProcess?: WriteStdinRenderProcess;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
type ExecCommandRenderState = {
|
|
76
|
+
sessionId?: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
60
79
|
// Pi validates the prepared value against SHELL_COMMAND_PARAMETERS immediately
|
|
61
80
|
// after this compatibility rewrite.
|
|
62
81
|
export function prepareShellCommandArguments(
|
|
@@ -75,14 +94,59 @@ export function prepareShellCommandArguments(args: unknown): unknown {
|
|
|
75
94
|
return prepared;
|
|
76
95
|
}
|
|
77
96
|
|
|
78
|
-
function writeStdinSummary(
|
|
97
|
+
function writeStdinSummary(
|
|
98
|
+
request: Partial<WriteStdinRequest>,
|
|
99
|
+
polledProcess: WriteStdinRenderProcess | undefined,
|
|
100
|
+
): string {
|
|
79
101
|
const id = typeof request.session_id === "number" ? request.session_id : "?";
|
|
80
102
|
const chars = typeof request.chars === "string" ? request.chars : "";
|
|
81
|
-
if (!chars) return `poll session ${id}`;
|
|
103
|
+
if (!chars) return polledProcess?.command ?? `poll session ${id}`;
|
|
82
104
|
const singleLine = chars.replaceAll("\n", "\\n").replaceAll("\r", "\\r");
|
|
83
105
|
return `write ${JSON.stringify(singleLine)} to session ${id}`;
|
|
84
106
|
}
|
|
85
107
|
|
|
108
|
+
export function renderWriteStdinCall(
|
|
109
|
+
request: Partial<WriteStdinRequest>,
|
|
110
|
+
polledProcess: WriteStdinRenderProcess | undefined,
|
|
111
|
+
yieldDuration: string | undefined,
|
|
112
|
+
theme: RenderTheme,
|
|
113
|
+
context: CommandCallRenderContext,
|
|
114
|
+
resolveBackground: CodexToolBackgroundResolver = () => DEFAULT_CONFIG.toolBackground,
|
|
115
|
+
): ReturnType<typeof renderCommandCall> {
|
|
116
|
+
const polling = !(request.chars ?? "");
|
|
117
|
+
const process = polling ? polledProcess : undefined;
|
|
118
|
+
return renderCommandCall(
|
|
119
|
+
polling ? `${WRITE_STDIN_TOOL_NAME} (polling)` : WRITE_STDIN_TOOL_NAME,
|
|
120
|
+
writeStdinSummary(request, process),
|
|
121
|
+
yieldDuration,
|
|
122
|
+
process?.workdir,
|
|
123
|
+
theme,
|
|
124
|
+
context,
|
|
125
|
+
resolveBackground,
|
|
126
|
+
process ? { sessionId: process.sessionId } : {},
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function resolvePolledProcess(
|
|
131
|
+
request: Partial<WriteStdinRequest>,
|
|
132
|
+
manager: UnifiedExecManager,
|
|
133
|
+
state: WriteStdinRenderState,
|
|
134
|
+
): WriteStdinRenderState["polledProcess"] {
|
|
135
|
+
if ((request.chars ?? "") || typeof request.session_id !== "number") return undefined;
|
|
136
|
+
if (state.polledProcess?.sessionId === request.session_id) return state.polledProcess;
|
|
137
|
+
const process = manager.observeProcess(request.session_id)?.();
|
|
138
|
+
if (!process) {
|
|
139
|
+
Reflect.deleteProperty(state, "polledProcess");
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
state.polledProcess = {
|
|
143
|
+
sessionId: process.sessionId,
|
|
144
|
+
command: process.command,
|
|
145
|
+
workdir: process.cwd,
|
|
146
|
+
};
|
|
147
|
+
return state.polledProcess;
|
|
148
|
+
}
|
|
149
|
+
|
|
86
150
|
function formatYieldDuration(milliseconds: number): string {
|
|
87
151
|
return milliseconds >= 1_000 ? `${milliseconds / 1_000}s` : `${milliseconds}ms`;
|
|
88
152
|
}
|
|
@@ -185,7 +249,7 @@ export default function registerCommandTools(
|
|
|
185
249
|
},
|
|
186
250
|
});
|
|
187
251
|
|
|
188
|
-
pi.registerTool({
|
|
252
|
+
pi.registerTool<typeof EXEC_COMMAND_PARAMETERS, CommandOutputDetails, ExecCommandRenderState>({
|
|
189
253
|
name: EXEC_COMMAND_TOOL_NAME,
|
|
190
254
|
label: EXEC_COMMAND_TOOL_NAME,
|
|
191
255
|
description: execCommandPrompt.description,
|
|
@@ -197,6 +261,7 @@ export default function registerCommandTools(
|
|
|
197
261
|
return manager.execCommand(params satisfies ExecCommandRequest, ctx, signal, onUpdate);
|
|
198
262
|
},
|
|
199
263
|
renderCall(args, theme, context) {
|
|
264
|
+
const state = context.state;
|
|
200
265
|
return renderCommandCall(
|
|
201
266
|
EXEC_COMMAND_TOOL_NAME,
|
|
202
267
|
typeof args.cmd === "string" ? args.cmd : "",
|
|
@@ -205,14 +270,22 @@ export default function registerCommandTools(
|
|
|
205
270
|
theme,
|
|
206
271
|
context,
|
|
207
272
|
resolveToolBackground,
|
|
273
|
+
() => (state.sessionId === undefined ? {} : { sessionId: state.sessionId }),
|
|
208
274
|
);
|
|
209
275
|
},
|
|
210
276
|
renderResult(result, options, theme, context) {
|
|
277
|
+
if (!options.isPartial) {
|
|
278
|
+
if (result.details.sessionId === undefined) {
|
|
279
|
+
Reflect.deleteProperty(context.state, "sessionId");
|
|
280
|
+
} else {
|
|
281
|
+
context.state.sessionId = result.details.sessionId;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
211
284
|
return renderCommandResult(result, options, theme, context, resolveToolBackground);
|
|
212
285
|
},
|
|
213
286
|
});
|
|
214
287
|
|
|
215
|
-
pi.registerTool({
|
|
288
|
+
pi.registerTool<typeof WRITE_STDIN_PARAMETERS, CommandOutputDetails, WriteStdinRenderState>({
|
|
216
289
|
name: WRITE_STDIN_TOOL_NAME,
|
|
217
290
|
label: WRITE_STDIN_TOOL_NAME,
|
|
218
291
|
description: writeStdinPrompt.description,
|
|
@@ -224,13 +297,13 @@ export default function registerCommandTools(
|
|
|
224
297
|
return manager.writeStdin(params satisfies WriteStdinRequest, signal, onUpdate);
|
|
225
298
|
},
|
|
226
299
|
renderCall(args, theme, context) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
300
|
+
const polledProcess = resolvePolledProcess(args, manager, context.state);
|
|
301
|
+
return renderWriteStdinCall(
|
|
302
|
+
args,
|
|
303
|
+
polledProcess,
|
|
230
304
|
resolveYieldDuration(args.yield_time_ms, (value) =>
|
|
231
305
|
effectiveWriteStdinYieldTimeMs(value, !(args.chars ?? "")),
|
|
232
306
|
),
|
|
233
|
-
undefined,
|
|
234
307
|
theme,
|
|
235
308
|
context,
|
|
236
309
|
resolveToolBackground,
|
package/package.json
CHANGED