mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-15 01:07:27 +00:00
fix(adapters): ground native schemas, merge-not-replace, add goose/cagent/zed
- common/mcp.go: MCPStyle enum + BuildMCPMapStyled for claude/crush/opencode/zed dialects - common/jsonmerge.go: MergeJSONKeys (JSON-first, JSONC fallback) preserves user keys; fix: try plain json.Unmarshal before StripJSONComments to avoid mangling URLs with // - common/yamlmerge.go: MergeYAMLKeys for YAML configs (goose) - common/blocks.go: add ProvidersAsMap for opencode map-shaped provider key - claudecode: merge settings.json (preserves hooks/permissions/env); MCPClaudeStyle (no type field) - crush: fix mcp key (was mcpServers); MCPCrushStyle entries include type field; merge crush.json; fix import key mcp - kilo: drop providers key (kilo has none); MCPOpencodeStyle (local/remote); merge kilo.json - opencode: fix provider (singular map) + model (not default_model); MCPOpencodeStyle; merge jsonc; fix import key mcp - goose: new adapter — YAML merge, extensions map, splitProviderModel, import reconstructs MCP from extensions - cagent: new adapter — renders starter default.yaml, import returns empty - zed: new adapter — merge settings.json, context_servers (MCPZedStyle) + agent.default_model - docs: append Grounded harness schemas section to design spec
This commit is contained in:
@@ -48,6 +48,45 @@ func buildModels(models []canonical.Model) []map[string]any {
|
||||
return out
|
||||
}
|
||||
|
||||
// ProvidersAsMap returns a name-keyed map of provider objects for harnesses
|
||||
// like opencode that use `provider` (singular, map-shaped) instead of a slice.
|
||||
// The gateway entry is keyed "harness-sync-gateway"; upstreams use their name.
|
||||
func ProvidersAsMap(p *canonical.Profile) map[string]any {
|
||||
out := map[string]any{}
|
||||
if p.Gateway.URL != "" {
|
||||
entry := map[string]any{
|
||||
"name": "harness-sync gateway",
|
||||
"options": map[string]any{
|
||||
"baseURL": p.Gateway.URL,
|
||||
"apiKey": p.Gateway.Token,
|
||||
},
|
||||
}
|
||||
if models := buildModels(p.Models); len(models) > 0 {
|
||||
modelsMap := map[string]any{}
|
||||
for _, m := range p.Models {
|
||||
modelsMap[m.ID] = map[string]any{"name": m.ID}
|
||||
}
|
||||
entry["models"] = modelsMap
|
||||
}
|
||||
out["harness-sync-gateway"] = entry
|
||||
}
|
||||
for _, up := range p.Upstreams {
|
||||
entry := map[string]any{"name": up.Name}
|
||||
opts := map[string]any{}
|
||||
if up.BaseURL != "" {
|
||||
opts["baseURL"] = up.BaseURL
|
||||
}
|
||||
if up.APIKey != "" {
|
||||
opts["apiKey"] = up.APIKey
|
||||
}
|
||||
if len(opts) > 0 {
|
||||
entry["options"] = opts
|
||||
}
|
||||
out[up.Name] = entry
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// BuildMCPMap returns canonical MCP servers as a name -> object map.
|
||||
// Empty map (not nil) is returned when there are no servers so the caller
|
||||
// can decide whether to include the key.
|
||||
|
||||
Reference in New Issue
Block a user