Skip to content

Introduce new favorite record format. Favourite (config.json) cleanup CLI command. Discovered model are persistent in config.json.#593

Open
eli-l wants to merge 20 commits into
Gitlawb:mainfrom
eli-l:feat/opencode-self-discovery
Open

Introduce new favorite record format. Favourite (config.json) cleanup CLI command. Discovered model are persistent in config.json.#593
eli-l wants to merge 20 commits into
Gitlawb:mainfrom
eli-l:feat/opencode-self-discovery

Conversation

@eli-l

@eli-l eli-l commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Favorites now use provider/model format to reduce unambiguity.
config cleanup command to cleanup stale favorite configs (old format).
For cleanup needs discovered models are saved in config.json for each provider.

Linked issue

Checklist

  • The linked issue already has the issue-approved label.
  • go build ./..., go vet ./..., and go test ./... pass locally.
  • gofmt clean.
  • Tests added/updated for the change (and run under -race where relevant).
  • UI changes include screenshots or a short recording where possible.

Summary by CodeRabbit

  • New Features

    • Added config summary and config cleanup commands, including machine-readable --json output.
    • Persist discovered provider models to improve later setup and model selection reuse.
  • Bug Fixes

    • Stale favorites cleanup removes invalid/unknown/unavailable entries across user and project config.
    • Favorites are now tracked per provider/model, including model IDs with slashes, with deduplication and consistent ordering.
    • Validation now reports multiple issues in one pass for invalid provider selections and favorite references.
  • Tests

    • Expanded CLI/config and model picker coverage for cleanup, persistence, and favorites behavior.

Copilot AI review requested due to automatic review settings July 8, 2026 09:31
@eli-l eli-l marked this pull request as draft July 8, 2026 09:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates Zero’s model favorites and provider model discovery so favorites are unambiguous (provider+model) and discovered model lists can be persisted into config.json, with a new zero config cleanup command to remove stale/invalid favorite entries.

Changes:

  • Switch favorites handling to provider-qualified keys (provider/modelID) and adjust model picker grouping/deduping accordingly.
  • Persist live-discovered provider model lists into config.json (wizard, onboarding/setup flow, model picker discovery, and zero providers models).
  • Add config validation for stale provider model selections / invalid favorites, plus a zero config cleanup command and tests.

