typ

package
v0.260801.2 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MPL-2.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AuthTypeAPIKey    = ai.AuthTypeAPIKey
	AuthTypeOAuth     = ai.AuthTypeOAuth
	AuthTypeVirtual   = ai.AuthTypeVirtual
	AuthTypeAWSSigV4  = ai.AuthTypeAWSSigV4
	AuthTypeAzureKey  = ai.AuthTypeAzureKey
	AuthTypeGCPVertex = ai.AuthTypeGCPVertex
)

AuthType constants - re-exported for backward compatibility

View Source
const (
	ProviderSourceUser    = ai.ProviderSourceUser
	ProviderSourceBuiltin = ai.ProviderSourceBuiltin
)
View Source
const (
	ToolVisibilityClient = coretool.ToolVisibilityClient
	ToolVisibilityServer = coretool.ToolVisibilityServer
)
View Source
const ClaudeOrgIDAuto = "auto"

ClaudeOrgIDAuto is the sentinel claude_org_id value that attaches the organization captured at OAuth login (OAuthDetail.ExtraFields["organization_id"]) as anthropic-organization-id. Sending the organization is opt-in: an unset (empty) flag attaches no organization header at all, preserving the classic behavior.

View Source
const ClaudeOrgIDKey contextKey = "claude_org_id"

ClaudeOrgIDKey carries the rule-level claude_org_id override down to the outbound Anthropic client/transport, which sends it as the anthropic-organization-id header instead of the provider's login-time organization.

View Source
const ClientUserAgentKey contextKey = "client_user_agent"

ClientUserAgentKey carries the *inbound* client's User-Agent header down to the outbound HTTP transport so it can be forwarded upstream. Distinct from CustomUserAgentKey (the explicit rule/scenario override); userAgentTransport resolves the precedence between them.

View Source
const Context1MKey contextKey = "context_1m"

Context1MKey carries the rule-level 1M-context hint down to the Anthropic client, whose Beta/Messages methods add the context-1m beta flag per request.

View Source
const CustomUserAgentKey contextKey = "custom_user_agent"

CustomUserAgentKey carries a rule-level User-Agent override down to the outbound HTTP transport.

View Source
const ProfileSeparator = ":"

ProfileSeparator is used to split "scenario:profile_id" strings.

View Source
const SessionIDKey contextKey = "session_id"
View Source
const UserAgentNone = "none"

UserAgentNone is the sentinel custom_user_agent value that strips the outbound User-Agent header entirely (the request is sent with no User-Agent), as opposed to an empty value which means "do not override". Some upstreams accept — or even prefer — requests without a User-Agent, so this gives operators an explicit "send nothing" option distinct from "leave default".

Variables

View Source
var ThinkingBudgetMapping = map[ThinkingEffortLevel]int64{
	ThinkingEffortLow:    1024,
	ThinkingEffortMedium: 5120,
	ThinkingEffortHigh:   20480,
	ThinkingEffortMax:    31999,
}

ThinkingBudgetMapping defines budget_tokens for each effort level. "off" / "" are intentionally absent — they signal disabled / pass-through, not a budget value, and are handled out-of-band by the transform layer.

Functions

func ApplyMCPRuntimeDefaults added in v0.260409.1540

func ApplyMCPRuntimeDefaults(config *MCPRuntimeConfig)

ApplyMCPRuntimeDefaults applies default values to MCP runtime config.

func BoolPtr added in v0.260409.1540

func BoolPtr(v bool) *bool

BoolPtr returns a pointer to the given bool.

func CanBindRulesToScenario

func CanBindRulesToScenario(scenario RuleScenario) bool

func CanUseScenarioInPath

func CanUseScenarioInPath(scenario RuleScenario) bool

func GetClaudeOrgID added in v0.260801.1

func GetClaudeOrgID(ctx context.Context) string

GetClaudeOrgID returns the per-request organization-id override, or "" if none.

func GetClientUserAgent added in v0.260723.1

func GetClientUserAgent(ctx context.Context) string

GetClientUserAgent returns the inbound client's User-Agent, or "" if none.

func GetContext1M added in v0.260611.1

func GetContext1M(ctx context.Context) bool

GetContext1M reports whether the request carries the 1M-context hint.

func GetCustomUserAgent added in v0.260531.1

func GetCustomUserAgent(ctx context.Context) string

GetCustomUserAgent returns the per-request User-Agent override, or "" if none.

func IsAffinityEligible added in v0.260625.1

func IsAffinityEligible(ruleUUID string, services []*loadbalance.Service, target *loadbalance.Service) bool

