FN-7390: add latest Claude CLI models
Expose the latest Claude CLI-callable Anthropic models with corrected supplemental metadata. - Add Sonnet 5, Fable 5, and Opus 4.8 to the pi-claude-cli supplemental model catalog. - Update context/output limits for recent Claude 4.x CLI rows. - Preserve catalog deduplication and assert Fable 5 uses the current 0/0 per MTok pricing. - Add a patch changeset for the published Fusion CLI package. Files changed: .changeset/fn-7390-claude-cli-latest-models.md | 7 ++++ packages/pi-claude-cli/index.ts | 40 ++++++++++++++++-- .../pi-claude-cli/src/__tests__/provider.test.ts | 47 +++++++++++++++------- 3 files changed, 76 insertions(+), 18 deletions(-) Fusion-Task-Id: FN-7390 Fusion-Task-Lineage: 54df5de7-c29e-44af-bcb6-9d768103576e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7390-claude-cli-latest-models.md
Normal file
7
.changeset/fn-7390-claude-cli-latest-models.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"@runfusion/fusion": patch
|
||||
---
|
||||
|
||||
summary: Restore Claude Sonnet 5 and latest Anthropic models in the Claude CLI model picker.
|
||||
category: fix
|
||||
dev: pi-claude-cli supplemental extraModels now advertises claude-sonnet-5 for the subscription-authenticated CLI surface; direct-Anthropic supplemental registration and static pricing remain withheld per FN-7374's 404 not_found_error handling. Local evidence used claude 2.1.197 with --model accepting aliases/full names; checksum remains upstream-pending-verification.
|
||||
@@ -193,7 +193,39 @@ export default function (pi: ExtensionAPI) {
|
||||
/*
|
||||
* FNXC:ModelCatalog 2026-07-01-18:18:
|
||||
* Keep Claude CLI supplemental metadata limited to models that Fusion can advertise without triggering the direct-Anthropic Sonnet 5 404 loop. `claude-sonnet-5` must come from the upstream/live registry before this provider shows it, because static metadata cannot prove the current account and CLI surface can call that model.
|
||||
*
|
||||
* FNXC:ModelCatalog 2026-07-01-20:37:
|
||||
* Supersede the prior Claude CLI withholding only for `pi-claude-cli`: the local `claude` subprocess routes through the user's Claude subscription/login and its 2.1.197 `--model` help accepts latest aliases/full names, so the CLI picker should advertise Sonnet 5 and newer CLI-callable rows. Keep direct Anthropic supplemental metadata and static pricing withheld because FN-7374's per-account `404 not_found_error` applies to that API surface, not this subscription-authenticated CLI surface.
|
||||
*/
|
||||
{
|
||||
id: "claude-sonnet-5",
|
||||
name: "Claude Sonnet 5",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 128_000,
|
||||
},
|
||||
{
|
||||
id: "claude-fable-5",
|
||||
name: "Claude Fable 5",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
// FNXC:ModelCatalog 2026-07-01-21:04: Fable 5 must use Anthropic's current $10/$50 per MTok row so Fusion's CLI picker does not understate supplemental model cost estimates.
|
||||
cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 128_000,
|
||||
},
|
||||
{
|
||||
id: "claude-opus-4-8",
|
||||
name: "Claude Opus 4.8",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
// FNXC:ModelCatalog 2026-07-01-20:37: The overview confirms Opus 4.8 context/output limits; mirror the closest current Opus CLI supplemental pricing until a precise per-model price row is pinned for this subscription surface.
|
||||
cost: { input: 5, output: 25, cacheRead: 0.5, cacheWrite: 6.25 },
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 128_000,
|
||||
},
|
||||
{
|
||||
id: "claude-opus-4-7",
|
||||
name: "Claude Opus 4.7",
|
||||
@@ -209,8 +241,8 @@ export default function (pi: ExtensionAPI) {
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
||||
contextWindow: 200_000,
|
||||
maxTokens: 16_384,
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 64_000,
|
||||
},
|
||||
{
|
||||
id: "claude-sonnet-4-5",
|
||||
@@ -219,7 +251,7 @@ export default function (pi: ExtensionAPI) {
|
||||
input: ["text", "image"],
|
||||
cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
||||
contextWindow: 200_000,
|
||||
maxTokens: 8_192,
|
||||
maxTokens: 64_000,
|
||||
},
|
||||
{
|
||||
id: "claude-haiku-4-5",
|
||||
@@ -228,7 +260,7 @@ export default function (pi: ExtensionAPI) {
|
||||
input: ["text", "image"],
|
||||
cost: { input: 0.8, output: 4, cacheRead: 0.08, cacheWrite: 1 },
|
||||
contextWindow: 200_000,
|
||||
maxTokens: 8_192,
|
||||
maxTokens: 64_000,
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ describe("provider registration (default export)", () => {
|
||||
expect(firstModel.cost).toBeDefined();
|
||||
});
|
||||
|
||||
it("includes supported extra Claude model entries without force-adding Sonnet 5", async () => {
|
||||
it("includes latest Claude models including Sonnet 5 for the CLI surface", async () => {
|
||||
const registerProvider = vi.fn();
|
||||
const mockPi = { registerProvider, on: vi.fn() } as any;
|
||||
|
||||
@@ -127,6 +127,9 @@ describe("provider registration (default export)", () => {
|
||||
const modelIds = new Set(config.models.map((m: { id: string }) => m.id));
|
||||
|
||||
for (const id of [
|
||||
"claude-sonnet-5",
|
||||
"claude-fable-5",
|
||||
"claude-opus-4-8",
|
||||
"claude-opus-4-7",
|
||||
"claude-sonnet-4-6",
|
||||
"claude-sonnet-4-5",
|
||||
@@ -135,30 +138,35 @@ describe("provider registration (default export)", () => {
|
||||
expect(modelIds.has(id)).toBe(true);
|
||||
}
|
||||
|
||||
expect(modelIds.has("claude-sonnet-5")).toBe(false);
|
||||
expect(
|
||||
config.models.find((m: { id: string }) => m.id === "claude-fable-5"),
|
||||
).toMatchObject({
|
||||
cost: { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
|
||||
});
|
||||
});
|
||||
|
||||
it("deduplicates extra models when catalog already includes them", async () => {
|
||||
const registerProvider = vi.fn();
|
||||
const mockPi = { registerProvider, on: vi.fn() } as any;
|
||||
const getModelsMock = vi.mocked(getModels);
|
||||
const upstreamSonnet5 = {
|
||||
id: "claude-sonnet-5",
|
||||
name: "Claude Sonnet 5 Upstream",
|
||||
api: "anthropic",
|
||||
provider: "anthropic",
|
||||
reasoning: false,
|
||||
input: ["text"],
|
||||
cost: { input: 99, output: 199, cacheRead: 9.9, cacheWrite: 24.75 },
|
||||
contextWindow: 123_456,
|
||||
maxTokens: 7_654,
|
||||
} as any;
|
||||
|
||||
getModelsMock.mockReturnValueOnce([
|
||||
...mockModels,
|
||||
{
|
||||
id: "claude-sonnet-5",
|
||||
name: "Claude Sonnet 5 Upstream",
|
||||
api: "anthropic",
|
||||
provider: "anthropic",
|
||||
reasoning: true,
|
||||
input: ["text", "image"],
|
||||
cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 128_000,
|
||||
} as any,
|
||||
upstreamSonnet5,
|
||||
{
|
||||
id: "claude-sonnet-4-6",
|
||||
name: "Claude Sonnet 4.6",
|
||||
name: "Claude Sonnet 4.6 Upstream",
|
||||
api: "anthropic",
|
||||
provider: "anthropic",
|
||||
reasoning: true,
|
||||
@@ -179,6 +187,17 @@ describe("provider registration (default export)", () => {
|
||||
);
|
||||
expect(matches).toHaveLength(1);
|
||||
}
|
||||
|
||||
expect(
|
||||
config.models.find((m: { id: string }) => m.id === "claude-sonnet-5"),
|
||||
).toMatchObject({
|
||||
name: upstreamSonnet5.name,
|
||||
reasoning: upstreamSonnet5.reasoning,
|
||||
input: upstreamSonnet5.input,
|
||||
cost: upstreamSonnet5.cost,
|
||||
contextWindow: upstreamSonnet5.contextWindow,
|
||||
maxTokens: upstreamSonnet5.maxTokens,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user