config

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package config 定义 core 的配置文件模型、加载与校验。

配置只描述事实,不承载行为:它不知道渠道客户端与插件宿主的存在,装配由 server 层完成。凭据一律只写环境变量名,配置文件里不出现密钥。

Index

Constants

View Source
const (
	DefaultListen       = "127.0.0.1:8787"
	DefaultLogFormat    = "json"
	DefaultLogLevel     = "info"
	DefaultTimeout      = 120 * time.Second
	DefaultPluginDir    = "plugins"
	DefaultMaxBodyBytes = 32 << 20
	// DefaultMaxTokens 是源请求未带 max_tokens 时给 Claude 补的值。它与
	// relay.DefaultClaudeMaxTokens 是同一个数:分层红线不允许 config 导入 relay,
	// 只能各写一份,改一处要同时改另一处。
	DefaultMaxTokens = 4096
	// MaxRetries 是渠道重试次数的上限,与 channel.MaxRetries 保持一致。
	MaxRetries = 10
	// 渠道亲和的参数默认值。
	DefaultAffinityTableSize = 8192
	DefaultAffinityTTL       = 10 * time.Minute
	// DefaultAffinityMinPrefixBytes 是前缀的字节下限。按中英文混排估算,4096 字节
	// 大致是一千出头到两千 tokens,落在上游最小可缓存长度(按模型 512 到 4096
	// tokens)的下半段。它是个启发式,估不准时应当按实际模型调高。
	DefaultAffinityMinPrefixBytes = 4096
	// DefaultInChannelStatuses 与 DefaultFailoverStatuses 是两组重试判据的默认
	// 取值。它们与 channel 包里内置的集合是同一组值:分层红线不允许 config 导入
	// channel,只能各写一份,改一处要同时改另一处。
	DefaultInChannelStatuses = "408,429,500,502,503,504"
	DefaultFailoverStatuses  = "408,401,403,429,500-599"
)

默认值。只在这里写一次,Load 与文档都以它为准。

Variables

This section is empty.

Functions

func Match

func Match(pattern, name string) bool

Match 报告名字是否命中该模式。模式不合法时返回 false。

Types

type Account added in v0.7.0

type Account struct {
	Name    string            `yaml:"name"`
	KeyEnv  string            `yaml:"key_env"`
	Headers map[string]string `yaml:"headers"`
}

Account 是一个上游账号。账号不是渠道,渠道在 auth.accounts 里按名字引用它, 加载时展开成多条渠道。单列一层是因为同一把凭据常要配给多种方言或同一上游的多个 入口,写成渠道就得把基址、路径、超时逐条抄一遍。

Headers 是账号级的附加请求头,用于上游按 workspace 或 organization 隔离的场景。

type Affinity added in v0.2.0

type Affinity struct {
	// TableSize 是前缀链记忆的条数上限。不大于零时没有会话标识的客户端不参与
	// 亲和。
	TableSize *int `yaml:"table_size"`
	// TTL 是前缀链记忆的寿命,按上游缓存的寿命设。
	TTL Duration `yaml:"ttl"`
	// MinPrefixBytes 是前缀的字节下限,短于它时不做亲和。
	MinPrefixBytes *int `yaml:"min_prefix_bytes"`
}

Affinity 是渠道亲和的参数。哪些渠道参与亲和由 Model.Affinity 的组名决定, 这里只放参数。

三个字段都是可选的,不写就用本文件里的默认常量。用指针是为了把「没写」与 「显式写成 0」区分开:最小前缀长度写成 0 表示不做这个判断。

type Auth

type Auth struct {
	// Style 取 bearer、x-api-key、query、custom 或 none。
	Style string `yaml:"style"`
	// KeyEnv 是凭据所在的环境变量名。
	KeyEnv string `yaml:"key_env"`
	// Accounts 是引用的顶层账号名,与 KeyEnv 互斥。它也是加载期字段:Expand
	// 把账号的 KeyEnv 填进展开出的每条渠道,这里随之清空,平铺形态因而与手写
	// 的等价配置完全一致。
	Accounts []string `yaml:"accounts"`
	// Header 是 Style 为 custom 时的请求头名。
	Header string `yaml:"header"`
	// Query 是 Style 为 query 时的查询参数名。
	Query string `yaml:"query"`
}

Auth 是渠道的鉴权方式。凭据值只从 KeyEnv 指定的环境变量读取,或由 Accounts 引用的顶层账号给出。

type Backoff added in v0.7.0

