Commit Graph

31 Commits

Author SHA1 Message Date
Blizzard 1c7e8e1ea9 docs: 修 DEPTH_ROADMAP/EINO 两处过期标记
- 删 T4.E 熔断器接回 failover 重复的过期 [ ] 项(222 行  为准);
  T2.1 熔断器联动注明已整合。
- EINO Phase D FSM 回写主题名笔误 sundynix.tasks.status → sundynix.status.task
  (文档 141 行自己记过这次迁移)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 13:29:01 +08:00
Blizzard bf75bb8a62 feat(gateway): SaaS P2 计量·增量3 —— GET /admin/usage 用量/积分/成本口径
系统级(store.WithoutTenant,跨租户)用量观测:
- 无 tenant:全平台按天 SUM 趋势 + 各租户用量排行(含当前余额)。
- 有 tenant:该租户按天趋势 + 当前积分余额。
- from/to(YYYYMMDD)缺省近 30 天。UsageTrend/UsageByTenant/TenantBalance store 方法。

live 验证:两口径数值自洽(balance=seed−credits、credits=tok×汇率、totals=trend之和)。
至此 P2 计量后端(事实源)齐:明细/账本/余额/rollup/查询。前端页 + P4 硬拦截/充值待需求拉动。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:42:21 +08:00
Blizzard d058a63434 feat(gateway): SaaS P2 计量·增量2 —— 积分账本 + 物化余额 + 用量 rollup
- credit_ledger(append-only):grant/usage/adjust 分录,扣量/充值的事实源。
- tenant.credit_balance_micro:物化余额(= 账本之和),用量扣、充值增。
- usage_rollup:租户/天 upsert 累加(配额/账单读一行,不扫明细)。
- 消费 usage_event 一个事务内:落明细 → applyUsageCredit(账本负分录+扣余额)
  → upsertRollup(累加)。幂等锚在 usage_event.task_id 唯一:RowsAffected==0(重投)
  则跳过账本/余额/rollup,绝不重复计费。软扣:余额可为负(不拦,硬闸留 P4)。
- GrantCredits 充值/发放 API(记 grant 分录+增余额;增量3 admin 接)。

live 验证:ledger 负分录(ref=task_id) / 余额递减 / rollup 两任务累加(count=2,tok/credits求和)
/ **balance==seed+SUM(ledger) 不变量成立**(物化余额 == 账本真值)。

增量3(GET /admin/usage 趋势+余额)待做。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 11:26:27 +08:00
Blizzard 22183cac51 docs: DEPTH_ROADMAP 增量2b 打勾(PG 核心表租户隔离闭合)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 10:18:55 +08:00
Blizzard 30d667954b feat(gateway): 多租户增量2 —— gorm 租户插件按上下文自动隔离查询(SaaS P1)
统一强制、别靠人肉:受租户模型标记 isTenantScoped() 后,store/tenant_scope.go
的 gorm 回调按请求 ctx 自动给查询加 WHERE tenant_id、创建自动填 tenant_id。
- KB / Agent 加 TenantID 字段 + isTenantScoped() 标记
- middleware.TenantContext 把 tenant 注入 request context 供 store 插件读取
- ctx 无租户(系统/回填/未登录)不过滤,保留跨租户操作能力
- 启动 BackfillRowTenants 回填存量行 tenant_id=owner 默认租户(幂等)

live 验证:创建自动写 tenant_id ✓;同 owner 不同 tenant 的行被查询过滤 ✓。
Doc/DocLink(异步入库)、Task/Eval(无 owner)留待增量2b。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 17:58:58 +08:00
Blizzard f7d12cbf66 docs: DEPTH_ROADMAP T4.A 多租户增量1 打勾(租户身份地基)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 17:32:11 +08:00
Blizzard 53f7e172c3 fix: KB 级联删「事务化」—— 失败不再留不可删孤儿(T4.F)
原为 best-effort:三库删失败只 log、MinIO 删错误全吞、PG 照删 → 删一半失败即在
向量/全文/图谱/MinIO 留下「PG 无记录、连 file_id 都查不到」的不可删孤儿。

