原文停在 2026-07-02 已严重失真:能力矩阵还写「多租户/RBAC 未动、真实计费 未做、NATS 集群未做」,而这三项均已完成并 live 验证。它又被 5 份设计文档 引用为配套文档,不能放着不管。 重写为 15 章 913 行,以代码为单一事实源: - 分层架构图 + 3 张关键链路时序图(任务提交/语音全双工/本地执行三道闸) + 三机部署拓扑图,全部 Mermaid(已用 mermaid-cli 逐张渲染验证) - 5 个服务逐个拆:internal 包职责 + 技术栈依赖表含版本 - NATS 契约总表:1 任务流 + 3 回流 + 4 组工具 RPC + 5 条持久回写流 + KV - 编排引擎:12 种节点 kind、ReAct、11 个平台工具、harness 五件套 - 29 张表全清单 + 9 个中间件 + 迁移机制 - 13 域功能实现状态总表(✅/🟡/❌) - 安全治理/可观测/客户端三产品面/CI-CD/技术栈速查/已知缺口 顺带记账:§9.14 点名 4 处文档与代码不符(PROGRESS.md 停更、DEPTH_ROADMAP 汇总表自相矛盾、Tier3 说 NATS 集群没做但已落地、PAYMENT_DESIGN 说不做订阅 但已实现),明确以代码为准,避免后来人被误导。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
42 KiB
sundynix-agentix · 架构设计文档
版本:2026-07-26 定位:事件驱动的多租户 AI Agent 平台。以 NATS 为统一总线,服务经契约解耦,Eino 为编排核心,控制面热切换;桌面端 JARVIS 既是语音入口,也是能操作用户电脑的中枢。
本文以代码为单一事实源。
PROGRESS.md(停更于 2026-06-19)与DEPTH_ROADMAP.md的汇总表已与代码脱节(详见 §9.14),仅作历史参考。配套文档:
ARCHITECTURE_REVIEW.md(架构评审)、DEPTH_ROADMAP.md(路线图)、EINO_ADOPTION.md(Eino 采纳)、SAAS_DESIGN.md/SAAS_P2_DESIGN.md(多租户与计量)、SPACE_DESIGN.md(共享工作区)、PAYMENT_DESIGN.md(支付)、VOICE_DESIGN.md(语音)、JARVIS_BRAIN_DESIGN.md(JARVIS 中枢)、LOCAL_AGENT_DESIGN.md(本地执行)、DEPLOY.md(部署)。
1. 系统概述
用户在桌面端搭一张编排图(或直接说话),任务经网关落库并发到 NATS;调度集群把 DSL 编译成 Eino compose 图执行,过程中自主调用工具(检索/联网/计算/操作用户电脑),Token 与执行轨迹实时流回界面;全程带计量计费、护栏、评测与链路追踪。
1.1 Monorepo 结构
sundynix-agentix/
├── sundynix-shared/ 共享库:NATS 总线 / 契约 / 对象存储 / 密钥 / OTel / prompts
├── sundynix-gateway/ 第 2 层 业务网关(HTTP + WS + 平台工具 + 后台常驻)
├── sundynix-dispatcher/ 第 4 层 Agent 编排调度集群(无对外端口)
├── sundynix-mcp-go/ 第 5 层 Go I/O 型工具服务(RAG / 记忆 / 报告 / 图表)
├── sundynix-mcp-py/ 第 5 层 Python 算法型工具服务(沙箱执行 / 文档解析)
├── sundynix-desktop/ 桌面端(Wails v3 + React 19)——主产品面
├── sundynix-admin/ 官网 + 运维控制台(同一 SPA,go:embed 进 gateway)
├── sundynix-web/ 薄 Web 面(租户自助:注册/组织/团队/账单)
├── deploy/ 三机部署配置 + NATS 集群配置
└── scripts/ 备份/恢复/RAG 评测
go.work 只纳入 4 个后端模块(shared / gateway / dispatcher / mcp-go)。
sundynix-desktop 刻意不入 workspace(它是客户端,独立依赖),因此在该目录下跑 Go 命令必须 GOWORK=off。
1.2 代码规模(实测)
| 部分 | 源码 | 测试 |
|---|---|---|
| Go · gateway | 14,395 | 2,775 |
| Go · dispatcher | 5,265 | 2,974 |
| Go · mcp-go | 3,844 | 1,319 |
| Go · shared | 2,173 | 681 |
| Go · desktop | 697 | 271 |
| TypeScript · desktop 前端 | 8,980 | 11 个前端测试文件 |
| TypeScript · admin | 9,360 | (同上) |
| TypeScript · web | 2,030 | (同上) |
| Python · mcp-py | 520 |
2. 分层架构总览
flowchart TB
subgraph CLIENT["客户端层"]
DESK["sundynix-desktop<br/>Wails v3 + React 19<br/>编排画布 · JARVIS · 本地 runner"]
ADMIN["sundynix-admin<br/>官网 / + 控制台 /admin"]
WEB["sundynix-web<br/>租户自助柜台"]
end
subgraph GW["第 2 层 · gateway(唯一对外入口)"]
HTTP["HTTP API + SSE(gin)"]
WS["WebSocket<br/>语音 /voice/stream<br/>本地执行器 /local/runner"]
PLAT["平台工具提供方<br/>platform_* / local_*"]
BG["后台常驻<br/>配置控制面 · 持久消费者<br/>入库 worker 池 · 3 个 ticker"]
end
BUS{{"NATS + JetStream<br/>统一总线(8MB payload)"}}
subgraph WORK["执行层"]
DISP["第 4 层 · dispatcher<br/>Eino compose 编排<br/>LLM 双池 + failover + 熔断<br/>harness 治理"]
MGO["第 5 层 · mcp-go<br/>RAG 三路 / 记忆 / 报告 / 图表"]
MPY["第 5 层 · mcp-py<br/>Docker 沙箱 / 文档解析"]
end
subgraph STORE["存储层"]
PG[("PostgreSQL 16<br/>29 张表")]
RDS[("Redis 7")]
MLV[("Milvus 2.4.13")]
BLV[("Bleve 全文")]
NEO[("Neo4j 5")]
OSS[("MinIO")]
end
LLM["LLM Provider<br/>OpenAI 兼容 · DeepSeek"]
VOLC["火山引擎<br/>ASR / TTS"]
DESK --> HTTP
ADMIN --> HTTP
WEB --> HTTP
DESK <--> WS
HTTP --> BUS
WS --> VOLC
BG <--> BUS
PLAT <--> BUS
BUS <--> DISP
BUS <--> MGO
BUS <--> MPY
DISP --> LLM
HTTP --> PG
HTTP --> RDS
HTTP --> OSS
MGO --> MLV
MGO --> BLV
MGO --> NEO
MGO --> OSS
DISP --> BUS
2.1 分层职责
| 层 | 组件 | 职责 | 对外端口 |
|---|---|---|---|
| 1 客户端 | desktop / admin / web | 交互与呈现 | — |
| 2 接入 | gateway | 鉴权、租户/空间上下文、限流、护栏、审计、任务落库与发射、SSE/WS 回流、平台工具、后台常驻 | 8080(生产 3000) |
| 3 总线 | NATS + JetStream | 任务队列、回流、工具 RPC、控制面广播、KV checkpoint | 4222 |
| 4 编排 | dispatcher | DSL→compose 图执行、ReAct 自主工具、多智能体、HITL 中断、评测纠偏 | 无(仅探针 8091) |
| 5 工具 | mcp-go / mcp-py | I/O 型与算法型能力,队列组水平扩 | 无(仅探针 8092) |
关键设计:dispatcher 与 mcp-* 都没有对外端口,只通过 NATS 通信 —— 攻击面收敛到 gateway 一个进程。
3. 服务详解
3.1 gateway —— 业务网关 / 统一接入层
github.com/sundynix/sundynix-gateway · Go 1.25.8 · 入口 cmd/server/main.go
| internal 包 | 职责 |
|---|---|
router |
Gin 装配:路由 + 中间件链 + CORS + admin SPA 回退 |
handler |
30+ 文件:task/agent/kb/report/space/tenant/billing/payment/voice/jarvis/prompt/admin/wechat/local_runner/platform_tools |
middleware |
RequestID · Observe · Auth 系列 · TenantContext · SpaceContext · RateLimit · Guardrail · Audit · Require*Role |
store |
Postgres(GORM) + Redis 全部访问;迁移、租户作用域插件、leader 选主 |
auth |
无状态 JWT 签发/校验 + bcrypt |
dsl |
前端 JSON DSL → contract.Task 解析组装 + 拓扑校验 |
guardrail |
输入护栏 Tier1(归一化 + 注入正则 + env 黑名单) |
payment |
渠道抽象 + manager + 微信支付 |
wechat |
公众号带参二维码扫码登录 + 事件回调 |
voice |
火山 V3 流式 ASR/TTS 客户端 + 二进制帧协议 + 攒句器 |
webui |
go:embed admin 产物打进二进制 |
nats |
shared/bus 薄封装 |
技术栈
| 用途 | 库 | 版本 |
|---|---|---|
| Web 框架 | gin-gonic/gin |
v1.12.0 |
| SSE | gin-contrib/sse |
v1.1.1 |
| ORM | gorm.io/gorm + driver/postgres |
v1.31.1 / v1.6.0 |
| 缓存 | redis/go-redis/v9 |
v9.20.0 |
| 鉴权 | golang-jwt/jwt/v5 + x/crypto(bcrypt) |
v5.3.1 / v0.53.0 |
| ID | bwmarrin/snowflake |
v0.3.0 |
| WebSocket | gorilla/websocket |
v1.5.3 |
| 指标 | prometheus/client_golang |
v1.23.2 |
| 追踪 | otelgin + otel |
v0.69.0 / v1.44.0 |
| 支付 | wechatpay-apiv3/wechatpay-go |
v0.2.21 |
| 测试 DB | glebarez/sqlite(纯 Go 无 CGO,仅测试) |
v1.11.0 |
后台常驻组件
| 组件 | 作用 |
|---|---|
ServeConfig ×3 |
模型配置控制面应答(kind = chat / embedding / voice) |
ServePrompts |
激活 prompt 集下发 |
ConsumeTaskStatus |
任务状态落库 + 报告完成时主动语音播报 |
ConsumeEval / ConsumeUsage |
评测结果 upsert / 用量落库计费 |
StartIngestWorkers |
JetStream 入库作业 worker 池(有界并发背压) |
ServePlatformTools |
gateway 自己作为 MCP 工具提供方(见 §5.4) |
StartReconcile / StartSubscriptionTicker / StartScheduleTicker |
微信掉单补偿 / 订阅周期发放 / JARVIS 定时任务 |
三个 ticker 均带 PG advisory lock 选主(store/leader.go),多副本下只有一个实例真正扫。
辅助 CLI:cmd/localsim(模拟桌面本地执行器)、cmd/voicesim(免麦端到端语音链路模拟)、cmd/voiceconfig、cmd/voicecheck。
3.2 dispatcher —— Agent 编排调度集群
github.com/sundynix/sundynix-dispatcher · Go 1.25.8 · 无 HTTP 业务端口
| internal 包 | 职责 |
|---|---|
eino |
编排引擎全部:orchestrator · compose_compiler/graph/callbacks · react_agent · coordinator · checkpoint · memory_extract · report |
harness |
治理五件套:budget · circuitbreaker · eval · jailbreak · output |
llm |
pool(热更新) · failover(主备链) · cache(输出缓存) |
dsl |
DSL 图 → 对话计划编译 |
nats |
shared/bus 薄封装 |
技术栈:cloudwego/eino v0.9.12 + eino-ext/components/model/openai v0.1.13(OpenAI 兼容协议)、otel v1.44.0。
另有 cmd/loadtest(阶梯并发压测器)。
3.3 mcp-go —— Go I/O 型工具服务
core NATS request-reply,订阅 sundynix.tools.go.>,队列组 mcp-go-workers,探针 :8092。
技术栈:blevesearch/bleve/v2 v2.4.2(CJK 分词)、milvus-sdk-go/v2 v2.4.1、neo4j-go-driver/v5 v5.24.0、go-redis/v9、gorm.io/gorm。
⚠️
internal/office/unioffice.go名字有误导性:并不引任何第三方 Office 库,而是用标准库archive/zip+ 内联 OOXML/WordprocessingML XML 手工拼.docx。
工具注册表(internal/mcp/gateway.go 的 buildRegistry() 是唯一事实源,dispatcher 经 list_tools 动态发现,加工具零改调度代码)
暴露给自主 agent(10 个):wiki_search(知识检索) · memory_get→recall_user_memory · memory_upsert→remember_user_fact · history_get · web_search · web_fetch · calculator · current_datetime · sql_query(仅 SELECT/WITH) · chart(bar/line/pie)
内部/流水线(13 个):kb_ingest · kb_delete · kb_search · kb_graph · report_render · report_store · report_export · external_api(带 SSRF 校验) · memory_delete · memory_list · history_append · health · echo
3.4 mcp-py —— Python 算法型工具服务
Python 3.11 · hatchling · 无 Web 框架(纯 asyncio + nats-py),订阅 sundynix.tools.py.>,队列组 mcp-py-workers。
依赖:nats-py>=2.7.0 · python-docx · openpyxl · pypdf · docker>=7.1.0
| 工具 | agent 暴露 | 说明 |
|---|---|---|
run_code |
✅ | Docker 沙箱 256m/10s |
secure_sandbox |
❌ | 更严档 128m/5s |
parse_document |
❌ | txt/md/csv 直读;docx/xlsx/pdf 按扩展名路由 |
echo |
❌ |
两层防护:sandbox.py AST 静态守卫(拒 os/sys/subprocess/socket/ctypes/pickle 与 eval/exec/open)+ interpreter.py Docker 真隔离(禁网 / 非 root / 丢能力 / 限资源 / 一次性)。
mineru.py(多模态解析)目前为桩。
3.5 shared —— 共享库
| 包 | 作用 |
|---|---|
bus |
NATS/JetStream 封装:流声明、任务收发、Token/Exec 回流、工具 RPC、5 条持久流、控制面、KV checkpoint;trace.go 把 W3C traceparent 塞进 NATS 头实现跨总线链路串联;消费侧解密 api_key |
contract |
三方共享契约:subject 常量、Task/ToolCall/ToolResult/各类 Event、入库 claim-check、报告对象键 |
blob |
MinIO 封装;cli==nil 即降级回退本地盘,不阻断启动 |
secrets |
AES-256-GCM,密钥由 SUNDYNIX_SECRET_KEY 经 SHA-256 派生;密文 enc:1:+base64url(nonce‖ct);无前缀原样返回(兼容旧明文) |
otelx |
OTel 启动器(W3C 传播器 + OTLP/HTTP → Jaeger)+ 带 trace_id 的结构化 slog |
prompts |
受管提示词注册表(内置默认 + PROMPTS_FILE 覆盖 + 控制面热下发) |
health |
给无 HTTP 端口的服务起极小探针服务 |
cmd/devnats |
内嵌 nats-server,本地开发免装 |
4. NATS 总线契约
4.1 任务主链(JetStream 持久)
| 流 / Subject | 值 | 用途 |
|---|---|---|
SUNDYNIX_TASKS |
sundynix.tasks.<id> |
任务队列,消费者 dispatchers(队列组负载均衡) |
4.2 回流(core NATS,即时不持久)
| Subject | 用途 |
|---|---|
sundynix.streams.<id> |
Token 流,结束用消息头 X-Stream-End: 1 |
sundynix.exec.<task_id> |
结构化执行节点事件(seq/node/kind/phase/label/ms) |
sundynix.voice.event.<user_id> |
JARVIS 语音事件(navigate / announce) |
4.3 工具调用(request-reply + 队列组)
| Subject | 队列组 | 提供方 |
|---|---|---|
sundynix.tools.go.<tool> |
mcp-go-workers |
mcp-go |
sundynix.tools.py.<tool> |
mcp-py-workers |
mcp-py |
sundynix.tools.platform.<tool> |
platform-tools-workers |
gateway 自己 |
sundynix.local.exec.<user_id> |
— | 桌面端 runner(无订阅 = 离线,明确报不可用) |
4.4 回写(JetStream 持久 + 落库幂等 → at-least-once 重投安全)
| 流 | 消费者 | Subject | 用途 |
|---|---|---|---|
SUNDYNIX_STATUS |
gateway-status |
sundynix.status.task |
任务生命周期状态 |
SUNDYNIX_USAGE |
gateway-usage |
sundynix.usage.task |
token 用量(计费凭据) |
SUNDYNIX_EVAL |
gateway-eval |
sundynix.eval.task |
自动评测结果 |
SUNDYNIX_APPROVALS |
approval-resumers |
sundynix.approval.<task_id> |
HITL 审批决定(抗离线) |
SUNDYNIX_INGEST |
ingest-workers |
sundynix.ingest.<job_id> |
入库作业队列(claim-check:大文件先落 MinIO,消息只带 StageKey) |
⚠️ 状态流 subject 必须在
sundynix.tasks.>之外,否则会被任务流捕获成「幽灵任务」自我放大。
KV:SUNDYNIX_CHECKPOINTS(TTL 24h)—— 键 task_id 存 compose checkpoint,键 pending:task_id 存 resume 记录。
4.5 控制面
sundynix.config.<kind>.get / .updated(kind = chat / embedding / voice)· sundynix.prompts.get / .updated · sundynix.health.dispatcher(心跳)。网关侧共用队列组 gateway-workers。
4.6 Task.Meta 约定
user_id · tenant_id · session_id · safety_check · token_budget · model_profile(=voice) · intent(=report) · topic · kb
状态机:submitted → running → done|failed|timeout,HITL 分支 waiting → running|rejected。
评测分级:ok(≥0.75) / warn(0.5~0.75) / poor(<0.5)。
5. 编排引擎
5.1 执行路径
Orchestrator.Handle → executeGraph → runComposeGraph → execComposeGraph(internal/eino/compose_compiler.go,唯一引擎):
dsl.Parse+dsl.Compile→ 建board(黑板,进 compose 本地状态)- 无图/空图 → 退化为 compose 单轮对话
- 建
compose.Graph:边只传占位信号flowSignal,真实数据全走黑板(注册 no-op merge 支持 fan-in);DAG 触发让无依赖节点自动并行 branch节点走AddBranch;approval节点在有 checkpoint 后端时编译为approvalInterruptLambda(compose.Interrupt落盘并释放 goroutine)- 编译失败 → 降级回自研
graph.go(已退役,保留作安全网)
5.2 节点类型(12 种)
| kind | 作用 |
|---|---|
input |
输入/查询 |
memory |
记忆召回 |
retriever |
RAG 检索 |
tool |
显式工具调用 |
agent |
LLM 推理;autonomous: true → 走 ReAct 自主工具循环 |
coordinator |
多智能体:agent-as-tool 派给专家 + 并行 fan-out + 综合 |
aggregate |
汇聚 |
approval |
HITL 人工审批(中断落盘) |
render |
渲染(报告等) |
map |
并行 fan-out |
output |
输出 |
branch |
条件分支(建图阶段单独处理,支持 else/default 兜底) |
5.3 ReAct 自主工具
react_agent.go 用 Eino react.NewAgent,工具集经 list_tools 从三个提供方动态发现(mcp-go / mcp-py / gateway platform)。
MaxStep默认 12(REACT_MAX_STEP可调)StreamToolCallChecker扫描整段流判定工具调用(默认只看首片段,deepseek 等常先吐文本再给 tool call 会漏判)inject参数(user_id / session_id / task_id / kb / tenant_id)服务端运行时绑定,不暴露给模型- 工具可自报
timeout_sec突破默认 3s(本地执行类要等用户点确认框)
5.4 平台工具族(gateway 提供,11 个)
平台操作的权威(提交关卡、归属校验、计费)都在 gateway,工具就长在权威所在地。
| 工具 | 作用 |
|---|---|
platform_recent_tasks / platform_task_status |
查任务列表 / 单任务状态与输出 |
platform_gen_report |
派发报告任务(走 preflightCore 同一关卡:预算/暂停/积分硬拦截) |
platform_open_view |
切换客户端界面(navigate 白名单) |
platform_schedule_create / _list / _cancel |
定时任务增删查 |
local_list_dir / local_read_file |
看/读用户电脑(只读) |
local_write_file / local_exec |
写文件 / 执行命令(三道闸,见 §8.3) |
安全铁律:一律 inject user_id + 服务端归属校验(越权查他人任务一律回「不存在」,不泄露存在性);会烧钱的提交必须过 preflightCore。
5.5 harness 治理层
| 组件 | 作用 |
|---|---|
budget.go |
token 预算估算(CJK≈1 tok/字),触顶中止整图 |
circuitbreaker.go |
三态熔断(阈值 3 次连续失败 / 冷却 20s / 半开 1 次探测) |
eval.go |
规则 + LLM-as-judge 评测,异步 off 热路径;低分触发自动纠偏 |
jailbreak.go |
Tier2 越狱分类(severity ≥0.7 才拦) |
output.go |
发射层逐片脱敏(sk-* / AKIA* / JWT / Bearer),跨分片不漏检 |
6. LLM 治理
cachingModel(输出缓存)
└─ failoverModel(主备链,每模型独立熔断器)
├─ 主模型(active)
└─ 备用模型(其它 enabled chat 模型)
- 双池:工作主力
pool(chat) + JARVIS 语音voicePool(voice),语音池空则透明回落工作池 - 热更新:经 NATS 配置控制面(
SubscribeModelConfigUpdated+ 启动时FetchModelConfigWithRetry) - 接入方式:
eino-ext/openai,OpenAI 兼容协议(当前用 DeepSeek 在线 API,不拉本地 Ollama) - 单次请求超时 120s;
LLM_FORCE_STUB=1走降级桩(压测用) - 暴露
ModelHealth(provider/model/role/state/fails)供 admin 展示 - 已知局限:Stream 仅在建流同步报错时切备,已开始回流 token 的中途失败不切
- 输出缓存:
respCacheTTL 60s(LLM_CACHE_TTL_S,0=关)、容量 512(LLM_CACHE_MAX),key = sha256
Prompt 版本化:shared/prompts 内置默认 → PROMPTS_FILE 覆盖 → sundynix_prompt 表 + admin 热切换(含 diff 与撤销),不重编译即可改。
Known key:graph.extract · eval.quality · eval.refine · guard.jailbreak · coordinator.lead · memory.extract
7. 数据存储
7.1 中间件职责
| 中间件 | 版本 | 用途 |
|---|---|---|
| NATS + JetStream | 2-alpine(max_payload 8MB) | 统一总线(见 §4) |
| PostgreSQL | 16-alpine | 主业务库,29 张表 |
| Redis | 7-alpine | 会话 / 限流 / 任务输出缓存(TTL 48h) / 扫码 ticket;有内存降级兜底 |
| Milvus | v2.4.13 standalone | RAG 向量路 |
| etcd | v3.5.14 | 仅 Milvus 元数据依赖 |
| MinIO | RELEASE.2023-03-20 | 文档正文 blob、报告源/产物(bucket sundynix-docs)+ Milvus 段存储 |
| Neo4j | 5-community | RAG 图谱路(三元组) |
| Jaeger | all-in-one 1.60 | OTLP 收集 + trace UI |
| Bleve | 进程内库(非容器) | RAG 全文路,scorch 落盘 BLEVE_PATH —— 唯一需要给 mcp-go 挂持久卷的原因 |
7.2 数据表全清单(29 张)
命名:TablePrefix: sundynix_ + SingularTable: true。公共基类 BaseModel = 雪花字符串 id + created/updated + 软删。
| # | 模型 | 表 | 职责 |
|---|---|---|---|
| 1 | User |
sundynix_user |
平台用户 |
| 2 | Task |
sundynix_task |
一次提交的编排任务(DSL);业务 id task_xxx 单列供 NATS subject |
| 3 | Eval |
sundynix_eval |
自动评测结果,按 task_id upsert |
| 4 | LLMModel |
sundynix_model |
模型后端配置,每 kind 同时刻仅一条 Active |
| 5 | KB |
sundynix_kb |
知识库,(space_id,name) 唯一,分区键 space_id/name |
| 6 | Doc |
sundynix_doc |
入库文档主表(Obsidian 式文库) |
| 7 | Agent |
sundynix_agent |
编排定义,(space_id,name) 唯一 |
| 8 | DocLink |
sundynix_doc_link |
[[双链]] 索引,供反链/关系图 |
| 9 | Pricing |
sundynix_pricing |
模型计价(每 1K token 输入/输出单价) |
| 10 | Prompt |
sundynix_prompt |
受管提示词版本,(key,version) 唯一 |
| 11 | AuditLog |
sundynix_audit_log |
敏感操作留痕,只增不改 |
| 12 | GuardrailEvent |
sundynix_guardrail_event |
输入护栏命中事件 |
| 13 | Tenant |
sundynix_tenant |
租户(计费/隔离单位),含物化余额列 |
| 14 | TenantMember |
sundynix_tenant_member |
用户↔租户成员关系 + 角色 |
| 15 | TenantInvite |
sundynix_tenant_invite |
可复用邀请码(扫码入组) |
| 16 | Space |
sundynix_space |
共享工作区(资源容器) |
| 17 | SpaceMember |
sundynix_space_member |
空间成员 + 空间内角色 |
| 18 | UsageEvent |
sundynix_usage_event |
用量明细,task_id 唯一 → 幂等 |
| 19 | CreditLedger |
sundynix_credit_ledger |
积分账本(append-only),余额 = SUM |
| 20 | UsageRollup |
sundynix_usage_rollup |
用量按租户/天聚合快照 |
| 21 | Setting |
sundynix_setting |
平台级键值配置 |
| 22 | CreditPack |
sundynix_credit_pack |
积分包商品 |
| 23 | PaymentOrder |
sundynix_payment_order |
充值订单(兑换码也写一行) |
| 24 | RedeemCode |
sundynix_redeem_code |
兑换码 |
| 25 | SubscriptionPlan |
sundynix_sub_plan |
订阅套餐 |
| 26 | Subscription |
sundynix_subscription |
已购订阅(到期即 expired,不自动续) |
| 27 | UserJarvis |
sundynix_user_jarvis |
每用户 JARVIS(名字/人设/自带火山 key,密文入库) |
| 28 | Schedule |
sundynix_schedule |
定时任务 |
| 29 | SchemaMigration |
sundynix_schema_migration |
已应用的版本化迁移记录 |
7.3 迁移机制
整段迁移在 PG advisory lock(key 20260721,60s 超时兜底)内串行:
legacy(默认关) → AutoMigrate(29 模型) → 版本化 schemaSteps
只有 AutoMigrate 失败才返回 error;版本化步骤失败只记日志下次重试。
4 个版本化步骤:账本 grant/adjust 的部分唯一索引(支付入账与退款的幂等闸)· 回填租户物化余额 · 微信 openid 唯一索引。 部分唯一索引不写在 struct tag 里 —— AutoMigrate 早于回填会撞车,必须回填后显式建。
破坏性 legacy 迁移需 ALLOW_LEGACY_SCHEMA_MIGRATION=1 显式开启(雪花 id 改造、双链改按 Doc.ID 关联)。
8. 关键链路
8.1 任务提交 → 编排 → 回流
sequenceDiagram
participant C as 桌面端
participant G as gateway
participant N as NATS
participant D as dispatcher
participant M as mcp-go
participant L as LLM
C->>G: POST /tasks (DSL)
G->>G: 鉴权 → 租户/空间上下文 → 限流 → 护栏
G->>G: preflight:预算/暂停/计费租户/积分硬拦截
G->>G: launch:落库 + 起录像器
G->>N: publish sundynix.tasks (JetStream)
G-->>C: 202 task_id
C->>G: GET /tasks/:id/stream (SSE, token 走 query)
N->>D: 消费任务
D->>D: DSL 编译为 compose.Graph
loop ReAct 循环
D->>L: 推理(failover + 熔断 + 缓存)
L-->>D: tool_call
D->>N: request sundynix.tools.go
N->>M: 队列组分发
M-->>D: ToolResult
end
D-->>N: Token 流 sundynix.streams
N-->>G: 订阅回流
G-->>C: SSE 逐字推送
D->>N: status / usage / eval(JetStream 持久)
N->>G: 幂等落库
8.2 语音 JARVIS 全双工
sequenceDiagram
participant U as 用户
participant C as 桌面端
participant G as gateway
participant V as 火山 ASR/TTS
participant D as dispatcher
U->>C: 按住空格说话(PTT)
C->>G: WS 二进制帧:PCM 16k 上行
G->>V: 流式 ASR(X-Api-Key 鉴权)
V-->>G: 转写(部分/最终)
G-->>C: transcript
U->>C: 松开 → end
G->>G: trySubmit:转写 → 组 DSL → 同一提交关卡
G-->>C: task_id
G->>D: 提交任务(model_profile=voice → 走快模型)
D-->>G: Token 流
G-->>C: reply(打字机,早于音频)
G->>V: 攒句 → 双向流 TTS
V-->>G: PCM 24k
G-->>C: speaking + 音频帧 → tts_end
C->>U: 无缝播放
要点
- ASR 与 TTS 是不同帧族(ASR 简帧无事件号;TTS V3 事件族带 event/session/gzip)
- 下行先订阅 token 流再建 TTS 会话 —— core NATS 无持久,订阅晚于产出会丢开头
- 客户端播放按
nextStart预约到未来时刻,收到tts_end时不能立即停(合成远快于语速,停了只剩前几个字)
8.3 本地执行(JARVIS 操作用户电脑)
sequenceDiagram
participant D as dispatcher
participant G as gateway
participant R as 桌面 Go host
participant U as 用户
Note over R,G: 登录后注册:WS /local/runner
R->>G: 上线(携带授权目录白名单)
G->>G: 队列组订阅 sundynix.local.exec
D->>G: 调 local_exec(timeout_sec=160)
G->>R: WS 转发 tool + args
R->>R: 闸一:独立开关校验
R->>R: 闸二:硬黑名单(14 条正则,命中不弹框直接拒)
R->>U: 闸三:原生确认框(默认按钮=拒绝,60s 无应答即拒)
U-->>R: 允许 / 本次会话都允许
R->>R: 沙箱内执行(cwd 锁授权目录,60s 超时,输出 16KB 截断)
R-->>G: 结果
G-->>D: ToolResult
超时链必须外松内紧:dispatcher 160s > gateway 150s > runner 转发 140s > 桌面端(审批 60s + 执行 60s)。 任一层比内层短,用户还在看确认框就会被判超时。
9. 功能实现状态
图例:✅ 已完成(live 验证) · 🟡 部分 · ❌ 未做
9.1 多租户 / 空间 / RBAC
| 功能 | 状态 |
|---|---|
| Tenant/TenantMember + 注册自动建默认租户 + 存量回填 | ✅ |
| gorm 租户隔离插件(查询/更新/删除自动加 tenant_id,创建自动填) | ✅ |
| 租户角色 RBAC(owner/admin/member/viewer)+ 路由级校验 | ✅ |
| 租户邀请码(二维码扫码入组) | ✅ |
| Space 共享工作区(KB/Agent 按空间共享 + 空间角色 + 全员空间) | ✅ |
用户 role 字段 + 角色表(把 RequireAdmin 从白名单升级为角色校验) |
❌ |
| 用户管理接口(列举/禁用/改角色) | ❌ |
9.2 计量 / 计费 / 支付
| 功能 | 状态 |
|---|---|
| 计价配置 + usage_event 计量 + credit_ledger 账本 + daily rollup | ✅ |
余额硬拦截(CREDIT_ENFORCE) |
✅ |
| 支付渠道抽象 + 微信 Native(真环境实测通过) | ✅ |
| 兑换码 / 人工核销 | ✅ |
| 对账 + 退款(adjust 负分录 + 回退余额 + 审计) | ✅ |
| 订阅套餐(周期发放 + 到期失效) | ✅ |
| 发票 / Stripe | ❌ |
9.3 知识库 / RAG
| 功能 | 状态 |
|---|---|
| 三路混合检索(Bleve 全文 + Milvus 向量 + Neo4j 图谱,RRF k=60 融合 + rerank) | ✅ |
| 中文分词修复(CJK bigram) | ✅ |
| 离线检索评测(recall@k / MRR,hybrid vs 单路) | ✅ |
| 大文件生产化(MinIO 正文 + 并发 embed + 窗口化图谱 + JetStream 持久队列,kill -9 续跑验证) | ✅ |
| KB 级联删事务化(三库 + MinIO 先删、PG 最后)+ MinIO 孤儿 GC | ✅ |
| Obsidian 式文库(Markdown + 双链 + 反链 + 关系图) | ✅ |
| 检索持久化治理 / 列表分页 | 🟡 |
| 多模态解析(MinerU/PaddleOCR) | 🟡 骨架,mineru.py 为桩 |
9.4 报告
| 功能 | 状态 |
|---|---|
| 报告编排(规划 → 分章并行 → 汇聚 → 存源) | ✅ |
| Word(.docx) 渲染(自建零依赖 OOXML) | ✅ |
| Markdown 导出 | ✅ |
| PDF 导出 | 🟡 走 webview 打印;后端原生 PDF 未做 |
| 分章 map 错误传播与汇总 | ✅ |
9.5 记忆
| 功能 | 状态 |
|---|---|
| memory CRUD + Profile 表 | ✅ |
| P1 异步攒批 Consolidate(每 3 轮 LLM 对账 ADD/UPDATE/DELETE/NOOP + 软删) | ✅ |
| P2 Score(Recency + Importance) 排序 + 衰减 + top30 截断 | ✅ |
| P3 Relevance(语义相关性) | ✅ |
| 会话历史 history_get/append | ✅ |
9.6 编排引擎
| 功能 | 状态 |
|---|---|
| Eino Phase A/B/C/D 全部(组件 → ReAct → compose 全图 → FSM) | ✅ |
compose 为唯一引擎(graph.go 已退役作降级网) |
✅ |
| HITL 人工审批中断(checkpoint 落盘 + NATS 决定回传 + 抗离线) | ✅ |
| 多智能体 coordinator(agent-as-tool + 定制 brief + 并行 fan-out + 专家超时) | ✅ |
| Branch else/default 兜底 · DSL 拓扑校验 · 工具动态发现 | ✅ |
| handoff / adk 可中断多智能体 | ❌ |
| 编译图缓存 | ❌ 判定为 premature(实测编译 ~13µs) |
| 审批 checkpoint 落盘失败重试(现只 log → 任务永卡 waiting) | ❌ |
9.7 模型治理
| 功能 | 状态 |
|---|---|
| 模型路由 + Fallback + 每模型三态熔断 | ✅ |
| 模型健康/熔断态 surface 到 admin | ✅ |
| 输出缓存 | ✅ |
| Prompt 版本化 v1(注册表)+ v2(DB 热切换 + diff + 撤销) | ✅ |
| 工作模型与 JARVIS 语音模型分离 + 用量按实际模型计量 | ✅ |
| Prompt 灰度 % A/B | ❌ |
9.8 评测 / 护栏
| 功能 | 状态 |
|---|---|
| 自动化评测(规则 + LLM 裁判,异步 off 热路径) | ✅ |
| 裁判校准 + 低分自动纠偏闭环(live 真触发) | ✅ |
| 输入护栏(注入检测 + 归一化 + 超大体拦截)+ 事件落库 | ✅ |
| 输出护栏(跨分片密钥脱敏) | ✅ |
| HITL 审批决定明细(理由)落库 | ❌ 现仅 who/when/status |
| 前端评测质量面板 | ❌ 后端 /tasks/:id/eval 已有 |
9.9 语音 / JARVIS 中枢
| 功能 | 状态 |
|---|---|
| 火山 ASR + 双向流 TTS 全双工(新版 API Key 鉴权) | ✅ |
| 语音触发任务(复用同一提交关卡) | ✅ |
| PTT 按住说话 + 打断 + 连续对话 + 打字机文本流 | ✅ |
| 每用户 JARVIS(名字/人设/自带豆包配置回落,语音不串主记忆) | ✅ |
| 全屏钢铁侠 HUD(接真实音频电平) | ✅ |
| P1 平台工具族(查任务/派报告,含越权拒绝与积分硬拦截验证) | ✅ |
| P2 动作通道(语音让界面切页,三层白名单) | ✅ |
| P3 主动播报(任务终态主动开口,正朗读则排队不抢麦) | ✅ |
| 声纹 / 唤醒词 / 音色克隆 / 多语种 / ASR-TTS failover | ❌ 本期不做 |
| P5 常驻 companion session | ❌ 暂缓(现靠 session history 串联已够用) |
9.10 本地执行
| 功能 | 状态 |
|---|---|
只读:local_list_dir / local_read_file + runner 注册 + 沙箱(逃逸单测全拦) |
✅ |
能动的手:local_write_file / local_exec + 三道闸(独立开关 + 14 条黑名单 + 原生审批框) |
✅ |
| 多目录白名单沙箱 + 空 path 自发现授权目录 | ✅ |
| 离线优雅降级(runner 不在线明确报不可用,不挂起) | ✅ |
| ToolPolicy 服务端策略下推 | 🟡 已有审批框 + 黑名单,下推未做 |
| 档 B:agent 循环下沉客户端(内环不过网) | ❌ 有决策门,未做 |
| gateway LLM 代理端点(档 B 的地基) | ❌ |
9.11 定时任务
| 功能 | 状态 |
|---|---|
sundynix_schedule + leader 锁 ticker(30s) + create/list/cancel 工具 |
✅ |
| 存自然语言指令,到点走同一关卡执行 + 主动播报 | ✅ |
| 先推进后提交防重复烧钱;停机错过的不补跑 | ✅ |
9.12 可观测 / 运维
| 功能 | 状态 |
|---|---|
Prometheus /metrics(路由模板低基数)+ 结构化日志 + X-Request-ID |
✅ |
/healthz /readyz 探针 + 依赖聚合健康 |
✅ |
| OTel 全链路(otelgin + 跨 NATS traceparent 传播 → Jaeger) | ✅ |
| admin 观测面(overview/status/tasks/spaces/usage/evals/datasources/orders/审计/护栏) | ✅ |
| 检索试验台(跨租户 + 单路 mode 对比) | ✅ |
| panic 进 trace span · TTFT/token-s 指标 | ❌ |
| K8s / DB HA / TLS / DR 演练 | ❌(例外:NATS 集群已落地) |
9.13 客户端
| 端 | 状态 |
|---|---|
| desktop(编排画布 · ⌘K · SSE 轨迹 · 文库 · 知识图谱 · 记忆面板 · JARVIS HUD · 本地 runner · 服务器地址运行时可配) | ✅ |
| admin(官网 + 控制台,go:embed 进 gateway) | ✅ |
| web(租户自助:注册/组织/团队/账单) | ✅ |
| 前端测试 | 🟡 11 个测试文件,集中在 lib 纯函数;视图层基本不测 |
9.14 ⚠️ 已知的文档记账偏差
以下 4 处文档与代码不符,一律以代码为准:
PROGRESS.md停在 2026-06-19,其中「计费未做」「多租户未做」「Relevance 待 P3」均已被后续代码推翻。DEPTH_ROADMAP.md进度表写「T4 后端做实 0/6 组」,但正文里 T4.A/B/E 大量条目已勾 ✅。DEPTH_ROADMAP.mdTier 3 写「NATS 集群未做」,实际三节点集群已在 128 落地。PAYMENT_DESIGN.md标题写「不做订阅」,但订阅套餐全套(表 + ticker + admin 页)已实现。
10. 安全与治理
10.1 中间件链(顺序有意义)
Recovery → otelgin → RequestID → Observe → cors → Auth → TenantContext → SpaceContext → RateLimit → Guardrail
Auth 必须前置于 RateLimit —— 否则无法按用户限流(企业网多人共享出口 IP 会互相拖累)。
10.2 鉴权
- JWT 无状态(
internal/auth),owner = 雪花 user.id;生产默认密钥 fail-fast Auth()非阻断解析 →RequireAuth()/RequireAdmin()(当前为ADMIN_USER_IDS白名单)AuthFromHeaderOrQuery():WS 与 SSE 带不了 Bearer 头,走?token=—— 用于/tasks/:id/stream、/tasks/:id/exec、/kb/ingest/:id/stream、/reports/:id/export、/voice/stream、/local/runner- 注册/登录各带 10/min 限流;微信公众号扫码登录独立通道
- 支付回调例外:
/billing/callback/:channel无 Bearer,渠道验签是唯一的门
10.3 密钥加密
shared/secrets:AES-256-GCM,密钥由 SUNDYNIX_SECRET_KEY 经 SHA-256 派生 32 字节;密文格式 enc:1: + base64url(nonce‖ciphertext),带版本前缀便于轮换。
全链路:gateway 保存时 Encrypt 落 PG → 密文原样过 NATS → dispatcher/mcp-go 在 bus 层 Decrypt。api_key 在磁盘与线缆上都非明文,仅构建 LLM 客户端时内存短暂还原。三服务的 SUNDYNIX_SECRET_KEY 必须一致。
微信支付商户私钥不落库不进镜像 —— 宿主目录只读挂载。
10.4 租户隔离
store/tenant_scope.go:tenantScopedMarker 空接口(小写方法,只有本包模型能标记)+ 4 个 gorm callback(query/update/delete 前自动加 tenant_id = ?,create 前自动填)。
两个必须记住的旁路:系统级读(admin 聚合)与跨租户写(对账)都要 WithoutTenant(ctx) —— 漏了会出回归或对账崩。
10.5 限流与审计
- 限流:Redis 为主后端 + 进程内固定窗口 fail-safe 兜底(Redis 挂时不再 fail-open,改宽松本地限流);已认证按 uid、未认证按 IP
- 审计:
Audit(db)只审计变更类(POST/PUT/DELETE/PATCH),best-effort 不拖垮主流程;挂在整个/admin组、prompt 激活/撤销、HITL 审批、租户成员变更、充值兑换 - 护栏事件:命中落
GuardrailEvent(actor/kind/reason/signals/path/ip)→ admin 审计页
11. 客户端形态
三个独立产品面,绝不合并:
| 端 | 定位 | 技术栈 | dev 端口 | 路由 |
|---|---|---|---|---|
| desktop | 用户工作产品 | Wails v3.0.0-alpha2.117 + React 19 + TS 5.6 + Tailwind 3.4 + React Flow 12 | 9245 (wails3) / 5173 (纯 vite) | 无路由,useState<ViewKey> |
| admin | 官网(/) + 平台超管控制塔(/admin) |
React 19 + react-router-dom 7 | 5174 | BrowserRouter |
| web | 租户客户自助柜台 | React 19 + react-router-dom 7 | 5175 | HashRouter(纯静态托管即可深链) |
desktop 页面(ViewKey):home 工作台 · studio 编排 · kb 知识库 · runs 运行 · report 报告 · memory 记忆 · usage 用量
admin 页面(17 条路由):仪表盘 / 服务状态 / 任务观测 / 自动评测 / 审计安全 / 模型配置 / 登录设置 / 语音设置 / 数据源RAG / 提示词 / 支付(配置·订阅·订单对账) / 租户用户 / 微信用户 / 空间 / 安全护栏
三端共用自建 UI 组件(src/ui/:Badge/Button/Card/Dialog/Input/Table/Tabs/Toast + cn),未引任何组件库。
测试统一 Vitest 4 + jsdom + Testing Library。
12. 部署拓扑
12.1 三机内网生产
flowchart LR
USER["用户桌面端"]
FRP["frp 映射"]
subgraph M132["192.168.100.132 · 应用机"]
GW["gateway 3000→8080<br/>内嵌 admin UI"]
DP["dispatcher"]
MG["mcp-go"]
MP["mcp-py"]
end
subgraph M128["192.168.100.128 · 基建机 + CI runner"]
N1["NATS 三节点集群<br/>4222/4223/4224<br/>REPLICAS=3"]
PG2[("PostgreSQL")]
RD[("Redis")]
ML[("Milvus + etcd")]
NJ[("Neo4j")]
JG["Jaeger"]
end
M126[("192.168.100.126<br/>业务 MinIO<br/>bucket sundynix-docs")]
TX["162.14.122.200<br/>微信 token 中控<br/>静态 IP"]
USER --> FRP
FRP --> GW
GW --> N1
DP --> N1
MG --> N1
MP --> N1
GW --> PG2
GW --> RD
GW --> M126
MG --> ML
MG --> NJ
MG --> M126
GW --> JG
DP --> JG
GW --> TX
要点
- 对外只暴露 132:3000(gateway:API + admin UI + 语音 WS + 本地 runner WS),其余全部内网
- NATS 三节点
cluster.name: sundynix-cluster,routes 互指 6222;NATS_STREAM_REPLICAS=3走 Raft quorum;三节点max_payload: 8MB必须一致 - 128 上的 Redis/Milvus/NATS 无认证,靠防火墙只放行 132/126 网段
- 132 只读挂载两个宿主目录:微信支付商户私钥、微信域名校验文件(不进镜像、不进 git)
- 备份
scripts/backup.sh(PG/Neo4j/Milvus/MinIO 卷),建议 cron 每日异机存档
12.2 单机一体化
docker-compose.prod.yml 一条命令拉起应用 4 服务 + 全套基建(要求 Docker 24+/Compose v2、~8GB 内存)。
基建端口一律不对宿主暴露,只留 gateway 与可选 Jaeger UI。密钥用 YAML 锚点 ${SUNDYNIX_SECRET_KEY:?} 强制 .env 必填。
12.3 密钥模型
| 类别 | 内容 | 存放 |
|---|---|---|
| 引导密钥 / 基建凭据 | SUNDYNIX_SECRET_KEY · JWT_SECRET · PG/Neo4j/MinIO 密码 |
.env,部署时填一次 |
| 业务模型 key | LLM api_key · 语音 key · 支付配置 | 不进 .env,登录 admin 配,AES 加密存 PG |
丢失主密钥 = 已存业务 key 全部失效。
首次管理员:注册第一个账号 → 取 user id → 填 ADMIN_USER_IDS → 重启 gateway。
13. CI / CD
13.1 GitHub Actions(质量门,push main + PR)
| Job | 内容 | 红门 |
|---|---|---|
go |
4 模块 build + vet + test -race |
✅ 一票否决 |
lint |
golangci-lint × 4 模块,only-new-issues(存量约 42 处不拦) |
✅ 仅新问题 |
security |
govulncheck(advisory 不阻断)+ gitleaks 扫提交历史(命中即失败) |
部分 |
web |
三前端 npm ci + tsc --noEmit + vitest |
✅ |
desktop |
macOS runner,GOWORK=off,先出前端产物供 go:embed |
✅ |
py |
Python 3.11 pytest(含沙箱守卫测试) | ✅ |
Go 1.25 / Node 20。所有 job 带 if: !contains(github.server_url, 'sundynix.cn') 避免内网 Gitea 误跑。
13.2 Gitea Actions(内网真实 CD)
push main → 128 runner:不用 actions/checkout(内网连不上 github.com,改 git init + fetch --depth 1)→ 构建 4 镜像 → docker save | gzip scp 到 132 → docker load + up -d --no-build → 健康检查门(循环 20 次 curl /healthz,失败打日志并 exit 1)。
132 上的 .env 手工预放、部署绝不覆盖。
⚠️ CD 无任何测试门 —— 测试只在 GitHub 侧跑,内网推送直接部署。
13.3 Release
tag v* → wails3 构建 macOS universal(lipo 合并)+ Windows amd64 → GitHub Release。旧版 App 启动查 /releases/latest 提示更新。
14. 技术栈总表
| 领域 | 选型 |
|---|---|
| 后端语言 | Go 1.25(4 模块 workspace)+ Python 3.11(算法工具) |
| Web 框架 | Gin v1.12.0 |
| 编排引擎 | CloudWeGo Eino v0.9.12 + eino-ext/openai |
| 消息总线 | NATS 2 + JetStream(持久流 + KV) |
| 主库 | PostgreSQL 16 + GORM v1.31.1(雪花 id + 软删 + 租户插件) |
| 缓存 | Redis 7(+ 进程内降级) |
| 向量 | Milvus v2.4.13 |
| 全文 | Bleve v2.4.2(进程内,CJK bigram) |
| 图谱 | Neo4j 5-community |
| 对象存储 | MinIO(minio-go v7.2.0) |
| LLM | OpenAI 兼容协议(DeepSeek 在线 API) |
| 语音 | 火山引擎豆包 · 流式 ASR + 双向流 TTS v3 |
| 可观测 | Prometheus + OpenTelemetry v1.44 + Jaeger 1.60 |
| 桌面端 | Wails v3.0.0-alpha2.117(Go host + WKWebView) |
| 前端 | React 19 + TypeScript 5.6 + Vite 5 + Tailwind 3.4 + React Flow 12 |
| 前端测试 | Vitest 4 + jsdom + Testing Library |
| 支付 | 微信支付 APIv3(Native 扫码) |
| 密钥 | AES-256-GCM(enc:1: 版本化密文) |
15. 已知缺口
按优先级归类,均为明确未做而非遗漏:
架构演进
- 本地 agent 档 B(循环下沉客户端,内环不过网)+ 其地基 gateway LLM 代理端点
- ToolPolicy 服务端策略下推
- JARVIS 常驻 companion session(现靠 session history 串联)
治理补全
- 用户 role 字段与角色表(
RequireAdmin仍是 env 白名单) - HITL 审批决定理由落库
- 审批 checkpoint 落盘失败重试(现只 log,任务会永卡 waiting)
- 预算硬顶兜底(budget ≤0 即无限)
生产硬化(Tier 3,等真实流量)
- DB HA · K8s 编排 · TLS 终止 · DR 演练 · 备份自动化
- panic 进 trace span · TTFT/token-s 细粒度指标
产品功能
- 报告后端原生 PDF(现走 webview 打印)
- 多模态文档解析去桩(MinerU/PaddleOCR)
- Prompt 灰度 A/B
- 前端评测质量面板(后端接口已有)
- 语音:唤醒词 / 声纹 / 音色克隆 / ASR-TTS failover
文档债
architecture.md(小写)是历史重复文件,内容早于本文,建议删除或改为指向本文的跳转PROGRESS.md/DEPTH_ROADMAP.md汇总表需按 §9.14 校正