runtime

package
v0.4.9 Latest Latest
Warning

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

Go to latest
Published: Oct 7, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package runtime assembles and owns a deployment, its event routing, and transport-neutral sessions.

Index

Constants

This section is empty.

Variables

View Source
var ErrBuilderUsed = errdefs.Conflictf("runtime Builder has already been used")

ErrBuilderUsed reports an attempted registration or Build after a Builder's single construction attempt has started.

Functions

func PatternAgentLifecycle added in v0.1.11

func PatternAgentLifecycle() event.Pattern

PatternAgentLifecycle matches every runtime agent lifecycle event.

func PatternRuntimeRebuild added in v0.1.14

func PatternRuntimeRebuild() event.Pattern

PatternRuntimeRebuild matches every runtime generation reload event.

func SubjectAgentRegistered added in v0.1.11

func SubjectAgentRegistered(id string) event.Subject

SubjectAgentRegistered returns the subject for a successful dynamic registration:

runtime.agent.<id>.registered

func SubjectAgentRemoved added in v0.1.11

func SubjectAgentRemoved(id string) event.Subject

SubjectAgentRemoved returns the subject for a successful dynamic removal:

runtime.agent.<id>.removed

func SubjectRuntimeRebuildCompleted added in v0.1.14

func SubjectRuntimeRebuildCompleted() event.Subject

SubjectRuntimeRebuildCompleted is published after a Reload atomically swapped the current generation.

func SubjectRuntimeRebuildFailed added in v0.1.14

func SubjectRuntimeRebuildFailed() event.Subject

SubjectRuntimeRebuildFailed is published when a Reload aborts before any swap; the previous generation keeps serving.

func SubjectRuntimeRebuildStarted added in v0.1.14

func SubjectRuntimeRebuildStarted() event.Subject

SubjectRuntimeRebuildStarted is published when a Reload begins building the next generation.

Types

type AgentLifecycleEvent added in v0.1.11

type AgentLifecycleEvent struct {
	AgentID     string `json:"agent_id"`
	Name        string `json:"name,omitempty"`
	Description string `json:"description,omitempty"`
}

AgentLifecycleEvent is the payload of runtime.agent.* lifecycle events. It intentionally carries only identity and card summary, so the envelope stays small.

type AgentRegistry added in v0.1.11

type AgentRegistry struct {
	// contains filtered or unexported fields
}

AgentRegistry is the runtime-live, concurrency-safe agent view. Dynamically registered agents live in its own map; statically deployed agents are served as a read-only fallback from the deployment result. It implements session.InstanceResolver, so the session manager resolves both kinds through one seam.

func (*AgentRegistry) Agent added in v0.1.11

func (r *AgentRegistry) Agent(id string) (*agent.Agent, bool)

Agent resolves a dynamically registered agent first, then falls back to the deployment snapshot.

func (*AgentRegistry) AgentNames added in v0.1.11

func (r *AgentRegistry) AgentNames() []string

AgentNames returns the sorted union of dynamically registered and deployed agent names.

func (*AgentRegistry) Close added in v0.1.11

func (r *AgentRegistry) Close() error

Close is retained for API compatibility but is a no-op: dynamic instances are owned by the generation that adopted them and closed by Generation.close, so closing them here would double-close.

func (*AgentRegistry) Delete added in v0.1.11

func (r *AgentRegistry) Delete(id string) (dynamicAgentEntry, bool)

Delete removes and returns a dynamically registered entry. Deployed agents are not affected and return ok=false.

func (*AgentRegistry) Dynamic added in v0.1.14

func (r *AgentRegistry) Dynamic(id string) (*agent.Agent, bool)

Dynamic returns the live instance registered under id, or ok=false. It is the dynamic-only view used by per-generation resolvers.

func (*AgentRegistry) DynamicNames added in v0.1.24

func (r *AgentRegistry) DynamicNames() []string

DynamicNames implements delegation.TargetSource: the sorted dynamic registration ids.

func (*AgentRegistry) Entries added in v0.1.14