改为「类事务」(跨库 2PC 不可行,退而求其次:不留不可恢复孤儿 + 失败可见可重试):
- milvus.deleteByFile / bleve.deleteDoc / blob.Delete 改返回 error(原 void 吞错)
- rag.DeleteDoc 三库全试一遍(最大化清理)+ 聚合错误(原只回 Neo4j 的错);三库删幂等
- gateway KbDeleteDoc 失败闭合:先删依赖存储(三库→MinIO)、PG 最后删;
  任一存储删失败 → 不删 PG、返 502「未删除请重试」(保留 file_id 供幂等重试)
- 语义翻转:从「总能从列表删掉但留孤儿」→「有孤儿风险就不删、报错可重试」

live:杀 mcp-go→删→502+文档保留;mcp-go 活→删→200+清空(清场僵尸进程后验证)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 16:32:25 +08:00
Blizzard 55d50417a9 feat: 模型健康/熔断态 surface 到管理端(T4.F 可观测)
failover/熔断的运行时态原来只在 dispatcher 日志、admin 看不到 —— 本次接到概览可见:
- harness: CircuitBreaker.Snapshot() 只读观测访问器(state + fails,不动状态机)
- llm: Pool.ModelHealth() 上报主备链每模型 {provider,model,role,state,fails};
  buildWithFallbacks 把模型名↔breaker 配对(同包直接读 failoverModel.breakers);
  newFailoverModel 改返回具体类型以便读 breakers
- dispatcher 心跳 payload 加 models[]
- gateway /admin/overview 独立超时 Ping dispatcher,合并进 models.health
- admin 概览「模型路由」新增「运行时链路态(实时)」:逐模型状态点
  (🟢在线/🔴熔断中+失败数/🟡半开探测/单点)
- 单测:Snapshot、Pool.ModelHealth(名字↔态配对/单点/空)
- live:配坏主→提交任务打熔断→概览显示 broken-demo「熔断中·失败3」,备用在线

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 12:00:13 +08:00
Blizzard c060000f64 docs: DEPTH_ROADMAP 记入「模型健康/熔断态 surface 到管理端」(T4.F 可观测)
failover demo 暴露的真实缺口:熔断/failover 运行时态只在 dispatcher 日志、admin UI 不可见。
待补:dispatcher 心跳上报每模型 breaker 态 → gateway 聚合 → 概览/状态页展示。后期一起做。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 14:29:24 +08:00
Blizzard 23b8fa5e8a feat(gateway): 安全收口 —— CORS 生产收紧 + 限流按用户(T4.F)
- CORS:开发期缺省仍放行 *(便利);生产(APP_ENV=prod/GIN_MODE=release)未显式配
  CORS_ALLOW_ORIGIN 则不发 ACAO 头(浏览器按同源拦截),逼运维显式配置允许的源
- 限流键改「已认证按 uid、未认证按 IP」:企业网多人共享出口 IP 不再互相拖累,
  单用户换 IP 也绕不过;中间件顺序调整 Auth 前置于 RateLimit(否则取不到 uid)
- isProd() 判定与 middleware.RequireAdmin 同口径
- live 冒烟:登录/认证请求正常(重排未破链),dev CORS 仍 *

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 13:55:20 +08:00
Blizzard 6095bc71d2 refactor(mcp-go): 拆除 search.Hybrid 残骸(T4.F)
- search.Hybrid 空转(NewHybrid 返空、Query 返 nil TODO)、构造后存进 Gateway
  却从不被调用(真实 RAG 走 rag.Engine)→ 纯误导性死重量
- 删 internal/search 包 + gateway.go 字段/构造参数 + main.go 接线
- build/vet 干净;wiki_search 不受影响(本就用 g.rag)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 13:39:14 +08:00
Blizzard 7c211719d2 fix(dispatcher): 熔断器接回 failover —— 挂掉的主模型跳过而非每次白试(T4.E 收官)
- failoverModel 加每模型熔断器(阈值3/冷却20s,比编排层更紧):
  主模型持续失败达阈值 → 熔断 → 后续请求直接跳过主、直连备用(省掉每次白试主的失败往返);
  冷却到点半开放行探测打回主,成功即自动恢复走主(靠熔断器半开机制,无需外部通知)
