diff --git a/pkg/agent/instance.go b/pkg/agent/instance.go index 880725660..9af38c1d0 100644 --- a/pkg/agent/instance.go +++ b/pkg/agent/instance.go @@ -131,6 +131,9 @@ func NewAgentInstance( } maxTokens := defaults.MaxTokens + if mc, err := cfg.GetModelConfig(defaults.OriginalModelName); err == nil { + maxTokens = mc.MaxTokens + } if maxTokens == 0 { maxTokens = 8192 } diff --git a/pkg/config/config.go b/pkg/config/config.go index 533f45a44..d37e1a973 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -327,6 +327,9 @@ type AgentDefaults struct { SubTurn SubTurnConfig `json:"subturn" envPrefix:"PICOCLAW_AGENTS_DEFAULTS_SUBTURN_"` ToolFeedback ToolFeedbackConfig `json:"tool_feedback,omitempty"` SplitOnMarker bool `json:"split_on_marker" env:"PICOCLAW_AGENTS_DEFAULTS_SPLIT_ON_MARKER"` // split messages on <|[SPLIT]|> marker + // OriginalModelName holds the original model name as specified in the config. + // This is used to resolve the model name in the model_list configuration. + OriginalModelName string `json:"-"` } const DefaultMaxMediaSize = 20 * 1024 * 1024 // 20 MB @@ -668,6 +671,7 @@ type ModelConfig struct { // Optional optimizations RPM int `json:"rpm,omitempty"` // Requests per minute limit + MaxTokens int `json:"max_tokens,omitempty"` // Maximum number of tokens per request MaxTokensField string `json:"max_tokens_field,omitempty"` // Field name for max tokens (e.g., "max_completion_tokens") RequestTimeout int `json:"request_timeout,omitempty"` ThinkingLevel string `json:"thinking_level,omitempty"` // Extended thinking: off|low|medium|high|xhigh|adaptive @@ -1287,6 +1291,7 @@ func expandMultiKeyModels(models []*ModelConfig) []*ModelConfig { ConnectMode: m.ConnectMode, Workspace: m.Workspace, RPM: m.RPM, + MaxTokens: m.MaxTokens, MaxTokensField: m.MaxTokensField, RequestTimeout: m.RequestTimeout, ThinkingLevel: m.ThinkingLevel, @@ -1307,6 +1312,7 @@ func expandMultiKeyModels(models []*ModelConfig) []*ModelConfig { ConnectMode: m.ConnectMode, Workspace: m.Workspace, RPM: m.RPM, + MaxTokens: m.MaxTokens, MaxTokensField: m.MaxTokensField, RequestTimeout: m.RequestTimeout, ThinkingLevel: m.ThinkingLevel, diff --git a/pkg/config/config_old.go b/pkg/config/config_old.go index fd54c9e08..b2ad686ba 100644 --- a/pkg/config/config_old.go +++ b/pkg/config/config_old.go @@ -660,6 +660,7 @@ type modelConfigV0 struct { // Optional optimizations RPM int `json:"rpm,omitempty"` // Requests per minute limit + MaxTokens int `json:"max_tokens,omitempty"` // Maximum number of tokens per request MaxTokensField string `json:"max_tokens_field,omitempty"` // Field name for max tokens (e.g., "max_completion_tokens") RequestTimeout int `json:"request_timeout,omitempty"` ThinkingLevel string `json:"thinking_level,omitempty"` // Extended thinking: off|low|medium|high|xhigh|adaptive @@ -744,6 +745,7 @@ func (c *configV0) Migrate() (*Config, error) { ConnectMode: m.ConnectMode, Workspace: m.Workspace, RPM: m.RPM, + MaxTokens: m.MaxTokens, MaxTokensField: m.MaxTokensField, RequestTimeout: m.RequestTimeout, ThinkingLevel: m.ThinkingLevel, diff --git a/pkg/config/migration.go b/pkg/config/migration.go index fee800a76..075fa408e 100644 --- a/pkg/config/migration.go +++ b/pkg/config/migration.go @@ -499,6 +499,7 @@ func loadConfigV0(data []byte) (migratable, error) { ConnectMode: m.ConnectMode, Workspace: m.Workspace, RPM: m.RPM, + MaxTokens: m.MaxTokens, MaxTokensField: m.MaxTokensField, RequestTimeout: m.RequestTimeout, ThinkingLevel: m.ThinkingLevel, diff --git a/pkg/config/multikey_test.go b/pkg/config/multikey_test.go index e58c6dc9e..0a4e56fa3 100644 --- a/pkg/config/multikey_test.go +++ b/pkg/config/multikey_test.go @@ -192,6 +192,7 @@ func TestExpandMultiKeyModels_PreservesOtherFields(t *testing.T) { APIBase: "https://api.example.com", Proxy: "http://proxy:8080", RPM: 60, + MaxTokens: 1024, MaxTokensField: "max_completion_tokens", RequestTimeout: 30, ThinkingLevel: "high", @@ -212,6 +213,9 @@ func TestExpandMultiKeyModels_PreservesOtherFields(t *testing.T) { if primary.RPM != 60 { t.Errorf("expected rpm preserved, got %d", primary.RPM) } + if primary.MaxTokens != 1024 { + t.Errorf("expected max_tokens preserved, got %d", primary.MaxTokens) + } if primary.MaxTokensField != "max_completion_tokens" { t.Errorf("expected max_tokens_field preserved, got %q", primary.MaxTokensField) } diff --git a/pkg/gateway/gateway.go b/pkg/gateway/gateway.go index c35b3e744..b003d0733 100644 --- a/pkg/gateway/gateway.go +++ b/pkg/gateway/gateway.go @@ -113,6 +113,9 @@ func Run(debug bool, homePath, configPath string, allowEmptyStartup bool) error } if modelID != "" { + if cfg.Agents.Defaults.OriginalModelName == "" { + cfg.Agents.Defaults.OriginalModelName = cfg.Agents.Defaults.ModelName + } cfg.Agents.Defaults.ModelName = modelID } diff --git a/web/backend/api/models.go b/web/backend/api/models.go index 38a55948b..9c5d57082 100644 --- a/web/backend/api/models.go +++ b/web/backend/api/models.go @@ -35,6 +35,7 @@ type modelResponse struct { ConnectMode string `json:"connect_mode,omitempty"` Workspace string `json:"workspace,omitempty"` RPM int `json:"rpm,omitempty"` + MaxTokens int `json:"max_tokens,omitempty"` MaxTokensField string `json:"max_tokens_field,omitempty"` RequestTimeout int `json:"request_timeout,omitempty"` ThinkingLevel string `json:"thinking_level,omitempty"` @@ -81,6 +82,7 @@ func (h *Handler) handleListModels(w http.ResponseWriter, r *http.Request) { ConnectMode: m.ConnectMode, Workspace: m.Workspace, RPM: m.RPM, + MaxTokens: m.MaxTokens, MaxTokensField: m.MaxTokensField, RequestTimeout: m.RequestTimeout, ThinkingLevel: m.ThinkingLevel, diff --git a/web/frontend/src/api/models.ts b/web/frontend/src/api/models.ts index aa66a7389..ca7f1d54e 100644 --- a/web/frontend/src/api/models.ts +++ b/web/frontend/src/api/models.ts @@ -14,6 +14,7 @@ export interface ModelInfo { connect_mode?: string workspace?: string rpm?: number + max_tokens?: number max_tokens_field?: string request_timeout?: number thinking_level?: string diff --git a/web/frontend/src/components/models/add-model-sheet.tsx b/web/frontend/src/components/models/add-model-sheet.tsx index de9481391..0e338d835 100644 --- a/web/frontend/src/components/models/add-model-sheet.tsx +++ b/web/frontend/src/components/models/add-model-sheet.tsx @@ -32,6 +32,7 @@ interface AddForm { connectMode: string workspace: string rpm: string + maxTokens: string maxTokensField: string requestTimeout: string thinkingLevel: string @@ -48,6 +49,7 @@ const EMPTY_ADD_FORM: AddForm = { connectMode: "", workspace: "", rpm: "", + maxTokens: "", maxTokensField: "", requestTimeout: "", thinkingLevel: "", @@ -128,6 +130,7 @@ export function AddModelSheet({ connect_mode: form.connectMode.trim() || undefined, workspace: form.workspace.trim() || undefined, rpm: form.rpm ? Number(form.rpm) : undefined, + max_tokens: form.maxTokens ? Number(form.maxTokens) : undefined, max_tokens_field: form.maxTokensField.trim() || undefined, request_timeout: form.requestTimeout ? Number(form.requestTimeout) @@ -302,6 +305,19 @@ export function AddModelSheet({ /> + + + + + + + +