feat: foundations — canonical types, Parse grammar, env DSNs, health, chains

Phase 1 of the majordomo build:
- llm/ canonical contract (messages, parts, tools, capabilities, streaming,
  Model/Provider, error classification)
- health/ clock-injected tracker (threshold bench, exponential capped
  cooldown, reset-on-success)
- root Registry + Parse (verbatim model ids, inline recursive alias
  expansion with cycle detection, chain dedup), LLM_* env-DSN providers
  (go-llm parity: lazy fallback + eager LoadEnv), health-aware chain
  executor behind the Model interface
- provider/fake scriptable test provider; hermetic test suite incl. the
  trailing-thinking chain and foreman:// env loading
- ADRs 0001-0008, CLAUDE.md, README (honest matrix), CI workflow,
  docs/phase-1-design.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 12:35:23 +02:00
parent 3025044817
commit dcd004289f
42 changed files with 3863 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
package llm
import "context"
// Model is the canonical generation interface. A Model may be a single
// provider-bound target or a failover chain — the two are interchangeable
// and callers never branch on which they got.
type Model interface {
// Generate performs one request/response round trip.
Generate(ctx context.Context, req Request, opts ...Option) (*Response, error)
// Stream performs one request with incremental delivery.
Stream(ctx context.Context, req Request, opts ...Option) (Stream, error)
// Capabilities reports what this model supports. For chains this is the
// head element's capabilities (the preferred target); per-attempt media
// normalization always uses the actual target's capabilities.
Capabilities() Capabilities
}
// ModelOption configures a Model at construction time (Provider.Model).
type ModelOption func(*ModelConfig)
// ModelConfig carries per-model construction settings shared by all
// providers.
type ModelConfig struct {
// Capabilities, when non-nil, overrides the provider's default
// capabilities for this model.
Capabilities *Capabilities
}
// ApplyModelOptions folds options into a config.
func ApplyModelOptions(opts []ModelOption) ModelConfig {
var cfg ModelConfig
for _, opt := range opts {
opt(&cfg)
}
return cfg
}
// WithCapabilities overrides the provider's default capabilities for one
// model (e.g. a vision-capable tag on an otherwise text-only provider).
func WithCapabilities(caps Capabilities) ModelOption {
return func(cfg *ModelConfig) { cfg.Capabilities = &caps }
}
// Provider mints Models bound to one backend. Implementations translate the
// canonical Request/Response to and from their wire format and enforce their
// declared Capabilities.
type Provider interface {
// Name is the registry identifier used in "provider/model" specs.
Name() string
// Model returns a Model bound to the given id. The id is whatever the
// backend accepts — majordomo passes it through verbatim and never
// validates it against a catalog.
Model(id string, opts ...ModelOption) (Model, error)
}