refactor(provider_registry): Phase B language-advantage pass — dichotomy wave

This commit is contained in:
Nick committed 2026-10-14 02:38:57 +01:00
1 parent 3d21fe3dac
commit b0d7380fb5
2 files changed
+36 -12

No files matched your search

+29 -11
View File
@@ -286,21 +286,39 @@ func (reg *ProviderRegistry) GetProvider(name string) *ModelProvider {
// ListModels — ProviderRegistry.list_models: enabled providers only,
// per-provider fetch errors degrade to a warning (never crash), and
// every model dict is annotated with provider + provider_type.
// Phase B: fetches fan out concurrently; results and warnings are
// assembled in registry order, so output stays byte-identical to the
// sequential oracle regardless of goroutine completion order.
func (reg *ProviderRegistry) ListModels() []map[string]any {
all := []map[string]any{}
type fetch struct {
p *ModelProvider
models []map[string]any
err error
}
fetches := []fetch{}
for _, name := range reg.orderedNames() {
p := reg.Providers[name]
if !p.Enabled {
if p := reg.Providers[name]; p != nil && p.Enabled {
fetches = append(fetches, fetch{p: p})
}
}
var wg sync.WaitGroup
for i := range fetches {
wg.Add(1)
go func(f *fetch) {
defer wg.Done()
f.models, f.err = reg.FetchModels(f.p)
}(&fetches[i])
}
wg.Wait()
all := []map[string]any{}
for _, f := range fetches {
if f.err != nil {
fmt.Printf("Warning: Could not fetch models from %s: %v\n", f.p.Name, f.err)
continue
}
models, err := reg.FetchModels(p)
if err != nil {
fmt.Printf("Warning: Could not fetch models from %s: %v\n", p.Name, err)
continue
}
for _, m := range models {
m["provider"] = p.Name
m["provider_type"] = p.ProviderType
for _, m := range f.models {
m["provider"] = f.p.Name
m["provider_type"] = f.p.ProviderType
all = append(all, m)
}
}
@@ -12,6 +12,7 @@ import (
"encoding/json"
"os"
"path/filepath"
"sync"
"testing"
"time"
)
@@ -31,11 +32,14 @@ type capturedReq struct {
// buildRegistryFromInput constructs a registry from a truth row:
// providers inserted in frozen key order (ParsePyJSON preserves the
// Python dict order), HTTP routed through the scripted Do seam.
// Python dict order), HTTP routed through the scripted Do seam. The
// capture is mutex-guarded because ListModels fans fetches out
// concurrently.
func buildRegistryFromInput(t *testing.T, input *PyDict) (*ProviderRegistry, *[]capturedReq) {
t.Helper()
reg := NewRegistry(filepath.Join(t.TempDir(), "providers.json"))
captured := &[]capturedReq{}
var capMu sync.Mutex
if routesAny := dget(input, "routes"); routesAny != nil {
routes, _ := routesAny.([]any)
reg.Do = func(url string, body []byte, headers map[string]string, timeout time.Duration) ([]byte, error) {
@@ -46,7 +50,9 @@ func buildRegistryFromInput(t *testing.T, input *PyDict) (*ProviderRegistry, *[]
if exc, ok := dget(route, "exc").(string); ok {
return nil, &urlError{msg: exc}
}
capMu.Lock()
*captured = append(*captured, capturedReq{url: url, body: body})
capMu.Unlock()
return json.Marshal(plainJSON(dget(route, "body")))
}
}