@howaboua/pi-codex-conversion 1.0.19 → 1.0.20
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/README.md +11 -5
- package/package.json +12 -7
- package/src/adapter/tool-set.ts +1 -0
- package/src/index.ts +39 -8
- package/src/prompt/build-system-prompt.ts +1 -0
- package/src/providers/openai-codex-custom-provider.ts +1543 -0
- package/src/providers/openai-responses-shared.ts +616 -0
- package/src/tools/apply-patch-tool.ts +1 -1
- package/src/tools/exec-command-tool.ts +1 -1
- package/src/tools/image-generation-tool.ts +112 -0
- package/src/tools/view-image-tool.ts +1 -1
- package/src/tools/web-search-tool.ts +2 -2
- package/src/tools/write-stdin-tool.ts +1 -1
package/README.md
CHANGED
|
@@ -4,16 +4,17 @@ Codex-oriented adapter for [Pi](https://github.com/badlogic/pi-mono).
|
|
|
4
4
|
|
|
5
5
|
This package replaces Pi's default Codex/GPT experience with a narrower Codex-like surface while staying close to Pi's own runtime and prompt construction:
|
|
6
6
|
|
|
7
|
-
- swaps active tools to `exec_command`, `write_stdin`, `apply_patch`, `view_image`,
|
|
7
|
+
- swaps active tools to `exec_command`, `write_stdin`, `apply_patch`, `view_image`, plus native OpenAI Codex Responses `web_search` and `image_generation` on `openai-codex`
|
|
8
|
+
- saves native Codex image-generation outputs into `.pi/openai-codex-images/` at the workspace/repo root and mirrors the newest image to `.pi/openai-codex-images/latest.png`
|
|
8
9
|
- preserves Pi's composed system prompt and applies a narrow Codex-oriented delta on top
|
|
9
10
|
- renders exec activity with Codex-style command and background-terminal labels
|
|
10
11
|
- renders `apply_patch` calls with Codex-style `Added` / `Edited` / `Deleted` diff blocks and Pi-style colored diff lines
|
|
11
|
-
- targets modern Pi tool/rendering APIs and is aligned with Pi `0.
|
|
12
|
+
- targets modern Pi tool/rendering APIs and is aligned with Pi `0.69.x`
|
|
12
13
|
|
|
13
14
|

|
|
14
15
|
|
|
15
16
|
> [!NOTE]
|
|
16
|
-
> Native OpenAI Codex Responses web search
|
|
17
|
+
> Native OpenAI Codex Responses web search activity is surfaced as merged foldable status messages. Pi still does not expose native web-search usage as true tool-call rows.
|
|
17
18
|
|
|
18
19
|
## Active tools in adapter mode
|
|
19
20
|
|
|
@@ -22,8 +23,9 @@ When the adapter is active, the LLM sees these tools:
|
|
|
22
23
|
- `exec_command` — shell execution with Codex-style `cmd` parameters and resumable sessions
|
|
23
24
|
- `write_stdin` — continue or poll a running exec session
|
|
24
25
|
- `apply_patch` — patch tool
|
|
25
|
-
- `view_image` — image-only wrapper around Pi's native image reading, enabled only for image-capable models
|
|
26
26
|
- `web_search` — native OpenAI Codex Responses web search, enabled only on the `openai-codex` provider
|
|
27
|
+
- `image_generation` — native OpenAI Codex Responses image generation, enabled only on image-capable `openai-codex` models
|
|
28
|
+
- `view_image` — image-only wrapper around Pi's native image reading, enabled only for image-capable models
|
|
27
29
|
|
|
28
30
|
Notably:
|
|
29
31
|
|
|
@@ -61,7 +63,9 @@ npm run check
|
|
|
61
63
|
- `write_stdin({ session_id, chars: "y\\n" })` renders like `Interacted with background terminal`
|
|
62
64
|
- `view_image({ path: "/absolute/path/to/screenshot.png" })` is available on image-capable models
|
|
63
65
|
- `web_search` is surfaced only on `openai-codex`, and the adapter rewrites it into the native OpenAI Responses `type: "web_search"` payload instead of executing a local function tool
|
|
64
|
-
-
|
|
66
|
+
- `image_generation` is surfaced only on image-capable `openai-codex` models, and the adapter rewrites it into the native OpenAI Responses `type: "image_generation", output_format: "png"` payload instead of executing a local function tool
|
|
67
|
+
- native `image_generation` outputs are saved under `.pi/openai-codex-images/` at the workspace/repo root, with the newest image mirrored to `.pi/openai-codex-images/latest.png`
|
|
68
|
+
- when native web search is available, the adapter shows a one-time session notice and merged foldable search-activity messages instead of native tool-call rows
|
|
65
69
|
- `apply_patch` partial failures stay inline in the patch row so successful and failed file entries can be seen together
|
|
66
70
|
|
|
67
71
|
Raw command output is still available by expanding the tool result.
|
|
@@ -138,6 +142,8 @@ That keeps the prompt much closer to `pi-mono` while still steering the model to
|
|
|
138
142
|
- When you switch away from those models, Pi restores the previous active tool set.
|
|
139
143
|
- `view_image` resolves paths against the active session cwd and only exposes `detail: "original"` for Codex-family image-capable models.
|
|
140
144
|
- `web_search` is exposed only for the `openai-codex` provider and is forwarded as the native OpenAI Codex Responses web search tool.
|
|
145
|
+
- `image_generation` is exposed only for image-capable `openai-codex` models and is forwarded as the native OpenAI Codex Responses image-generation tool.
|
|
146
|
+
- generated images are written under `.pi/openai-codex-images/` at the workspace/repo root, and the latest image is mirrored to `.pi/openai-codex-images/latest.png`.
|
|
141
147
|
- `apply_patch` paths stay restricted to the current working directory.
|
|
142
148
|
- partial `apply_patch` failures stay in the original patch block and highlight the failed entry instead of adding a second warning row.
|
|
143
149
|
- `exec_command` / `write_stdin` use a custom PTY-backed session manager via `node-pty` for interactive sessions.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@howaboua/pi-codex-conversion",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "Codex-oriented tool and prompt adapter for pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -51,19 +51,24 @@
|
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@mariozechner/pi-
|
|
55
|
-
"@mariozechner/pi-
|
|
56
|
-
"@
|
|
54
|
+
"@mariozechner/pi-ai": "^0.69.0",
|
|
55
|
+
"@mariozechner/pi-coding-agent": "^0.69.0",
|
|
56
|
+
"@mariozechner/pi-tui": "^0.69.0",
|
|
57
|
+
"typebox": "^1.1.24"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
|
-
"@mariozechner/pi-
|
|
60
|
-
"@mariozechner/pi-
|
|
60
|
+
"@mariozechner/pi-ai": "^0.69.0",
|
|
61
|
+
"@mariozechner/pi-coding-agent": "^0.69.0",
|
|
62
|
+
"@mariozechner/pi-tui": "^0.69.0",
|
|
61
63
|
"tsx": "^4.20.5",
|
|
64
|
+
"typebox": "^1.1.24",
|
|
62
65
|
"typescript": "^5.9.3"
|
|
63
66
|
},
|
|
64
67
|
"dependencies": {
|
|
65
68
|
"node-pty": "^1.1.0",
|
|
69
|
+
"partial-json": "^0.1.7",
|
|
66
70
|
"tree-sitter-bash": "^0.25.1",
|
|
67
|
-
"web-tree-sitter": "^0.26.7"
|
|
71
|
+
"web-tree-sitter": "^0.26.7",
|
|
72
|
+
"ws": "^8.20.0"
|
|
68
73
|
}
|
|
69
74
|
}
|
package/src/adapter/tool-set.ts
CHANGED
|
@@ -4,5 +4,6 @@ export const STATUS_TEXT = "\u001b[38;2;0;76;255mCodex adapter\u001b[0m";
|
|
|
4
4
|
export const DEFAULT_TOOL_NAMES = ["read", "bash", "edit", "write"];
|
|
5
5
|
|
|
6
6
|
export const CORE_ADAPTER_TOOL_NAMES = ["exec_command", "write_stdin", "apply_patch"];
|
|
7
|
+
export const IMAGE_GENERATION_TOOL_NAME = "image_generation";
|
|
7
8
|
export const VIEW_IMAGE_TOOL_NAME = "view_image";
|
|
8
9
|
export const WEB_SEARCH_TOOL_NAME = "web_search";
|
package/src/index.ts
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionContext } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
import { getCodexRuntimeShell } from "./adapter/runtime-shell.ts";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
CORE_ADAPTER_TOOL_NAMES,
|
|
5
|
+
DEFAULT_TOOL_NAMES,
|
|
6
|
+
IMAGE_GENERATION_TOOL_NAME,
|
|
7
|
+
STATUS_KEY,
|
|
8
|
+
STATUS_TEXT,
|
|
9
|
+
VIEW_IMAGE_TOOL_NAME,
|
|
10
|
+
WEB_SEARCH_TOOL_NAME,
|
|
11
|
+
} from "./adapter/tool-set.ts";
|
|
4
12
|
import { clearApplyPatchRenderState, registerApplyPatchTool } from "./tools/apply-patch-tool.ts";
|
|
5
13
|
import { isCodexLikeContext, isOpenAICodexContext } from "./adapter/codex-model.ts";
|
|
6
14
|
import { createExecCommandTracker } from "./tools/exec-command-state.ts";
|
|
7
15
|
import { registerExecCommandTool } from "./tools/exec-command-tool.ts";
|
|
8
16
|
import { createExecSessionManager } from "./tools/exec-session-manager.ts";
|
|
17
|
+
import {
|
|
18
|
+
IMAGE_SAVE_DISPLAY_MESSAGE_TYPE,
|
|
19
|
+
WEB_SEARCH_ACTIVITY_MESSAGE_TYPE,
|
|
20
|
+
registerOpenAICodexCustomProvider,
|
|
21
|
+
} from "./providers/openai-codex-custom-provider.ts";
|
|
22
|
+
import { registerImageGenerationTool, rewriteNativeImageGenerationTool, supportsNativeImageGeneration } from "./tools/image-generation-tool.ts";
|
|
9
23
|
import { buildCodexSystemPrompt, extractPiPromptSkills, type PromptSkill } from "./prompt/build-system-prompt.ts";
|
|
10
24
|
import { registerViewImageTool, supportsOriginalImageDetail } from "./tools/view-image-tool.ts";
|
|
11
25
|
import {
|
|
@@ -21,12 +35,13 @@ import { registerWriteStdinTool } from "./tools/write-stdin-tool.ts";
|
|
|
21
35
|
|
|
22
36
|
interface AdapterState {
|
|
23
37
|
enabled: boolean;
|
|
38
|
+
cwd: string;
|
|
24
39
|
previousToolNames?: string[];
|
|
25
40
|
promptSkills: PromptSkill[];
|
|
26
41
|
webSearchNoticeShown: boolean;
|
|
27
42
|
}
|
|
28
43
|
|
|
29
|
-
const ADAPTER_TOOL_NAMES = [...CORE_ADAPTER_TOOL_NAMES,
|
|
44
|
+
const ADAPTER_TOOL_NAMES = [...CORE_ADAPTER_TOOL_NAMES, WEB_SEARCH_TOOL_NAME, IMAGE_GENERATION_TOOL_NAME, VIEW_IMAGE_TOOL_NAME];
|
|
30
45
|
|
|
31
46
|
function getCommandArg(args: unknown): string | undefined {
|
|
32
47
|
if (!args || typeof args !== "object" || !("cmd" in args) || typeof args.cmd !== "string") {
|
|
@@ -47,12 +62,16 @@ function isToolCallOnlyAssistantMessage(message: unknown): boolean {
|
|
|
47
62
|
|
|
48
63
|
export default function codexConversion(pi: ExtensionAPI) {
|
|
49
64
|
const tracker = createExecCommandTracker();
|
|
50
|
-
const state: AdapterState = { enabled: false, promptSkills: [], webSearchNoticeShown: false };
|
|
65
|
+
const state: AdapterState = { enabled: false, cwd: process.cwd(), promptSkills: [], webSearchNoticeShown: false };
|
|
51
66
|
const sessions = createExecSessionManager();
|
|
52
67
|
|
|
68
|
+
registerOpenAICodexCustomProvider(pi, {
|
|
69
|
+
getCurrentCwd: () => state.cwd,
|
|
70
|
+
});
|
|
53
71
|
registerApplyPatchTool(pi);
|
|
54
72
|
registerExecCommandTool(pi, tracker, sessions);
|
|
55
73
|
registerWriteStdinTool(pi, sessions);
|
|
74
|
+
registerImageGenerationTool(pi);
|
|
56
75
|
registerWebSearchTool(pi);
|
|
57
76
|
registerWebSearchSessionNoteRenderer(pi);
|
|
58
77
|
|
|
@@ -61,6 +80,7 @@ export default function codexConversion(pi: ExtensionAPI) {
|
|
|
61
80
|
});
|
|
62
81
|
|
|
63
82
|
pi.on("session_start", async (_event, ctx) => {
|
|
83
|
+
state.cwd = ctx.cwd;
|
|
64
84
|
state.webSearchNoticeShown = false;
|
|
65
85
|
clearApplyPatchRenderState();
|
|
66
86
|
tracker.clear();
|
|
@@ -68,6 +88,7 @@ export default function codexConversion(pi: ExtensionAPI) {
|
|
|
68
88
|
});
|
|
69
89
|
|
|
70
90
|
pi.on("model_select", async (_event, ctx) => {
|
|
91
|
+
state.cwd = ctx.cwd;
|
|
71
92
|
syncAdapter(pi, ctx, state);
|
|
72
93
|
});
|
|
73
94
|
|
|
@@ -110,16 +131,23 @@ export default function codexConversion(pi: ExtensionAPI) {
|
|
|
110
131
|
});
|
|
111
132
|
|
|
112
133
|
pi.on("before_provider_request", async (event, ctx) => {
|
|
134
|
+
state.cwd = ctx.cwd;
|
|
113
135
|
if (!isOpenAICodexContext(ctx)) {
|
|
114
136
|
return undefined;
|
|
115
137
|
}
|
|
116
|
-
return rewriteNativeWebSearchTool(event.payload, ctx.model);
|
|
138
|
+
return rewriteNativeImageGenerationTool(rewriteNativeWebSearchTool(event.payload, ctx.model), ctx.model);
|
|
117
139
|
});
|
|
118
140
|
|
|
119
141
|
pi.on("context", async (event) => {
|
|
120
142
|
return {
|
|
121
143
|
messages: event.messages.filter(
|
|
122
|
-
(message) =>
|
|
144
|
+
(message) =>
|
|
145
|
+
!(
|
|
146
|
+
message.role === "custom" &&
|
|
147
|
+
(message.customType === WEB_SEARCH_SESSION_NOTE_TYPE ||
|
|
148
|
+
message.customType === WEB_SEARCH_ACTIVITY_MESSAGE_TYPE ||
|
|
149
|
+
message.customType === IMAGE_SAVE_DISPLAY_MESSAGE_TYPE)
|
|
150
|
+
),
|
|
123
151
|
),
|
|
124
152
|
};
|
|
125
153
|
});
|
|
@@ -169,12 +197,15 @@ function setStatus(ctx: ExtensionContext, enabled: boolean): void {
|
|
|
169
197
|
|
|
170
198
|
function getAdapterToolNames(ctx: ExtensionContext): string[] {
|
|
171
199
|
const toolNames = [...CORE_ADAPTER_TOOL_NAMES];
|
|
172
|
-
if (Array.isArray(ctx.model?.input) && ctx.model.input.includes("image")) {
|
|
173
|
-
toolNames.push(VIEW_IMAGE_TOOL_NAME);
|
|
174
|
-
}
|
|
175
200
|
if (supportsNativeWebSearch(ctx.model)) {
|
|
176
201
|
toolNames.push(WEB_SEARCH_TOOL_NAME);
|
|
177
202
|
}
|
|
203
|
+
if (supportsNativeImageGeneration(ctx.model)) {
|
|
204
|
+
toolNames.push(IMAGE_GENERATION_TOOL_NAME);
|
|
205
|
+
}
|
|
206
|
+
if (Array.isArray(ctx.model?.input) && ctx.model.input.includes("image")) {
|
|
207
|
+
toolNames.push(VIEW_IMAGE_TOOL_NAME);
|
|
208
|
+
}
|
|
178
209
|
return toolNames;
|
|
179
210
|
}
|
|
180
211
|
|
|
@@ -13,6 +13,7 @@ const CODEX_GUIDELINES = [
|
|
|
13
13
|
"For short or non-interactive commands, prefer the default `exec_command` wait instead of a tiny `yield_time_ms` that forces an extra follow-up call.",
|
|
14
14
|
"When polling a running exec session with empty `chars`, wait meaningfully between polls and do not repeatedly poll by reflex.",
|
|
15
15
|
"Do not request `tty` unless interactive terminal behavior is required.",
|
|
16
|
+
"Native `image_generation` outputs are saved under `.pi/openai-codex-images/` and mirrored to `.pi/openai-codex-images/latest.png`. Use `view_image` only when pixel-level inspection is necessary.",
|
|
16
17
|
];
|
|
17
18
|
|
|
18
19
|
function insertBeforeTrailingContext(prompt: string, section: string): string {
|