IsAffinityEligible reports whether target is a service the routing strategy would actually select right now, so session affinity can decide whether a pin is still valid. ruleUUID scopes the breaker store: each rule has independent breaker state per service, so eligibility reflects only the traffic this rule observes (a service failing under another rule does not demote a pin here). It is config-shape driven rather than tactic-label driven — "tier" is just the emergent shape of a multi-layer rule, so this answers the same question for every shape:

  • one service → the only service; eligible whenever present.
  • one tier, many services → eligible iff target's own breaker is available (don't stick a session to a dead peer when healthy peers exist).
  • many tiers → eligible iff target is breaker-available AND its tier is the highest-priority tier that currently has any available service (don't stay on a fallback tier after the primary recovers).

PromotionHold de-jitters batch return-to-primary: when a higher-priority tier has just recovered (within DefaultPromotionHold), it only takes NEW sessions. A session already pinned to a lower tier is kept there until the recovered primary has stayed healthy past the hold — so a freshly-recovered primary doesn't vacuum all fallback-tier sessions back at once and re-trip under full load. This mirrors the "low tier has an inherent, lower-priority stickiness" intent: the primary must prove stable to outweigh it.

It mirrors TierTactic.SelectService's bucket walk but uses the non-consuming breaker read (IsAvailable) so it never steals the half-open probe. When every service is tripped it falls back to "target is in the lowest-numbered tier" (matching TierTactic's degrade-don't-disappear behavior) so a pin is honored rather than wedging.

func IsMCPSourceEnabled added in v0.260409.1540

func IsMCPSourceEnabled(source MCPSourceConfig) bool

IsMCPSourceEnabled returns whether a source is enabled. Nil means enabled for backward compatibility with existing configs.

func IsProfiledScenario

func IsProfiledScenario(raw RuleScenario) bool

IsProfiledScenario returns true if the scenario string contains a profile suffix.

func IsSimpleProfileAlias added in v0.260625.1

func IsSimpleProfileAlias(s string) bool

IsSimpleProfileAlias reports whether s is a URL-friendly profile alias that the profile-alias middleware is allowed to resolve to a profile ID.

A profile is addressed as the "<alias>" half of "/tingly/<base>:<alias>", so the alias has to be a clean URL path token. We whitelist the RFC 3986 unreserved slug subset — ASCII letters, digits, '-' and '_' — which needs no escaping and contains no path/profile separators. Names that fail this check are not routable by name; callers must address those profiles by ID.

func IsValidRecordingMode

func IsValidRecordingMode(mode string) bool

IsValidRecordingMode checks if the given string is a valid recording mode

func PickBreakerAvailable added in v0.260716.1

func PickBreakerAvailable(ruleUUID string, candidates []*loadbalance.Service, pick func([]*loadbalance.Service) *loadbalance.Service, claim bool) *loadbalance.Service

PickBreakerAvailable runs a two-phase, breaker-aware selection over candidates: gather the breaker-available subset with the non-consuming IsAvailable read (rule-scoped), let pick choose among that subset, then — when claim is true — claim the picked service's breaker slot via Allow. A pick whose claim fails (its half-open probe is already in flight) is dropped and the remainder re-picked, so exactly one probe reaches a recovering service. claim=false is the side-effect-free preview mode for read-only surfaces: it picks from the same available subset but never consumes a probe slot.

It returns nil when no candidate is breaker-available or claimable — callers own the degrade decision (TierTactic moves to the next bucket; the horizontal path in LoadBalancer falls back to an unfiltered pick so the client sees the real upstream error).

func RegisterScenario

func RegisterScenario(descriptor ScenarioDescriptor) error

func ScenarioSupportsTransport added in v0.260507.1

func ScenarioSupportsTransport(scenario RuleScenario, transport ScenarioTransport) bool

ScenarioSupportsTransport reports whether the given scenario's descriptor declares support for the specified transport.

func ValidateProfileName added in v0.260625.1

func ValidateProfileName(name string) error

ValidateProfileName enforces, at profile creation/rename time, that a name is a simple alias usable directly in a route ("/tingly/<base>:<name>"). Pushing the constraint to the write path is the primary defense: every stored profile is then guaranteed routable by name, and IsSimpleProfileAlias on the routing path only has to guard legacy data created before this check. The "default" and the "p"<digits> ID shape are additionally reserved so user names cannot collide with system-managed profile identities.

func WithClaudeOrgID added in v0.260801.1

func WithClaudeOrgID(ctx context.Context, orgID string) context.Context

WithClaudeOrgID attaches the anthropic-organization-id override that the outbound Anthropic client reads at request time. Empty values are not attached (no override).

func WithClientUserAgent added in v0.260723.1

func WithClientUserAgent(ctx context.Context, ua string) context.Context

WithClientUserAgent attaches the inbound client's User-Agent so an outbound HTTP transport may forward it upstream when nothing else overrides the UA. Empty values are not attached (no client UA to forward).

func WithContext1M added in v0.260611.1

func WithContext1M(ctx context.Context) context.Context

WithContext1M marks the request as wanting Anthropic's 1M context window.

func WithCustomUserAgent added in v0.260531.1

func WithCustomUserAgent(ctx context.Context, ua string) context.Context

WithCustomUserAgent attaches a User-Agent override that an outbound HTTP transport may read at request time.

func WithSessionID added in v0.260414.2000

func WithSessionID(ctx context.Context, sessionID SessionID) context.Context

WithSessionID adds a sessionID to the context. This allows sessionID to be propagated through the call chain without explicit parameter passing.

Types

type AdvisorConfig added in v0.260507.1

type AdvisorConfig struct {
	// ProviderUUID references a configured provider by UUID.
	ProviderUUID string `json:"provider_uuid,omitempty" yaml:"provider_uuid,omitempty"`
	Model        string `json:"model,omitempty" yaml:"model,omitempty"`

	// ProviderResolver is a function that resolves a provider by UUID at call time.
	// It is not persisted to JSON/YAML and must be set by the server before use.
	ProviderResolver func(string) (*Provider, error) `json:"-" yaml:"-"`

	MaxUsesPerRequest int `json:"max_uses_per_request,omitempty" yaml:"max_uses_per_request,omitempty"`
	// The max token output by adviser. Too much explodes worker's context. 4k is enough for pure suggestions.
	MaxTokens int `json:"max_tokens,omitempty" yaml:"max_tokens,omitempty"`
	// TimeoutSeconds overrides the default 60s per-call timeout. Set higher for slow/large models.
	TimeoutSeconds int `json:"timeout_seconds,omitempty" yaml:"timeout_seconds,omitempty"`
}

AdvisorConfig configures the in-process advisor tool source.

type AuthType

type AuthType = ai.AuthType

AuthType represents the authentication type for a provider Type alias for backward compatibility with common/provider

type CapacityBasedParams added in v0.260409.1540

type CapacityBasedParams struct{}

CapacityBasedParams holds parameters for capacity-based load balancing

type CapacityBasedTactic added in v0.260409.1540

type CapacityBasedTactic struct{}

CapacityBasedTactic implements capacity-based load balancing It selects services based on available capacity (weighted random)

func GetCapacityBasedTactic added in v0.260409.1540

func GetCapacityBasedTactic() *CapacityBasedTactic

GetCapacityBasedTactic returns the capacity-based tactic singleton

func NewCapacityBasedTactic added in v0.260409.1540

func NewCapacityBasedTactic() *CapacityBasedTactic

NewCapacityBasedTactic creates a new capacity-based tactic

func (*CapacityBasedTactic) GetName added in v0.260409.1540

func (cbt *CapacityBasedTactic) GetName() string

GetName returns the tactic name

func (*CapacityBasedTactic) GetType added in v0.260409.1540

GetType returns the tactic type

func (*CapacityBasedTactic) SelectService added in v0.260409.1540

func (cbt *CapacityBasedTactic) SelectService(rule *Rule) *loadbalance.Service

SelectService selects a service using capacity-based weighted random. Capacity is determined by Service.ModelCapacity (from rule config). Higher capacity = higher probability of selection.

type ClaudeCodeProfileConfig added in v0.260723.1

type ClaudeCodeProfileConfig struct {
	Env         map[string]string `json:"env,omitempty" yaml:"env,omitempty"`
	UnsetEnv    []string          `json:"unset_env,omitempty" yaml:"unset_env,omitempty"`
	DefaultMode string            `json:"default_mode,omitempty" yaml:"default_mode,omitempty"`
}

ClaudeCodeProfileConfig stores only the delta from a profile's inherited Claude Code configuration. Env contains explicit values, UnsetEnv contains inherited keys the profile removes, and an empty DefaultMode means inherit. Generated settings files remain disposable runtime artifacts.

type ClientKey added in v0.260409.1540

type ClientKey struct {
	ProviderUUID string    `json:"provider_uuid"`
	Model        string    `json:"model"`
	SessionID    SessionID `json:"session_id,omitempty"`
}

ClientKey uniquely identifies a cached client in the ClientPool. For OAuth providers with a real user session, SessionID is included to isolate per-user OAuth credentials. For API-key providers or IP-fallback sessions, SessionID is omitted so clients are shared at provider level.

func NewClientKey added in v0.260409.1540

func NewClientKey(provider *Provider, model string, session SessionID) ClientKey

NewClientKey builds a ClientKey applying OAuth session-scoping rules. sessionID is only included in the key when:

  • typ.AuthType == AuthTypeOAuth
  • session is not empty
  • session is not an IP-fallback (which would create one key per IP)

func (ClientKey) IsSessionScoped added in v0.260409.1540

func (k ClientKey) IsSessionScoped() bool

IsSessionScoped returns true when this key is bound to a specific user session.

func (ClientKey) String added in v0.260409.1540

func (k ClientKey) String() string

String returns a stable string for use as map key.

type CredentialBundle added in v0.260531.1

type CredentialBundle = ai.CredentialBundle

CredentialBundle holds multi-field credentials for non-bearer auth types Type alias for backward compatibility with common/provider

type DiscoveryResult

type DiscoveryResult struct {
	TotalIdesScanned int             `json:"total_ides_scanned"`
	IdesFound        []IDESource     `json:"ides_found"`
	SkillsFound      int             `json:"skills_found"`
	Locations        []SkillLocation `json:"locations"`
}

DiscoveryResult represents the result of IDE discovery

type FlagCategory added in v0.260531.1

type FlagCategory string

FlagCategory groups flags for presentation in the UI.

const (
	// FlagCategoryApp — flags that target a specific client application (IDE, CLI tool, etc).
	FlagCategoryApp FlagCategory = "app"
	// FlagCategoryRequestOpenAI — request-level adjustments for OpenAI-compatible upstreams:
	// endpoint routing, field rewrites, tool blocking, user-agent overrides.
	FlagCategoryRequestOpenAI FlagCategory = "request_openai"
	// FlagCategoryRequestAnthropic — request-level adjustments for Anthropic-compatible upstreams:
	// message normalisation and other Anthropic-protocol-specific transforms.
	FlagCategoryRequestAnthropic FlagCategory = "request_anthropic"
	// FlagCategoryResponse — flags that modify the response body/stream.
	FlagCategoryResponse FlagCategory = "response"
	// FlagCategoryReasoning — extended-thinking / reasoning-effort controls.
	FlagCategoryReasoning FlagCategory = "reasoning"
	// FlagCategoryRouting — routing / load-balancing behavior (session
	// affinity, etc) that decides which upstream service a request lands on.
	FlagCategoryRouting FlagCategory = "routing"
	// FlagCategoryVision — image/vision handling (vision proxy describer).
	FlagCategoryVision FlagCategory = "vision"
)

type FlagOption added in v0.260531.1

type FlagOption struct {
	Value string `json:"value"`
	Label string `json:"label"`
}

FlagOption is one selectable value for a FlagTypeEnum spec.

func DefaultUserAgents added in v0.260611.1

func DefaultUserAgents() []FlagOption

DefaultUserAgents returns a curated, non-exhaustive list of recommended User-Agent strings for the custom_user_agent flag (both rule- and scenario-level). The values mirror the vendor-pinned User-Agents the built-in clients send (see internal/client/*.go) plus a few widely used CLI/SDK agents, so operators can impersonate a known client when an upstream gates on it. Label is a human-friendly name; Value is the literal User-Agent header.

type FlagSpec added in v0.260531.1

type FlagSpec struct {
	Key         string        `json:"key"`
	Label       string        `json:"label"`
	Description string        `json:"description"`
	Type        FlagValueType `json:"type"`
	Category    FlagCategory  `json:"category"`
	// Placeholder is the hint text shown in string-type input fields.
	Placeholder string `json:"placeholder,omitempty"`
	// Options enumerates the selectable values for FlagTypeEnum flags.
	// The first option is treated as the default when the stored value is empty.
	Options []FlagOption `json:"options,omitempty"`
	// Suggestions offers a non-exhaustive list of recommended values for a
	// FlagTypeString flag. Unlike Options (enum) these are not the only legal
	// values — the UI surfaces them as a quick-pick / autocomplete while still
	// allowing free-form input. Used by custom_user_agent to expose the common
	// CLI/agent User-Agent strings (see DefaultUserAgents).
	Suggestions []FlagOption `json:"suggestions,omitempty"`
	// Shared indicates this flag also exists at the scenario level
	// (ScenarioFlags) and participates in scenario→rule inheritance.
	Shared bool `json:"shared,omitempty"`
	// InheritanceMode describes how the scenario-level and rule-level values
	// combine when both are set:
	//   - "or":       bool OR — either level enabling it activates the flag
	//   - "override": rule non-zero/non-empty wins, else scenario default
	// Empty means the flag is rule-only (not shared).
	InheritanceMode string `json:"inheritance_mode,omitempty"`
}

FlagSpec describes a single rule-level flag's metadata for the UI catalog. Keys must match the JSON tag name on RuleFlags.

func RuleFlagRegistry added in v0.260531.1

func RuleFlagRegistry() []FlagSpec

RuleFlagRegistry returns the catalog of supported rule flags. The order is the recommended display order in the UI — categories are grouped implicitly by adjacent entries sharing the same Category value.

type FlagValueType added in v0.260531.1

type FlagValueType string

FlagValueType describes how a rule flag is represented in storage and UI.

const (
	FlagTypeBool   FlagValueType = "bool"
	FlagTypeString FlagValueType = "string"
	FlagTypeEnum   FlagValueType = "enum"
	// FlagTypeInt is a non-negative integer value. The UI renders a numeric
	// text field. Zero is treated as inactive (equivalent to omitempty).
	FlagTypeInt FlagValueType = "int"
	// FlagTypeServiceRef is a {provider, model} pair selected via the model
	// picker. The UI renders a service picker (provider + model); an empty
	// pair is treated as inactive. Backed by a typed struct on RuleFlags, not
	// a scalar.
	FlagTypeServiceRef FlagValueType = "service_ref"
)

type FlexibleBool

type FlexibleBool bool

FlexibleBool is a boolean type that can unmarshal from both bool and int (0/1) This handles cases where JSON data may contain numeric values instead of booleans

func (FlexibleBool) MarshalJSON

func (fb FlexibleBool) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for FlexibleBool

func (*FlexibleBool) UnmarshalJSON

func (fb *FlexibleBool) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler for FlexibleBool

type GroupingStrategy

type GroupingStrategy struct {
	// Mode: "flat" (no grouping), "auto" (automatic based on file count), "pattern" (by pattern)
	Mode string `json:"mode"`
	// GroupPattern: pattern for grouping when mode="pattern", e.g., "skills" groups by skills directory
	// The pattern is searched in the file path, and everything up to (and including) the match becomes the group key
	GroupPattern string `json:"group_pattern,omitempty"`
	// MinFilesForSplit: minimum files before splitting a group (only for auto mode)
	MinFilesForSplit int `json:"min_files_for_split,omitempty"`
}

GroupingStrategy defines how skills should be grouped in the UI

type HealthFilter

type HealthFilter struct {
	// contains filtered or unexported fields
}

HealthFilter filters services based on their health status

func NewHealthFilter

func NewHealthFilter(monitor *loadbalance.HealthMonitor) *HealthFilter

NewHealthFilter creates a new health filter with the given health monitor

func (*HealthFilter) Filter

func (hf *HealthFilter) Filter(services []*loadbalance.Service) []*loadbalance.Service

Filter filters out unhealthy services from the given list Returns only healthy services. If no healthy services are found, returns an empty slice (not nil).

func (*HealthFilter) FilterWithFallback

func (hf *HealthFilter) FilterWithFallback(services []*loadbalance.Service) []*loadbalance.Service

FilterWithFallback filters services and returns healthy ones. If no healthy services are found, returns all services as a fallback. This is useful when you want to avoid complete failure even if all services are marked unhealthy.

func (*HealthFilter) GetHealthMonitor

func (hf *HealthFilter) GetHealthMonitor() *loadbalance.HealthMonitor

GetHealthMonitor returns the underlying health monitor

func (*HealthFilter) IsHealthy

func (hf *HealthFilter) IsHealthy(serviceID string) bool

IsHealthy checks if a specific service is healthy

type IDEAdapter

type IDEAdapter struct {
	Key               IDESource `json:"key"`
	DisplayName       string    `json:"display_name"`
	RelativeDetectDir string    `json:"relative_detect_dir"`
	Icon              string    `json:"icon"`
	SupportsSymlink   bool      `json:"supports_symlink"`
	// ScanPatterns defines glob patterns for finding skill files (e.g., ["*.md", "skill/*.md"])
	// Patterns are relative to the detected IDE base directory (relative_detect_dir).
	// If empty, defaults to ["**/*.md"]
	ScanPatterns []string `json:"scan_patterns,omitempty"`
	// GroupingStrategy defines how skills should be grouped in the UI
	GroupingStrategy *GroupingStrategy `json:"grouping_strategy,omitempty"`
}

IDEAdapter defines the configuration for an IDE adapter

type IDESource

type IDESource string

IDESource represents the type of IDE/source for skills

const (
	IDESourceClaudeCode    IDESource = "claude-code"
	IDESourceOpenCode      IDESource = "opencode"
	IDESourceVSCode        IDESource = "vscode"
	IDESourceCursor        IDESource = "cursor"
	IDESourceCodex         IDESource = "codex"
	IDESourceAntigravity   IDESource = "antigravity"
	IDESourceAmp           IDESource = "amp"
	IDESourceKiloCode      IDESource = "kilo-code"
	IDESourceRooCode       IDESource = "roo-code"
	IDESourceGoose         IDESource = "goose"
	IDESourceGeminiCLI     IDESource = "gemini-cli"
	IDESourceGitHubCopilot IDESource = "github-copilot"
	IDESourceClawdbot      IDESource = "clawdbot"
	IDESourceDroid         IDESource = "droid"
	IDESourceWindsurf      IDESource = "windsurf"
	IDESourceCustom        IDESource = "custom"
)

type LoadBalancingTactic

type LoadBalancingTactic interface {
	SelectService(rule *Rule) *loadbalance.Service
	GetName() string
	GetType() loadbalance.TacticType
}

LoadBalancingTactic defines the interface for load balancing strategies

func CreateTacticWithTypedParams

func CreateTacticWithTypedParams(tacticType loadbalance.TacticType, params TacticParams) LoadBalancingTactic

func GetDefaultTactic

func GetDefaultTactic(tType loadbalance.TacticType) LoadBalancingTactic

type MCPAuthType added in v0.260414.2000

type MCPAuthType string

MCPAuthType defines authentication type

const (
	MCPAuthTypeNone   MCPAuthType = "none"
	MCPAuthTypeHeader MCPAuthType = "headers"
	MCPAuthTypeOAuth  MCPAuthType = "oauth"
)

type MCPClient added in v0.260414.2000

type MCPClient struct {
	ID     string          `json:"id"`
	Config MCPSourceConfig `json:"config"`
	Tools  []MCPTool       `json:"tools"`
	State  MCPClientState  `json:"state"`
}

MCPClient represents a registered MCP client

type MCPClientState added in v0.260414.2000

type MCPClientState string

MCPClientState defines client connection state

const (
	MCPClientStateConnected    MCPClientState = "connected"
	MCPClientStateConnecting   MCPClientState = "connecting"
	MCPClientStateDisconnected MCPClientState = "disconnected"
	MCPClientStateError        MCPClientState = "error"
)

type MCPConnectionType added in v0.260414.2000

type MCPConnectionType string

MCPConnectionType defines connection type

const (
	MCPConnectionTypeSTDIO MCPConnectionType = "stdio"
	MCPConnectionTypeHTTP  MCPConnectionType = "http"
	MCPConnectionTypeSSE   MCPConnectionType = "sse"
)

type MCPMode added in v0.260414.2000

type MCPMode string

MCPMode defines MCP runtime mode

const (
	MCPModeServertool MCPMode = "servertool" // servertool mode: tingly-box connects to external MCP servers and injects tools into AI requests
	MCPModeClienttool MCPMode = "clienttool" // clienttool mode (default): external clients connect to tingly-box
)

type MCPOAuthConfig added in v0.260414.2000

type MCPOAuthConfig struct {
	ClientID     string   `json:"client_id"`
	ClientSecret string   `json:"client_secret,omitempty"`
	AuthorizeURL string   `json:"authorize_url"`
	TokenURL     string   `json:"token_url"`
	Scopes       []string `json:"scopes,omitempty"`
}

MCPOAuthConfig OAuth 2.0 configuration

type MCPRuntimeConfig added in v0.260409.1540

type MCPRuntimeConfig struct {
	Mode                  MCPMode           `json:"mode,omitempty"` // deprecated: kept only for backward compatibility
	Sources               []MCPSourceConfig `json:"sources,omitempty"`
	RequestTimeout        int               `json:"request_timeout,omitempty"`          // seconds, default: 30
	StripDisabledMCPTools bool              `json:"strip_disabled_mcp_tools,omitempty"` // dangerous: strip disabled MCP declarations/tool_calls
}

MCPRuntimeConfig contains global MCP runtime configuration.

type MCPSourceConfig added in v0.260409.1540

type MCPSourceConfig struct {
	ID         string            `json:"id,omitempty"`         // unique source id for normalized tool names
	Name       string            `json:"name,omitempty"`       // client name (unique, no spaces/hyphens)
	Enabled    *bool             `json:"enabled,omitempty"`    // nil means enabled (backward-compatible default)
	Transport  string            `json:"transport,omitempty"`  // "http", "stdio", or "sse"
	Endpoint   string            `json:"endpoint,omitempty"`   // endpoint URL for HTTP/SSE transport
	Headers    map[string]string `json:"headers,omitempty"`    // static headers for MCP calls
	Tools      []string          `json:"tools,omitempty"`      // allow list, empty means all
	Command    string            `json:"command,omitempty"`    // command for stdio transport
	Args       []string          `json:"args,omitempty"`       // args for stdio command
	Cwd        string            `json:"cwd,omitempty"`        // working directory for stdio command
	Env        map[string]string `json:"env,omitempty"`        // extra env vars for stdio command
	ProxyURL   string            `json:"proxy_url,omitempty"`  // HTTP proxy URL for outgoing requests
	Visibility ToolVisibility    `json:"visibility,omitempty"` // "client" or "server"

	// Local mode specific fields
	ConnectionType      MCPConnectionType `json:"connection_type,omitempty"`       // stdio/http/sse
	AuthType            MCPAuthType       `json:"auth_type,omitempty"`             // headers/oauth
	AllowedExtraHeaders []string          `json:"allowed_extra_headers,omitempty"` // allowed request headers to forward
	StdioConfig         *MCPStdioConfig   `json:"stdio_config,omitempty"`
	OAuthConfig         *MCPOAuthConfig   `json:"oauth_config,omitempty"`
	ToolsToExecute      []string          `json:"tools_to_execute,omitempty"`      // available tools
	ToolsAutoExec       []string          `json:"tools_to_auto_execute,omitempty"` // auto-execute tools (agent mode)
	IsPingAvailable     *bool             `json:"is_ping_available,omitempty"`     // health check method
	AutoRegistered      bool              `json:"auto_registered,omitempty"`       // true if auto-registered on first connect
	Advisor             *AdvisorConfig    `json:"advisor,omitempty" yaml:"advisor,omitempty"`
}

MCPSourceConfig defines one MCP source connection.

type MCPStdioConfig added in v0.260414.2000

type MCPStdioConfig struct {
	Command string   `json:"command"`        // execution command
	Args    []string `json:"args,omitempty"` // command arguments
	Env     []string `json:"env,omitempty"`  // inherited environment variables
	Cwd     string   `json:"cwd,omitempty"`  // working directory
}

MCPStdioConfig STDIO connection configuration

type MCPTool added in v0.260414.2000

type MCPTool struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
}

