From b1a2f2f6b57c4a4cd34953d77ef1b9d6d1c29dc6 Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Tue, 22 Sep 2026 13:55:17 +0300 Subject: [PATCH 1/2] feat(integrations): route gpt-* pi models through openai-responses api --- src/integrations/pi.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/integrations/pi.ts b/src/integrations/pi.ts index ab63869..40f23a7 100644 --- a/src/integrations/pi.ts +++ b/src/integrations/pi.ts @@ -18,6 +18,7 @@ export type ThinkingLevelMap = Partial>; export type PiModelEntry = { id: string; + api?: string; contextWindow?: number; name?: string; input?: string[]; @@ -90,6 +91,7 @@ export function deriveThinkingFields( } const isDeepSeekModel = (id: string): boolean => id.startsWith("deepseek"); +const isGptModel = (id: string): boolean => id.startsWith("gpt-"); /** Project one daemon model onto a pi config entry. */ export function buildPiModelEntry( @@ -113,6 +115,15 @@ export function buildPiModelEntry( if (mods.includes("image")) input.push("image"); entry.input = input; + // gpt-* models are served through OpenAI's Responses API; the provider-level + // `api: "openai-completions"` stays the default for everything else. For + // non-gpt models keep whatever per-model api the user curated. + if (isGptModel(model.id)) { + entry.api = "openai-responses"; + } else if (previous?.api !== undefined) { + entry.api = previous.api; + } + const derived = deriveThinkingFields(model); if (derived) { entry.reasoning = derived.reasoning; From e8f14ac47581653b15d25f83c366b5859a89b8b7 Mon Sep 17 00:00:00 2001 From: redshift <213178690+1ftredsh@users.noreply.github.com> Date: Tue, 22 Sep 2026 14:03:23 +0300 Subject: [PATCH 2/2] test(integrations): cover gpt-* openai-responses pinning --- tests/integrations/pi.test.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/integrations/pi.test.ts b/tests/integrations/pi.test.ts index abbc673..88495e8 100644 --- a/tests/integrations/pi.test.ts +++ b/tests/integrations/pi.test.ts @@ -246,6 +246,7 @@ describe("buildPiModelEntry", () => { expect(entry).toEqual({ id: "gpt-5.6-sol", + api: "openai-responses", name: "OpenAI: GPT-5.6 Sol", contextWindow: 1050000, input: ["text", "image"], @@ -313,4 +314,23 @@ describe("buildPiModelEntry", () => { expect("reasoning" in entry).toBe(false); expect("thinkingLevelMap" in entry).toBe(false); }); + + it("pins api=openai-responses for gpt-* models, overriding any curated value", () => { + const previous: PiModelEntry = { id: "gpt-5.6-sol", api: "openai-completions" }; + + const entry = buildPiModelEntry(model({ id: "gpt-5.6-sol" }), previous); + + expect(entry.api).toBe("openai-responses"); + }); + + it("preserves a user-curated api on non-gpt models and omits it otherwise", () => { + const curated = buildPiModelEntry( + model({ id: "glm-5.3" }), + { id: "glm-5.3", api: "openai-responses" }, + ); + expect(curated.api).toBe("openai-responses"); + + const plain = buildPiModelEntry(model({ id: "glm-5.3" })); + expect("api" in plain).toBe(false); + }); });