spec

package
v1.0.0-alpha.13 Latest Latest
Warning

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

Go to latest
Published: May 9, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package spec reads Agentfiles into structured Agentfile values.

Parsing is a two-phase process: a line scanner handles comments, heredocs, and ARG expansion, then each instruction line is parsed by a participle v2 grammar. Semantic validation runs after parsing.

Agentfile (text)
      |
      v
+-------------+
| Line Scanner |  comments, blank lines, # syntax=
+-------------+
      |
      v  (per instruction line)
+-------------+
|  Heredoc    |  extract <<MARKER content
|  Extractor  |
+-------------+
      |
      v
+-------------+
|  ARG        |  ${VAR} substitution
|  Expansion  |
+-------------+
      |
      v
+-------------+
| Participle  |  grammar-based instruction parsing
|  Parser     |  FROM, RUNTIME, MODEL, NAME, CONTEXT,
|             |  CONFIG, BIN, ADD, LABEL, ARG
+-------------+
      |
      v
+-------------+
| Validation  |  FROM first, reserved names, required
|             |  config constraints
+-------------+
      |
      v
  *Agentfile

Index

Constants

View Source
const (
	AgentConfigLayerMediatype = "application/vnd.openotters.agent.config.v1+json"
	ContextLayerMediaType     = "application/vnd.openotters.context.v1"
	AgentArtifactType         = "application/vnd.openotters.agent.v1"

	// BinArtifactType marks an OCI image as an openotters bin-tool
	// (vnd.openotters.bin.* annotations, single binary per platform).
	// Lets consumers distinguish tool images from agent images without
	// relying on annotation-sniffing.
	BinArtifactType = "application/vnd.openotters.bin.v1"

	OctetStream = "application/octet-stream"
	Markdown    = "text/markdown"

	AnnotationBinName        = "vnd.openotters.bin.name"
	AnnotationBinPath        = "vnd.openotters.bin.path"
	AnnotationBinDescription = "vnd.openotters.bin.description"
	AnnotationBinUsage       = "vnd.openotters.bin.usage"

	DefaultBinPath   = "/"
	DefaultUsagePath = "/USAGE.md"
)
View Source
const DefaultSyntax = "openotters/agentfile:1"

DefaultSyntax is the syntax value assumed when an Agentfile omits the `# syntax=` pragma. Parse stamps this onto Agentfile.Syntax.

View Source
const DefaultTag = "latest"

Variables

View Source
var SupportedSyntaxes = []string{DefaultSyntax}

SupportedSyntaxes lists every `# syntax=` value the parser accepts.

Functions

func GenerateAgentMD

func GenerateAgentMD(af *Agentfile) string

GenerateAgentMD generates markdown documentation from an Agentfile.

func IsQualified

func IsQualified(name string) bool

IsQualified reports whether name carries a registry-host component. Heuristic matches containerd / docker reference parsers: the first slash-separated segment is a host when it contains "." (a TLD) or ":" (a port), or equals "localhost". Bare names like "foo" or "agents/foo" are unqualified — a caller with a default registry fills the host in via QualifyWithDefault.

Accepts either a bare name ("agents/foo") or a full reference string ("agents/foo:v1") — the trailing tag, if any, is stripped before the host-detection runs so callers don't need to ParseReference first.

func Validate

func Validate(af *Agentfile) error

Validate checks structural invariants on a programmatically constructed Agentfile: FROM is required, context name AGENT is reserved, and required configs cannot carry a default value. Parse already runs Validate; callers who build an Agentfile in code should call Validate themselves.

Types

type Add

type Add struct {
	Src         string `json:"src"`
	Dst         string `json:"dst"`
	Description string `json:"description,omitempty"`
	Content     []byte `json:"-"`
}

type Agent

