ir

package
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 4, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package ir defines the canonical Intermediate Representation (IR) produced by compiling an AST. The IR is the sole source of truth for the runtime — it is execution-oriented, fully resolved, and independent of the DSL authoring surface.

Index

Constants

View Source
const (
	SessionFresh         = types.SessionFresh
	SessionInherit       = types.SessionInherit
	SessionArtifactsOnly = types.SessionArtifactsOnly
	SessionFork          = types.SessionFork
)
View Source
const (
	RouterFanOutAll  = types.RouterFanOutAll
	RouterCondition  = types.RouterCondition
	RouterRoundRobin = types.RouterRoundRobin
	RouterLLM        = types.RouterLLM
)
View Source
const (
	AwaitNone       = types.AwaitNone
	AwaitWaitAll    = types.AwaitWaitAll
	AwaitBestEffort = types.AwaitBestEffort
)
View Source
const (
	InteractionNone       = types.InteractionNone
	InteractionHuman      = types.InteractionHuman
	InteractionLLM        = types.InteractionLLM
	InteractionLLMOrHuman = types.InteractionLLMOrHuman
)
View Source
const (
	MCPTransportUnknown = types.MCPTransportUnknown
	MCPTransportStdio   = types.MCPTransportStdio
	MCPTransportHTTP    = types.MCPTransportHTTP
	MCPTransportSSE     = types.MCPTransportSSE
)
View Source
const (
	FieldTypeString      = types.FieldTypeString
	FieldTypeBool        = types.FieldTypeBool
	FieldTypeInt         = types.FieldTypeInt
	FieldTypeFloat       = types.FieldTypeFloat
	FieldTypeJSON        = types.FieldTypeJSON
	FieldTypeStringArray = types.FieldTypeStringArray
)

Variables

View Source
var ValidReasoningEfforts = map[string]bool{
	"low":    true,
	"medium": true,
	"high":   true,
	"xhigh":  true,
	"max":    true,
}

ValidReasoningEfforts is the set of accepted reasoning effort levels. Mirrors the Anthropic effort spec (platform.claude.com/docs/en/build-with-claude/effort) and the CLAUDE_CODE_EFFORT_LEVEL env var (code.claude.com/docs/en/model-config). Per-model availability is curated upstream in claw-code-go's ModelEntry; this set is the union across all models.

Functions

func IsTerminalNode

func IsTerminalNode(n Node) bool

IsTerminalNode returns true if the node is a DoneNode or FailNode.

func NodeActiveMCPServers

func NodeActiveMCPServers(n Node) []string

NodeActiveMCPServers returns the ActiveMCPServers list for nodes that support it, or nil.

func NodeInputSchema

func NodeInputSchema(n Node) string

NodeInputSchema returns the InputSchema for nodes that support it, or "".

func NodeOutputSchema

func NodeOutputSchema(n Node) string

NodeOutputSchema returns the OutputSchema for nodes that support it, or "".

func NodePromptRefs

func NodePromptRefs(node Node) []string

NodePromptRefs returns all prompt reference names used by a node.

func NodePublish

func NodePublish(n Node) string

NodePublish returns the Publish field for nodes that support it, or "".

Types

type AgentNode

type AgentNode struct {
	BaseNode
	LLMFields
	SchemaFields
	InteractionFields
	MCP              *MCPConfig // node-level MCP activation/filtering
	ActiveMCPServers []string   // populated after project config resolution
	Publish          string     // persistent artifact name (empty if not set)
	Session          SessionMode
	Tools            []string // tool capability names
	ToolPolicy       []string // per-node tool policy patterns (nil = inherit workflow)
	ToolMaxSteps     int      // max tool-use iterations (0 = not set)
	AwaitMode        AwaitMode
	Compaction       *Compaction // per-node compaction overrides (nil = inherit workflow)
}

AgentNode is an LLM agent node with tools, structured I/O, and optional delegation.

func (*AgentNode) NodeKind

func (n *AgentNode) NodeKind() NodeKind

NodeKind implements Node.

type AwaitMode

