Documentation
¶
Overview ¶
Package bindings assembles host capabilities into a script.Env for any script.Runtime implementation (jsrt, luart, etc.).
Purpose ¶
bindings does two things: (1) expose Go-side interfaces as script-callable globals/tables; (2) provide common presets to reduce boilerplate. Business policy (who may call what, quotas, auth) belongs to the caller: pass pre-trimmed dependencies or tighten capabilities via Options. VM-agnostic: bindings never parses syntax; Lua/JS are handled by script sub-packages.
Dependency constraint ¶
bindings depends only on workflow and llm — never on graph. Type aliases in the graph package (graph.Board = workflow.Board, etc.) allow graph/node/scriptnode to pass *graph.Board to bindings without conversion.
Layering model ¶
- core: BindingFunc, BuildEnv — language-agnostic assembly primitives.
- atomic bridges: one file per host capability, named New<Domain>Bridge; the injected global is typically the lowercase domain name (board, fs, …).
- expr subsystem: compiled-program LRU cache (see expr.go), transparent to scripts.
- presets: common combinations as convenience functions; presets express "default assembly" and do not replace caller-level policy.
- LLM bridge (bridge_llm.go): calls llm.RunRound / llm.StreamRound and returns structured results to scripts; does NOT write to the board (scripts control data flow explicitly). Supports blocking llm.run() and iterator-based llm.stream() modes.
Directory layout ¶
doc.go package-level design notes (this file) core.go BindingFunc, BuildEnv bridge_board.go workflow board variables bridge_stream.go streaming events (backed by workflow.StreamCallback) bridge_expr.go expr-lang expressions (eval) bridge_shell.go sandboxed subprocesses (allowlist via ShellOption) bridge_fs.go workspace files bridge_runtime.go sub-script execScript (inherits parent bindings) run.go run metadata (run_id, task_id) bridge_llm.go NewLLMBridge → global "llm" (run / stream); delegates to llm.RunRound / llm.StreamRound tools.go tool.Registry (deny-by-default, explicit allowlist or AllowAll) expr.go LRU cache and evalExpr (unexported) presets.go AgentStepBindings and other combinations *_test.go table-driven / jsrt integration tests
Global naming convention ¶
Script global names match the name returned by BindingFunc: board, stream, expr, shell, fs, runtime (injected by scriptnode), run, tools, llm. Methods exposed by each bridge use lowercase_underscore style, consistent with existing script conventions.
Integration with Graph / workflow ¶
- Graph ScriptNode: composes board+stream+expr+runtime in ExecuteBoard, then appends shell/fs per node type (see graph/node/scriptnode).
- Workflow Agent: uses presets or manual composition; add NewLLMBridge when LLM access is needed.
Checklist for adding a new bridge ¶
- Are closure-captured dependencies thread-safe and context-cancellable?
- Are defaults least-privilege (e.g. tools deny-by-default, shell recommends allowlist)?
- Are return values stable on the script side (map field names, multi-return mapping in luart/jsrt)?
- Should it be included in a preset? Document which execution paths it is compatible with.
Testing conventions ¶
Integration tests use jsrt to execute small script snippets that verify bindings; pure Go logic (e.g. LRU) is covered by *_test.go unit tests.
Index ¶
- func BuildEnv(ctx context.Context, config map[string]any, fns ...BindingFunc) *script.Env
- func RuntimeBinding(ctx context.Context, rt script.Runtime, parentBindings map[string]any) map[string]any
- type AgentStepOptions
- type BindingFunc
- func AgentStepBindings(o AgentStepOptions) []BindingFunc
- func NewBoardBridge(board *workflow.Board) BindingFunc
- func NewExprBridge() BindingFunc
- func NewFSBridge(ws workspace.Workspace) BindingFunc
- func NewLLMBridge(opts LLMBridgeOptions) BindingFunc
- func NewRunBridge(opts RunBridgeOptions) BindingFunc
- func NewShellBridge(runner workspace.CommandRunner, opts ...ShellOption) BindingFunc
- func NewStreamBridge(stream workflow.StreamCallback, nodeID string) BindingFunc
- func NewToolBridge(reg *tool.Registry, opts ...ToolBridgeOption) BindingFunc
- type LLMBridgeOptions
- type RunBridgeOptions
- type ShellOption
- type ToolBridgeOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AgentStepOptions ¶
type AgentStepOptions struct {
Board *workflow.Board
// TaskID / RunID mirror workflow.Request fields; RunID overrides board when non-empty.
TaskID string
RunID string
ToolRegistry *tool.Registry
// AllowedTools is passed to WithAllowedToolNames when non-empty (ignored if ToolRegistry is nil).
AllowedTools []string
}
AgentStepOptions selects common bindings for one workflow agent step (Lua/JS), without pulling in LLM streaming (add NewStreamBridge at the call site if needed).
type BindingFunc ¶
BindingFunc creates a named binding for script execution. The returned name becomes the global variable name in the script scope, and the value is typically a map[string]any of callable Go functions.
func AgentStepBindings ¶
func AgentStepBindings(o AgentStepOptions) []BindingFunc
AgentStepBindings returns a typical binding set: board, run, expr, optional tools. Caller still supplies config + script.Runtime-specific globals (signal, etc.).
func NewBoardBridge ¶
func NewBoardBridge(board *workflow.Board) BindingFunc
NewBoardBridge exposes workflow board variables as global "board".
func NewExprBridge ¶
func NewExprBridge() BindingFunc
NewExprBridge exposes expr-lang as global "expr" (eval).
func NewFSBridge ¶
func NewFSBridge(ws workspace.Workspace) BindingFunc
NewFSBridge exposes workspace file ops as global "fs".
func NewLLMBridge ¶
func NewLLMBridge(opts LLMBridgeOptions) BindingFunc
NewLLMBridge exposes LLM calls to scripts as global "llm":
llm.run() — blocking, returns full result
llm.run({ temperature: 0.2 }) — with config overrides
llm.stream() — returns iterator { next, token, finish }
Neither mode writes to the board; the script controls what to do with results.
func NewRunBridge ¶
func NewRunBridge(opts RunBridgeOptions) BindingFunc
NewRunBridge exposes read-only run metadata to scripts as global "run":
- get_run_id() string
- get_task_id() string
func NewShellBridge ¶
func NewShellBridge(runner workspace.CommandRunner, opts ...ShellOption) BindingFunc
NewShellBridge exposes shell execution as global "shell".
func NewStreamBridge ¶
func NewStreamBridge(stream workflow.StreamCallback, nodeID string) BindingFunc
NewStreamBridge exposes streaming as global "stream" (emit).
func NewToolBridge ¶
func NewToolBridge(reg *tool.Registry, opts ...ToolBridgeOption) BindingFunc
NewToolBridge exposes tool execution to scripts as global "tools":
- call(name, argumentsJSON) -> { content, is_error, tool_call_id }
- list() -> []string (names the script is allowed to call)
Security: by default no tool is callable until WithAllowedToolNames or WithToolAllowAll is set.
type LLMBridgeOptions ¶
type LLMBridgeOptions struct {
Stream workflow.StreamCallback
EventID string
Resolver llm.LLMResolver
Registry *tool.Registry
// BaseConfig is merged with overrides passed from the script.
BaseConfig llm.RoundConfig
// ReadMessages returns the messages to send to the LLM.
// The caller controls where messages come from (board, parameters, etc.).
// When nil, an empty slice is used.
ReadMessages func(ctx context.Context) []model.Message
}
LLMBridgeOptions configures NewLLMBridge.
type RunBridgeOptions ¶
type RunBridgeOptions struct {
Board *workflow.Board
// TaskID is optional (e.g. workflow.Request.TaskID).
TaskID string
// RunID, if non-empty, is returned by get_run_id instead of reading the board.
RunID string
}
RunBridgeOptions configures NewRunBridge (workflow / agent metadata on the board).
type ShellOption ¶
type ShellOption func(*shellConfig)
ShellOption configures a shell bridge.
func WithAllowedCommands ¶
func WithAllowedCommands(cmds ...string) ShellOption
WithAllowedCommands restricts the shell bridge to only execute the specified commands. When set, any command not in the list is rejected.
type ToolBridgeOption ¶
type ToolBridgeOption func(*toolBridgeConfig)
ToolBridgeOption configures NewToolBridge.
func WithAllowedToolNames ¶
func WithAllowedToolNames(names ...string) ToolBridgeOption
WithAllowedToolNames restricts script-visible tools; names must match registry entries.
func WithToolAllowAll ¶
func WithToolAllowAll() ToolBridgeOption
WithToolAllowAll allows calling any tool registered in the registry. Use only when scripts are fully trusted.