- 全部模型都熔断时强制试主兜底(编排层 o.breaker 兜"全挂")
- WithTools 重包共享同一批 breakers(状态不清零)——否则每次 rewrap 熔断失效,关键坑
- harness 加 NewCircuitBreakerWith(threshold,cooldown,halfOpenMax) 参数化构造
- Generate/Stream 用泛型 runFailover 共用选路循环(去重)
- 3 新单测:熔断跳过主/WithTools 共享熔断状态/冷却后半开恢复(全三态)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:49:54 +08:00
Blizzard 65e939889e feat(gateway): DSL 拓扑校验 —— 前置拦截坏图(T4.E)
- ParseAndAssemble 加 validateTopology:拦重复/空节点 id + 悬挂边
  (source/target 指向不存在节点),避免坏图进编排后被 compose 静默跳过
- 保守策略:空图 / 报告任务 {topic} / 非标准载荷一律宽松放过,不误伤合法提交
- 单测覆盖合法/重复id/空id/悬挂边×2/空端点/放过场景
- live:悬挂边 POST /tasks → 422(错误指明具体边与缺失节点);合法图 → 202

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:14:31 +08:00
Blizzard 4bec95fde1 fix(dispatcher): Branch else 兜底 + 选路留痕(T4.E)
- branchNode 识别 default/else 边:主选择(true/false 或边序)未命中任何下游时,
  走显式 default 边而非悄悄落 END
- trace 明确区分「走 default / 未匹配收口结束(END) / 正常选路」,
  杜绝静默 fall-through 被误当 bug
- compose 层原有 len(chosen)==0 → END 收口保留(无 default 时的安全兜底)
- 3 断言单测:default 命中 / 条件真走 true / 无 default 未命中仍返回空

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:08:05 +08:00
Blizzard f9c849b14b fix(dispatcher): 多智能体专家超时 —— 卡死专家不再拖垮协调(T4.E)
- specialistTool 加 timeout 字段(默认 specialistTimeout=3min,专家可多轮 react+工具故给宽)
- InvokableRun 用 WithTimeout 包裹专家派发;超时(DeadlineExceeded)作为"观察"
  跳过该专家(err=nil),lead 据其余专家继续综合,不中断整个协调
- 2 单测:卡死专家 ~50ms 跳过并返回超时观察 / 正常专家不受影响
- timeout=0 时不包裹(向后兼容既有 specialistTool 构造)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 10:03:29 +08:00
Blizzard de36ed4cb3 fix(dispatcher): Map 节点错误传播 —— 并行子项失败不再静默(T4.E)
- writeSection 返回 (body, error):仅真·LLM 调用失败返 err;预算触顶/模型未配置
  是主动降级(可见降级正文,err=nil)不计失败
- writeSections 返回 ([]section, failed):失败项 Body 带可见「撰写失败」标记 + 汇总失败数
- mapNode:全部子项失败 → 置 b.fatalErr(任务判 failed 而非静默 done-空);
  部分失败 → trace span + 流式 ⚠️ 告警
- report handleReport:部分章节失败时流式提示,不再当全成功
- 3 单测:全失败/部分精确计数(=1 非 all-or-nothing)/mapNode 置 fatalErr

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:56:26 +08:00
Blizzard a830ae2a04 feat(admin): 审计 & 安全事件页(T4.B 收尾)
- 新增「审计 & 安全」页(/audit,运维组):接 /admin/audit + /admin/guardrail-events
  - 安全事件:护栏拦截/灰区放行(kind 徽标 + 原因 + method/path + actor/ip/时间)
  - 操作审计:变更操作(方法配色徽标 + 路径 + 状态码着色 + actor/ip/时间)
  - 顶栏统计(操作留痕/护栏拦截/灰区) + 30s 自刷 + 手动刷新
