on main help sign in
fix(agent): support flat_rate cost handling (#2116)
5816fadhuaiyuWangh
internal/agent/agent.go+14−3
@@ -103,6 +103,7 @@ type Model struct {
103 Model fantasy.LanguageModel
103 Model fantasy.LanguageModel
104 CatwalkCfg catwalk.Model
104 CatwalkCfg catwalk.Model
105 ModelCfg config.SelectedModel
105 ModelCfg config.SelectedModel
106+ FlatRate bool
106}
107}
107
108
108type sessionAgent struct {
109type sessionAgent struct {
@@ -1079,6 +1080,11 @@ func (a *sessionAgent) generateTitle(ctx context.Context, sessionID string, user
1079 cost = *openrouterCost
1080 cost = *openrouterCost
1080 }
1081 }
1081
1082
1083+ // Skip cost accumulation
1084+ if model.FlatRate {
1085+ cost = 0
1086+ }
1087+
1082 promptTokens := resp.TotalUsage.InputTokens + resp.TotalUsage.CacheCreationTokens
1088 promptTokens := resp.TotalUsage.InputTokens + resp.TotalUsage.CacheCreationTokens
1083 completionTokens := resp.TotalUsage.OutputTokens
1089 completionTokens := resp.TotalUsage.OutputTokens
1084
1090
@@ -1113,12 +1119,17 @@ func (a *sessionAgent) updateSessionUsage(model Model, session *session.Session,
1113
1119
1114 a.eventTokensUsed(session.ID, model, usage, cost)
1120 a.eventTokensUsed(session.ID, model, usage, cost)
1115
1121
1122+ // Use override cost if available (e.g., from OpenRouter).
1116 if overrideCost != nil {
1123 if overrideCost != nil {
1117− session.Cost += *overrideCost
1124+ cost = *overrideCost
1118− } else {
1125+ }
1119− session.Cost += cost
1126+
1127+ // Skip cost accumulation
1128+ if model.FlatRate {
1129+ cost = 0
1120 }
1130 }
1121
1131
1132+ session.Cost += cost
1122 session.CompletionTokens = usage.OutputTokens
1133 session.CompletionTokens = usage.OutputTokens
1123 session.PromptTokens = usage.InputTokens + usage.CacheReadTokens
1134 session.PromptTokens = usage.InputTokens + usage.CacheReadTokens
1124}
1135}
internal/agent/coordinator.go+2
@@ -626,10 +626,12 @@ func (c *coordinator) buildAgentModels(ctx context.Context, isSubAgent bool) (Mo
626 Model: largeModel,
626 Model: largeModel,
627 CatwalkCfg: *largeCatwalkModel,
627 CatwalkCfg: *largeCatwalkModel,
628 ModelCfg: largeModelCfg,
628 ModelCfg: largeModelCfg,
629+ FlatRate: largeProviderCfg.FlatRate,
629 }, Model{
630 }, Model{
630 Model: smallModel,
631 Model: smallModel,
631 CatwalkCfg: *smallCatwalkModel,
632 CatwalkCfg: *smallCatwalkModel,
632 ModelCfg: smallModelCfg,
633 ModelCfg: smallModelCfg,
634+ FlatRate: smallProviderCfg.FlatRate,
633 }, nil
635 }, nil
634}
636}
635
637
internal/config/config.go+3
@@ -120,6 +120,9 @@ type ProviderConfig struct {
120 // Used to pass extra parameters to the provider.
120 // Used to pass extra parameters to the provider.
121 ExtraParams map[string]string `json:"-"`
121 ExtraParams map[string]string `json:"-"`
122
122
123+ // Skip cost accumulation for this provider when using subscription or flat rate billing.
124+ FlatRate bool `json:"flat_rate,omitempty" jsonschema:"description=Flat-rate mode for this provider"`
125+
123 // The provider models
126 // The provider models
124 Models []catwalk.Model `json:"models,omitempty" jsonschema:"description=List of models available from this provider"`
127 Models []catwalk.Model `json:"models,omitempty" jsonschema:"description=List of models available from this provider"`
125}
128}
schema.json+4
@@ -588,6 +588,10 @@
588 "type": "object",
588 "type": "object",
589 "description": "Additional provider-specific options for this provider"
589 "description": "Additional provider-specific options for this provider"
590 },
590 },
591+ "flat_rate": {
592+ "type": "boolean",
593+ "description": "Flat-rate mode for this provider"
594+ },
591 "models": {
595 "models": {
592 "items": {
596 "items": {
593 "$ref": "#/$defs/Model"
597 "$ref": "#/$defs/Model"