Files
ragflow/internal/agent/component/base.go
Zhichang Yu 4c54cefd29 Port 14 upstream agent security / correctness fixes to Go canvas (#16455)
Mirrors 14 merged upstream PRs into the Go agent port.

PRs ported:
  - #15609 ExeSQL SSRF guard + DNS pin
  - #15436 HTTP timeout on external API tools
  - #16363 be_output restore + DeepL error path
  - #15644 switch no longer matches empty condition
  - #15374 session_id bind to path agent_id (DAO idor guard)
  - #16169 sandbox artifact ownership gate
  - #15457 tenant ownership on agentbots
  - #15145 rerun agent document access check
- #15446 thinking switch (component portion; provider policy lives in
internal/llm)
  - #15426 Invoke URL/proxy SSRF + DNS pin + no-redirects
  - #15238 agentbot thinking-logs beta endpoint
  - #14589 UserFillUp SSE event propagation
  - #14890 anonymous webhook opt-in
- #15068 PipelineChunker new component (text/file_ref/parser_id
dispatch; file-format extraction is a follow-up)

40 files, +2355 / -58 lines. 33 new tests, all targeted package suites
pass (1721 + 4 skipped); 1 pre-existing flaky test unrelated.
2026-06-30 16:28:48 +08:00

96 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Package component implements the RAGFlow agent canvas components
// in Go following the 5-tier porting strategy (T1T5; see
// docs/develop/agent-go-port-design.md §4.1).
//
// Component is the runtime contract every RAGFlow component
// implements; it is a richer interface than
// internal/agent/runtime.Component (which is the minimal Invoke-only
// surface canvas needs at build time). Any concrete *Component here
// satisfies runtime.Component structurally, which is how the canvas
// builder consumes a registered component via
// runtime.DefaultFactory().
//
// ParamError and ErrNotImplemented are aliased from runtime so the
// canvas builder and the component implementations share the same
// types without a cycle.
package component
import (
"context"
"ragflow/internal/agent/runtime"
)
// Component is the runtime contract every RAGFlow component implements.
// Mirrors the Python ComponentBase.invoke / invoke_async surface
// (agent/component/base.py:365, 408, 422) plus a Stream variant for SSE
// output (the Message component).
//
// Inputs() and Outputs() return parameter metadata for tooling / docs /
// graph introspection — name → human description. Not used at runtime.
//
// Any value implementing this interface also satisfies the smaller
// runtime.Component interface (Invoke only), so the canvas builder
// can consume a *Component via runtime.DefaultFactory() without any
// extra adaptation.
type Component interface {
// Name returns the registered component name (e.g. "LLM", "Agent",
// "Switch"). Case-insensitive lookup — the registry normalizes input.
Name() string
// Invoke runs the component synchronously. inputs is the resolved
// parameter map (variable references already substituted by the canvas
// engine). Returns the output map; components should put their public
// outputs at top-level keys.
Invoke(ctx context.Context, inputs map[string]any) (map[string]any, error)
// Stream is the streaming variant. The default implementation may
// return a buffered channel that emits the same payload as Invoke, then
// closes — components that natively stream (LLM, Message) override.
// May return (nil, nil) for non-streaming components.
Stream(ctx context.Context, inputs map[string]any) (<-chan map[string]any, error)
// Inputs returns parameter metadata: param_name → description.
Inputs() map[string]string
// Outputs returns output metadata: param_name → description.
Outputs() map[string]string
}
// ParamBase is the optional parameter validation/serialization surface.
// Components that need validation can embed *BaseParam (below) or implement
// this directly. Components that don't need it (e.g. ExitLoop) can omit.
//
// Mirrors agent/component/param_base.py:ComponentParamBase (Python).
type ParamBase interface {
// Update copies conf into the receiver, validating types. Used by
// editors / APIs that hand-craft a params map.
Update(conf map[string]any) error
// Check performs deep validation (required fields, value ranges).
// Called once before Invoke — returning an error aborts the run.
Check() error
// AsDict returns the params as a plain map for serialization / debug.
AsDict() map[string]any
}
// ErrNotImplemented aliases runtime.ErrNotImplemented so component-side
// code (and the canvas builder it interoperates with) share a single
// sentinel value.
var ErrNotImplemented = runtime.ErrNotImplemented
// ParamError aliases runtime.ParamError. Existing code that constructs
// &ParamError{Field: ..., Reason: ...} continues to work; the value
// it produces is the same type runtime.SetDefaultFactory consumers see.
type ParamError = runtime.ParamError
// BeOutput wraps a single output value into the canonical
// {"content": v} frame downstream components (Message, VariableAggregator)
// consume. Mirrors agent/component/base.py:ComponentBase.be_output
// (restored by PR #16363 after the agent refactor dropped it). Most
// components can just return `map[string]any{"content": v}` inline,
// but this helper keeps the wrapper construction in one place so
// error/empty paths can produce a uniform output shape without
// duplicating the literal everywhere.
func BeOutput(v any) map[string]any {
return map[string]any{"content": v}
}