Reviewed changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
internal/tui/provider_wizard.go Persist discovered models after saving a provider; refresh in-memory provider list.
internal/tui/provider_wizard_test.go Update wizard rendering expectations for model display.
internal/tui/picker.go Persist live-discovered models; change favorites to provider-qualified keys; adjust picker assembly/dedup.
internal/tui/picker_test.go Add coverage for provider-qualified favorites and slash-containing model IDs; update expectations.
internal/tui/options.go Extend setup selection payload to include discovered models list for persistence.
internal/tui/onboarding.go Include discovered models list in setup save call.
internal/swarm/scheduler_test.go Tighten scheduler test assertion around run counting.
internal/providermodeldiscovery/discovery.go Add OnLiveModels callback and ToDiscoveredModels helper.
internal/providermodeldiscovery/discovery_test.go Verify OnLiveModels errors don’t break discovery flow.
internal/config/writer.go Add SetProviderDiscoveredModels and discovered-model dedup/sort helper.
internal/config/writer_test.go Add tests for SetProviderDiscoveredModels behavior and error cases.
internal/config/validate.go Add semantic validation for provider model vs discovered list and favorites inventory refs.
internal/config/validate_test.go Add tests for invalid favorites and stale provider model selection.
internal/config/types.go Introduce DiscoveredModel and add Models to provider profiles.
internal/config/types_test.go Add JSON round-trip tests for discovered models and provider profile models.
internal/config/local_control_test.go Update resolve options construction to include explicit Env map.
internal/config/cleanup.go Add stale/invalid favorites cleanup logic based on user-config inventory.
internal/config/cleanup_test.go Add coverage for cleanup behavior across user + project config paths.
internal/cli/setup.go Persist discovered models during setup (non-fatal warning on failure).
internal/cli/provider_models.go Persist discovered models after providers models discovery.
internal/cli/provider_models_test.go Add persistence test and seed named provider in selection test.
internal/cli/config.go Add zero config summary and zero config cleanup subcommand implementations.
internal/cli/command_center.go Route zero config to summary/cleanup subcommands; update help text.
internal/cli/command_center_test.go Add tests for config cleanup output and JSON payload; seed config in deps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/tui/provider_wizard.go Outdated
Comment on lines +1133 to +1138
// Refresh savedProviders so /model shows the newly added / updated provider
// without requiring a restart. The profile was just persisted (above) and is
// guaranteed usable (key stored / env var set / local), so it qualifies.
if strings.TrimSpace(profile.Name) != "" {
m.savedProviders = mergeSavedProvider(m.savedProviders, profile)
}
Comment thread internal/tui/provider_wizard.go Outdated
Comment on lines +1969 to +1984
// mergeSavedProvider replaces or appends a profile in the saved list by name.
// This lets the provider wizard refresh m.savedProviders so /model sees newly
// added providers without requiring a restart.
func mergeSavedProvider(profiles []config.ProviderProfile, profile config.ProviderProfile) []config.ProviderProfile {
name := strings.TrimSpace(profile.Name)
if name == "" {
return profiles
}
for i, p := range profiles {
if strings.EqualFold(strings.TrimSpace(p.Name), name) {
profiles[i] = profile
return profiles
}
}
return append(profiles, profile)
}
Comment on lines +53 to +55
if err := persistDiscoveredProviderModels(deps, profile.Name, models); err != nil {
return writeAppError(stderr, err.Error(), exitProvider)
}
Comment thread internal/config/cleanup.go Outdated
Comment on lines +10 to +12
// CleanupStaleFavorites removes favorite model entries from the user and
// project configs that do not reference a provider/model available from the
// global user config.
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 706c063c-8c73-48f8-927a-71bbf3a036d9

📥 Commits

Reviewing files that changed from the base of the PR and between 167dcdb and 3ff7189.

📒 Files selected for processing (1)
  • go.mod
✅ Files skipped from review due to trivial changes (1)
  • go.mod

Walkthrough

Adds persisted discovered-model storage, a config cleanup subcommand, semantic validation for provider/favorite model references, and provider-qualified favorites handling in the TUI. Also updates curated provider model catalog entries and a few unrelated tests/runtime settings.

Changes

Discovered models, cleanup, and favorites

Layer / File(s) Summary
Discovered model schema
internal/config/types.go, internal/config/types_test.go
Adds DiscoveredModel{ID} type, extends ProviderProfile.Models, and updates JSON unmarshal/round-trip coverage.
Config writer for discovered models
internal/config/writer.go, internal/config/writer_test.go
Adds SetProviderDiscoveredModels and deduplication logic to trim, dedupe, sort, and persist per-provider model lists.
Discovery hook for live models
internal/providermodeldiscovery/discovery.go, internal/providermodeldiscovery/discovery_test.go
Adds Options.OnLiveModels during DiscoverCatalog and ToDiscoveredModels conversion, with error swallowing covered by tests.
CLI persistence of discovered models
internal/cli/provider_models.go, internal/cli/provider_models_test.go, internal/cli/setup.go
providers models and setup save flows persist discovered models and warn on non-fatal write failures.
TUI persistence of discovered models
internal/tui/options.go, internal/tui/onboarding.go, internal/tui/provider_wizard.go, internal/tui/provider_wizard_test.go, internal/tui/picker.go
SetupSelection.Models carries discovered models through onboarding/wizard/picker flows and persists them.
Provider-qualified favorites keying
internal/tui/picker.go, internal/tui/picker_test.go
Reworks picker favorites/dedup logic to use "provider/modelID" keys instead of raw model IDs.
Config cleanup core
internal/config/cleanup.go, internal/config/cleanup_test.go
Adds CleanupStaleFavorites and inventory/validation helpers to strip stale or invalid favoriteModels entries from config files.
CLI cleanup subcommand
internal/cli/command_center.go, internal/cli/config.go, internal/cli/command_center_test.go
Splits config into summary and cleanup subcommands, adds handlers and usage text, and covers both output modes in tests.
Semantic validation
internal/config/validate.go, internal/config/validate_test.go
Reworks semantic validation to accumulate issues and adds provider-model/favorite-model reference checks.
Catalog curated entries/filter reorg
internal/providermodelcatalog/catalog.go, internal/providermodelcatalog/filter.go
Updates curated model entries for select providers and changes Models() return composition.
Unrelated test and runtime adjustments
internal/config/local_control_test.go, internal/swarm/scheduler_test.go, go.mod
Adds explicit Env maps to Resolve calls, adds a scheduler wait, and updates the Go toolchain version.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI as CLI (providers models / setup)
  participant Discovery as providermodeldiscovery
  participant ConfigWriter as config.SetProviderDiscoveredModels
  participant UserConfig as user config.json

  User->>CLI: run providers models or setup
  CLI->>Discovery: DiscoverCatalog(Options{OnLiveModels})
  Discovery->>Discovery: fetch live /models
  Discovery->>CLI: OnLiveModels(liveModels)
  CLI->>ConfigWriter: SetProviderDiscoveredModels(path, provider, models)
  ConfigWriter->>ConfigWriter: trim, dedupe, sort models
  ConfigWriter->>UserConfig: write updated provider.Models
  ConfigWriter-->>CLI: success or error
  CLI-->>User: model list output