MCPTool represents an MCP tool definition

type OAuthDetail

type OAuthDetail = ai.OAuthDetail

OAuthDetail contains OAuth-specific authentication information Type alias for backward compatibility with common/provider

type ProfileMeta

type ProfileMeta struct {
	ID         string                   `json:"id" yaml:"id"`                                       // Profile ID (e.g. "p1")
	Name       string                   `json:"name" yaml:"name"`                                   // Human-readable name (unique within base scenario)
	Unified    bool                     `json:"unified" yaml:"unified"`                             // true=unified mode (single model), false=separate mode (individual models, default)
	ClaudeCode *ClaudeCodeProfileConfig `json:"claude_code,omitempty" yaml:"claude_code,omitempty"` // Persistent overrides for generated Claude Code settings.
}

ProfileMeta stores metadata for a scenario profile. Profiles allow multiple Rule + ScenarioFlags configurations per base scenario. A profile is identified by a short service-generated ID (e.g. "p1", "p2").

type Provider

type Provider = ai.Provider

Provider represents an AI model api key and provider configuration Type alias for backward compatibility with common/provider

type ProviderSource added in v0.260514.1

type ProviderSource = ai.ProviderSource

ProviderSource constants - re-exported for backward compatibility

type RandomParams

type RandomParams struct{}

