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 } }