type AwaitMode = types.AwaitMode

AwaitMode determines how a convergence point handles multiple incoming branches.

func NodeAwaitMode

func NodeAwaitMode(n Node) AwaitMode

NodeAwaitMode returns the AwaitMode for nodes that support it, or AwaitNone.

type BaseNode

type BaseNode struct {
	ID string // unique identifier (= DSL name)
}

BaseNode provides the common ID field embedded in every concrete node.

func (BaseNode) NodeID

func (b BaseNode) NodeID() string

NodeID implements Node.

type Budget

type Budget struct {
	MaxParallelBranches int
	MaxDuration         string // e.g. "60m"
	MaxCostUSD          float64
	MaxTokens           int
	MaxIterations       int
}

Budget defines execution limits for a workflow.

type Compaction

type Compaction struct {
	Threshold      float64 // 0 = inherit (env / 0.85 default)
	PreserveRecent int     // 0 = inherit (default 4)
}

Compaction overrides the default compaction behavior. Threshold is applied as a fraction of the model's context window (0 means inherit). PreserveRecent caps the number of recent messages kept verbatim (0 means inherit).

type CompileResult

type CompileResult struct {
	Workflow    *Workflow
	Diagnostics []Diagnostic
}

CompileResult holds the compiled IR workflow and any diagnostics.

func Compile

func Compile(file *ast.File) *CompileResult

Compile transforms an AST File into a canonical IR Workflow. In V1, exactly one workflow per file is supported.

func (*CompileResult) HasErrors

func (r *CompileResult) HasErrors() bool

HasErrors returns true if any diagnostic is an error.

type ComputeExpr

type ComputeExpr struct {
	Key string    // output field name
	AST *expr.AST // parsed expression
	Raw string    // original source for diagnostics / unparse
}

ComputeExpr is a single field expression in a ComputeNode.

type ComputeNode

type ComputeNode struct {
	BaseNode
	SchemaFields
	Exprs     []*ComputeExpr // ordered field-name → parsed AST pairs
	AwaitMode AwaitMode
}

ComputeNode evaluates a set of named expressions over the standard reference namespaces (vars, input, outputs, artifacts, loop, run) and returns them as a structured output. It performs no LLM call and no shell-out; expressions are parsed at compile time and re-evaluated on each visit.

func (*ComputeNode) NodeKind

func (n *ComputeNode) NodeKind() NodeKind

NodeKind implements Node.

type DataMapping

type DataMapping struct {
	Key  string // target input field name
	Refs []*Ref // parsed references from the template value
	Raw  string // original template string for debugging
}

DataMapping maps a target input field key to a parsed reference.

type DiagCode

type DiagCode string

DiagCode identifies the kind of compilation diagnostic.

