Documentation
¶
Index ¶
- Constants
- Variables
- func Assemble(cwd string) (cfg *engine.LLMConfig, warnings []error, err error)
- func ConfigExists() bool
- func DefaultModelForProvider(provider string) string
- func FetchSubscriptionType(ctx context.Context, accessToken string) (string, error)
- func GenerateOAuthURL() (authURL, verifier string, err error)
- func GenerateOpenAIOAuthURL() (authURL, verifier, state string, err error)
- func InteractiveSetup(ctx context.Context, promptHandler PromptHandler) (bool, error)
- func IsProvider(name string) bool
- func IsSecretURI(v string) bool
- func IsTerminalOAuthRefreshError(err error) bool
- func IsTokenExpired(provider *Provider) bool
- func LLMConfigured() bool
- func RefreshOAuthTokensIfNeeded(ctx context.Context) error
- func Remove() error
- func ResolveSecret(ctx context.Context, path string) ([]byte, error)
- func SubscriptionLabel(subType string) string
- func UpdateFile(fn func(existing []byte) ([]byte, error)) error
- type AbovePrinter
- type BrowserOpener
- type Config
- type LLMConfig
- type ModelInfo
- type OAuthCallbackServer
- type OAuthTokenResponse
- type OpenAITokenResponse
- type PromptHandler
- type Provider
- func ExchangeOAuthCode(ctx context.Context, authCode, verifier string) (*Provider, error)
- func ExchangeOpenAIOAuthCode(ctx context.Context, code, verifier string) (*Provider, error)
- func RefreshOAuthProviderAfterRejection(ctx context.Context, name, rejected string) (*Provider, error)
- func RefreshOAuthProviderIfNeeded(ctx context.Context, name string) (*Provider, error)
- func RefreshOAuthToken(ctx context.Context, provider *Provider) (*Provider, error)
- func RefreshOpenAIOAuthToken(ctx context.Context, provider *Provider) (*Provider, error)
- type ProviderEntry
Constants ¶
const ( FieldAPIKey = "api_key" FieldAuthToken = "auth_token" FieldAuthTokenExpiresAt = "auth_token_expires_at" //nolint:gosec // a field name, not a credential )
Credential fields: the path components of llmconfig://<provider>/<field>, named after the engine.LLMProviderConfig fields they fill.
const (
ConfigFileName = userconfig.FileName
)
Variables ¶
var ( ConfigRoot = filepath.Join(xdg.ConfigHome, "dagger") ConfigFile = userconfig.Path() )
var ErrAborted = errors.New("setup cancelled")
ErrAborted is returned when the user cancels a setup form (e.g. ctrl+c).
var ErrMalformed = errors.New("malformed LLM configuration")
ErrMalformed marks an assembly error caused by a value that cannot be parsed. Unlike an unreadable source, sending the config without it would silently misconfigure the router.
var ErrOAuthReauthenticationRequired = errors.New("OAuth reauthentication required")
ErrOAuthReauthenticationRequired marks refresh failures that cannot succeed again until the user replaces the OAuth grant.
Functions ¶
func Assemble ¶
Assemble builds the LLM configuration to send to the engine from, lowest to highest precedence: the config file's [llm] section, the process environment, and cwd/.env.
A source that cannot be read (an unparseable config file or .env) is left out and reported in warnings; the rest still applies, as it did when the engine read these itself. A value that cannot be parsed is an error wrapping ErrMalformed, and no config is returned.
Literal credentials read from .env are remembered for ResolveSecret, which serves them as llmconfig:// secrets; the last Assemble call wins.
func DefaultModelForProvider ¶
DefaultModelForProvider returns the default model ID for the given provider, or empty string if the provider is unknown.
func FetchSubscriptionType ¶
FetchSubscriptionType queries the Anthropic OAuth profile endpoint to determine the user's subscription type (pro, max, team, enterprise).
func GenerateOAuthURL ¶
GenerateOAuthURL generates a PKCE-protected OAuth authorization URL. Returns the URL the user should visit and the PKCE verifier for later use.
func GenerateOpenAIOAuthURL ¶
GenerateOpenAIOAuthURL generates a PKCE-protected OAuth authorization URL for OpenAI Codex (ChatGPT subscription). Returns the URL, the PKCE verifier, and the state parameter.
func InteractiveSetup ¶
func InteractiveSetup(ctx context.Context, promptHandler PromptHandler) (bool, error)
InteractiveSetup guides user through LLM configuration. It is additive: already-configured providers are shown with a summary and can be reconfigured, while new providers can be added alongside them. Returns (configured bool, error) - configured is true if setup completed.
func IsProvider ¶
IsProvider reports whether name is a provider the engine can route to.
func IsSecretURI ¶
IsSecretURI reports whether v is a reference to a secret (op://…, vault://…, env://…) rather than the secret itself.
func IsTerminalOAuthRefreshError ¶
IsTerminalOAuthRefreshError reports a refresh failure that requires the user to authenticate again instead of retrying the same credential.
func IsTokenExpired ¶
IsTokenExpired reports whether the OAuth access token has expired, or is close enough to expiring to be worth replacing now. An unknown expiry is not expired: the refresher runs on every secret resolution, so guessing here would rotate the refresh token continuously.
func LLMConfigured ¶
func LLMConfigured() bool
LLMConfigured checks if the config file exists and has LLM providers configured.
func RefreshOAuthTokensIfNeeded ¶
RefreshOAuthTokensIfNeeded checks all OAuth providers in the config and refreshes any expired tokens. This should be called client-side before connecting to the engine.
func Remove ¶
func Remove() error
Remove deletes the [llm] section from the config file. Other sections are preserved; the file itself is only removed once nothing else remains.
func ResolveSecret ¶
ResolveSecret serves llmconfig://<provider>/<field> secrets. It is registered as the scheme's resolver by the CLI.
A credential Assemble took from ./.env is served as read. Anything else is read from the config file at every resolution:
- api_key: the provider's stored API key.
- auth_token: the subscription OAuth token, refreshed first if it is due or if the context carries the RejectedSecretValue fingerprint of the current token; the rotated token is persisted.
- auth_token_expires_at: the token's true expiry, RFC 3339 UTC, or empty when unknown. The engine reads it right after auth_token, so it sees the expiry of a token that read just rotated.
A provider that is absent or disabled is a not-found error.
func SubscriptionLabel ¶
SubscriptionLabel returns a human-readable label for a subscription type.
func UpdateFile ¶
UpdateFile applies fn to the current config file contents under the cross-process lock and writes the result back atomically with 0600 permissions. fn receives nil when the file does not exist yet. The file is shared between subsystems ([llm], [workspaces], ...), so fn must preserve sections it does not own.
Types ¶
type AbovePrinter ¶
type AbovePrinter interface {
PrintAbove(text string)
}
AbovePrinter is an optional interface that PromptHandlers may implement to print text above the TUI into the terminal scrollback buffer. This is useful for content that must not be word-wrapped (e.g. clickable URLs).
type BrowserOpener ¶
BrowserOpener is an optional interface that PromptHandlers may implement to open a URL in the user's browser. OAuth flows use it to launch the authorization page automatically; the printed URL stays the fallback. It is client-side (the Frontend implements it), so core/llmconfig does not depend on a browser package.
type Config ¶
type Config struct {
LLM LLMConfig `toml:"llm"`
}
Config represents the top-level dagger config file. Only the [llm] section is managed here; other sections are preserved as-is.
type LLMConfig ¶
type LLMConfig struct {
DefaultProvider string `toml:"default_provider"`
DefaultModel string `toml:"default_model,omitempty"`
Providers map[string]Provider `toml:"providers"`
}
LLMConfig represents the [llm] section.
type ModelInfo ¶
type ModelInfo struct {
// ID is the model identifier sent in API requests.
ID string
// Label is a short human-readable name for display in selection UIs.
Label string
// CanReason indicates that the model supports extended reasoning / thinking.
CanReason bool
// ReasoningLevels lists the reasoning effort levels the model supports
// (e.g. "low", "medium", "high"). Empty if reasoning is not supported.
ReasoningLevels []string
// DefaultReasoningEffort is the default reasoning level for the model.
DefaultReasoningEffort string
// Default indicates this is the recommended default for its provider.
Default bool
}
ModelInfo describes a model available from a provider.
func ModelByID ¶
ModelByID looks up a specific model by provider and model ID. Returns the model and true if found, zero value and false otherwise.
func ModelsForProvider ¶
ModelsForProvider returns the model list for a given provider key. Returns nil for unknown providers.
type OAuthCallbackServer ¶
type OAuthCallbackServer struct {
// contains filtered or unexported fields
}
OAuthCallbackServer listens on localhost for an OAuth callback.
func StartOAuthCallbackServer ¶
func StartOAuthCallbackServer(port int, expectedState string) (*OAuthCallbackServer, error)
StartOAuthCallbackServer starts a local HTTP server to receive OAuth callbacks. It listens on the given port and validates the state parameter.
func (*OAuthCallbackServer) Close ¶
func (s *OAuthCallbackServer) Close()
Close shuts down the callback server.
func (*OAuthCallbackServer) WaitForCode ¶
func (s *OAuthCallbackServer) WaitForCode(ctx context.Context) string
WaitForCode waits for the OAuth callback to deliver a code, or for the context to be cancelled. Returns empty string if timed out or cancelled.
type OAuthTokenResponse ¶
type OAuthTokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
}
OAuthTokenResponse represents the token endpoint response.
type OpenAITokenResponse ¶
type OpenAITokenResponse struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
}
OpenAITokenResponse represents the OpenAI token endpoint response.
type PromptHandler ¶
PromptHandler is the minimal interface needed for interactive prompts
type Provider ¶
type Provider struct {
APIKey string `toml:"api_key"`
BaseURL string `toml:"base_url,omitempty"`
Model string `toml:"model,omitempty"`
SmallModel string `toml:"small_model,omitempty"`
AzureVersion string `toml:"azure_version,omitempty"`
DisableStreaming bool `toml:"disable_streaming,omitempty"`
Enabled bool `toml:"enabled"`
// OAuth fields for Claude Code subscription auth
AuthType string `toml:"auth_type,omitempty"` // "oauth" for Claude Code OAuth
AuthToken string `toml:"auth_token,omitempty"` // OAuth access token
RefreshToken string `toml:"refresh_token,omitempty"` // OAuth refresh token
// TokenExpiresAt is when the access token truly expires, in unix
// milliseconds, with no safety margin baked in. The margin is applied when
// the value is checked (IsTokenExpired), so an absent or short expires_in
// can't persist an already-expired value.
TokenExpiresAt int64 `toml:"token_expires_at,omitempty"`
// TokenExpiry is the legacy expiry: the same instant with the safety margin
// already subtracted. Still written so that an older CLI sharing this config
// file keeps working — it reads only this field and treats 0 as expired,
// which would put it in a refresh loop rotating the token out from under
// this one. TokenExpiresAt wins when both are present.
TokenExpiry int64 `toml:"token_expiry,omitempty"`
SubscriptionType string `toml:"subscription_type,omitempty"` // "pro", "max", "team", "enterprise"
// ReasoningEffort is the reasoning level for the provider's model, taken
// from the model's catwalk reasoning_levels (e.g. "low", "medium", "high").
// Empty disables reasoning.
ReasoningEffort string `toml:"reasoning_effort,omitempty"`
// APICompat selects which API protocol to use for custom/local endpoints.
// Values: "openai" (OpenAI-compatible) or "anthropic" (Anthropic-compatible).
// When set, BaseURL is used as the endpoint and the model name is passed through.
APICompat string `toml:"api_compat,omitempty"`
// ClaudeCodeVersion is the Claude Code release (a bare X.Y.Z) to present
// when authenticating Anthropic with a subscription OAuth token, overriding
// the engine's built-in default.
ClaudeCodeVersion string `toml:"claude_code_version,omitempty"`
}
Provider represents a single LLM provider's configuration.
func ExchangeOAuthCode ¶
ExchangeOAuthCode exchanges an authorization code for tokens. The authCode should be in the format "code#state" as provided by the callback.
func ExchangeOpenAIOAuthCode ¶
ExchangeOpenAIOAuthCode exchanges an authorization code for OpenAI tokens.
func RefreshOAuthProviderAfterRejection ¶
func RefreshOAuthProviderAfterRejection(ctx context.Context, name, rejected string) (*Provider, error)
RefreshOAuthProviderAfterRejection reloads the provider from disk and refreshes if due, or if rejected is the SHA-256 hex fingerprint of its current access token. A different token on disk wins without forcing another rotation: a concurrent process may already have recovered the credential for us.
func RefreshOAuthProviderIfNeeded ¶
RefreshOAuthProviderIfNeeded refreshes a single OAuth provider by name if its token has expired, persisting the result. It returns the provider as it now stands (refreshed or not), or nil if it is absent, disabled, or not an OAuth provider. Used to keep a long-running session's bearer token fresh: the client re-resolves the token on demand rather than only at startup.
func RefreshOAuthToken ¶
RefreshOAuthToken refreshes an expired OAuth token.
func RefreshOpenAIOAuthToken ¶
RefreshOpenAIOAuthToken refreshes an expired OpenAI OAuth token.
func (*Provider) TokenExpiresAtRFC3339 ¶
TokenExpiresAtRFC3339 formats the true access-token expiry as RFC 3339 in UTC — the wire format of the llmconfig://<provider>/auth_token_expires_at secret the engine reads alongside the token — or "" when the expiry is unknown.
func (*Provider) TokenExpiresAtTime ¶
TokenExpiresAtTime returns the true access-token expiry, or the zero time when it is unknown. Configs written before token_expires_at existed carry only token_expiry, which had the margin subtracted at write time — add it back to recover the real instant.
type ProviderEntry ¶
type ProviderEntry struct {
// Label is the human-readable name shown in the selector.
Label string
// Value is the choice identifier used in the setup switch.
Value string
// ConfigKey is the key in Config.LLM.Providers (may differ from Value
// for OAuth variants, e.g. "anthropic-oauth" → "anthropic").
ConfigKey string
// IsOAuth is true if this entry expects OAuth authentication.
IsOAuth bool
}
ProviderEntry describes a provider option for the setup UI.
func ProviderEntries ¶
func ProviderEntries() []ProviderEntry
ProviderEntries returns the ordered list of provider options for setup UIs.