@@ -25,7 +25,14 @@ export const ModelInfoView = ({
2525} : ModelInfoViewProps ) => {
2626 const { t } = useAppTranslation ( )
2727
28- const infoItems = [
28+ // Show tiered pricing table for OpenAI Native when model supports non-standard tiers
29+ const allowedTiers =
30+ ( modelInfo ?. allowedServiceTiers || [ ] ) . filter ( ( tier ) => tier === "flex" || tier === "priority" ) ?? [ ]
31+ const tierPricing = modelInfo ?. serviceTierPricing
32+ const shouldShowTierPricingTable = apiProvider === "openai-native" && allowedTiers . length > 0 && ! ! tierPricing
33+ const fmt = ( n ?: number ) => ( typeof n === "number" ? `${ formatPrice ( n ) } ` : "—" )
34+
35+ const baseInfoItems = [
2936 typeof modelInfo ?. contextWindow === "number" && modelInfo . contextWindow > 0 && (
3037 < >
3138 < span className = "font-medium" > { t ( "settings:modelInfo.contextWindow" ) } </ span > { " " }
@@ -53,6 +60,21 @@ export const ModelInfoView = ({
5360 supportsLabel = { t ( "settings:modelInfo.supportsPromptCache" ) }
5461 doesNotSupportLabel = { t ( "settings:modelInfo.noPromptCache" ) }
5562 /> ,
63+ apiProvider === "gemini" && (
64+ < span className = "italic" >
65+ { selectedModelId . includes ( "pro-preview" )
66+ ? t ( "settings:modelInfo.gemini.billingEstimate" )
67+ : t ( "settings:modelInfo.gemini.freeRequests" , {
68+ count : selectedModelId && selectedModelId . includes ( "flash" ) ? 15 : 2 ,
69+ } ) } { " " }
70+ < VSCodeLink href = "https://ai.google.dev/pricing" className = "text-sm" >
71+ { t ( "settings:modelInfo.gemini.pricingDetails" ) }
72+ </ VSCodeLink >
73+ </ span >
74+ ) ,
75+ ] . filter ( Boolean )
76+
77+ const priceInfoItems = [
5678 modelInfo ?. inputPrice !== undefined && modelInfo . inputPrice > 0 && (
5779 < >
5880 < span className = "font-medium" > { t ( "settings:modelInfo.inputPrice" ) } :</ span > { " " }
@@ -77,20 +99,10 @@ export const ModelInfoView = ({
7799 { formatPrice ( modelInfo . cacheWritesPrice || 0 ) } / 1M tokens
78100 </ >
79101 ) ,
80- apiProvider === "gemini" && (
81- < span className = "italic" >
82- { selectedModelId . includes ( "pro-preview" )
83- ? t ( "settings:modelInfo.gemini.billingEstimate" )
84- : t ( "settings:modelInfo.gemini.freeRequests" , {
85- count : selectedModelId && selectedModelId . includes ( "flash" ) ? 15 : 2 ,
86- } ) } { " " }
87- < VSCodeLink href = "https://ai.google.dev/pricing" className = "text-sm" >
88- { t ( "settings:modelInfo.gemini.pricingDetails" ) }
89- </ VSCodeLink >
90- </ span >
91- ) ,
92102 ] . filter ( Boolean )
93103
104+ const infoItems = shouldShowTierPricingTable ? baseInfoItems : [ ...baseInfoItems , ...priceInfoItems ]
105+
94106 return (
95107 < >
96108 { modelInfo ?. description && (
@@ -106,6 +118,62 @@ export const ModelInfoView = ({
106118 < div key = { index } > { item } </ div >
107119 ) ) }
108120 </ div >
121+
122+ { shouldShowTierPricingTable && (
123+ < div className = "mt-2" >
124+ < div className = "text-xs text-vscode-descriptionForeground mb-1" >
125+ Pricing by service tier (price per 1M tokens)
126+ </ div >
127+ < div className = "border border-vscode-dropdown-border rounded-xs overflow-hidden" >
128+ < table className = "w-full text-sm" >
129+ < thead className = "bg-vscode-dropdown-background" >
130+ < tr >
131+ < th className = "text-left px-3 py-1.5" > Tier</ th >
132+ < th className = "text-right px-3 py-1.5" > Input</ th >
133+ < th className = "text-right px-3 py-1.5" > Output</ th >
134+ < th className = "text-right px-3 py-1.5" > Cache reads</ th >
135+ </ tr >
136+ </ thead >
137+ < tbody >
138+ < tr className = "border-t border-vscode-dropdown-border/60" >
139+ < td className = "px-3 py-1.5" > Standard</ td >
140+ < td className = "px-3 py-1.5 text-right" > { fmt ( modelInfo ?. inputPrice ) } </ td >
141+ < td className = "px-3 py-1.5 text-right" > { fmt ( modelInfo ?. outputPrice ) } </ td >
142+ < td className = "px-3 py-1.5 text-right" > { fmt ( modelInfo ?. cacheReadsPrice ) } </ td >
143+ </ tr >
144+ { allowedTiers . includes ( "flex" ) && (
145+ < tr className = "border-t border-vscode-dropdown-border/60" >
146+ < td className = "px-3 py-1.5" > Flex</ td >
147+ < td className = "px-3 py-1.5 text-right" >
148+ { fmt ( tierPricing ?. flex ?. inputPrice ?? modelInfo ?. inputPrice ) }
149+ </ td >
150+ < td className = "px-3 py-1.5 text-right" >
151+ { fmt ( tierPricing ?. flex ?. outputPrice ?? modelInfo ?. outputPrice ) }
152+ </ td >
153+ < td className = "px-3 py-1.5 text-right" >
154+ { fmt ( tierPricing ?. flex ?. cacheReadsPrice ?? modelInfo ?. cacheReadsPrice ) }
155+ </ td >
156+ </ tr >
157+ ) }
158+ { allowedTiers . includes ( "priority" ) && (
159+ < tr className = "border-t border-vscode-dropdown-border/60" >
160+ < td className = "px-3 py-1.5" > Priority</ td >
161+ < td className = "px-3 py-1.5 text-right" >
162+ { fmt ( tierPricing ?. priority ?. inputPrice ?? modelInfo ?. inputPrice ) }
163+ </ td >
164+ < td className = "px-3 py-1.5 text-right" >
165+ { fmt ( tierPricing ?. priority ?. outputPrice ?? modelInfo ?. outputPrice ) }
166+ </ td >
167+ < td className = "px-3 py-1.5 text-right" >
168+ { fmt ( tierPricing ?. priority ?. cacheReadsPrice ?? modelInfo ?. cacheReadsPrice ) }
169+ </ td >
170+ </ tr >
171+ ) }
172+ </ tbody >
173+ </ table >
174+ </ div >
175+ </ div >
176+ ) }
109177 </ >
110178 )
111179}
0 commit comments