- 语义:只把 .env **确实声明过**的键覆盖回 env 值;env 未声明的键(fallback/multimodal/maxTokens/reasoning/personaModels)原样保留;**组集合不增减**(不复活被面板删的组、不删面板新增的组);无键可改时不写盘。成功即热重载 LLM 栈。返回 {reset:[{group,keys}], skipped:[{group,reason}], path},**只回键名、不回显凭据值**。
- 护栏:必须 confirm:true(缺失/false/非法 body ⇒ 400,且**先于任何读写**);**owner-only**(与同页 POST /admin/llm、/admin/llm/test 同门 —— 这是破坏性写,门不比同族更宽);审计动作 llm.resetFromEnv(camelCase,全仓多词动作的既有约定)。失败路径明确报错(env_defaults_unreadable / models_unreadable / llm_unavailable),不假成功。
- 组合根注入 Deps.EnvPath(网关不 fopen .env):请求时按既有解析入口重读,语义 =「退回 .env 现在声明的默认值」;.env 层里的 provider 是同义反复,不计入「env 为该组声明了什么」的判定(有专门用例)。
- 前端:LLM 页「重置为 env 默认」卡片(中文二次确认 → 提交 → 按 reset/skipped 渲染 → 成功后重拉配置),标签 owner 专属(与 System.tsx 同款)。
- 契约 v0.62:api-client(权限矩阵改回 12+10+38=60、端点表 9b、重置契约小节、写操作契约、changelog、banner)与 api-reference(端点表 #70、§5.13a 详情含 curl、§8.2/§8.3/§8.4)同步;字段名三方逐字对齐。
- 主会话独立验收:隔离 worktree(R1 的 19 文件)build/vet 绿、gateway+config 三包绿、R1 用例 10 PASS、reset_from_env 残留 0;**变异亲自复现**(去掉 confirm 校验 ⇒ RequiresConfirm 红:status = 200, want 400,且响应体显示面板配置真的被改)。
- 子代理自报并已处理:测试文件触 500 行上限 ⇒ 拆成语义侧 + 护栏侧两份;门改回 owner-only 后前端标签会误导 admin ⇒ 改「owner 专属」并重建 bundle。任务书本身仍是旧口径(owner|admin / snake_case)—— 已由主会话登记修正说明,避免压缩后有人按任务书回退。
- 未做(诚实边界):不支持按组重置;不纳入 channels.json/plugins.json;不自动重启(contextWindow 的预算推导仍只在启动时算一次)。新端点需下一次 build+restart 才在 :10942 生效。
142 lines
6.9 KiB
Go
142 lines
6.9 KiB
Go
package gateway
|
||
|
||
import (
|
||
"database/sql"
|
||
"io/fs"
|
||
"log/slog"
|
||
"net/http"
|
||
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/bus"
|
||
pluginmgr "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/plugin"
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
|
||
)
|
||
|
||
// VectorState 是组合根报告的向量增强(pgvector)运行状态,供管理侧
|
||
// 「存储状态」端点回答「PG 到底有没有生效」(design/03 §3)。
|
||
//
|
||
// 它是**复用**而非探测:网关不读环境变量、不新开 PG 连接、不
|
||
// 自行 ping —— 真相只有组合根知道(DB_PG_URL 是否配置 + 活的向量
|
||
// 索引是哪个后端),因此由它注入,避免面板看到与运行时不一致的
|
||
// 第二个判断。
|
||
type VectorState struct {
|
||
// Configured 报告 DB_PG_URL 是否已配置(非空即算),即
|
||
// 增强开关在不在。
|
||
Configured bool
|
||
// Live 报告当前活的向量索引确实是 PostgreSQL+pgvector 后端。
|
||
// 配置了但连接/schema 准备失败时为 false —— 此时语义检索已降级,
|
||
// 面板必须显示「未就绪」而不是假装增强生效。
|
||
Live bool
|
||
}
|
||
|
||
// Deps 承载网关被注入的依赖。除 Auth 外每个字段都容忍
|
||
// nil,Auth 是必需的(认证支撑登录与每一个 RBAC
|
||
// 决策)。Registry/Loop 由具体的 *capability.Registry 与
|
||
// *loop.Loop 满足;Sessions/Personas/Memories 由具体的会话
|
||
// 管理器、人格注册表与记忆存储满足,只有当依赖留为
|
||
// nil 时 handler 才返回 []。
|
||
type Deps struct {
|
||
// Log 是基础 logger。为 nil 时使用丢弃型 logger。
|
||
Log *slog.Logger
|
||
// Auth 是 JWT/RBAC 服务。必需。
|
||
Auth Authenticator
|
||
// Bus 是 WS hub 所订阅的进程内事件总线。可选。
|
||
Bus bus.Bus
|
||
// Registry 枚举能力/插件/渠道。可选。
|
||
Registry CapabilityStore
|
||
// Loop 运行聊天回合。可选(未设置时 chat 返回错误)。
|
||
Loop Chatter
|
||
// Session 列出渠道会话。可选。
|
||
Session SessionStore
|
||
// Personas 列出人格。可选。
|
||
Personas PersonaStore
|
||
// Memories 列出记忆条目。可选。
|
||
Memories MemoryStore
|
||
// History 是持久化聊天历史存储(design/16)。可选;为 nil 时
|
||
// 会话/消息端点退化(列出回退到渠道会话,其余 501)。
|
||
History HistoryStore
|
||
// IoT 列出 IoT 设备。可选。
|
||
IoT IoTStore
|
||
// Scheduler 为 subagent_ask WS 路由审计子代理上下文。
|
||
// 可选(未设置时 subagent_ask 返回明确的错误)。
|
||
Scheduler SubagentAuditor
|
||
// Tasks 为 task_output_query WS 路由查询任务输出。
|
||
// 可选(未设置时 task_output_query 返回明确的错误)。
|
||
Tasks TaskOutputStore
|
||
// Automations 列出自动化与提醒。可选。
|
||
Automations AutomationStore
|
||
// Users 列出账号与 API key。可选(回退到已配置的
|
||
// 单个管理账号)。
|
||
Users UserStore
|
||
// Refresh 是非透明 refresh token 存储。可选:为 nil 时登录省略
|
||
// refreshToken,/auth/refresh + /auth/logout 返回 not-configured。
|
||
Refresh RefreshGrantStore
|
||
// Backthink 列出后台思考记录。可选。
|
||
Backthink BackthinkStore
|
||
// RAG 支撑管理侧知识库 RAG 模块。可选;未设置时列出/搜索
|
||
// 返回空,写端点报告明确的 501。
|
||
RAG RagStore
|
||
// LLM 是可热切换的 provider 栈(models.json,design/04 §3.1)。
|
||
// 可选:为 nil 时管理 /llm 端点回退到环境配置,使
|
||
// 既有的网关测试继续可用。
|
||
LLM *model.RuntimeLLM
|
||
// EnvPath 是进程启动时解析的 `.env` 文件路径(组合根传给 config.Load 的同一个)。
|
||
// 「重置为 env 默认」动作(切片 R1)按**既有 config 解析入口**重读 env 默认层,
|
||
// 网关自己绝不 fopen `.env`。空表示只看进程环境变量(与 config.Load("") 的
|
||
// 约定一致,生产走 systemd/env_file 时就是这种形态)。可选。
|
||
EnvPath string
|
||
// Channels 是运行时可编辑的渠道适配器配置(channels.json)。
|
||
// 可选:为 nil 时管理 /channels/config 端点返回明确的
|
||
// not-configured 错误,与 LLM 栈未设置时的行为一致。
|
||
Channels ChannelConfigStore
|
||
// Plugins 是运行时可安装的外部工具 provider 管理器
|
||
// (plugins.json + 活的 MCP server)。可选:为 nil 时安装返回
|
||
// 明确的 not-implemented 错误,卸载回退为普通的能力
|
||
// 移除,使既有的网关测试继续可用。
|
||
Plugins *pluginmgr.Manager
|
||
// OwnerRegistrar 把扫码登录绑定的主人 id 盖进主人
|
||
// 白名单(configs/users/owner.yaml)并热更新活的 profile。
|
||
// 可选:为 nil 时 weixin 确认流程仍会持久化 channels.json,但
|
||
// 跳过白名单登记(按设计即为尽力而为)。
|
||
OwnerRegistrar OwnerRegistrar
|
||
// AuditStore 持久化管理审计链(observability → audit)。为 nil 时
|
||
// 网关退化为内存存储,使端点仍能返回
|
||
// 数据;组合根注入基于 a.db 的 NewSQLiteAuditStore 以获得真实
|
||
// 持久化。可选。
|
||
AuditStore AuditStore
|
||
// DatabasePath 是组合根实际打开的 SQLite 数据库文件解析后
|
||
// 路径(由 resolveSQLitePath 推导的值,当数据目录默认值
|
||
// 生效时可能与 cfg.DB.SQLitePath 不同)。它支撑
|
||
// 管理备份/恢复端点。可选;为空时那些端点诚实作答,
|
||
// 返回明确的 not-configured 错误。
|
||
DatabasePath string
|
||
// DataDir 是解析后的数据目录(resolveDataDir 返回的值,当操作系统
|
||
// 默认值生效时可能与 cfg.DataDir 不同)。它支撑
|
||
// 图片上传存储(<DataDir>/uploads)及其静态路由。可选;
|
||
// 为空时上传 handler 回退到 cfg.DataDir。
|
||
DataDir string
|
||
// Database 是组合根已打开的活 SQLite 连接池。管理侧的
|
||
// 「存储状态」只读端点用它读页级统计与 documents 表 ——
|
||
// 复用既有池,端点自身不另开连接或连接池。可选;为 nil 时
|
||
// 该端点诚实作答(500 storage_unavailable),绝不假装
|
||
// 拿到了数据。
|
||
Database *sql.DB
|
||
// Vector 是组合根报告的向量增强(pgvector)运行时状态,
|
||
// 见 VectorState。网关只读它,绝不自行探测。可选;零值
|
||
// 表示「未配置」(kind:"none"),与未启用增强的部署一致。
|
||
Vector VectorState
|
||
// Streaming 标记注入的 Loop 具备流式能力(其 OnStream
|
||
// 已接线为发布 ws.stream_chunk)。设置后 hub 会跳过它自己的
|
||
// 单次最终 stream_chunk 发送,因为增量已通过 OnStream 流出。
|
||
Streaming bool
|
||
// Frontend 是为所有非 API、非 WS 路由提供的 SPA 文件系统。
|
||
// 为 nil 时网关不提供任何静态资产(只有 API 与 WS)。
|
||
// 使用内嵌的 dist(internal/webui)或外部 dist 目录。
|
||
Frontend fs.FS
|
||
// Webhooks 是外部挂载的入站 HTTP handler(端点路径 →
|
||
// handler),通常来自接收 webhook 回调的渠道适配器
|
||
// (例如 webhook)。每个都挂到 ServeMux 上且不经网关认证;
|
||
// handler 自身强制其签名/授权(webhook HMAC)。
|
||
// 可选。
|
||
Webhooks map[string]http.Handler
|
||
}
|