type Backoff struct {
	// Base 是第一次重试前的等待时长,第 n 次重试等待 base × 2^(n-1)。
	Base Duration `yaml:"base"`
	// Max 是指数退避的上限。
	Max Duration `yaml:"max"`
	// MaxRetryAfter 是上游 Retry-After 的上限,超过就不再重试,直接换候选。
	MaxRetryAfter Duration `yaml:"max_retry_after"`
}

Backoff 是渠道内重试的退避参数。三个字段都可以不写,不写就用内置常量。

上限与 Retry-After 都放在渠道级而不引入全局默认值来源:退避是「这条上游 多久能再收一个请求」的属性,不同上游不一样,与账号、方言无关。

type Behavior added in v0.7.0

type Behavior struct {
	// MaxBodyBytes 是客户端请求体的字节上限。
	MaxBodyBytes *int `yaml:"max_body_bytes"`
	// DefaultMaxTokens 是源请求未带 max_tokens 时给 Claude 补的值。
	DefaultMaxTokens *int `yaml:"default_max_tokens"`
}

Behavior 是进程级的行为默认值,YAML 里写成 defaults 段。

两个数都是「装配时读一次、运行期不再变」的进程级参数,因此不塞进渠道或模型 这些既有段:请求体上限属于整个进程,补 max_tokens 是内核的部署级行为。用指针 是为了把「没写」与「显式写成 0」区分开,0 不是合法值,校验会拦下。

内核还有 tool_loss_policy、model_suffix、thinking_adapter 三个行为开关, 这里没有对应的键:前两个会改变「哪个模型名参与匹配」,打开之后 models[].upstream 与 ${model} 的语义跟着变,要另写一节语义说明;tool_loss_policy 等「要不要允许 reject」的口径定了再上。在它们落地之前,宿主仍可在 Go 侧构造 relay.Options 注入内核。

type Channel

type Channel struct {
	Name       string            `yaml:"name"`
	Dialect    string            `yaml:"dialect"`
	BaseURL    string            `yaml:"base_url"`
	Path       string            `yaml:"path"`
	Auth       Auth              `yaml:"auth"`
	Timeout    Duration          `yaml:"timeout"`
	MaxRetries *int              `yaml:"max_retries"`
	Headers    map[string]string `yaml:"headers"`
	Backoff    Backoff           `yaml:"backoff"`
	// FailoverStatuses 覆盖全局的 retry.failover,空串表示沿用全局。
	FailoverStatuses string `yaml:"failover_statuses"`
}

Channel 是一个上游渠道。BaseURL 是渠道基址,Path 为空时按方言取默认路径。

type Config

type Config struct {
	// Path 是配置文件的绝对路径,由 Load 填入。Parse 不填。
	Path   string `yaml:"-"`
	Listen string `yaml:"listen"`
	Log    Log    `yaml:"log"`
	// Behavior 是 defaults 段,放进程级的行为默认值。
	//
	// 字段名不叫 Defaults:Config.Defaults() 已经是公开方法,同名字段与它冲突。
	// YAML 键固定写作 defaults,那是配置文件里的名字,不随 Go 侧命名走。
	Behavior Behavior `yaml:"defaults"`
	// Accounts 是加载期的顶层账号清单,Expand 之后为空。
	Accounts []Account `yaml:"accounts"`
	Channels []Channel `yaml:"channels"`
	Models   []Model   `yaml:"models"`
	Plugins  Plugins   `yaml:"plugins"`
	Affinity Affinity  `yaml:"affinity"`
	// Retry 是重试判据的两组状态码集合。
	Retry Retry `yaml:"retry"`
}

Config 是一份完整的服务配置。

func Load

func Load(path string) (*Config, error)

Load 读取并校验配置文件。

解码开启 KnownFields:拼错的字段在加载时报错,而不是被静默忽略。相对路径一律 以配置文件所在目录为基准,因此工作目录变化不会改变行为。

func Parse

func Parse(reader io.Reader) (*Config, error)

Parse 从阅读器解析配置并校验。相对路径保留原样,调用方需要时自行归一。

顶层账号是加载期形态,Parse 会自己调一次 Expand,因此返回值里只剩下展开后的 渠道名,没有账号引用。校验跑两次:第一次看原始写法,账号引用关系(账号是否 存在、有没有人引用)只有在展开之前才看得清;第二次看平铺形态,用来抓展开名 与手写渠道名撞车这类展开之后才出现的重名。见 Config.Expand 的注释。

func (*Config) AffinityMinPrefixBytes added in v0.2.0