- api.ts 增 listAudit / listGuardrailEvents + 类型
- 风格对齐重做后的服务状态页(中性克制)
- T4.B 整组完成(剩 HITL 审批明细可选小项)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:43:41 +08:00
Blizzard 9e43d07428 feat(gateway): 护栏拦截事件落库 + 安全事件流(T4.B)
- store.GuardrailEvent 表(sundynix_guardrail_event) + AppendGuardrailEvent/ListGuardrailEvents
- middleware.Guardrail(db):命中 blocked/suspect 时 best-effort 落库
  (actor/kind/reason/signals/method/path/ip,独立超时 ctx)
- GET /api/v1/admin/guardrail-events:安全事件流(倒序,翻页)
- store.clampPage 抽出分页归一(audit/guardrail 共用)
- live:注入 "ignore all previous instructions" → 422 硬拦 + 事件留痕(kind=blocked)
- DEPTH_ROADMAP T4.B 护栏事件打勾

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:31:31 +08:00
Blizzard 16c67dcb4f feat(gateway): 敏感操作审计日志(T4.B)
- store.AuditLog 表(sundynix_audit_log) + AppendAudit/ListAudit
- middleware.Audit(db):只审计变更类(POST/PUT/DELETE/PATCH),收尾 best-effort
  落库(独立超时 ctx,失败静默不拖垮主流程);挂管理组 + prompt 激活/撤销 + HITL 审批
- GET /api/v1/admin/audit:倒序审计流(limit/offset 翻页)
- live:PUT pricing / POST prompts/deactivate 留痕(actor/path/status/ip),GET 不记
- DEPTH_ROADMAP T4.B:overview + audit 打勾

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 09:19:52 +08:00
Blizzard e2104efc64 feat(gateway): admin/overview 系统级聚合接口 + Tier4 后端路线图
- GET /api/v1/admin/overview (RequireAdmin):全平台口径聚合——
  用户/KB/文档总数 + 全局任务(今日/累计/趋势/终态) + 全局评测均分
  + 模型配置态(主/备/各kind数) + 提示词覆盖态 + 服务健康
- store.SystemCounts:全局 users/kb/doc 计数(区别 owner 隔离的个人口径)
- 区别桌面端个人 stats/overview:管理端概览改吃此接口(系统控制塔)
- DEPTH_ROADMAP 新增 Tier4 后端做实(A–F 六组,三路 Explore 审计产出)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 08:59:28 +08:00
Blizzard cb7dd86121 docs: DEPTH_ROADMAP T2.3 + T2 深化 4/4 全清(prompt DB 控制面热切换,live)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 14:59:52 +08:00
Blizzard 16c9298cf8 docs: DEPTH_ROADMAP T2.3 prompt 版本化地基(文件覆盖,live A/B),v2待
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 14:36:04 +08:00
Blizzard 865a47eeea docs: DEPTH_ROADMAP T2.2 检索质量评测(混合稳健兜底,量化在案)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 13:56:39 +08:00
Blizzard 4f52b30f95 docs: DEPTH_ROADMAP 新增 T2.4 大文件RAG生产化(三段/P0-P2 全勾,均 live 验证)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 13:38:03 +08:00
Blizzard ce70388e52 docs: DEPTH_ROADMAP T2.2 三路做实(中文全文/图谱修活),质量评测待补
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 10:00:59 +08:00
Blizzard 5d090304e5 docs: DEPTH_ROADMAP T2.3 输出缓存(半做,诚实标注命中率有限)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 09:40:45 +08:00
Blizzard 3519570178 docs: DEPTH_ROADMAP T2.1 (模型 Fallback)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 09:26:47 +08:00
Blizzard ef6f525a74 refactor(dispatcher): T1.1 退役 graph.go —— 编排引擎收成单一 compose
compose 已默认数天、HITL/多智能体/评测全在其上真实跑过,soak 充分。删掉自研拓扑
解释器这第二套引擎,消灭"双实现 drift"税:

- 删 runGraph(graph.go 的自研解释器)+ composeEnabled/EINO_COMPOSE 逃生舱开关
  + runConversation(仅 runGraph 用的死代码)。
- executeGraph 直接走 runComposeGraph;compose 编译失败兜底改单轮对话(不再回退
  graph.go);清掉仅 runGraph 用的 import(otel attribute/trace/otelx)。
