nextlevelbuilder / nextlevelbuilder/goclaw
media_chain: buildDefaultChain uses hardcoded provider names instead of registry lookup by type
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 3.6k
- Forks
- 1.1k
- Avg merge
- 3d 5h
- Merged PRs (30d)
- 24
Description
Problem
buildDefaultChain in internal/tools/media_provider_chain.go iterates over a hardcoded priority list of provider names (e.g. "openrouter", "gemini", "anthropic", "dashscope") and calls registry.Get(ctx, name) to check availability.
This breaks when providers are registered under different names (e.g. aistudio-google instead of gemini, or alibabacloud instead of dashscope). The chain comes back empty even though a compatible provider is available.
Additionally, ResolveMediaProviderChain returns the builtin_tools.settings chain immediately without checking if those providers are actually registered, causing a silent "all providers failed" error at call time.
Root cause
// buildDefaultChain — looks up by hardcoded name, not by type
for _, name := range priority {
if _, err := registry.Get(ctx, name); err == nil { // fails if registered as "aistudio-google"
...
}
}
// ResolveMediaProviderChain — returns settings chain without registry validation
chain := parseChainSettings(raw, defaultModels)
if len(chain) > 0 {
return chain // may contain providers not in registry
}
Suggested fix
-
buildDefaultChain: iterateregistry.List(ctx)instead of the hardcoded names. Resolve each provider's type viaResolveProviderType(p), then match againstdefaultModels(keyed by type). Sort results by the priority type list. -
ResolveMediaProviderChain: after parsing the settings chain, filter entries throughregistry.Get(). If the filtered result is empty, log a warning and fall through tobuildDefaultChain.
// buildDefaultChain — iterate all registered providers, filter by type capability
byType := make(map[string][]MediaProviderEntry)
for _, name := range registry.List(ctx) {
p, _ := registry.Get(ctx, name)
pType := ResolveProviderType(p)
if model, ok := defaultModels[pType]; ok {
byType[pType] = append(byType[pType], MediaProviderEntry{Provider: name, Model: model, Enabled: true})
}
}
// order by priority type list
for _, pType := range priority {
chain = append(chain, byType[pType]...)
}
// ResolveMediaProviderChain — filter settings chain by registry
var available []MediaProviderEntry
for _, e := range chain {
if _, err := registry.Get(ctx, e.Provider); err == nil {
available = append(available, e)
} else {
slog.Warn("media_chain: configured provider not registered, skipping", "tool", toolName, "provider", e.Provider)
}
}
if len(available) > 0 {
return available
}
slog.Warn("media_chain: all configured providers unavailable, falling back to defaults", "tool", toolName)
// fall through to buildDefaultChain
Impact
Affects all media tools that use ResolveMediaProviderChain: read_image, read_video, read_audio, read_document, create_image, create_audio, create_video.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in internal/tools/media_provider_chain.go by tracing buildDefaultChain and ResolveMediaProviderChain through registry.List, registry.Get, ResolveProviderType, and the defaultModels priority list. Verify behavior for providers registered under aliases and for unavailable configured entries across the listed media tools; done means compatible registered providers are selected and settings fall back when none are available.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend, tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100