Documentation
¶
Overview ¶
Package serve is the importable serve band: the config→listener composition that turns a loaded configuration into a running Harbor Protocol server.
Distinct from internal/server ¶
internal/server is the Protocol server's request-handling core (scope authorizers, bootstrap handler, search-scope adapters). This package sits ABOVE it: it assembles the runtime (via internal/runtime/assemble), mounts the Protocol surfaces (via BuildMux), binds the listener, and owns the serve/close lifecycle. In short — internal/server answers requests; this package composes the process that listens for them.
One constructor, production-shaped by construction ¶
Boot REQUIRES a non-nil auth-validator factory: identity is mandatory, so a nil factory is a loud construction error, never an unauthenticated listener. Boot mounts ONLY the surfaces every caller shares. Dev-only surfaces (the bootstrap-token endpoint, draft scaffolding, the token-rotate surface, the Console static build, fixture seeding, the mock-LLM snapshot override) are composed CALLER-SIDE through the injection seams on Options — the extra pre-CORS routes, the auth-surface builder, the LLM-snapshot builder, and the post-boot hook. The dev signer never reaches this package.
Lifecycle ¶
Boot returns a Handle whose Serve binds the listener and runs until ctx cancels, and whose Close drains every subsystem in reverse dependency order. On any boot error every already-opened subsystem is Closed before returning.
cmd/harbor/session_ensurer.go — adapts the concrete sessions.Registry to the protocol.SessionEnsurer seam.
The Protocol ControlSurface owns the create-on-first-use behaviour on `start` but must not import the sessions package (it depends only on the error-only `protocol.SessionEnsurer` interface). This adapter lives at the cmd/harbor wiring boundary — the one place allowed to know both the concrete registry and the Protocol surface — and translates the registry's lifecycle sentinels into the protocol-side sentinels the surface's error mapper understands.
Index ¶
- Variables
- func BootDeclaredMCPServerNames(cfg *config.Config) []string
- func BootDeclaredMCPServerSet(cfg *config.Config) map[string]struct{}
- func InstanceID(prefix string) string
- func MCPAddStdioAllowlist(cfg *config.Config) []string
- type AuthSurfaceBuilder
- type AuthValidatorFactory
- type BuiltMux
- type Enricher
- func (e *Enricher) Cost(_ context.Context, _ identity.Identity, _ string) prototypes.TaskCostRollup
- func (e *Enricher) ParentSession(_ context.Context, _ identity.Identity, _ string) prototypes.TaskParentSessionRef
- func (e *Enricher) PlannerSnapshot(_ context.Context, _ identity.Identity, _ string) *prototypes.TaskPlannerSnapshotRef
- func (e *Enricher) Trajectory(_ context.Context, _ identity.Identity, taskID string) *prototypes.TaskTrajectoryRef
- type ExtraRoutesFunc
- type Handle
- type LLMSnapshotBuilder
- type MCPConnectionAttacher
- type MCPConnectionDetacher
- type MuxInput
- type Options
- type PostBootFunc
- type PostBootHandles
- type RouteMount
- type RunLoopDriver
- type RunLoopDriverOptions
- type SessionEnsurerAdapter
- type TenantOverrideResolver
Constants ¶
This section is empty.
Variables ¶
var ErrAuthValidatorFactoryRequired = errors.New("serve: auth-validator factory is required (identity is mandatory; nil is never an unauthenticated listener)")
ErrAuthValidatorFactoryRequired is returned by Boot when Options carries a nil AuthValidatorFactory. Identity is mandatory: the serve band never stands up an unauthenticated listener. Callers compare via errors.Is.
var ErrRunLoopDriverMisconfigured = errors.New("dev: per-task RunLoop driver missing a mandatory dependency")
ErrRunLoopDriverMisconfigured fires when NewRunLoopDriver is called with a nil bus / RunLoop / planner. Driver invariant: all three are mandatory.
Functions ¶
func BootDeclaredMCPServerNames ¶
BootDeclaredMCPServerNames returns the names of every MCP server declared in the boot yaml (`tools.mcp_servers[].name`) — the set the remove verb rejects and the run-start reconcile never detaches (boot-declared servers are not revisioned state).
func BootDeclaredMCPServerSet ¶
BootDeclaredMCPServerSet returns the boot-declared MCP server names as a set for the run-start reconcile's O(1) skip check.
func InstanceID ¶
InstanceID mints a stable-per-process instance identifier of the form "<prefix>-<hostname>" (bare prefix when the hostname is unavailable). A Console attached to multiple Runtimes keys each attachment by it. Shared by every production serve caller so the id shape stays uniform.
func MCPAddStdioAllowlist ¶
MCPAddStdioAllowlist projects the operator's stdio allowlist out of config for the runtime add-connection gate. A nil block yields a nil allowlist (fail-closed — every stdio add is rejected).
Types ¶
type AuthSurfaceBuilder ¶
type AuthSurfaceBuilder func(red audit.Redactor, bus events.EventBus, logger *slog.Logger) (*auth.RotateSurface, error)
AuthSurfaceBuilder builds the optional token-rotate surface after the runtime is assembled (it needs the redactor + bus the assembly produces). The dev caller injects a builder that closes over its dev signer; the production caller leaves it nil (no in-runtime token issuer).
type AuthValidatorFactory ¶
type AuthValidatorFactory func(ctx context.Context, cfg *config.Config, red audit.Redactor, bus events.EventBus, logger *slog.Logger) (auth.Validator, error)
AuthValidatorFactory builds the Protocol auth validator from the loaded config plus the assembled redactor / bus / logger. The production caller injects a JWKS-backed factory; the dev caller injects one built from its ephemeral dev signer. It is REQUIRED — a nil factory fails Boot loud.
func NewJWKSAuthValidatorFactory ¶
func NewJWKSAuthValidatorFactory() AuthValidatorFactory
NewJWKSAuthValidatorFactory returns THE production auth-validator factory: it projects the operator's identity config onto a JWKS-backed Validator (URL or file source), wiring the assembled redactor / bus / logger. The initial JWKS fetch runs synchronously inside the projection, so a bad source fails the boot loud. Every production serve caller (the serve subcommand and the external-serving facade) injects this one factory — a second hand-rolled copy is the drift this shared constructor exists to prevent.
type BuiltMux ¶
type BuiltMux struct {
// Mux is the transports mux the caller mounts under /v1/.
Mux *http.ServeMux
// FlowRegistry is the empty registry the flows surface serves. Nil when
// the flows surface was not mounted (no artifact store / task registry).
FlowRegistry *flow.Registry
}
BuiltMux is the result of BuildMux: the mounted Protocol mux plus the flow registry the flows surface serves (the caller seeds the same registry).
type Enricher ¶
type Enricher struct {
// contains filtered or unexported fields
}
Enricher is the production tasks.get Enricher for the dev stack. It provides parent-session / cost / planner-snapshot enrichment from in-memory runtime state, plus trajectory projection.
safe for concurrent reuse: the enricher is immutable after construction — the trajectory accessor is a pure function (no mutable receiver state).
func NewEnricher ¶
func NewEnricher(trajectoryFn func(tasks.TaskID) *planner.Trajectory) *Enricher
NewEnricher builds the tasks.get Enricher over a trajectory accessor. The accessor is a pure function (the run-loop driver's TrajectoryByTaskID), so the returned Enricher is safe for concurrent reuse.
func (*Enricher) Cost ¶
func (e *Enricher) Cost(_ context.Context, _ identity.Identity, _ string) prototypes.TaskCostRollup
Cost returns a zero-valued cost rollup — cost aggregation is deferred to the `llm.cost.recorded` event stream.
func (*Enricher) ParentSession ¶
func (e *Enricher) ParentSession(_ context.Context, _ identity.Identity, _ string) prototypes.TaskParentSessionRef
ParentSession returns a zero-valued ref — the parent-session card is populated by the projector from the task identity when no enricher backfills it.
func (*Enricher) PlannerSnapshot ¶
func (e *Enricher) PlannerSnapshot(_ context.Context, _ identity.Identity, _ string) *prototypes.TaskPlannerSnapshotRef
PlannerSnapshot returns nil — planner-checkpoint references are deferred to the checkpoint store.
func (*Enricher) Trajectory ¶
func (e *Enricher) Trajectory(_ context.Context, _ identity.Identity, taskID string) *prototypes.TaskTrajectoryRef
Trajectory projects the planner's in-memory reasoning trace onto the Protocol wire. Steps with empty ReasoningTrace are filtered out. Returns nil when the task's trajectory is unavailable (evicted or the run-loop didn't store one).
type ExtraRoutesFunc ¶
ExtraRoutesFunc mounts caller-side pre-CORS routes and returns any closers they registered. Called after the boot's validator and bind address are known and before the CORS wrap. On error, the closers accumulated up to the failing step MUST still be returned — Boot appends them to its rollback chain before inspecting the error, so a partially-mounted seam never leaks an already-constructed subsystem.
type Handle ¶
type Handle struct {
// Cfg / Bus are exported so a supervising caller (the dev hot-reload
// loop) can read the reload policy and publish reload lifecycle events.
Cfg *config.Config
Bus events.EventBus
// contains filtered or unexported fields
}
Handle is the running serve band a successful Boot returns. Serve binds the listener and runs until ctx cancels; Close drains every subsystem in reverse dependency order.
func Boot ¶
Boot reads the config, opens every subsystem, composes the Protocol surface, and returns a Handle whose Serve binds the listener. On any error every already-opened subsystem is Closed before returning.
func (*Handle) BindAddr ¶
BindAddr reports the address the listener is (or will be) bound to. After Serve binds an ephemeral port it reflects the OS-assigned address. Internally synchronized — safe to call while Serve runs.
func (*Handle) Close ¶
Close runs every subsystem's Close in reverse dependency order. Idempotent: the closer slice is drained exactly once; a second Close is a no-op.
type LLMSnapshotBuilder ¶
type LLMSnapshotBuilder func(cfg *config.Config) (*llm.ConfigSnapshot, error)
LLMSnapshotBuilder projects the loaded config onto the LLM ConfigSnapshot the runtime opens the client with. The dev caller injects a builder that runs the mock-LLM gate and overrides the driver when the escape hatch fired; a nil builder uses the default llm.SnapshotFromConfig projection.
type MCPConnectionAttacher ¶
type MCPConnectionAttacher struct {
// contains filtered or unexported fields
}
MCPConnectionAttacher implements agentcfgprotocol.ConnectionAttacher by reusing the boot-time mcpdrv.Attach lifecycle (dial → initialize → discover → register) against the LIVE catalog + registry + bus. It owns a mutex-guarded closer chain so a runtime-added server's transport drains on stack teardown.
Concurrent reuse: the collaborators (catalog / registry / bus / logger / defaultIdentity) are set once at construction; the only mutable state is the closers slice, guarded by mu (documented internally-synchronised).
func NewMCPConnectionAttacher ¶
func NewMCPConnectionAttacher(catalog tools.ToolCatalog, registry *mcpdrv.Registry, bus events.EventBus, logger *slog.Logger, defaultIdentity identity.Identity, oauthProviders map[string]toolauth.OAuthProvider) *MCPConnectionAttacher
NewMCPConnectionAttacher builds the production attacher. catalog, registry, and bus are mandatory (mcpdrv.Attach validates them too). oauthProviders may be nil when no provider is declared.
func (*MCPConnectionAttacher) Attach ¶
func (a *MCPConnectionAttacher) Attach(ctx context.Context, req agentcfgprotocol.AttachRequest) error
Attach drives the real MCP attach for one runtime-added connection. The operator-supplied auth Headers flow to the live transport ONLY (the agent-config service never persists them). A partial-attach failure is drained by mcpdrv.Attach's own closer-chain handling; this method merges the per-add closers into its master chain under the lock so teardown drains the subprocess. An auth-required condition is surfaced by wrapping agentcfgprotocol.ErrAuthRequired so the service parks on the unified pause/resume primitive.
type MCPConnectionDetacher ¶
type MCPConnectionDetacher struct {
// contains filtered or unexported fields
}
MCPConnectionDetacher implements projection.ConnectionDetacher against the LIVE catalog + registry. Concurrent reuse: the collaborators are set once at construction; the type holds no mutable state (the registry + catalog own their own synchronisation).
func NewMCPConnectionDetacher ¶
func NewMCPConnectionDetacher(catalog tools.ToolCatalog, registry *mcpdrv.Registry, logger *slog.Logger) *MCPConnectionDetacher
NewMCPConnectionDetacher builds the production detacher. catalog and registry are mandatory (the reconcile is a no-op without them).
func (*MCPConnectionDetacher) AttachedSources ¶
func (d *MCPConnectionDetacher) AttachedSources(_ context.Context) []string
AttachedSources returns the source ids currently live in the MCP registry. NOTE: Registry.SourceIDs is a PROCESS-GLOBAL enumeration — correct for the single-agent dev wiring, but the future multi-agent attach leg must scope the attached set to the reconciling agent (see the projection.ConnectionDetacher interface doc).
func (*MCPConnectionDetacher) Detach ¶
func (d *MCPConnectionDetacher) Detach(ctx context.Context, source string) error
Detach deregisters the source's tools from the catalog (when the catalog supports source deregistration — the optional CatalogSourceDeregisterer companion) and from the MCP registry, closing its transport gracefully. An already-gone source is a no-op (ErrServerNotFound is swallowed — idempotent).
type MuxInput ¶
type MuxInput struct {
Cfg *config.Config
Surface *protocol.ControlSurface
Bus events.EventBus
// Redactor / Logger / Metrics feed every surface's audit + posture legs.
Redactor audit.Redactor
Logger *slog.Logger
Metrics *telemetry.MetricsRegistry
// LLMSnapshot is the resolved snapshot the posture provider projects.
LLMSnapshot llm.ConfigSnapshot
// Core subsystem handles.
Tasks tasks.TaskRegistry
Sessions *sessions.Registry
Agents *agentregistry.Registry
Artifacts artifacts.ArtifactStore
Memory memory.MemoryStore
Catalog tools.ToolCatalog
Coordinator pauseresume.Coordinator
MCPRegistry *mcpdrv.Registry
MCPToolContext *mcpconsole.ToolContextStore
State state.StateStore
Skills skills.SkillStore
// Control-plane handles.
AgentConfig agentcfg.Registry
AgentConfigID string
SessionOverlay sessionoverlay.Store
RunsStore *runsprotocol.Store
// RunLoopDriver backs the tasks.get trajectory enricher. Nil leaves
// tasks reads un-enriched (a stack without a run loop).
RunLoopDriver *RunLoopDriver
OAuthProviders map[string]toolauth.OAuthProvider
// Governance handles. TenantOverridePolicy backs governance.set/get
// tenant overrides; KeyRotator backs governance.rotate_key. Both are
// built caller-side (the policy is shared with the run-loop driver; the
// rotator's lifecycle is the assembly's).
TenantOverridePolicy *governance.TenantOverridePolicy
KeyRotator *llm.ProviderKeyRotator
ValidModels []string
// MCPAttacher backs agent_config.add_mcp_connection. Built caller-side so
// its Close joins the caller's closer chain; nil leaves the add verb
// unwired.
MCPAttacher agentcfgprotocol.ConnectionAttacher
MCPStdioAllowlist []string
BootDeclaredMCP []string
// Auth. Validator nil mounts the transports WithoutValidator (the
// explicit test-kit opt-out); AuthSurface nil leaves auth.rotate_token
// un-mounted (the production posture — no in-runtime token issuer).
Validator auth.Validator
AuthSurface *auth.RotateSurface
// Posture stamps.
DisplayName string
InstanceID string
BuildVersion string
BuildCommit string
// TopologyAvailable advertises the topology.snapshot capability (true
// only when the caller wired a topology accessor onto the surface).
TopologyAvailable bool
}
MuxInput carries the assembled subsystem handles and the caller-side posture stamps BuildMux mounts the Protocol surface over. Every handle is optional except the ControlSurface and the bus: a nil handle leaves the corresponding surface un-mounted (the route then 404s), exactly as the two callers already behave under their skip/absence paths.
type Options ¶
type Options struct {
ConfigPath string
// Config, when non-nil, is used directly instead of loading and
// validating ConfigPath — the entry point for a caller that already
// holds a validated (or programmatically-built) configuration.
// Boot re-runs the full-binary Validate on it so a hand-built config
// cannot bypass validation. When both Config and ConfigPath are set
// Config wins; when Config is nil ConfigPath is loaded.
Config *config.Config
Port int
BindAddr string
Logger *slog.Logger
Stderr io.Writer
SubcommandLabel string
// PreferConfigBindAddr opts into honoring the operator-configured
// `server.bind_addr` (which may name a non-loopback interface) when no
// explicit BindAddr override is given. ONLY the production serve caller
// sets it. The dev/console callers leave it false so they stay
// loopback-only on 127.0.0.1:<Port> — a dev boot against a serve-shaped
// yaml must never expose the dev-token stack off-box.
PreferConfigBindAddr bool
// AuthValidatorFactory is REQUIRED (nil fails Boot loud).
AuthValidatorFactory AuthValidatorFactory
// MCPDefaultIdentity is the identity a boot-time / runtime-added MCP
// connection dials under.
MCPDefaultIdentity identity.Identity
// DisplayName / InstanceID stamp the posture surface's runtime.info.
DisplayName string
InstanceID string
// BuildVersion / BuildCommit stamp runtime.info's build identity.
BuildVersion string
BuildCommit string
// DevAllowMock stamps the Serve start log's dev_allow_mock attribute —
// the dev caller sets it when the mock escape hatch fired so an operator
// reading the boot line sees the dev-only posture. A stamp only; the mock
// gate itself is caller policy inside BuildLLMSnapshot.
DevAllowMock bool
// RegisterCatalog forwards a compiled-tool registrar onto the
// assembly's pre-policy catalog seam (assemble.Options.RegisterCatalog):
// a tool it registers is wrapped with its declared approval / OAuth /
// policy shell before the run loop can dispatch it. Nil is a no-op —
// the stock serve caller passes nil; an external serving binary passes
// its agent's RegisterTools.
RegisterCatalog func(catalog tools.ToolCatalog) error
// Caller-side injection seams (all optional).
BuildLLMSnapshot LLMSnapshotBuilder
BuildAuthSurface AuthSurfaceBuilder
ExtraRoutes ExtraRoutesFunc
PostBoot PostBootFunc
}
Options bundles the inputs Boot consumes. ConfigPath (not a pre-loaded config) is carried so a hot-reload supervisor re-reads the file on each reboot by re-calling Boot with the same Options.
type PostBootFunc ¶
type PostBootFunc func(ctx context.Context, h PostBootHandles) error
PostBootFunc runs after the listener + surfaces are composed but before Serve. The dev caller uses it to seed fixture entities.
type PostBootHandles ¶
type PostBootHandles struct {
Sessions *sessions.Registry
Agents *agentregistry.Registry
Tasks tasks.TaskRegistry
Artifacts artifacts.ArtifactStore
Memory memory.MemoryStore
Tools tools.ToolCatalog
Flows *flow.Registry
Bus events.EventBus
Logger *slog.Logger
}
PostBootHandles carries the assembled subsystem handles the post-boot hook receives (the dev caller's fixture seeder writes through them).
type RouteMount ¶
type RouteMount struct {
Router *http.ServeMux
Validator auth.Validator
Bus events.EventBus
Redactor audit.Redactor
Logger *slog.Logger
// BindAddr is the resolved listen address (the bootstrap handler puts it
// in its connection envelope).
BindAddr string
}
RouteMount is handed to the ExtraRoutes seam so a caller can mount pre-CORS routes (draft scaffolding, the bootstrap-token endpoint, the Console static build) with access to the boot's validator, bus, and bound address. The caller returns any closers its routes registered (a draft store's Close).
type RunLoopDriver ¶
type RunLoopDriver struct {
// contains filtered or unexported fields
}
RunLoopDriver subscribes to `task.spawned` and drives a RunLoop per spawned foreground task. The driver is constructed by bootDevStack and Closed during stack teardown.
func NewRunLoopDriver ¶
func NewRunLoopDriver(opts RunLoopDriverOptions) (*RunLoopDriver, error)
NewRunLoopDriver validates the opts and returns a stopped driver. Call Start before serving; call Close to drain.
func (*RunLoopDriver) Close ¶
func (d *RunLoopDriver) Close(_ context.Context) error
Close cancels the subscription, waits for the subscribe-loop to drain, then waits for every in-flight RunLoop goroutine to return. Idempotent: a second Close walks no-ops. The supplied ctx is accepted for the closer-signature compatibility (closeFns takes a ctx); the driver's drain has its own bounded shape (every RunLoop observes d.subCtx cancellation and returns within one drain boundary). A pathological RunLoop that holds ctx-cancellation indefinitely would block Close; the dev cmd's serve loop applies the Server.ShutdownGracePeriod ceiling at the http boundary, so a blocked Close eventually surfaces as a graceless exit.
func (*RunLoopDriver) SessionOverridesStore ¶
func (d *RunLoopDriver) SessionOverridesStore() *runsprotocol.Store
SessionOverridesStore returns the pending-override Store the driver consumes at run start. It is the seam a caller wires the runs.set_overrides service to so a set reaches the run; exposed so a caller can assert the two share one Store.
func (*RunLoopDriver) Start ¶
func (d *RunLoopDriver) Start(ctx context.Context) error
Start opens the admin-scoped subscription and launches the subscribe-loop goroutine. Idempotent: a second Start is a no-op. The supplied ctx anchors the subscription's lifetime — when ctx cancels (e.g. boot was aborted before Close), the subscription cancels along with it.
func (*RunLoopDriver) TrajectoryByTaskID ¶
func (d *RunLoopDriver) TrajectoryByTaskID(taskID tasks.TaskID) *planner.Trajectory
TrajectoryByTaskID returns a defensive SNAPSHOT of a run's trajectory (its Query + a copy of the append-only Steps slice), or nil when the task's trajectory has been evicted or never existed. Safe for an out-of-band Protocol reader (the Enricher on a tasks.get) to call while the run is IN-FLIGHT: the snapshot is taken under the run's per-run trajMu — the SAME lock the steering RunLoop holds around each per-step append — so the returned Steps slice never observes a mid-append slice header (the data race the Enricher would otherwise hit against the run loop). Only the fields the Enricher reads (Query + Steps) are copied; the trajectory's shared maps are deliberately NOT aliased into the snapshot.
type RunLoopDriverOptions ¶
type RunLoopDriverOptions struct {
Logger *slog.Logger
Bus events.EventBus
RunLoop *steering.RunLoop
Planner planner.Planner
Tasks tasks.TaskRegistry // mandatory: the FSM the driver advances on Run exit
TaskKind tasks.TaskKind // KindForeground at V1; the driver spawns RunLoops for this kind
// driveBackground widens the driver to ALSO
// drive KindBackground tasks — the ones a planner-emitted SpawnTask
// creates. False (the default / legacy test path) keeps the
// foreground-only behaviour. Recursion is bounded at the spawn site
// by the dev executor's absolute_max_spawn_depth cap, not here.
DriveBackground bool
// RunContext consumer wiring. All three of
// memory / skillsDirectory / planningHints are OPTIONAL: a dev
// stack that did not open the respective subsystem hands nil; the
// driver projects the corresponding RunContext field to nil and
// the planner omits the wrapper. The skills
// surface is the `skills.Directory` — the bounded,
// pinned-then-recent, capability-filtered `<skills_context>`
// producer (the directory carries its own MaxEntries cap; the
// pre-111d SkillStore.Search + skillsContextMax pair is deleted).
Memory memory.MemoryStore
MemoryRecall memory.RecallSettings
SkillsDirectory *skills.Directory
PlanningHints *planner.PlanningHints
// tool dispatch + Catalog projection +
// Trajectory. The tool catalog is the shared catalog the rest of
// the dev stack already populated (in-process tools, MCP-discovered
// tools, etc.). MaxStepsRunLoop caps the runloop's outer step
// counter (separate from the planner-internal cap that goes onto
// react via PlannerConfig.MaxSteps).
Catalog tools.ToolCatalog
Executor steering.ToolExecutor
MaxStepsRunLoop int
// operator-declared GrantedScopes
// threaded into the per-run catalog view's CatalogFilter. Tools
// whose AuthScopes exceed this set are invisible to the planner.
// Nil / empty list means no scopes granted (the existing latent
// default before the plumb-through).
GrantedScopes []string
// the artifact store the multimodal
// materializer reads from. Required only when `task.InputArtifactIDs`
// is non-empty (text-only tasks never touch the store). A nil
// store with input artifacts on the task degrades gracefully —
// the materializer emits text-stub-only references the LLM
// routes via the catalog.
ArtifactStore artifacts.ArtifactStore
// trajectory compression. `tokenBudget`
// projects onto RunSpec.Base.Budget.TokenBudget (the per-run
// runtime budget — a run option, never
// planner state); `compression` is the assembly-built
// planner.CompressionRunner the runloop invokes at each step
// boundary when the budget is non-zero. Both zero/nil (the
// default) = compression off, byte-identical behaviour.
TokenBudget int
Compression *planner.CompressionRunner
// the per-agent attachment disposition policy
// decoded from `multimodal.disposition` (the middle precedence
// layer of the disposition resolution). Zero value = no agent
// policy; the runtime default applies.
DispositionPolicy planner.DispositionPolicy
// tenantOverrides resolves an admin-set tenant default for the run's
// LLM parameters at run start (model / extra-instructions /
// temperature / max-tokens / reasoning-effort). OPTIONAL — a nil
// resolver means "no tenant defaults to apply" (the run uses the
// agent/config defaults). When supplied, the driver reads it ONCE per
// run and pins the resolved snapshot into the run's RunContext so the
// swap lands on this run (next-turn relative to the admin's set), never
// mid-flight.
TenantOverrides TenantOverrideResolver
// sessionOverrides is the in-process pending-override Store the
// `runs.set_overrides` Service writes into. The driver Consumes the
// session's pending override at run start (one-shot) and composes it
// OVER the tenant default (session › tenant › config). OPTIONAL — a
// nil Store means "no session overrides" (the run uses tenant/config
// only). It is the SAME Store handed to the runs Service so a set and
// the consume meet.
SessionOverrides *runsprotocol.Store
// agentConfig resolves the agent's active config revision at run start
// (the agent-config control plane). OPTIONAL — a nil registry means
// "no agent-config projection" (the run uses every directory-visible
// skill). When supplied with a non-empty agentConfigID, the run reads
// the active revision ONCE at run start and pins the resolved
// skills-set into the per-run projection so a config edit applies on
// the NEXT run (next-turn-only), never mid-flight.
AgentConfig agentcfg.Registry
AgentConfigID string
// sessionOverlay resolves the SESSION-scoped safe-subset overlay (the
// non-admin lower tier) at run start: the session's user prompt layer,
// narrow-only source/tool disables (UNIONED into the admin exclusion set
// — can only narrow, never widen), and ephemeral personal skills. Keyed
// by the REAL (tenant, user, session) triple, so it is session-isolated.
// OPTIONAL — nil means "no session overlay" (the run uses the admin agent
// config only). The SAME store the session-safe Protocol verbs write into.
SessionOverlay sessionoverlay.Store
// runCompletionHook is the static `runtime.hooks.run_completion`
// projection (nil when unset). At run start the driver resolves the
// effective hook via the shared projection (agent-config over this yaml
// over none) and pins it into the RunSpec, so an edit lands next-run.
RunCompletionHook *steering.CompletionHookSpec
// connectionDetacher drives the DETACH leg of run-start reconciliation:
// at run start the driver detaches every MCP server that is attached but
// no longer declared by the agent's active config revision (a removed
// connection, or a rollback past an add), so the next run's projected
// catalog excludes it. OPTIONAL — nil means no reconcile (the
// backward-compatible path). Injected at the cmd/harbor boundary (it
// imports the concrete MCP driver; this driver stays driver-agnostic).
ConnectionDetacher projection.ConnectionDetacher
// bootDeclaredMCP is the set of boot-declared (yaml) MCP server names the
// reconcile MUST NEVER detach (they are not revisioned state). Nil/empty
// when no yaml server is declared.
BootDeclaredMCP map[string]struct{}
// namingDefault is the static `runtime.naming` fleet-default auto-naming
// policy; the driver resolves the effective policy per run (agent-config
// over this yaml over off). Opt-in, default off.
NamingDefault config.RuntimeNamingConfig
// sessionTitler is the session-registry seam the auto-naming trigger
// writes/reads through (RecordCompletedTurn / AutoNamingState /
// SetTitleAuto). The same *sessions.Registry the sessions Protocol routes
// project over. Nil ⇒ no auto-naming trigger even when a policy resolves.
SessionTitler steering.SessionTitler
// namingLLM is the run's wrapped LLM client the ONE naming Complete call
// flows through (governance/safety via ctx identity). Nil ⇒ no auto-naming
// trigger.
NamingLLM steering.NamingCompleter
}
RunLoopDriverOptions bundles the dependencies the driver consumes. Bus + RunLoop + Planner + TaskRegistry are all mandatory; a nil any of them returns ErrRunLoopDriverMisconfigured from NewRunLoopDriver. The TaskRegistry is what the driver calls MarkRunning / MarkComplete / MarkFailed on to advance the FSM (closes issue #123).
type SessionEnsurerAdapter ¶
type SessionEnsurerAdapter struct {
// contains filtered or unexported fields
}
SessionEnsurerAdapter wraps a *sessions.Registry as a protocol.SessionEnsurer. Immutable after construction; the wrapped registry is itself concurrency-safe, so the adapter is too.
func NewSessionEnsurerAdapter ¶
func NewSessionEnsurerAdapter(reg *sessions.Registry) *SessionEnsurerAdapter
NewSessionEnsurerAdapter builds the adapter. A nil registry would be a wiring bug; the caller (cmd_dev bootDevStack) always passes the constructed registry.
func (*SessionEnsurerAdapter) EnsureSession ¶
EnsureSession implements protocol.SessionEnsurer. It calls the registry's create-on-first-use EnsureOpen and translates the registry's sentinels into the protocol-side sentinels so the ControlSurface's mapSessionEnsureError reaches a stable Protocol code. An unclassified error is wrapped (not swallowed) so the surface's catch-all maps it to CodeRuntimeError (CLAUDE.md §5 — fail loud).
type TenantOverrideResolver ¶
type TenantOverrideResolver interface {
Get(ctx context.Context, tenant string) (governance.TenantOverrideSpec, bool, error)
}
TenantOverrideResolver is the narrow read seam the run loop uses to resolve an admin-set tenant default at run start. The `*governance.TenantOverridePolicy` concrete satisfies it.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package external is the production-only entry point behind the public sdk/server facade: it turns a validated configuration into a running Harbor Protocol server that an external Go binary can host, with its compiled in-process tools wrapped at the pre-policy catalog seam.
|
Package external is the production-only entry point behind the public sdk/server facade: it turns a validated configuration into a running Harbor Protocol server that an external Go binary can host, with its compiled in-process tools wrapped at the pre-policy catalog seam. |