RandomParams represents parameters for random tactic (currently empty but extensible)

func AsRandomParams

func AsRandomParams(p TacticParams) (RandomParams, bool)

Type assertion helpers for TacticParams. They accept both the pointer and value forms because UnmarshalJSON stores pointers while hand-built configs may use values.

type RandomTactic

type RandomTactic struct{}

RandomTactic implements random selection with weighted probability

func NewRandomTactic

func NewRandomTactic() *RandomTactic

NewRandomTactic creates a new random tactic

func (*RandomTactic) GetName

func (rt *RandomTactic) GetName() string

func (*RandomTactic) GetType

func (rt *RandomTactic) GetType() loadbalance.TacticType

func (*RandomTactic) SelectService

func (rt *RandomTactic) SelectService(rule *Rule) *loadbalance.Service

SelectService selects a service randomly based on weights

type RecordingMode

type RecordingMode string

RecordingMode represents the recording mode for scenario recording

const (
	RecordingModeDisabled              RecordingMode = ""                        // Recording disabled (default)
	RecordingModeRequestOnly           RecordingMode = "request"                 // Record transformed request only
	RecordingModeRequestResponse       RecordingMode = "request_response"        // Record transformed request + final response
	RecordingModeStagedRequestResponse RecordingMode = "staged_request_response" // Record original request + transformed request + final response
)