Loading

Changes

Catalog defaults and test/runtime adjustments

Layer / File(s) Summary
Catalog curated entries and filtering order
internal/providermodelcatalog/catalog.go, internal/providermodelcatalog/filter.go
Updates curated provider model entries and changes Models() to return deduped models without the previous filter wrapper.
Test and runtime adjustments
internal/config/local_control_test.go, internal/swarm/scheduler_test.go, go.mod
Adds explicit Env maps to config resolution tests, waits for scheduler run counts, and updates the Go directive.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • Gitlawb/zero#386: Both PRs modify internal/cli/provider_models.go and the zero providers models flow.
  • Gitlawb/zero#544: Both PRs touch internal/providermodelcatalog model filtering and curated provider model behavior.

Suggested reviewers: gnanam1990, Vasanthdev2004, anandh8x, kevincodex1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main changes: favorite format, config cleanup, and persisted discovered models.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
internal/tui/provider_wizard.go (2)

1968-1984: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the existing saved-profile upsert helper

mergeSavedProvider is the same replace-or-append-by-name logic as upsertSavedProviderProfile, and the surrounding code already guarantees a non-empty profile.Name. Drop the duplicate helper and call the existing one instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/provider_wizard.go` around lines 1968 - 1984, The
mergeSavedProvider helper duplicates the existing replace-or-append-by-name
logic already implemented by upsertSavedProviderProfile, and the caller context
already ensures profile.Name is non-empty. Remove mergeSavedProvider and update
the provider wizard flow to reuse upsertSavedProviderProfile instead, keeping
the saved profile refresh behavior in provider_wizard.go consistent through the
existing helper.

1130-1139: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop the duplicate m.savedProviders update
mergeSavedProvider and upsertSavedProviderProfile both replace-or-append by name, so this path updates the same slice twice. Keep one call here and remove the now-unused helper if nothing else depends on it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/tui/provider_wizard.go` around lines 1130 - 1139, The saved
providers slice is being updated twice for the same profile, once via
mergeSavedProvider and again via upsertSavedProviderProfile, causing redundant
replace-or-append behavior. In provider_wizard.go, keep only one savedProviders
update in this commit path around the profile persistence flow and remove the
now-unused helper if nothing else references it; use the mergeSavedProvider and
upsertSavedProviderProfile symbols to verify the duplicate path is eliminated.
internal/providermodeldiscovery/discovery.go (1)

52-54: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Intentional error swallowing is correct but consider logging.