- 保留 board / 各节点执行器(retriever/tool/agent/branch/approval/map/render/aggregate)
  / 工具函数 —— 它们是 compose 各节点 lambda 复用的,非 graph.go 专属。
- 测试:8 处 runGraph→runComposeGraph;等价测试(对照两引擎)转为 compose 正确性测试;
  runConversation 的开关测试转为「无 ChatModel 降级 runAgent」。

go test ./... 全绿 + vet 干净;冒烟 简单 agent/分支图 跑通。此后每个编排改动不再两边
对齐,成本减半。DEPTH_ROADMAP T1.1 。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 08:53:02 +08:00
Blizzard cb6eec5614 feat(desktop): T0.2 多智能体进 Studio —— coordinator 节点 + 专家卡片 + 派发可观测
把已通的多智能体后端(MULTI_AGENT.md)接上 UI,用户可在画布拖出协调者图。

- nodeCatalog: 新增 `coordinator`「多智能体协调」节点(indigo) + 新字段类型
  `agentList` + Specialist 接口({name,use,system,tools}),与后端 parseSpecialists 对齐。
- Inspector: AgentListField —— 可增删的子智能体卡片(名/用途/系统提示词/工具逗号分隔)。
- dsl 校验: agentList 需 ≥1 个有名字的专家、名字不重复。
- RunsView: 「工具调用」面板纳入专家派发(kind=agent),改名「工具/专家」,专家项
  用 Users 图标 + indigo「专家」徽标区分(此前只筛 kind=tool,漏掉多智能体派发)。
- 导出: agents 数组经 exportDsl 原样透传进 DSL → 后端 parseSpecialists 直接消费。

tsc + vitest(19) 绿;UI 同款结构 DSL 后端可跑(协调链路 live 已验)。
DEPTH_ROADMAP T0.2 ,T0 激活 2/2 完成。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 17:14:14 +08:00
Blizzard 5fb6e3ffa8 fix(harness): T0.1 校准评测裁判 —— 让恒温器真触发(此前全 1.00 空转)
诊断:旧评测 LLM judge 恒给 0.94/1.00、从不判 poor → 低分自动纠偏闭环几乎从没
启动。根因两层:
1. 提示词软:只说"严格"但无评分基准、不强制挑毛病 → 模型恒锚定 4–5。
2. 数学更致命:归一 score/5 下限 0.2,叠加无来源 Overall=0.4*rule+0.6*s 的
   0.4*rule≈0.4 底 → Overall 恒 ≥0.52、poor(<0.5)对"流畅但跑题/错误"永不可达。

修复:
- judge 提示词改对抗性+rubric:默认怀疑、先点缺陷再打分、给死 1–5 评分基准、
  要求用满区间;grounded judge 忠实度按编造说法递减(一处编造≤2)。
- 归一 score/5 → normJudge=(v-1)/4(1→0),让低质能压到 poor 触发纠偏。
- 测试:normJudge 区间 + 流畅跑题(judge=1)可达 poor + 好坏区分度;更新两处旧
  断言(4→0.75, 2→0.25)。

live 验证(deepseek):跑题→0.40 poor→自动纠偏(0.40→0.55);截断→0.55 warn;
好答案→1.00 ok。校准前三者全 1.00。评测+纠偏的投入由"摆设"变"在用"。

DEPTH_ROADMAP T0.1 。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 16:23:30 +08:00
Blizzard cc1a2c39aa docs: 深度路线图 DEPTH_ROADMAP.md —— 现有广度下做深度的优先级清单
诊断深度不足分四类:A 建了没激活(评测裁判恒 1.00、多智能体无 UI)、B 重复税
(双引擎、前端测试薄)、C AI 核心还浅(单模型无 fallback、RAG 部分降级/桩)、
D 生产硬化(部署深度,无真实流量前暂缓)。

按"杠杆÷工作量"排:T0 激活(校准评测/多智能体进 Studio) → T1 收口(退役
graph.go/前端补齐) → T2 深化(模型 fallback/RAG/prompt 版本+缓存) → T3 硬化⏸。
完成一项勾一项。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 16:14:09 +08:00