type Rule

type Rule struct {
	UUID          string                 `json:"uuid"`
	Scenario      RuleScenario           `json:"scenario,required" yaml:"scenario"` // openai, anthropic, claude_code; defaults to openai
	RequestModel  string                 `json:"request_model" yaml:"request_model"`
	ResponseModel string                 `json:"response_model" yaml:"response_model"`
	Description   string                 `json:"description"`
	Services      []*loadbalance.Service `json:"services" yaml:"services"`
	// Per-rule feature flags (e.g. cursor_compat / cursor_compat_auto).
	Flags RuleFlags `json:"flags,omitempty" yaml:"flags,omitempty"`
	// Unified Tactic Configuration
	LBTactic Tactic `json:"lb_tactic" yaml:"lb_tactic"`
	Active   bool   `json:"active" yaml:"active"`
	// Smart Routing Configuration
	SmartEnabled bool                        `json:"smart_enabled" yaml:"smart_enabled"`
	SmartRouting []smartrouting.SmartRouting `json:"smart_routing,omitempty" yaml:"smart_routing,omitempty"`
}

Rule represents a request/response configuration with load balancing support

func (*Rule) AffinityEnabled added in v0.260604.1

func (r *Rule) AffinityEnabled() bool

AffinityEnabled reports whether session affinity should be applied for this rule. Affinity is a load-balancing concern, independent of smart routing.

func (*Rule) AffinityTTL added in v0.260604.1

func (r *Rule) AffinityTTL() time.Duration

AffinityTTL returns the rule's configured session-affinity TTL.

func (*Rule) GetActiveServices

func (r *Rule) GetActiveServices() []*loadbalance.Service

GetActiveServices returns all active services with initialized stats

func (*Rule) GetCurrentService

func (r *Rule) GetCurrentService() *loadbalance.Service

GetCurrentService returns the rule's default service: the first active one. (The per-rule CurrentServiceID pointer this used to consult was removed — it was never advanced at runtime, so "first active" was always the effective behavior.)

func (*Rule) GetDefaultModel

func (r *Rule) GetDefaultModel() string

GetDefaultModel returns the model from the currently selected service using load balancing tactic

func (*Rule) GetDefaultProvider

func (r *Rule) GetDefaultProvider() string

GetDefaultProvider returns the provider from the currently selected service using load balancing tactic

func (*Rule) GetScenario

func (r *Rule) GetScenario() RuleScenario

GetScenario returns the scenario, defaulting to openai if empty

func (*Rule) GetServices

func (r *Rule) GetServices() []*loadbalance.Service

GetServices returns the services to use for this rule

func (*Rule) GetTacticType

func (r *Rule) GetTacticType() loadbalance.TacticType

GetTacticType returns the load balancing tactic type

func (*Rule) GetUUID

func (r *Rule) GetUUID() string

GetUUID returns the rule UUID

func (*Rule) ToJSON

func (r *Rule) ToJSON() interface{}

ToJSON implementation

type RuleFlags

