mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-12 00:45:22 +00:00
Dead code removed: - BuildProviders, buildModels, ProviderEntry (no production callers) - ZedLanguageModels (shadowed by adapter-local version, wrong schema) - GatewayProviderID deprecated constant (zero references) - Corresponding dead tests for BuildProviders Deduplication: - Extract common.DefaultHome() to internal/adapter/common/home.go - All 7 adapters call common.DefaultHome() instead of local copies (-49 lines) Simplification: - mcp.go: merge MCPClaudeStyle/MCPCrushStyle branches (identical URL path, one-line difference in stdio path) — clearer intent, fewer lines - kilo.go: extract opencode.jsonc merge to mergeOpenCodeJSONC() helper, Render() drops from 92 to ~55 lines - goose.go: strings.IndexByte → strings.Cut in splitProviderModel
93 lines
2.2 KiB
Go
93 lines
2.2 KiB
Go
package common
|
|
|
|
import "github.com/lukaszraczylo/harness-sync/internal/canonical"
|
|
|
|
// MCPStyle selects the dialect for MCP server entries.
|
|
type MCPStyle int
|
|
|
|
const (
|
|
// MCPClaudeStyle: claude-code shape — {command, args, env, url, transport}.
|
|
MCPClaudeStyle MCPStyle = iota
|
|
// MCPCrushStyle: crush shape — adds type: stdio|http|sse.
|
|
MCPCrushStyle
|
|
// MCPOpencodeStyle: kilo + opencode shape — type: local|remote, command as []string.
|
|
MCPOpencodeStyle
|
|
// MCPZedStyle: zed context_servers — {enabled, command, args} or {enabled, url}.
|
|
MCPZedStyle
|
|
)
|
|
|
|
// BuildMCPMapStyled returns the MCP map for the given harness dialect.
|
|
func BuildMCPMapStyled(reg *canonical.MCPRegistry, style MCPStyle) map[string]any {
|
|
out := map[string]any{}
|
|
if reg == nil {
|
|
return out
|
|
}
|
|
for _, s := range reg.Servers {
|
|
out[s.Name] = mcpEntry(s, style)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func mcpEntry(s canonical.MCPServer, style MCPStyle) map[string]any {
|
|
e := map[string]any{}
|
|
switch style {
|
|
case MCPClaudeStyle, MCPCrushStyle:
|
|
if s.URL != "" {
|
|
t := s.Transport
|
|
if t == "" {
|
|
t = "http"
|
|
}
|
|
e["type"] = t
|
|
e["url"] = s.URL
|
|
} else {
|
|
// Claude honours Transport field; Crush always uses "stdio".
|
|
t := "stdio"
|
|
if style == MCPClaudeStyle && s.Transport != "" {
|
|
t = s.Transport
|
|
}
|
|
e["type"] = t
|
|
if s.Command != "" {
|
|
e["command"] = s.Command
|
|
}
|
|
if len(s.Args) > 0 {
|
|
e["args"] = s.Args
|
|
}
|
|
if len(s.Env) > 0 {
|
|
e["env"] = s.Env
|
|
}
|
|
}
|
|
case MCPOpencodeStyle:
|
|
if s.URL != "" {
|
|
e["type"] = "remote"
|
|
e["url"] = s.URL
|
|
} else {
|
|
e["type"] = "local"
|
|
cmd := []string{}
|
|
if s.Command != "" {
|
|
cmd = append(cmd, s.Command)
|
|
}
|
|
cmd = append(cmd, s.Args...)
|
|
e["command"] = cmd
|
|
if len(s.Env) > 0 {
|
|
e["environment"] = s.Env
|
|
}
|
|
}
|
|
e["enabled"] = true
|
|
case MCPZedStyle:
|
|
// Do NOT emit "enabled" — Zed 1.3.x has a serde flatten+deny_unknown_fields
|
|
// bug where outer-struct fields bleed into the untagged enum variants and
|
|
// fail all of them. Omitting "enabled" defaults to true.
|
|
if s.URL != "" {
|
|
e["url"] = s.URL
|
|
} else {
|
|
if s.Command != "" {
|
|
e["command"] = s.Command
|
|
}
|
|
if len(s.Args) > 0 {
|
|
e["args"] = s.Args
|
|
}
|
|
}
|
|
}
|
|
return e
|
|
}
|