refactor(provider_registry): Phase B language-advantage pass — dichotomy wave
This commit is contained in:
1 parent
3d21fe3dac
commit
b0d7380fb5
2 files changed
+36
-12
No files matched your search
@@ -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")))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user