const (
	DiagUnknownNode           DiagCode = "C001" // edge references unknown node
	DiagUnknownSchema         DiagCode = "C002" // node references unknown schema
	DiagUnknownPrompt         DiagCode = "C003" // node references unknown prompt
	DiagBadTemplateRef        DiagCode = "C004" // malformed template reference
	DiagDuplicateLoop         DiagCode = "C005" // conflicting loop definitions
	DiagNoWorkflow            DiagCode = "C006" // no workflow found in file
	DiagMultipleWorkflow      DiagCode = "C007" // multiple workflows (unsupported in V1)
	DiagMissingEntry          DiagCode = "C008" // entry node not found
	DiagMissingModelOrBackend DiagCode = "C018" // agent/judge has neither model nor backend
	DiagDuplicateMCPServer    DiagCode = "C024" // duplicate top-level mcp_server name
	DiagInvalidMCPServer      DiagCode = "C025" // invalid MCP server config
	DiagCodexDiscouraged      DiagCode = "C030" // codex backend is supported but discouraged
	DiagComputeNoExpr         DiagCode = "C039" // compute node has no expressions
	DiagBadExpr               DiagCode = "C040" // expression failed to parse
	DiagDuplicateNodeID       DiagCode = "C041" // two declarations share a node ID
	DiagReservedNodeName      DiagCode = "C042" // user node uses reserved name (done/fail)
)
const (
	DiagSessionAfterConvergence DiagCode = "C009" // session: inherit or fork on convergence point
	DiagMultipleDefaultEdges    DiagCode = "C010" // multiple unconditional edges from same non-fan_out source
	DiagAmbiguousCondition      DiagCode = "C011" // ambiguous conditional edges from same source
	DiagMissingFallback         DiagCode = "C012" // conditional edges with no default fallback
	DiagConditionNotBool        DiagCode = "C013" // when field is not boolean in output schema
	DiagConditionFieldNotFound  DiagCode = "C014" // when field not found in source output schema
	DiagUnreachableNode         DiagCode = "C016" // node unreachable from entry
	DiagHistoryRefNotInLoop     DiagCode = "C017" // outputs.<node>.history but node not in a loop
	DiagUndeclaredCycle         DiagCode = "C019" // cycle without a declared loop (infinite loop risk)
	DiagRoundRobinTooFewEdges   DiagCode = "C020" // round_robin router with fewer than 2 outgoing edges
	DiagLLMRouterTooFewEdges    DiagCode = "C021" // llm router with fewer than 2 outgoing edges
	DiagLLMRouterConditionEdge  DiagCode = "C022" // llm router edge has a 'when' condition
	DiagRouterLLMOnlyProperty   DiagCode = "C023" // LLM-only property on non-llm router
	DiagInvalidReasoningEffort  DiagCode = "C024" // invalid reasoning_effort value
	DiagInvalidLoopIterations   DiagCode = "C026" // loop max_iterations must be >= 1
	DiagDuplicateWithKey        DiagCode = "C028" // duplicate with-mapping key across edges to same target
	DiagUnknownRefNode          DiagCode = "C030" // outputs ref to non-existent node
	DiagRefFieldNotInSchema     DiagCode = "C031" // outputs ref field not in output schema
	DiagRefNodeNoSchema         DiagCode = "C032" // outputs ref field on node without output schema
	DiagUndeclaredVar           DiagCode = "C033" // vars ref to undeclared variable
	DiagInputFieldNotInSchema   DiagCode = "C034" // input ref field not in input schema
	DiagUnknownArtifact         DiagCode = "C035" // artifacts ref to unpublished artifact
	DiagRefNodeNotReachable     DiagCode = "C036" // outputs ref to node not reachable before consumer
	DiagNodeMaxTokensVsBudget   DiagCode = "C037" // node-level max_tokens exceeds workflow.budget.max_tokens
	DiagUnsupportedMCPAuth      DiagCode = "C038" // MCP server Auth.Type not supported (only "oauth2" is wired)
	DiagInvalidCompaction       DiagCode = "C043" // compaction.threshold or compaction.preserve_recent out of range
)

type Diagnostic

type Diagnostic struct {
	Code     DiagCode
	Severity Severity
	Message  string
	NodeID   string
	EdgeID   string
	Hint     string
}

Diagnostic represents a compilation error or warning.

NodeID and EdgeID are best-effort attribution fields used by tooling (the editor renders them as inline badges). They may be empty when the diagnostic is global (e.g. "no workflow"). EdgeID follows the canonical "<from>-><to>" format the editor uses; when multiple edges share endpoints the first matching one wins.

Hint is a one-line, user-facing fix suggestion when one is known. The authoritative documentation still lives in `docs/diagnostics.md`; Hint is for UIs that want a quick tooltip without round-tripping to docs.

func (Diagnostic) Error

func (d Diagnostic) Error() string

type DoneNode

type DoneNode struct {
	BaseNode
	AwaitMode AwaitMode // convergence strategy when multiple branches arrive
}

DoneNode is a terminal success node.

func (*DoneNode) NodeKind

func (n *DoneNode) NodeKind() NodeKind

NodeKind implements Node.

type Edge