func (r *AgentRegistry) Entries() map[string]dynamicAgentEntry

Entries returns a defensive copy of every dynamic registration.

func (*AgentRegistry) Put added in v0.1.11

func (r *AgentRegistry) Put(id string, entry dynamicAgentEntry) error

Put registers a dynamically registered agent, rejecting duplicates.

func (*AgentRegistry) Replace added in v0.1.14

func (r *AgentRegistry) Replace(
	entries map[string]dynamicAgentEntry,
	deployed *deploy.Result,
)

Replace atomically swaps the dynamic view and the deployed fallback. It is the Reload commit path; callers must hold lifecycleMu.

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

Builder transactionally assembles one Runtime over a resource registry. It is single-use.

func NewBuilder

func NewBuilder(reg *resource.Registry) *Builder

NewBuilder creates a Runtime builder over a resource registry. The registry must already hold every resource factory the document references (event bus, checkpoint store, tool assemblies, engines, hooks, ...).

func (*Builder) Build

func (b *Builder) Build(ctx context.Context, doc deploy.Document) (*Runtime, error)

Build constructs one fully started Runtime. A Builder may be used for exactly one Build attempt.

func (*Builder) WithExternalResource added in v0.2.6

func (b *Builder) WithExternalResource(ext ExternalResource) error

WithExternalResource injects one caller-owned dependency value. The name and contract must be declared in the deployment document's runtime.external_deps before Build. It is rejected after Build starts.

func (*Builder) WithExternalResources added in v0.2.6

func (b *Builder) WithExternalResources(externals []ExternalResource) error

WithExternalResources injects caller-owned dependency values. See WithExternalResource.

func (*Builder) WithHostFactory

func (b *Builder) WithHostFactory(decorator HostFactoryDecorator) error

WithHostFactory installs a decorator over the runtime's base host factory. It is rejected when nil or after Build starts.

func (*Builder) WithLoader

func (b *Builder) WithLoader(loader *resource.Loader) error

WithLoader installs the deployment-level loader used to materialize {"file":…} / {"embed":…} settings subtrees and agent engine/hook settings. It is rejected after Build starts.

func (*Builder) WithResolver added in v0.2.8

func (b *Builder) WithResolver(resolver *resource.ReferenceResolver) error

WithResolver registers custom schemes for inline ${scheme:ref} strings in every settings subtree (resources, agent engines, agent hooks) before a factory decodes them. Expansion semantics are identical to deploy.WithResolver, which this option passes through unchanged; see that option for the authoritative merge rules. It is rejected when nil, when already set, or after Build starts.

func (*Builder) WithResultHostFactory added in v0.1.14

func (b *Builder) WithResultHostFactory(decorator ResultHostFactoryDecorator) error

WithResultHostFactory installs a decorator that runs after WithHostFactory with access to the fully assembled deployment. It is rejected when nil or after Build starts.

type Config

type Config struct {
	// EventBus names the deployment resource providing event.Bus.
	EventBus string
	// CheckpointStore names the deployment resource providing
	// agent.CheckpointStore; empty keeps checkpoints as a host no-op.
	CheckpointStore string
	// Sessions configures the runtime-owned session manager.
	Sessions       SessionConfig
	DynamicCatalog *DynamicCatalogConfig
	// ExternalDeps declares caller-owned dependency values that the
	// application injects through Builder.WithExternalResource.
	ExternalDeps []ExternalDependency
}

Config is the strictly decoded deploy.Document.Runtime subtree.

func DecodeConfig

func DecodeConfig(ctx context.Context, doc deploy.Document) (Config, error)

DecodeConfig strictly decodes and validates the runtime subtree.

type DynamicCatalogConfig

type DynamicCatalogConfig struct {
	Tools map[string]string
}

DynamicCatalogConfig maps agent IDs to tool.Assembly resource names; the reserved "default" key is the fallback for agents without an explicit entry. The injection policy itself lives in each tool.Assembly's dynamic settings — the runtime only wires the assembly and creates per-session views.

type ExternalDependency added in v0.2.6