The _ = options.OnLiveModels(liveModels) pattern silently discards persistence failures. The test confirms this is by design — discovery results should not be blocked by cache write errors. However, a failed persist means the cleanup feature won't have fresh data, and the operator has no signal. Consider a debug-level log when the callback returns an error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/providermodeldiscovery/discovery.go` around lines 52 - 54, The
OnLiveModels callback in discovery should still ignore persistence failures, but
it currently discards the error without any signal. Update the discovery flow
around options.OnLiveModels in discovery.go so that when the callback returns an
error it is captured and emitted as a debug-level log with enough context to
identify the live-model persistence attempt, while still allowing discovery to
continue unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/cli/provider_models.go`:
- Around line 53-55: The `ListProviderModels` flow is treating
`persistDiscoveredProviderModels` failure as fatal, which prevents the
discovered models from being shown. Update the error handling around
`persistDiscoveredProviderModels(deps, profile.Name, models)` so persistence
errors are reported to stderr but do not return `writeAppError` or exit early.
Keep the discovery results flowing through `writeProviderModels`/the model
display path even when persistence fails, and only use the persistence failure
as a non-blocking warning.

In `@internal/config/cleanup.go`:
- Around line 135-154: `validFavoriteModelRef` handles empty provider model maps
differently from nil maps, which causes cleanup to reject all favorites for
providers whose discovered `Models` collapse to an empty set. Update the logic
in `favoriteModelInventory.validFavoriteModelRef` so an empty non-nil model map
is treated the same as nil (allow all), matching the behavior already used by
`invalidProviderModelIssues` in `validate.go`. Keep the provider/model lookup
and normalization intact, but change the final availability check to skip
enforcement when the provider’s model map has no entries.

---

Nitpick comments:
In `@internal/providermodeldiscovery/discovery.go`:
- Around line 52-54: The OnLiveModels callback in discovery should still ignore
persistence failures, but it currently discards the error without any signal.
Update the discovery flow around options.OnLiveModels in discovery.go so that
when the callback returns an error it is captured and emitted as a debug-level
log with enough context to identify the live-model persistence attempt, while
still allowing discovery to continue unchanged.

In `@internal/tui/provider_wizard.go`:
- Around line 1968-1984: The mergeSavedProvider helper duplicates the existing
replace-or-append-by-name logic already implemented by
upsertSavedProviderProfile, and the caller context already ensures profile.Name
is non-empty. Remove mergeSavedProvider and update the provider wizard flow to
reuse upsertSavedProviderProfile instead, keeping the saved profile refresh
behavior in provider_wizard.go consistent through the existing helper.
- Around line 1130-1139: The saved providers slice is being updated twice for
the same profile, once via mergeSavedProvider and again via
upsertSavedProviderProfile, causing redundant replace-or-append behavior. In
provider_wizard.go, keep only one savedProviders update in this commit path
around the profile persistence flow and remove the now-unused helper if nothing
else references it; use the mergeSavedProvider and upsertSavedProviderProfile
symbols to verify the duplicate path is eliminated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c846310c-aa1e-41a2-8b67-40fadc0317b0

📥 Commits

Reviewing files that changed from the base of the PR and between 8f15650 and fc0db3a.

📒 Files selected for processing (24)
  • internal/cli/command_center.go
  • internal/cli/command_center_test.go
  • internal/cli/config.go
  • internal/cli/provider_models.go
  • internal/cli/provider_models_test.go
  • internal/cli/setup.go
  • internal/config/cleanup.go
  • internal/config/cleanup_test.go
  • internal/config/local_control_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validate.go
  • internal/config/validate_test.go
  • internal/config/writer.go
  • internal/config/writer_test.go
  • internal/providermodeldiscovery/discovery.go
  • internal/providermodeldiscovery/discovery_test.go
  • internal/swarm/scheduler_test.go
  • internal/tui/onboarding.go
  • internal/tui/options.go
  • internal/tui/picker.go
  • internal/tui/picker_test.go
  • internal/tui/provider_wizard.go
  • internal/tui/provider_wizard_test.go

Comment thread internal/cli/provider_models.go
Comment thread internal/config/cleanup.go
eli-l and others added 17 commits July 8, 2026 12:43
…lidates each favourite model against known providers and models, removing the obsolete/unavailable favourites.
- picker.go: dedupe catalog items by (provider, model) by recording
  seen[fk] after append so two same-Value items from different owners
  (e.g. openai + custom) both surface
- discovery.go: ignore OnLiveModels persistence errors so /model still
  shows live models when the cache write fails
- options.go: complete the SetupSelection.Models doc comment
- cleanup_test.go: rename invalid/typo'd test funcs to match the
  CleanupStaleFavorites API surface and fix the matching t.Fatalf
  messages
Refines the regression test added in f8a7433 to assert that:

1. The OnLiveModels callback receives the raw live models before any
   catalog fallback.
2. DiscoverCatalog returns the catalog-fallback models and a nil error
   even when the callback returns an error.

Renames TestDiscoverCatalogIgnoresOnLiveModelsError to
TestDiscoverCatalog_OnLiveModelsErrorIsSwallowed for clarity and
to match the rest of the file's naming.

Addresses the only outstanding review concern on PR Gitlawb#408 that
needed test coverage; the other four review items were already
addressed in f8a7433.
@eli-l eli-l force-pushed the feat/opencode-self-discovery branch from fc0db3a to 1f74d10 Compare July 8, 2026 10:31
@eli-l eli-l requested a review from Copilot July 8, 2026 10:31
@eli-l eli-l marked this pull request as ready for review July 8, 2026 10:32

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/providercatalog/catalog_test.go (1)

43-47: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Include opencode-go-anthropic-compatible in TransportAnthropicCompat

internal/providercatalog/catalog_test.go:295-296 should list opencode-go-anthropic-compatible under TransportAnthropicCompat too; catalog.go marks it as anthropic-compatible, so ListByTransport(TransportAnthropicCompat) should return it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/providercatalog/catalog_test.go` around lines 43 - 47, Update the
provider catalog mapping so `opencode-go-anthropic-compatible` is included in
`TransportAnthropicCompat` as well as its current transport group; adjust the
relevant setup in `catalog.go` and the expectations in `catalog_test.go` around
`ListByTransport` so the provider is returned for `TransportAnthropicCompat`.
🧹 Nitpick comments (1)
internal/providermodelcatalog/catalog.go (1)