type Edge struct {
	From string // source node ID
	To   string // target node ID

	// Condition (optional). Condition is a field name from the source
	// node's output schema. Negated inverts the check. Mutually exclusive
	// with Expression: the compiler chooses one form per edge.
	Condition string
	Negated   bool

	// Expression (optional). When non-nil, this parsed expression replaces
	// Condition/Negated and is evaluated against the source node's output
	// (exposed as `input`/`outputs.<self>`), the run vars, artifacts, and
	// loop/run namespaces.
	Expression    *expr.AST
	ExpressionSrc string // original source string preserved for unparse/debug

	// Loop reference (optional). LoopName references a Loop in Workflow.Loops.
	LoopName string

	// Data mappings (optional). Each entry maps a target input field
	// to a resolved reference expression.
	With []*DataMapping
}

Edge represents a directed transition between two nodes, with optional condition, loop reference, and data mappings.

func (*Edge) IsConditional

func (e *Edge) IsConditional() bool

IsConditional reports whether an edge carries any predicate (simple boolean field or parsed expression). Used by validators and the runtime to distinguish guarded edges from unconditional fallbacks.

type FailNode

type FailNode struct {
	BaseNode
	AwaitMode AwaitMode // convergence strategy when multiple branches arrive
}

FailNode is a terminal failure node.

func (*FailNode) NodeKind

func (n *FailNode) NodeKind() NodeKind

NodeKind implements Node.

type FieldType

type FieldType = types.FieldType

FieldType enumerates the V1 schema field types.

type HumanNode

type HumanNode struct {
	BaseNode
	SchemaFields
	InteractionFields
	Publish      string
	MinAnswers   int    // minimum answers required
	Instructions string // prompt reference for human instructions
	Model        string // model for LLM-based interaction modes
	SystemPrompt string // prompt reference for LLM-based interaction modes
	AwaitMode    AwaitMode
}

HumanNode is a human pause/resume node.

func (*HumanNode) NodeKind

func (n *HumanNode) NodeKind() NodeKind

NodeKind implements Node.

type InteractionFields

type InteractionFields struct {
	Interaction       InteractionMode // interaction handling mode
	InteractionPrompt string          // prompt reference guiding LLM for llm_or_human decisions
	InteractionModel  string          // model for llm/llm_or_human modes (fallback to Model)
}

InteractionFields groups interaction-related fields.

type InteractionMode

type InteractionMode = types.InteractionMode

InteractionMode controls how a node handles user interaction requests. Available on agent, judge, and human nodes.

func NodeInteraction

func NodeInteraction(n Node) InteractionMode

NodeInteraction returns the Interaction field for nodes that support it, or InteractionNone.

type JudgeNode

type JudgeNode struct {
	BaseNode
	LLMFields
	SchemaFields
	InteractionFields
	MCP              *MCPConfig
	ActiveMCPServers []string
	Publish          string
	Session          SessionMode
	Tools            []string
	ToolPolicy       []string // per-node tool policy patterns (nil = inherit workflow)
	ToolMaxSteps     int
	AwaitMode        AwaitMode
	Compaction       *Compaction // per-node compaction overrides (nil = inherit workflow)
}

JudgeNode is a verdict-producing LLM node (typically no tools).

func (*JudgeNode) NodeKind

func (n *JudgeNode) NodeKind() NodeKind

NodeKind implements Node.

type LLMFields

type LLMFields struct {
	Model           string // model identifier (env refs already noted)
	Backend         string // execution backend name (empty = direct LLM call)
	SystemPrompt    string // prompt reference name
	UserPrompt      string // prompt reference name
	MaxTokens       int    // per-node cap on output tokens (0 = backend default)
	ReasoningEffort string // reasoning effort level: "low", "medium", "high", "xhigh", "max"
	Readonly        bool   // when true, node is not considered mutating for workspace safety
}

LLMFields groups fields shared by LLM-capable nodes (Agent, Judge, Router-LLM).

type Loop

type Loop struct {
	Name          string
	MaxIterations int
}

Loop defines a named bounded loop. Multiple edges can reference the same loop; the runtime shares a single counter per loop name.

type MCPAuth

