FN-7754: seed OpenAI GPT-5.6 Codex models into pi createFnAgent registry
Wires the GPT-5.6 codenamed OpenAI Codex models (gpt-5.6-luna/sol/terra) into the engine pi model-registry seeding surface, mirroring the dashboard's /api/models supplemental merge so the models are no longer missing from pi. - Call mergeSupplementalOpenAiCodexModels() in createFnAgent (packages/engine/src/pi.ts) alongside the existing Anthropic supplemental merge - Add regression tests covering synthesis of missing GPT-5.6 rows and dedupe against pinned catalog entries - Update docs/settings-reference.md to describe the additive surfacing on both /api/models and the engine/pi registry-seeding path - Add a patch changeset for @runfusion/fusion Files changed: .changeset/fn-7754-openai-gpt-5-6-pi-surface.md | 7 +++ docs/settings-reference.md | 2 +- .../src/__tests__/pi-create-fn-agent.test.ts | 63 ++++++++++++++++++++++ packages/engine/src/pi.ts | 6 +++ 4 files changed, 77 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-7754 Fusion-Task-Lineage: b61b6812-c94b-46d8-b187-445ccdd6e4e9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7754-openai-gpt-5-6-pi-surface.md
Normal file
7
.changeset/fn-7754-openai-gpt-5-6-pi-surface.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
summary: The latest OpenAI GPT-5.6 models now appear everywhere, not just the Settings model list.
|
||||||
|
category: fix
|
||||||
|
dev: Wires mergeSupplementalOpenAiCodexModels into the engine pi createFnAgent registry-seeding surface (packages/engine/src/pi.ts) alongside the existing mergeSupplementalAnthropicModels call, mirroring register-model-routes.ts. FN-7745 only wired the dashboard /api/models route, so gpt-5.6-luna/sol/terra were absent on the pi surface. Additive, dedupe-safe; adds a pi-create-fn-agent regression test.
|
||||||
@@ -977,7 +977,7 @@ When the Cursor Runtime plugin (`fusion-plugin-cursor-runtime`) is installed and
|
|||||||
|
|
||||||
When the Grok Runtime plugin (`fusion-plugin-grok-runtime`) is installed and the `useGrokCli` toggle is enabled (Settings → Authentication), Grok CLI-discovered models (`grok models`) are surfaced additively in `/api/models` under the `grok-cli` provider — id/name derived from the discovered model id/label. This surfacing is fetched through a short-TTL, single-flight cache so the model picker never spawns `grok` on every request; a missing/failed/unavailable Grok CLI binary simply yields zero `grok-cli` rows without affecting other providers. Disabling `useGrokCli` hides all `grok-cli` rows. Unlike Cursor (OAuth/session auth), Grok is API-key auth: the Settings card's status text guides operators to `GROK_API_KEY` or `~/.grok/user-settings.json` when the binary is available but no key is configured.
|
When the Grok Runtime plugin (`fusion-plugin-grok-runtime`) is installed and the `useGrokCli` toggle is enabled (Settings → Authentication), Grok CLI-discovered models (`grok models`) are surfaced additively in `/api/models` under the `grok-cli` provider — id/name derived from the discovered model id/label. This surfacing is fetched through a short-TTL, single-flight cache so the model picker never spawns `grok` on every request; a missing/failed/unavailable Grok CLI binary simply yields zero `grok-cli` rows without affecting other providers. Disabling `useGrokCli` hides all `grok-cli` rows. Unlike Cursor (OAuth/session auth), Grok is API-key auth: the Settings card's status text guides operators to `GROK_API_KEY` or `~/.grok/user-settings.json` when the binary is available but no key is configured.
|
||||||
|
|
||||||
The three GPT-5.6 codenamed OpenAI Codex variants (`gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`) are additively surfaced under the `openai-codex` provider (FN-7745, mirroring the Anthropic/Z.ai supplemental-merge pattern above) so they appear in `/api/models` whenever `openai-codex` is configured — deduped against any pinned pi-ai catalog row that already carries one of the ids.
|
The three GPT-5.6 codenamed OpenAI Codex variants (`gpt-5.6-luna`, `gpt-5.6-sol`, `gpt-5.6-terra`) are additively surfaced under the `openai-codex` provider (FN-7745/FN-7754, mirroring the Anthropic/Z.ai supplemental-merge pattern above) so they appear both in dashboard `/api/models` and the engine/pi `createFnAgent` registry-seeding surface whenever `openai-codex` is configured — deduped against any pinned pi-ai catalog row that already carries one of the ids.
|
||||||
|
|
||||||
### Planning model
|
### Planning model
|
||||||
|
|
||||||
|
|||||||
@@ -1932,6 +1932,69 @@ describe("createFnAgent", () => {
|
|||||||
expect(anthropicRegistrations).toHaveLength(0);
|
expect(anthropicRegistrations).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("synthesizes OpenAI Codex GPT-5.6 models from supplemental metadata when the pi registry lacks them", async () => {
|
||||||
|
// FNXC:ModelCatalog 2026-07-09-00:00:
|
||||||
|
// FN-7754 regression coverage for the createFnAgent registry-seeding surface: a pi catalog with no openai-codex provider/models must still surface all GPT-5.6 codenamed variants through the shared additive supplemental merge.
|
||||||
|
getAllMock.mockReturnValue([]);
|
||||||
|
findMock.mockImplementation((provider: string, modelId: string) => ({ provider, id: modelId }));
|
||||||
|
|
||||||
|
const { createFnAgent } = await import("../pi.js");
|
||||||
|
await createFnAgent({
|
||||||
|
cwd: "/tmp",
|
||||||
|
systemPrompt: "test",
|
||||||
|
tools: "readonly",
|
||||||
|
defaultProvider: "openai-codex",
|
||||||
|
defaultModelId: "gpt-5.6-luna",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(registerProviderMock).toHaveBeenCalledWith("openai-codex", expect.objectContaining({
|
||||||
|
models: expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: "gpt-5.6-luna" }),
|
||||||
|
expect.objectContaining({ id: "gpt-5.6-sol" }),
|
||||||
|
expect.objectContaining({ id: "gpt-5.6-terra" }),
|
||||||
|
]),
|
||||||
|
}));
|
||||||
|
expect(createAgentSessionMock).toHaveBeenCalledWith(expect.objectContaining({
|
||||||
|
model: { provider: "openai-codex", id: "gpt-5.6-luna" },
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not duplicate OpenAI Codex GPT-5.6 rows already present in the pi registry", async () => {
|
||||||
|
const existingLunaRow = {
|
||||||
|
provider: "openai-codex",
|
||||||
|
id: "gpt-5.6-luna",
|
||||||
|
name: "GPT-5.6 Luna Upstream",
|
||||||
|
reasoning: true,
|
||||||
|
input: ["text"],
|
||||||
|
cost: { input: 1, output: 2 },
|
||||||
|
contextWindow: 200_000,
|
||||||
|
maxTokens: 16_000,
|
||||||
|
};
|
||||||
|
getAllMock.mockReturnValue([existingLunaRow]);
|
||||||
|
findMock.mockImplementation((provider: string, modelId: string) => ({ provider, id: modelId }));
|
||||||
|
|
||||||
|
const { createFnAgent } = await import("../pi.js");
|
||||||
|
await createFnAgent({
|
||||||
|
cwd: "/tmp",
|
||||||
|
systemPrompt: "test",
|
||||||
|
tools: "readonly",
|
||||||
|
defaultProvider: "openai-codex",
|
||||||
|
defaultModelId: "gpt-5.6-luna",
|
||||||
|
});
|
||||||
|
|
||||||
|
const openAiCodexRegistrations = registerProviderMock.mock.calls.filter(([name]) => name === "openai-codex");
|
||||||
|
expect(openAiCodexRegistrations).toHaveLength(1);
|
||||||
|
const registeredProvider = openAiCodexRegistrations[0]?.[1] as { models: Array<{ id: string; name?: string }> };
|
||||||
|
const registeredModels = registeredProvider.models;
|
||||||
|
const lunaRows = registeredModels.filter((model) => model.id === "gpt-5.6-luna");
|
||||||
|
expect(lunaRows).toHaveLength(1);
|
||||||
|
expect(lunaRows[0]).toMatchObject({ name: "GPT-5.6 Luna Upstream" });
|
||||||
|
expect(registeredModels).toEqual(expect.arrayContaining([
|
||||||
|
expect.objectContaining({ id: "gpt-5.6-sol" }),
|
||||||
|
expect.objectContaining({ id: "gpt-5.6-terra" }),
|
||||||
|
]));
|
||||||
|
});
|
||||||
|
|
||||||
// Restored v0.51.0 behavior: a subscription-OAuth `anthropic/<model>` selection stays on
|
// Restored v0.51.0 behavior: a subscription-OAuth `anthropic/<model>` selection stays on
|
||||||
// the built-in `anthropic` provider (pi-ai POSTs the OAuth token to /v1 with Claude Code
|
// the built-in `anthropic` provider (pi-ai POSTs the OAuth token to /v1 with Claude Code
|
||||||
// impersonation). No `/v1`-based `anthropic-subscription` provider is registered, and there
|
// impersonation). No `/v1`-based `anthropic-subscription` provider is registered, and there
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ import {
|
|||||||
mergeBuiltInGrokProviderModels,
|
mergeBuiltInGrokProviderModels,
|
||||||
mergeBuiltInZaiProviderModels,
|
mergeBuiltInZaiProviderModels,
|
||||||
mergeSupplementalAnthropicModels,
|
mergeSupplementalAnthropicModels,
|
||||||
|
mergeSupplementalOpenAiCodexModels,
|
||||||
registerBuiltInGrokProvider,
|
registerBuiltInGrokProvider,
|
||||||
registerBuiltInZaiProvider,
|
registerBuiltInZaiProvider,
|
||||||
resolvePiExtensionProjectRoot,
|
resolvePiExtensionProjectRoot,
|
||||||
@@ -2121,6 +2122,11 @@ export async function createFnAgent(options: AgentOptions): Promise<AgentResult>
|
|||||||
}
|
}
|
||||||
modelRegistry.refresh();
|
modelRegistry.refresh();
|
||||||
mergeSupplementalAnthropicModels(modelRegistry, (message) => extensionsLog.warn(message));
|
mergeSupplementalAnthropicModels(modelRegistry, (message) => extensionsLog.warn(message));
|
||||||
|
/*
|
||||||
|
* FNXC:ModelCatalog 2026-07-09-00:00:
|
||||||
|
* FN-7754 mirrors the dashboard register-model-routes.ts supplemental merge seam so the GPT-5.6 codenamed OpenAI-Codex models surface on the engine createFnAgent registry-seeding path, not just /api/models. FN-7745 only wired the dashboard surface; this merge is additive and dedupe-safe, so pinned catalog rows win and no duplicate ids are added.
|
||||||
|
*/
|
||||||
|
mergeSupplementalOpenAiCodexModels(modelRegistry, (message) => extensionsLog.warn(message));
|
||||||
|
|
||||||
// Build the pi built-in tool set. We deliberately do NOT use the bundled
|
// Build the pi built-in tool set. We deliberately do NOT use the bundled
|
||||||
// `createCodingTools` / `createReadOnlyTools` presets — they're missing
|
// `createCodingTools` / `createReadOnlyTools` presets — they're missing
|
||||||
|
|||||||
Reference in New Issue
Block a user