refactor(workers): per-tenant provider resolution for background workers

Replace static provider/model fields with per-tenant resolution at
processing time. Fixes architectural mismatch where singleton workers
used tenant-specific system_configs.

Changes:
- Add shared ResolveBackgroundProvider() in providerresolve package
- Refactor vault enrichWorker, episodic, dreaming workers to resolve
  provider per-event using registry + systemConfigs
- Remove hot-reload machinery (no longer needed)
- Update ConsolidationDeps to use Registry/SystemConfigs

Fallback chain: background.provider → agent.default_provider → first
registered provider.
This commit is contained in:
viettranx committed 2026-04-12 16:19:55 +07:00
1 parent e021934e68
commit 3fa3fb5ebf
17 files changed
+259 -191

No files matched your search

@@ -0,0 +1,64 @@
package providerresolve
import (
"context"
"github.com/google/uuid"
"github.com/nextlevelbuilder/goclaw/internal/providers"
"github.com/nextlevelbuilder/goclaw/internal/store"
)
// ResolveBackgroundProvider resolves the LLM provider for background workers.
// Fallback chain: background.provider → agent.default_provider → first registered.
// Used by vault enrichment, episodic summarization, dreaming consolidation.
func ResolveBackgroundProvider(
ctx context.Context,
tenantID uuid.UUID,
registry *providers.Registry,
systemConfigs store.SystemConfigStore,
) (providers.Provider, string) {
if registry == nil {
return nil, ""
}
// Load system configs for the tenant
var configs map[string]string
if systemConfigs != nil {
tctx := store.WithTenantID(ctx, tenantID)
configs, _ = systemConfigs.List(tctx)
}
// tryResolve attempts to get a provider by name
tryResolve := func(name, model string) (providers.Provider, string, bool) {
if name == "" {
return nil, "", false
}
p, err := registry.GetForTenant(tenantID, name)
if err != nil || p == nil {
return nil, "", false
}
if model == "" {
model = p.DefaultModel()
}
return p, model, true
}
// 1. Explicit background config
if p, m, ok := tryResolve(configs["background.provider"], configs["background.model"]); ok {
return p, m
}
// 2. Agent default provider
if p, m, ok := tryResolve(configs["agent.default_provider"], configs["agent.default_model"]); ok {
return p, m
}
// 3. First registered provider
names := registry.ListForTenant(tenantID)
if len(names) == 0 {
return nil, ""
}
p, err := registry.GetForTenant(tenantID, names[0])
if err != nil {
return nil, ""
}
return p, p.DefaultModel()
}