type MCPAuth struct {
	// Type is the authentication scheme. The only supported value is
	// "oauth2"; other values produce a C-code diagnostic.
	Type string

	// AuthURL is the OAuth authorization endpoint the user's browser
	// visits to consent.
	AuthURL string

	// TokenURL is the back-channel endpoint that issues access and
	// refresh tokens.
	TokenURL string

	// RevokeURL is the optional RFC 7009 revocation endpoint.
	RevokeURL string

	// ClientID is the OAuth client identifier registered with the
	// provider.
	ClientID string

	// Scopes is the set of OAuth scopes requested at authorization.
	Scopes []string
}

MCPAuth describes how to authenticate against an MCP server. Only the OAuth2 authorization-code + PKCE flow is wired today; `Type` is reserved for future schemes (bearer, mTLS, ...).

type MCPConfig

type MCPConfig struct {
	AutoloadProject *bool
	Inherit         *bool
	Servers         []string
	Disable         []string
}

MCPConfig represents workflow-level or node-level MCP activation/filtering.

type MCPServer

type MCPServer struct {
	Name      string
	Transport MCPTransport
	Command   string
	Args      []string
	URL       string
	Headers   map[string]string
	Auth      *MCPAuth
}

MCPServer is a reusable MCP server declaration or resolved catalog entry.

type MCPTransport

type MCPTransport = types.MCPTransport

MCPTransport identifies the transport used by an MCP server.

type MermaidView

type MermaidView int

MermaidView controls the level of detail in the generated diagram.

const (
	// MermaidCompact shows nodes with kind icons and simple edge labels.
	MermaidCompact MermaidView = iota
	// MermaidDetailed shows nodes with full metadata and annotated edges.
	MermaidDetailed
	// MermaidFull shows all available metadata including schemas fields,
	// prompts, tools, budget, variables, and loops.
	MermaidFull
)

type Node

type Node interface {
	NodeID() string
	NodeKind() NodeKind
}

Node is the IR node interface. Concrete types: AgentNode, JudgeNode, RouterNode, HumanNode, ToolNode, DoneNode, FailNode.

type NodeKind

type NodeKind int

NodeKind discriminates the type of node.

const (
	NodeAgent   NodeKind = iota // LLM agent
	NodeJudge                   // verdict-producing LLM node
	NodeRouter                  // deterministic routing (no LLM)
	NodeHuman                   // human pause/resume
	NodeTool                    // direct command execution (no LLM)
	NodeCompute                 // deterministic expression evaluation (no LLM, no shell)
	NodeDone                    // terminal: success
	NodeFail                    // terminal: failure
)

func (NodeKind) String

func (k NodeKind) String() string

type Prompt

type Prompt struct {
	Name         string
	Body         string // raw template text
	TemplateRefs []*Ref // references found in the body
}

Prompt is a resolved prompt declaration. TemplateRefs contains all references extracted from the prompt body.

type Ref

type Ref struct {
	Kind RefKind
	Path []string // dotted path segments after the namespace
	Raw  string   // original template expression, e.g. "{{outputs.node.field}}"
}

Ref is a single normalized reference extracted from a template expression. Examples:

{{vars.x}}                → Kind=RefVars, Path=["x"]
{{outputs.node}}          → Kind=RefOutputs, Path=["node"]
{{outputs.node.field}}    → Kind=RefOutputs, Path=["node","field"]
{{input.field}}           → Kind=RefInput, Path=["field"]
{{artifacts.name}}        → Kind=RefArtifacts, Path=["name"]

func ParseRefs

func ParseRefs(s string) ([]*Ref, error)

ParseRefs extracts all {{...}} template references from a string. Returns the parsed Ref values. Returns an error if a template expression is malformed.

type RefKind

type RefKind int

RefKind discriminates the namespace of a reference.

const (
	RefVars      RefKind = iota // {{vars.x}}
	RefInput                    // {{input.field}}
	RefOutputs                  // {{outputs.node}} or {{outputs.node.field}}
	RefArtifacts                // {{artifacts.name}}
	RefLoop                     // {{loop.<name>.iteration}} / .max / .previous_output[.field]
	RefRun                      // {{run.id}}
)