func (c *Config) AffinityMinPrefixBytes() int

AffinityMinPrefixBytes 返回前缀的字节下限。返回零表示不做这个判断。

func (*Config) AffinityTTL added in v0.2.0

func (c *Config) AffinityTTL() time.Duration

AffinityTTL 返回前缀链记忆的寿命。

func (*Config) AffinityTableSize added in v0.2.0

func (c *Config) AffinityTableSize() int

AffinityTableSize 返回前缀链记忆的条数上限。

func (*Config) ChannelByName

func (c *Config) ChannelByName(name string) (Channel, bool)

ChannelByName 按名字取渠道配置。

func (*Config) DefaultMaxTokens added in v0.7.0

func (c *Config) DefaultMaxTokens() int

DefaultMaxTokens 返回源请求未带 max_tokens 时给 Claude 补的值。没写 defaults.default_max_tokens 时返回 DefaultMaxTokens。

func (*Config) Defaults

func (c *Config) Defaults()

Defaults 填入未写的默认值。校验前调用。

func (*Config) EnabledPlugins

func (c *Config) EnabledPlugins() []Plugin

EnabledPlugins 返回启用中的插件,按 order 升序排列;order 相同时保持配置顺序。

func (*Config) Expand added in v0.7.0

func (c *Config) Expand() *Config

Expand 返回展开顶层账号之后的副本,原对象不改。

顶层账号是加载期形态,因此这个方法是那条约定的唯一入口:Load 与 Parse 解析 完自己会调一次,从它们拿到的 Config 已经是平铺的。程序化构造带账号的 Config 之后要自己再调一次,否则展开出的渠道没被建出来,渠道的 Auth.KeyEnv 是空的。

展开按内容判断是否还有账号数据:顶层 accounts 为空且没有渠道写 auth.accounts 时直接返回副本。判断基于字段内容而不是调用历史,所以平铺形态再展开不会让 候选数按账号数相乘,同一个对象重复调用结果也一致。

展开会清掉账号层的痕迹:顶层 accounts 与每条渠道的 auth.accounts 都不保留, 所以返回的 Config 能直接序列化后重新加载。

func (*Config) FailoverStatusesFor added in v0.7.0

func (c *Config) FailoverStatusesFor(channel Channel) ([]int, error)

FailoverStatusesFor 返回该渠道生效的换候选状态码集合,升序。渠道写了 failover_statuses 就用它,否则用全局的 retry.failover,都没写时用内置默认集合。

func (*Config) MaxBodyBytes added in v0.7.0

func (c *Config) MaxBodyBytes() int64

MaxBodyBytes 返回请求体的字节上限。没写 defaults.max_body_bytes 时返回 DefaultMaxBodyBytes,因此不配置时的行为与逐字段写死默认值的版本一致。

func (*Config) PluginConfig

func (c *Config) PluginConfig(key string) map[string]any

PluginConfig 返回指定插件的配置对象,未配置时返回空 map。

func (*Config) Resolve

func (c *Config) Resolve(model string) []Route

Resolve 返回该模型名的候选路由,按配置顺序排列。没有匹配项时返回空切片。

func (*Config) RetryStatuses added in v0.7.0

func (c *Config) RetryStatuses() ([]int, error)

RetryStatuses 返回生效的渠道内重试状态码集合,升序。没写 retry.in_channel 时返回内置默认集合。装配层把它填进每个渠道的 Spec。

func (*Config) Validate

func (c *Config) Validate() error

Validate 校验配置。返回的错误说明第几条配置出了什么问题。

type Duration

type Duration time.Duration

Duration 是配置里可读的时长,写法与 time.ParseDuration 一致,例如 120s、1m30s。 为兼容只写数字的配置,纯数字按秒解释。

func (Duration) Duration

func (d Duration) Duration() time.Duration

Duration 返回标准库时长。

func (Duration) MarshalYAML

func (d Duration) MarshalYAML() (any, error)

MarshalYAML 按 time.Duration 的字符串形式写出。

func (Duration) String

func (d Duration) String() string

String 返回可读时长。

func (*Duration) UnmarshalJSON

func (d *Duration) UnmarshalJSON(data []byte) error

UnmarshalJSON 让 Duration 在 JSON 里也能工作,便于 CLI 输出配置快照。

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML 支持字符串与数字两种写法。

type Key added in v0.7.0