174-183: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Collapse the redundant fallback in Models. dedupeModels(provider.DefaultModel, registryModels(provider)) already covers the empty-registry case, so the len(models) check and nil return can be removed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/providermodelcatalog/catalog.go` around lines 174 - 183, Collapse
the redundant fallback in Models by removing the explicit len(models) branch and
nil return; Models should return dedupeModels(provider.DefaultModel,
curatedModels[provider.ID]) when curated data exists, otherwise directly return
dedupeModels(provider.DefaultModel, registryModels(provider)). Keep the function
name Models and the dedupeModels helper as the main touchpoints when updating
this logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/tui/picker.go`:
- Around line 509-520: modelFavoriteKey is still using the raw OwnerProvider
casing, which can cause favorites lookups to miss for the same provider/model
pair. Update modelFavoriteKey to normalize the provider portion to lower-case
before building the provider-qualified key, matching the canonicalization
already used by NormalizeRecentModels and pickerItemDedupKey. Keep the existing
trimming behavior for item.Value and OwnerProvider, and ensure the returned
favorite key is generated consistently regardless of provider name casing.

---

Outside diff comments:
In `@internal/providercatalog/catalog_test.go`:
- Around line 43-47: Update the provider catalog mapping so
`opencode-go-anthropic-compatible` is included in `TransportAnthropicCompat` as
well as its current transport group; adjust the relevant setup in `catalog.go`
and the expectations in `catalog_test.go` around `ListByTransport` so the
provider is returned for `TransportAnthropicCompat`.

---

Nitpick comments:
In `@internal/providermodelcatalog/catalog.go`:
- Around line 174-183: Collapse the redundant fallback in Models by removing the
explicit len(models) branch and nil return; Models should return
dedupeModels(provider.DefaultModel, curatedModels[provider.ID]) when curated
data exists, otherwise directly return dedupeModels(provider.DefaultModel,
registryModels(provider)). Keep the function name Models and the dedupeModels
helper as the main touchpoints when updating this logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 81d60cdb-434a-459b-87d3-c6f9310fc967

📥 Commits

Reviewing files that changed from the base of the PR and between fc0db3a and 1f74d10.