func (RefKind) String

func (rk RefKind) String() string

type RouterMode

type RouterMode = types.RouterMode

type RouterNode

type RouterNode struct {
	BaseNode
	LLMFields              // only populated for RouterLLM mode
	RouterMode  RouterMode // fan_out_all, condition, round_robin, or llm
	RouterMulti bool       // LLM router: select multiple targets (default: one)
}

RouterNode is a routing node with 4 modes: fan_out_all, condition, round_robin, llm. LLMFields are only populated when RouterMode == RouterLLM.

func (*RouterNode) NodeKind

func (n *RouterNode) NodeKind() NodeKind

NodeKind implements Node.

type Schema

type Schema struct {
	Name   string
	Fields []*SchemaField
}

Schema is a resolved schema with its fields.

type SchemaField

type SchemaField struct {
	Name       string
	Type       FieldType
	EnumValues []string // non-nil only if enum constraint present
}

SchemaField is a single field in a schema.

type SchemaFields

type SchemaFields struct {
	InputSchema  string // schema reference name (empty if not set)
	OutputSchema string // schema reference name (empty if not set)
}

SchemaFields groups input/output schema references.

type SessionMode

type SessionMode = types.SessionMode

type Severity

type Severity int

Severity indicates the severity of a diagnostic.

const (
	SeverityError Severity = iota
	SeverityWarning
)

func (Severity) String

func (s Severity) String() string

type ToolNode

type ToolNode struct {
	BaseNode
	SchemaFields
	Command     string // command to execute, may contain {{...}} template refs
	CommandRefs []*Ref // parsed template references in Command (resolved at runtime)
	Session     SessionMode
	AwaitMode   AwaitMode
}

ToolNode executes a shell command directly (no LLM).

func (*ToolNode) NodeKind

func (n *ToolNode) NodeKind() NodeKind

NodeKind implements Node.

type Var

type Var struct {
	Name       string
	Type       VarType
	HasDefault bool
	Default    interface{} // string, int64, float64, or bool
}

Var is a resolved workflow variable with its type and optional default.

type VarType

type VarType int

VarType enumerates variable types.

const (
	VarString VarType = iota
	VarBool
	VarInt
	VarFloat
	VarJSON
	VarStringArray
)

func (VarType) String

func (vt VarType) String() string

type Workflow

type Workflow struct {
	Name           string
	Entry          string             // entry node ID
	Nodes          map[string]Node    // node ID → node
	Edges          []*Edge            // ordered list of edges
	Schemas        map[string]*Schema // schema name → resolved schema
	Prompts        map[string]*Prompt // prompt name → resolved prompt
	Vars           map[string]*Var    // var name → resolved variable
	Loops          map[string]*Loop   // loop name → loop definition
	Budget         *Budget            // workflow budget (nil if not set)
	Compaction     *Compaction        // workflow-level compaction overrides (nil = no override)
	MCP            *MCPConfig         // workflow-level MCP activation/filtering
	DefaultBackend string             // workflow-level default backend (empty = not set)
	ToolPolicy     []string           // workflow-level tool policy patterns (nil = open)
	Interaction    *InteractionMode   // workflow-level default interaction mode (nil = not set)
	Worktree       string             // "auto" runs in a per-run git worktree; "" or "none" runs in-place
	// MCPServers contains the explicit top-level declarations from the .iter file.
	MCPServers map[string]*MCPServer
	// ActiveMCPServers and ResolvedMCPServers are populated after project config
	// resolution, not by the compiler itself.
	ActiveMCPServers   []string
	ResolvedMCPServers map[string]*MCPServer
}

Workflow is the top-level IR unit. It contains everything needed to execute a workflow: resolved nodes, edges, schemas, prompts, vars, loops and budget.

func (*Workflow) ToMermaid

func (w *Workflow) ToMermaid(view MermaidView) string

ToMermaid renders the workflow IR as a Mermaid flowchart string.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL