|
6 | 6 | applyEquivalentModels, |
7 | 7 | canonicalizeLocalModelsContent, |
8 | 8 | convertBasetenToLocalModel, |
| 9 | + convertCohereToLocalModel, |
| 10 | + applyCohereLiteLLMPricing, |
| 11 | + isSupportedCohereChatModel, |
9 | 12 | convertRemoteToLocalModel, |
10 | 13 | applyBasetenPricing, |
11 | 14 | applyOpenRouterPricing, |
@@ -953,3 +956,96 @@ describe("applyOpenRouterPricing", () => { |
953 | 956 | expect(applyOpenRouterPricing("x-ai/grok-4.5", model, orModel)).toBeNull(); |
954 | 957 | }); |
955 | 958 | }); |
| 959 | + |
| 960 | +describe("convertCohereToLocalModel", () => { |
| 961 | + it("maps a Cohere chat model to an openai-format cohere entry (no LiteLLM = no pricing)", () => { |
| 962 | + const spec = convertCohereToLocalModel({ |
| 963 | + name: "command-a-reasoning-08-2025", |
| 964 | + endpoints: ["chat"], |
| 965 | + context_length: 288768, |
| 966 | + }); |
| 967 | + expect(spec.format).toBe("openai"); |
| 968 | + expect(spec.flavor).toBe("chat"); |
| 969 | + expect(spec.max_input_tokens).toBe(288768); |
| 970 | + expect(spec.available_providers).toEqual(["cohere"]); |
| 971 | + // No LiteLLM overlay -> no fabricated pricing. |
| 972 | + expect(spec.input_cost_per_mil_tokens).toBeUndefined(); |
| 973 | + expect(spec.output_cost_per_mil_tokens).toBeUndefined(); |
| 974 | + }); |
| 975 | + |
| 976 | + it("overlays LiteLLM pricing (per-token -> per-mil) when available", () => { |
| 977 | + const spec = convertCohereToLocalModel( |
| 978 | + { |
| 979 | + name: "command-a-03-2025", |
| 980 | + endpoints: ["chat"], |
| 981 | + context_length: 256000, |
| 982 | + }, |
| 983 | + { |
| 984 | + input_cost_per_token: 2.5e-6, |
| 985 | + output_cost_per_token: 1e-5, |
| 986 | + cache_read_input_token_cost: 1.25e-6, |
| 987 | + }, |
| 988 | + ); |
| 989 | + expect(spec.input_cost_per_mil_tokens).toBe(2.5); |
| 990 | + expect(spec.output_cost_per_mil_tokens).toBe(10); |
| 991 | + expect(spec.input_cache_read_cost_per_mil_tokens).toBe(1.25); |
| 992 | + }); |
| 993 | +}); |
| 994 | + |
| 995 | +describe("isSupportedCohereChatModel", () => { |
| 996 | + it("accepts a live chat model", () => { |
| 997 | + expect( |
| 998 | + isSupportedCohereChatModel({ |
| 999 | + name: "command-a-03-2025", |
| 1000 | + endpoints: ["chat"], |
| 1001 | + }), |
| 1002 | + ).toBe(true); |
| 1003 | + }); |
| 1004 | + |
| 1005 | + it("rejects non-chat, fine-tuned, and deprecated models", () => { |
| 1006 | + expect( |
| 1007 | + isSupportedCohereChatModel({ name: "embed-v4.0", endpoints: ["embed"] }), |
| 1008 | + ).toBe(false); |
| 1009 | + expect( |
| 1010 | + isSupportedCohereChatModel({ |
| 1011 | + name: "my-finetune", |
| 1012 | + endpoints: ["chat"], |
| 1013 | + finetuned: true, |
| 1014 | + }), |
| 1015 | + ).toBe(false); |
| 1016 | + expect( |
| 1017 | + isSupportedCohereChatModel({ |
| 1018 | + name: "command-r", |
| 1019 | + endpoints: ["chat"], |
| 1020 | + is_deprecated: true, |
| 1021 | + }), |
| 1022 | + ).toBe(false); |
| 1023 | + }); |
| 1024 | +}); |
| 1025 | + |
| 1026 | +describe("applyCohereLiteLLMPricing", () => { |
| 1027 | + const priceless: ModelSpec = { |
| 1028 | + format: "openai", |
| 1029 | + flavor: "chat", |
| 1030 | + available_providers: ["cohere"], |
| 1031 | + }; |
| 1032 | + |
| 1033 | + it("fills pricing on an existing price-less entry when LiteLLM has it", () => { |
| 1034 | + const priced = applyCohereLiteLLMPricing("command-a-03-2025", priceless, { |
| 1035 | + input_cost_per_token: 2.5e-6, |
| 1036 | + output_cost_per_token: 1e-5, |
| 1037 | + cache_read_input_token_cost: 1.25e-6, |
| 1038 | + }); |
| 1039 | + expect(priced?.input_cost_per_mil_tokens).toBe(2.5); |
| 1040 | + expect(priced?.output_cost_per_mil_tokens).toBe(10); |
| 1041 | + expect(priced?.input_cache_read_cost_per_mil_tokens).toBe(1.25); |
| 1042 | + }); |
| 1043 | + |
| 1044 | + it("returns null when LiteLLM has no entry or pricing is unchanged", () => { |
| 1045 | + expect(applyCohereLiteLLMPricing("x", priceless, undefined)).toBeNull(); |
| 1046 | + const already: ModelSpec = { ...priceless, input_cost_per_mil_tokens: 2.5 }; |
| 1047 | + expect( |
| 1048 | + applyCohereLiteLLMPricing("x", already, { input_cost_per_token: 2.5e-6 }), |
| 1049 | + ).toBeNull(); |
| 1050 | + }); |
| 1051 | +}); |
0 commit comments