routers

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Jun 11, 2026 License: Apache-2.0 Imports: 5 Imported by: 0

Documentation

Overview

Package routers ships Harbor's runtime routing surface — Phase 14 of the runtime kernel chain (RFC §6.1).

Three router shapes:

  • PredicateRouter: ordered list of (predicate, target) pairs. The first predicate that matches selects the target.
  • UnionRouter: payload-tag dispatch (string discriminator → target). Used for sum-type-shaped payloads (e.g. planner Decision variants).
  • RoutePolicy: explicit-target override. Set on an envelope's Meta["route_policy"] to bypass predicate / union routing and route to a specific target. The planner-driven path.

Routers wrap as engine.Node via AsNode(name); they consume the Phase 10 NodeContext.Emit surface to write into the chosen branch. A router does NOT transform payloads — it decides where to send them.

Index

Constants

View Source
const MetaKeyRoutePolicy = "route_policy"

MetaKeyRoutePolicy is the Envelope.Meta key under which RoutePolicy can ride. Centralised so callers and tests reference one symbol rather than the string literal.

Variables

View Source
var ErrRouteNotFound = errors.New("routers: no branch matched and no default configured")

ErrRouteNotFound — predicate / union routing produced no target and the router has no Default. Wraps with a human-readable suffix indicating which router (predicate vs union) and what went wrong. Phase 11's RunError will subsume this error code; Phase 14 ships the typed sentinel so callers can errors.Is.

Functions

This section is empty.

Types

type PredicateBranch

type PredicateBranch struct {
	Predicate func(messages.Envelope) bool
	Target    engine.NodeRef
}

PredicateBranch is one (predicate, target) pair on a PredicateRouter. Predicates are evaluated in slice order; the first one returning true selects the target.

type PredicateRouter

type PredicateRouter struct {
	Branches []PredicateBranch
	Default  *engine.NodeRef
}

PredicateRouter selects the first branch whose predicate matches the incoming envelope. Branch order matters; the Default target catches "no match" (or returns ErrRouteNotFound when nil).

Routing happens via RoutePolicy: the router-as-Node returns the envelope unchanged but writes the chosen target into Meta[MetaKeyRoutePolicy]. The engine's worker honors that policy when it emits to the router's outgoing channels (every adjacency receives the envelope, but only the targeted node will see it via downstream filtering — see "Honoring RoutePolicy in adjacency" below).

For Phase 14, the recommended adjacency shape is:

router → branchA, branchB, branchC

where every branch node guards its NodeFunc with a RoutePolicy check at entry (returning a no-op envelope if the policy does not target it). This keeps the engine's worker loop unchanged from Phase 10 — routers are pure node-level concerns.

A more elegant adjacency shape (engine-level RoutePolicy honoring) is reserved for a follow-up phase that extends Phase 10's worker; Phase 14 stays out of engine.go to avoid colliding with the parallel Phase 11 fork.

func (*PredicateRouter) AsNode

func (r *PredicateRouter) AsNode(name string) engine.Node

AsNode wraps the router as an engine.Node. The wrapped NodeFunc examines the envelope, evaluates predicates in order, writes the chosen target into Meta[MetaKeyRoutePolicy], and returns the envelope unchanged. The engine's adjacency map then routes the output to all branches; each branch's NodeFunc reads Meta and drops the envelope if it isn't the targeted branch.

Returns a Node whose Name is `name` and whose Func wraps the router. AllowCycle defaults to false — routers are downstream-only.

func (*PredicateRouter) Select

Select evaluates the router's predicates and returns the chosen target. Returns ErrRouteNotFound when no branch matches and no default is set. A nil receiver is rejected with ErrRouteNotFound rather than panicking — defensive coding, since a misconfigured graph might construct a PredicateRouter with no branches.

type RoutePolicy

type RoutePolicy struct {
	// ExplicitTarget names a single downstream node by name. nil means
	// "no override."
	ExplicitTarget *engine.NodeRef
}

RoutePolicy is the override mechanism that bypasses predicate / union routing when set on an envelope's Meta["route_policy"]. Useful for planner-driven branch selection where the planner already knows the target (e.g. a deterministic-planner step that names the next node explicitly).

ExplicitTarget is a *engine.NodeRef so a nil pointer means "no override; defer to predicate/union routing." A non-nil pointer pinning a specific target overrides whatever the wrapped router would have selected.

func FromMeta

func FromMeta(meta map[string]any) (RoutePolicy, bool)

FromMeta extracts a RoutePolicy from env.Meta if present. Returns (zero, false) when Meta is nil, the key is absent, or the value is not a RoutePolicy. Callers use the bool to decide whether to honor the override; the zero value is a safe fall-through.

type UnionRouter

type UnionRouter struct {
	Tag      func(any) string
	Branches map[string]engine.NodeRef
	Default  *engine.NodeRef
}

UnionRouter dispatches based on payload tag — a string discriminator the Tag function extracts from env.Payload. The result keys into Branches; Default catches the unknown-tag case.

Used for sum-type-shaped payloads. Example:

router := &UnionRouter{
    Tag: func(p any) string {
        switch p.(type) {
        case planner.CallTool:    return "call_tool"
        case planner.Finish:      return "finish"
        }
        return ""
    },
    Branches: map[string]engine.NodeRef{
        "call_tool": toolDispatcher.Ref(),
        "finish":    finalizer.Ref(),
    },
    Default: nil, // unknown tag → ErrRouteNotFound
}

func (*UnionRouter) AsNode

func (r *UnionRouter) AsNode(name string) engine.Node

AsNode wraps the router as an engine.Node. The wrapped NodeFunc extracts the tag, looks up the branch, writes the chosen target into Meta[MetaKeyRoutePolicy], and returns the envelope unchanged.

func (*UnionRouter) Select

func (r *UnionRouter) Select(env messages.Envelope) (engine.NodeRef, error)

Select extracts the payload tag and returns the matching branch. A nil Tag function or a nil receiver returns ErrRouteNotFound. An empty / unknown tag falls back to Default; nil Default returns ErrRouteNotFound with the offending tag in the wrapped message.

Jump to

Keyboard shortcuts

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