Documentation

HotPlex Worker Gateway — Configuration Guide

configs/ 目录包含完整的配置体系。项目遵循 Convention Over Configuration 原则——代码内嵌生产就绪的默认值 (internal/config/config.go:Default()),所有 YAML 字段均可选。


目录结构

configs/
├── config.yaml          # Base — 生产中性默认值,覆盖代码 Default() 的部分字段
├── config-dev.yaml      # Dev  — 继承 base,覆盖开发环境值
├── config-prod.yaml     # Prod — 继承 base,覆盖生产环境值
├── env.example          # 环境变量模板 → cp 到 .env 使用
└── README.md

快速开始

cp configs/env.example ~/.hotplex/.env   # 填入 HOTPLEX_JWT_SECRET、HOTPLEX_ADMIN_TOKEN_1
make dev                                # 自动使用 config-dev.yaml

配置优先级(从低到高)

优先级 来源 说明
1 Default() 代码默认值 internal/config/config.go 编译时内嵌
2 父级配置文件 inherits 递归加载,支持多级继承与循环检测
3 当前配置文件 -config 指定的 YAML
4 环境变量 HOTPLEX_* Viper AutomaticEnv + applyMessagingEnv() 手动映射
5 Secrets Provider JWT/Token 等敏感字段,仅此渠道

环境变量映射公式:HOTPLEX_<SECTION>_<FIELD>,全大写下划线连接。 例如 pool.max_sizeHOTPLEX_POOL_MAX_SIZE

编号式环境变量支持令牌轮转:HOTPLEX_ADMIN_TOKEN_1HOTPLEX_ADMIN_TOKEN_N


配置继承

子配置通过 inherits 指定父文件,只需列出与 base 不同的字段。支持多级继承和循环检测。

inherits: config.yaml
log:
  level: "debug"

完整字段参考

默认值列config.yaml 的值(即实际生效的 base 值)。括号内标注代码 Default() 的原始值,仅当两者不同时显示。

gateway — WebSocket 网关

控制 WebSocket 连接的底层传输参数。Hub 为每个连接启动独立的 ReadPump / WritePump goroutine,通过带缓冲的 broadcast channel 路由事件。

字段 类型 默认值 热重载 说明
addr string :8888 网关监听地址。客户端通过此端口建立 WebSocket 连接(AEP v1 协议)。生产环境建议置于反向代理(Nginx/ALB)之后并启用 TLS。启动后不可变更——HTTP Server 在启动时绑定端口
read_buffer_size int 4096 WebSocket 读缓冲区大小(bytes)。gorilla/websocket.Upgrader 在 HTTP → WS 升级时分配,影响单连接内存占用。4KB 适合以 JSON 文本为主的消息流。启动后不可变更——Upgrader 在 NewHub 时初始化
write_buffer_size int 4096 WebSocket 写缓冲区大小(bytes)。同上,为写方向预分配的缓冲。启动后不可变更——同 read_buffer_size
ping_interval duration 54s 服务端发送 WebSocket Ping 帧的间隔。必须小于 pong_timeout,推荐为其 90%。ReadPump goroutine 在此间隔触发 WritePump 发送 Ping,用于检测半开连接(客户端进程崩溃但 TCP 未关闭)
pong_timeout duration 60s 等待客户端 Pong 响应的超时。超时后 ReadPump 关闭连接,触发 Hub 注销和 session 清理。此值应略大于客户端的 ping-pong 往返延迟
write_timeout duration 10s 单次 WebSocket 写操作的截止时间。WritePump 在发送每条消息前设置 SetWriteDeadline,超时则判定连接已死。防止慢速客户端阻塞其他连接的写操作
idle_timeout duration 5m WebSocket 物理连接空闲超时。如果连接在此时间内没有任何帧(包括 ping/pong),服务端主动断开。用于清理已断开但 TCP 未关闭的僵尸连接
max_frame_size int64 32768 单个 WebSocket 帧最大允许字节数(32KB)。ReadPump 使用此值设置 SetReadLimit,超过则立即关闭连接。防止恶意客户端发送超大帧耗尽内存
broadcast_queue_size int 256 Hub broadcast channel 的缓冲大小。Hub.Run() 从此 channel 消费事件并路由到各 session 连接。增大可缓解瞬时事件突发,但增加内存占用。启动后不可变更——Go channel 大小在 make 时确定
platform_write_buffer int 64 平台连接(Slack/Feishu)的异步写 channel 容量。每个 platform conn 内部有一个带缓冲 channel 接收待发送事件,WriteCtx 将事件入队后立即返回。64 个槽位在 120ms 合并窗口下可容纳约 8 个批次
platform_drop_threshold int 56 平台连接开始丢弃可丢弃事件的水位线(channel 填充度)。当 channel 使用量超过此阈值(87.5%),message.deltaraw 事件被静默丢弃以缓解反压,但 state/done/error 等关键事件永不丢弃
delta_coalesce_interval duration 120ms 平台连接 Delta 事件的合并窗口。在此时间窗口内的多个 message.delta 事件会被合并为一次 API 调用发送给 Slack/Feishu。120ms 约等于每秒 8.3 次更新,适配飞书 CardKit 的 10 次/秒限制,同时保持首 token 延迟在 200ms 感知阈值内
delta_coalesce_size int 200 Delta 合并的 rune 数量阈值。当合并窗口内累积的文本超过 200 个 rune(约 40 个 token),立即刷新而非等待定时器。作为突发流量的安全阀,仅在输出高峰时触发

