@oai404iao/pi-codex-minimal-tools 1.4.0 → 2.0.0
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 +44 -17
- package/THIRD_PARTY_NOTICES.md +20 -0
- package/config.schema.json +1 -2
- package/index.ts +2 -0
- package/package.json +14 -13
- package/provenance/openai-codex-ddea03ad-astra.json +54 -0
- package/src/activation.ts +1 -56
- package/src/adapter/compaction/checkpoint.ts +1 -0
- package/src/adapter/compaction/collect.ts +1 -0
- package/src/adapter/compaction/http.ts +1 -0
- package/src/adapter/compaction/request.ts +1 -0
- package/src/adapter/compaction/transport.ts +1 -0
- package/src/adapter/compaction/websocket.ts +1 -0
- package/src/background-image-generation.ts +1 -574
- package/src/capabilities.ts +1 -146
- package/src/codex-http.ts +1 -133
- package/src/codex-identity-extension.ts +1 -339
- package/src/codex-request-profile.ts +1 -45
- package/src/codex-reserved-tools.ts +1 -323
- package/src/codex-wire-identity.ts +1 -596
- package/src/extension/prewarm-snapshot.ts +1 -0
- package/src/extension/provider-presentation.ts +1 -0
- package/src/extension/provider-runtime.ts +1 -0
- package/src/extension/register.ts +36 -0
- package/src/extension/startup-prewarm.ts +1 -0
- package/src/fast-mode.ts +1 -124
- package/src/glyphs.ts +1 -70
- package/src/index.ts +8 -331
- package/src/model-catalog/catalog.ts +1 -636
- package/src/model-catalog/default-models.json +8 -0
- package/src/model-catalog/runtime.ts +1 -113
- package/src/model-catalog/types.ts +1 -95
- package/src/native-compaction.ts +1 -393
- package/src/patch/apply.ts +1 -338
- package/src/patch/parser.ts +1 -224
- package/src/patch/render.ts +1 -201
- package/src/provider-headers.ts +1 -54
- package/src/provider-native-tools.ts +1 -71
- package/src/provider-shim.ts +20 -4511
- package/src/providers/codex-apply-patch-tool.ts +1 -23
- package/src/providers/openai-codex/cache-key.ts +1 -0
- package/src/providers/openai-codex/captured-stream.ts +1 -0
- package/src/providers/openai-codex/constants.ts +1 -0
- package/src/providers/openai-codex/continuation.ts +1 -0
- package/src/providers/openai-codex/errors.ts +1 -0
- package/src/providers/openai-codex/events.ts +1 -0
- package/src/providers/openai-codex/headers.ts +1 -0
- package/src/providers/openai-codex/lite.ts +1 -0
- package/src/providers/openai-codex/message.ts +1 -0
- package/src/providers/openai-codex/prewarm.ts +1 -0
- package/src/providers/openai-codex/proxy.ts +1 -0
- package/src/providers/openai-codex/reasoning.ts +1 -0
- package/src/providers/openai-codex/request-body.ts +1 -0
- package/src/providers/openai-codex/request-context.ts +1 -0
- package/src/providers/openai-codex/request-metadata.ts +1 -0
- package/src/providers/openai-codex/retry.ts +1 -0
- package/src/providers/openai-codex/runtime.ts +1 -0
- package/src/providers/openai-codex/sse.ts +1 -0
- package/src/providers/openai-codex/stream-effects.ts +1 -0
- package/src/providers/openai-codex/stream.ts +1 -0
- package/src/providers/openai-codex/types.ts +1 -0
- package/src/providers/openai-codex/urls.ts +1 -0
- package/src/providers/openai-codex/usage.ts +1 -0
- package/src/providers/openai-codex/websocket-connection.ts +1 -0
- package/src/providers/openai-codex/websocket-events.ts +1 -0
- package/src/providers/openai-codex/websocket-session.ts +1 -0
- package/src/providers/openai-codex/websocket-socket.ts +1 -0
- package/src/providers/openai-codex/websocket-stream.ts +1 -0
- package/src/providers/openai-responses-shared.ts +7 -1463
- package/src/providers/responses/citations.ts +1 -0
- package/src/providers/responses/history.ts +1 -0
- package/src/providers/responses/items.ts +1 -0
- package/src/providers/responses/markdown.ts +1 -0
- package/src/providers/responses/messages.ts +1 -0
- package/src/providers/responses/signatures.ts +1 -0
- package/src/providers/responses/stream-state.ts +1 -0
- package/src/providers/responses/stream.ts +1 -0
- package/src/providers/responses/text-renderer.ts +1 -0
- package/src/providers/responses/text.ts +1 -0
- package/src/providers/responses/tool-identity.ts +1 -0
- package/src/providers/responses/tools.ts +1 -0
- package/src/providers/responses/types.ts +1 -0
- package/src/providers/responses/usage.ts +1 -0
- package/src/settings.ts +1 -247
- package/src/subagent-inline.ts +1 -8
- package/src/tools/apply-patch.ts +1 -84
- package/src/tools/image-generation/capture.ts +1 -0
- package/src/tools/image-generation/display.ts +1 -0
- package/src/tools/image-generation/preview.ts +1 -0
- package/src/tools/image-generation/storage.ts +1 -0
- package/src/tools/image-generation/types.ts +1 -0
- package/src/tools/image-generation.ts +1 -274
- package/src/tools/view-image.ts +1 -98
- package/src/tools/web-search/activity.ts +1 -0
- package/src/tools/web-search/capture.ts +1 -0
- package/src/tools/web-search/render.ts +1 -0
- package/src/tools/web-search.ts +1 -554
- package/src/utils/images.ts +1 -73
- package/src/utils/theme.ts +1 -0
package/src/fast-mode.ts
CHANGED
|
@@ -1,124 +1 @@
|
|
|
1
|
-
|
|
2
|
-
ExtensionAPI,
|
|
3
|
-
ExtensionCommandContext,
|
|
4
|
-
ExtensionContext,
|
|
5
|
-
} from "@earendil-works/pi-coding-agent";
|
|
6
|
-
import {
|
|
7
|
-
modelKey,
|
|
8
|
-
type ModelLike,
|
|
9
|
-
} from "./capabilities.js";
|
|
10
|
-
import { loadModelSettings } from "./model-catalog/runtime.js";
|
|
11
|
-
import type { ResolvedCodexModelSettings } from "./model-catalog/runtime.js";
|
|
12
|
-
import {
|
|
13
|
-
configPath,
|
|
14
|
-
loadSettings,
|
|
15
|
-
updateConfig,
|
|
16
|
-
type CodexMinimalToolsSettings,
|
|
17
|
-
} from "./settings.js";
|
|
18
|
-
|
|
19
|
-
export const FAST_MODE_STATUS_KEY = "codex-fast-mode";
|
|
20
|
-
export const FAST_MODE_SERVICE_TIER = "priority" as const;
|
|
21
|
-
|
|
22
|
-
export function isFastModeModel(model: ModelLike | undefined): boolean {
|
|
23
|
-
return Boolean(loadModelSettings(model).fastServiceTier);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function resolveFastModeServiceTier(
|
|
27
|
-
settings: Pick<CodexMinimalToolsSettings, "enabled" | "fastMode"> & Partial<ResolvedCodexModelSettings>,
|
|
28
|
-
model: ModelLike | undefined,
|
|
29
|
-
): string | undefined {
|
|
30
|
-
if (!settings.enabled || !settings.fastMode) return undefined;
|
|
31
|
-
if (settings.modelProfile) return settings.fastServiceTier;
|
|
32
|
-
return loadModelSettings(model, undefined, settings as CodexMinimalToolsSettings).fastServiceTier;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function applyFastModeServiceTier<T extends Record<string, unknown>>(
|
|
36
|
-
body: T,
|
|
37
|
-
settings: Pick<CodexMinimalToolsSettings, "enabled" | "fastMode"> & Partial<ResolvedCodexModelSettings>,
|
|
38
|
-
model: ModelLike | undefined,
|
|
39
|
-
): T {
|
|
40
|
-
const serviceTier = resolveFastModeServiceTier(settings, model);
|
|
41
|
-
if (!serviceTier || body.service_tier !== undefined) return body;
|
|
42
|
-
return { ...body, service_tier: serviceTier };
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function fastModeLines(ctx: ExtensionContext): string[] {
|
|
46
|
-
const settings = loadSettings(ctx.cwd);
|
|
47
|
-
const model = ctx.model as ModelLike | undefined;
|
|
48
|
-
const modelSettings = loadModelSettings(model, ctx.cwd, settings);
|
|
49
|
-
const activeTier = resolveFastModeServiceTier(modelSettings, model);
|
|
50
|
-
return [
|
|
51
|
-
"Codex Fast mode",
|
|
52
|
-
`enabled: ${settings.fastMode}`,
|
|
53
|
-
`service tier: ${modelSettings.fastServiceTier ?? "(unsupported)"}`,
|
|
54
|
-
`model: ${modelKey(model)}`,
|
|
55
|
-
`active for current model: ${Boolean(activeTier)}`,
|
|
56
|
-
`config: ${configPath()}`,
|
|
57
|
-
];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export function syncFastModeStatus(ctx: ExtensionContext): void {
|
|
61
|
-
const settings = loadSettings(ctx.cwd);
|
|
62
|
-
const model = ctx.model as ModelLike | undefined;
|
|
63
|
-
const tier = resolveFastModeServiceTier(loadModelSettings(model, ctx.cwd, settings), model);
|
|
64
|
-
const ui = ctx.ui as ExtensionContext["ui"] | undefined;
|
|
65
|
-
ui?.setStatus?.(
|
|
66
|
-
FAST_MODE_STATUS_KEY,
|
|
67
|
-
tier,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function showFastModeStatus(ctx: ExtensionCommandContext): void {
|
|
72
|
-
syncFastModeStatus(ctx as ExtensionContext);
|
|
73
|
-
ctx.ui.notify(fastModeLines(ctx as ExtensionContext).join("\n"), "info");
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export function registerFastMode(pi: ExtensionAPI): void {
|
|
77
|
-
pi.registerCommand("fast", {
|
|
78
|
-
description: "Toggle model-profile Fast mode. Usage: /fast [on|off|status]",
|
|
79
|
-
handler: async (args: string, ctx) => {
|
|
80
|
-
const command = args.trim().toLowerCase().split(/\s+/, 1)[0] ?? "";
|
|
81
|
-
const settings = loadSettings(ctx.cwd);
|
|
82
|
-
let patch: Partial<CodexMinimalToolsSettings> | undefined;
|
|
83
|
-
|
|
84
|
-
switch (command) {
|
|
85
|
-
case "":
|
|
86
|
-
patch = { fastMode: !settings.fastMode };
|
|
87
|
-
break;
|
|
88
|
-
case "on":
|
|
89
|
-
patch = { fastMode: true };
|
|
90
|
-
break;
|
|
91
|
-
case "off":
|
|
92
|
-
patch = { fastMode: false };
|
|
93
|
-
break;
|
|
94
|
-
case "status":
|
|
95
|
-
showFastModeStatus(ctx);
|
|
96
|
-
return;
|
|
97
|
-
default:
|
|
98
|
-
ctx.ui.notify("Usage: /fast [on|off|status]", "warning");
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
try {
|
|
103
|
-
updateConfig(patch);
|
|
104
|
-
showFastModeStatus(ctx);
|
|
105
|
-
} catch (error) {
|
|
106
|
-
ctx.ui.notify(
|
|
107
|
-
`Failed to update Fast mode: ${error instanceof Error ? error.message : String(error)}`,
|
|
108
|
-
"error",
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
},
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
pi.on("session_start", async (_event, ctx) => {
|
|
115
|
-
syncFastModeStatus(ctx);
|
|
116
|
-
});
|
|
117
|
-
pi.on("model_select", async (_event, ctx) => {
|
|
118
|
-
syncFastModeStatus(ctx);
|
|
119
|
-
});
|
|
120
|
-
pi.on("session_shutdown", async (_event, ctx) => {
|
|
121
|
-
const ui = ctx.ui as ExtensionContext["ui"] | undefined;
|
|
122
|
-
ui?.setStatus?.(FAST_MODE_STATUS_KEY, undefined);
|
|
123
|
-
});
|
|
124
|
-
}
|
|
1
|
+
export * from "@oai404iao/pi-codex-core/internal/fast-mode";
|
package/src/glyphs.ts
CHANGED
|
@@ -1,70 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export type GlyphStyle = "unicode" | "ascii";
|
|
4
|
-
|
|
5
|
-
export function glyphStyle(cwd?: string): GlyphStyle {
|
|
6
|
-
return loadSettings(cwd).glyphStyle;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export const GLYPHS = {
|
|
10
|
-
unicode: {
|
|
11
|
-
frame: { tl: "┏", tr: "┓", bl: "┗", br: "┛", h: "━", v: "┃" },
|
|
12
|
-
line: "─",
|
|
13
|
-
tree: { mid: "├─ ", last: "└─ ", stem: "│ ", blank: " " },
|
|
14
|
-
bullet: "● ",
|
|
15
|
-
emptyBullet: "○ ",
|
|
16
|
-
dot: " · ",
|
|
17
|
-
ok: "✓",
|
|
18
|
-
fail: "✗",
|
|
19
|
-
warn: "▲",
|
|
20
|
-
diamond: "◆",
|
|
21
|
-
prompt: "π",
|
|
22
|
-
ellipsis: "…",
|
|
23
|
-
arrow: "→",
|
|
24
|
-
codeBar: "▌",
|
|
25
|
-
},
|
|
26
|
-
ascii: {
|
|
27
|
-
frame: { tl: "+", tr: "+", bl: "+", br: "+", h: "-", v: "|" },
|
|
28
|
-
line: "-",
|
|
29
|
-
tree: { mid: "|-- ", last: "`-- ", stem: "| ", blank: " " },
|
|
30
|
-
bullet: "* ",
|
|
31
|
-
emptyBullet: "o ",
|
|
32
|
-
dot: " - ",
|
|
33
|
-
ok: "+",
|
|
34
|
-
fail: "x",
|
|
35
|
-
warn: "!",
|
|
36
|
-
diamond: "*",
|
|
37
|
-
prompt: "pi",
|
|
38
|
-
ellipsis: "...",
|
|
39
|
-
arrow: "->",
|
|
40
|
-
codeBar: "|",
|
|
41
|
-
},
|
|
42
|
-
} as const;
|
|
43
|
-
|
|
44
|
-
export function glyphs(cwd?: string): (typeof GLYPHS)[GlyphStyle] {
|
|
45
|
-
return GLYPHS[glyphStyle(cwd)];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function truncateIndicator(cwd?: string): string {
|
|
49
|
-
return glyphs(cwd).ellipsis;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function truncateText(text: string, maxChars: number, cwd?: string): string {
|
|
53
|
-
if (text.length <= maxChars) return text;
|
|
54
|
-
const indicator = truncateIndicator(cwd);
|
|
55
|
-
return `${text.slice(0, Math.max(0, maxChars - indicator.length))}${indicator}`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export function dot(cwd?: string): string {
|
|
59
|
-
return glyphs(cwd).dot;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function treeGlyph(branch: "├" | "└" | "│", cwd?: string): string {
|
|
63
|
-
const tree = glyphs(cwd).tree;
|
|
64
|
-
if (branch === "│") return tree.stem;
|
|
65
|
-
return branch === "└" ? tree.last : tree.mid;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function frameGlyphs(cwd?: string): (typeof GLYPHS)[GlyphStyle]["frame"] {
|
|
69
|
-
return glyphs(cwd).frame;
|
|
70
|
-
}
|
|
1
|
+
export * from "@oai404iao/pi-codex-runtime/internal/glyphs";
|
package/src/index.ts
CHANGED
|
@@ -1,334 +1,11 @@
|
|
|
1
|
-
import type { ExtensionAPI
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
computeNextActiveTools,
|
|
7
|
-
computeToolCapabilities,
|
|
8
|
-
modelKey,
|
|
9
|
-
NATIVE_MUTATION_TOOL_NAMES,
|
|
10
|
-
PACKAGE_TOOL_NAMES,
|
|
11
|
-
type ModelLike,
|
|
12
|
-
type NativeMutationToolName,
|
|
13
|
-
} from "./capabilities.js";
|
|
14
|
-
import {
|
|
15
|
-
registerOpenAIResponsesProviders,
|
|
16
|
-
type OpenAIResponsesProviderController,
|
|
17
|
-
} from "./provider-shim.js";
|
|
18
|
-
import { rewriteNativeOpenAiTools } from "./provider-native-tools.js";
|
|
19
|
-
import { configPath, loadSettings, settingsDiagnostics } from "./settings.js";
|
|
20
|
-
import {
|
|
21
|
-
modelCatalogDiagnostics,
|
|
22
|
-
modelsPath,
|
|
23
|
-
resolveModelProfile,
|
|
24
|
-
} from "./model-catalog/catalog.js";
|
|
25
|
-
import { loadModelSettings } from "./model-catalog/runtime.js";
|
|
26
|
-
import { createApplyPatchToolDefinition } from "./tools/apply-patch.js";
|
|
27
|
-
import { createImageGenerationToolDefinition } from "./tools/image-generation.js";
|
|
28
|
-
import { createWebSearchToolDefinition } from "./tools/web-search.js";
|
|
29
|
-
import { viewImage, viewImageToolSchema, type ValidatedImage, type ViewImageInput } from "./tools/view-image.js";
|
|
30
|
-
import { glyphs } from "./glyphs.js";
|
|
31
|
-
import { resolveCodexRequestProfile } from "./codex-request-profile.js";
|
|
32
|
-
import { registerNativeCompaction } from "./native-compaction.js";
|
|
33
|
-
import { registerFastMode, resolveFastModeServiceTier } from "./fast-mode.js";
|
|
34
|
-
|
|
35
|
-
const INSTALL_SYMBOL = Symbol.for("pi-codex-minimal-tools.installed");
|
|
36
|
-
|
|
37
|
-
function terminalImageProtocol(): "kitty" | "iterm2" | null {
|
|
38
|
-
return getCapabilities().images ?? null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function formatBytes(bytes: number): string {
|
|
42
|
-
if (!Number.isFinite(bytes) || bytes < 0) return "unknown size";
|
|
43
|
-
if (bytes < 1024) return `${bytes} B`;
|
|
44
|
-
if (bytes < 1024 * 1024) return `${Math.round(bytes / 102.4) / 10}K`;
|
|
45
|
-
return `${Math.round(bytes / (1024 * 102.4)) / 10}M`;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function viewImageCallText(args: ViewImageInput | undefined, theme: any): string {
|
|
49
|
-
const path = typeof args?.path === "string" ? args.path : "image";
|
|
50
|
-
const detail = args?.detail && args.detail !== "auto" ? ` ${theme.fg("dim", `${glyphs().dot.trim()} ${args.detail}`)}` : "";
|
|
51
|
-
return `${theme.fg("accent", glyphs().bullet)}${theme.fg("text", theme.bold("View Image "))}${theme.fg("accent", path)}${detail}`;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function viewImageResultText(details: ValidatedImage | undefined, theme: any): string {
|
|
55
|
-
if (!details) return `${theme.fg("accent", glyphs().bullet)}${theme.fg("text", theme.bold("View Image"))}${theme.fg("dim", `${glyphs().dot}image loaded`)}`;
|
|
56
|
-
const type = details.mimeType.replace(/^image\//, "").toUpperCase();
|
|
57
|
-
const protocol = terminalImageProtocol();
|
|
58
|
-
const preview = protocol ? theme.fg("success", `inline ${protocol}`) : theme.fg("warning", "fallback");
|
|
59
|
-
return `${theme.fg("accent", glyphs().bullet)}${theme.fg("text", theme.bold("View Image "))}${theme.fg("accent", details.displayPath)}${theme.fg("dim", glyphs().dot)}${theme.fg("success", type)}${theme.fg("dim", `${glyphs().dot}${formatBytes(details.sizeBytes)}${glyphs().dot}`)}${preview}`;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function emptyComponent(): Component {
|
|
63
|
-
return { invalidate() {}, render: () => [] };
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function textComponent(text: string): Component {
|
|
67
|
-
return new Text(text, 0, 0);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
function viewImageResultComponent(result: any, options: any, theme: any, context: any): Component {
|
|
71
|
-
if (options?.isPartial) return emptyComponent();
|
|
72
|
-
const details = result?.details as ValidatedImage | undefined;
|
|
73
|
-
const imagePart = result?.content?.find?.((part: any) => part?.type === "image" && typeof part.data === "string" && typeof part.mimeType === "string");
|
|
74
|
-
const header = textComponent(viewImageResultText(details, theme));
|
|
75
|
-
if (!imagePart) return header;
|
|
76
|
-
const imageTheme = { fallbackColor: (text: string) => theme.fg("dim", text) };
|
|
77
|
-
const maxHeightCells = options?.expanded ? 28 : 18;
|
|
78
|
-
const image = new Image(imagePart.data, imagePart.mimeType, imageTheme, { maxWidthCells: 80, maxHeightCells, filename: details?.displayPath });
|
|
79
|
-
return {
|
|
80
|
-
invalidate() {
|
|
81
|
-
header.invalidate();
|
|
82
|
-
image.invalidate();
|
|
83
|
-
},
|
|
84
|
-
render(width: number): string[] {
|
|
85
|
-
return [...header.render(width), ...image.render(width)];
|
|
86
|
-
},
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function contextModel(ctx: ExtensionContext): ModelLike | undefined {
|
|
91
|
-
return ctx.model as ModelLike | undefined;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
type SuppressedMutationTools = Map<NativeMutationToolName, number>;
|
|
95
|
-
|
|
96
|
-
function captureSuppressedMutationTools(
|
|
97
|
-
activeTools: readonly string[],
|
|
98
|
-
removedTools: readonly string[],
|
|
99
|
-
suppressed: SuppressedMutationTools,
|
|
100
|
-
): void {
|
|
101
|
-
for (const name of NATIVE_MUTATION_TOOL_NAMES) {
|
|
102
|
-
if (!removedTools.includes(name) || suppressed.has(name)) continue;
|
|
103
|
-
const index = activeTools.indexOf(name);
|
|
104
|
-
if (index >= 0) suppressed.set(name, index);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function restoreSuppressedMutationTools(activeTools: readonly string[], suppressed: SuppressedMutationTools): string[] {
|
|
109
|
-
if (suppressed.size === 0) return [...activeTools];
|
|
110
|
-
|
|
111
|
-
const restored = [...activeTools];
|
|
112
|
-
for (const [name, index] of [...suppressed.entries()].sort(([, left], [, right]) => left - right)) {
|
|
113
|
-
if (!restored.includes(name)) restored.splice(Math.min(index, restored.length), 0, name);
|
|
114
|
-
}
|
|
115
|
-
suppressed.clear();
|
|
116
|
-
return restored;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function syncActiveTools(
|
|
120
|
-
pi: ExtensionAPI,
|
|
121
|
-
ctx: ExtensionContext,
|
|
122
|
-
toolsRegistered: boolean,
|
|
123
|
-
suppressedMutationTools: SuppressedMutationTools,
|
|
124
|
-
): void {
|
|
125
|
-
const active = pi.getActiveTools?.() ?? [];
|
|
126
|
-
const settings = loadSettings(ctx.cwd);
|
|
127
|
-
const supportedModelsLoaded = hasConfiguredModelsLoaded(ctx, settings);
|
|
128
|
-
if (!toolsRegistered || !supportedModelsLoaded) {
|
|
129
|
-
const next = restoreSuppressedMutationTools(
|
|
130
|
-
active.filter((name) => !PACKAGE_TOOL_NAMES.includes(name as never)),
|
|
131
|
-
suppressedMutationTools,
|
|
132
|
-
);
|
|
133
|
-
if (next.join("\0") !== active.join("\0")) pi.setActiveTools(next);
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
const next = computeNextActiveTools(active, contextModel(ctx), settings);
|
|
137
|
-
captureSuppressedMutationTools(active, next.removed, suppressedMutationTools);
|
|
138
|
-
const activeTools = next.activeTools.includes("apply_patch")
|
|
139
|
-
? next.activeTools
|
|
140
|
-
: restoreSuppressedMutationTools(next.activeTools, suppressedMutationTools);
|
|
141
|
-
if (activeTools.join("\0") !== active.join("\0")) pi.setActiveTools(activeTools);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function statusLines(pi: ExtensionAPI, ctx: ExtensionContext): string[] {
|
|
145
|
-
const settings = loadSettings(ctx.cwd);
|
|
146
|
-
const model = contextModel(ctx);
|
|
147
|
-
const modelSettings = loadModelSettings(model, ctx.cwd, settings);
|
|
148
|
-
const capabilities = computeToolCapabilities(model, settings);
|
|
149
|
-
const requestProfile = resolveCodexRequestProfile(modelSettings.requestProfile);
|
|
150
|
-
const modelProfile = modelSettings.modelProfile;
|
|
151
|
-
const active = new Set(pi.getActiveTools?.() ?? []);
|
|
152
|
-
const fastModeTier = resolveFastModeServiceTier(modelSettings, model);
|
|
153
|
-
return [
|
|
154
|
-
"Codex Minimal Tools",
|
|
155
|
-
`model: ${modelKey(model)}`,
|
|
156
|
-
`config: ${configPath()}`,
|
|
157
|
-
`models: ${modelsPath()}`,
|
|
158
|
-
`model profile: ${modelProfile ? `${modelProfile.sources.join("+")} #${modelProfile.profileHash}` : "(none)"}`,
|
|
159
|
-
`configured models loaded: ${hasConfiguredModelsLoaded(ctx, settings)}`,
|
|
160
|
-
`enabled: ${settings.enabled}`,
|
|
161
|
-
`autoEnable: ${settings.autoEnable}`,
|
|
162
|
-
`provider shim: ${modelSettings.providerShimActive ? "active" : "inactive"}`,
|
|
163
|
-
`responses endpoint: ${modelSettings.apiKeyMode ? "openai" : "codex"}`,
|
|
164
|
-
`responses transport: ${modelSettings.openaiTransport}`,
|
|
165
|
-
`Responses WebSocket prewarm: ${modelSettings.openaiWebSocketPrewarm}`,
|
|
166
|
-
`fast mode: ${settings.fastMode ? modelSettings.fastServiceTier ?? "on (unsupported)" : "off"}${fastModeTier ? ", active" : ""}`,
|
|
167
|
-
`compaction: ${modelSettings.compactionMode}`,
|
|
168
|
-
`request profile: ${requestProfile.responsesMode}/${requestProfile.patchTransport}, summary=${requestProfile.reasoningSummary}, system=${requestProfile.systemPromptPlacement}, hosted=${requestProfile.supportsHostedTools}, parallel=${requestProfile.supportsParallelTools}`,
|
|
169
|
-
`web search: ${modelSettings.webSearchImplementation ?? "off"}`,
|
|
170
|
-
`image generation: ${modelSettings.imageGenerationImplementation ?? "off"}`,
|
|
171
|
-
`legacy additionalModelIds: ${settings.additionalModelIds.length > 0 ? settings.additionalModelIds.join(", ") : "(none)"}`,
|
|
172
|
-
`apiKeyMode: ${modelSettings.apiKeyMode}`,
|
|
173
|
-
`native provider shim: ${settings.enabled ? "registered" : "disabled"}`,
|
|
174
|
-
"tools:",
|
|
175
|
-
...Object.entries(capabilities).map(([name, capability]) => `- ${name}: ${capability.enabled ? "supported" : "disabled"}${active.has(name) ? ", active" : ""} — ${capability.reason}`),
|
|
176
|
-
];
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function registerDiagnosticCommand(pi: ExtensionAPI): void {
|
|
180
|
-
const showDoctor = (ctx: ExtensionCommandContext) => {
|
|
181
|
-
const settings = loadSettings(ctx.cwd);
|
|
182
|
-
const lines = statusLines(pi, ctx as ExtensionContext);
|
|
183
|
-
lines.push(`image output dir: ${settings.imageOutputDir}`);
|
|
184
|
-
lines.push(`OPENAI_API_KEY: ${process.env.OPENAI_API_KEY ? "present" : "not set"}`);
|
|
185
|
-
const diagnostics = settingsDiagnostics();
|
|
186
|
-
if (diagnostics.length > 0) lines.push("settings diagnostics:", ...diagnostics.map((line) => `- ${line}`));
|
|
187
|
-
const catalogDiagnostics = modelCatalogDiagnostics();
|
|
188
|
-
if (catalogDiagnostics.length > 0) lines.push("model catalog diagnostics:", ...catalogDiagnostics.map((line) => `- ${line}`));
|
|
189
|
-
const profileDiagnostics = loadModelSettings(contextModel(ctx), ctx.cwd, settings)
|
|
190
|
-
.modelProfile?.diagnostics
|
|
191
|
-
.filter((line) => !catalogDiagnostics.includes(line)) ?? [];
|
|
192
|
-
if (profileDiagnostics.length > 0) {
|
|
193
|
-
lines.push("active model profile diagnostics:", ...profileDiagnostics.map((line) => `- ${line}`));
|
|
194
|
-
}
|
|
195
|
-
ctx.ui.notify(lines.join("\n"), "info");
|
|
196
|
-
};
|
|
197
|
-
pi.registerCommand("codex-minimal-tools", {
|
|
198
|
-
description: "Show Codex Minimal Tools status. Usage: /codex-minimal-tools | /codex-minimal-tools:doctor",
|
|
199
|
-
handler: async (args: string, ctx) => {
|
|
200
|
-
const subcommand = args.trim().split(/\s+/, 1)[0]?.toLowerCase();
|
|
201
|
-
if (subcommand === "doctor") {
|
|
202
|
-
showDoctor(ctx);
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
if (!subcommand) {
|
|
206
|
-
ctx.ui.notify(statusLines(pi, ctx as ExtensionContext).join("\n"), "info");
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
ctx.ui.notify(statusLines(pi, ctx as ExtensionContext).join("\n"), "info");
|
|
210
|
-
},
|
|
211
|
-
});
|
|
212
|
-
pi.registerCommand("codex-minimal-tools:doctor", {
|
|
213
|
-
description: "Run lightweight self-checks",
|
|
214
|
-
handler: async (_args: string, ctx) => showDoctor(ctx),
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function registerTools(
|
|
219
|
-
pi: ExtensionAPI,
|
|
220
|
-
providerController?: OpenAIResponsesProviderController,
|
|
221
|
-
): void {
|
|
222
|
-
pi.registerTool(createImageGenerationToolDefinition({
|
|
223
|
-
loadSettings: (cwd, model) => loadModelSettings(model, cwd),
|
|
224
|
-
getCurrentTurnId: (sessionId) => providerController?.getCurrentTurnId(sessionId),
|
|
225
|
-
}) as never);
|
|
226
|
-
pi.registerTool(createWebSearchToolDefinition({
|
|
227
|
-
getCurrentTurnId: (sessionId) => providerController?.getCurrentTurnId(sessionId),
|
|
228
|
-
getRequestIdentity: (sessionId) =>
|
|
229
|
-
providerController?.getRequestIdentity?.(sessionId),
|
|
230
|
-
}) as never);
|
|
231
|
-
pi.registerTool({
|
|
232
|
-
renderShell: "self",
|
|
233
|
-
name: "view_image",
|
|
234
|
-
label: "View Image",
|
|
235
|
-
description: "Inspect a local image file by returning image content to the model. Relative paths resolve against ctx.cwd; a leading @ is accepted.",
|
|
236
|
-
promptSnippet: "Inspect local image files by path.",
|
|
237
|
-
promptGuidelines: ["Use view_image when you need to inspect a local image file; pass the path in the path argument."],
|
|
238
|
-
parameters: viewImageToolSchema,
|
|
239
|
-
async execute(_toolCallId: string, params: ViewImageInput, _signal: AbortSignal | undefined, _onUpdate: unknown, ctx: ExtensionContext) {
|
|
240
|
-
const settings = loadSettings(ctx.cwd);
|
|
241
|
-
return viewImage(params, ctx.cwd, { workspaceOnly: settings.viewImageWorkspaceOnly }) as never;
|
|
242
|
-
},
|
|
243
|
-
renderCall(args: ViewImageInput, theme: any, context: any) {
|
|
244
|
-
if (context?.executionStarted && !context?.isPartial) return emptyComponent();
|
|
245
|
-
return textComponent(viewImageCallText(args, theme));
|
|
246
|
-
},
|
|
247
|
-
renderResult(result: any, options: any, theme: any, context: any) {
|
|
248
|
-
return viewImageResultComponent(result, options, theme, context);
|
|
249
|
-
},
|
|
250
|
-
} as never);
|
|
251
|
-
pi.registerTool(createApplyPatchToolDefinition({
|
|
252
|
-
deferRendering: loadSettings().deferApplyPatchRendering,
|
|
253
|
-
}) as never);
|
|
254
|
-
}
|
|
1
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import codexImagegen from "@oai404iao/pi-codex-imagegen";
|
|
3
|
+
import codexWebSearch from "@oai404iao/pi-codex-web-search";
|
|
4
|
+
import codexCore from "@oai404iao/pi-codex-core";
|
|
255
5
|
|
|
6
|
+
/** Legacy installation entry; shared session claims deduplicate separately installed packages. */
|
|
256
7
|
export default function codexMinimalTools(pi: ExtensionAPI): void {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
let currentCwd = process.cwd();
|
|
262
|
-
let toolsRegistered = false;
|
|
263
|
-
let providerController: OpenAIResponsesProviderController | undefined;
|
|
264
|
-
const suppressedMutationTools: SuppressedMutationTools = new Map();
|
|
265
|
-
const ensureToolsRegistered = (ctx: ExtensionContext): boolean => {
|
|
266
|
-
currentCwd = ctx.cwd;
|
|
267
|
-
if (toolsRegistered) return true;
|
|
268
|
-
const settings = loadSettings(ctx.cwd);
|
|
269
|
-
const supportedModelsLoaded = hasConfiguredModelsLoaded(ctx, settings);
|
|
270
|
-
if (!settings.enabled || !supportedModelsLoaded) return false;
|
|
271
|
-
registerTools(pi, providerController);
|
|
272
|
-
toolsRegistered = true;
|
|
273
|
-
return true;
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
pi.on("session_start", async (_event, ctx) => {
|
|
277
|
-
syncActiveTools(pi, ctx, ensureToolsRegistered(ctx), suppressedMutationTools);
|
|
278
|
-
});
|
|
279
|
-
pi.on("model_select", async (_event, ctx) => {
|
|
280
|
-
syncActiveTools(pi, ctx, ensureToolsRegistered(ctx), suppressedMutationTools);
|
|
281
|
-
});
|
|
282
|
-
pi.on("thinking_level_select", async (_event, ctx) => {
|
|
283
|
-
syncActiveTools(pi, ctx, ensureToolsRegistered(ctx), suppressedMutationTools);
|
|
284
|
-
});
|
|
285
|
-
pi.on("session_shutdown", async () => {
|
|
286
|
-
const active = pi.getActiveTools?.() ?? [];
|
|
287
|
-
const restored = restoreSuppressedMutationTools(active, suppressedMutationTools);
|
|
288
|
-
if (restored.join("\0") !== active.join("\0")) pi.setActiveTools(restored);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
const initialSettings = loadSettings(currentCwd);
|
|
292
|
-
if (initialSettings.enabled) {
|
|
293
|
-
providerController = registerOpenAIResponsesProviders(pi, { getCurrentCwd: () => currentCwd });
|
|
294
|
-
registerNativeCompaction(pi, providerController);
|
|
295
|
-
registerBackgroundImageGenerationCommand(pi);
|
|
296
|
-
// Pi renders the target transcript before session_start when switching
|
|
297
|
-
// sessions. Register definitions during extension load so resumed tool
|
|
298
|
-
// rows can resolve their custom renderers instead of falling back to raw
|
|
299
|
-
// argument JSON. syncActiveTools still controls model-specific activation.
|
|
300
|
-
registerTools(pi, providerController);
|
|
301
|
-
toolsRegistered = true;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
registerDiagnosticCommand(pi);
|
|
305
|
-
registerFastMode(pi);
|
|
306
|
-
|
|
307
|
-
pi.on("before_provider_request", (event, ctx) => {
|
|
308
|
-
currentCwd = ctx.cwd;
|
|
309
|
-
const settings = loadSettings(ctx.cwd);
|
|
310
|
-
const model = contextModel(ctx);
|
|
311
|
-
const modelSettings = loadModelSettings(model, ctx.cwd, settings);
|
|
312
|
-
const profile = resolveModelProfile(model, { settings });
|
|
313
|
-
if (
|
|
314
|
-
!settings.enabled
|
|
315
|
-
|| !profile?.effective.enabled
|
|
316
|
-
|| !modelSettings.providerShimActive
|
|
317
|
-
|| !modelSettings.nativeProviderTools
|
|
318
|
-
) return undefined;
|
|
319
|
-
const capabilities = computeToolCapabilities(contextModel(ctx), settings);
|
|
320
|
-
const webSearch = profile.effective.tools.webSearch;
|
|
321
|
-
const result = rewriteNativeOpenAiTools(event.payload, {
|
|
322
|
-
imageModel: settings.imageModel,
|
|
323
|
-
imageGeneration: modelSettings.imageGenerationImplementation ?? false,
|
|
324
|
-
webSearch: capabilities.web_search.enabled
|
|
325
|
-
&& webSearch
|
|
326
|
-
? {
|
|
327
|
-
implementation: webSearch.implementation,
|
|
328
|
-
contentTypes: webSearch.contentTypes,
|
|
329
|
-
}
|
|
330
|
-
: false,
|
|
331
|
-
});
|
|
332
|
-
return result.rewritten.length > 0 ? result.payload : undefined;
|
|
333
|
-
});
|
|
8
|
+
codexImagegen(pi);
|
|
9
|
+
codexWebSearch(pi);
|
|
10
|
+
codexCore(pi);
|
|
334
11
|
}
|