type ExternalDependency struct {
	// Name is the resource-ref name used in document deps, e.g. "db".
	Name string `json:"name"`
	// Contract is the expected DepSpec.Type of consuming factories,
	// e.g. "db.Pool".
	Contract string `json:"contract"`
}

ExternalDependency declares one caller-owned dependency in the runtime section of a deployment document.

func (ExternalDependency) Validate added in v0.2.6

func (d ExternalDependency) Validate() error

Validate checks one external dependency declaration.

type ExternalResource added in v0.2.6

type ExternalResource struct {
	ExternalDependency
	Value any
}

ExternalResource pairs one external dependency declaration with the caller-owned value that satisfies it.

func (ExternalResource) Validate added in v0.2.6

func (e ExternalResource) Validate() error

Validate checks the declaration and rejects nil values.

type Generation added in v0.1.14

type Generation struct {
	// contains filtered or unexported fields
}

Generation is one immutable deployment snapshot plus the services derived from it: the built result, the host factory, the per-agent resolver, and the dynamic tool catalog. A generation is built as a value and swapped into the Runtime atomically; it is never mutated while current except for the one-time freeze performed by Reload (adopting the dynamic instances that retire with it).

type HostFactoryDecorator

type HostFactoryDecorator func(session.HostFactory) (session.HostFactory, error)

HostFactoryDecorator wraps the runtime's built-in base host factory. The decorator receives the base factory (event publishing, interrupts, ask-user, checkpointing) and MUST delegate anything it does not override back to it — the canonical shape is agent.HostFuncs{Inner: base, ...}.

type RegisterAgentOption added in v0.1.11

type RegisterAgentOption func(*registerOptions) error

RegisterAgentOption configures one dynamic agent registration.

func WithToolAssembly added in v0.1.11

func WithToolAssembly(resourceName string) RegisterAgentOption

WithToolAssembly names a built tool.Assembly resource used as the new agent's dynamic catalog entry. It requires the deployment to have a dynamic_catalog section.

type ReloadOption added in v0.1.14

type ReloadOption func(*reloadOptions) error

ReloadOption configures one Reload call. The option set is reserved for future policy (e.g. dropping vs failing on re-bind); v1 has no options.

type ReloadResult added in v0.1.14

type ReloadResult struct {
	GenerationID  uint64
	PreviousID    uint64
	ReboundAgents []string
	DrainedAgents []string
}

ReloadResult describes one successful generation swap.

type ResultHostFactoryDecorator added in v0.1.14

type ResultHostFactoryDecorator func(result *deploy.Result, factory session.HostFactory) (session.HostFactory, error)

ResultHostFactoryDecorator wraps the runtime's host factory with access to the fully assembled deployment. It runs after any HostFactoryDecorator, so the deployment-aware layer sits outermost and can expose deployment-built services (e.g. delegation) on every turn host. The result is borrowed only for the duration of the call.

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Runtime owns the complete application object graph built by Builder.

func (*Runtime) Agent added in v0.1.11

func (r *Runtime) Agent(name string) (*agent.Agent, bool)

Agent resolves an agent by name from the live view (dynamically registered first, then the deployment snapshot).

func (*Runtime) AgentNames added in v0.1.11

func (r *Runtime) AgentNames() []string

AgentNames returns the sorted union of deployed and dynamically registered agent names.

func (*Runtime) Attach added in v0.1.5

func (r *Runtime) Attach(
	ctx context.Context,
	pattern event.Pattern,
	sink event.Sink,
	opts ...event.AttachOption,
) (func(), error)

Attach subscribes pattern on the runtime's borrowed event router and delivers matching envelopes to sink until the returned stop function is called, ctx is cancelled, the subscription ends, or the sink returns an error (which detaches that attachment). It is the runtime-level entry point for consumers that want run events without resolving the deployment document's event_bus resource themselves — for example UI sinks subscribing to prompt lifecycle events:

detach, err := app.Attach(ctx, session.PatternPromptRequested(), sink)
defer detach()