admin — 管理 API

提供 REST 端点用于监控(stats、health)和会话管理(list、get、terminate)。应通过防火墙或网络策略限制访问。

字段 类型 默认值 热重载 说明
enabled bool true 是否启动 Admin HTTP 服务。设为 false 则不监听管理端口,所有 /admin/* 端点不可用
addr string :9999 Admin API 监听地址。生产环境应绑定到内网 IP(如 10.0.0.1:9999)或通过 allowed_cidrs 限制访问
tokens []string [] 授权令牌列表。通过 HOTPLEX_ADMIN_TOKEN_1..N 编号式环境变量设置。每个请求需携带 Authorization: Bearer <token> 头。支持多令牌用于无损轮转
token_scopes map {} 令牌到权限的 RBAC 映射。key 为令牌值,value 为权限列表(如 ["session:read", "session:write"])。未映射的令牌使用 default_scopes
default_scopes []string ["session:read", "stats:read", "health:read"] 未在 token_scopes 中显式映射的令牌的默认权限集
ip_whitelist_enabled bool false 启用 CIDR 白名单。开启后仅 allowed_cidrs 中的网段可访问 Admin API。Docker/Kubernetes 环境建议使用网络策略替代
allowed_cidrs []string 127.0.0.0/8, 10.0.0.0/8 信任的 CIDR 网段列表。仅当 ip_whitelist_enabled: true 时生效
rate_limit_enabled bool true 启用基于令牌桶的速率限制。按客户端 IP 独立计数,防止单个客户端滥用管理接口
requests_per_sec int 10 令牌桶的持续填充速率(每秒令牌数)。超出此速率的请求返回 429
burst int 20 令牌桶的最大容量(突发上限)。允许短时间内的请求突发,如监控面板轮询

db — 数据存储

控制 SQLite 持久化行为。所有写操作通过单写 goroutine 串行化(channel 缓冲 50 条/100ms 批量刷盘),保证 WAL 模式下的写入一致性。

字段 类型 默认值 热重载 说明
path string ~/.hotplex/data/hotplex.db SQLite 数据库文件路径。~ 自动展开为用户主目录。文件不存在时自动创建。加载时自动转为绝对路径
events_path string ~/.hotplex/data/events.db SQLite 事件数据库文件路径。独立于 path,存储事件级持久化数据(AEP Envelope)。默认与主数据库同目录
wal_mode bool true 启用 Write-Ahead Logging 模式。WAL 允许并发读写(读不阻塞写),是单写 goroutine 架构的前提。禁止关闭,否则写性能急剧下降且并发读不可用
busy_timeout duration 500ms SQLite 锁等待超时。当另一个写操作持有时,当前操作在此时间内重试。500ms 在单写 goroutine 模型下足够覆盖一次批量刷盘
max_open_conns int 1 最大数据库连接数。SQLite 的并发写入受限于单连接,设为 1 确保所有操作在同一连接上串行化

security — 安全与认证

控制客户端认证、TLS 加密、CORS 跨域策略。

字段 类型 默认值 热重载 说明
api_key_header string X-API-Key API Key 认证的 HTTP 头名称。客户端通过此头发送 API Key,Hub 在 WebSocket 升级前校验
api_keys []string [] 允许访问的 API 密钥列表。通过 HOTPLEX_SECURITY_API_KEY_1..N 编号式环境变量设置。为空时不做 API Key 校验(依赖 JWT 或网络策略保护)。热重载时原子替换整个 key 集合,不影响进行中的请求
tls_enabled bool false 启用 TLS(WSS)。生产环境必须设为 true。启用后网关使用 tls_cert_filetls_key_file 加载证书
tls_cert_file string /etc/hotplex/tls/server.crt TLS 证书文件路径。仅当 tls_enabled: true 时使用
tls_key_file string /etc/hotplex/tls/server.key TLS 私钥文件路径。仅当 tls_enabled: true 时使用
allowed_origins []string ["*"] CORS 允许的 Origin 列表。WebSocket 升级时 Upgrader.CheckOrigin 校验请求的 Origin 头。["*"] 允许所有来源(仅开发用),生产应限制为具体域名。热重载即时生效——每次 WS 升级请求读取最新配置
jwt_audience string hotplex-gateway JWT aud 声明的期望值。用于验证令牌的目标受众,防止令牌跨服务复用
jwt_secret []byte JWT 签名密钥(ES256)。通过 HOTPLEX_JWT_SECRET 环境变量提供(base64 编码),禁止写入 YAML。用于签发和验证 session token

session — 会话生命周期

会话遵循 5 状态机:CREATED → RUNNING → IDLE → TERMINATED → DELETED。Manager 持有内存中的活跃会话映射,SQLite 持久化元数据,后台 GC goroutine 按 gc_scan_interval 周期扫描过期会话。

字段 类型 默认值 热重载 说明
retention_period duration 168h (7天) TERMINATED 会话在数据库中的保留时长。过期后 GC 扫描将其标记为 DELETED 并从数据库物理删除。较长的保留期支持会话历史回溯和调试
gc_scan_interval duration 1m GC 后台扫描间隔。每次扫描检查:① IDLE 会话的 idle_expires_at 是否到期 → TERMINATED ② 会话的 max_lifetime 是否到期 → TERMINATED ③ TERMINATED 会话的 retention_period 是否到期 → DELETE。热重载通过 channel 信号重置 ticker,不中断正在执行的 GC 周期
max_concurrent int 1000 全局最大并发活跃会话数(CREATED + RUNNING + IDLE)。超出时新会话创建请求被拒绝并返回 POOL_EXHAUSTED 错误。根据服务器内存和 Worker 资源需求调整。实际配额由 pool.max_size 控制
event_store_enabled bool true 启用事件持久化。Bridge 在每个 done 事件时将完整 Envelope 写入 MessageStore,用于会话回放、调试和审计。关闭后不写事件日志,减少 I/O
event_store_type string sqlite (代码: "") 事件存储后端类型。目前仅支持 "sqlite"。空字符串表示未指定,依赖 config.yaml 设置

pool — 会话池

PoolManager 在内存中追踪全局和每用户的会话配额。每个 Worker 进程按 512MB 估算内存占用。

字段 类型 默认值 热重载 说明
min_size int 0 预热池最小维持数量。大于 0 时启动后立即预创建指定数量的 Worker 进程,减少首次请求延迟。生产环境建议 >0 以消除冷启动
max_size int 100 全局最大活跃会话数(所有用户合计)。PoolManager.Acquire() 在 totalCount >= maxSize 时拒绝新会话。与 session.max_concurrent 协同工作
max_idle_per_user int 5 (代码: 5) 单个用户(bot_id)允许的最大同时活跃会话数。防止单个用户占用过多资源。0 = 不限
max_memory_per_user int64 3221225472 (3GB, 代码: 3GB) 单个用户的总估算内存配额(bytes)。按每 Worker 512MB 估算,3GB 允许约 6 个并发 Worker。超出时拒绝新会话并返回 MEMORY_EXCEEDED。Linux 上 Worker 通过 RLIMIT_AS 硬限制为 512MB,macOS 不支持此机制。内存配额检查使用启动时快照

工作目录优先级 (WorkDir Priority)

Worker 进程启动时的工作目录遵循以下优先级覆盖逻辑:

  1. 会话级 (Session):客户端在 session.initmetadata.work_dir 中指定的路径(最高优先级)。
  2. 平台级 (Platform):在 messaging.slack.work_dirmessaging.feishu.work_dir 中指定的路径。
  3. 全局级 (Global):在 worker.default_work_dir 中指定的路径(最低优先级,默认兜底)。

worker — Worker 进程

每个会话对应一个独立的 Worker 子进程(如 claude CLI),通过 stdin/stdout 的 NDJSON 协议通信。进程使用 PGID 隔离,终止时对整个进程组发送信号。

字段 类型 默认值 热重载 说明
max_lifetime duration 24h 绝对生存周期。Worker 进程从启动开始计算的强制最大寿命。到期后无论是否活跃均会被终止。旨在通过定期刷新来清除潜在的内存泄漏或内部状态退化。Worker 可通过 resume 机制在下次请求时无缝重启。
idle_timeout duration 60m 闲置回收周期(Idle Recycle)。Worker 在等待新输入(IDLE 状态)时的最大允许时长。每次接收到用户输入后该计时器都会重置。旨在及时释放不活跃会话占用的资源。较短的超时释放资源更快,但可能导致用户体感的冷启动增加。
execution_timeout duration 30m 僵死检测周期(Zombie IO Timeout)。Worker 在执行中(RUNNING 状态)无任何 I/O 输出反馈的最大时长。用于检测并强制清理卡死、陷入无限循环或无响应的 Worker 进程,防止会话永久阻塞。
default_work_dir string ~/.hotplex/workspace Worker 进程的默认工作目录。当 session 或 platform 未指定 work_dir 时使用。~ 自动展开为用户主目录。目录不存在时自动创建(mkdir -p
pid_dir string ~/.hotplex/.pids/ PID 文件目录。proc.Manager 在启动 Worker 时写入 PID 文件用于孤儿进程清理。网关重启时自动扫描此目录,杀死不再有父进程的孤儿 Worker
env_blocklist []string [] 环境变量黑名单。默认所有 os.Environ() 变量透传给 Worker,仅黑名单中的变量被过滤。条目以 _ 结尾时按前缀匹配(如 HOTPLEX_ 阻止所有 HOTPLEX_* 变量)。HOTPLEX_WORKER_ 前缀的变量会被剥离前缀后注入(如 HOTPLEX_WORKER_GITHUB_TOKENGITHUB_TOKEN
environment []string [] 额外注入 Worker 进程的环境变量列表。每个条目支持 KEY=VALUEKEY=${VAR} 格式。这是唯一支持 ${VAR} 展开的配置字段,引用未设置变量(无默认值)的条目会被静默丢弃。优先级最高,覆盖所有其他来源

worker.auto_retry — LLM 自动重试

当 Worker(如 Claude Code)遇到 LLM Provider 的临时错误(429 限流、529 过载、网络超时等),Bridge 自动检测并触发重试,对用户透明。

错误拦截机制:当 enabled: true 时,Worker 发出的 error 事件会被 Bridge 暂存而非立即转发。等到 done 事件到达时判断是否可重试——如果可重试,原始 error 事件被丢弃,用户只看到 notify 消息(如"🔄 正在自动重试");如果不可重试,error 事件在 done 之后放行给客户端。这样用户不会看到原始的 LLM 技术错误信息(如 “429 rate_limit_error”),只看到友好的重试通知。

字段 类型 默认值 热重载 说明
enabled bool true 启用自动重试。关闭后 Worker 遇到临时错误时直接将错误事件转发给客户端
max_retries int 9 单个会话的最大重试次数。每次 Worker 完成一个 turn(done 事件),Bridge 检查输出是否匹配可重试错误模式。达到上限后停止重试,返回提示让用户手动操作。9 次重试在 base_delay=5s 指数退避下总耗时约 5+10+20+40+80+120+120+120+120 ≈ 640s(11 分钟),不会超过网关的 execution_timeout(默认 30 分钟)
base_delay duration 5s 首次重试的等待时间。采用指数退避:第 1 次等 base_delay,第 2 次等 2×base_delay,依此类推,直到 max_delay
max_delay duration 120s 退避延迟上限。即使指数增长超过此值,实际延迟也不会超过 120s
retry_input string 继续 重试时发送给 Worker 的文本。Bridge 在 Worker 的 stdin 写入此文本,触发 Worker 重新发起 LLM 请求
notify_user bool true 重试期间是否通知用户。启用时在重试前发送一条 message 事件(如"🔄 正在自动重试 (1/9)…"),替代原始 LLM 错误信息。关闭后用户看不到任何重试提示,但错误信息仍然会被拦截
patterns []string [] 追加模式 (Append Mode)。在此定义的正则表达式将追加到内置模式(如 429, 5xx, 网络超时等)之后。自定义模式与内置模式共同生效,不会覆盖内置逻辑。

webchat — 嵌入式 Web Chat

控制网关内嵌的 Web Chat SPA 服务。Next.js 静态导出通过 go:embed 编译时嵌入二进制,网关同时托管 API 和前端。

字段 类型 默认值 热重载 说明
enabled bool true 启用 Web Chat SPA 托管。设为 false 则网关仅提供 WebSocket/API 端点,不提供前端静态文件
addr string "" Web Chat 地址(信息展示用)。用于启动 Banner 显示,不控制实际监听端口。Web Chat 由 Gateway 的 HTTP Server 在同一端口托管

agent_config — Agent 角色配置 (B/C Channels)

定义 Agent 的“人格(Persona)”与“上下文(Context)”。系统自动将这些 Markdown 文件注入到系统提示词的 XML 标签中。

字段 类型 默认值 热重载 说明
enabled bool true 是否启用 Agent 配置注入。关闭后 Agent 将仅使用代码内建的通用提示词。
config_dir string ~/.hotplex/agent-configs 配置文件根目录。支持 per-bot 3 级目录 fallback,按文件独立解析:<config_dir>/<platform>/<botID>/<file><config_dir>/<platform>/<file><config_dir>/<file>,命中第一个非空文件即停止。有效平台值:slackfeishuwebchat""(仅全局级)

skills — 技能管理

管理 Agent 可调用的工具和发现逻辑。

字段 类型 默认值 热重载 说明
cache_ttl duration 5m 技能发现结果在内存中的缓存时长。过期后触发重新扫描。设为 0 则禁用缓存(不推荐,会增加磁盘 I/O)。

log — 日志

控制网关进程的日志输出。使用 log/slog 结构化日志,所有日志带有 service=hotplex-gatewayversion 字段。

字段 类型 默认值 热重载 说明
level string info 最低日志级别。debug 输出所有事件流转细节(每个收发的事件),适合开发调试。info 仅输出关键生命周期事件(连接注册、会话创建/终止等)。warn/error 仅输出异常情况。热重载通过 slog.LevelVar 即时生效,无需重启
format string json 日志格式。json 为结构化 JSON(适合日志聚合系统如 ELK/Loki)。text 为人类可读的 key=value 格式(适合终端直接查看)。Makefile dev-logs 使用 tail -f 展示。启动后不可变更——Handler 在初始化时确定格式

messaging — 消息平台全局设置

控制所有消息平台(Slack/飞书)的共享行为。

字段 类型 默认值 热重载 说明
turn_summary_enabled bool true 是否在每次会话回合完成后发送 turn summary(回合摘要)。关闭后 Slack 不发送 TableBlock 摘要,飞书不发送 CardKit 卡片(但飞书仍保留 Log.Info 遥测日志)。通过环境变量 HOTPLEX_MESSAGING_TURN_SUMMARY_ENABLED 覆盖。启动时确定,运行中变更需重启

messaging.slack — Slack Socket Mode

通过 Slack Socket Mode 建立 WebSocket 连接到 Slack 服务器,实现无需公网入口的消息收发。消息经过 chunker(长消息拆分)→ dedup(TTL 去重)→ format(Markdown 转换)→ rate limiter → send 的流水线处理。Streaming 使用 SlackStreamingWriter,以 150ms 间隔、20 rune 阈值增量更新消息。

字段 类型 默认值 热重载 说明
enabled bool false 启用 Slack 适配器。启动时通过 Socket Mode 连接到 Slack 服务器,开始监听消息事件
bot_token string Slack Bot User OAuth Token(xoxb- 前缀)。用于调用 Slack Web API 发送消息、更新卡片。通过环境变量 HOTPLEX_MESSAGING_SLACK_BOT_TOKEN 设置
app_token string Slack App-Level Token(xapp- 前缀)。用于建立 Socket Mode WebSocket 连接。需要在 Slack App 配置中启用 Socket Mode 并生成。通过环境变量 HOTPLEX_MESSAGING_SLACK_APP_TOKEN 设置
socket_mode bool true (代码: false) 启用 Socket Mode。Socket Mode 通过 WebSocket 与 Slack 服务器通信,无需公网可访问的 HTTP 端点。关闭则需要配置 Events API URL
worker_type string claude_code 为 Slack 会话创建的 Worker 类型。决定使用哪个适配器启动 Worker 进程(claude_code = Claude Code CLI,opencodeserver = OpenCode Server)
work_dir string Worker 进程的工作目录。为空时使用 worker.default_work_dir。可按平台设置不同目录
dm_policy string allowlist 私聊(DM)的访问策略。open = 允许所有人,allowlist = 仅 allow_from + allow_dm_from 中的用户,disabled = 禁止所有私聊
group_policy string allowlist 频道和群组 DM 的访问策略。选项同 dm_policyrequire_mention: true 时,即使策略允许,也需要 @机器人 才触发
require_mention bool true 群组中是否需要 @机器人 才触发处理。私聊始终触发,不受此限制。true 避免群组中的每条消息都创建 Worker 会话
allow_from []string [] 全局白名单(同时授权 DM 和群组)。值为 Slack User ID 或显示名。在 allowlist 策略下生效
allow_dm_from []string [] 仅私聊白名单。与 allow_from 合并去重
allow_group_from []string [] 仅群组白名单。与 allow_from 合并去重
reconnect_base_delay duration 1s Socket Mode 连接断开后的首次重连延迟。采用指数退避,每次翻倍直到 reconnect_max_delay
reconnect_max_delay duration 60s 重连延迟上限。避免在网络故障时过于频繁地重试
assistant_api_enabled *bool nil 是否启用 Assistant API 模式。nil(未设置)= 自动检测。true = 强制使用 Assistant API,false = 使用标准对话模式

messaging.feishu — 飞书 WebSocket

通过飞书 WebSocket 客户端接收事件(P2 模式),使用流式卡片(CardKit)实现增量更新。消息发送经过 4 层防护:TTL 守卫 → 完整性检查 → 带退避重试 → IM Patch 降级。

字段 类型 默认值 热重载 说明
enabled bool false 启用飞书适配器。启动时通过 WebSocket 连接到飞书服务器,监听消息事件
app_id string 飞书应用 ID(cli_ 前缀)。在飞书开放平台创建应用后获取。通过环境变量 HOTPLEX_MESSAGING_FEISHU_APP_ID 设置
app_secret string 飞书应用密钥。用于获取 tenant_access_token 调用飞书 API。通过环境变量 HOTPLEX_MESSAGING_FEISHU_APP_SECRET 设置
worker_type string claude_code 为飞书会话创建的 Worker 类型。同 Slack 的 worker_type
work_dir string Worker 进程工作目录。同 Slack 的 work_dir
dm_policy string allowlist 单聊访问策略。选项同 Slack
group_policy string allowlist 群组和话题群访问策略。选项同 Slack
require_mention bool true 群组中是否需要 @机器人。同 Slack
allow_from []string [] 全局白名单。值为飞书 User ID 或 Open ID
allow_dm_from []string [] 仅单聊白名单
allow_group_from []string [] 仅群组白名单
stt_provider string feishu+local 语音转文字引擎。feishu = 飞书 speech_to_text API(需开通权限),local = 本地命令行引擎(SenseVoice-Small ONNX),feishu+local = 云端优先本地降级(推荐),空 = 禁用 STT
stt_local_cmd string python3 scripts/stt_server.py 本地 STT 命令。含 {file} → 每次请求 fork 新进程(冷启动约 3-5s);不含 {file} → 常驻子进程 + stdin/stdout JSON 协议(零冷启动,适合高频使用,模型约占 900MB 内存)。详细安装说明见 STT 安装手册
stt_local_idle_ttl duration 15m 常驻模式空闲超时。STT 子进程在此时间内无转写请求则自动关闭,节省内存。0 = 永不关闭。仅常驻模式生效

完整的 STT 安装配置说明STT-Setup.md —— 涵盖 Python 依赖安装、模型下载、Ephemeral/Persistent 模式配置、Docker 部署和故障排查。


环境变量速查

所有环境变量以 HOTPLEX_ 前缀。编号式变量 (_1..N) 支持多值轮转。

变量 必填 说明
HOTPLEX_JWT_SECRET JWT 签名密钥(base64 编码,ES256 算法)
HOTPLEX_ADMIN_TOKEN_1 主管理端令牌
HOTPLEX_ADMIN_TOKEN_2..N 备用管理端令牌(轮转用)
HOTPLEX_SECURITY_API_KEY_1..N 客户端 API 密钥
HOTPLEX_LOG_LEVEL 覆盖 log.level
HOTPLEX_LOG_FORMAT 覆盖 log.format
HOTPLEX_DB_PATH 覆盖 db.path
HOTPLEX_GATEWAY_ADDR 覆盖 gateway.addr
HOTPLEX_ADMIN_ADDR 覆盖 admin.addr
HOTPLEX_SESSION_MAX_CONCURRENT 覆盖 session.max_concurrent
HOTPLEX_POOL_MAX_SIZE 覆盖 pool.max_size
HOTPLEX_POOL_MAX_MEMORY_PER_USER 覆盖 pool.max_memory_per_user
HOTPLEX_MESSAGING_SLACK_* 覆盖 messaging.slack.* 全部字段
HOTPLEX_MESSAGING_FEISHU_* 覆盖 messaging.feishu.* 全部字段
HOTPLEX_MESSAGING_TURN_SUMMARY_ENABLED 覆盖 messaging.turn_summary_enabled

热重载

Watcher 监听 -config 指定文件的变更(500ms 防抖),通过反射逐字段比较检测变化,验证新配置后原子替换 ConfigStore 并通知各组件的 observer。

可热重载字段(即时生效,无需重启)

模块 字段 生效机制
log level slog.LevelVar 动态切换
security api_keys Authenticator 原子替换 key map
security allowed_origins 每次 WS 升级请求读取最新值
session gc_scan_interval Channel 信号重置 GC ticker
pool max_size PoolManager 加锁更新
pool max_idle_per_user 同上
worker.auto_retry enabled / max_retries / base_delay / max_delay / retry_input / notify_user / patterns LLMRetryController 原子替换配置和编译后的正则
admin requests_per_sec / burst 令牌桶动态调整填充速率和容量
admin tokens Admin API token 列表热更新

不可热重载字段(变更需重启)

以下字段涉及启动时一次性创建的资源,运行中无法变更:

模块 字段 原因
gateway addr HTTP Server 启动时绑定端口
gateway read_buffer_size / write_buffer_size WebSocket Upgrader 在 NewHub 时初始化
gateway broadcast_queue_size Go channel 大小在 make 时确定
log format slog Handler 在初始化时确定格式
db path / wal_mode SQLite 连接在启动时建立
security tls_* / jwt_secret TLS 证书和 JWT 密钥在启动时加载

变更不可热重载字段时,Watcher 会记录日志 config: static field changed, restart required,新值存入 ConfigStore 但不产生实际效果,需重启网关才能生效。

支持历史快照和回滚(最多 64 个版本),回滚操作同样通过 ConfigStore 原子传播到所有 observer。


Dev vs Prod 差异

字段 config-dev.yaml config-prod.yaml
admin.rate_limit_enabled false (base: true)
session.retention_period 24h (base: 168h)
session.max_concurrent 100 (base: 1000)
pool.max_size 50 500
pool.min_size (base: 0) 10(预热)
pool.max_memory_per_user 3GB 3GB
worker.idle_timeout 30m 30m
worker.execution_timeout 30m (base: 30m)
log.level debug (base: info)
log.format text (base: json)
security.tls_enabled (base: false) true
security.allowed_origins (base: *) 具体域名
messaging.*.enabled true (base: false)
messaging.feishu.*_policy (base: allowlist) open

生产安全清单

  • jwt_secret 仅通过 HOTPLEX_JWT_SECRET 设置,禁止写入 YAML
  • admin.tokens 仅通过 HOTPLEX_ADMIN_TOKEN_1..N 设置
  • 生产必须 tls_enabled: true
  • admin.addr 绑定内网或通过 allowed_cidrs 限制访问
  • 敏感凭据使用编号式环境变量支持轮转
  • db.wal_mode 禁止关闭(true