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 不同)。它支撑 // 图片上传存储(/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 // Usage 是 LLM 用量汇总的只读出口(切片 U1)。可选;为 nil 时 // GET /api/v1/admin/llm/usage 诚实作答 500 usage_unavailable, // 绝不回一份全 0 的假汇总。 Usage LlmUsageStore // EventStore 是渠道事件留存的只读查询出口(design/26 §4.5;切片 E6)。 // 组合根注入的正是交给桥接层写入的**同一个** `*events.SQLStore` 句柄 // (同一个库、同一份口径)。可选;为 nil 时 // GET /api/v1/admin/channels/events 与 `.../counters` 诚实作答 // 500 channel_events_unavailable,绝不回一份全 0 的假汇总。 EventStore ChannelEventStore // MaxParallelTurns 是单会话在途并行路数的上限(design/15 §2.5.7)。 // 零值/负数 ⇒ 编排器用默认 2;1 ⇒ 关闭真并行(恒 1 路,完全回落到 // queue + 回合内 steer 的现状);超过硬上限 3 ⇒ 钳到 3。 // 它刻意是编排器的构造期旋钮而不是一个全局:真并行只由显式声明 // (上行 `chat.parallel`)触发,因此调大它不会改变任何未声明并行的客户端行为。 MaxParallelTurns int // Flow 是「最近一轮链路图」的只读出口(契约 v0.71 的 // GET /api/v1/admin/flow/graph)。组合根注入的正是交给 loop 的那个 // *loop.FlowPublisher —— 同一个对象,因此查询面读到的就是实时发布的那张图。 // 可选;为 nil 时端点诚实作答 500 flow_unavailable,绝不回 // graph:null(那会把「图源没接线」伪装成「这一轮确实没有图」)。 Flow FlowGraphSource // FlowGraphs 是**已落盘轮次图**的只读出口(契约 v0.73;design/19 §4 的 P3 // 「多轮历史回放」)。组合根注入的是发布器**每轮收尾落一条**用的同一个 // `*flowgraph.SQLStore`。可选;为 nil 时端点回退到只有内存的行为 // (turns 为空、turnId 只能命中内存里那一轮),内存与落盘都没接线才 500。 FlowGraphs FlowGraphStore // MemoryTidy 是记忆整理「试算」的注入出口(契约 v0.75;切片 MT1)。组合根 // 注入的就是低峰心跳跑的那个 `*memory.TidyService` —— 同一套规则、同一份配置, // 因此试算给出的建议与当晚那一轮同口径。试算自身**零副作用**(不写任何表)。 // 可选;为 nil(真 nil,不是带类型的 nil 指针)时端点回 500 `tidy_unavailable`, // 绝不回空候选假装「没有建议」。 MemoryTidy MemoryTidyDryRunner }