The router is owned by the Runtime: Attach fails with NotAvailable after Close, and every attachment is torn down when the Runtime closes. External attachments inherit the bus default backpressure (DropNewest), so a slow consumer drops envelopes instead of blocking the run pipeline; pass event.WithAttachBackpressure to opt into a different policy for a specific subscription.

func (*Runtime) Close

func (r *Runtime) Close() error

Close stops new session work, waits for active turns, and releases all owned objects. Concurrent callers wait for and receive the same aggregate result.

func (*Runtime) Drain added in v0.2.5

func (r *Runtime) Drain(ctx context.Context) error

Drain quiesces the runtime for offline replacement. It is serialized with RegisterAgent / UnregisterAgent / Reload / Close and delegates to the session manager's Drain: new session leases and new Starts on already-open leases are refused, while active turns finish naturally (bounded by ctx). Drain never interrupts running turns; after it returns the runtime stays drained and the caller should Close it once its replacement is ready. A drained Runtime cannot serve new work, so a timed-out Drain may be retried or followed by Close.

func (*Runtime) RegisterAgent added in v0.1.11

func (r *Runtime) RegisterAgent(
	ctx context.Context,
	name string,
	def agent.Definition,
	opts ...RegisterAgentOption,
) (*agent.Agent, error)

RegisterAgent assembles and registers a new agent at runtime: the Definition is run through the same assembly path as deployment (deploy.BindAgent), then the agent becomes resolvable by the session manager. The name must not collide with an existing dynamic agent or a deployed agent (both are Conflict).

RegisterAgent is serialized with UnregisterAgent and Close. After Close it fails with NotAvailable.

func (*Runtime) Reload added in v0.1.14

func (r *Runtime) Reload(
	ctx context.Context,
	doc deploy.Document,
	opts ...ReloadOption,
) (*ReloadResult, error)

Reload transactionally replaces the deployment document with a new generation:

  1. Validates the document and decodes the runtime config.
  2. Builds the new deploy.Result (rollback on failure).
  3. Resolves the new generation's event_bus / checkpoint_store and validates the resume contract. Each generation owns its values, so the document may change their configuration or implementation freely; a reload whose event_bus factory returns the current generation's bus (a shared singleton) is rejected.
  4. Rebuilds the host factory with the same decorator.
  5. Re-binds every dynamic agent against the new result; any failure aborts the whole reload.
  6. Drains sessions of deployed agents removed by the new document.
  7. Atomically swaps the manager epoch and the runtime's current generation; the old generation retires and closes once its in-flight turns drain.

In-flight turns always complete on the generation they started on; the next Start uses the new generation. Reload is serialized with RegisterAgent / UnregisterAgent / Close via lifecycleMu.

func (*Runtime) Resource added in v0.1.14

func (r *Runtime) Resource(name string) (any, bool)

Resource borrows the current generation's built deployment resource value by deployment name. Like Agent, it resolves through the live view: after a Reload it returns the new generation's value, and the retired generation's values are closed with it. Callers borrow the value and must not close it. For values the application must own the lifecycle of (or keep across reloads), construct them outside the runtime and inject them through the resource registry instead.

func (*Runtime) Sessions

func (r *Runtime) Sessions() *session.Manager

Sessions returns the runtime-owned transport-neutral session manager.

func (*Runtime) UnregisterAgent added in v0.1.11

func (r *Runtime) UnregisterAgent(
	ctx context.Context,
	name string,
	opts ...UnregisterAgentOption,
) error

UnregisterAgent removes a dynamically registered agent: new session activity is blocked, live sessions are drained (active turns are allowed to finish, bounded by ctx or WithRemoveTimeout), and the agent's engine and hooks are closed. Unknown names are an idempotent no-op; deployed (static) agents cannot be removed at runtime.

type RuntimeRebuildEvent added in v0.1.14

