fix(zed): switch to language_models.openai_compatible for Agent panel visibility

The Zed Agent panel (new ACP-based UI) only discovers providers registered
under language_models.openai_compatible.<name>, not language_models.openai.
Each named entry appears as its own provider in the LLM Providers list.

- language_models.openai_compatible.harness-sync-gateway holds gateway URL + models
- agent.default_model.provider = 'harness-sync-gateway' (was 'openai')
- Model entries include capabilities {tools,images,parallel_tool_calls}
- Export common.GatewayProviderID so zed.go can reference it
- Fix staticcheck QF1001 (De Morgan's law) in io.go
- Fix struct field alignment in File (80→72 bytes)
- gofmt remaining files
This commit is contained in:
2026-05-23 21:12:47 +01:00
parent fd97c60df2
commit bde3128dba
27 changed files with 345 additions and 117 deletions
+19 -26
View File
@@ -43,6 +43,19 @@ func defaultHome() string {
// Name returns the harness identifier.
func (a *Adapter) Name() string { return name }
// Capabilities declares what claude-code harness-sync manages.
// Claude Code has its own Anthropic Max subscription — provider/model config is skipped.
func (a *Adapter) Capabilities() adapter.HarnessCapabilities {
return adapter.HarnessCapabilities{
ManagesProviders: false,
ManagesModels: false,
ManagesMCP: true,
ManagesSkills: true,
ManagesInstructions: true,
HasBuiltInSub: true,
}
}
// Detect returns true when ~/.claude exists.
func (a *Adapter) Detect() bool {
_, err := os.Stat(filepath.Join(a.home, ".claude"))
@@ -50,9 +63,8 @@ func (a *Adapter) Detect() bool {
}
// Render produces the FileSet that applies the canonical bundle to claude-code.
// settings.json is MERGED into any existing file so user-managed keys
// settings.json is MERGED into any existing file so user-managed keys
// (hooks, permissions, env, …) are preserved.
// Claude Code manages its own subscription and settings.json — harness-sync
// only manages skills/agents symlinks, CLAUDE.md, and MCP servers.
func (a *Adapter) Render(b *canonical.Bundle) (*adapter.FileSet, error) {
fs := adapter.NewFileSet()
base := filepath.Join(a.home, ".claude")
@@ -78,29 +90,6 @@ func (a *Adapter) Render(b *canonical.Bundle) (*adapter.FileSet, error) {
Content: []byte(instructions),
})
// settings.json holds the gateway env vars + model override.
// Only emit when a gateway URL is configured.
if b.Profile.Gateway.URL != "" {
settingsPath := filepath.Join(base, "settings.json")
settingsExisting, _ := os.ReadFile(settingsPath)
settingsOverlay := map[string]any{
"model": b.Profile.Gateway.DefaultModel,
"env": map[string]any{
"ANTHROPIC_BASE_URL": b.Profile.Gateway.URL,
"ANTHROPIC_AUTH_TOKEN": b.Profile.Gateway.Token,
},
}
settingsMerged, err := common.MergeJSONKeys(settingsExisting, settingsOverlay)
if err != nil {
return nil, err
}
fs.Add(adapter.File{
Dest: settingsPath,
Kind: adapter.RenderedFile,
Content: settingsMerged,
})
}
// Claude Code reads MCP servers from two files on disk:
// * ~/.claude.json (live, written by `claude mcp add`)
// * ~/.claude/mcp_servers.json (older / fallback location)
@@ -133,6 +122,10 @@ func (a *Adapter) Render(b *canonical.Bundle) (*adapter.FileSet, error) {
Dest: livePath,
Kind: adapter.RenderedFile,
Content: liveMerged,
// NoMerge: .claude.json is a live state file (Claude Code rewrites it
// constantly). The JSON merge above already reconciles at the key level;
// a git 3-way merge on top causes perpetual conflicts.
NoMerge: true,
})
}