launch: add thinking capability detection to opencode

This commit is contained in:
Eva Ho
2026-04-08 14:42:57 -07:00
parent 698e04a14b
commit 30d9100fff

View File

@@ -1,16 +1,21 @@
package launch
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
"os/exec"
"path/filepath"
"runtime"
"slices"
"strings"
"github.com/ollama/ollama/api"
"github.com/ollama/ollama/cmd/internal/fileutil"
"github.com/ollama/ollama/envconfig"
modeltype "github.com/ollama/ollama/types/model"
)
// OpenCode implements Runner and Editor for OpenCode integration.
@@ -229,6 +234,9 @@ func readModelJSONModels() []string {
}
func buildModelEntries(modelList []string) map[string]any {
client := api.NewClient(envconfig.Host(), http.DefaultClient)
ctx := context.Background()
models := make(map[string]any)
for _, model := range modelList {
entry := map[string]any{
@@ -242,7 +250,49 @@ func buildModelEntries(modelList []string) map[string]any {
}
}
}
applyOpenCodeReasoning(ctx, client, model, entry)
models[model] = entry
}
return models
}
// applyOpenCodeReasoning detects thinking capability and sets reasoning config
// on the model entry. When the model supports thinking, it sets "reasoning": true
// and configures variants for the OpenCode TUI:
// - GPT-OSS: supports variable effort levels (low/medium/high) and defaults to
// medium via options. Thinking cannot be turned off.
// - Other models: only support on/off. Disables built-in low/medium/high variants
// and adds a "none" variant so users can toggle thinking off via Ctrl+T.
//
// When the model does not support thinking, no reasoning config is set.
func applyOpenCodeReasoning(ctx context.Context, client *api.Client, modelName string, entry map[string]any) {
resp, err := client.Show(ctx, &api.ShowRequest{Model: modelName})
if err != nil {
return
}
if slices.Contains(resp.Capabilities, modeltype.CapabilityThinking) {
entry["reasoning"] = true
if strings.Contains(modelName, "gpt-oss") {
// GPT-OSS models support variable thinking effort levels
// and cannot turn thinking off. Keep the built-in
// low/medium/high variants as-is and default to medium.
options, ok := entry["options"].(map[string]any)
if !ok {
options = make(map[string]any)
}
options["reasoningEffort"] = "medium"
entry["options"] = options
} else {
// Most models only support thinking on or off.
// Disable the built-in low/medium/high variants and add none.
entry["variants"] = map[string]any{
"none": map[string]any{"reasoningEffort": "none"},
"low": map[string]any{"disabled": true},
"medium": map[string]any{"disabled": true},
"high": map[string]any{"disabled": true},
}
}
}
}