type RuntimeRebuildEvent struct {
	GenerationID         uint64   `json:"generation_id"`
	PreviousGenerationID uint64   `json:"previous_generation_id,omitempty"`
	ReboundAgents        []string `json:"rebound_agents,omitempty"`
	DrainedAgents        []string `json:"drained_agents,omitempty"`
	Error                string   `json:"error,omitempty"`
}

RuntimeRebuildEvent is the payload of runtime.rebuild.* events.

type SessionConfig

type SessionConfig struct {
	IdleTimeout             time.Duration
	SinkBuffer              int
	SpeculativeBufferEvents int
	SpeculativeBufferBytes  int
	DeliveryConcurrency     int
	MaxSessions             int
	Resume                  bool
}

SessionConfig configures the runtime-owned session manager.

type StreamExportRegistry added in v0.1.30

type StreamExportRegistry struct {
	// contains filtered or unexported fields
}

StreamExportRegistry is the runtime-owned bridge between the serializable stream targets persisted in async delegation records and the runtime's live stream transports.

It implements both halves of the delegation stream contract:

  • Exporter describes sinks the runtime attached to a turn as serializable targets at async submit time. It recognizes sinks that implement delegation.StreamTargetProvider (the registry's conversation sinks do), so decorators wrapping a conversation sink can pass the description through;
  • Resolver re-materializes those targets worker-side when no in-process escrow entry survives.

Resolver is whitelisted by construction: it only accepts the kinds declared by the delegation contract (conversation, bus), and conversation sinks come from the registry's own registered set — never from request data.

Reachability: conversation targets resolve to a live sink registered in the resolving process's registry, so they recover streams when the in-process escrow was lost but do NOT deliver across processes. Bus targets resolve to a named bus and are the kind capable of true cross-process delivery (when the bus transport spans processes).

func NewStreamExportRegistry added in v0.1.30

func NewStreamExportRegistry(buses map[string]event.Bus) *StreamExportRegistry

NewStreamExportRegistry builds a registry over the given whitelist of named event buses. conversations is empty until the UI attaches through RegisterConversation.

func (*StreamExportRegistry) ConversationSink added in v0.1.30

func (r *StreamExportRegistry) ConversationSink(contextID string) (agent.StreamSink, bool)

ConversationSink returns the registered live sink for a conversation, wrapped with its context id so StreamExportRegistry.Exporter can describe it. Turn attachment should use this instance as the SinkSpec.Sink so the async exporter recognizes the destination. ok=false when the conversation is not attached.

func (*StreamExportRegistry) Exporter added in v0.1.30

Exporter implements delegation.StreamTargetExporter: it recognizes sinks that implement delegation.StreamTargetProvider (the registry's conversation sinks do, and decorators may pass the description through) and describes them as conversation targets. All other sinks report ok=false.

func (*StreamExportRegistry) RegisterConversation added in v0.1.30

func (r *StreamExportRegistry) RegisterConversation(contextID string, sink agent.StreamSink)

RegisterConversation attaches a live, conversation-scoped sink that outlives individual turns. UI layers call this when they open a conversation and UnregisterConversation when they detach. Nil sinks are ignored.

func (*StreamExportRegistry) Resolver added in v0.1.30

Resolver implements delegation.StreamTargetResolver with a strict kind whitelist. conversation targets resolve to the registered live sink; bus targets resolve to a fixed forwarder onto the named bus. Unknown kinds are policy-denied; known kinds with unknown ids are not-found or validation errors. No sink is ever constructed from free-form persisted data.

func (*StreamExportRegistry) UnregisterConversation added in v0.1.30

func (r *StreamExportRegistry) UnregisterConversation(contextID string)

UnregisterConversation removes the conversation's sink. Idempotent.

type UnregisterAgentOption added in v0.1.11

type UnregisterAgentOption func(*removeOptions) error

UnregisterAgentOption configures one dynamic agent removal.

func WithRemoveTimeout added in v0.1.11

func WithRemoveTimeout(d time.Duration) UnregisterAgentOption

WithRemoveTimeout bounds how long UnregisterAgent waits for active turns to finish before giving up. On timeout the agent is left in place (registration intact, sessions intact) and the call is retryable.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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