📒 Files selected for processing (27)
  • internal/cli/command_center.go
  • internal/cli/command_center_test.go
  • internal/cli/config.go
  • internal/cli/provider_models.go
  • internal/cli/provider_models_test.go
  • internal/cli/setup.go
  • internal/config/cleanup.go
  • internal/config/cleanup_test.go
  • internal/config/local_control_test.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/config/validate.go
  • internal/config/validate_test.go
  • internal/config/writer.go
  • internal/config/writer_test.go
  • internal/providercatalog/catalog_test.go
  • internal/providermodelcatalog/catalog.go
  • internal/providermodelcatalog/filter.go
  • internal/providermodeldiscovery/discovery.go
  • internal/providermodeldiscovery/discovery_test.go
  • internal/swarm/scheduler_test.go
  • internal/tui/onboarding.go
  • internal/tui/options.go
  • internal/tui/picker.go
  • internal/tui/picker_test.go
  • internal/tui/provider_wizard.go
  • internal/tui/provider_wizard_test.go
✅ Files skipped from review due to trivial changes (1)
  • internal/providermodelcatalog/filter.go
🚧 Files skipped from review as they are similar to previous changes (23)
  • internal/tui/options.go
  • internal/swarm/scheduler_test.go
  • internal/config/writer_test.go
  • internal/config/writer.go
  • internal/config/types.go
  • internal/config/types_test.go
  • internal/providermodeldiscovery/discovery.go
  • internal/cli/provider_models_test.go
  • internal/config/cleanup.go
  • internal/cli/provider_models.go
  • internal/cli/command_center.go
  • internal/config/local_control_test.go
  • internal/config/cleanup_test.go
  • internal/config/validate.go
  • internal/cli/setup.go
  • internal/cli/command_center_test.go
  • internal/tui/onboarding.go
  • internal/tui/provider_wizard_test.go
  • internal/tui/provider_wizard.go
  • internal/providermodeldiscovery/discovery_test.go
  • internal/cli/config.go
  • internal/tui/picker_test.go
  • internal/config/validate_test.go

Comment thread internal/tui/picker.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 27 out of 27 changed files in this pull request and generated 4 comments.

