Skip to content

Commit 85290da

Browse files
fix: list Fantastico models from the control plane and add its icon
The model catalog lives on the control plane, not on an OpenAI-style /models route, so autodetect hit a 404 on /api/models. listModels now reads /edge/models for account keys and /runtime/models for project keys. Also adds the Fantastico logo to the provider picker. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent d429bbb commit 85290da

4 files changed

Lines changed: 78 additions & 0 deletions

File tree

‎core/llm/llms/Fantastico.ts‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,21 @@ class Fantastico extends OpenAI {
1616
};
1717

1818
protected useOpenAIAdapterFor: (LlmApiRequestType | "*")[] = ["*"];
19+
20+
/**
21+
* The catalog is served by the control plane, not by the inference endpoint:
22+
* account keys read it from `/edge/models`, project keys from `/runtime/models`.
23+
*/
24+
async listModels(): Promise<string[]> {
25+
const route = this.apiKey?.startsWith("sk-fant-") ? "runtime" : "edge";
26+
const controlPlane = (this.apiBase ?? "").replace(/\/+$/, "");
27+
const response = await this.fetch(`${controlPlane}/${route}/models`, {
28+
method: "GET",
29+
headers: { Authorization: `Bearer ${this.apiKey}` },
30+
});
31+
const data = (await response.json()) as { models?: { id: string }[] };
32+
return (data.models ?? []).map((m) => m.id);
33+
}
1934
}
2035

2136
export default Fantastico;

‎core/llm/llms/Fantastico.vitest.ts‎

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
import Fantastico from "./Fantastico";
4+
5+
function mockModels(fantastico: Fantastico) {
6+
return vi.spyOn(fantastico, "fetch").mockResolvedValue(
7+
new Response(
8+
JSON.stringify({
9+
models: [{ id: "anthropic/claude-sonnet-4.5" }, { id: "openai/gpt-5" }],
10+
}),
11+
),
12+
);
13+
}
14+
15+
describe("Fantastico", () => {
16+
it("should have correct provider name", () => {
17+
expect(Fantastico.providerName).toBe("fantastico");
18+
});
19+
20+
it("should default to the production control plane", () => {
21+
expect(Fantastico.defaultOptions.apiBase).toBe(
22+
"https://fantastico.cc/api/",
23+
);
24+
});
25+
26+
it("should list models from /edge/models with an account key", async () => {
27+
const fantastico = new Fantastico({
28+
model: "AUTODETECT",
29+
apiKey: "ck-fant-test",
30+
});
31+
const fetchSpy = mockModels(fantastico);
32+
33+
const models = await fantastico.listModels();
34+
35+
expect(models).toEqual(["anthropic/claude-sonnet-4.5", "openai/gpt-5"]);
36+
expect(fetchSpy).toHaveBeenCalledWith(
37+
"https://fantastico.cc/api/edge/models",
38+
expect.objectContaining({
39+
headers: { Authorization: "Bearer ck-fant-test" },
40+
}),
41+
);
42+
});
43+
44+
it("should list models from /runtime/models with a project key", async () => {
45+
const fantastico = new Fantastico({
46+
model: "AUTODETECT",
47+
apiKey: "sk-fant-test",
48+
apiBase: "https://fantastico.example/api",
49+
});
50+
const fetchSpy = mockModels(fantastico);
51+
52+
await fantastico.listModels();
53+
54+
expect(fetchSpy).toHaveBeenCalledWith(
55+
"https://fantastico.example/api/runtime/models",
56+
expect.anything(),
57+
);
58+
});
59+
});

‎gui/public/logos/fantastico.svg‎

Lines changed: 3 additions & 0 deletions
Loading

‎gui/src/pages/AddNewModel/configs/providers.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,7 @@ To get started, [register](https://dataplatform.cloud.ibm.com/registration/stepo
12731273
fantastico: {
12741274
title: "Fantastico",
12751275
provider: "fantastico",
1276+
icon: "fantastico.svg",
12761277
description:
12771278
"Per-developer account keys with preallocated budgets and one company bill. No proxy: requests go straight to the model provider.",
12781279
longDescription:

0 commit comments

Comments
 (0)