fix(opencode/kilo): add top-level name + models Record to ProvidersAsMap

opencode/kilo require top-level 'name' and a 'models' Record<modelID,Model>
in each provider entry for the harness UI to enumerate and display models.
Without 'name', the gateway appears unlabelled; without 'models', the provider
shows no model list in the selector.
This commit is contained in:
2026-05-23 21:12:46 +01:00
parent ce7a217231
commit fd97c60df2
+21 -4
View File
@@ -113,18 +113,34 @@ func CrushRoleModels(p *canonical.Profile) map[string]any {
} }
// ProvidersAsMap returns a name-keyed map of provider objects for harnesses // ProvidersAsMap returns a name-keyed map of provider objects for harnesses
// like opencode/kilo that use `provider` (singular, map-shaped) instead of a // like opencode/kilo that use `provider` (singular, map-shaped). Includes
// slice. Each entry has npm + options.{baseURL,apiKey} per the opencode schema. // top-level "name" and "models" Record so the harness UI can enumerate models.
func ProvidersAsMap(p *canonical.Profile) map[string]any { func ProvidersAsMap(p *canonical.Profile) map[string]any {
out := map[string]any{} out := map[string]any{}
if p.Gateway.URL != "" { if p.Gateway.URL != "" {
out[gatewayProviderID] = map[string]any{ models := map[string]any{}
"npm": "@ai-sdk/openai-compatible", for _, m := range p.Models {
displayName := m.ID
if m.Alias != "" {
displayName = m.Alias
}
models[m.ID] = map[string]any{
"name": displayName,
"limit": map[string]any{"context": 200000, "output": 8192},
}
}
entry := map[string]any{
"name": "harness-sync gateway",
"npm": "@ai-sdk/openai-compatible",
"options": map[string]any{ "options": map[string]any{
"baseURL": p.Gateway.URL, "baseURL": p.Gateway.URL,
"apiKey": p.Gateway.Token, "apiKey": p.Gateway.Token,
}, },
} }
if len(models) > 0 {
entry["models"] = models
}
out[gatewayProviderID] = entry
} }
for _, up := range p.Upstreams { for _, up := range p.Upstreams {
entry := map[string]any{ entry := map[string]any{
@@ -145,6 +161,7 @@ func ProvidersAsMap(p *canonical.Profile) map[string]any {
return out return out
} }
// KiloModelString returns the "providerID/modelID" string used by kilo/opencode. // KiloModelString returns the "providerID/modelID" string used by kilo/opencode.
func KiloModelString(p *canonical.Profile) string { func KiloModelString(p *canonical.Profile) string {
if p.Gateway.DefaultModel == "" { if p.Gateway.DefaultModel == "" {