router

package
v0.4.2 Latest Latest
Warning

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

Go to latest
Published: Sep 9, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package router decides which model does which job.

The provider package speaks one dialect to every runtime; this package is the policy on top: which tier handles a task, what happens when a tier is missing, and what may cross the network.

Index

Constants

View Source
const DefaultRetentionDays = 30

DefaultRetentionDays is long enough that a monthly consolidation still has its evidence, short enough that a laptop running the daemon continuously does not quietly fill up.

Variables

View Source
var ErrNoModel = errors.New("no model available for this tier")

ErrNoModel means a runtime is answering but none of its models can serve the tier that was asked for.

Like ErrNoRuntime it is a condition rather than a failure, and it exists for the same reason: a caller that treats "you have no reasoning model" the same as "the database is corrupt" either refuses to run on a small machine or reports a real fault as a quiet zero. Callers test for it instead of matching on the message.

View Source
var ErrNoRuntime = errors.New("no local model runtime found — start Ollama, LM Studio, Jan or Msty")

ErrNoRuntime means nothing answered on any known local port.

It is a condition, not a failure. Generation genuinely needs a model, but retrieval degrades to lexical and the whole continuity surface — checkpoint, resume, note_progress, before_you_try — needs no model at all. Callers that only want those should carry on with a nil Router rather than refusing to start, so this is a sentinel they can test for instead of matching on the message.

Functions

func ConfigPath

func ConfigPath(vault string) string

func DeleteKey

func DeleteKey(ref string) error

func GetKey

func GetKey(ref string) (string, error)

func Preview

func Preview(text string, findings []Finding, maxChars int) string

Preview renders what the user sees before approving egress for a tier.

func Redact

func Redact(text string, findings []Finding) string

Redact replaces the given findings with typed placeholders. Placeholders are stable per value, so a note mentioning one person twice stays coherent to the model rather than reading as two different people.

func SetKey

func SetKey(ref, secret string) error

Types

type Capability

type Capability struct {
	Model string
	// Loads is false for models that list but fail to load — a corrupt or
	// version-mismatched pull, which is common enough to be worth catching
	// rather than letting it surface as a pipeline error at 3am.
	Loads bool
	// StructuredOutput is false when the endpoint ignores or rejects
	// response_format. Extraction must not be routed here.
	StructuredOutput bool
	Err              string
}

Capability is what a probe actually established about a model, as opposed to what the runtime advertised.

type Config

type Config struct {
	Tiers map[string]TierConfig `json:"tiers"`
	// ExtraBlocked apps appended to the capture blocklist.
	ExtraBlocked []string `json:"extra_blocked,omitempty"`
	// Think is how much a reasoning model reasons before answering: "off", "low",
	// "medium", or "high". Empty means "low". This is the knob that keeps a
	// thinking model from spending its whole budget thinking and returning an
	// empty answer over the /v1 endpoint.
	Think string `json:"think,omitempty"`
	// RetentionDays is how long raw capture events are kept before the daemon
	// drops them. Rollups have already extracted anything worth keeping by then,
	// which is the whole point of the two-tier design.
	//
	// This existed as an idea long before it existed as a number: capture polls
	// every five seconds, and until now nothing scheduled a prune, so raw events
	// accumulated for as long as the daemon ran. 0 means the default; a negative
	// value means keep everything, for someone who has decided that on purpose.
	RetentionDays int `json:"retention_days,omitempty"`
}

func Defaults

func Defaults() *Config

Defaults match what a stock Ollama install tends to have. Anything missing is resolved at probe time rather than failing here.

func Load

func Load(vault string) (*Config, error)

func (*Config) Retention

func (c *Config) Retention() (days int, forever bool)

Retention resolves the configured window, in days. The second return says whether events are kept forever, which callers must report rather than present as a number.

func (*Config) Save

func (c *Config) Save(vault string) error

type Finding

type Finding struct {
	Kind  string // email, phone, key, path, url
	Value string
	Start int
	End   int
}

func Scan

func Scan(text string) []Finding

Scan finds candidates worth showing the user before egress. It deliberately over-reports: a false positive costs one glance, a false negative leaks.

type Router

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

func New

func New(cfg *Config, vault string) (*Router, error)

func (*Router) Available

func (r *Router) Available() []string

Available reports every configured tier and what it resolved to, for `brain doctor`. The first-run greeting is built from this.

func (*Router) Local

func (r *Router) Local() *provider.Provider

func (*Router) Model

func (r *Router) Model(t Tier) (string, error)

Model resolves a tier to a model that exists. A tier whose configured model is missing or broken degrades to the next tier down with a warning, rather than failing the whole pipeline — a rollup running on a smaller model is worth more than no rollup.

func (*Router) ModelFor

func (r *Router) ModelFor(t Tier, needSchema bool) (string, error)

ModelFor is Model plus a structured-output requirement. Extraction callers use this so a model that cannot honour a schema is never handed a schema.

func (*Router) Probe

func (r *Router) Probe(model string) Capability

Probe verifies a model can actually run and whether it honours constrained decoding. Cheap enough to run at startup; cached for the process lifetime.

func (*Router) SetVerbose

func (r *Router) SetVerbose(v bool)

type Tier

type Tier int

Tier orders jobs by how much capability they need. Small local models are perfectly good at narrow extraction and hopeless at synthesis, so the work is split rather than pointed at one model.

const (
	// T0 embeddings.
	T0 Tier = iota
	// T1 per-event classify and extract.
	T1
	// T2 rollup, entity resolution, interactive ask.
	T2
	// T3 weekly synthesis and hard queries. Cloud, opt-in.
	T3
)

func ParseTier

func ParseTier(s string) (Tier, error)

func (Tier) String

func (t Tier) String() string

type TierConfig

type TierConfig struct {
	Model string `json:"model"`
	// BaseURL empty means "use the discovered local runtime".
	BaseURL string `json:"base_url,omitempty"`
	// KeyRef names a Keychain entry. Keys are never stored in the config file
	// and never in the vault.
	KeyRef string `json:"key_ref,omitempty"`
	// CloudOK gates network egress for this tier. Off until the user confirms
	// a redaction preview.
	CloudOK bool `json:"cloud_ok,omitempty"`
}

TierConfig binds a tier to a model and, for T3, to a remote endpoint.

Jump to

Keyboard shortcuts

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