type RuleFlags struct {
	// CursorCompat enables Cursor compatibility handling (rich content normalization, stream usage stripping, tool gating).
	CursorCompat bool `json:"cursor_compat,omitempty" yaml:"cursor_compat,omitempty"`

	// CursorCompatAuto enables Cursor auto-detection based on request headers.
	CursorCompatAuto bool `json:"cursor_compat_auto,omitempty" yaml:"cursor_compat_auto,omitempty"`

	// SkipUsage strips the `usage` field from both streaming and non-streaming responses.
	SkipUsage bool `json:"skip_usage,omitempty" yaml:"skip_usage,omitempty"`

	// CustomUserAgent overrides the User-Agent header sent to upstream providers.
	// Empty value means do not override.
	CustomUserAgent string `json:"custom_user_agent,omitempty" yaml:"custom_user_agent,omitempty"`

	// UseMaxCompletionTokens rewrites the `max_tokens` request field to `max_completion_tokens`
	// (OpenAI's newer field name for o1/o3/gpt-5 family models).
	UseMaxCompletionTokens bool `json:"use_max_completion_tokens,omitempty" yaml:"use_max_completion_tokens,omitempty"`

	// UseMaxTokens rewrites the `max_completion_tokens` request field back to the legacy
	// `max_tokens` field. Use this for providers or models that reject `max_completion_tokens`.
	UseMaxTokens bool `json:"use_max_tokens,omitempty" yaml:"use_max_tokens,omitempty"`

	// OpenAIEndpointOverride forces the OpenAI endpoint selection (chat or
	// responses), overriding the capability-aware adaptive router. Empty or
	// "auto" preserves adaptive behavior. OpenAI providers only; Anthropic
	// and Google providers ignore this. On Codex OAuth providers, "chat"
	// is silently ignored (Codex has no Chat endpoint) and a warning is logged.
	OpenAIEndpointOverride string `json:"openai_endpoint_override,omitempty" yaml:"openai_endpoint_override,omitempty"`

	// BlockTools is a comma-separated list of tool names to strip from the
	// inbound request's tool list before it is forwarded upstream. Matching is
	// exact on the tool name as the client sent it. Empty means no blocking.
	BlockTools string `json:"block_tools,omitempty" yaml:"block_tools,omitempty"`

	// ThinkingEffort is the unified extended-thinking control. Recognized
	// values: "" (by client, default), "off" (force disabled), or one of
	// "low"/"medium"/"high"/"max" (force enabled with the matching budget).
	// Maps to budget_tokens for Anthropic and reasoning_effort for OpenAI
	// ("max" collapses to "high" for OpenAI which has no "max").
	ThinkingEffort ThinkingEffortLevel `json:"thinking_effort,omitempty" yaml:"thinking_effort,omitempty"`

	// CleanHeader strips x-anthropic-billing-header blocks from system messages.
	// Auto-enabled for billing scenarios (claude_code, claude_desktop) during protocol
	// transformation. Can be manually set to force enable/disable.
	CleanHeader bool `json:"clean_header,omitempty" yaml:"clean_header,omitempty"`

	// ClaudeCodeCompat rewrites any "system" role in the messages array to "user"
	// before forwarding. Claude Code sends system-role entries inside the messages
	// list (a non-standard extension); this flag normalizes them for third-party
	// providers that reject that role. Auto-applied when the scenario's
	// ClaudeCodeCompat flag is set.
	ClaudeCodeCompat bool `json:"claude_code_compat,omitempty" yaml:"claude_code_compat,omitempty"`

	// SessionAffinity pins a client session to the service it first landed on.
	// The value is the TTL in seconds (0 = disabled). Subsequent requests in
	// the same session keep hitting that service until the affinity entry
	// expires. This is a load-balancing concern and works independently of
	// smart routing.
	//
	// Rule-only: there is no scenario-level inheritance. The built-in Claude
	// Code / Claude Desktop / Codex rules default this to 1800s (30 min) via
	// init seeds + migration; any other rule is off unless explicitly set.
	SessionAffinity int `json:"session_affinity,omitempty" yaml:"session_affinity,omitempty"`

	// VisionProxyService enables the rule-scoped vision proxy when set. When a
	// request matched by this rule carries an image, the configured service
	// describes it and the image block is replaced with text before the
	// request reaches the downstream model. Same effect as the scenario-level
	// vision proxy (ScenarioConfig.Extensions["vision_proxy_service"]), only
	// narrower in scope; when both are set the rule-level service wins.
	VisionProxyService *VisionProxyService `json:"vision_proxy_service,omitempty" yaml:"vision_proxy_service,omitempty"`

	// Context1M enables Anthropic's 1M token context window for supported models
	// (Sonnet 4.6+, Opus 4.6+). When enabled, the gateway injects the
	// context-1m-2025-08-07 beta flag into the upstream request's
	// anthropic-beta header. The model name sent to Anthropic is unchanged —
	// only the beta header changes behavior.
	Context1M bool `json:"context_1m,omitempty" yaml:"context_1m,omitempty"`

	// ClaudeOrgID controls the anthropic-organization-id header sent upstream
	// for Claude OAuth providers. Organization attribution is opt-in: empty
	// (default) sends no organization header at all. "auto"
	// (typ.ClaudeOrgIDAuto) sends the organization captured at OAuth login
	// (OAuthDetail.ExtraFields["organization_id"]), which org-bound
	// entitlements (e.g. Cyber Verification) rely on. Any other value sends
	// that organization id verbatim.
	ClaudeOrgID string `json:"claude_org_id,omitempty" yaml:"claude_org_id,omitempty"`
}

RuleFlags represents per-rule feature flags.

type RuleScenario

type RuleScenario string

RuleScenario represents the scenario for a routing rule

const (
	ScenarioOpenAI        RuleScenario = "openai"
	ScenarioAnthropic     RuleScenario = "anthropic"
	ScenarioAgent         RuleScenario = "agent"
	ScenarioTeam          RuleScenario = "team" // Centrally deployed model shared across a team; hidden by default in the UI
	ScenarioCodex         RuleScenario = "codex"
	ScenarioClaudeCode    RuleScenario = "claude_code"
	ScenarioOpenCode      RuleScenario = "opencode"
	ScenarioXcode         RuleScenario = "xcode"
	ScenarioVSCode        RuleScenario = "vscode"
	ScenarioClaudeDesktop RuleScenario = "claude_desktop"
	ScenarioSmartGuide    RuleScenario = "_smart_guide"
	ScenarioGlobal        RuleScenario = "_global"  // Global flags that apply to all scenarios
	ScenarioEmbed         RuleScenario = "embed"    // Embedding application scenario; only serves /embeddings
	ScenarioImageGen      RuleScenario = "imagegen" // Image generation scenario; only serves /images/generations
)

func BuiltinScenarios

func BuiltinScenarios() []RuleScenario

func ParseScenarioProfile

func ParseScenarioProfile(raw RuleScenario) (base RuleScenario, profileID string)

ParseScenarioProfile splits "claude_code:p1" into base scenario and profile ID. "claude_code" returns ("claude_code", "").

func ProfiledScenarioName

func ProfiledScenarioName(base RuleScenario, profileID string) RuleScenario

ProfiledScenarioName combines base scenario and profile ID into "base:profileID".

func (RuleScenario) Base added in v0.260611.1

func (s RuleScenario) Base() RuleScenario

Base returns the base scenario, stripping any profile suffix. "claude_code:p1".Base() == "claude_code"; "claude_code".Base() == "claude_code".

func (RuleScenario) Is added in v0.260611.1

func (s RuleScenario) Is(base RuleScenario) bool

Is reports whether the scenario's base equals the given base scenario. Equivalent to s.Base() == base, but reads more naturally at call sites.

type ScanResult

type ScanResult struct {
	LocationID string  `json:"location_id"`
	Skills     []Skill `json:"skills"`
	Error      string  `json:"error,omitempty"`
}

ScanResult represents the result of scanning a location

type ScenarioConfig

type ScenarioConfig struct {
	Scenario   RuleScenario           `json:"scenario" yaml:"scenario"`
	Flags      ScenarioFlags          `json:"flags" yaml:"flags"`                               // Scenario configuration flags
	Extensions map[string]interface{} `json:"extensions,omitempty" yaml:"extensions,omitempty"` // Reserved for future extensions
}

ScenarioConfig represents configuration for a specific scenario

func (*ScenarioConfig) GetDefaultFlags

func (sc *ScenarioConfig) GetDefaultFlags() ScenarioFlags

GetDefaultFlags returns the effective flags for a scenario. If no routing mode (Unified/Separate/Smart) is explicitly set, Unified defaults to true so callers that depend on exactly one mode being active always see a consistent value. All other flags are returned as stored.

func (*ScenarioConfig) IsRecordingEnable added in v0.260702.1

func (sc *ScenarioConfig) IsRecordingEnable() bool

type ScenarioDescriptor

type ScenarioDescriptor struct {
	// ID is the stable scenario identifier stored on rules and scenario configs.
	ID RuleScenario `json:"id" yaml:"id"`
	// SupportedTransport declares which protocol surfaces may resolve rules bound to this scenario.
	SupportedTransport []ScenarioTransport `json:"supported_transport" yaml:"supported_transport"`
	// AllowRuleBinding controls whether API/CLI callers may create or update rules under this scenario.
	AllowRuleBinding bool `json:"allow_rule_binding" yaml:"allow_rule_binding"`
	// AllowDirectPathUse controls whether scenario-scoped HTTP paths like /openai/{scenario}/... are valid.
	AllowDirectPathUse bool `json:"allow_direct_path_use" yaml:"allow_direct_path_use"`
	// SupportsProfiles indicates whether this scenario supports named profiles.
	SupportsProfiles bool `json:"supports_profiles" yaml:"supports_profiles"`
}

func BuiltinScenarioDescriptors

func BuiltinScenarioDescriptors() []ScenarioDescriptor

func GetScenarioDescriptor

func GetScenarioDescriptor(scenario RuleScenario) (ScenarioDescriptor, bool)

func RegisteredScenarioDescriptors

func RegisteredScenarioDescriptors() []ScenarioDescriptor

