diff --git a/internal/harnesses/harnesses.go b/internal/harnesses/harnesses.go index d637b00..3417abf 100644 --- a/internal/harnesses/harnesses.go +++ b/internal/harnesses/harnesses.go @@ -13,8 +13,12 @@ type Status struct { } type ConfigureOptions struct { - Model string - Overwrite bool + Model string + // ContextWindow and MaxOutputTokens are what the model list reports for + // Model, zero when it does not say. + ContextWindow int + MaxOutputTokens int + Overwrite bool } type LaunchOptions struct { diff --git a/internal/harnesses/pi.go b/internal/harnesses/pi.go index f10bfcf..ecd672a 100644 --- a/internal/harnesses/pi.go +++ b/internal/harnesses/pi.go @@ -46,7 +46,9 @@ type piProviderConfig struct { } type piModelConfig struct { - ID string `json:"id"` + ID string `json:"id"` + ContextWindow int `json:"contextWindow"` + MaxTokens int `json:"maxTokens"` } type PiHarness struct { @@ -402,7 +404,7 @@ func (p *PiHarness) configureMerge(opts ConfigureOptions) error { "X-Title": "Pi", }, "models": []any{ - map[string]any{"id": opts.Model}, + piModelConfigFrom(opts), }, }, }, @@ -445,7 +447,7 @@ func (p *PiHarness) configureOverwrite(opts ConfigureOptions) error { "X-Title": "Pi", }, Models: []piModelConfig{ - {ID: opts.Model}, + piModelConfigFrom(opts), }, }, }, @@ -468,6 +470,22 @@ func (p *PiHarness) configureOverwrite(opts ConfigureOptions) error { return nil } +// piModelConfigFrom describes the configured model with its capacities, since +// Pi caps a model without them at 128k tokens. +func piModelConfigFrom(opts ConfigureOptions) piModelConfig { + entry := piCatalogModelFrom(client.Model{ + ID: opts.Model, + ContextWindow: opts.ContextWindow, + MaxOutputTokens: opts.MaxOutputTokens, + }) + + return piModelConfig{ + ID: entry.ID, + ContextWindow: entry.ContextWindow, + MaxTokens: entry.MaxTokens, + } +} + func (p *PiHarness) modelsPath() string { return filepath.Join(p.configDir, "models.json") } diff --git a/internal/harnesses/pi_test.go b/internal/harnesses/pi_test.go index 7fb400c..8a8405b 100644 --- a/internal/harnesses/pi_test.go +++ b/internal/harnesses/pi_test.go @@ -39,7 +39,9 @@ func TestPiHarnessRoundTrip(t *testing.T) { // Configure the machine. err = harness.Configure(ConfigureOptions{ - Model: "anthropic/claude-fable-5", + Model: "anthropic/claude-fable-5", + ContextWindow: 1_000_000, + MaxOutputTokens: 64_000, }) require.NoError(t, err) @@ -63,7 +65,7 @@ func TestPiHarnessRoundTrip(t *testing.T) { "X-Title": "Pi" }, "models": [ - {"id": "anthropic/claude-fable-5"} + {"id": "anthropic/claude-fable-5", "contextWindow": 1000000, "maxTokens": 64000} ] } } @@ -107,7 +109,7 @@ func TestPiHarnessConfigureCreatesMissingConfig(t *testing.T) { "X-Title": "Pi" }, "models": [ - {"id": "anthropic/claude-fable-5"} + {"id": "anthropic/claude-fable-5", "contextWindow": 200000, "maxTokens": 8192} ] } } diff --git a/internal/tui/pages/requesty/dashboard/integrations.go b/internal/tui/pages/requesty/dashboard/integrations.go index 80b17c8..f8fe0bc 100644 --- a/internal/tui/pages/requesty/dashboard/integrations.go +++ b/internal/tui/pages/requesty/dashboard/integrations.go @@ -254,7 +254,10 @@ func (m integrationState) updateModelStep(msg tea.KeyPressMsg) (integrationState if m.wizard.modelsErr == nil && len(models) > 0 && m.cursor < len(m.items) { - m.wizard.options.Model = models[m.wizard.modelCursor].ID + model := models[m.wizard.modelCursor] + m.wizard.options.Model = model.ID + m.wizard.options.ContextWindow = model.ContextWindow + m.wizard.options.MaxOutputTokens = model.MaxOutputTokens m.wizard.step = integrationModeWizardStep m.wizard.modeCursor = 0 m.wizard.configureErr = nil @@ -292,6 +295,8 @@ func (m integrationState) updateModeStep(msg tea.KeyPressMsg) (integrationState, case "esc": m.wizard.step = integrationModelWizardStep m.wizard.options.Model = "" + m.wizard.options.ContextWindow = 0 + m.wizard.options.MaxOutputTokens = 0 m.wizard.modeCursor = 0 m.wizard.configureErr = nil case "up", "k":