mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-06-29 15:31:05 +08:00
Ports the agent canvas subsystem from Python to Go.
## What's included
### Canvas Engine (Phase 0/1)
- State engine, scheduler, variable resolver, Redis checkpoint store,
cancel protocol
- **209 tests** across canvas / component / io packages
### 22 Components (P0–P4)
| Tier | Components |
|---|---|
| P0 T1+T2+T3 | LLM, Agent, ExitLoop, Switch, Categorize, Begin,
Message, Invoke |
| P1 T3 | VariableAggregator, VariableAssigner, StringTransform,
ListOperations, DataOperations |
| P2 T3 | Iteration, IterationItem, Loop, LoopItem |
| P3 T3 | UserFillUp, Fillup |
| P4 T5 | Browser, ExcelProcessor, DocsGenerator |
### DSL v2 Schema (Phase 2.5)
- Typed v2 in-memory model with v1-to-v2 auto-detect converter
- v1 legacy field stripping per plan §2.11.7
### HTTP Endpoints & Bug Fixes (Plans PR1–PR3)
- **DELETE SQL bug fix**: gorm v2 `Where("id = ?", id).Delete(...)`
pattern
- **CreateAgent validation**: title/DSL required, duplicate check, 103
envelope
- **13 new endpoints**: templates, prompts, tags, sessions CRUD,
chat/completions (SSE + non-stream stubs), rerun, test_db_connection,
logs, webhook/logs
- **756 Go unit tests** (745 → 756, +18)
- **17 → 0 Python integration test failures** (test_agents.py +
test_session_management/)
### Tools
21 eino tools: HTTPHelper, search tools, financial/data tools, mandatory
stubs
### Infrastructure
OTel observability, NATS message queue, DeepDoc gRPC client, SSRF
guards, IDOR mitigation
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
|
|
// (Python v1 case-insensitivity per dsl-v1-corner-cases.md §13).
|
|
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]
|
|
}
|
|
}
|
|
}
|