type ScenarioFlags

type ScenarioFlags struct {
	Unified  bool `json:"unified" yaml:"unified"`   // Single configuration for all models
	Separate bool `json:"separate" yaml:"separate"` // Separate configuration for each model

	// Experimental feature flags (scenario-based opt-in)
	SmartCompact bool          `json:"smart_compact,omitempty" yaml:"smart_compact,omitempty"` // Enable smart compact (remove thinking blocks)
	RecordingV2  RecordingMode `json:"recording_v2,omitempty" yaml:"recording_v2,omitempty"`   // Enable scenario recording V2 (request/request_response/staged_request_response)
	// SkipUsage strips usage fields from streaming chunks and responses.
	// Use for clients that cannot handle usage data (e.g. Xcode). Equivalent
	// to the rule-level skip_usage flag but applied as a scenario-wide default.
	SkipUsage bool `json:"skip_usage,omitempty" yaml:"skip_usage,omitempty"`

	// ThinkingEffort is the unified extended-thinking control. Recognized
	// values: "" (by client, default), "off" (force disabled), or one of
	// "low"/"medium"/"high"/"max" (force enabled with the matching budget).
	ThinkingEffort ThinkingEffortLevel `json:"thinking_effort,omitempty" yaml:"thinking_effort,omitempty"`

	// CustomUserAgent overrides the outbound User-Agent header for every rule
	// under this scenario. Acts as a scenario-wide default; individual rules can
	// override it via RuleFlags.CustomUserAgent (rule value wins when non-empty).
	// Empty value means do not override. Same effect and injection path as the
	// rule-level flag — see internal/client/custom_ua_transport.go.
	CustomUserAgent string `json:"custom_user_agent,omitempty" yaml:"custom_user_agent,omitempty"`

	// ClaudeCodeCompat rewrites any "system" role in the messages array to "user"
	// before forwarding. Claude Code sends system-role entries inside the messages
	// list (a non-standard extension); this flag normalizes them so third-party
	// providers that reject that role do not error out.
	ClaudeCodeCompat bool `json:"claude_code_compat,omitempty" yaml:"claude_code_compat,omitempty"`
}

ScenarioFlags represents configuration flags for a scenario

type ScenarioTransport

type ScenarioTransport string
const (
	TransportOpenAI    ScenarioTransport = "openai"
	TransportAnthropic ScenarioTransport = "anthropic"
	TransportEmbed     ScenarioTransport = "embed"
	TransportImageGen  ScenarioTransport = "imagegen"
)

type SessionID added in v0.260409.1540

type SessionID struct {
	Source   SessionSource `json:"source"`
	Value    string        `json:"value"`
	IPBackup string        `json:"ip_backup,omitempty"` // Always store client IP when available
}

SessionID carries a resolved session identifier with its source. IPBackup is always populated (when available) as a fallback for rate limiting or logging.

func GetSessionID added in v0.260414.2000

func GetSessionID(ctx context.Context) SessionID

GetSessionID retrieves the sessionID from the context. Returns empty SessionID if not found in context.

func (SessionID) GetIP added in v0.260414.2000

func (s SessionID) GetIP() string

GetIP returns the IP address if available, first trying IPBackup then Value (for IP-fallback).

func (SessionID) IsEmpty added in v0.260409.1540

func (s SessionID) IsEmpty() bool

IsEmpty returns true for zero value (no session resolved).

func (SessionID) IsIPFallback added in v0.260409.1540

func (s SessionID) IsIPFallback() bool

IsIPFallback returns true for client-IP fallback sessions (no better session available). IP-fallback sessions should not be used for per-user client scoping.

func (SessionID) String added in v0.260409.1540

func (s SessionID) String() string

String returns the JSON-encoded representation, e.g. {"source":"user","value":"abc","ip_backup":"1.2.3.4"}.

type SessionSource added in v0.260409.1540

type SessionSource string

SessionSource identifies where a session ID was resolved from.

const (
	SessionSourceUser   SessionSource = "user" // Anthropic metadata.user_id
	SessionSourceHeader SessionSource = "hdr"  // X-Tingly-Session-ID header
	SessionSourceIP     SessionSource = "ip"   // ClientIP fallback
)

type Skill

type Skill struct {
	ID          string    `json:"id"`
	Name        string    `json:"name"`
	Filename    string    `json:"filename"`
	Path        string    `json:"path"`
	LocationID  string    `json:"location_id"`
	FileType    string    `json:"file_type"`
	Description string    `json:"description,omitempty"`
	ContentHash string    `json:"content_hash,omitempty"`
	Size        int64     `json:"size,omitempty"`
	ModifiedAt  time.Time `json:"modified_at,omitempty"`
	Content     string    `json:"content,omitempty"`
}

Skill represents a single skill file

type SkillLocation

type SkillLocation struct {
	ID               string    `json:"id"`
	Name             string    `json:"name"`
	Path             string    `json:"path"`
	IDESource        IDESource `json:"ide_source"`
	SkillCount       int       `json:"skill_count"`
	Icon             string    `json:"icon,omitempty"`
	IsAutoDiscovered bool      `json:"is_auto_discovered,omitempty"`
	IsInstalled      bool      `json:"is_installed,omitempty"`
	LastScannedAt    time.Time `json:"last_scanned_at,omitempty"`
	// GroupingStrategy: optional override for this specific location
	GroupingStrategy *GroupingStrategy `json:"grouping_strategy,omitempty"`
}

SkillLocation represents a skill location (directory)

type SpeedBasedParams

type SpeedBasedParams struct {
	MinSamplesRequired int     `json:"min_samples_required"` // Minimum samples before making decisions
	SpeedThresholdTps  float64 `json:"speed_threshold_tps"`  // Minimum acceptable tokens per second
	SampleWindowSize   int     `json:"sample_window_size"`   // Number of speed samples to keep
}

SpeedBasedParams holds parameters for speed-based tactic

func AsSpeedBasedParams

func AsSpeedBasedParams(p TacticParams) (SpeedBasedParams, bool)

type SpeedBasedTactic

type SpeedBasedTactic struct {
	MinSamplesRequired int     // Minimum samples before making decisions
	SpeedThresholdTps  float64 // Minimum acceptable tokens per second
	SampleWindowSize   int     // Number of speed samples to keep
}

SpeedBasedTactic implements load balancing based on token generation speed

func NewSpeedBasedTactic

func NewSpeedBasedTactic(minSamplesRequired int, speedThresholdTps float64, sampleWindowSize int) *SpeedBasedTactic

NewSpeedBasedTactic creates a new speed-based tactic

func (*SpeedBasedTactic) GetName

func (st *SpeedBasedTactic) GetName() string

func (*SpeedBasedTactic) GetType

func (st *SpeedBasedTactic) GetType() loadbalance.TacticType

func (*SpeedBasedTactic) SelectService

func (st *SpeedBasedTactic) SelectService(rule *Rule) *loadbalance.Service

SelectService selects service based on token generation speed

type Tactic

type Tactic struct {
	Type   loadbalance.TacticType `json:"type" yaml:"type"`
	Params TacticParams           `json:"params" yaml:"params"`
}

Tactic bundles the strategy type and its parameters together

func NewDefaultTactic added in v0.260716.1

func NewDefaultTactic(tacticType loadbalance.TacticType) Tactic

NewDefaultTactic returns a Tactic of the given type carrying that type's default params. Used when an API caller names a tactic without params.

func (*Tactic) Instantiate

func (tc *Tactic) Instantiate() LoadBalancingTactic

