124 lines
4.9 KiB
Go
124 lines
4.9 KiB
Go
package agent
|
|
|
|
// config is the resolved, unexported construction state for a Session. It is
|
|
// populated only through Option values, so callers never name or mutate it
|
|
// directly — the exported surface stays limited to With* constructors and the
|
|
// Session methods.
|
|
type config struct {
|
|
model string
|
|
baseURL string
|
|
protocol string
|
|
provider string
|
|
apiKey string
|
|
systemPrompt string
|
|
appendSystemPrompt []string
|
|
thinking string
|
|
noTools bool
|
|
allowedTools []string
|
|
disallowedTools []string
|
|
skills bool
|
|
memory bool
|
|
}
|
|
|
|
// Option configures a Session at construction time. Options are applied in the
|
|
// order passed to New, so a later option overrides an earlier one that sets the
|
|
// same field. Because config is unexported, the only way to produce an Option is
|
|
// through the With* constructors below — which keeps the public surface free of
|
|
// internal types.
|
|
type Option func(*config)
|
|
|
|
// WithModel sets the model id, which also selects the provider the way the pigo
|
|
// CLI does (e.g. "claude-opus-4-8" → Anthropic, "openrouter/free" → OpenRouter).
|
|
// The default is "openrouter/free".
|
|
func WithModel(model string) Option {
|
|
return func(c *config) { c.model = model }
|
|
}
|
|
|
|
// WithBaseURL points the session at a custom endpoint. Pair it with
|
|
// [WithProtocol] to say whether that endpoint speaks the OpenAI or Anthropic
|
|
// wire format.
|
|
func WithBaseURL(baseURL string) Option {
|
|
return func(c *config) { c.baseURL = baseURL }
|
|
}
|
|
|
|
// WithProtocol selects the wire protocol for a custom endpoint: "openai" or
|
|
// "anthropic". It is only consulted when [WithBaseURL] is set.
|
|
func WithProtocol(protocol string) Option {
|
|
return func(c *config) { c.protocol = protocol }
|
|
}
|
|
|
|
// WithProvider selects a named provider from your pigo configuration instead of
|
|
// inferring one from the model id.
|
|
func WithProvider(name string) Option {
|
|
return func(c *config) { c.provider = name }
|
|
}
|
|
|
|
// WithAPIKey sets the API key for the resolved provider, overriding the
|
|
// provider's environment variable. When unset, the provider's usual environment
|
|
// variable is used (e.g. ANTHROPIC_API_KEY, OPENROUTER_API_KEY).
|
|
func WithAPIKey(key string) Option {
|
|
return func(c *config) { c.apiKey = key }
|
|
}
|
|
|
|
// WithSystemPrompt replaces pigo's built-in base instruction with prompt. Use
|
|
// this for full control over the agent's persona and rules; use
|
|
// [WithAppendSystemPrompt] instead to keep the built-in instruction and add to
|
|
// it.
|
|
func WithSystemPrompt(prompt string) Option {
|
|
return func(c *config) { c.systemPrompt = prompt }
|
|
}
|
|
|
|
// WithAppendSystemPrompt appends one or more blocks to the system prompt,
|
|
// leaving pigo's built-in instruction in place. Repeated calls accumulate.
|
|
func WithAppendSystemPrompt(blocks ...string) Option {
|
|
return func(c *config) {
|
|
c.appendSystemPrompt = append(c.appendSystemPrompt, blocks...)
|
|
}
|
|
}
|
|
|
|
// WithThinkingLevel sets the reasoning-effort level. Valid values are "off",
|
|
// "minimal", "low", "medium", "high", "xhigh", and "max". The default is
|
|
// "medium". An invalid value makes New return an error.
|
|
func WithThinkingLevel(level string) Option {
|
|
return func(c *config) { c.thinking = level }
|
|
}
|
|
|
|
// WithTools restricts the session to the named built-in tools (an allowlist,
|
|
// e.g. WithTools("read", "grep")). Names are matched case-insensitively, so
|
|
// "Read" and "read" are equivalent. A name that matches no tool makes New
|
|
// return an error rather than silently ignoring it. Combine with
|
|
// [WithDisallowedTools]; deny always wins over allow.
|
|
func WithTools(names ...string) Option {
|
|
return func(c *config) { c.allowedTools = append(c.allowedTools, names...) }
|
|
}
|
|
|
|
// WithDisallowedTools removes the named built-in tools (a denylist, e.g.
|
|
// WithDisallowedTools("bash")). Deny always wins: a tool named here is removed
|
|
// even if it also appears in [WithTools]. As with WithTools, an unknown name
|
|
// makes New return an error.
|
|
func WithDisallowedTools(names ...string) Option {
|
|
return func(c *config) { c.disallowedTools = append(c.disallowedTools, names...) }
|
|
}
|
|
|
|
// WithoutTools removes every tool, producing a pure text-completion session that
|
|
// cannot touch the filesystem or run commands. It overrides [WithTools] and
|
|
// [WithDisallowedTools], which become inert once the tool set is empty.
|
|
func WithoutTools() Option {
|
|
return func(c *config) { c.noTools = true }
|
|
}
|
|
|
|
// WithSkills enables discovery of on-disk skills, which are advertised to the
|
|
// model and loadable during a run. Skills are off by default so an embedded
|
|
// session stays independent of the machine's shared skills directory.
|
|
func WithSkills() Option {
|
|
return func(c *config) { c.skills = true }
|
|
}
|
|
|
|
// WithMemory enables pigo's persistent memory store, letting the agent recall
|
|
// context saved by earlier runs and record new memories. Memory is off by
|
|
// default so an embedded session does not read or write shared state unless
|
|
// asked.
|
|
func WithMemory() Option {
|
|
return func(c *config) { c.memory = true }
|
|
}
|