xyz_rust/config.rs
1// 派发配置:模式词、能力开关与内置参数。零值即默认可直接使用;
2// 命令行 --xyz.* 与各模式的裸名 flag 优先级高于这里的字段值。
3
4use std::time::Duration;
5
6use crate::logx;
7
8/// ModeWords 重命名内建模式关键词。留空的字段保持默认(serve、mcp、
9/// help)。
10#[derive(Debug, Clone, Default)]
11pub struct ModeWords {
12 pub serve: String,
13 /// 独立的 HTTP 模式(仅 REST + /openapi.json,不挂 /mcp;spec §13.1)。
14 pub http: String,
15 pub mcp: String,
16 pub help: String,
17}
18
19/// Capabilities 在运行时开关通道(与 build feature 相互独立)。零值保持
20/// 全部可用。禁用通道只移除它自己的运行时路径:模式词(serve/mcp/help)
21/// 与 -v/--version 继续工作,被禁用的模式以清晰错误应答。被禁通道的
22/// CLI()/HTTP()/MCP() 配置照常编译与运行——只是不再被消费。
23#[derive(Debug, Clone, Copy, Default)]
24pub struct Capabilities {
25 /// 不在命令注册表上生成子命令(mcp/serve/help/-v 仍可用)。
26 pub no_cli: bool,
27 /// mcp 模式不可用(stdio/http 都拒绝)。
28 pub no_mcp: bool,
29 /// serve 模式不可用。
30 pub no_http: bool,
31}
32
33/// Config 调整派发器。零值保持全部默认。
34#[derive(Debug, Clone, Default)]
35pub struct Config {
36 pub modes: ModeWords,
37 pub capabilities: Capabilities,
38
39 /// serve 与 mcp(http) 模式的默认监听地址(各模式自己的 --addr flag
40 /// 优先)。
41 pub addr: String,
42 /// 开启 serve REST 与 MCP http 传输的 Bearer 凭据校验,每个元素是
43 /// 一个可接受的 token;空表示不校验。命令行写法:--xyz.bearer=tok1,tok2
44 /// (stdio 传输为本地进程,不受影响)。
45 pub bearer_tokens: Vec<String>,
46
47 /// 库自身诊断的日志级别(logx 输出到 stderr)。零值(LevelUnset)
48 /// 保持默认 Info。命令行:--xyz.log-level=debug|info|warn|error。
49 pub log_level: crate::logx::Level,
50 /// serve 模式的每请求超时(TimeoutLayer);0 = 不设超时。
51 /// (标准头超时在 Rust 实现里未单独配置,见 README 与 Go 版差异节。)
52 pub timeout: Duration,
53 /// cert_file/key_file 同时给定则 serve 以 TLS 监听
54 /// (--xyz.tls-cert/--xyz.tls-key)。
55 pub cert_file: String,
56 pub key_file: String,
57 /// CORSOrigins 非空则开启 CORS:逐个 Origin 放行("*" 表示任意来源),
58 /// OPTIONS 预检在鉴权之前应答。命令行:--xyz.cors=origin1,origin2。
59 pub cors_origins: Vec<String>,
60
61 /// 界面语言覆盖:""=自动(--xyz.lang flag > 本字段 > LANG/LC_ALL 环境
62 /// 检测 > 英文默认)。取值 "en" | "zh-CN"。
63 pub lang: String,
64 /// 用户的多语言内容覆盖表:语言 → (消息键 → 文本)。键名见 lang 目录
65 /// (xyz-spec §15.8 的规范键表)。
66 pub translations: std::collections::HashMap<String, std::collections::HashMap<String, String>>,
67
68 /// serve/mcp 启动时注入的通道级默认参数(字段线上名 → 字符串值):
69 /// 请求/调用未显式提供时自动补上,优先级高于全局 default 属性、低于
70 /// 显式入参与接口默认。命令行:--default k=v(可重复/逗号分隔对)。
71 pub channel_defaults: std::collections::HashMap<String, String>,
72
73 /// help 总览的自定义文本块:前者原样插在总览开头(程序名/描述/版本/
74 /// 仓库地址等自己拼),后者插在结尾(命令表之后,即使命令表被隐藏也
75 /// 打印)。空 = 不插入。
76 pub help_before: String,
77 pub help_after: String,
78
79 /// 应用名(spec §11.6/§12.6):X-App-Name 响应头与 MCP serverInfo.name。
80 /// 空 = 二进制 basename。
81 pub name: String,
82 /// 应用版本(spec §11.6/§12.6):X-App-Version 响应头与
83 /// serverInfo.version。空 = version::version()(默认 "dev")。
84 /// 与 xyz 库自身的版本(version::SDK_VERSION → X-XYZ-Version)无关。
85 pub version: String,
86 /// 代码级全局默认格式(spec §10.7 第四层):""|auto = 按 TTY 解析为
87 /// format_interactive / format_piped。命令行 --xyz.format(第二层,
88 /// format_from_flag 置位)与逐命令 CliHints.format(第三层)优先。
89 pub format: String,
90 /// format=auto 时交互式终端下的具体格式(默认 text)。
91 pub format_interactive: String,
92 /// format=auto 时非交互(管道/重定向/其他程序调用)下的具体格式
93 /// (默认 jsonl)。
94 pub format_piped: String,
95 /// 标记 format 来自命令行 --xyz.format(命令行层,高于逐命令 hint)。
96 pub format_from_flag: bool,
97 /// 附加到每个 HTTP 响应的自定义静态头(键值原样写入;与自动
98 /// X-App-*/X-XYZ-* 头并存)。命令行:--xyz.header k=v(可重复)。
99 pub response_headers: Vec<(String, String)>,
100 /// 关闭自动服务器上下文头(HTTP 的 X-App-*/X-XYZ-* 与 MCP 结果的
101 /// _meta.xyz):spec §11.6/§12.8 的单一开关。自定义头不受影响。
102 /// 命令行:--xyz.no-server-headers。
103 pub no_server_headers: bool,
104 /// 接受未知 query 参数(默认 false = 严格:400 `invalid_input`,消息列出
105 /// 该路由允许的参数集;spec §11.2)。静默忽略会让拼错/已移除的参数看起来
106 /// 生效。命令行:--xyz.allow-unknown-query。
107 pub allow_unknown_query: bool,
108}
109
110impl Config {
111 pub fn default_log_level(&self) -> logx::Level {
112 self.log_level
113 }
114
115 /// 应用名:config 覆盖 > 二进制 basename(spec §11.6/§12.6)。
116 pub fn resolved_name(&self) -> String {
117 if !self.name.is_empty() {
118 return self.name.clone();
119 }
120 crate::cli::bin_name()
121 }
122
123 /// 应用版本:config 覆盖 > 版本槽(默认 "dev")。
124 pub fn resolved_version(&self) -> String {
125 if !self.version.is_empty() {
126 return self.version.clone();
127 }
128 crate::version::version().to_string()
129 }
130}