Instantiate converts the configuration into functional logic. An unset tactic (nil or Type==0) resolves to Random, matching the documented default in Rule.GetTacticType(); these previously disagreed (Adaptive vs Random), so unconfigured rules silently ran Adaptive.

func (*Tactic) UnmarshalJSON

func (tc *Tactic) UnmarshalJSON(data []byte) error

UnmarshalJSON handles the polymorphic decoding of TacticParams

type TacticParams

type TacticParams interface {
	// contains filtered or unexported methods
}

TacticParams represents parameters for different load balancing tactics This is a sealed type that can only be one of the specific tactic parameter types

func DefaultCapacityBasedParams added in v0.260409.1540

func DefaultCapacityBasedParams() TacticParams

DefaultCapacityBasedParams returns default capacity-based parameters

func DefaultRandomParams

func DefaultRandomParams() TacticParams

DefaultParams returns default parameters for each tactic type

func DefaultSpeedBasedParams

func DefaultSpeedBasedParams() TacticParams

func DefaultTierParams added in v0.260604.1

func DefaultTierParams() TacticParams

DefaultTierParams returns the default tier-tactic params. Random within a tier is a sensible default: it spreads load across equally-tiered services without requiring extra config.

func NewRandomParams

func NewRandomParams() TacticParams

NewRandomParams creates parameters for the random tactic.

type ThinkingEffortLevel

type ThinkingEffortLevel = string

ThinkingEffortLevel represents the thinking effort level for extended thinking

const (
	// ThinkingEffortDefault is the "by client" sentinel: pass the client's
	// thinking config through unchanged. Empty string so omitempty hides it.
	ThinkingEffortDefault ThinkingEffortLevel = ""
	// ThinkingEffortOff is the "explicitly disabled" sentinel: strip thinking
	// from the outbound request regardless of what the client sent.
	ThinkingEffortOff    ThinkingEffortLevel = "off"
	ThinkingEffortLow    ThinkingEffortLevel = "low"
	ThinkingEffortMedium ThinkingEffortLevel = "medium"
	ThinkingEffortHigh   ThinkingEffortLevel = "high"
	ThinkingEffortMax    ThinkingEffortLevel = "max"
)

type ThinkingMode

type ThinkingMode string

ThinkingMode is retained for backward compatibility with the deprecated per-scenario / per-rule "thinking_mode" flag. New code should use ThinkingEffortLevel (with "off" / level / "" semantics) instead.

const (
	ThinkingModeDefault  ThinkingMode = "default"  // Use client request config
	ThinkingModeEnable   ThinkingMode = "enable"   // Force extended thinking on
	ThinkingModeDisable  ThinkingMode = "disable"  // Force extended thinking off
	ThinkingModeAdaptive ThinkingMode = "adaptive" // Convert existing thinking config to enabled
	ThinkingModeForce    ThinkingMode = "force"    // Deprecated alias for ThinkingModeEnable
)

type TierParams added in v0.260604.1

type TierParams struct {
	WithinTierTactic loadbalance.TacticType `json:"within_tier_tactic"`
}

TierParams holds parameters for the tier-based failover tactic. WithinTierTactic decides how to share load among services that share the same Tier value (i.e. that are "tied" at a tier).

type TierTactic added in v0.260604.1

type TierTactic struct {
	WithinTierTactic loadbalance.TacticType
}

TierTactic implements tier-based failover load balancing.

Services are bucketed by Service.Tier (ascending; lower tier number tried first; T0 is the highest-priority tier). The lowest-tier bucket containing at least one service whose circuit breaker permits a request is selected. Within that bucket, the WithinTierTactic (e.g. random) chooses the final service. This yields:

  • "Direct + fallback" when each service has a distinct Tier.
  • "Two equivalent services share a tier, with a backup tier below" when several services share the same Tier.

Recovery is automatic: every request reconsiders the buckets from the top, so once a lower-tier service's breaker closes the routing returns to it without any extra coordination.

func NewTierTactic added in v0.260604.1

func NewTierTactic(within loadbalance.TacticType) *TierTactic

NewTierTactic creates a tier tactic with the given sub-tactic used to break ties within a tier.

func (*TierTactic) GetName added in v0.260604.1

func (pt *TierTactic) GetName() string

func (*TierTactic) GetType added in v0.260604.1

func (pt *TierTactic) GetType() loadbalance.TacticType

func (*TierTactic) PreviewService added in v0.260716.1

func (pt *TierTactic) PreviewService(rule *Rule) *loadbalance.Service

PreviewService selects exactly like SelectService but never claims a breaker probe slot. Read-only surfaces (e.g. the admin current-service preview) must use it: a preview that consumed the single half-open probe would block real traffic from probing the recovering service.

func (*TierTactic) SelectService added in v0.260604.1

func (pt *TierTactic) SelectService(rule *Rule) *loadbalance.Service

SelectService returns the highest-priority service whose breaker is closed (or half-open and unclaimed). It returns nil when every active service is currently tripped — callers should surface the original upstream error in that case.

Selection is two-phase per tier: candidates are gathered with the non-consuming IsAvailable read, the sub-tactic picks one, and only the picked service claims a breaker slot via Allow. Claiming for every candidate up front would consume half-open probe slots of services that are never dispatched; with no outcome ever reported, those slots stayed taken and the service could never finish recovering.

type ToolDescriptor added in v0.260514.1

type ToolDescriptor struct {
	Name           string             `json:"name"`
	SourceID       string             `json:"source_id"`
	Visibility     ToolVisibility     `json:"visibility"`
	Implementation ToolImplementation `json:"implementation"`
	Provider       ToolProvider       `json:"provider"`
	Description    string             `json:"description,omitempty"`
}

type ToolImplementation added in v0.260514.1

type ToolImplementation string
const (
	ToolImplementationMCP     ToolImplementation = "mcp"
	ToolImplementationVirtual ToolImplementation = "virtual"
)

type ToolProvider added in v0.260514.1

type ToolProvider string
const (
	ToolProviderBuiltin ToolProvider = "builtin"
	ToolProviderCustom  ToolProvider = "custom"
)

type ToolVisibility added in v0.260514.1

type ToolVisibility = coretool.ToolVisibility

type TransportKey added in v0.260409.1540

type TransportKey struct {
	ProviderUUID string    `json:"provider_uuid"`
	SessionID    SessionID `json:"session_id,omitempty"` // Included for per-session OAuth providers
}

TransportKey uniquely identifies a cached HTTP transport. The key is based on provider + session (for OAuth providers) so that: - API-key providers share transports across sessions (TCP connection pool reuse) - OAuth providers get per-session transports for proper isolation

Note: ProxyURL is NOT part of the key because it's a provider configuration, not a separate dimension for connection pooling. When a provider's proxy changes, the old transport should be invalidated and a new one created.

func (TransportKey) IsSessionScoped added in v0.260414.2000

func (k TransportKey) IsSessionScoped() bool

IsSessionScoped returns true when this key is bound to a specific user session.

func (TransportKey) String added in v0.260409.1540

func (k TransportKey) String() string

String returns a stable string for use as map key.

type VModelDetail added in v0.260514.1

type VModelDetail = ai.VModelDetail

VModelDetail contains virtual-model provider configuration Type alias for backward compatibility with common/provider

type VisionProxyService added in v0.260604.1

type VisionProxyService struct {
	Provider string `json:"provider" yaml:"provider"`
	Model    string `json:"model" yaml:"model"`
}

VisionProxyService identifies the upstream used to describe images for the vision proxy: a provider UUID plus a model name (the system's standard two-element service identity).

Jump to

Keyboard shortcuts

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