@@ -51,6 +51,7 @@ type GatewayHandler struct {
5151 maxAccountSwitchesGemini int
5252 cfg * config.Config
5353 settingService * service.SettingService
54+ pricingService * service.PricingService
5455}
5556
5657// NewGatewayHandler creates a new GatewayHandler
@@ -68,6 +69,7 @@ func NewGatewayHandler(
6869 userMsgQueueService * service.UserMessageQueueService ,
6970 cfg * config.Config ,
7071 settingService * service.SettingService ,
72+ pricingService * service.PricingService ,
7173) * GatewayHandler {
7274 pingInterval := time .Duration (0 )
7375 maxAccountSwitches := 10
@@ -104,6 +106,7 @@ func NewGatewayHandler(
104106 maxAccountSwitchesGemini : maxAccountSwitchesGemini ,
105107 cfg : cfg ,
106108 settingService : settingService ,
109+ pricingService : pricingService ,
107110 }
108111}
109112
@@ -869,38 +872,125 @@ func (h *GatewayHandler) Models(c *gin.Context) {
869872 availableModels := h .gatewayService .GetAvailableModels (c .Request .Context (), groupID , "" )
870873
871874 if len (availableModels ) > 0 {
872- // Build model list from whitelist
873- models := make ([]claude.Model , 0 , len (availableModels ))
874- for _ , modelID := range availableModels {
875- models = append (models , claude.Model {
876- ID : modelID ,
877- Type : "model" ,
878- DisplayName : modelID ,
879- CreatedAt : "2024-01-01T00:00:00Z" ,
880- })
881- }
882- c .JSON (http .StatusOK , gin.H {
883- "object" : "list" ,
884- "data" : models ,
885- })
875+ h .writeModelsResponse (c , availableModels )
886876 return
887877 }
888878
889879 // Fallback to default models
890880 if platform == "openai" {
891- c .JSON (http .StatusOK , gin.H {
892- "object" : "list" ,
893- "data" : openai .DefaultModels ,
894- })
881+ h .writeDefaultOpenAIModelsResponse (c )
895882 return
896883 }
897884
885+ h .writeDefaultClaudeModelsResponse (c )
886+ }
887+
888+ type modelPricingResponse struct {
889+ InputCostPerToken * float64 `json:"input_cost_per_token,omitempty"`
890+ OutputCostPerToken * float64 `json:"output_cost_per_token,omitempty"`
891+ CacheReadInputTokenCost * float64 `json:"cache_read_input_token_cost,omitempty"`
892+ CacheCreationInputTokenCost * float64 `json:"cache_creation_input_token_cost,omitempty"`
893+ }
894+
895+ type modelResponse struct {
896+ ID string `json:"id"`
897+ Type string `json:"type"`
898+ DisplayName string `json:"display_name"`
899+ CreatedAt string `json:"created_at"`
900+ ContextLength * int `json:"context_length,omitempty"`
901+ MaxOutputTokens * int `json:"max_output_tokens,omitempty"`
902+ Pricing * modelPricingResponse `json:"pricing,omitempty"`
903+ }
904+
905+ func (h * GatewayHandler ) writeModelsResponse (c * gin.Context , modelIDs []string ) {
906+ models := make ([]modelResponse , 0 , len (modelIDs ))
907+ for _ , modelID := range modelIDs {
908+ models = append (models , h .buildModelResponse (modelID , modelID , "2024-01-01T00:00:00Z" ))
909+ }
910+ c .JSON (http .StatusOK , gin.H {
911+ "object" : "list" ,
912+ "data" : models ,
913+ })
914+ }
915+
916+ func (h * GatewayHandler ) writeDefaultOpenAIModelsResponse (c * gin.Context ) {
917+ models := make ([]modelResponse , 0 , len (openai .DefaultModels ))
918+ for _ , model := range openai .DefaultModels {
919+ createdAt := time .Unix (model .Created , 0 ).UTC ().Format (time .RFC3339 )
920+ models = append (models , h .buildModelResponse (model .ID , model .DisplayName , createdAt ))
921+ }
922+ c .JSON (http .StatusOK , gin.H {
923+ "object" : "list" ,
924+ "data" : models ,
925+ })
926+ }
927+
928+ func (h * GatewayHandler ) writeDefaultClaudeModelsResponse (c * gin.Context ) {
929+ models := make ([]modelResponse , 0 , len (claude .DefaultModels ))
930+ for _ , model := range claude .DefaultModels {
931+ models = append (models , h .buildModelResponse (model .ID , model .DisplayName , model .CreatedAt ))
932+ }
898933 c .JSON (http .StatusOK , gin.H {
899934 "object" : "list" ,
900- "data" : claude . DefaultModels ,
935+ "data" : models ,
901936 })
902937}
903938
939+ func (h * GatewayHandler ) buildModelResponse (modelID , displayName , createdAt string ) modelResponse {
940+ resp := modelResponse {
941+ ID : modelID ,
942+ Type : "model" ,
943+ DisplayName : displayName ,
944+ CreatedAt : createdAt ,
945+ }
946+
947+ pricing := h .lookupModelMetadata (modelID )
948+ if pricing == nil {
949+ return resp
950+ }
951+
952+ if pricing .MaxInputTokens > 0 {
953+ v := pricing .MaxInputTokens
954+ resp .ContextLength = & v
955+ }
956+ if pricing .MaxOutputTokens > 0 {
957+ v := pricing .MaxOutputTokens
958+ resp .MaxOutputTokens = & v
959+ }
960+
961+ metaPricing := & modelPricingResponse {}
962+ if pricing .InputCostPerToken > 0 {
963+ v := pricing .InputCostPerToken
964+ metaPricing .InputCostPerToken = & v
965+ }
966+ if pricing .OutputCostPerToken > 0 {
967+ v := pricing .OutputCostPerToken
968+ metaPricing .OutputCostPerToken = & v
969+ }
970+ if pricing .CacheReadInputTokenCost > 0 {
971+ v := pricing .CacheReadInputTokenCost
972+ metaPricing .CacheReadInputTokenCost = & v
973+ }
974+ if pricing .CacheCreationInputTokenCost > 0 {
975+ v := pricing .CacheCreationInputTokenCost
976+ metaPricing .CacheCreationInputTokenCost = & v
977+ }
978+ if metaPricing .InputCostPerToken != nil || metaPricing .OutputCostPerToken != nil || metaPricing .CacheReadInputTokenCost != nil || metaPricing .CacheCreationInputTokenCost != nil {
979+ resp .Pricing = metaPricing
980+ }
981+
982+ return resp
983+ }
984+
985+ func (h * GatewayHandler ) lookupModelMetadata (modelID string ) * service.LiteLLMModelPricing {
986+ if h != nil && h .pricingService != nil {
987+ if pricing := h .pricingService .GetModelPricing (modelID ); pricing != nil {
988+ return pricing
989+ }
990+ }
991+ return service .GetDefaultModelMetadata (modelID )
992+ }
993+
904994// AntigravityModels 返回 Antigravity 支持的全部模型
905995// GET /antigravity/models
906996func (h * GatewayHandler ) AntigravityModels (c * gin.Context ) {
0 commit comments