mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-03 01:01:56 +08:00
Replaces the Python agent canvas runtime with a Go implementation that runs inside `cmd/server_main`. The canvas compiles into an eino Workflow that pauses on wait-for-user via native Interrupt/Resume (no sentinel flag) and resumes from a Redis-backed CheckPointStore. All 21 Python agent components and ~35 tools are ported with functional parity. Sandbox providers now read their JSON config from the admin-panel system_settings table with env fallback. 234 files / +35,413 / -6,111. All Go files are gofmt-clean (CI gate added); drops the v2 DSL E2E step and the gap-analysis plan (both redundant after the port ships). ## Type of change - [x] Refactoring - [x] New feature - [x] Bug fix 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
77 lines
2.3 KiB
Go
77 lines
2.3 KiB
Go
// Package component — registry (orchestrator-owned, DO NOT EDIT).
|
|
//
|
|
// Registry maps component names to factories. Each component's init() calls
|
|
// Register(name, factory) to enroll itself; lookup is case-insensitive
|
|
// (matches Python v1 component_name case-insensitivity).
|
|
package component
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
)
|
|
|
|
// Factory constructs a Component from a params map (loaded from the DSL).
|
|
// Returning an error here aborts the run with a clear message.
|
|
type Factory func(params map[string]any) (Component, error)
|
|
|
|
var (
|
|
registryMu sync.RWMutex
|
|
registry = make(map[string]Factory)
|
|
)
|
|
|
|
// Register enrolls a component factory under name (case-insensitive).
|
|
// Intended to be called from init() in each component's <name>.go file.
|
|
func Register(name string, f Factory) {
|
|
registryMu.Lock()
|
|
defer registryMu.Unlock()
|
|
key := strings.ToLower(strings.TrimSpace(name))
|
|
if key == "" {
|
|
panic("component: Register called with empty name")
|
|
}
|
|
if _, exists := registry[key]; exists {
|
|
panic(fmt.Sprintf("component: %q already registered", name))
|
|
}
|
|
registry[key] = f
|
|
}
|
|
|
|
// New constructs a Component by name. Returns an error if the name is
|
|
// unknown or the factory rejects the params. The empty-string case is
|
|
// treated as "not found" so the error message is consistent.
|
|
func New(name string, params map[string]any) (Component, error) {
|
|
registryMu.RLock()
|
|
f, ok := registry[strings.ToLower(strings.TrimSpace(name))]
|
|
registryMu.RUnlock()
|
|
if !ok {
|
|
return nil, fmt.Errorf("component: unknown component %q (registered: %s)", name, RegisteredNames())
|
|
}
|
|
if f == nil {
|
|
return nil, fmt.Errorf("component: nil factory for %q", name)
|
|
}
|
|
return f(params)
|
|
}
|
|
|
|
// RegisteredNames returns the sorted list of registered component names.
|
|
// Used for diagnostics and the API 500 path "list available components".
|
|
func RegisteredNames() []string {
|
|
registryMu.RLock()
|
|
defer registryMu.RUnlock()
|
|
names := make([]string, 0, len(registry))
|
|
for n := range registry {
|
|
names = append(names, n)
|
|
}
|
|
// Stable order for error messages / UI listing.
|
|
sortStrings(names)
|
|
return names
|
|
}
|
|
|
|
// sortStrings is a small in-place insertion sort to avoid the sort package
|
|
// dependency for a list that's <50 items long in practice.
|
|
func sortStrings(s []string) {
|
|
for i := 1; i < len(s); i++ {
|
|
for j := i; j > 0 && s[j-1] > s[j]; j-- {
|
|
s[j-1], s[j] = s[j], s[j-1]
|
|
}
|
|
}
|
|
}
|