Comment on lines +267 to +271
// For the restricted provider (opencode-go-anthropic) a
// non-allowed model returns false immediately, without reaching the
// IsKnownNonCodingModelID, Local, or LooksLikeCodingModelID checks.
restricted := providercatalog.Descriptor{
ID: "opencode-go-anthropic-compatible",
ID: "opencode-go-anthropic",
TransportBedrock: {"bedrock"},
TransportVertex: {"vertex"},
TransportAnthropicCompat: {"minimax", "minimaxi-cn", "opencode-go-anthropic-compatible", "custom-anthropic-compatible"},
TransportAnthropicCompat: {"minimax", "minimaxi-cn", "custom-anthropic-compatible"},
Comment on lines +54 to +56
if err := persistDiscoveredProviderModels(deps, profile.Name, models); err != nil {
return writeAppError(stderr, err.Error(), exitProvider)
}
Comment thread internal/tui/picker.go
Comment on lines +516 to +518
if owner := strings.TrimSpace(item.OwnerProvider); owner != "" {
return owner + "/" + id
}
Persist failures during `providers models` are now stderr warnings, not
fatal exits (Copilot + CodeRabbit). CleanupStaleFavorites treats empty
model inventories the same as nil (CodeRabbit); its doc comment also
reflects the invalid-format cleanup it actually performs (Copilot).
Provider-casing normalization in modelFavoriteKey and favoriteModelSet
matches pickerItemDedupKey and NormalizeRecentModels (CodeRabbit). The
provider wizard no longer calls the redundant mergeSavedProvider helper
that duplicated upsertSavedProviderProfile (Copilot + CodeRabbit).

Test fixes the reviewers missed: TransportAnthropicCompat expectation
restored for the still-registered opencode-go-anthropic-compatible
catalog entry; the discovery-gate test now uses the matching provider id
the gate actually fires on; the providers-models test seeds the temp
config file with the profile its resolveConfig override returns; and
the favorites picker test is rewritten for the per-provider/model
semantics instead of the pre-Gitlawb#593 per-Value format.

go test ./... green (75 packages, 0 FAIL). gofmt, vet, build clean.
@kevincodex1

Copy link
Copy Markdown
Contributor

hello @eli-l thanks for your work on this. kindly rebase to main and fix conflcits

eli-l added 2 commits July 9, 2026 09:59
govulncheck ./... is clean on 1.26.5 (no vulnerabilities). go build ./... passes. CI reads toolchain via go-version-file: go.mod so all three OS runners pick this up automatically.

@anandh8x anandh8x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking on #429. The core problem is real: favorites are still bare model ids, while RecentModels is already provider-qualified, so multi-provider setups can resolve the wrong provider.

What works in the direction of this PR:

  • Making favorites provider-aware matches what we already do for recents
  • A migration path for old bare-id favorites is needed either way

Where I'd push back is scope. Caching full discovered model lists on every provider in config.json, plus a new zero config cleanup command, is a bigger product surface than the favorites ambiguity needs. A tighter cut would be:

  1. Store favorites the same way as RecentModels (provider + model), not a "provider/model" string split
  2. Migrate or drop old bare-id favorites on read/write
  3. Defer full model-list persistence and the cleanup command unless there's a stronger reason than validation inventory

A few concrete issues on the current tip:

  • Branch is conflicting with main (mergeStateStatus: DIRTY) — needs a rebase before review can finish
  • Checklist still has go build / go test / gofmt unchecked
  • zero providers models failing when the discovered-models write fails is inconsistent with the wizard, which treats that as best-effort; listing should still succeed
  • mergeSavedProvider looks like a second path next to upsertSavedProviderProfile — worth consolidating
  • Splitting favorites on the first / is fragile if a provider name ever contains /; structured fields avoid that

Happy to re-review a narrower favorites-only revision. The multi-provider favorite fix is worth landing; the rest can follow if we still need it.

@gnanam1990 gnanam1990 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Verdict: Request changes. Agree with @anandh8x on scope and structured favorites.

Process / merge

  • Branch is still CONFLICTING with main (mergeStateStatus: DIRTY) — rebase/merge main before this can land. I hit a conflict in internal/config/local_control_test.go locally.
  • Checklist still has go build / go test / gofmt unchecked.
  • Parent issue #429 is issue-approved — good.

What improved on tip (prior feedback)

  • zero providers models now warns on persist failure instead of failing the list (good).
  • mergeSavedProvider is gone; wizard uses upsertSavedProviderProfile (good).

Blockers

  1. Bare-id favorites break silently, then cleanup deletes them.
    favoriteModelSet keeps old entries like "gpt-4.1"; modelFavoriteKey always uses "provider/model" when OwnerProvider is set. Favorites vanish after upgrade. zero config cleanup treats bare IDs as invalid and removes them — data loss, not migration.

  2. First-/ encoding is wrong for slashy model IDs.
    Legacy favorites are bare model IDs. IDs like openai/gpt-4.1 (OpenRouter-style) get misread as provider=openai. Structured {provider, model} fields (same as RecentModelEntry) avoid this. Do not encode identity in a single slash-separated string.

  3. Scope is still too large for the favorites fix.
    Caching full discovered model lists + zero config cleanup + inventory-based validation circularly justify each other. A tighter cut:

    1. Store favorites like RecentModels (provider + model fields)
    2. Migrate or drop bare-id favorites on read/write
    3. Defer model-list persistence and the cleanup command

Other notes

  • Listing models still rewrites config as a side effect and persists before catalog filtering.
  • OnLiveModels errors are swallowed (_ =); picker can fail persist with no UI warning.
  • Cleanup inventory is user-config only — project-scoped providers get purged.
  • New validate requiring provider.Model ∈ provider.Models is a separate semantic change and will false-positive before discovery.
  • providermodelcatalog.Models() dropped FilterModelsForProvider — looks unrelated; restore or justify separately.

Ask

Happy to re-review a favorites-only revision on a rebased tip: structured provider+model favorites + real migration for bare (and slash-containing) legacy IDs. Model cache / cleanup can follow in a separate PR if still needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants