cascade-ai 0.48.1 → 0.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -2
- package/dist/cli.cjs +2113 -51
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2113 -51
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +2050 -47
- package/dist/index.cjs +2050 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -0
- package/dist/index.d.ts +159 -0
- package/dist/index.js +2050 -47
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/desktop-core.cjs
CHANGED
|
@@ -222594,8 +222594,1660 @@ Anthropic.Messages = Messages2;
|
|
|
222594
222594
|
Anthropic.Models = Models2;
|
|
222595
222595
|
Anthropic.Beta = Beta;
|
|
222596
222596
|
|
|
222597
|
+
// src/core/router/pricing-data.json
|
|
222598
|
+
var pricing_data_default = {
|
|
222599
|
+
entries: [
|
|
222600
|
+
{
|
|
222601
|
+
model: "claude-opus-5",
|
|
222602
|
+
provider: "anthropic",
|
|
222603
|
+
modality: "text",
|
|
222604
|
+
currency: "USD",
|
|
222605
|
+
asOf: "2026-07-27",
|
|
222606
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222607
|
+
provenance: "vendor-pricing-page",
|
|
222608
|
+
tiers: [
|
|
222609
|
+
{
|
|
222610
|
+
inputPer1m: 5,
|
|
222611
|
+
outputPer1m: 25,
|
|
222612
|
+
cachedInputPer1m: 0.5,
|
|
222613
|
+
cacheWritePer1m: 6.25,
|
|
222614
|
+
reasoningOutputPer1m: 25
|
|
222615
|
+
}
|
|
222616
|
+
],
|
|
222617
|
+
batchMultiplier: 0.5,
|
|
222618
|
+
contextWindow: 1e6
|
|
222619
|
+
},
|
|
222620
|
+
{
|
|
222621
|
+
model: "claude-opus-4-8",
|
|
222622
|
+
provider: "anthropic",
|
|
222623
|
+
modality: "text",
|
|
222624
|
+
currency: "USD",
|
|
222625
|
+
asOf: "2026-07-27",
|
|
222626
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222627
|
+
provenance: "vendor-pricing-page",
|
|
222628
|
+
tiers: [
|
|
222629
|
+
{
|
|
222630
|
+
inputPer1m: 5,
|
|
222631
|
+
outputPer1m: 25,
|
|
222632
|
+
cachedInputPer1m: 0.5,
|
|
222633
|
+
cacheWritePer1m: 6.25,
|
|
222634
|
+
reasoningOutputPer1m: 25
|
|
222635
|
+
}
|
|
222636
|
+
],
|
|
222637
|
+
batchMultiplier: 0.5,
|
|
222638
|
+
contextWindow: 1e6
|
|
222639
|
+
},
|
|
222640
|
+
{
|
|
222641
|
+
model: "claude-opus-4-7",
|
|
222642
|
+
provider: "anthropic",
|
|
222643
|
+
modality: "text",
|
|
222644
|
+
currency: "USD",
|
|
222645
|
+
asOf: "2026-07-27",
|
|
222646
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222647
|
+
provenance: "vendor-pricing-page",
|
|
222648
|
+
tiers: [
|
|
222649
|
+
{
|
|
222650
|
+
inputPer1m: 5,
|
|
222651
|
+
outputPer1m: 25,
|
|
222652
|
+
cachedInputPer1m: 0.5,
|
|
222653
|
+
cacheWritePer1m: 6.25,
|
|
222654
|
+
reasoningOutputPer1m: 25
|
|
222655
|
+
}
|
|
222656
|
+
],
|
|
222657
|
+
batchMultiplier: 0.5,
|
|
222658
|
+
contextWindow: 1e6
|
|
222659
|
+
},
|
|
222660
|
+
{
|
|
222661
|
+
model: "claude-opus-4-6",
|
|
222662
|
+
provider: "anthropic",
|
|
222663
|
+
modality: "text",
|
|
222664
|
+
currency: "USD",
|
|
222665
|
+
asOf: "2026-07-27",
|
|
222666
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222667
|
+
provenance: "vendor-pricing-page",
|
|
222668
|
+
tiers: [
|
|
222669
|
+
{
|
|
222670
|
+
inputPer1m: 5,
|
|
222671
|
+
outputPer1m: 25,
|
|
222672
|
+
cachedInputPer1m: 0.5,
|
|
222673
|
+
cacheWritePer1m: 6.25,
|
|
222674
|
+
reasoningOutputPer1m: 25
|
|
222675
|
+
}
|
|
222676
|
+
],
|
|
222677
|
+
batchMultiplier: 0.5,
|
|
222678
|
+
contextWindow: 1e6
|
|
222679
|
+
},
|
|
222680
|
+
{
|
|
222681
|
+
model: "claude-opus-4-5",
|
|
222682
|
+
provider: "anthropic",
|
|
222683
|
+
modality: "text",
|
|
222684
|
+
currency: "USD",
|
|
222685
|
+
asOf: "2026-07-27",
|
|
222686
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222687
|
+
provenance: "vendor-pricing-page",
|
|
222688
|
+
tiers: [
|
|
222689
|
+
{
|
|
222690
|
+
inputPer1m: 5,
|
|
222691
|
+
outputPer1m: 25,
|
|
222692
|
+
cachedInputPer1m: 0.5,
|
|
222693
|
+
cacheWritePer1m: 6.25,
|
|
222694
|
+
reasoningOutputPer1m: 25
|
|
222695
|
+
}
|
|
222696
|
+
],
|
|
222697
|
+
batchMultiplier: 0.5,
|
|
222698
|
+
contextWindow: 2e5
|
|
222699
|
+
},
|
|
222700
|
+
{
|
|
222701
|
+
model: "claude-opus-4-1",
|
|
222702
|
+
provider: "anthropic",
|
|
222703
|
+
modality: "text",
|
|
222704
|
+
currency: "USD",
|
|
222705
|
+
asOf: "2026-07-27",
|
|
222706
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222707
|
+
provenance: "vendor-pricing-page",
|
|
222708
|
+
tiers: [
|
|
222709
|
+
{
|
|
222710
|
+
inputPer1m: 15,
|
|
222711
|
+
outputPer1m: 75,
|
|
222712
|
+
cachedInputPer1m: 1.5,
|
|
222713
|
+
cacheWritePer1m: 18.75,
|
|
222714
|
+
reasoningOutputPer1m: 75
|
|
222715
|
+
}
|
|
222716
|
+
],
|
|
222717
|
+
batchMultiplier: 0.5,
|
|
222718
|
+
contextWindow: 2e5,
|
|
222719
|
+
notes: "Deprecated by Anthropic; priced for historical/cost-reporting accuracy."
|
|
222720
|
+
},
|
|
222721
|
+
{
|
|
222722
|
+
model: "claude-opus-4",
|
|
222723
|
+
provider: "anthropic",
|
|
222724
|
+
modality: "text",
|
|
222725
|
+
currency: "USD",
|
|
222726
|
+
asOf: "2026-07-27",
|
|
222727
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222728
|
+
provenance: "vendor-pricing-page",
|
|
222729
|
+
tiers: [
|
|
222730
|
+
{
|
|
222731
|
+
inputPer1m: 15,
|
|
222732
|
+
outputPer1m: 75,
|
|
222733
|
+
cachedInputPer1m: 1.5,
|
|
222734
|
+
cacheWritePer1m: 18.75,
|
|
222735
|
+
reasoningOutputPer1m: 75
|
|
222736
|
+
}
|
|
222737
|
+
],
|
|
222738
|
+
batchMultiplier: 0.5,
|
|
222739
|
+
contextWindow: 2e5,
|
|
222740
|
+
notes: "Retired except on Google Cloud; priced for historical/cost-reporting accuracy."
|
|
222741
|
+
},
|
|
222742
|
+
{
|
|
222743
|
+
model: "claude-sonnet-5",
|
|
222744
|
+
provider: "anthropic",
|
|
222745
|
+
modality: "text",
|
|
222746
|
+
currency: "USD",
|
|
222747
|
+
asOf: "2026-07-27",
|
|
222748
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222749
|
+
provenance: "vendor-pricing-page",
|
|
222750
|
+
tiers: [
|
|
222751
|
+
{
|
|
222752
|
+
inputPer1m: 2,
|
|
222753
|
+
outputPer1m: 10,
|
|
222754
|
+
cachedInputPer1m: 0.2,
|
|
222755
|
+
cacheWritePer1m: 2.5,
|
|
222756
|
+
reasoningOutputPer1m: 10
|
|
222757
|
+
}
|
|
222758
|
+
],
|
|
222759
|
+
batchMultiplier: 0.5,
|
|
222760
|
+
contextWindow: 1e6,
|
|
222761
|
+
notes: "Introductory pricing through 2026-08-31. Standard pricing of $3/$15 per 1M takes effect 2026-09-01 \u2014 re-check this entry then."
|
|
222762
|
+
},
|
|
222763
|
+
{
|
|
222764
|
+
model: "claude-sonnet-4-6",
|
|
222765
|
+
provider: "anthropic",
|
|
222766
|
+
modality: "text",
|
|
222767
|
+
currency: "USD",
|
|
222768
|
+
asOf: "2026-07-27",
|
|
222769
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222770
|
+
provenance: "vendor-pricing-page",
|
|
222771
|
+
tiers: [
|
|
222772
|
+
{
|
|
222773
|
+
inputPer1m: 3,
|
|
222774
|
+
outputPer1m: 15,
|
|
222775
|
+
cachedInputPer1m: 0.3,
|
|
222776
|
+
cacheWritePer1m: 3.75,
|
|
222777
|
+
reasoningOutputPer1m: 15
|
|
222778
|
+
}
|
|
222779
|
+
],
|
|
222780
|
+
batchMultiplier: 0.5,
|
|
222781
|
+
contextWindow: 1e6
|
|
222782
|
+
},
|
|
222783
|
+
{
|
|
222784
|
+
model: "claude-sonnet-4-5",
|
|
222785
|
+
provider: "anthropic",
|
|
222786
|
+
modality: "text",
|
|
222787
|
+
currency: "USD",
|
|
222788
|
+
asOf: "2026-07-27",
|
|
222789
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222790
|
+
provenance: "vendor-pricing-page",
|
|
222791
|
+
tiers: [
|
|
222792
|
+
{
|
|
222793
|
+
maxInputTokens: 2e5,
|
|
222794
|
+
inputPer1m: 3,
|
|
222795
|
+
outputPer1m: 15,
|
|
222796
|
+
cachedInputPer1m: 0.3,
|
|
222797
|
+
cacheWritePer1m: 3.75,
|
|
222798
|
+
reasoningOutputPer1m: 15
|
|
222799
|
+
},
|
|
222800
|
+
{
|
|
222801
|
+
inputPer1m: 6,
|
|
222802
|
+
outputPer1m: 22.5,
|
|
222803
|
+
cachedInputPer1m: 0.6,
|
|
222804
|
+
cacheWritePer1m: 7.5,
|
|
222805
|
+
reasoningOutputPer1m: 22.5
|
|
222806
|
+
}
|
|
222807
|
+
],
|
|
222808
|
+
batchMultiplier: 0.5,
|
|
222809
|
+
contextWindow: 2e5,
|
|
222810
|
+
notes: "Long-context (>200K) premium applies to the 1M-context beta. Base rates from the Anthropic pricing page; the >200K tier from the litellm catalog (Anthropic does not tabulate it on the pricing page)."
|
|
222811
|
+
},
|
|
222812
|
+
{
|
|
222813
|
+
model: "claude-sonnet-4",
|
|
222814
|
+
provider: "anthropic",
|
|
222815
|
+
modality: "text",
|
|
222816
|
+
currency: "USD",
|
|
222817
|
+
asOf: "2026-07-27",
|
|
222818
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222819
|
+
provenance: "vendor-pricing-page",
|
|
222820
|
+
tiers: [
|
|
222821
|
+
{
|
|
222822
|
+
inputPer1m: 3,
|
|
222823
|
+
outputPer1m: 15,
|
|
222824
|
+
cachedInputPer1m: 0.3,
|
|
222825
|
+
cacheWritePer1m: 3.75,
|
|
222826
|
+
reasoningOutputPer1m: 15
|
|
222827
|
+
}
|
|
222828
|
+
],
|
|
222829
|
+
batchMultiplier: 0.5,
|
|
222830
|
+
contextWindow: 2e5
|
|
222831
|
+
},
|
|
222832
|
+
{
|
|
222833
|
+
model: "claude-haiku-4-5",
|
|
222834
|
+
provider: "anthropic",
|
|
222835
|
+
modality: "text",
|
|
222836
|
+
currency: "USD",
|
|
222837
|
+
asOf: "2026-07-27",
|
|
222838
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222839
|
+
provenance: "vendor-pricing-page",
|
|
222840
|
+
tiers: [
|
|
222841
|
+
{
|
|
222842
|
+
inputPer1m: 1,
|
|
222843
|
+
outputPer1m: 5,
|
|
222844
|
+
cachedInputPer1m: 0.1,
|
|
222845
|
+
cacheWritePer1m: 1.25,
|
|
222846
|
+
reasoningOutputPer1m: 5
|
|
222847
|
+
}
|
|
222848
|
+
],
|
|
222849
|
+
batchMultiplier: 0.5,
|
|
222850
|
+
contextWindow: 2e5
|
|
222851
|
+
},
|
|
222852
|
+
{
|
|
222853
|
+
model: "claude-haiku-3-5",
|
|
222854
|
+
provider: "anthropic",
|
|
222855
|
+
modality: "text",
|
|
222856
|
+
currency: "USD",
|
|
222857
|
+
asOf: "2026-07-27",
|
|
222858
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
222859
|
+
provenance: "vendor-pricing-page",
|
|
222860
|
+
tiers: [
|
|
222861
|
+
{
|
|
222862
|
+
inputPer1m: 0.8,
|
|
222863
|
+
outputPer1m: 4,
|
|
222864
|
+
cachedInputPer1m: 0.08,
|
|
222865
|
+
cacheWritePer1m: 1,
|
|
222866
|
+
reasoningOutputPer1m: 4
|
|
222867
|
+
}
|
|
222868
|
+
],
|
|
222869
|
+
batchMultiplier: 0.5,
|
|
222870
|
+
contextWindow: 2e5
|
|
222871
|
+
},
|
|
222872
|
+
{
|
|
222873
|
+
model: "gpt-5.6-sol",
|
|
222874
|
+
provider: "openai",
|
|
222875
|
+
aliases: [
|
|
222876
|
+
"gpt-5.6"
|
|
222877
|
+
],
|
|
222878
|
+
modality: "text",
|
|
222879
|
+
currency: "USD",
|
|
222880
|
+
asOf: "2026-07-27",
|
|
222881
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
222882
|
+
provenance: "litellm-catalog",
|
|
222883
|
+
tiers: [
|
|
222884
|
+
{
|
|
222885
|
+
maxInputTokens: 272e3,
|
|
222886
|
+
inputPer1m: 5,
|
|
222887
|
+
outputPer1m: 30,
|
|
222888
|
+
cachedInputPer1m: 0.5,
|
|
222889
|
+
cacheWritePer1m: 6.25
|
|
222890
|
+
},
|
|
222891
|
+
{
|
|
222892
|
+
inputPer1m: 10,
|
|
222893
|
+
outputPer1m: 45,
|
|
222894
|
+
cachedInputPer1m: 1,
|
|
222895
|
+
cacheWritePer1m: 12.5
|
|
222896
|
+
}
|
|
222897
|
+
],
|
|
222898
|
+
batchMultiplier: 0.5,
|
|
222899
|
+
contextWindow: 105e4
|
|
222900
|
+
},
|
|
222901
|
+
{
|
|
222902
|
+
model: "gpt-5.6-terra",
|
|
222903
|
+
provider: "openai",
|
|
222904
|
+
modality: "text",
|
|
222905
|
+
currency: "USD",
|
|
222906
|
+
asOf: "2026-07-27",
|
|
222907
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
222908
|
+
provenance: "litellm-catalog",
|
|
222909
|
+
tiers: [
|
|
222910
|
+
{
|
|
222911
|
+
maxInputTokens: 272e3,
|
|
222912
|
+
inputPer1m: 2.5,
|
|
222913
|
+
outputPer1m: 15,
|
|
222914
|
+
cachedInputPer1m: 0.25,
|
|
222915
|
+
cacheWritePer1m: 3.125
|
|
222916
|
+
},
|
|
222917
|
+
{
|
|
222918
|
+
inputPer1m: 5,
|
|
222919
|
+
outputPer1m: 22.5,
|
|
222920
|
+
cachedInputPer1m: 0.5,
|
|
222921
|
+
cacheWritePer1m: 6.25
|
|
222922
|
+
}
|
|
222923
|
+
],
|
|
222924
|
+
batchMultiplier: 0.5,
|
|
222925
|
+
contextWindow: 105e4
|
|
222926
|
+
},
|
|
222927
|
+
{
|
|
222928
|
+
model: "gpt-5.6-luna",
|
|
222929
|
+
provider: "openai",
|
|
222930
|
+
modality: "text",
|
|
222931
|
+
currency: "USD",
|
|
222932
|
+
asOf: "2026-07-27",
|
|
222933
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
222934
|
+
provenance: "litellm-catalog",
|
|
222935
|
+
tiers: [
|
|
222936
|
+
{
|
|
222937
|
+
maxInputTokens: 272e3,
|
|
222938
|
+
inputPer1m: 1,
|
|
222939
|
+
outputPer1m: 6,
|
|
222940
|
+
cachedInputPer1m: 0.1,
|
|
222941
|
+
cacheWritePer1m: 1.25
|
|
222942
|
+
},
|
|
222943
|
+
{
|
|
222944
|
+
inputPer1m: 2,
|
|
222945
|
+
outputPer1m: 9,
|
|
222946
|
+
cachedInputPer1m: 0.2,
|
|
222947
|
+
cacheWritePer1m: 2.5
|
|
222948
|
+
}
|
|
222949
|
+
],
|
|
222950
|
+
batchMultiplier: 0.5,
|
|
222951
|
+
contextWindow: 105e4
|
|
222952
|
+
},
|
|
222953
|
+
{
|
|
222954
|
+
model: "gpt-5.5",
|
|
222955
|
+
provider: "openai",
|
|
222956
|
+
modality: "text",
|
|
222957
|
+
currency: "USD",
|
|
222958
|
+
asOf: "2026-07-27",
|
|
222959
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
222960
|
+
provenance: "litellm-catalog",
|
|
222961
|
+
tiers: [
|
|
222962
|
+
{
|
|
222963
|
+
maxInputTokens: 272e3,
|
|
222964
|
+
inputPer1m: 5,
|
|
222965
|
+
outputPer1m: 30,
|
|
222966
|
+
cachedInputPer1m: 0.5
|
|
222967
|
+
},
|
|
222968
|
+
{
|
|
222969
|
+
inputPer1m: 10,
|
|
222970
|
+
outputPer1m: 45,
|
|
222971
|
+
cachedInputPer1m: 1
|
|
222972
|
+
}
|
|
222973
|
+
],
|
|
222974
|
+
batchMultiplier: 0.5,
|
|
222975
|
+
contextWindow: 105e4
|
|
222976
|
+
},
|
|
222977
|
+
{
|
|
222978
|
+
model: "gpt-5.4",
|
|
222979
|
+
provider: "openai",
|
|
222980
|
+
modality: "text",
|
|
222981
|
+
currency: "USD",
|
|
222982
|
+
asOf: "2026-07-27",
|
|
222983
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
222984
|
+
provenance: "litellm-catalog",
|
|
222985
|
+
tiers: [
|
|
222986
|
+
{
|
|
222987
|
+
maxInputTokens: 272e3,
|
|
222988
|
+
inputPer1m: 2.5,
|
|
222989
|
+
outputPer1m: 15,
|
|
222990
|
+
cachedInputPer1m: 0.25
|
|
222991
|
+
},
|
|
222992
|
+
{
|
|
222993
|
+
inputPer1m: 5,
|
|
222994
|
+
outputPer1m: 22.5,
|
|
222995
|
+
cachedInputPer1m: 0.5
|
|
222996
|
+
}
|
|
222997
|
+
],
|
|
222998
|
+
batchMultiplier: 0.5,
|
|
222999
|
+
contextWindow: 105e4
|
|
223000
|
+
},
|
|
223001
|
+
{
|
|
223002
|
+
model: "gpt-5.4-mini",
|
|
223003
|
+
provider: "openai",
|
|
223004
|
+
modality: "text",
|
|
223005
|
+
currency: "USD",
|
|
223006
|
+
asOf: "2026-07-27",
|
|
223007
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223008
|
+
provenance: "litellm-catalog",
|
|
223009
|
+
tiers: [
|
|
223010
|
+
{
|
|
223011
|
+
inputPer1m: 0.75,
|
|
223012
|
+
outputPer1m: 4.5,
|
|
223013
|
+
cachedInputPer1m: 0.075
|
|
223014
|
+
}
|
|
223015
|
+
],
|
|
223016
|
+
batchMultiplier: 0.5,
|
|
223017
|
+
contextWindow: 105e4
|
|
223018
|
+
},
|
|
223019
|
+
{
|
|
223020
|
+
model: "gpt-5",
|
|
223021
|
+
provider: "openai",
|
|
223022
|
+
modality: "text",
|
|
223023
|
+
currency: "USD",
|
|
223024
|
+
asOf: "2026-07-27",
|
|
223025
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223026
|
+
provenance: "litellm-catalog",
|
|
223027
|
+
tiers: [
|
|
223028
|
+
{
|
|
223029
|
+
inputPer1m: 1.25,
|
|
223030
|
+
outputPer1m: 10,
|
|
223031
|
+
cachedInputPer1m: 0.125
|
|
223032
|
+
}
|
|
223033
|
+
],
|
|
223034
|
+
contextWindow: 272e3
|
|
223035
|
+
},
|
|
223036
|
+
{
|
|
223037
|
+
model: "gpt-5-mini",
|
|
223038
|
+
provider: "openai",
|
|
223039
|
+
modality: "text",
|
|
223040
|
+
currency: "USD",
|
|
223041
|
+
asOf: "2026-07-27",
|
|
223042
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223043
|
+
provenance: "litellm-catalog",
|
|
223044
|
+
tiers: [
|
|
223045
|
+
{
|
|
223046
|
+
inputPer1m: 0.25,
|
|
223047
|
+
outputPer1m: 2,
|
|
223048
|
+
cachedInputPer1m: 0.025
|
|
223049
|
+
}
|
|
223050
|
+
],
|
|
223051
|
+
contextWindow: 272e3
|
|
223052
|
+
},
|
|
223053
|
+
{
|
|
223054
|
+
model: "gpt-5-nano",
|
|
223055
|
+
provider: "openai",
|
|
223056
|
+
modality: "text",
|
|
223057
|
+
currency: "USD",
|
|
223058
|
+
asOf: "2026-07-27",
|
|
223059
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223060
|
+
provenance: "litellm-catalog",
|
|
223061
|
+
tiers: [
|
|
223062
|
+
{
|
|
223063
|
+
inputPer1m: 0.05,
|
|
223064
|
+
outputPer1m: 0.4,
|
|
223065
|
+
cachedInputPer1m: 5e-3
|
|
223066
|
+
}
|
|
223067
|
+
],
|
|
223068
|
+
contextWindow: 272e3
|
|
223069
|
+
},
|
|
223070
|
+
{
|
|
223071
|
+
model: "gpt-4.1",
|
|
223072
|
+
provider: "openai",
|
|
223073
|
+
modality: "text",
|
|
223074
|
+
currency: "USD",
|
|
223075
|
+
asOf: "2026-07-27",
|
|
223076
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223077
|
+
provenance: "litellm-catalog",
|
|
223078
|
+
tiers: [
|
|
223079
|
+
{
|
|
223080
|
+
inputPer1m: 2,
|
|
223081
|
+
outputPer1m: 8,
|
|
223082
|
+
cachedInputPer1m: 0.5
|
|
223083
|
+
}
|
|
223084
|
+
],
|
|
223085
|
+
batchMultiplier: 0.5,
|
|
223086
|
+
contextWindow: 1047576
|
|
223087
|
+
},
|
|
223088
|
+
{
|
|
223089
|
+
model: "gpt-4.1-mini",
|
|
223090
|
+
provider: "openai",
|
|
223091
|
+
modality: "text",
|
|
223092
|
+
currency: "USD",
|
|
223093
|
+
asOf: "2026-07-27",
|
|
223094
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223095
|
+
provenance: "litellm-catalog",
|
|
223096
|
+
tiers: [
|
|
223097
|
+
{
|
|
223098
|
+
inputPer1m: 0.4,
|
|
223099
|
+
outputPer1m: 1.6,
|
|
223100
|
+
cachedInputPer1m: 0.1
|
|
223101
|
+
}
|
|
223102
|
+
],
|
|
223103
|
+
batchMultiplier: 0.5,
|
|
223104
|
+
contextWindow: 1047576
|
|
223105
|
+
},
|
|
223106
|
+
{
|
|
223107
|
+
model: "gpt-4.1-nano",
|
|
223108
|
+
provider: "openai",
|
|
223109
|
+
modality: "text",
|
|
223110
|
+
currency: "USD",
|
|
223111
|
+
asOf: "2026-07-27",
|
|
223112
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223113
|
+
provenance: "litellm-catalog",
|
|
223114
|
+
tiers: [
|
|
223115
|
+
{
|
|
223116
|
+
inputPer1m: 0.1,
|
|
223117
|
+
outputPer1m: 0.4,
|
|
223118
|
+
cachedInputPer1m: 0.025
|
|
223119
|
+
}
|
|
223120
|
+
],
|
|
223121
|
+
batchMultiplier: 0.5,
|
|
223122
|
+
contextWindow: 1047576
|
|
223123
|
+
},
|
|
223124
|
+
{
|
|
223125
|
+
model: "gpt-4o",
|
|
223126
|
+
provider: "openai",
|
|
223127
|
+
modality: "text",
|
|
223128
|
+
currency: "USD",
|
|
223129
|
+
asOf: "2026-07-27",
|
|
223130
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223131
|
+
provenance: "litellm-catalog",
|
|
223132
|
+
tiers: [
|
|
223133
|
+
{
|
|
223134
|
+
inputPer1m: 2.5,
|
|
223135
|
+
outputPer1m: 10,
|
|
223136
|
+
cachedInputPer1m: 1.25
|
|
223137
|
+
}
|
|
223138
|
+
],
|
|
223139
|
+
batchMultiplier: 0.5,
|
|
223140
|
+
contextWindow: 128e3
|
|
223141
|
+
},
|
|
223142
|
+
{
|
|
223143
|
+
model: "gpt-4o-mini",
|
|
223144
|
+
provider: "openai",
|
|
223145
|
+
modality: "text",
|
|
223146
|
+
currency: "USD",
|
|
223147
|
+
asOf: "2026-07-27",
|
|
223148
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223149
|
+
provenance: "litellm-catalog",
|
|
223150
|
+
tiers: [
|
|
223151
|
+
{
|
|
223152
|
+
inputPer1m: 0.15,
|
|
223153
|
+
outputPer1m: 0.6,
|
|
223154
|
+
cachedInputPer1m: 0.075
|
|
223155
|
+
}
|
|
223156
|
+
],
|
|
223157
|
+
batchMultiplier: 0.5,
|
|
223158
|
+
contextWindow: 128e3
|
|
223159
|
+
},
|
|
223160
|
+
{
|
|
223161
|
+
model: "gpt-5.5",
|
|
223162
|
+
provider: "azure",
|
|
223163
|
+
region: "global",
|
|
223164
|
+
modality: "text",
|
|
223165
|
+
currency: "USD",
|
|
223166
|
+
asOf: "2026-07-27",
|
|
223167
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223168
|
+
provenance: "litellm-catalog",
|
|
223169
|
+
tiers: [
|
|
223170
|
+
{
|
|
223171
|
+
maxInputTokens: 272e3,
|
|
223172
|
+
inputPer1m: 5,
|
|
223173
|
+
outputPer1m: 30,
|
|
223174
|
+
cachedInputPer1m: 0.5
|
|
223175
|
+
},
|
|
223176
|
+
{
|
|
223177
|
+
inputPer1m: 10,
|
|
223178
|
+
outputPer1m: 45,
|
|
223179
|
+
cachedInputPer1m: 1
|
|
223180
|
+
}
|
|
223181
|
+
],
|
|
223182
|
+
contextWindow: 105e4
|
|
223183
|
+
},
|
|
223184
|
+
{
|
|
223185
|
+
model: "gpt-5.5",
|
|
223186
|
+
provider: "azure",
|
|
223187
|
+
region: "us",
|
|
223188
|
+
modality: "text",
|
|
223189
|
+
currency: "USD",
|
|
223190
|
+
asOf: "2026-07-27",
|
|
223191
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223192
|
+
provenance: "litellm-catalog",
|
|
223193
|
+
tiers: [
|
|
223194
|
+
{
|
|
223195
|
+
maxInputTokens: 272e3,
|
|
223196
|
+
inputPer1m: 5.5,
|
|
223197
|
+
outputPer1m: 33,
|
|
223198
|
+
cachedInputPer1m: 0.55
|
|
223199
|
+
},
|
|
223200
|
+
{
|
|
223201
|
+
inputPer1m: 11,
|
|
223202
|
+
outputPer1m: 49.5,
|
|
223203
|
+
cachedInputPer1m: 1.1
|
|
223204
|
+
}
|
|
223205
|
+
],
|
|
223206
|
+
contextWindow: 105e4
|
|
223207
|
+
},
|
|
223208
|
+
{
|
|
223209
|
+
model: "gpt-5.5",
|
|
223210
|
+
provider: "azure",
|
|
223211
|
+
region: "eu",
|
|
223212
|
+
modality: "text",
|
|
223213
|
+
currency: "USD",
|
|
223214
|
+
asOf: "2026-07-27",
|
|
223215
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223216
|
+
provenance: "litellm-catalog",
|
|
223217
|
+
tiers: [
|
|
223218
|
+
{
|
|
223219
|
+
maxInputTokens: 272e3,
|
|
223220
|
+
inputPer1m: 5.5,
|
|
223221
|
+
outputPer1m: 33,
|
|
223222
|
+
cachedInputPer1m: 0.55
|
|
223223
|
+
},
|
|
223224
|
+
{
|
|
223225
|
+
inputPer1m: 11,
|
|
223226
|
+
outputPer1m: 49.5,
|
|
223227
|
+
cachedInputPer1m: 1.1
|
|
223228
|
+
}
|
|
223229
|
+
],
|
|
223230
|
+
contextWindow: 105e4
|
|
223231
|
+
},
|
|
223232
|
+
{
|
|
223233
|
+
model: "gpt-5.4",
|
|
223234
|
+
provider: "azure",
|
|
223235
|
+
region: "global",
|
|
223236
|
+
modality: "text",
|
|
223237
|
+
currency: "USD",
|
|
223238
|
+
asOf: "2026-07-27",
|
|
223239
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223240
|
+
provenance: "litellm-catalog",
|
|
223241
|
+
tiers: [
|
|
223242
|
+
{
|
|
223243
|
+
maxInputTokens: 272e3,
|
|
223244
|
+
inputPer1m: 2.5,
|
|
223245
|
+
outputPer1m: 15,
|
|
223246
|
+
cachedInputPer1m: 0.25
|
|
223247
|
+
},
|
|
223248
|
+
{
|
|
223249
|
+
inputPer1m: 5,
|
|
223250
|
+
outputPer1m: 22.5,
|
|
223251
|
+
cachedInputPer1m: 0.5
|
|
223252
|
+
}
|
|
223253
|
+
],
|
|
223254
|
+
contextWindow: 105e4
|
|
223255
|
+
},
|
|
223256
|
+
{
|
|
223257
|
+
model: "gpt-5.4",
|
|
223258
|
+
provider: "azure",
|
|
223259
|
+
region: "us",
|
|
223260
|
+
modality: "text",
|
|
223261
|
+
currency: "USD",
|
|
223262
|
+
asOf: "2026-07-27",
|
|
223263
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223264
|
+
provenance: "litellm-catalog",
|
|
223265
|
+
tiers: [
|
|
223266
|
+
{
|
|
223267
|
+
inputPer1m: 2.75,
|
|
223268
|
+
outputPer1m: 16.5,
|
|
223269
|
+
cachedInputPer1m: 0.28
|
|
223270
|
+
}
|
|
223271
|
+
],
|
|
223272
|
+
contextWindow: 105e4
|
|
223273
|
+
},
|
|
223274
|
+
{
|
|
223275
|
+
model: "gpt-5.4",
|
|
223276
|
+
provider: "azure",
|
|
223277
|
+
region: "eu",
|
|
223278
|
+
modality: "text",
|
|
223279
|
+
currency: "USD",
|
|
223280
|
+
asOf: "2026-07-27",
|
|
223281
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223282
|
+
provenance: "litellm-catalog",
|
|
223283
|
+
tiers: [
|
|
223284
|
+
{
|
|
223285
|
+
inputPer1m: 2.75,
|
|
223286
|
+
outputPer1m: 16.5,
|
|
223287
|
+
cachedInputPer1m: 0.28
|
|
223288
|
+
}
|
|
223289
|
+
],
|
|
223290
|
+
contextWindow: 105e4
|
|
223291
|
+
},
|
|
223292
|
+
{
|
|
223293
|
+
model: "gpt-5.6-terra",
|
|
223294
|
+
provider: "azure",
|
|
223295
|
+
region: "global",
|
|
223296
|
+
modality: "text",
|
|
223297
|
+
currency: "USD",
|
|
223298
|
+
asOf: "2026-07-27",
|
|
223299
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223300
|
+
provenance: "litellm-catalog",
|
|
223301
|
+
tiers: [
|
|
223302
|
+
{
|
|
223303
|
+
maxInputTokens: 272e3,
|
|
223304
|
+
inputPer1m: 2.5,
|
|
223305
|
+
outputPer1m: 15,
|
|
223306
|
+
cachedInputPer1m: 0.25
|
|
223307
|
+
},
|
|
223308
|
+
{
|
|
223309
|
+
inputPer1m: 5,
|
|
223310
|
+
outputPer1m: 22.5,
|
|
223311
|
+
cachedInputPer1m: 0.5
|
|
223312
|
+
}
|
|
223313
|
+
],
|
|
223314
|
+
contextWindow: 105e4
|
|
223315
|
+
},
|
|
223316
|
+
{
|
|
223317
|
+
model: "gpt-5.6-terra",
|
|
223318
|
+
provider: "azure",
|
|
223319
|
+
region: "eu",
|
|
223320
|
+
modality: "text",
|
|
223321
|
+
currency: "USD",
|
|
223322
|
+
asOf: "2026-07-27",
|
|
223323
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223324
|
+
provenance: "litellm-catalog",
|
|
223325
|
+
tiers: [
|
|
223326
|
+
{
|
|
223327
|
+
maxInputTokens: 272e3,
|
|
223328
|
+
inputPer1m: 2.75,
|
|
223329
|
+
outputPer1m: 16.5,
|
|
223330
|
+
cachedInputPer1m: 0.275
|
|
223331
|
+
},
|
|
223332
|
+
{
|
|
223333
|
+
inputPer1m: 5.5,
|
|
223334
|
+
outputPer1m: 24.75,
|
|
223335
|
+
cachedInputPer1m: 0.55
|
|
223336
|
+
}
|
|
223337
|
+
],
|
|
223338
|
+
contextWindow: 105e4
|
|
223339
|
+
},
|
|
223340
|
+
{
|
|
223341
|
+
model: "gpt-5",
|
|
223342
|
+
provider: "azure",
|
|
223343
|
+
region: "global",
|
|
223344
|
+
modality: "text",
|
|
223345
|
+
currency: "USD",
|
|
223346
|
+
asOf: "2026-07-27",
|
|
223347
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223348
|
+
provenance: "litellm-catalog",
|
|
223349
|
+
tiers: [
|
|
223350
|
+
{
|
|
223351
|
+
inputPer1m: 1.25,
|
|
223352
|
+
outputPer1m: 10,
|
|
223353
|
+
cachedInputPer1m: 0.125
|
|
223354
|
+
}
|
|
223355
|
+
],
|
|
223356
|
+
contextWindow: 272e3
|
|
223357
|
+
},
|
|
223358
|
+
{
|
|
223359
|
+
model: "gpt-5-mini",
|
|
223360
|
+
provider: "azure",
|
|
223361
|
+
region: "global",
|
|
223362
|
+
modality: "text",
|
|
223363
|
+
currency: "USD",
|
|
223364
|
+
asOf: "2026-07-27",
|
|
223365
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223366
|
+
provenance: "litellm-catalog",
|
|
223367
|
+
tiers: [
|
|
223368
|
+
{
|
|
223369
|
+
inputPer1m: 0.25,
|
|
223370
|
+
outputPer1m: 2,
|
|
223371
|
+
cachedInputPer1m: 0.025
|
|
223372
|
+
}
|
|
223373
|
+
],
|
|
223374
|
+
contextWindow: 272e3
|
|
223375
|
+
},
|
|
223376
|
+
{
|
|
223377
|
+
model: "gpt-5-nano",
|
|
223378
|
+
provider: "azure",
|
|
223379
|
+
region: "global",
|
|
223380
|
+
modality: "text",
|
|
223381
|
+
currency: "USD",
|
|
223382
|
+
asOf: "2026-07-27",
|
|
223383
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223384
|
+
provenance: "litellm-catalog",
|
|
223385
|
+
tiers: [
|
|
223386
|
+
{
|
|
223387
|
+
inputPer1m: 0.05,
|
|
223388
|
+
outputPer1m: 0.4,
|
|
223389
|
+
cachedInputPer1m: 5e-3
|
|
223390
|
+
}
|
|
223391
|
+
],
|
|
223392
|
+
contextWindow: 272e3
|
|
223393
|
+
},
|
|
223394
|
+
{
|
|
223395
|
+
model: "gpt-4.1",
|
|
223396
|
+
provider: "azure",
|
|
223397
|
+
region: "global",
|
|
223398
|
+
modality: "text",
|
|
223399
|
+
currency: "USD",
|
|
223400
|
+
asOf: "2026-07-27",
|
|
223401
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223402
|
+
provenance: "litellm-catalog",
|
|
223403
|
+
tiers: [
|
|
223404
|
+
{
|
|
223405
|
+
inputPer1m: 2,
|
|
223406
|
+
outputPer1m: 8,
|
|
223407
|
+
cachedInputPer1m: 0.5
|
|
223408
|
+
}
|
|
223409
|
+
],
|
|
223410
|
+
batchMultiplier: 0.5,
|
|
223411
|
+
contextWindow: 1047576
|
|
223412
|
+
},
|
|
223413
|
+
{
|
|
223414
|
+
model: "gpt-4o",
|
|
223415
|
+
provider: "azure",
|
|
223416
|
+
region: "global",
|
|
223417
|
+
modality: "text",
|
|
223418
|
+
currency: "USD",
|
|
223419
|
+
asOf: "2026-07-27",
|
|
223420
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223421
|
+
provenance: "litellm-catalog",
|
|
223422
|
+
tiers: [
|
|
223423
|
+
{
|
|
223424
|
+
inputPer1m: 2.5,
|
|
223425
|
+
outputPer1m: 10,
|
|
223426
|
+
cachedInputPer1m: 1.25
|
|
223427
|
+
}
|
|
223428
|
+
],
|
|
223429
|
+
contextWindow: 128e3
|
|
223430
|
+
},
|
|
223431
|
+
{
|
|
223432
|
+
model: "gpt-4o-mini",
|
|
223433
|
+
provider: "azure",
|
|
223434
|
+
region: "global",
|
|
223435
|
+
modality: "text",
|
|
223436
|
+
currency: "USD",
|
|
223437
|
+
asOf: "2026-07-27",
|
|
223438
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223439
|
+
provenance: "litellm-catalog",
|
|
223440
|
+
tiers: [
|
|
223441
|
+
{
|
|
223442
|
+
inputPer1m: 0.165,
|
|
223443
|
+
outputPer1m: 0.66,
|
|
223444
|
+
cachedInputPer1m: 0.075
|
|
223445
|
+
}
|
|
223446
|
+
],
|
|
223447
|
+
contextWindow: 128e3,
|
|
223448
|
+
notes: "Azure charges $0.165/$0.66 per 1M for gpt-4o-mini vs $0.15/$0.60 on OpenAI \u2014 same model, different price."
|
|
223449
|
+
},
|
|
223450
|
+
{
|
|
223451
|
+
model: "gemini-3.1-pro",
|
|
223452
|
+
provider: "gemini",
|
|
223453
|
+
aliases: [
|
|
223454
|
+
"gemini-3.1-pro-preview"
|
|
223455
|
+
],
|
|
223456
|
+
modality: "text",
|
|
223457
|
+
currency: "USD",
|
|
223458
|
+
asOf: "2026-07-27",
|
|
223459
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223460
|
+
provenance: "vendor-pricing-page",
|
|
223461
|
+
tiers: [
|
|
223462
|
+
{
|
|
223463
|
+
maxInputTokens: 2e5,
|
|
223464
|
+
inputPer1m: 2,
|
|
223465
|
+
outputPer1m: 12,
|
|
223466
|
+
cachedInputPer1m: 0.2,
|
|
223467
|
+
reasoningOutputPer1m: 12
|
|
223468
|
+
},
|
|
223469
|
+
{
|
|
223470
|
+
inputPer1m: 4,
|
|
223471
|
+
outputPer1m: 18,
|
|
223472
|
+
cachedInputPer1m: 0.4,
|
|
223473
|
+
reasoningOutputPer1m: 18
|
|
223474
|
+
}
|
|
223475
|
+
],
|
|
223476
|
+
batchMultiplier: 0.5,
|
|
223477
|
+
contextWindow: 1048576,
|
|
223478
|
+
notes: "Long-context tier: $2/$12 per 1M up to 200K prompt tokens, $4/$18 above it."
|
|
223479
|
+
},
|
|
223480
|
+
{
|
|
223481
|
+
model: "gemini-3-pro",
|
|
223482
|
+
provider: "gemini",
|
|
223483
|
+
aliases: [
|
|
223484
|
+
"gemini-3-pro-preview"
|
|
223485
|
+
],
|
|
223486
|
+
modality: "text",
|
|
223487
|
+
currency: "USD",
|
|
223488
|
+
asOf: "2026-07-27",
|
|
223489
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223490
|
+
provenance: "vendor-pricing-page",
|
|
223491
|
+
tiers: [
|
|
223492
|
+
{
|
|
223493
|
+
maxInputTokens: 2e5,
|
|
223494
|
+
inputPer1m: 2,
|
|
223495
|
+
outputPer1m: 12,
|
|
223496
|
+
cachedInputPer1m: 0.2,
|
|
223497
|
+
reasoningOutputPer1m: 12
|
|
223498
|
+
},
|
|
223499
|
+
{
|
|
223500
|
+
inputPer1m: 4,
|
|
223501
|
+
outputPer1m: 18,
|
|
223502
|
+
cachedInputPer1m: 0.4,
|
|
223503
|
+
reasoningOutputPer1m: 18
|
|
223504
|
+
}
|
|
223505
|
+
],
|
|
223506
|
+
batchMultiplier: 0.5,
|
|
223507
|
+
contextWindow: 1048576
|
|
223508
|
+
},
|
|
223509
|
+
{
|
|
223510
|
+
model: "gemini-3.6-flash",
|
|
223511
|
+
provider: "gemini",
|
|
223512
|
+
modality: "text",
|
|
223513
|
+
currency: "USD",
|
|
223514
|
+
asOf: "2026-07-27",
|
|
223515
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223516
|
+
provenance: "vendor-pricing-page",
|
|
223517
|
+
tiers: [
|
|
223518
|
+
{
|
|
223519
|
+
inputPer1m: 1.5,
|
|
223520
|
+
outputPer1m: 7.5,
|
|
223521
|
+
cachedInputPer1m: 0.15,
|
|
223522
|
+
reasoningOutputPer1m: 7.5
|
|
223523
|
+
}
|
|
223524
|
+
],
|
|
223525
|
+
batchMultiplier: 0.5,
|
|
223526
|
+
contextWindow: 1048576,
|
|
223527
|
+
notes: "Released 2026-07-21. Output pricing dropped ~17% from Gemini 3.5 Flash ($9.00 -> $7.50 per 1M); input unchanged."
|
|
223528
|
+
},
|
|
223529
|
+
{
|
|
223530
|
+
model: "gemini-3.5-flash",
|
|
223531
|
+
provider: "gemini",
|
|
223532
|
+
modality: "text",
|
|
223533
|
+
currency: "USD",
|
|
223534
|
+
asOf: "2026-07-27",
|
|
223535
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223536
|
+
provenance: "vendor-pricing-page",
|
|
223537
|
+
tiers: [
|
|
223538
|
+
{
|
|
223539
|
+
inputPer1m: 1.5,
|
|
223540
|
+
outputPer1m: 9,
|
|
223541
|
+
cachedInputPer1m: 0.15,
|
|
223542
|
+
reasoningOutputPer1m: 9
|
|
223543
|
+
}
|
|
223544
|
+
],
|
|
223545
|
+
batchMultiplier: 0.5,
|
|
223546
|
+
contextWindow: 1048576
|
|
223547
|
+
},
|
|
223548
|
+
{
|
|
223549
|
+
model: "gemini-3.5-flash-lite",
|
|
223550
|
+
provider: "gemini",
|
|
223551
|
+
modality: "text",
|
|
223552
|
+
currency: "USD",
|
|
223553
|
+
asOf: "2026-07-27",
|
|
223554
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing",
|
|
223555
|
+
provenance: "litellm-catalog",
|
|
223556
|
+
tiers: [
|
|
223557
|
+
{
|
|
223558
|
+
inputPer1m: 0.3,
|
|
223559
|
+
outputPer1m: 2.5,
|
|
223560
|
+
cachedInputPer1m: 0.03,
|
|
223561
|
+
reasoningOutputPer1m: 2.5
|
|
223562
|
+
}
|
|
223563
|
+
],
|
|
223564
|
+
batchMultiplier: 0.5,
|
|
223565
|
+
contextWindow: 1048576
|
|
223566
|
+
},
|
|
223567
|
+
{
|
|
223568
|
+
model: "gemini-3.1-flash-lite",
|
|
223569
|
+
provider: "gemini",
|
|
223570
|
+
modality: "text",
|
|
223571
|
+
currency: "USD",
|
|
223572
|
+
asOf: "2026-07-27",
|
|
223573
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing#gemini-3.1-flash-lite",
|
|
223574
|
+
provenance: "litellm-catalog",
|
|
223575
|
+
tiers: [
|
|
223576
|
+
{
|
|
223577
|
+
inputPer1m: 0.25,
|
|
223578
|
+
outputPer1m: 1.5,
|
|
223579
|
+
cachedInputPer1m: 0.025,
|
|
223580
|
+
reasoningOutputPer1m: 1.5
|
|
223581
|
+
}
|
|
223582
|
+
],
|
|
223583
|
+
batchMultiplier: 0.5,
|
|
223584
|
+
contextWindow: 1048576
|
|
223585
|
+
},
|
|
223586
|
+
{
|
|
223587
|
+
model: "gemini-3-flash",
|
|
223588
|
+
provider: "gemini",
|
|
223589
|
+
aliases: [
|
|
223590
|
+
"gemini-3-flash-preview"
|
|
223591
|
+
],
|
|
223592
|
+
modality: "text",
|
|
223593
|
+
currency: "USD",
|
|
223594
|
+
asOf: "2026-07-27",
|
|
223595
|
+
source: "https://ai.google.dev/pricing/gemini-3",
|
|
223596
|
+
provenance: "litellm-catalog",
|
|
223597
|
+
tiers: [
|
|
223598
|
+
{
|
|
223599
|
+
inputPer1m: 0.5,
|
|
223600
|
+
outputPer1m: 3,
|
|
223601
|
+
cachedInputPer1m: 0.05,
|
|
223602
|
+
reasoningOutputPer1m: 3
|
|
223603
|
+
}
|
|
223604
|
+
],
|
|
223605
|
+
contextWindow: 1048576
|
|
223606
|
+
},
|
|
223607
|
+
{
|
|
223608
|
+
model: "gemini-2.5-pro",
|
|
223609
|
+
provider: "gemini",
|
|
223610
|
+
modality: "text",
|
|
223611
|
+
currency: "USD",
|
|
223612
|
+
asOf: "2026-07-27",
|
|
223613
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223614
|
+
provenance: "litellm-catalog",
|
|
223615
|
+
tiers: [
|
|
223616
|
+
{
|
|
223617
|
+
maxInputTokens: 2e5,
|
|
223618
|
+
inputPer1m: 1.25,
|
|
223619
|
+
outputPer1m: 10,
|
|
223620
|
+
cachedInputPer1m: 0.125
|
|
223621
|
+
},
|
|
223622
|
+
{
|
|
223623
|
+
inputPer1m: 2.5,
|
|
223624
|
+
outputPer1m: 15,
|
|
223625
|
+
cachedInputPer1m: 0.25
|
|
223626
|
+
}
|
|
223627
|
+
],
|
|
223628
|
+
contextWindow: 1048576
|
|
223629
|
+
},
|
|
223630
|
+
{
|
|
223631
|
+
model: "gemini-2.5-flash",
|
|
223632
|
+
provider: "gemini",
|
|
223633
|
+
modality: "text",
|
|
223634
|
+
currency: "USD",
|
|
223635
|
+
asOf: "2026-07-27",
|
|
223636
|
+
source: "https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash-preview",
|
|
223637
|
+
provenance: "litellm-catalog",
|
|
223638
|
+
tiers: [
|
|
223639
|
+
{
|
|
223640
|
+
inputPer1m: 0.3,
|
|
223641
|
+
outputPer1m: 2.5,
|
|
223642
|
+
cachedInputPer1m: 0.03,
|
|
223643
|
+
reasoningOutputPer1m: 2.5
|
|
223644
|
+
}
|
|
223645
|
+
],
|
|
223646
|
+
contextWindow: 1048576
|
|
223647
|
+
},
|
|
223648
|
+
{
|
|
223649
|
+
model: "gemini-2.5-flash-lite",
|
|
223650
|
+
provider: "gemini",
|
|
223651
|
+
modality: "text",
|
|
223652
|
+
currency: "USD",
|
|
223653
|
+
asOf: "2026-07-27",
|
|
223654
|
+
source: "https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash-lite",
|
|
223655
|
+
provenance: "litellm-catalog",
|
|
223656
|
+
tiers: [
|
|
223657
|
+
{
|
|
223658
|
+
inputPer1m: 0.1,
|
|
223659
|
+
outputPer1m: 0.4,
|
|
223660
|
+
cachedInputPer1m: 0.01,
|
|
223661
|
+
reasoningOutputPer1m: 0.4
|
|
223662
|
+
}
|
|
223663
|
+
],
|
|
223664
|
+
contextWindow: 1048576
|
|
223665
|
+
},
|
|
223666
|
+
{
|
|
223667
|
+
model: "gemini-2.0-flash",
|
|
223668
|
+
provider: "gemini",
|
|
223669
|
+
modality: "text",
|
|
223670
|
+
currency: "USD",
|
|
223671
|
+
asOf: "2026-07-27",
|
|
223672
|
+
source: "https://ai.google.dev/pricing#2_0flash",
|
|
223673
|
+
provenance: "litellm-catalog",
|
|
223674
|
+
tiers: [
|
|
223675
|
+
{
|
|
223676
|
+
inputPer1m: 0.1,
|
|
223677
|
+
outputPer1m: 0.4,
|
|
223678
|
+
cachedInputPer1m: 0.025
|
|
223679
|
+
}
|
|
223680
|
+
],
|
|
223681
|
+
contextWindow: 1048576,
|
|
223682
|
+
notes: "Gemini Developer API price. Vertex AI lists $0.15/$0.60 per 1M for the same model \u2014 see the vertex entry."
|
|
223683
|
+
},
|
|
223684
|
+
{
|
|
223685
|
+
model: "gemini-2.0-flash-lite",
|
|
223686
|
+
provider: "gemini",
|
|
223687
|
+
modality: "text",
|
|
223688
|
+
currency: "USD",
|
|
223689
|
+
asOf: "2026-07-27",
|
|
223690
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing#gemini-2.0-flash-lite",
|
|
223691
|
+
provenance: "litellm-catalog",
|
|
223692
|
+
tiers: [
|
|
223693
|
+
{
|
|
223694
|
+
inputPer1m: 0.075,
|
|
223695
|
+
outputPer1m: 0.3,
|
|
223696
|
+
cachedInputPer1m: 0.01875
|
|
223697
|
+
}
|
|
223698
|
+
],
|
|
223699
|
+
contextWindow: 1048576
|
|
223700
|
+
},
|
|
223701
|
+
{
|
|
223702
|
+
model: "gemini-2.0-flash",
|
|
223703
|
+
provider: "vertex",
|
|
223704
|
+
modality: "text",
|
|
223705
|
+
currency: "USD",
|
|
223706
|
+
asOf: "2026-07-27",
|
|
223707
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223708
|
+
provenance: "vendor-pricing-page",
|
|
223709
|
+
tiers: [
|
|
223710
|
+
{
|
|
223711
|
+
inputPer1m: 0.15,
|
|
223712
|
+
outputPer1m: 0.6
|
|
223713
|
+
}
|
|
223714
|
+
],
|
|
223715
|
+
batchMultiplier: 0.5,
|
|
223716
|
+
notes: "Vertex AI lists $0.15/$0.60 per 1M; the Gemini Developer API lists $0.10/$0.40 for the same model."
|
|
223717
|
+
},
|
|
223718
|
+
{
|
|
223719
|
+
model: "gemini-3.1-pro",
|
|
223720
|
+
provider: "vertex",
|
|
223721
|
+
aliases: [
|
|
223722
|
+
"gemini-3.1-pro-preview"
|
|
223723
|
+
],
|
|
223724
|
+
modality: "text",
|
|
223725
|
+
currency: "USD",
|
|
223726
|
+
asOf: "2026-07-27",
|
|
223727
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223728
|
+
provenance: "vendor-pricing-page",
|
|
223729
|
+
tiers: [
|
|
223730
|
+
{
|
|
223731
|
+
maxInputTokens: 2e5,
|
|
223732
|
+
inputPer1m: 2,
|
|
223733
|
+
outputPer1m: 12,
|
|
223734
|
+
cachedInputPer1m: 0.2,
|
|
223735
|
+
reasoningOutputPer1m: 12
|
|
223736
|
+
},
|
|
223737
|
+
{
|
|
223738
|
+
inputPer1m: 4,
|
|
223739
|
+
outputPer1m: 18,
|
|
223740
|
+
cachedInputPer1m: 0.4,
|
|
223741
|
+
reasoningOutputPer1m: 18
|
|
223742
|
+
}
|
|
223743
|
+
],
|
|
223744
|
+
batchMultiplier: 0.5,
|
|
223745
|
+
contextWindow: 1048576
|
|
223746
|
+
},
|
|
223747
|
+
{
|
|
223748
|
+
model: "gemini-3.6-flash",
|
|
223749
|
+
provider: "vertex",
|
|
223750
|
+
modality: "text",
|
|
223751
|
+
currency: "USD",
|
|
223752
|
+
asOf: "2026-07-27",
|
|
223753
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223754
|
+
provenance: "vendor-pricing-page",
|
|
223755
|
+
tiers: [
|
|
223756
|
+
{
|
|
223757
|
+
inputPer1m: 1.5,
|
|
223758
|
+
outputPer1m: 7.5,
|
|
223759
|
+
cachedInputPer1m: 0.15,
|
|
223760
|
+
reasoningOutputPer1m: 7.5
|
|
223761
|
+
}
|
|
223762
|
+
],
|
|
223763
|
+
batchMultiplier: 0.5,
|
|
223764
|
+
contextWindow: 1048576
|
|
223765
|
+
},
|
|
223766
|
+
{
|
|
223767
|
+
model: "gemini-2.5-pro",
|
|
223768
|
+
provider: "vertex",
|
|
223769
|
+
modality: "text",
|
|
223770
|
+
currency: "USD",
|
|
223771
|
+
asOf: "2026-07-27",
|
|
223772
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223773
|
+
provenance: "vendor-pricing-page",
|
|
223774
|
+
tiers: [
|
|
223775
|
+
{
|
|
223776
|
+
maxInputTokens: 2e5,
|
|
223777
|
+
inputPer1m: 1.25,
|
|
223778
|
+
outputPer1m: 10,
|
|
223779
|
+
cachedInputPer1m: 0.13
|
|
223780
|
+
},
|
|
223781
|
+
{
|
|
223782
|
+
inputPer1m: 2.5,
|
|
223783
|
+
outputPer1m: 15,
|
|
223784
|
+
cachedInputPer1m: 0.25
|
|
223785
|
+
}
|
|
223786
|
+
],
|
|
223787
|
+
batchMultiplier: 0.5,
|
|
223788
|
+
contextWindow: 1048576
|
|
223789
|
+
},
|
|
223790
|
+
{
|
|
223791
|
+
model: "gemini-2.5-flash",
|
|
223792
|
+
provider: "vertex",
|
|
223793
|
+
modality: "text",
|
|
223794
|
+
currency: "USD",
|
|
223795
|
+
asOf: "2026-07-27",
|
|
223796
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
223797
|
+
provenance: "vendor-pricing-page",
|
|
223798
|
+
tiers: [
|
|
223799
|
+
{
|
|
223800
|
+
inputPer1m: 0.3,
|
|
223801
|
+
outputPer1m: 2.5,
|
|
223802
|
+
cachedInputPer1m: 0.03,
|
|
223803
|
+
reasoningOutputPer1m: 2.5
|
|
223804
|
+
}
|
|
223805
|
+
],
|
|
223806
|
+
batchMultiplier: 0.5,
|
|
223807
|
+
contextWindow: 1048576
|
|
223808
|
+
},
|
|
223809
|
+
{
|
|
223810
|
+
model: "claude-sonnet-4-6",
|
|
223811
|
+
provider: "openrouter",
|
|
223812
|
+
modality: "text",
|
|
223813
|
+
currency: "USD",
|
|
223814
|
+
asOf: "2026-07-27",
|
|
223815
|
+
source: "https://openrouter.ai/anthropic/claude-sonnet-4.6",
|
|
223816
|
+
provenance: "litellm-catalog",
|
|
223817
|
+
tiers: [
|
|
223818
|
+
{
|
|
223819
|
+
maxInputTokens: 2e5,
|
|
223820
|
+
inputPer1m: 3,
|
|
223821
|
+
outputPer1m: 15,
|
|
223822
|
+
cachedInputPer1m: 0.3,
|
|
223823
|
+
cacheWritePer1m: 3.75
|
|
223824
|
+
},
|
|
223825
|
+
{
|
|
223826
|
+
inputPer1m: 6,
|
|
223827
|
+
outputPer1m: 22.5,
|
|
223828
|
+
cachedInputPer1m: 0.6,
|
|
223829
|
+
cacheWritePer1m: 7.5
|
|
223830
|
+
}
|
|
223831
|
+
],
|
|
223832
|
+
contextWindow: 1e6
|
|
223833
|
+
},
|
|
223834
|
+
{
|
|
223835
|
+
model: "claude-haiku-4-5",
|
|
223836
|
+
provider: "openrouter",
|
|
223837
|
+
modality: "text",
|
|
223838
|
+
currency: "USD",
|
|
223839
|
+
asOf: "2026-07-27",
|
|
223840
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223841
|
+
provenance: "litellm-catalog",
|
|
223842
|
+
tiers: [
|
|
223843
|
+
{
|
|
223844
|
+
inputPer1m: 1,
|
|
223845
|
+
outputPer1m: 5,
|
|
223846
|
+
cachedInputPer1m: 0.1,
|
|
223847
|
+
cacheWritePer1m: 1.25
|
|
223848
|
+
}
|
|
223849
|
+
],
|
|
223850
|
+
contextWindow: 2e5
|
|
223851
|
+
},
|
|
223852
|
+
{
|
|
223853
|
+
model: "gpt-5",
|
|
223854
|
+
provider: "openrouter",
|
|
223855
|
+
modality: "text",
|
|
223856
|
+
currency: "USD",
|
|
223857
|
+
asOf: "2026-07-27",
|
|
223858
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223859
|
+
provenance: "litellm-catalog",
|
|
223860
|
+
tiers: [
|
|
223861
|
+
{
|
|
223862
|
+
inputPer1m: 1.25,
|
|
223863
|
+
outputPer1m: 10,
|
|
223864
|
+
cachedInputPer1m: 0.125
|
|
223865
|
+
}
|
|
223866
|
+
],
|
|
223867
|
+
contextWindow: 272e3
|
|
223868
|
+
},
|
|
223869
|
+
{
|
|
223870
|
+
model: "gpt-5-mini",
|
|
223871
|
+
provider: "openrouter",
|
|
223872
|
+
modality: "text",
|
|
223873
|
+
currency: "USD",
|
|
223874
|
+
asOf: "2026-07-27",
|
|
223875
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223876
|
+
provenance: "litellm-catalog",
|
|
223877
|
+
tiers: [
|
|
223878
|
+
{
|
|
223879
|
+
inputPer1m: 0.25,
|
|
223880
|
+
outputPer1m: 2,
|
|
223881
|
+
cachedInputPer1m: 0.025
|
|
223882
|
+
}
|
|
223883
|
+
],
|
|
223884
|
+
contextWindow: 272e3
|
|
223885
|
+
},
|
|
223886
|
+
{
|
|
223887
|
+
model: "gemini-3.1-pro",
|
|
223888
|
+
provider: "openrouter",
|
|
223889
|
+
aliases: [
|
|
223890
|
+
"gemini-3.1-pro-preview"
|
|
223891
|
+
],
|
|
223892
|
+
modality: "text",
|
|
223893
|
+
currency: "USD",
|
|
223894
|
+
asOf: "2026-07-27",
|
|
223895
|
+
source: "https://openrouter.ai/google/gemini-3.1-pro-preview",
|
|
223896
|
+
provenance: "litellm-catalog",
|
|
223897
|
+
tiers: [
|
|
223898
|
+
{
|
|
223899
|
+
maxInputTokens: 2e5,
|
|
223900
|
+
inputPer1m: 2,
|
|
223901
|
+
outputPer1m: 12,
|
|
223902
|
+
cachedInputPer1m: 0.2
|
|
223903
|
+
},
|
|
223904
|
+
{
|
|
223905
|
+
inputPer1m: 4,
|
|
223906
|
+
outputPer1m: 18,
|
|
223907
|
+
cachedInputPer1m: 0.4,
|
|
223908
|
+
cacheWritePer1m: 0.25
|
|
223909
|
+
}
|
|
223910
|
+
],
|
|
223911
|
+
contextWindow: 1048576
|
|
223912
|
+
},
|
|
223913
|
+
{
|
|
223914
|
+
model: "text-embedding-3-small",
|
|
223915
|
+
provider: "openai",
|
|
223916
|
+
modality: "embedding",
|
|
223917
|
+
currency: "USD",
|
|
223918
|
+
asOf: "2026-07-27",
|
|
223919
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223920
|
+
provenance: "litellm-catalog",
|
|
223921
|
+
tiers: [
|
|
223922
|
+
{
|
|
223923
|
+
inputPer1m: 0.02,
|
|
223924
|
+
outputPer1m: 0
|
|
223925
|
+
}
|
|
223926
|
+
],
|
|
223927
|
+
batchMultiplier: 0.5,
|
|
223928
|
+
contextWindow: 8191
|
|
223929
|
+
},
|
|
223930
|
+
{
|
|
223931
|
+
model: "text-embedding-3-large",
|
|
223932
|
+
provider: "openai",
|
|
223933
|
+
modality: "embedding",
|
|
223934
|
+
currency: "USD",
|
|
223935
|
+
asOf: "2026-07-27",
|
|
223936
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223937
|
+
provenance: "litellm-catalog",
|
|
223938
|
+
tiers: [
|
|
223939
|
+
{
|
|
223940
|
+
inputPer1m: 0.13,
|
|
223941
|
+
outputPer1m: 0
|
|
223942
|
+
}
|
|
223943
|
+
],
|
|
223944
|
+
batchMultiplier: 0.5,
|
|
223945
|
+
contextWindow: 8191
|
|
223946
|
+
},
|
|
223947
|
+
{
|
|
223948
|
+
model: "gemini-embedding-001",
|
|
223949
|
+
provider: "gemini",
|
|
223950
|
+
modality: "embedding",
|
|
223951
|
+
currency: "USD",
|
|
223952
|
+
asOf: "2026-07-27",
|
|
223953
|
+
source: "https://ai.google.dev/gemini-api/docs/embeddings#model-versions",
|
|
223954
|
+
provenance: "litellm-catalog",
|
|
223955
|
+
tiers: [
|
|
223956
|
+
{
|
|
223957
|
+
inputPer1m: 0.15,
|
|
223958
|
+
outputPer1m: 0
|
|
223959
|
+
}
|
|
223960
|
+
],
|
|
223961
|
+
contextWindow: 2048
|
|
223962
|
+
},
|
|
223963
|
+
{
|
|
223964
|
+
model: "dall-e-3",
|
|
223965
|
+
provider: "openai",
|
|
223966
|
+
modality: "image",
|
|
223967
|
+
currency: "USD",
|
|
223968
|
+
asOf: "2026-07-27",
|
|
223969
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
223970
|
+
provenance: "litellm-catalog",
|
|
223971
|
+
rates: [
|
|
223972
|
+
{
|
|
223973
|
+
unit: "per_image",
|
|
223974
|
+
amount: 0.04,
|
|
223975
|
+
variant: "1024x1024 standard"
|
|
223976
|
+
}
|
|
223977
|
+
]
|
|
223978
|
+
},
|
|
223979
|
+
{
|
|
223980
|
+
model: "gemini-3-pro-image",
|
|
223981
|
+
provider: "gemini",
|
|
223982
|
+
modality: "image",
|
|
223983
|
+
currency: "USD",
|
|
223984
|
+
asOf: "2026-07-27",
|
|
223985
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing",
|
|
223986
|
+
provenance: "litellm-catalog",
|
|
223987
|
+
rates: [
|
|
223988
|
+
{
|
|
223989
|
+
unit: "per_image",
|
|
223990
|
+
amount: 0.134,
|
|
223991
|
+
variant: "default output resolution"
|
|
223992
|
+
}
|
|
223993
|
+
],
|
|
223994
|
+
notes: "Google bills image output per output-token ($120 per 1M image output tokens); $0.134/image is that rate applied to one default-resolution image. Cost per image therefore varies with resolution."
|
|
223995
|
+
},
|
|
223996
|
+
{
|
|
223997
|
+
model: "imagen-4.0-generate-001",
|
|
223998
|
+
provider: "vertex",
|
|
223999
|
+
modality: "image",
|
|
224000
|
+
currency: "USD",
|
|
224001
|
+
asOf: "2026-07-27",
|
|
224002
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
224003
|
+
provenance: "litellm-catalog",
|
|
224004
|
+
rates: [
|
|
224005
|
+
{
|
|
224006
|
+
unit: "per_image",
|
|
224007
|
+
amount: 0.04
|
|
224008
|
+
}
|
|
224009
|
+
]
|
|
224010
|
+
},
|
|
224011
|
+
{
|
|
224012
|
+
model: "veo-3.1-generate-001",
|
|
224013
|
+
provider: "gemini",
|
|
224014
|
+
modality: "video",
|
|
224015
|
+
currency: "USD",
|
|
224016
|
+
asOf: "2026-07-27",
|
|
224017
|
+
source: "https://ai.google.dev/gemini-api/docs/video",
|
|
224018
|
+
provenance: "litellm-catalog",
|
|
224019
|
+
rates: [
|
|
224020
|
+
{
|
|
224021
|
+
unit: "per_second",
|
|
224022
|
+
amount: 0.4
|
|
224023
|
+
}
|
|
224024
|
+
]
|
|
224025
|
+
},
|
|
224026
|
+
{
|
|
224027
|
+
model: "veo-3.1-generate-001",
|
|
224028
|
+
provider: "vertex",
|
|
224029
|
+
modality: "video",
|
|
224030
|
+
currency: "USD",
|
|
224031
|
+
asOf: "2026-07-27",
|
|
224032
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/veo",
|
|
224033
|
+
provenance: "litellm-catalog",
|
|
224034
|
+
rates: [
|
|
224035
|
+
{
|
|
224036
|
+
unit: "per_second",
|
|
224037
|
+
amount: 0.4
|
|
224038
|
+
}
|
|
224039
|
+
]
|
|
224040
|
+
},
|
|
224041
|
+
{
|
|
224042
|
+
model: "tts-1",
|
|
224043
|
+
provider: "openai",
|
|
224044
|
+
modality: "speech",
|
|
224045
|
+
currency: "USD",
|
|
224046
|
+
asOf: "2026-07-27",
|
|
224047
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
224048
|
+
provenance: "litellm-catalog",
|
|
224049
|
+
rates: [
|
|
224050
|
+
{
|
|
224051
|
+
unit: "per_character",
|
|
224052
|
+
amount: 15e-6
|
|
224053
|
+
}
|
|
224054
|
+
],
|
|
224055
|
+
notes: "$15 per 1M characters."
|
|
224056
|
+
},
|
|
224057
|
+
{
|
|
224058
|
+
model: "tts-1-hd",
|
|
224059
|
+
provider: "openai",
|
|
224060
|
+
modality: "speech",
|
|
224061
|
+
currency: "USD",
|
|
224062
|
+
asOf: "2026-07-27",
|
|
224063
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
224064
|
+
provenance: "litellm-catalog",
|
|
224065
|
+
rates: [
|
|
224066
|
+
{
|
|
224067
|
+
unit: "per_character",
|
|
224068
|
+
amount: 3e-5
|
|
224069
|
+
}
|
|
224070
|
+
],
|
|
224071
|
+
notes: "$30 per 1M characters."
|
|
224072
|
+
},
|
|
224073
|
+
{
|
|
224074
|
+
model: "whisper-1",
|
|
224075
|
+
provider: "openai",
|
|
224076
|
+
modality: "transcription",
|
|
224077
|
+
currency: "USD",
|
|
224078
|
+
asOf: "2026-07-27",
|
|
224079
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
224080
|
+
provenance: "litellm-catalog",
|
|
224081
|
+
rates: [
|
|
224082
|
+
{
|
|
224083
|
+
unit: "per_audio_minute",
|
|
224084
|
+
amount: 6e-3
|
|
224085
|
+
}
|
|
224086
|
+
],
|
|
224087
|
+
notes: "litellm records $0.0001 per audio second; $0.006/minute is that rate x 60."
|
|
224088
|
+
}
|
|
224089
|
+
]
|
|
224090
|
+
};
|
|
224091
|
+
|
|
224092
|
+
// src/core/router/pricing.ts
|
|
224093
|
+
var DATASET = pricing_data_default;
|
|
224094
|
+
function normalizeForPricing(id) {
|
|
224095
|
+
let s3 = id.trim().toLowerCase();
|
|
224096
|
+
s3 = s3.replace(/^models\//, "");
|
|
224097
|
+
const slash = s3.lastIndexOf("/");
|
|
224098
|
+
if (slash !== -1) s3 = s3.slice(slash + 1);
|
|
224099
|
+
const tag = s3.search(/[:@]/);
|
|
224100
|
+
if (tag !== -1) s3 = s3.slice(0, tag);
|
|
224101
|
+
s3 = s3.replace(/-latest$/, "");
|
|
224102
|
+
s3 = s3.replace(/-preview(?:-\d{2}-\d{2})?$/, "");
|
|
224103
|
+
s3 = s3.replace(/-\d{4}-\d{2}-\d{2}$/, "");
|
|
224104
|
+
s3 = s3.replace(/-\d{8}$/, "");
|
|
224105
|
+
s3 = s3.replace(/-preview$/, "");
|
|
224106
|
+
return s3;
|
|
224107
|
+
}
|
|
224108
|
+
function indexKey(model, provider, region) {
|
|
224109
|
+
return `${provider}|${normalizeForPricing(model)}|${region ?? ""}`;
|
|
224110
|
+
}
|
|
224111
|
+
var INDEX = /* @__PURE__ */ new Map();
|
|
224112
|
+
for (const entry of DATASET.entries) {
|
|
224113
|
+
for (const name of [entry.model, ...entry.aliases ?? []]) {
|
|
224114
|
+
const withRegion = indexKey(name, entry.provider, entry.region);
|
|
224115
|
+
if (!INDEX.has(withRegion)) INDEX.set(withRegion, entry);
|
|
224116
|
+
const bare = indexKey(name, entry.provider);
|
|
224117
|
+
const existing = INDEX.get(bare);
|
|
224118
|
+
if (!existing || existing.region && existing.region !== "global" && entry.region === "global") {
|
|
224119
|
+
INDEX.set(bare, entry);
|
|
224120
|
+
}
|
|
224121
|
+
}
|
|
224122
|
+
}
|
|
224123
|
+
function findPricing(modelId, provider, opts = {}) {
|
|
224124
|
+
const ids = [modelId, opts.baseModelId].filter((x5) => !!x5);
|
|
224125
|
+
const providers = [provider, ...opts.fallbackProviders ?? []];
|
|
224126
|
+
for (const p3 of providers) {
|
|
224127
|
+
for (const id of ids) {
|
|
224128
|
+
const hit = (opts.region ? INDEX.get(indexKey(id, p3, opts.region)) : void 0) ?? INDEX.get(indexKey(id, p3));
|
|
224129
|
+
if (hit) return { entry: hit, matchedProvider: p3, viaFallback: p3 !== provider };
|
|
224130
|
+
}
|
|
224131
|
+
}
|
|
224132
|
+
return null;
|
|
224133
|
+
}
|
|
224134
|
+
function tierFor(entry, inputTokens = 0) {
|
|
224135
|
+
const tiers = entry.tiers;
|
|
224136
|
+
if (!tiers?.length) return null;
|
|
224137
|
+
for (const t4 of tiers) {
|
|
224138
|
+
if (t4.maxInputTokens === void 0 || inputTokens <= t4.maxInputTokens) return t4;
|
|
224139
|
+
}
|
|
224140
|
+
return tiers[tiers.length - 1] ?? null;
|
|
224141
|
+
}
|
|
224142
|
+
var PER_1M_TO_PER_1K = 1 / 1e3;
|
|
224143
|
+
function tokenRatesPer1k(entry, opts = {}) {
|
|
224144
|
+
const tier = tierFor(entry, opts.inputTokens ?? 0);
|
|
224145
|
+
if (!tier) return null;
|
|
224146
|
+
const mult = (opts.batch ? entry.batchMultiplier ?? 1 : 1) * PER_1M_TO_PER_1K;
|
|
224147
|
+
const out = {
|
|
224148
|
+
input: tier.inputPer1m * mult,
|
|
224149
|
+
output: tier.outputPer1m * mult
|
|
224150
|
+
};
|
|
224151
|
+
if (tier.cachedInputPer1m !== void 0) out.cachedInput = tier.cachedInputPer1m * mult;
|
|
224152
|
+
if (tier.cacheWritePer1m !== void 0) out.cacheWrite = tier.cacheWritePer1m * mult;
|
|
224153
|
+
if (tier.reasoningOutputPer1m !== void 0) out.reasoningOutput = tier.reasoningOutputPer1m * mult;
|
|
224154
|
+
return out;
|
|
224155
|
+
}
|
|
224156
|
+
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]);
|
|
224157
|
+
function isLoopbackOrPrivateHost(url2) {
|
|
224158
|
+
if (!url2) return false;
|
|
224159
|
+
try {
|
|
224160
|
+
const host = new URL(url2).hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
224161
|
+
if (LOOPBACK_HOSTS.has(host) || LOOPBACK_HOSTS.has(`[${host}]`)) return true;
|
|
224162
|
+
if (host.endsWith(".local")) return true;
|
|
224163
|
+
if (/^127\./.test(host)) return true;
|
|
224164
|
+
if (/^10\./.test(host)) return true;
|
|
224165
|
+
if (/^192\.168\./.test(host)) return true;
|
|
224166
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(host)) return true;
|
|
224167
|
+
return false;
|
|
224168
|
+
} catch {
|
|
224169
|
+
return false;
|
|
224170
|
+
}
|
|
224171
|
+
}
|
|
224172
|
+
function isLocalEndpoint(cfg) {
|
|
224173
|
+
if (typeof cfg.local === "boolean") return cfg.local;
|
|
224174
|
+
if (cfg.type === "ollama") return true;
|
|
224175
|
+
if (cfg.type === "openai-compatible") return isLoopbackOrPrivateHost(cfg.baseUrl);
|
|
224176
|
+
return false;
|
|
224177
|
+
}
|
|
224178
|
+
var UNKNOWN = { input: 0, output: 0, unknown: true, free: false };
|
|
224179
|
+
var FREE = { input: 0, output: 0, unknown: false, free: true };
|
|
224180
|
+
function resolvePricing(model, opts = {}) {
|
|
224181
|
+
if (model.isLocal) return FREE;
|
|
224182
|
+
const fallbackProviders = model.provider === "azure" ? ["openai"] : model.provider === "gemini" ? ["vertex"] : [];
|
|
224183
|
+
const match = findPricing(model.id, model.provider, {
|
|
224184
|
+
region: opts.region,
|
|
224185
|
+
baseModelId: model.baseModelId,
|
|
224186
|
+
fallbackProviders
|
|
224187
|
+
});
|
|
224188
|
+
if (!match) return UNKNOWN;
|
|
224189
|
+
const rates = tokenRatesPer1k(match.entry, { inputTokens: opts.inputTokens, batch: opts.batch });
|
|
224190
|
+
if (!rates) return UNKNOWN;
|
|
224191
|
+
return {
|
|
224192
|
+
input: rates.input,
|
|
224193
|
+
output: rates.output,
|
|
224194
|
+
unknown: false,
|
|
224195
|
+
free: false,
|
|
224196
|
+
entry: match.entry,
|
|
224197
|
+
...match.viaFallback ? { estimatedFromProvider: match.matchedProvider } : {}
|
|
224198
|
+
};
|
|
224199
|
+
}
|
|
224200
|
+
function withResolvedPricing(model, opts = {}) {
|
|
224201
|
+
const p3 = resolvePricing(model, opts);
|
|
224202
|
+
return {
|
|
224203
|
+
...model,
|
|
224204
|
+
inputCostPer1kTokens: p3.input,
|
|
224205
|
+
outputCostPer1kTokens: p3.output,
|
|
224206
|
+
...p3.unknown ? { pricingUnknown: true } : { pricingUnknown: false }
|
|
224207
|
+
};
|
|
224208
|
+
}
|
|
224209
|
+
function isPricingUnknown(model) {
|
|
224210
|
+
return model.pricingUnknown === true && !model.isLocal;
|
|
224211
|
+
}
|
|
224212
|
+
var BLENDED_COST_CEILING = 0.05;
|
|
224213
|
+
function blendedCostPer1k(model) {
|
|
224214
|
+
if (isPricingUnknown(model)) return BLENDED_COST_CEILING;
|
|
224215
|
+
return model.inputCostPer1kTokens + model.outputCostPer1kTokens * 2;
|
|
224216
|
+
}
|
|
224217
|
+
var DISAGREEMENT_THRESHOLD = 0.02;
|
|
224218
|
+
function reconcilePrice(model, live) {
|
|
224219
|
+
const baseline = resolvePricing(model);
|
|
224220
|
+
const liveIsZero = !(live.input > 0) && !(live.output > 0);
|
|
224221
|
+
if (liveIsZero && !model.isLocal) {
|
|
224222
|
+
return { input: baseline.input, output: baseline.output, accepted: false };
|
|
224223
|
+
}
|
|
224224
|
+
if (baseline.unknown || !baseline.entry) {
|
|
224225
|
+
return { input: live.input, output: live.output, accepted: true };
|
|
224226
|
+
}
|
|
224227
|
+
const dsBlend = baseline.input + baseline.output * 2;
|
|
224228
|
+
const liveBlend = live.input + live.output * 2;
|
|
224229
|
+
const ratio = dsBlend > 0 ? liveBlend / dsBlend : Number.POSITIVE_INFINITY;
|
|
224230
|
+
const material = dsBlend > 0 && Math.abs(ratio - 1) > DISAGREEMENT_THRESHOLD;
|
|
224231
|
+
return {
|
|
224232
|
+
input: live.input,
|
|
224233
|
+
output: live.output,
|
|
224234
|
+
accepted: true,
|
|
224235
|
+
...material ? {
|
|
224236
|
+
disagreement: {
|
|
224237
|
+
modelId: model.id,
|
|
224238
|
+
provider: model.provider,
|
|
224239
|
+
dataset: { input: baseline.input, output: baseline.output },
|
|
224240
|
+
live: { input: live.input, output: live.output },
|
|
224241
|
+
ratio: Math.round(ratio * 1e3) / 1e3,
|
|
224242
|
+
datasetAsOf: baseline.entry.asOf,
|
|
224243
|
+
datasetSource: baseline.entry.source
|
|
224244
|
+
}
|
|
224245
|
+
} : {}
|
|
224246
|
+
};
|
|
224247
|
+
}
|
|
224248
|
+
|
|
222597
224249
|
// src/constants.ts
|
|
222598
|
-
var CASCADE_VERSION = "0.
|
|
224250
|
+
var CASCADE_VERSION = "0.50.0";
|
|
222599
224251
|
var CASCADE_CONFIG_DIR = ".cascade";
|
|
222600
224252
|
var CASCADE_MD_FILE = "CASCADE.md";
|
|
222601
224253
|
var CASCADE_IGNORE_FILE = ".cascadeignore";
|
|
@@ -222944,6 +224596,13 @@ var MODELS = {
|
|
|
222944
224596
|
for (const _m of Object.values(MODELS)) {
|
|
222945
224597
|
if (_m.supportsToolUse === void 0) _m.supportsToolUse = !_m.isLocal;
|
|
222946
224598
|
}
|
|
224599
|
+
for (const _m of Object.values(MODELS)) {
|
|
224600
|
+
const priced = resolvePricing(_m);
|
|
224601
|
+
if (priced.unknown || priced.free || priced.estimatedFromProvider) continue;
|
|
224602
|
+
_m.inputCostPer1kTokens = priced.input;
|
|
224603
|
+
_m.outputCostPer1kTokens = priced.output;
|
|
224604
|
+
_m.pricingUnknown = false;
|
|
224605
|
+
}
|
|
222947
224606
|
var T1_MODEL_PRIORITY = [
|
|
222948
224607
|
"gpt-5.5",
|
|
222949
224608
|
"gpt-5.4",
|
|
@@ -223034,21 +224693,49 @@ var PROVIDER_DISPLAY_NAMES = {
|
|
|
223034
224693
|
|
|
223035
224694
|
// src/utils/cost.ts
|
|
223036
224695
|
function resolveModelPricing(model) {
|
|
223037
|
-
|
|
223038
|
-
|
|
223039
|
-
|
|
224696
|
+
if (model.isLocal) return { input: 0, output: 0, unknown: false };
|
|
224697
|
+
if (model.inputCostPer1kTokens > 0 || model.outputCostPer1kTokens > 0) {
|
|
224698
|
+
return {
|
|
224699
|
+
input: model.inputCostPer1kTokens,
|
|
224700
|
+
output: model.outputCostPer1kTokens,
|
|
224701
|
+
unknown: false
|
|
224702
|
+
};
|
|
224703
|
+
}
|
|
224704
|
+
const fromDataset = resolvePricing(model);
|
|
224705
|
+
if (!fromDataset.unknown) {
|
|
224706
|
+
return {
|
|
224707
|
+
input: fromDataset.input,
|
|
224708
|
+
output: fromDataset.output,
|
|
224709
|
+
unknown: false,
|
|
224710
|
+
...fromDataset.estimatedFromProvider ? { estimatedFromProvider: fromDataset.estimatedFromProvider } : {}
|
|
224711
|
+
};
|
|
224712
|
+
}
|
|
224713
|
+
if (model.id) {
|
|
223040
224714
|
const known = Object.values(MODELS).find((m3) => m3.id === model.id && !m3.isLocal);
|
|
223041
|
-
if (known) {
|
|
223042
|
-
|
|
223043
|
-
|
|
224715
|
+
if (known && (known.inputCostPer1kTokens > 0 || known.outputCostPer1kTokens > 0)) {
|
|
224716
|
+
return {
|
|
224717
|
+
input: known.inputCostPer1kTokens,
|
|
224718
|
+
output: known.outputCostPer1kTokens,
|
|
224719
|
+
unknown: false
|
|
224720
|
+
};
|
|
223044
224721
|
}
|
|
223045
224722
|
}
|
|
223046
|
-
return { input, output };
|
|
224723
|
+
return { input: 0, output: 0, unknown: true };
|
|
223047
224724
|
}
|
|
223048
224725
|
function calculateCost(inputTokens, outputTokens, model) {
|
|
223049
224726
|
const { input, output } = resolveModelPricing(model);
|
|
223050
224727
|
return inputTokens / 1e3 * input + outputTokens / 1e3 * output;
|
|
223051
224728
|
}
|
|
224729
|
+
function buildTokenUsage(inputTokens, outputTokens, model) {
|
|
224730
|
+
const { input, output, unknown: unknown2 } = resolveModelPricing(model);
|
|
224731
|
+
return {
|
|
224732
|
+
inputTokens,
|
|
224733
|
+
outputTokens,
|
|
224734
|
+
totalTokens: inputTokens + outputTokens,
|
|
224735
|
+
estimatedCostUsd: inputTokens / 1e3 * input + outputTokens / 1e3 * output,
|
|
224736
|
+
...unknown2 ? { costUnknown: true } : {}
|
|
224737
|
+
};
|
|
224738
|
+
}
|
|
223052
224739
|
|
|
223053
224740
|
// src/providers/base.ts
|
|
223054
224741
|
var BaseProvider = class {
|
|
@@ -223068,12 +224755,7 @@ var BaseProvider = class {
|
|
|
223068
224755
|
return calculateCost(inputTokens, outputTokens, this.model);
|
|
223069
224756
|
}
|
|
223070
224757
|
makeUsage(inputTokens, outputTokens) {
|
|
223071
|
-
return
|
|
223072
|
-
inputTokens,
|
|
223073
|
-
outputTokens,
|
|
223074
|
-
totalTokens: inputTokens + outputTokens,
|
|
223075
|
-
estimatedCostUsd: this.estimateCost(inputTokens, outputTokens)
|
|
223076
|
-
};
|
|
224758
|
+
return buildTokenUsage(inputTokens, outputTokens, this.model);
|
|
223077
224759
|
}
|
|
223078
224760
|
};
|
|
223079
224761
|
|
|
@@ -223242,7 +224924,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
223242
224924
|
return data.data.filter((m3) => isChatModel(m3.id)).map((m3) => {
|
|
223243
224925
|
const known = Object.values(MODELS).find((km) => km.id === m3.id && km.provider === "anthropic");
|
|
223244
224926
|
if (known) return known;
|
|
223245
|
-
return {
|
|
224927
|
+
return withResolvedPricing({
|
|
223246
224928
|
id: m3.id,
|
|
223247
224929
|
name: m3.display_name || m3.id,
|
|
223248
224930
|
provider: "anthropic",
|
|
@@ -223253,7 +224935,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
223253
224935
|
maxOutputTokens: 8e3,
|
|
223254
224936
|
supportsStreaming: true,
|
|
223255
224937
|
isLocal: false
|
|
223256
|
-
};
|
|
224938
|
+
});
|
|
223257
224939
|
});
|
|
223258
224940
|
} catch {
|
|
223259
224941
|
return Object.values(MODELS).filter((m3) => m3.provider === "anthropic");
|
|
@@ -231330,7 +233012,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
231330
233012
|
return response.data.filter((m3) => isChatModel(m3.id)).map((m3) => {
|
|
231331
233013
|
const known = Object.values(MODELS).find((km) => km.id === m3.id && km.provider === "openai");
|
|
231332
233014
|
if (known) return known;
|
|
231333
|
-
return {
|
|
233015
|
+
return withResolvedPricing({
|
|
231334
233016
|
id: m3.id,
|
|
231335
233017
|
name: m3.id,
|
|
231336
233018
|
provider: "openai",
|
|
@@ -231341,7 +233023,7 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
231341
233023
|
maxOutputTokens: 4e3,
|
|
231342
233024
|
supportsStreaming: true,
|
|
231343
233025
|
isLocal: false
|
|
231344
|
-
};
|
|
233026
|
+
});
|
|
231345
233027
|
});
|
|
231346
233028
|
} catch {
|
|
231347
233029
|
return Object.values(MODELS).filter((m3) => m3.provider === "openai");
|
|
@@ -231437,6 +233119,10 @@ function azureModelForDeployment(cfg) {
|
|
|
231437
233119
|
const baseModelId = cfg.model?.trim() || inferAzureBaseModel(id) || void 0;
|
|
231438
233120
|
const base = baseModelId ? MODELS[baseModelId] : void 0;
|
|
231439
233121
|
if (base) {
|
|
233122
|
+
const azurePrice = resolvePricing(
|
|
233123
|
+
{ id, provider: "azure", isLocal: false, baseModelId },
|
|
233124
|
+
{ region: cfg.region }
|
|
233125
|
+
);
|
|
231440
233126
|
return {
|
|
231441
233127
|
...base,
|
|
231442
233128
|
id,
|
|
@@ -231445,7 +233131,12 @@ function azureModelForDeployment(cfg) {
|
|
|
231445
233131
|
provider: "azure",
|
|
231446
233132
|
baseModelId,
|
|
231447
233133
|
// real identity for benchmark + live pricing
|
|
231448
|
-
supportsToolUse: base.supportsToolUse ?? true
|
|
233134
|
+
supportsToolUse: base.supportsToolUse ?? true,
|
|
233135
|
+
...azurePrice.unknown ? {} : {
|
|
233136
|
+
inputCostPer1kTokens: azurePrice.input,
|
|
233137
|
+
outputCostPer1kTokens: azurePrice.output,
|
|
233138
|
+
pricingUnknown: false
|
|
233139
|
+
}
|
|
231449
233140
|
};
|
|
231450
233141
|
}
|
|
231451
233142
|
return {
|
|
@@ -249638,7 +251329,7 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
249638
251329
|
(km) => km.id === id && km.provider === "gemini"
|
|
249639
251330
|
);
|
|
249640
251331
|
if (known) return known;
|
|
249641
|
-
return {
|
|
251332
|
+
return withResolvedPricing({
|
|
249642
251333
|
id,
|
|
249643
251334
|
name: m3.displayName || id,
|
|
249644
251335
|
provider: "gemini",
|
|
@@ -249649,7 +251340,7 @@ var GeminiProvider = class extends BaseProvider {
|
|
|
249649
251340
|
maxOutputTokens: m3.outputTokenLimit || 8e3,
|
|
249650
251341
|
supportsStreaming: true,
|
|
249651
251342
|
isLocal: false
|
|
249652
|
-
};
|
|
251343
|
+
});
|
|
249653
251344
|
});
|
|
249654
251345
|
} catch {
|
|
249655
251346
|
return Object.values(MODELS).filter((m3) => m3.provider === "gemini");
|
|
@@ -249996,9 +251687,10 @@ var OllamaProvider = class extends BaseProvider {
|
|
|
249996
251687
|
return supportedKeywords.some((k4) => name.includes(k4)) && isChatModel(name);
|
|
249997
251688
|
});
|
|
249998
251689
|
const shows = await Promise.all(entries.map((m3) => this.showModel(m3.name)));
|
|
251690
|
+
const local = isLocalEndpoint({ ...this.config, type: "ollama" });
|
|
249999
251691
|
return entries.map((m3, i4) => {
|
|
250000
251692
|
const show = shows[i4];
|
|
250001
|
-
return {
|
|
251693
|
+
return withResolvedPricing({
|
|
250002
251694
|
id: m3.name,
|
|
250003
251695
|
name: m3.name,
|
|
250004
251696
|
provider: "ollama",
|
|
@@ -250008,10 +251700,10 @@ var OllamaProvider = class extends BaseProvider {
|
|
|
250008
251700
|
outputCostPer1kTokens: 0,
|
|
250009
251701
|
maxOutputTokens: 4e3,
|
|
250010
251702
|
supportsStreaming: true,
|
|
250011
|
-
isLocal:
|
|
251703
|
+
isLocal: local,
|
|
250012
251704
|
supportsToolUse: show?.tools ?? isToolCapable(m3.name),
|
|
250013
251705
|
minSizeB: this.parseSizeB(m3.details?.parameter_size)
|
|
250014
|
-
};
|
|
251706
|
+
});
|
|
250015
251707
|
});
|
|
250016
251708
|
} catch {
|
|
250017
251709
|
return [];
|
|
@@ -250116,7 +251808,8 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
|
250116
251808
|
}).filter((x5) => typeof x5 === "string" && x5.length > 0);
|
|
250117
251809
|
if (ids.length === 0) return [this.model];
|
|
250118
251810
|
const chatIds = ids.filter((id) => isChatModel(id));
|
|
250119
|
-
|
|
251811
|
+
const local = isLocalEndpoint(this.config);
|
|
251812
|
+
return (chatIds.length ? chatIds : ids).map((id) => withResolvedPricing({
|
|
250120
251813
|
id,
|
|
250121
251814
|
name: id,
|
|
250122
251815
|
provider: "openai-compatible",
|
|
@@ -250126,7 +251819,7 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
|
250126
251819
|
outputCostPer1kTokens: 0,
|
|
250127
251820
|
maxOutputTokens: 4e3,
|
|
250128
251821
|
supportsStreaming: true,
|
|
250129
|
-
isLocal:
|
|
251822
|
+
isLocal: local
|
|
250130
251823
|
}));
|
|
250131
251824
|
}
|
|
250132
251825
|
async isAvailable() {
|
|
@@ -250341,7 +252034,7 @@ var ModelSelector = class {
|
|
|
250341
252034
|
else if (this.availableProviders.size === 1) providerStr = Array.from(this.availableProviders)[0];
|
|
250342
252035
|
}
|
|
250343
252036
|
if (providerStr && this.availableProviders.has(providerStr)) {
|
|
250344
|
-
const dynamicModel = {
|
|
252037
|
+
const dynamicModel = withResolvedPricing({
|
|
250345
252038
|
id: actualId,
|
|
250346
252039
|
name: actualId,
|
|
250347
252040
|
provider: providerStr,
|
|
@@ -250352,7 +252045,7 @@ var ModelSelector = class {
|
|
|
250352
252045
|
maxOutputTokens: 8e3,
|
|
250353
252046
|
supportsStreaming: true,
|
|
250354
252047
|
isLocal: providerStr === "ollama"
|
|
250355
|
-
};
|
|
252048
|
+
});
|
|
250356
252049
|
this.addDynamicModel(dynamicModel);
|
|
250357
252050
|
return dynamicModel;
|
|
250358
252051
|
}
|
|
@@ -250744,6 +252437,8 @@ var LiveDataProvider = class {
|
|
|
250744
252437
|
snapshot = null;
|
|
250745
252438
|
prices = /* @__PURE__ */ new Map();
|
|
250746
252439
|
capabilities = /* @__PURE__ */ new Map();
|
|
252440
|
+
/** Dataset-vs-live price mismatches, deduped by `provider:modelId`. */
|
|
252441
|
+
disagreements = /* @__PURE__ */ new Map();
|
|
250747
252442
|
source = "bundled";
|
|
250748
252443
|
fetchedAt = 0;
|
|
250749
252444
|
loaded = false;
|
|
@@ -250897,14 +252592,45 @@ var LiveDataProvider = class {
|
|
|
250897
252592
|
/**
|
|
250898
252593
|
* Returns a price-corrected copy of each model when live pricing is known,
|
|
250899
252594
|
* leaving the original untouched (so the shared catalog is never mutated).
|
|
252595
|
+
*
|
|
252596
|
+
* Reconciliation policy (see reconcilePrice in pricing.ts): the bundled
|
|
252597
|
+
* dataset is the authoritative baseline, and a live quote overrides it
|
|
252598
|
+
* because it is fresher by construction — but the disagreement is RECORDED,
|
|
252599
|
+
* not swallowed. A dataset/live mismatch is the best signal available that
|
|
252600
|
+
* the committed prices have gone stale, so it must be visible rather than
|
|
252601
|
+
* silently resolved in either direction. A live quote of $0 for a non-local
|
|
252602
|
+
* model is rejected outright: that is the very failure mode this change
|
|
252603
|
+
* exists to prevent, and a marketplace's free-tier alias must never zero out
|
|
252604
|
+
* the price of the paid model Cascade is actually calling.
|
|
250900
252605
|
*/
|
|
250901
252606
|
applyLivePricing(models) {
|
|
250902
252607
|
return models.map((m3) => {
|
|
250903
252608
|
const p3 = this.getLivePrice(m3.baseModelId ?? m3.id);
|
|
250904
252609
|
if (!p3) return m3;
|
|
250905
|
-
|
|
252610
|
+
const reconciled = reconcilePrice(m3, p3);
|
|
252611
|
+
if (reconciled.disagreement) this.recordDisagreement(reconciled.disagreement);
|
|
252612
|
+
if (!reconciled.accepted) return m3;
|
|
252613
|
+
return {
|
|
252614
|
+
...m3,
|
|
252615
|
+
inputCostPer1kTokens: reconciled.input,
|
|
252616
|
+
outputCostPer1kTokens: reconciled.output,
|
|
252617
|
+
pricingUnknown: false
|
|
252618
|
+
};
|
|
250906
252619
|
});
|
|
250907
252620
|
}
|
|
252621
|
+
recordDisagreement(d2) {
|
|
252622
|
+
const key = `${d2.provider}:${d2.modelId}`;
|
|
252623
|
+
if (this.disagreements.has(key)) return;
|
|
252624
|
+
this.disagreements.set(key, d2);
|
|
252625
|
+
}
|
|
252626
|
+
/**
|
|
252627
|
+
* Dataset-vs-live price mismatches seen this session, newest-model-first
|
|
252628
|
+
* insertion order. Surfaced by `cascade models --verbose`; a non-empty list
|
|
252629
|
+
* means src/core/router/pricing-data.json is probably due a refresh.
|
|
252630
|
+
*/
|
|
252631
|
+
getPriceDisagreements() {
|
|
252632
|
+
return [...this.disagreements.values()];
|
|
252633
|
+
}
|
|
250908
252634
|
/** Current capability facts for a model id, or null when unknown. */
|
|
250909
252635
|
getCapability(modelId) {
|
|
250910
252636
|
return this.capabilities.get(normalizeModelId2(modelId)) ?? null;
|
|
@@ -251101,7 +252827,9 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
251101
252827
|
tokensByTier: {},
|
|
251102
252828
|
inputTokensByTier: {},
|
|
251103
252829
|
outputTokensByTier: {},
|
|
251104
|
-
costByFeature: {}
|
|
252830
|
+
costByFeature: {},
|
|
252831
|
+
untrackedCostCalls: 0,
|
|
252832
|
+
untrackedCostModels: []
|
|
251105
252833
|
};
|
|
251106
252834
|
tierModels = /* @__PURE__ */ new Map();
|
|
251107
252835
|
/**
|
|
@@ -251451,7 +253179,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
251451
253179
|
`Model ${model.id} inference timed out after ${cloudTimeoutMs}ms`
|
|
251452
253180
|
);
|
|
251453
253181
|
}
|
|
251454
|
-
const
|
|
253182
|
+
const corrected = buildTokenUsage(
|
|
251455
253183
|
result.usage.inputTokens,
|
|
251456
253184
|
result.usage.outputTokens,
|
|
251457
253185
|
model
|
|
@@ -251460,7 +253188,8 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
251460
253188
|
...result,
|
|
251461
253189
|
usage: {
|
|
251462
253190
|
...result.usage,
|
|
251463
|
-
estimatedCostUsd:
|
|
253191
|
+
estimatedCostUsd: corrected.estimatedCostUsd,
|
|
253192
|
+
...corrected.costUnknown ? { costUnknown: true } : { costUnknown: void 0 }
|
|
251464
253193
|
}
|
|
251465
253194
|
};
|
|
251466
253195
|
if (!result || typeof result.content !== "string" || !result.usage) {
|
|
@@ -251647,7 +253376,9 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
251647
253376
|
tokensByTier: { ...this.stats.tokensByTier },
|
|
251648
253377
|
inputTokensByTier: { ...this.stats.inputTokensByTier },
|
|
251649
253378
|
outputTokensByTier: { ...this.stats.outputTokensByTier },
|
|
251650
|
-
costByFeature: { ...this.stats.costByFeature }
|
|
253379
|
+
costByFeature: { ...this.stats.costByFeature },
|
|
253380
|
+
untrackedCostCalls: this.stats.untrackedCostCalls,
|
|
253381
|
+
untrackedCostModels: [...this.stats.untrackedCostModels]
|
|
251651
253382
|
};
|
|
251652
253383
|
}
|
|
251653
253384
|
/**
|
|
@@ -251698,7 +253429,9 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
251698
253429
|
tokensByTier: {},
|
|
251699
253430
|
inputTokensByTier: {},
|
|
251700
253431
|
outputTokensByTier: {},
|
|
251701
|
-
costByFeature: {}
|
|
253432
|
+
costByFeature: {},
|
|
253433
|
+
untrackedCostCalls: 0,
|
|
253434
|
+
untrackedCostModels: []
|
|
251702
253435
|
};
|
|
251703
253436
|
this.sessionCostUsd = 0;
|
|
251704
253437
|
this.budgetState = "ok";
|
|
@@ -251883,6 +253616,18 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter__default.default {
|
|
|
251883
253616
|
if (featureTag) {
|
|
251884
253617
|
this.stats.costByFeature[featureTag] = (this.stats.costByFeature[featureTag] ?? 0) + usage.estimatedCostUsd;
|
|
251885
253618
|
}
|
|
253619
|
+
if (usage.costUnknown) {
|
|
253620
|
+
this.stats.untrackedCostCalls += 1;
|
|
253621
|
+
if (!this.stats.untrackedCostModels.includes(model.id)) {
|
|
253622
|
+
this.stats.untrackedCostModels.push(model.id);
|
|
253623
|
+
const capped = this.config?.budget?.maxCostPerRunUsd != null || this.config?.budget?.sessionBudgetUsd != null;
|
|
253624
|
+
this.emit("cost:untracked", {
|
|
253625
|
+
modelId: model.id,
|
|
253626
|
+
provider: model.provider,
|
|
253627
|
+
reason: capped ? `No published price for ${model.provider}:${model.id}. Its spend is not counted toward your cost budget \u2014 the token cap still applies. Add it to the pricing dataset, or set the provider's \`local: true\` if this endpoint really is free.` : `No published price for ${model.provider}:${model.id}. Cost for this model is reported as "not tracked" rather than $0.00.`
|
|
253628
|
+
});
|
|
253629
|
+
}
|
|
253630
|
+
}
|
|
251886
253631
|
this.runTokens += usage.totalTokens;
|
|
251887
253632
|
this.runCostUsd += usage.estimatedCostUsd;
|
|
251888
253633
|
this.updateBudgetState();
|
|
@@ -252023,6 +253768,14 @@ var BaseTier = class extends EventEmitter__default.default {
|
|
|
252023
253768
|
this.emit("tier:status", event);
|
|
252024
253769
|
}
|
|
252025
253770
|
/** Record the model serving this tier; future status events carry it. */
|
|
253771
|
+
/**
|
|
253772
|
+
* The model actually serving this tier ("provider:id"), once one has been
|
|
253773
|
+
* chosen. The run breaker reads it to attribute a failure to a model rather
|
|
253774
|
+
* than to the subtask that happened to hit it.
|
|
253775
|
+
*/
|
|
253776
|
+
getServingModel() {
|
|
253777
|
+
return this.servingModel;
|
|
253778
|
+
}
|
|
252026
253779
|
setServingModel(model) {
|
|
252027
253780
|
this.servingModel = model || void 0;
|
|
252028
253781
|
}
|
|
@@ -253758,6 +255511,7 @@ var T2Manager = class extends BaseTier {
|
|
|
253758
255511
|
escalations = [];
|
|
253759
255512
|
peerSyncBuffer = [];
|
|
253760
255513
|
store;
|
|
255514
|
+
runBreaker;
|
|
253761
255515
|
t3PeerBus = new PeerBus();
|
|
253762
255516
|
// ← T3↔T3 bus (local to this T2)
|
|
253763
255517
|
t2PeerBus;
|
|
@@ -253788,6 +255542,15 @@ var T2Manager = class extends BaseTier {
|
|
|
253788
255542
|
this.router = router;
|
|
253789
255543
|
this.toolRegistry = toolRegistry;
|
|
253790
255544
|
}
|
|
255545
|
+
/**
|
|
255546
|
+
* Share the run-wide circuit breaker. Every T2 in a run gets the SAME
|
|
255547
|
+
* instance: three sections each failing once against a dead model is the
|
|
255548
|
+
* same fact as one section failing three times, and a per-section breaker
|
|
255549
|
+
* would never see it.
|
|
255550
|
+
*/
|
|
255551
|
+
setRunBreaker(breaker) {
|
|
255552
|
+
this.runBreaker = breaker;
|
|
255553
|
+
}
|
|
253791
255554
|
setStore(store) {
|
|
253792
255555
|
this.store = store;
|
|
253793
255556
|
}
|
|
@@ -253911,7 +255674,8 @@ Guidance (must be followed): ${decision.note}`
|
|
|
253911
255674
|
const overallStatus = this.determineStatus(t3Results);
|
|
253912
255675
|
const isOk = overallStatus === "COMPLETED" || overallStatus === "PARTIAL";
|
|
253913
255676
|
this.setStatus(isOk ? "COMPLETED" : "FAILED", summary);
|
|
253914
|
-
|
|
255677
|
+
const sectionAction = overallStatus === "COMPLETED" ? "Section complete" : overallStatus === "PARTIAL" ? "Section partially complete \u2014 some subtasks failed" : overallStatus === "ESCALATED" ? "Section escalated \u2014 needs a decision" : "Section failed \u2014 no subtask completed";
|
|
255678
|
+
this.sendStatusUpdate({ progressPct: 100, currentAction: sectionAction, status: "IN_PROGRESS", output: summary });
|
|
253915
255679
|
const result = {
|
|
253916
255680
|
sectionId: assignment.sectionId,
|
|
253917
255681
|
sectionTitle: assignment.sectionTitle,
|
|
@@ -254081,6 +255845,24 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
|
254081
255845
|
const reinforceCfg = this.router.getReinforcementsConfig?.() ?? { enabled: false, maxPerSection: 4 };
|
|
254082
255846
|
let reinforcementsAdded = 0;
|
|
254083
255847
|
while (remaining.size > 0) {
|
|
255848
|
+
if (this.runBreaker?.isOpen()) {
|
|
255849
|
+
const why = this.runBreaker.skipMessage();
|
|
255850
|
+
this.log(`Run breaker open \u2014 skipping ${remaining.size} remaining subtask(s)`);
|
|
255851
|
+
for (const id of remaining) {
|
|
255852
|
+
this.t3PeerBus.publish(this.id, id, why, "FAILED");
|
|
255853
|
+
resultMap.set(id, {
|
|
255854
|
+
subtaskId: id,
|
|
255855
|
+
status: "FAILED",
|
|
255856
|
+
output: why,
|
|
255857
|
+
testResults: { checksRun: [], passed: [], failed: [] },
|
|
255858
|
+
issues: [why],
|
|
255859
|
+
peerSyncsUsed: [],
|
|
255860
|
+
correctionAttempts: 0
|
|
255861
|
+
});
|
|
255862
|
+
}
|
|
255863
|
+
remaining.clear();
|
|
255864
|
+
break;
|
|
255865
|
+
}
|
|
254084
255866
|
const runnableIds = [...remaining].filter((id) => (inDegree.get(id) ?? 0) === 0);
|
|
254085
255867
|
if (runnableIds.length === 0) {
|
|
254086
255868
|
const fallbackId = [...remaining].sort(
|
|
@@ -254183,8 +255965,32 @@ HIERARCHY CONTEXT: ${this.hierarchyContext}` : ""),
|
|
|
254183
255965
|
remaining.delete(id);
|
|
254184
255966
|
const r4 = waveResults[i4];
|
|
254185
255967
|
if (r4.status === "rejected") {
|
|
254186
|
-
this.log(`T3 worker ${id} failed: ${r4.reason instanceof Error ? r4.reason.message : String(r4.reason)} \u2014 retrying once`);
|
|
254187
255968
|
const assignment = sanitizedAssignments.find((a2) => a2.subtaskId === id);
|
|
255969
|
+
const failedModel = workerMap.get(id)?.getServingModel();
|
|
255970
|
+
const tripped = this.runBreaker?.record(r4.reason, failedModel);
|
|
255971
|
+
if (tripped) {
|
|
255972
|
+
this.log(`Run breaker opened: ${tripped.failures} consecutive ${tripped.kind} failures on ${tripped.modelId} \u2014 stopping`);
|
|
255973
|
+
this.emit("run:breaker", tripped);
|
|
255974
|
+
}
|
|
255975
|
+
if (this.runBreaker?.isOpen()) {
|
|
255976
|
+
const why = this.runBreaker.skipMessage();
|
|
255977
|
+
this.log(`T3 worker ${id} failed and the run breaker is open \u2014 not retrying`);
|
|
255978
|
+
this.t3PeerBus.publish(this.id, id, why, "FAILED");
|
|
255979
|
+
resultMap.set(id, {
|
|
255980
|
+
subtaskId: id,
|
|
255981
|
+
status: "FAILED",
|
|
255982
|
+
output: why,
|
|
255983
|
+
testResults: { checksRun: [], passed: [], failed: [] },
|
|
255984
|
+
issues: [why],
|
|
255985
|
+
peerSyncsUsed: [],
|
|
255986
|
+
correctionAttempts: 0
|
|
255987
|
+
});
|
|
255988
|
+
for (const dependent of adj.get(id) ?? []) {
|
|
255989
|
+
inDegree.set(dependent, Math.max(0, (inDegree.get(dependent) ?? 0) - 1));
|
|
255990
|
+
}
|
|
255991
|
+
continue;
|
|
255992
|
+
}
|
|
255993
|
+
this.log(`T3 worker ${id} failed: ${r4.reason instanceof Error ? r4.reason.message : String(r4.reason)} \u2014 retrying once`);
|
|
254188
255994
|
try {
|
|
254189
255995
|
const retried = await this.retryT3(assignment, taskId);
|
|
254190
255996
|
resultMap.set(id, retried);
|
|
@@ -254516,6 +256322,7 @@ var T1Administrator = class extends BaseTier {
|
|
|
254516
256322
|
t2Managers = /* @__PURE__ */ new Map();
|
|
254517
256323
|
escalations = [];
|
|
254518
256324
|
store;
|
|
256325
|
+
runBreaker;
|
|
254519
256326
|
t2PeerBus = new PeerBus();
|
|
254520
256327
|
permissionEscalator;
|
|
254521
256328
|
toolCreator;
|
|
@@ -254530,6 +256337,10 @@ var T1Administrator = class extends BaseTier {
|
|
|
254530
256337
|
this.toolRegistry = toolRegistry;
|
|
254531
256338
|
this.config = config2;
|
|
254532
256339
|
}
|
|
256340
|
+
/** Share the run-wide circuit breaker with every section manager. */
|
|
256341
|
+
setRunBreaker(breaker) {
|
|
256342
|
+
this.runBreaker = breaker;
|
|
256343
|
+
}
|
|
254533
256344
|
setStore(store) {
|
|
254534
256345
|
this.store = store;
|
|
254535
256346
|
}
|
|
@@ -254892,6 +256703,7 @@ SPEC RULES \u2014 each subtask is a self-contained spec slice (workers execute f
|
|
|
254892
256703
|
};
|
|
254893
256704
|
const managers = sections.map((section) => {
|
|
254894
256705
|
const manager = new T2Manager(this.router, this.toolRegistry, this.id);
|
|
256706
|
+
if (this.runBreaker) manager.setRunBreaker(this.runBreaker);
|
|
254895
256707
|
manager.setHierarchyContext(`You are a T2 Manager for the section "${section.sectionTitle}". You are part of a COMPLEX task overseen by T1 Administrator.`);
|
|
254896
256708
|
if (this.store) {
|
|
254897
256709
|
manager.setStore(this.store);
|
|
@@ -255177,6 +256989,158 @@ Reply with exactly one word: YES, NO, or UNSURE.
|
|
|
255177
256989
|
}
|
|
255178
256990
|
};
|
|
255179
256991
|
|
|
256992
|
+
// src/core/router/provider-errors.ts
|
|
256993
|
+
var SYSTEMIC = /* @__PURE__ */ new Set([
|
|
256994
|
+
"rate_limit",
|
|
256995
|
+
"quota_exhausted",
|
|
256996
|
+
"auth",
|
|
256997
|
+
"model_unavailable"
|
|
256998
|
+
]);
|
|
256999
|
+
function isSystemicKind(kind2) {
|
|
257000
|
+
return SYSTEMIC.has(kind2);
|
|
257001
|
+
}
|
|
257002
|
+
function statusOf(err) {
|
|
257003
|
+
if (!err || typeof err !== "object") return void 0;
|
|
257004
|
+
const e3 = err;
|
|
257005
|
+
for (const key of ["status", "statusCode", "code"]) {
|
|
257006
|
+
const v6 = e3[key];
|
|
257007
|
+
if (typeof v6 === "number" && v6 >= 100 && v6 < 600) return v6;
|
|
257008
|
+
}
|
|
257009
|
+
const resp = e3["response"];
|
|
257010
|
+
if (resp && typeof resp["status"] === "number") return resp["status"];
|
|
257011
|
+
const inner = e3["error"];
|
|
257012
|
+
if (inner && typeof inner["code"] === "number") return inner["code"];
|
|
257013
|
+
return void 0;
|
|
257014
|
+
}
|
|
257015
|
+
function messageOf(err) {
|
|
257016
|
+
if (err instanceof Error) return err.message;
|
|
257017
|
+
if (typeof err === "string") return err;
|
|
257018
|
+
if (err && typeof err === "object") {
|
|
257019
|
+
const e3 = err;
|
|
257020
|
+
if (typeof e3["message"] === "string") return e3["message"];
|
|
257021
|
+
const inner = e3["error"];
|
|
257022
|
+
if (inner && typeof inner["message"] === "string") return inner["message"];
|
|
257023
|
+
try {
|
|
257024
|
+
return JSON.stringify(err);
|
|
257025
|
+
} catch {
|
|
257026
|
+
}
|
|
257027
|
+
}
|
|
257028
|
+
return String(err);
|
|
257029
|
+
}
|
|
257030
|
+
function classifyProviderError(err) {
|
|
257031
|
+
const raw = messageOf(err).trim();
|
|
257032
|
+
const status = statusOf(err);
|
|
257033
|
+
const m3 = raw.toLowerCase();
|
|
257034
|
+
const kind2 = (() => {
|
|
257035
|
+
if (status === 429) {
|
|
257036
|
+
return /quota|billing|credit|exceeded your current quota|insufficient/.test(m3) ? "quota_exhausted" : "rate_limit";
|
|
257037
|
+
}
|
|
257038
|
+
if (status === 401 || status === 403) return "auth";
|
|
257039
|
+
if (status === 404) return "model_unavailable";
|
|
257040
|
+
if (/rate limit|too many requests|resource_exhausted/.test(m3)) {
|
|
257041
|
+
return /quota|billing|credit|insufficient/.test(m3) ? "quota_exhausted" : "rate_limit";
|
|
257042
|
+
}
|
|
257043
|
+
if (/quota|billing|insufficient_quota|insufficient credit|payment required/.test(m3)) return "quota_exhausted";
|
|
257044
|
+
if (/api key|unauthorized|authentication|permission denied|invalid[_ ]api/.test(m3)) return "auth";
|
|
257045
|
+
if (/model .*(not found|does not exist|unavailable)|no such model|unknown model|not supported for/.test(m3)) {
|
|
257046
|
+
return "model_unavailable";
|
|
257047
|
+
}
|
|
257048
|
+
if (/context length|too many tokens|maximum context|prompt is too long|input too long/.test(m3)) return "context_length";
|
|
257049
|
+
if (/safety|content filter|blocked|recitation|prohibited/.test(m3)) return "content_filter";
|
|
257050
|
+
if (/econnreset|etimedout|enotfound|socket hang up|network|fetch failed|aborted/.test(m3)) return "network";
|
|
257051
|
+
return "unknown";
|
|
257052
|
+
})();
|
|
257053
|
+
return { kind: kind2, systemic: isSystemicKind(kind2), status, raw };
|
|
257054
|
+
}
|
|
257055
|
+
function describeProviderError(c4, modelId) {
|
|
257056
|
+
const on = ` on ${modelId}` ;
|
|
257057
|
+
const detail = c4.raw ? ` Provider said: ${c4.raw}` : "";
|
|
257058
|
+
switch (c4.kind) {
|
|
257059
|
+
case "rate_limit":
|
|
257060
|
+
return `Rate limit hit${on}. The provider is throttling requests \u2014 lower the number of parallel workers, or use a model with a higher requests-per-minute allowance.${detail}`;
|
|
257061
|
+
case "quota_exhausted":
|
|
257062
|
+
return `Quota or billing limit reached${on}. This will not recover on its own \u2014 check the provider's billing page, or switch this tier to a different provider.${detail}`;
|
|
257063
|
+
case "auth":
|
|
257064
|
+
return `Authentication failed${on}. The API key is missing, expired, or lacks access to this model \u2014 re-check the key in Settings > Providers.${detail}`;
|
|
257065
|
+
case "model_unavailable":
|
|
257066
|
+
return `Model unavailable${on}. The id may be wrong, retired, or not enabled for this API key \u2014 pick a different model for this tier.${detail}`;
|
|
257067
|
+
case "context_length":
|
|
257068
|
+
return `The prompt was too long${on}. Reduce the attached context, or use a model with a larger context window for this tier.${detail}`;
|
|
257069
|
+
case "content_filter":
|
|
257070
|
+
return `The provider's safety filter refused this request${on}.${detail}`;
|
|
257071
|
+
case "network":
|
|
257072
|
+
return `Network error reaching the provider${on}. This is usually transient.${detail}`;
|
|
257073
|
+
default:
|
|
257074
|
+
return `The model call failed${on}.${detail}`;
|
|
257075
|
+
}
|
|
257076
|
+
}
|
|
257077
|
+
|
|
257078
|
+
// src/core/run-breaker.ts
|
|
257079
|
+
var DEFAULT_FAILURE_THRESHOLD = 3;
|
|
257080
|
+
var RunBreaker = class {
|
|
257081
|
+
threshold;
|
|
257082
|
+
/** modelId → consecutive systemic failures of the SAME kind. */
|
|
257083
|
+
counts = /* @__PURE__ */ new Map();
|
|
257084
|
+
trip = null;
|
|
257085
|
+
constructor(threshold = DEFAULT_FAILURE_THRESHOLD) {
|
|
257086
|
+
this.threshold = Math.max(1, threshold);
|
|
257087
|
+
}
|
|
257088
|
+
/**
|
|
257089
|
+
* Record a failed model call. Returns the trip if this failure is the one
|
|
257090
|
+
* that opened the breaker, otherwise null.
|
|
257091
|
+
*
|
|
257092
|
+
* A non-systemic failure RESETS the model's counter: it is evidence the model
|
|
257093
|
+
* is reachable and answering, which is exactly what a systemic streak claims
|
|
257094
|
+
* it is not.
|
|
257095
|
+
*/
|
|
257096
|
+
record(err, modelId) {
|
|
257097
|
+
if (this.trip) return null;
|
|
257098
|
+
const id = modelId?.trim() || "unknown-model";
|
|
257099
|
+
const c4 = classifyProviderError(err);
|
|
257100
|
+
if (!c4.systemic) {
|
|
257101
|
+
this.counts.delete(id);
|
|
257102
|
+
return null;
|
|
257103
|
+
}
|
|
257104
|
+
const prev = this.counts.get(id);
|
|
257105
|
+
const n8 = prev && prev.kind === c4.kind ? prev.n + 1 : 1;
|
|
257106
|
+
this.counts.set(id, { kind: c4.kind, n: n8, last: c4 });
|
|
257107
|
+
if (n8 >= this.threshold) {
|
|
257108
|
+
this.trip = {
|
|
257109
|
+
modelId: id,
|
|
257110
|
+
kind: c4.kind,
|
|
257111
|
+
failures: n8,
|
|
257112
|
+
message: describeProviderError(c4, id)
|
|
257113
|
+
};
|
|
257114
|
+
return this.trip;
|
|
257115
|
+
}
|
|
257116
|
+
return null;
|
|
257117
|
+
}
|
|
257118
|
+
/** True once the run should stop launching work that would fail identically. */
|
|
257119
|
+
isOpen() {
|
|
257120
|
+
return this.trip !== null;
|
|
257121
|
+
}
|
|
257122
|
+
/** Why the breaker opened, or null while it is closed. */
|
|
257123
|
+
reason() {
|
|
257124
|
+
return this.trip;
|
|
257125
|
+
}
|
|
257126
|
+
/**
|
|
257127
|
+
* One line for a worker/section that never ran because the breaker was
|
|
257128
|
+
* already open. Says the work was skipped deliberately — not that it failed
|
|
257129
|
+
* on its own merits, which is what an empty FAILED status would imply.
|
|
257130
|
+
*/
|
|
257131
|
+
skipMessage() {
|
|
257132
|
+
const t4 = this.trip;
|
|
257133
|
+
if (!t4) return "Skipped.";
|
|
257134
|
+
return `Skipped \u2014 the run stopped after ${t4.failures} consecutive failures on ${t4.modelId}. ${t4.message}`;
|
|
257135
|
+
}
|
|
257136
|
+
/** Test/diagnostic view of the per-model streaks. */
|
|
257137
|
+
streaks() {
|
|
257138
|
+
const out = {};
|
|
257139
|
+
for (const [k4, v6] of this.counts) out[k4] = { kind: v6.kind, n: v6.n };
|
|
257140
|
+
return out;
|
|
257141
|
+
}
|
|
257142
|
+
};
|
|
257143
|
+
|
|
255180
257144
|
// src/tools/registry.ts
|
|
255181
257145
|
var import_ignore = __toESM(require_ignore(), 1);
|
|
255182
257146
|
|
|
@@ -297684,7 +299648,18 @@ var ProviderConfigSchema = external_exports.object({
|
|
|
297684
299648
|
apiVersion: external_exports.string().optional(),
|
|
297685
299649
|
model: external_exports.string().optional(),
|
|
297686
299650
|
authToken: external_exports.string().optional(),
|
|
297687
|
-
credentialSource: external_exports.string().optional()
|
|
299651
|
+
credentialSource: external_exports.string().optional(),
|
|
299652
|
+
/**
|
|
299653
|
+
* "This endpoint is self-hosted, so inference genuinely costs $0."
|
|
299654
|
+
* Only meaningful for `ollama` and `openai-compatible`. Unset ⇒ inferred:
|
|
299655
|
+
* ollama is local, openai-compatible is local when its baseUrl is
|
|
299656
|
+
* loopback/LAN. Set it explicitly to override — e.g. `false` for an Ollama
|
|
299657
|
+
* instance you rent, `true` for a llama.cpp box on your own LAN reached by
|
|
299658
|
+
* hostname.
|
|
299659
|
+
*/
|
|
299660
|
+
local: external_exports.boolean().optional(),
|
|
299661
|
+
/** Region for providers whose price varies by region (Azure: global | us | eu | …). */
|
|
299662
|
+
region: external_exports.string().optional()
|
|
297688
299663
|
});
|
|
297689
299664
|
var ModelOverridesSchema = external_exports.object({
|
|
297690
299665
|
t1: external_exports.string().optional(),
|
|
@@ -298270,8 +300245,8 @@ var TaskAnalyzer = class {
|
|
|
298270
300245
|
}
|
|
298271
300246
|
costEfficiency(model, complexity) {
|
|
298272
300247
|
if (this.tracker) return this.tracker.costEfficiencyScore(model, complexity);
|
|
298273
|
-
const blended = model
|
|
298274
|
-
const normalised = Math.min(1, blended /
|
|
300248
|
+
const blended = blendedCostPer1k(model);
|
|
300249
|
+
const normalised = Math.min(1, blended / BLENDED_COST_CEILING);
|
|
298275
300250
|
const complexityWeight = (6 - complexity) / 5;
|
|
298276
300251
|
return Math.max(0.1, 1 - normalised * complexityWeight);
|
|
298277
300252
|
}
|
|
@@ -298406,8 +300381,8 @@ var ModelPerformanceTracker = class {
|
|
|
298406
300381
|
* normalised over $0.05 blended as the "expensive" ceiling.
|
|
298407
300382
|
*/
|
|
298408
300383
|
costEfficiencyScore(model, complexity) {
|
|
298409
|
-
const blended = model
|
|
298410
|
-
const normalised = Math.min(1, blended /
|
|
300384
|
+
const blended = blendedCostPer1k(model);
|
|
300385
|
+
const normalised = Math.min(1, blended / BLENDED_COST_CEILING);
|
|
298411
300386
|
const complexityWeight = (6 - complexity) / 5;
|
|
298412
300387
|
return Math.max(0.1, 1 - normalised * complexityWeight);
|
|
298413
300388
|
}
|
|
@@ -301042,6 +303017,7 @@ ${prompt}` : prompt;
|
|
|
301042
303017
|
if (toolCreator) toolCreator.setPermissionEscalator(escalator);
|
|
301043
303018
|
const rootPrompt = buildContextualPrompt(options.prompt, options.conversationHistory);
|
|
301044
303019
|
let finalOutput = "";
|
|
303020
|
+
const runBreaker = new RunBreaker();
|
|
301045
303021
|
let t2Results = [];
|
|
301046
303022
|
let runError = null;
|
|
301047
303023
|
let identityPrompt = "";
|
|
@@ -301110,6 +303086,7 @@ ${prompt}` : prompt;
|
|
|
301110
303086
|
this.emit("tier:status", { tierId: "t3-root", status: "COMPLETED", role: "T3" });
|
|
301111
303087
|
} else if (complexity === "Moderate") {
|
|
301112
303088
|
const t22 = new T2Manager(this.router, this.toolRegistry, "root");
|
|
303089
|
+
t22.setRunBreaker(runBreaker);
|
|
301113
303090
|
t22.setPresenter(true);
|
|
301114
303091
|
t22.setHierarchyContext("You are the ROOT Manager for this task. There is no T1 Administrator involved in this run. You are responsible for decomposing the task and managing T3 workers directly.");
|
|
301115
303092
|
if (identityPrompt) {
|
|
@@ -301170,6 +303147,7 @@ _(incomplete: ${reasons.join("; ")})_` : partial2;
|
|
|
301170
303147
|
}
|
|
301171
303148
|
} else {
|
|
301172
303149
|
const t1 = new T1Administrator(this.router, this.toolRegistry, this.config);
|
|
303150
|
+
t1.setRunBreaker(runBreaker);
|
|
301173
303151
|
t1.setPresenter(true);
|
|
301174
303152
|
t1.setHierarchyContext("You are the top-level Administrator. You are responsible for the overall plan and supervising multiple T2 Managers.");
|
|
301175
303153
|
if (identityPrompt) {
|
|
@@ -301194,6 +303172,20 @@ _(incomplete: ${reasons.join("; ")})_` : partial2;
|
|
|
301194
303172
|
finalOutput = result.output;
|
|
301195
303173
|
t2Results = result.t2Results;
|
|
301196
303174
|
}
|
|
303175
|
+
const trip = runBreaker.reason();
|
|
303176
|
+
if (trip) {
|
|
303177
|
+
finalOutput = [
|
|
303178
|
+
`\u26A0 **Run stopped early \u2014 ${trip.modelId} was failing every request.**`,
|
|
303179
|
+
"",
|
|
303180
|
+
trip.message,
|
|
303181
|
+
"",
|
|
303182
|
+
`Cascade stopped after ${trip.failures} consecutive failures rather than retrying every remaining subtask against the same model, which would have cost more and produced the same result.`,
|
|
303183
|
+
finalOutput ? `
|
|
303184
|
+
---
|
|
303185
|
+
|
|
303186
|
+
${finalOutput}` : ""
|
|
303187
|
+
].join("\n").trimEnd();
|
|
303188
|
+
}
|
|
301197
303189
|
} catch (err) {
|
|
301198
303190
|
if (err instanceof CascadeCancelledError || err instanceof Error && err.name === "AbortError" || options.signal?.aborted) {
|
|
301199
303191
|
this.emit("run:cancelled", {
|
|
@@ -301260,7 +303252,11 @@ _(incomplete: ${reasons.join("; ")})_` : partial2;
|
|
|
301260
303252
|
inputTokens: 0,
|
|
301261
303253
|
outputTokens: 0,
|
|
301262
303254
|
totalTokens: stats.totalTokens,
|
|
301263
|
-
estimatedCostUsd: stats.totalCostUsd
|
|
303255
|
+
estimatedCostUsd: stats.totalCostUsd,
|
|
303256
|
+
// At least one call ran on a model with no known price, so its spend is
|
|
303257
|
+
// missing from the total above. Say so rather than letting the caller
|
|
303258
|
+
// present an undercount as the final figure.
|
|
303259
|
+
...stats.untrackedCostCalls > 0 ? { costUnknown: true } : {}
|
|
301264
303260
|
},
|
|
301265
303261
|
t2Results,
|
|
301266
303262
|
durationMs,
|
|
@@ -301330,7 +303326,8 @@ _(incomplete: ${reasons.join("; ")})_` : partial2;
|
|
|
301330
303326
|
inputTokens: 0,
|
|
301331
303327
|
outputTokens: 0,
|
|
301332
303328
|
totalTokens: stats2.totalTokens,
|
|
301333
|
-
estimatedCostUsd: stats2.totalCostUsd
|
|
303329
|
+
estimatedCostUsd: stats2.totalCostUsd,
|
|
303330
|
+
...stats2.untrackedCostCalls > 0 ? { costUnknown: true } : {}
|
|
301334
303331
|
},
|
|
301335
303332
|
t2Results: [],
|
|
301336
303333
|
durationMs: Date.now() - startMs,
|
|
@@ -301354,7 +303351,8 @@ _(incomplete: ${reasons.join("; ")})_` : partial2;
|
|
|
301354
303351
|
inputTokens: result.usage?.inputTokens ?? 0,
|
|
301355
303352
|
outputTokens: result.usage?.outputTokens ?? 0,
|
|
301356
303353
|
totalTokens: stats.totalTokens,
|
|
301357
|
-
estimatedCostUsd: stats.totalCostUsd
|
|
303354
|
+
estimatedCostUsd: stats.totalCostUsd,
|
|
303355
|
+
...stats.untrackedCostCalls > 0 ? { costUnknown: true } : {}
|
|
301358
303356
|
},
|
|
301359
303357
|
t2Results: [],
|
|
301360
303358
|
durationMs: Date.now() - startMs,
|
|
@@ -303922,7 +305920,10 @@ var DashboardServer = class {
|
|
|
303922
305920
|
this.socket.broadcast("cost:update", {
|
|
303923
305921
|
sessionId,
|
|
303924
305922
|
totalTokens: result.usage.totalTokens,
|
|
303925
|
-
totalCostUsd: result.usage.estimatedCostUsd
|
|
305923
|
+
totalCostUsd: result.usage.estimatedCostUsd,
|
|
305924
|
+
// True when a model with no known price was used: the total above is
|
|
305925
|
+
// an undercount, and the UI must not present it as the full spend.
|
|
305926
|
+
costUnknown: result.usage.costUnknown === true
|
|
303926
305927
|
});
|
|
303927
305928
|
this.throttledBroadcast("workspace");
|
|
303928
305929
|
} catch (err) {
|
|
@@ -304235,7 +306236,8 @@ var DashboardServer = class {
|
|
|
304235
306236
|
this.socket.broadcast("cost:update", {
|
|
304236
306237
|
sessionId,
|
|
304237
306238
|
totalTokens: result.usage.totalTokens,
|
|
304238
|
-
totalCostUsd: result.usage.estimatedCostUsd
|
|
306239
|
+
totalCostUsd: result.usage.estimatedCostUsd,
|
|
306240
|
+
costUnknown: result.usage.costUnknown === true
|
|
304239
306241
|
});
|
|
304240
306242
|
this.throttledBroadcast("workspace");
|
|
304241
306243
|
} catch (err) {
|
|
@@ -304777,7 +306779,8 @@ ${prompt}`;
|
|
|
304777
306779
|
this.socket.broadcast("cost:update", {
|
|
304778
306780
|
sessionId,
|
|
304779
306781
|
totalTokens: result.usage.totalTokens,
|
|
304780
|
-
totalCostUsd: result.usage.estimatedCostUsd
|
|
306782
|
+
totalCostUsd: result.usage.estimatedCostUsd,
|
|
306783
|
+
costUnknown: result.usage.costUnknown === true
|
|
304781
306784
|
});
|
|
304782
306785
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
304783
306786
|
this.throttledBroadcast("workspace");
|