type Agent struct {
	From     string            `json:"from"`
	Runtime  string            `json:"runtime,omitempty"`
	Model    string            `json:"model,omitempty"`
	Name     string            `json:"name,omitempty"`
	Contexts []*Context        `json:"contexts,omitempty"`
	Configs  []*Config         `json:"configs,omitempty"`
	Bins     []*Bin            `json:"bins,omitempty"`
	Adds     []*Add            `json:"adds,omitempty"`
	Exec     []string          `json:"exec,omitempty"`
	Labels   map[string]string `json:"labels,omitempty"`
	Args     map[string]string `json:"args,omitempty"`
	Envs     []*Env            `json:"envs,omitempty"`
}

type Agentfile

type Agentfile struct {
	Syntax string `json:"syntax"`
	Agent  *Agent `json:"agent"`
}

func Parse

func Parse(r io.Reader) (*Agentfile, error)

func ParseFile

func ParseFile(path string) (*Agentfile, error)

func (*Agentfile) Apply

func (a *Agentfile) Apply(overrides ...Override) *Agentfile

Apply mutates a in place by running each override. Returns a for chaining.

type Bin

type Bin struct {
	Name        string `json:"name"`
	Image       string `json:"image"`
	Description string `json:"description,omitempty"`
	Usage       string `json:"usage,omitempty"`
}

type Config

type Config struct {
	Key         string `json:"key"`
	Value       any    `json:"value,omitempty"`
	Description string `json:"description,omitempty"`
	Required    bool   `json:"required,omitempty"`
}

type Context

type Context struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Content     string `json:"content,omitempty"`
	File        string `json:"file,omitempty"`
}

type Env

type Env struct {
	Key         string `json:"key"`
	Value       string `json:"value"`
	Description string `json:"description,omitempty"`
}

Env declares an OS environment variable to be set on the spawned agent process. Unlike Config (a runtime-SDK knob the agent reads via the runtime API) and Arg (build-time substitution), Env values land directly on os/exec's Cmd.Env (system executor) and container.Config.Env (docker executor).

Reserved keys (PATH, HOME, XDG_*, TMPDIR, LANG, OTTERS_AGENT_ROOT, any *_API_KEY / *_API_BASE) are rejected by Validate to keep the locked-down env contract intact.

type Override

type Override func(*Agentfile)

Override mutates a parsed Agentfile. Overrides are applied via Apply and are intended for runtime field replacements (model, runtime image, etc.) coming from CLI flags or daemon config. Kept distinct from spec.Config, which is a data record declared in the Agentfile itself.

func WithModel

func WithModel(model string) Override

WithModel overrides Agent.Model.

func WithRuntime

func WithRuntime(runtime string) Override

WithRuntime overrides Agent.Runtime.

type Reference

type Reference struct {
	Name string
	Tag  string
}

Reference identifies an OCI image by name and tag. Name can be local ("meteo") or remote ("ghcr.io/openotters/agents/meteo"). Tag defaults to "latest" when not specified.

func ParseReference

func ParseReference(s string) Reference

ParseReference parses a reference string in the form "name" or "name:tag". The tag is the part after the last colon that follows the last slash. This correctly handles host:port/name:tag references.

func QualifyWithDefault

func QualifyWithDefault(ref Reference, defaultRegistry string) Reference

QualifyWithDefault returns ref with defaultRegistry prepended to its Name iff Name isn't already qualified. defaultRegistry should not include a scheme or trailing slash; an empty defaultRegistry is a no-op (callers without a default fall back to the unmodified ref).

func (Reference) String

func (r Reference) String() string

String returns the reference as "name:tag".

func (Reference) Validate

func (r Reference) Validate() error

Validate checks that the reference has at least a name.

type ReferenceWithDigest

type ReferenceWithDigest struct {
	Reference Reference
	Digest    digest.Digest
}

ReferenceWithDigest pairs a Reference with a content-addressed digest from the OCI store.

func (ReferenceWithDigest) String

func (r ReferenceWithDigest) String() string

String returns "name:tag@digest".

Jump to

Keyboard shortcuts

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