feat(agents): add chat model pricing metadata (#22959)

## Summary
- add chat model pricing metadata to the agents admin form and SDK
metadata
- split pricing into its own section and show default pricing as
placeholders
- apply default pricing when admins leave pricing fields blank
This commit is contained in:
Michael Suchacz
2026-03-12 07:37:33 +01:00
committed by GitHub
parent 3325b86903
commit fba00a6b3a
17 changed files with 958 additions and 165 deletions
+54
View File
@@ -3095,6 +3095,10 @@ func marshalChatModelCallConfig(
return json.RawMessage("{}"), nil
}
if err := validateChatModelCallConfig(modelConfig); err != nil {
return nil, err
}
encoded, err := json.Marshal(modelConfig)
if err != nil {
return nil, xerrors.Errorf("encode model config: %w", err)
@@ -3102,6 +3106,44 @@ func marshalChatModelCallConfig(
return encoded, nil
}
func validateChatModelCallConfig(modelConfig *codersdk.ChatModelCallConfig) error {
if modelConfig == nil {
return nil
}
costConfig := codersdk.ModelCostConfig{}
if modelConfig.Cost != nil {
costConfig = *modelConfig.Cost
}
pricingFields := []struct {
name string
value *float64
}{
{name: "cost.input_price_per_million_tokens", value: costConfig.InputPricePerMillionTokens},
{name: "cost.output_price_per_million_tokens", value: costConfig.OutputPricePerMillionTokens},
{name: "cost.cache_read_price_per_million_tokens", value: costConfig.CacheReadPricePerMillionTokens},
{name: "cost.cache_write_price_per_million_tokens", value: costConfig.CacheWritePricePerMillionTokens},
}
for _, field := range pricingFields {
if err := validateNonNegativeFloat64Field(field.name, field.value); err != nil {
return err
}
}
return nil
}
func validateNonNegativeFloat64Field(name string, value *float64) error {
if value == nil {
return nil
}
if *value < 0 {
return xerrors.Errorf("%s must be greater than or equal to zero", name)
}
return nil
}
func unmarshalChatModelCallConfig(
raw json.RawMessage,
) *codersdk.ChatModelCallConfig {
@@ -3130,9 +3172,21 @@ func isZeroChatModelCallConfig(config *codersdk.ChatModelCallConfig) bool {
config.TopK == nil &&
config.PresencePenalty == nil &&
config.FrequencyPenalty == nil &&
isZeroModelCostConfig(config.Cost) &&
isZeroChatModelProviderOptions(config.ProviderOptions)
}
func isZeroModelCostConfig(cost *codersdk.ModelCostConfig) bool {
if cost == nil {
return true
}
return cost.InputPricePerMillionTokens == nil &&
cost.OutputPricePerMillionTokens == nil &&
cost.CacheReadPricePerMillionTokens == nil &&
cost.CacheWritePricePerMillionTokens == nil
}
func isZeroChatModelProviderOptions(options *codersdk.ChatModelProviderOptions) bool {
if options == nil {
return true