type Key struct {
	// Path 是配置路径。
	//
	// 嵌套用点号连接,列表在字段名后加 [] 再写元素字段,例如 channels[].timeout。
	// 不写成 channels.timeout:后者读起来像 channels 自己有个 timeout 字段,而实际
	// 字段在列表元素上;[] 把这一层明写出来。元素本身是标量的列表(如
	// channels[].auth.accounts)路径就到字段名为止,类型名里的 [] 已经说明了它是列表。
	Path string
	// Type 是类型名,如 string、int、duration、map[string]string。
	Type string
	// Default 是默认值的可读形式。没有默认值的字段写「必填」或「空」。
	Default string
}

Key 是配置键表里的一条。CLI 的帮助、新配置模板与 `config path` 输出都从这份 表生成,同一份字段信息不再抄三份。

func Keys added in v0.7.0

func Keys() []Key

Keys 返回配置键表,按 Config 的字段声明顺序排列。

路径与类型由 Config 的字段与 yaml tag 现算,字段改名或加减字段时表跟着变, 不存在第二份手抄的字段清单。表里没有「是否可 set」这一列:那是 CLI `config set` 的策略,不是配置本身的事实,钉进 core 的公开面等于把一条命令行的策略写进库的 兼容承诺;CLI 自己维护可写白名单更合适。

type Log

type Log struct {
	Format string `yaml:"format"`
	Level  string `yaml:"level"`
}

Log 是日志配置。

type Matcher

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

Matcher 是一个已校验的模型名匹配器。

func CompileMatch

func CompileMatch(pattern string) (Matcher, error)

CompileMatch 校验匹配式并返回匹配器。

支持两个通配符:* 匹配任意长度的一段(含 / 与 :),? 匹配一个字符。 其余字符按字面比较。模型名按 UTF-8 字符逐个比较。

func (Matcher) Match

func (m Matcher) Match(name string) bool

Match 报告名字是否命中。按 rune 比较,通配符不跨字符。

func (Matcher) Pattern

func (m Matcher) Pattern() string

Pattern 返回原始匹配式。

type Model

type Model struct {
	Match    string `yaml:"match"`
	Channel  string `yaml:"channel"`
	Upstream string `yaml:"upstream"`
	Dialect  string `yaml:"dialect"`
	Affinity string `yaml:"affinity"`
}

Model 是一条模型路由规则。Match 支持 * 通配,同一个模型可以有多条规则, 按配置顺序依次尝试。

Upstream 是发往上游的模型名,可以写 ${model} 占位符,替换成客户端请求里 经插件改写后真正参与匹配的那个模型名。写法与校验规则见 Validate 与 docs/config.md。

Affinity 是渠道亲和的组名。命中该模型的规则里,组名相同的候选组成一个池, 池里的渠道被当作可互换的;同一段会话的连续请求会在池内粘住一条,池外的候选 按配置顺序排在池后面兜底。留空表示不参与。

type Plugin

type Plugin struct {
	Key     string         `yaml:"key"`
	Enabled bool           `yaml:"enabled"`
	Order   int            `yaml:"order"`
	Config  map[string]any `yaml:"config"`
}

Plugin 是一个插件的启用状态与顺序。

type Plugins

type Plugins struct {
	// Dir 是插件目录,相对路径以配置文件所在目录为基准。
	Dir  string   `yaml:"dir"`
	List []Plugin `yaml:"list"`
}

Plugins 是插件目录与插件清单。

type Retry added in v0.7.0

type Retry struct {
	// InChannel 是渠道内原地重试的状态码集合。
	InChannel string `yaml:"in_channel"`
	// Failover 是换下一条候选的状态码集合,渠道级 failover_statuses 可以覆盖它。
	Failover string `yaml:"failover"`
}

Retry 是重试判据的两组状态码集合,都写成逗号分隔的字符串。

in_channel 是渠道内原地重试的集合,failover 是换下一条候选的集合。 failover 必须包含 in_channel:凡是在渠道内重试过的失败,重试耗尽后还要能降级, 否则会出现「重试了却不换候选」的死角。401 与 403 只在 failover 一侧:它们说明 凭据或权限有问题,同一条渠道原地重试不会变好。

写成字符串而不是 YAML 数组:区间写法(500-599)与混类型数组难写也难校验。 范围是 100 到 599,每项要么是整数,要么是 a-b 且 a <= b。

type Route

type Route struct {
	Channel  string
	Upstream string
	Dialect  dialect.Name
	// Affinity 取自语规则,是这条候选所属的亲和组名,空串表示不参与。
	Affinity string
}

Route 是解析后的一条候选路由。

Jump to

Keyboard shortcuts

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