@howaboua/pi-codex-conversion 1.5.4 → 1.5.5-dev.22.90056d4
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 +6 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/adapter/activation.ts +36 -13
- package/src/adapter/config.ts +3 -0
- package/src/adapter/state.ts +1 -0
- package/src/codex-settings/command.ts +6 -4
- package/src/codex-settings/ui.ts +2 -0
- package/src/index.ts +16 -3
- package/vendor/apply-patch/win32-arm64/apply_patch.exe +0 -0
- package/vendor/apply-patch/win32-x64/apply_patch.exe +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.5
|
|
4
|
+
|
|
5
|
+
- Avoid registering disabled native `web_search` and `image_generation` tools so other extensions can own those names.
|
|
6
|
+
- Preserve other extensions' `web_search` and `image_generation` tools when the matching Codex feature is off.
|
|
7
|
+
- Added a `/codex status` toggle and settings UI option for hiding the Codex footer/statusline.
|
|
8
|
+
|
|
3
9
|
## 1.5.4
|
|
4
10
|
|
|
5
11
|
- Added `/codex` settings UI.
|
package/README.md
CHANGED
|
@@ -42,6 +42,7 @@ Notably:
|
|
|
42
42
|
Use `/codex` to change adapter settings.
|
|
43
43
|
|
|
44
44
|
- `/codex all` — use the Codex tool and prompt adapter on every model
|
|
45
|
+
- `/codex status` — toggle the footer/statusline entry
|
|
45
46
|
- `/codex fast` — toggle priority service tier for the OpenAI Codex provider
|
|
46
47
|
- `/codex search` — toggle native Codex web search
|
|
47
48
|
- `/codex image` — toggle native Codex image generation
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@ import { supportsNativeImageGeneration } from "../tools/image-generation-tool.ts
|
|
|
15
15
|
import { supportsNativeWebSearch } from "../tools/web-search-tool.ts";
|
|
16
16
|
|
|
17
17
|
const ADAPTER_TOOL_NAMES = [...CORE_ADAPTER_TOOL_NAMES, WEB_SEARCH_TOOL_NAME, IMAGE_GENERATION_TOOL_NAME, VIEW_IMAGE_TOOL_NAME];
|
|
18
|
+
const ALWAYS_OWNED_ADAPTER_TOOL_NAMES = [...CORE_ADAPTER_TOOL_NAMES, VIEW_IMAGE_TOOL_NAME];
|
|
18
19
|
|
|
19
20
|
export function syncAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
|
|
20
21
|
if (shouldUseCodexAdapter(ctx, state.config)) {
|
|
@@ -29,32 +30,41 @@ export function shouldUseCodexAdapter(ctx: ExtensionContext, config: CodexConver
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
function enableAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
|
|
32
|
-
const
|
|
33
|
+
const currentAdapterOwnedTools = getAdapterOwnedToolNames(state.config);
|
|
34
|
+
const adapterOwnedTools = state.enabled ? mergeToolNames(state.adapterOwnedToolNames ?? currentAdapterOwnedTools, currentAdapterOwnedTools) : currentAdapterOwnedTools;
|
|
35
|
+
const toolNames = mergeAdapterTools(pi.getActiveTools(), getAdapterToolNames(ctx, state.config), adapterOwnedTools);
|
|
33
36
|
if (!state.enabled) {
|
|
34
37
|
// Preserve the previous active set once so switching away from Codex-like
|
|
35
38
|
// models restores the user's existing Pi tool configuration. Strip adapter
|
|
36
39
|
// tools in case a fresh session starts from persisted/mixed active tools.
|
|
37
|
-
state.previousToolNames = stripAdapterTools(pi.getActiveTools());
|
|
40
|
+
state.previousToolNames = stripAdapterTools(pi.getActiveTools(), adapterOwnedTools);
|
|
38
41
|
state.enabled = true;
|
|
39
42
|
}
|
|
43
|
+
state.adapterOwnedToolNames = currentAdapterOwnedTools;
|
|
40
44
|
pi.setActiveTools(toolNames);
|
|
41
45
|
setStatus(ctx, true, state.config);
|
|
42
46
|
}
|
|
43
47
|
|
|
44
48
|
function disableAdapter(pi: ExtensionAPI, ctx: ExtensionContext, state: AdapterState): void {
|
|
45
49
|
const previousToolNames = state.previousToolNames && state.previousToolNames.length > 0 ? state.previousToolNames : DEFAULT_TOOL_NAMES;
|
|
46
|
-
const
|
|
47
|
-
|
|
50
|
+
const adapterOwnedTools = state.adapterOwnedToolNames ?? getAdapterOwnedToolNames(state.config);
|
|
51
|
+
const restoredTools = restoreTools(previousToolNames, pi.getActiveTools(), adapterOwnedTools);
|
|
52
|
+
if (state.enabled || hasAdapterTools(pi.getActiveTools(), adapterOwnedTools)) {
|
|
48
53
|
pi.setActiveTools(restoredTools);
|
|
49
54
|
}
|
|
50
55
|
if (state.enabled) {
|
|
51
56
|
state.enabled = false;
|
|
57
|
+
state.adapterOwnedToolNames = undefined;
|
|
52
58
|
}
|
|
53
59
|
setStatus(ctx, false, state.config);
|
|
54
60
|
}
|
|
55
61
|
|
|
56
62
|
function setStatus(ctx: ExtensionContext, enabled: boolean, config: CodexConversionConfig): void {
|
|
57
63
|
if (!ctx.hasUI) return;
|
|
64
|
+
if (!config.statusLine) {
|
|
65
|
+
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
58
68
|
const statusConfig = getStatusConfig(ctx, config);
|
|
59
69
|
ctx.ui.setStatus(STATUS_KEY, enabled ? buildStatusText(statusConfig) : undefined);
|
|
60
70
|
}
|
|
@@ -85,25 +95,38 @@ function getAdapterToolNames(ctx: ExtensionContext, config: CodexConversionConfi
|
|
|
85
95
|
return toolNames;
|
|
86
96
|
}
|
|
87
97
|
|
|
88
|
-
|
|
89
|
-
|
|
98
|
+
function getAdapterOwnedToolNames(config: CodexConversionConfig): string[] {
|
|
99
|
+
return [
|
|
100
|
+
...ALWAYS_OWNED_ADAPTER_TOOL_NAMES,
|
|
101
|
+
...(config.webSearch ? [WEB_SEARCH_TOOL_NAME] : []),
|
|
102
|
+
...(config.imageGeneration ? [IMAGE_GENERATION_TOOL_NAME] : []),
|
|
103
|
+
];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function mergeToolNames(...toolNameGroups: string[][]): string[] {
|
|
107
|
+
return [...new Set(toolNameGroups.flat())];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function mergeAdapterTools(activeTools: string[], adapterTools: string[], adapterOwnedTools: string[] = adapterTools): string[] {
|
|
111
|
+
const ownedTools = new Set([...ALWAYS_OWNED_ADAPTER_TOOL_NAMES, ...adapterTools, ...adapterOwnedTools]);
|
|
112
|
+
const preservedTools = activeTools.filter((toolName) => !DEFAULT_TOOL_NAMES.includes(toolName) && !ownedTools.has(toolName));
|
|
90
113
|
return [...adapterTools, ...preservedTools];
|
|
91
114
|
}
|
|
92
115
|
|
|
93
|
-
export function restoreTools(previousTools: string[], activeTools: string[]): string[] {
|
|
94
|
-
const restored = stripAdapterTools(previousTools);
|
|
116
|
+
export function restoreTools(previousTools: string[], activeTools: string[], adapterOwnedTools: string[] = ADAPTER_TOOL_NAMES): string[] {
|
|
117
|
+
const restored = stripAdapterTools(previousTools, adapterOwnedTools);
|
|
95
118
|
for (const toolName of activeTools) {
|
|
96
|
-
if (!
|
|
119
|
+
if (!adapterOwnedTools.includes(toolName) && !restored.includes(toolName)) {
|
|
97
120
|
restored.push(toolName);
|
|
98
121
|
}
|
|
99
122
|
}
|
|
100
123
|
return restored;
|
|
101
124
|
}
|
|
102
125
|
|
|
103
|
-
export function stripAdapterTools(toolNames: string[]): string[] {
|
|
104
|
-
return toolNames.filter((toolName) => !
|
|
126
|
+
export function stripAdapterTools(toolNames: string[], adapterOwnedTools: string[] = ADAPTER_TOOL_NAMES): string[] {
|
|
127
|
+
return toolNames.filter((toolName) => !adapterOwnedTools.includes(toolName));
|
|
105
128
|
}
|
|
106
129
|
|
|
107
|
-
function hasAdapterTools(activeTools: string[]): boolean {
|
|
108
|
-
return activeTools.some((toolName) =>
|
|
130
|
+
function hasAdapterTools(activeTools: string[], adapterOwnedTools: string[]): boolean {
|
|
131
|
+
return activeTools.some((toolName) => adapterOwnedTools.includes(toolName));
|
|
109
132
|
}
|
package/src/adapter/config.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type CodexVerbosity = "low" | "medium" | "high";
|
|
|
7
7
|
export interface CodexConversionConfig {
|
|
8
8
|
fast: boolean;
|
|
9
9
|
imageGeneration: boolean;
|
|
10
|
+
statusLine: boolean;
|
|
10
11
|
useOnAllModels: boolean;
|
|
11
12
|
webSearch: boolean;
|
|
12
13
|
verbosity: CodexVerbosity;
|
|
@@ -16,6 +17,7 @@ export const CODEX_CONVERSION_CONFIG_BASENAME = "pi-codex-conversion.json";
|
|
|
16
17
|
export const DEFAULT_CODEX_CONVERSION_CONFIG: CodexConversionConfig = {
|
|
17
18
|
fast: false,
|
|
18
19
|
imageGeneration: true,
|
|
20
|
+
statusLine: true,
|
|
19
21
|
useOnAllModels: false,
|
|
20
22
|
webSearch: true,
|
|
21
23
|
verbosity: "low",
|
|
@@ -47,6 +49,7 @@ export function readCodexConversionConfig(configPath: string = getCodexConversio
|
|
|
47
49
|
return {
|
|
48
50
|
fast: typeof parsed.fast === "boolean" ? parsed.fast : DEFAULT_CODEX_CONVERSION_CONFIG.fast,
|
|
49
51
|
imageGeneration: typeof parsed.imageGeneration === "boolean" ? parsed.imageGeneration : DEFAULT_CODEX_CONVERSION_CONFIG.imageGeneration,
|
|
52
|
+
statusLine: typeof parsed.statusLine === "boolean" ? parsed.statusLine : DEFAULT_CODEX_CONVERSION_CONFIG.statusLine,
|
|
50
53
|
useOnAllModels: typeof parsed.useOnAllModels === "boolean" ? parsed.useOnAllModels : DEFAULT_CODEX_CONVERSION_CONFIG.useOnAllModels,
|
|
51
54
|
webSearch: typeof parsed.webSearch === "boolean" ? parsed.webSearch : DEFAULT_CODEX_CONVERSION_CONFIG.webSearch,
|
|
52
55
|
verbosity: normalizeCodexVerbosity(parsed.verbosity) ?? DEFAULT_CODEX_CONVERSION_CONFIG.verbosity,
|
package/src/adapter/state.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { syncAdapter } from "../adapter/activation.ts";
|
|
|
9
9
|
import type { AdapterState } from "../adapter/state.ts";
|
|
10
10
|
import { openCodexSettingsScreen } from "./ui.ts";
|
|
11
11
|
|
|
12
|
-
const CODEX_COMMAND_COMPLETIONS = ["all", "fast", "search", "image", "low", "medium", "high"] as const;
|
|
12
|
+
const CODEX_COMMAND_COMPLETIONS = ["all", "status", "fast", "search", "image", "low", "medium", "high"] as const;
|
|
13
13
|
|
|
14
|
-
export function registerCodexCommand(pi: ExtensionAPI, state: AdapterState): void {
|
|
14
|
+
export function registerCodexCommand(pi: ExtensionAPI, state: AdapterState, onConfigApplied?: (config: CodexConversionConfig) => void): void {
|
|
15
15
|
function saveAndApply(ctx: ExtensionContext, nextConfig: CodexConversionConfig): boolean {
|
|
16
16
|
const writeResult = writeCodexConversionConfig(nextConfig);
|
|
17
17
|
if (!writeResult.ok) {
|
|
@@ -19,6 +19,7 @@ export function registerCodexCommand(pi: ExtensionAPI, state: AdapterState): voi
|
|
|
19
19
|
return false;
|
|
20
20
|
}
|
|
21
21
|
state.config = nextConfig;
|
|
22
|
+
onConfigApplied?.(nextConfig);
|
|
22
23
|
syncAdapter(pi, ctx, state);
|
|
23
24
|
return true;
|
|
24
25
|
}
|
|
@@ -37,7 +38,7 @@ export function registerCodexCommand(pi: ExtensionAPI, state: AdapterState): voi
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
if (arg) {
|
|
40
|
-
ctx.ui.notify("Usage: /codex, /codex all, /codex fast, /codex search, /codex image, /codex low|medium|high", "warning");
|
|
41
|
+
ctx.ui.notify("Usage: /codex, /codex all, /codex status, /codex fast, /codex search, /codex image, /codex low|medium|high", "warning");
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
43
44
|
|
|
@@ -57,6 +58,7 @@ export function registerCodexCommand(pi: ExtensionAPI, state: AdapterState): voi
|
|
|
57
58
|
function getCommandConfigUpdate(arg: string, config: CodexConversionConfig): CodexConversionConfig | undefined {
|
|
58
59
|
if (arg === "fast") return { ...config, fast: !config.fast };
|
|
59
60
|
if (arg === "all") return { ...config, useOnAllModels: !config.useOnAllModels };
|
|
61
|
+
if (arg === "status") return { ...config, statusLine: !config.statusLine };
|
|
60
62
|
if (arg === "search") return { ...config, webSearch: !config.webSearch };
|
|
61
63
|
if (arg === "image") return { ...config, imageGeneration: !config.imageGeneration };
|
|
62
64
|
const verbosity = normalizeCodexVerbosity(arg);
|
|
@@ -64,5 +66,5 @@ function getCommandConfigUpdate(arg: string, config: CodexConversionConfig): Cod
|
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
function formatCodexSettings(config: CodexConversionConfig): string {
|
|
67
|
-
return `Codex settings: all models ${config.useOnAllModels ? "on" : "off"}, fast ${config.fast ? "on" : "off"}, web search ${config.webSearch ? "on" : "off"}, image generation ${config.imageGeneration ? "on" : "off"}, verbosity ${config.verbosity}`;
|
|
69
|
+
return `Codex settings: all models ${config.useOnAllModels ? "on" : "off"}, statusline ${config.statusLine ? "on" : "off"}, fast ${config.fast ? "on" : "off"}, web search ${config.webSearch ? "on" : "off"}, image generation ${config.imageGeneration ? "on" : "off"}, verbosity ${config.verbosity}`;
|
|
68
70
|
}
|
package/src/codex-settings/ui.ts
CHANGED
|
@@ -13,6 +13,7 @@ export async function openCodexSettingsScreen(ctx: ExtensionContext, options: Co
|
|
|
13
13
|
await ctx.ui.custom<void>((tui, theme, _kb, done) => {
|
|
14
14
|
const buildItems = (): SettingItem[] => [
|
|
15
15
|
{ id: "useOnAllModels", label: "Use on all models", currentValue: draft.useOnAllModels ? "on" : "off", values: ["off", "on"] },
|
|
16
|
+
{ id: "statusLine", label: "Statusline", currentValue: draft.statusLine ? "on" : "off", values: ["off", "on"] },
|
|
16
17
|
{ id: "fast", label: "Fast mode", currentValue: draft.fast ? "on" : "off", values: ["off", "on"] },
|
|
17
18
|
{ id: "webSearch", label: "Web search", currentValue: draft.webSearch ? "on" : "off", values: ["off", "on"] },
|
|
18
19
|
{ id: "imageGeneration", label: "Image generation", currentValue: draft.imageGeneration ? "on" : "off", values: ["off", "on"] },
|
|
@@ -27,6 +28,7 @@ export async function openCodexSettingsScreen(ctx: ExtensionContext, options: Co
|
|
|
27
28
|
const nextDraft = { ...draft };
|
|
28
29
|
const previousValue = buildItems().find((item) => item.id === id)?.currentValue;
|
|
29
30
|
if (id === "useOnAllModels") nextDraft.useOnAllModels = value === "on";
|
|
31
|
+
if (id === "statusLine") nextDraft.statusLine = value === "on";
|
|
30
32
|
if (id === "fast") nextDraft.fast = value === "on";
|
|
31
33
|
if (id === "webSearch") nextDraft.webSearch = value === "on";
|
|
32
34
|
if (id === "imageGeneration") nextDraft.imageGeneration = value === "on";
|
package/src/index.ts
CHANGED
|
@@ -44,6 +44,19 @@ export default function codexConversion(pi: ExtensionAPI) {
|
|
|
44
44
|
const tracker = createExecCommandTracker();
|
|
45
45
|
const state: AdapterState = { enabled: false, cwd: process.cwd(), promptSkills: [], config: readCodexConversionConfig() };
|
|
46
46
|
const sessions = createExecSessionManager();
|
|
47
|
+
let nativeWebSearchRegistered = false;
|
|
48
|
+
let nativeImageGenerationRegistered = false;
|
|
49
|
+
|
|
50
|
+
function ensureOptionalNativeToolsRegistered(config = state.config): void {
|
|
51
|
+
if (config.webSearch && !nativeWebSearchRegistered) {
|
|
52
|
+
registerWebSearchTool(pi);
|
|
53
|
+
nativeWebSearchRegistered = true;
|
|
54
|
+
}
|
|
55
|
+
if (config.imageGeneration && !nativeImageGenerationRegistered) {
|
|
56
|
+
registerImageGenerationTool(pi);
|
|
57
|
+
nativeImageGenerationRegistered = true;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
47
60
|
|
|
48
61
|
registerOpenAICodexCustomProvider(pi, {
|
|
49
62
|
getCurrentCwd: () => state.cwd,
|
|
@@ -51,9 +64,8 @@ export default function codexConversion(pi: ExtensionAPI) {
|
|
|
51
64
|
registerApplyPatchTool(pi);
|
|
52
65
|
registerExecCommandTool(pi, tracker, sessions);
|
|
53
66
|
registerWriteStdinTool(pi, sessions);
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
registerCodexCommand(pi, state);
|
|
67
|
+
ensureOptionalNativeToolsRegistered();
|
|
68
|
+
registerCodexCommand(pi, state, ensureOptionalNativeToolsRegistered);
|
|
57
69
|
|
|
58
70
|
sessions.onSessionExit((sessionId) => {
|
|
59
71
|
tracker.recordSessionFinished(sessionId);
|
|
@@ -62,6 +74,7 @@ export default function codexConversion(pi: ExtensionAPI) {
|
|
|
62
74
|
pi.on("session_start", async (_event, ctx) => {
|
|
63
75
|
state.cwd = ctx.cwd;
|
|
64
76
|
state.config = readCodexConversionConfig();
|
|
77
|
+
ensureOptionalNativeToolsRegistered();
|
|
65
78
|
state.promptSkills = extractPiPromptSkills(ctx.getSystemPrompt());
|
|
66
79
|
registerViewImageTool(pi, { allowOriginalDetail: supportsOriginalImageDetail(ctx.model) });
|
|
67
80
|
clearApplyPatchRenderState();
|
|
Binary file
|
|
Binary file
|