import { registerQuotaManagement } from "./quota/extension.ts"; import { registerAutoReasoning } from "./tools/change-reasoning/definition.ts"; import { registerModelToolPolicy } from "./contributions/model-tool-policy.ts"; import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent"; import registerNativeCompaction from "./compaction/index.ts"; import { applyCodexCompatibility } from "./compatibility.ts"; import registerContextWindow from "./context-window.ts"; import { registerCodexNativeXSettings } from "./contributions/xsettings.ts"; import { type CodexDiagnosticsController, createCodexDiagnosticsController } from "./diagnostics/controller.ts"; import registerFastMode from "./fast-mode.ts"; import { registerCodexPromptPayloadAdapter } from "./prompt-payload-adapter.ts"; import { registerOpenAICodexProvider } from "./provider/provider.ts"; import type { CodexProviderRuntime } from "./provider/runtime.ts"; import { registerTextVerbosity } from "./provider/text-verbosity.ts"; import { createWebRunTool } from "./tools/web-run/definition.ts"; import { registerWebCitations } from "./ui/web-citations.ts"; function reportDiagnosticsFailure(ctx: ExtensionContext, action: string, error: unknown): void { if (!ctx.hasUI) return; try { ctx.ui.notify( `Codex cache diagnostics could not ${action}: ${error instanceof Error ? error.message : String(error)}`, "warning", ); } catch { // Optional diagnostics must not affect provider lifecycle. } } export function registerCodexNativeLifecycle( pi: Pick, runtime: Pick, diagnostics: CodexDiagnosticsController, ): { settingsChanged(): Promise } { let currentContext: ExtensionContext | undefined; const configureDiagnostics = async (ctx: ExtensionContext, action: string): Promise => { try { await diagnostics.configure(ctx); } catch (error) { reportDiagnosticsFailure(ctx, action, error); } }; pi.on("cache_warming_decision", (_event, ctx) => { // Codex cannot honor Pi's one-token warming cap; do not advance its live response chain. if (ctx.model?.provider === "openai-codex") return { action: "stop" }; return undefined; }); pi.on("session_start", async (_event, ctx) => { currentContext = ctx; runtime.startSession(ctx); await configureDiagnostics(ctx, "start"); }); pi.on("model_select", async (_event, ctx) => { currentContext = ctx; runtime.selectModel(ctx); await configureDiagnostics(ctx, "reconfigure"); }); pi.on("session_shutdown", async (_event, ctx) => { currentContext = undefined; try { await diagnostics.shutdown(); } catch (error) { reportDiagnosticsFailure(ctx, "stop", error); } finally { runtime.shutdownSession(ctx); } }); return { async settingsChanged() { if (currentContext) await configureDiagnostics(currentContext, "reconfigure"); }, }; } export default function codexNativeExtension(pi: ExtensionAPI): void { registerWebCitations(pi); const unregisterPromptPayloadAdapter = registerCodexPromptPayloadAdapter(); const unregisterModelToolPolicy = registerModelToolPolicy(pi); registerAutoReasoning(pi); registerQuotaManagement(pi); const webRunTool = createWebRunTool(); const runtime = registerOpenAICodexProvider(pi); let applyingModelCompatibility = false; const applyModelCompatibility = async (_event: unknown, ctx: ExtensionContext): Promise => { if (applyingModelCompatibility || !ctx.model) return; const model = applyCodexCompatibility(ctx.model); if (!model || model === ctx.model) return; applyingModelCompatibility = true; try { await pi.setModel(model); } finally { applyingModelCompatibility = false; } }; pi.on("session_start", applyModelCompatibility); pi.on("model_select", applyModelCompatibility); const diagnostics = createCodexDiagnosticsController(runtime); pi.registerTool(webRunTool); const contextWindow = registerContextWindow(pi); registerNativeCompaction(pi, { resetTransportAfterCompaction: (sessionId) => runtime.resetTransportAfterCompaction(sessionId), startCompactionPrewarm: (input) => runtime.startCompactionPrewarm(input), }); const fastMode = registerFastMode(pi); registerTextVerbosity(pi); const lifecycle = registerCodexNativeLifecycle(pi, runtime, diagnostics); const unregisterXSettings = registerCodexNativeXSettings(async (settings) => { fastMode.settingsChanged(settings); await contextWindow.settingsChanged(settings); await lifecycle.settingsChanged(); }); pi.on("session_shutdown", (event) => { if (event.reason !== "reload" && event.reason !== "quit") return; unregisterPromptPayloadAdapter(); unregisterModelToolPolicy(); fastMode.dispose(); contextWindow.dispose(); unregisterXSettings(); }); }