Blizzard
addaa1b34f
feat(space): 共享工作区增量3a —— Agent 编排按 Space 共享(纯 PG 打样)
...
引入 Space 中间容器(租户>Space>成员),资源作用域从 owner 改为 space_id,
让"个人私有/项目临时组队/整租户共享"出自同一模型(设计见 SPACE_DESIGN.md)。
先在纯 PG 的 Agent 上打样,零存储风险,验证协作+RBAC+切换 UX。
后端:
- 新表 Space{tenant_id,name,kind,creator,archived} + SpaceMember{space_id,user_id,role}
(如 Tenant 般不 isTenantScoped);User.ActiveSpaceID;Agent 作用域 owner→space_id,
owner 降级为创建人(供 UI 显示 / 删他人鉴权)
- store/space.go:个人空间幂等/活跃空间解析/切换/列表/建/成员CRUD/归档
- 迁移顺序坑:结构体只放非唯一 index,MigrateAgentSpaces 回填 space_id 后再建唯一
索引 idx_agent_sn + DROP 旧 idx_agent_on(否则存量空 space_id 撞车);启动序4步幂等
- 中间件 SpaceContext(注入 space_id) + RequireSpaceRole(照 RequireTenantRole)
- handler/space.go 空间端点 + 路由;agent.go 改空间作用域(删/覆盖他人需 admin)
- 计费零改动(Space 与 ResolveBillingTenantID 正交)
桌面端:
- api.ts space 接口;顶栏 SpaceSwitcher(含新建项目空间);StudioView 随空间切换
重拉编排 + viewer 禁保存;Agent 列表显示创建人 + 按 mine 控删除
验证:中间件6门控单测 + DB迁移(13个人空间/9 Agent全re-key/索引换新) + 后端HTTP全
场景(member见他人编排/删他人403、viewer存403、非成员切空间400+隔离、owner删他人200)
+ 浏览器实机(切换器3空间/Studio空间编排随切换隔离刷新/创建人显示/console无错)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-13 10:51:33 +08:00
Blizzard
248267984c
feat(desktop): 顶栏租户切换器(多租户)—— 切换活跃租户即换工作区+计费
...
用户属多个租户时,顶栏显示租户下拉(Building2 图标):切换即调 POST /me/tenant
换活跃租户,随后刷新余额芯片(显示新计费租户的可花余额)。仅 >1 租户时出现。
api 加 myTenants/switchTenant。
live 验证(preview):demoB(属公司A+公司B) 切换器显两租户;从公司A(共享,余额15.84)
切到公司B(个人,余额6.38)→ 后端 active 持久化、芯片随之更新为 6.4(橙,偏低)。tsc+48 测试全过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-08 11:02:36 +08:00
Blizzard
a878e2dc89
feat(desktop): 「用量」视图 —— 我的积分余额/消耗趋势/最近消耗(P3 续)
...
给终端用户一个自己的计量观测面(守边界:只读自己租户):
- 新增 UsageView(左导航 MANAGE 组「用量」,Coins 图标):余额 hero 卡
(硬拦截+余额≤0→红/偏低→橙)、区间 KPI(积分/Token/成本/运行数)、
积分消耗按天趋势条形图(近7/近30天可切)、最近消耗明细表(任务/模型/token/积分/成本)。
读 /api/v1/me/usage。
- 顶栏积分余额芯片改为可点,进「用量」页(onOpenUsage → setView)。
live 验证(preview):视图显示 公司A 余额 15.92 + KPI + 趋势bar(落在实际消耗日) +
最近消耗 3 行真实数据;tsc + 48 测试全过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-08 09:31:12 +08:00
Blizzard
511ae199a4
feat(desktop): 顶栏积分余额芯片 + 提交遇余额不足透出友好文案(P3 租户感知)
...
让计费对终端用户可见(守 desktop/admin 边界:只读自己租户,不碰 admin 配置):
- TopBar 加积分余额芯片(Coins 图标):常态显余额;硬拦截开+余额≤0 → 红「余额不足」;
偏低 → 橙。tooltip 显租户名 + 是否拦截。api.tenantCurrent() 读 /tenants/current。
- App 登录后拉租户上下文,每 20s 轮询 + 运行结束即刷新(余额跟手)。
- submitTask 遇 402 解析后端 error 文案透出(如「租户积分余额不足,请充值后再试」),
在运行面板报错处显示,用户知道为何被拦。
live 验证(preview):芯片显示 公司A 余额 15.9 ✓;enforce 开+余额0 时 /tenants/current
标 enforce+余额0(芯片转「余额不足」)、提交 402 带友好文案 ✓;tsc + 48 测试全过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-08 09:18:30 +08:00
Blizzard
d2662a1f37
fix(history): 历史运行复盘读库持久化 —— 杜绝过 Redis TTL 后卡「流式中…」
...
问题:历史任务超 Redis 流 10min TTL 后,SSE 回放在空流上永久阻塞 → 运行页卡「流式中…」、
轨迹/工具/输出全空。
修复:收尾把最终输出 + 执行轨迹持久化到 PG,历史复盘改读库(不依赖 Redis TTL):
- store:Task 加 output/trace 两列;SaveTaskOutput/SaveTaskTrace/GetRunDetail。
trace 用 type:text(不是 jsonb)——否则提交时空串 "" 入 jsonb 列会 INSERT 失败、整条任务不落库。
(已 ALTER 既有 trace 列 jsonb→text。)
- gateway:token/exec 录制器在 done 时把累计的输出/轨迹快照落库。
- 新增 GET /tasks/:id/replay 返回持久化的 {output, exec}。
- RunsView:选中历史运行改 runReplay() 读库(秒回、phase 立即 done/error),不再 SSE 回放。
即便旧任务无持久化数据,也是 done+空态,绝不再卡「流式中…」。
live:新任务落库 output 305 字(含表格) + 轨迹 5 事件,/replay 正确返回;tsc+vite、gateway 全绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-26 17:52:26 +08:00
Blizzard
3cf3c0b070
feat(desktop): 运行·观测 重做为运行历史 + 复盘(Tier2,用上 exec Redis 回放)
...
RunsView 原本只能看「最近一次」实时运行;现做成完整的运行历史复盘:
后端 GET /api/v1/runs?limit=(store.RecentRuns):任务 LEFT JOIN 评测,返回
task_id/status/time + eval level/overall,供历史列表。
前端 RunsView:左侧运行历史列表(状态点 + 相对时间 + 评测分级徽标),点选任一历史运行
→ 经 streamExec/streamTokens 从 Redis 回放该次执行轨迹 + 模型输出(对已完成任务流即回放),
并取 /tasks/:id/eval 显示评测(分级/忠实度/纠偏/评语/flags)。「当前运行」固定置顶沿用实时订阅。
api 补 listRuns + taskEval。
这正是之前 exec 轨迹 Redis 回放的消费场景。live(vite + 预览):提一新任务 → 历史列表出现 →
点选 → 完整回放轨迹(2 节点/2518ms/含推理过程)+ 答案全文 + 评测 ok·1.00,无控制台报错。
tsc+vite 构建通过,gateway 全绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-26 16:34:07 +08:00
Blizzard
1344bf98a0
feat(desktop): 工作台重做为实时仪表盘 + /stats/overview 聚合端点(Tier1 UI 升级)
...
桌面端首屏原是静态宣传页(stat 全硬编码、唯一活数据是网关在线),"太单调"。
重做为活的驾驶舱:
后端 GET /api/v1/stats/overview(聚合,几条轻量查询):
- 任务今日/累计、7 日趋势、近 7 天终态分布(实例级,Task 无 owner)
- 评测均分 + 忠实度均值 + 计数;知识库文档/库数(owner 级)
- token 今日 + 7 日趋势(Redis 日计数)、近期运行 feed、服务健康(复用 health 口径)
- store.StatsOverview + RecentTasks。
前端 Home 重写为仪表盘:4 指标卡(今日任务/Token/评测均分/知识库)带 SVG 火花线、
近期运行 feed(状态点+相对时间,点进运行观测)、7 日任务量柱图、服务健康灯带、能力入口、
快捷动作。5s 轮询刷新。配色沿用现有 ink 暗底 + brand/accent。
live(vite dev + 预览截图):登录后仪表盘渲染真实活数据(今日任务/Token/评测 1.00/近期运行/
服务全绿),无控制台报错。tsc+vite 构建通过,gateway 全绿。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-26 16:13:54 +08:00
Blizzard
d7c6fab933
fix(hitl): 审批弹窗可靠化(状态轮询兜底)+ 审批节点入调色板并改橙色
...
两个实测发现的问题:
1. 审批条偶发不弹、任务卡「运行中」:exec 的 await 事件走实时 core NATS(无回放),
UI 的 EventSource 晚连一拍就漏掉 → 永远不弹审批。改为轮询持久化的任务状态
(GET /tasks/:id,每 1.5s),status==waiting 即弹审批条,不再依赖易抢跑的 exec 事件;
exec 事件仅用于丰富摘要。新增 api.taskStatus + RunState.lifecycle/detail +
App.tsx 轮询 + 终态停轮询;BottomDrawer 审批条触发改以 lifecycle==waiting 为准。
2. Studio 左侧调色板没有「人工审批」节点(只加了 NODE_KINDS,漏了 NODE_ORDER),
且其配色与「输入」同为 amber 难以区分:补进 NODE_ORDER(分支与并行之间),
配色改 orange(橙)与输入的 amber(琥珀金)区分。
验证:桌面端 live 重启确认审批条可靠弹出 + 批准/拒绝两条路径正常;左侧节点列表与
画布配色区分清晰。tsc 干净 + vitest 36 过。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-24 14:51:37 +08:00
Blizzard
16a6c4b1aa
feat(hitl): 人工审批中断(Eino Phase D)—— 审批节点暂停→批准续跑/拒绝中止
...
专用「审批」节点方案,全栈打通。
后端:
- contract:TaskWaiting/TaskRejected 状态 + ApprovalSubject/ApprovalDecision。
- bus:PublishApproval + WaitApproval(订阅决定主题,带超时);消费者 AckWait
30s→15min(阻塞等人审期间消息未 ack,否则重投成重复任务)。
- dispatcher:ApprovalWaiter 接口 + approvalNode——执行到审批节点发 await 事件 +
置 waiting,阻塞等决定。批准→回 running 放行下游;拒绝/超时→errRejected 哨兵→
剪下游→rejected,优雅收尾不计熔断。超时安全默认拒绝。
taskExecTimeout 3→10min(审批5 < 执行10 < AckWait15)。
- 网关:POST /tasks/:id/approve(仅 waiting 态受理,幂等)。
桌面端:
- Studio 新增「人工审批」节点(nodeCatalog,可填标题/说明)。
- run.ts pendingApproval() 从 exec 流派生待审中断 + waiting 节点状态。
- BottomDrawer ApprovalBar:琥珀审批条(摘要 + 批准/拒绝 + 备注,调 api.approveTask)。
- ExecTrace waiting 状态灯。
验证:后端 curl 实测 waiting→批准→running→done;waiting→拒绝→rejected(下游未跑)。
前端 tsc + vitest 36 过(pendingApproval 4 例 + waiting 状态)。全模块 build+vet+test 全绿。
EINO_ADOPTION Phase D 标记 HITL 完成。
未覆盖:compose 路径(EINO_COMPOSE,默认关)的 approval 节点;桌面端审批条未在 GUI 实点。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-24 13:18:47 +08:00
Blizzard
0edfc948ba
feat(memory): P2 读路径打分 + 桌面端记忆面板(看/改/删)
...
读路径(Generative Agents 公式的 Recency+Importance 两项,Relevance 待 P3):
- memory.Get 改为 rankProfiles:Score=0.4·Recency+0.6·Importance,按分降序、截断 top-30。
Recency=0.98^天 指数衰减;未评分行用兜底 importance=5(不被不公平遗忘)。纯函数 + 单测。
- 新增 Store.List(结构化、不截断)+ memory_list 工具。
桌面端记忆面板:
- gateway GET /memory(列表) + DELETE /memory?key=(软删),受保护组。
- api listMemory/deleteMemory;MemoryView 右侧从占位 → 真列表:按分排序展示
key/value/重要度/最近时间,可内联编辑(PUT)与删除(软删);左侧登记后自动刷新。
实测:PUT 两条 → GET 返回带 importance/last_seen 的有序列表(较新者靠前)→ DELETE 一条
(软删)→ 再 GET 已消失。rank/recency/兜底 importance 单测过;前端 tsc+构建通过。
至此记忆:召回(打分) + 历史 + 自动对账(P1) + 用户可管控(面板) 闭环。Relevance(Milvus) 留 P3。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-22 14:48:11 +08:00
Blizzard
9657a07bb5
feat(auth): 鉴权片2 —— 前端登录闭环 + 保护路由 + 去掉 header 兜底
...
把 JWT 鉴权从后端核心闭环到端到端:
后端:
- middleware.RequireAuth:上下文无已验证 uid 则 401;挂在 owner 作用域业务路由组。
- 路由拆 公开/受保护:公开=auth/health + 按 task_id 寻址的 SSE 与报告导出
(EventSource/下载无法带 Bearer);受保护=tasks/memory/kb*/agents/reports/billing。
- userID(c) 去掉 X-User-ID 兜底,仅信任 JWT 注入的 uid。
- 修 CORS:Allow-Headers 增 Authorization(否则浏览器拦截带 Bearer 的请求)。
前端:
- lib/api:token 存 localStorage + Bearer 头(不再发 X-User-ID)+ authRegister/Login/Me
+ 401 清令牌并广播 sdx:logout;submitTask/report/memory/列表加载走 Bearer 与 401 守卫。
- views/Login:登录/注册全屏门。
- App:启动校验令牌 → 无则渲染 Login,有则进主应用;identity.userId=已验证 user.id;
监听 sdx:logout 回登录页。
- TopBar:去掉可编辑身份输入,改显登录用户 + 登出。
实跑验证(docker+gateway+preview):
- RequireAuth:无 token /kb/list、/agents → 401;/health → 200;带 token → 200。
- 前端:无 token 显登录门;注入有效 token 重载 → 进主应用、顶栏显 Dexter、KB 加载本人库、
隔离徽标显雪花 uid。控制台无错、生产构建通过。
- 过程中发现并修复 CORS 缺 Authorization 头的真实 bug。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 16:32:00 +08:00
Blizzard
1dd6b0cce3
feat(report): 生成只出 Markdown 预览,导出时再渲染 Word/PDF/Markdown
...
把"渲染"从生成阶段解耦到导出阶段(导出时再处理):
- 生成阶段:报告正文按 Markdown 流式预览(前端 <Markdown> 已渲染),
dispatcher 不再 eager 渲染 docx,改为经 mcp-go report_store 落盘报告源(title+sections JSON)。
- 导出阶段(按需现渲染):
- GET /reports/:id/export?format=docx → mcp-go report_export 读源渲染 .docx;
- ?format=md → 返回 Markdown 文本;
- PDF → 前端把已渲染的 Markdown 送进打印视图出 PDF(CJK 零字体依赖)。
- 旧 /reports/:id/download 兼容保留(默认 docx)。
改动:
- contract: ReportSourcePath(id) = <id>.json。
- mcp-go: 新增 report_store / report_export 工具(report_render 保留给 Studio render 节点)。
- dispatcher: handleReport 末尾 renderReport → storeReport。
- gateway: DownloadReport → ExportReport(经 NATS 调 report_export)。
- 前端: ReportView 单个「Word」→「导出」组 Word/PDF/Markdown;
desktop.printReportHtml 客户端打印;api.reportExportUrl。
实测(docker 全栈 + mcp-go + gateway + dispatcher + DeepSeek 真跑):
- 真实生成「绿茶的功效」18s 完成,report_store 落源(5章, 6280B) ✓
- export md 返回正确 Markdown(# 标题/## 小节/正文) ✓
- export docx 为合法「Microsoft Word 2007+」(含 document.xml/Content_Types) ✓
- 前端 tsc 干净 + 生产构建通过 ✓
(注:发现并修复一处环境问题——mcp-go 启动时若 Milvus 未起会阻塞在
rag 初始化、永不订阅工具,导致所有 mcp-go 工具"no responders";起全栈后正常。
报告生成在累积大量未完成 DeepSeek 流连接时会偶发卡顿,干净进程下正常。
前端导出按钮的实时点击因 React 受控输入自动化限制未在预览中走通,非代码缺陷。)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-17 14:04:06 +08:00
Blizzard
5d76652bff
refactor(kb): 文件主表 + 文档关联改用雪花ID(弃用按名关联)
...
把 sundynix_doc 明确为"文件主表",补齐文件基础信息字段;
文档间 [[双链]] 改为以 Doc.ID 关联,查询/渲染一律按文件 ID。
store:
- Doc 增 Ext(后缀)/MD5(内容指纹) 字段;ObjectKey 即"存放链接"
- DocLink 由 (FromName,ToName) 改为 (FromID,ToID,ToName)
· FromID/ToID 关联 Doc.ID;ToName 保留用于悬空链接展示与回填
- SaveDoc 返回新建/更新文件的雪花 ID(供建链)
- 新增 GetDocByID(按 ID + owner 取正文,防越权)
- ReplaceDocLinks 以 fromID 重建出链,按 [[名称]] 解析目标 ID
- 新增 ResolveInboundLinks:目标入库后回填指向它的悬空链接
- ListLinks 只返回已解析(to_id 非空)的 ID→ID 边
- migrateDocLinkToID:旧按名双链表无 from_id 列则重建为按 ID 关联
gateway/handler:
- runIngest 计算 ext/md5,SaveDoc 取回 ID 后建链 + 回填悬空
- KbDoc 改为 GET ?id=(按文件 ID 取全文)
- KbVault 返回 id+ext;KbLinks 返回 from/to 为 ID
desktop:
- VaultDoc 增 id/ext;getDoc(docId) 按 ID 取正文
- VaultPanel 选中态/正文/反链/关系图改用 ID,名↔ID 双向映射
渲染;保存笔记后按名定位回其新 ID
验证(gateway+PG+MinIO 实测):vault 带 id+ext;双链 ID→ID 且
A→B 悬空链接在 B 入库后成功回填;按 ID 取大文档(15006字)从
MinIO 完整取回;跨 owner 按 ID 取文档 404(隔离生效)。桌面端
文库 Tab 按 ID 选中/载入/反链渲染正常,无控制台报错。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-15 09:38:02 +08:00
Blizzard
69967ea534
refactor(kb): 文库列表/正文分离 + [[双链]]索引表(可扛大文件)
...
不再一次拉回整库正文、不再前端扫全文 —— 列表只读元数据,正文按需取,链接走索引。
- store: SaveDoc 维护 size+preview(前 500 字);ListVault 仅 Select 元数据(name/size/preview,
不含 content);GetDoc 取单篇全文;DocLink 表 + ReplaceDocLinks(入库/编辑时按 from 重建出链)
+ ListLinks。
- gateway: 入库/笔记保存时正则抽 [[链接]]→ReplaceDocLinks 维护索引;
/kb/vault 改返元数据+预览;新增 /kb/doc(单篇全文) 与 /kb/links(全库双链)。
- 前端:listVault 返元数据,新增 getDoc/listLinks;VaultPanel 列表只展示名/字数,
选中后 getDoc 按需载正文(带加载态),反链/笔记关系图改用服务端 links 索引(不扫全文)。
验证:curl /kb/vault 仅 name/size/preview;/kb/doc 取单篇;/kb/links 返 3 条双链。
Preview:文库点「架构总览」按需载正文(平台分五层)、反向链接(1)=Dispatcher(来自索引)。tsc+vite+gateway build 通过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 16:53:23 +08:00
Blizzard
4bf614a07c
feat(studio): Agent 编排服务端保存 + 我的编排列表(owner 隔离)
...
编排好的 Agent 现在可命名保存到服务端、跨会话可见;左侧「我的编排」列出本人全部。
- store: sundynix_agent 表(owner+name 唯一,Graph=React Flow {nodes,edges} JSON 含布局,
UpdatedAt);ListAgents(最近在前)/SaveAgent(OnConflict 覆盖图+时间)/DeleteAgent。AutoMigrate +Agent。
- gateway: GET/POST/DELETE /api/v1/agents(owner 隔离,身份取自 X-User-ID)。
- 前端:api listAgents/saveAgent/deleteAgent;StudioView 左面板下半区「我的编排(N)」列出本人编排,
点击载入(含布局)、悬停删除;工具栏 编排名+保存(服务端),去掉 localStorage 模板。
验证:curl 保存「合同审查流程」→ wt 列表含之,alice 列表为空(隔离)。Preview:示例图填名「尽调问答
Agent」保存 → 左「我的编排(2)」即时出现两条、可点载入。tsc+vite+gateway build 通过;重建 .app。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 16:23:03 +08:00
Blizzard
337d4d7619
feat(studio): 完善编排 —— 检索接本人知识库 + 真实模型下拉 + 模板/示例
...
把编排从"演示桩"接到真实平台:检索节点查本人 owner 隔离的知识库,节点下拉用真实数据。
- dispatcher:makeToolNode 用 task user_id 给检索类工具的 kb 加 owner 前缀("uid/kb"),
编排里的「检索(RAG)」节点真正命中本人知识库(与隔离对齐)。
- 前端 StudioView:加 identity,载入 /kb/list 与 chat 模型作为「检索.kb」「Agent.model」下拉真值;
Inspector 支持 dynamicOptions(无真值时提示去创建)。
- 编辑体验:示例(一键加载 输入→检索→Agent→输出 可运行图)/ 清空 / 模板名+保存(localStorage,
含布局)/ 载入下拉;ReactFlow deleteKeyCode 支持 Del/Backspace 删节点。
验证:示例图运行 → gateway 发布任务 → dispatcher 编译 → mcp-go 日志 `tool=wiki_search
args=[kb:wt/default ...]`(kb 已按 owner 作用域)→ 命中本人库 → DeepSeek 流式作答;
底部抽屉 完成 ✓ · 工具调用 1。tsc+vite+dispatcher build 通过;重建 .app。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 16:14:54 +08:00
Blizzard
10ac5a5277
feat(kb): 笔记可编辑(按 doc 替换重索引)+ 笔记关系图([[双链]])
...
Obsidian 化继续:笔记能编辑/新建,文档间 [[双链]] 连成可点关系图。
按 doc 重索引(编辑不重复累积):
- Milvus 加 doc 字段(旧 schema 自动重建);insert 带 doc;deleteDoc(kb,doc) 重入库前清旧块。
- Bleve 索引 id 含 doc + deleteDoc 按 kb+doc 清旧块。
- rag.Ingest(kb, doc, text):写入前按 doc 删旧块再写(Neo4j MERGE 仍幂等,附加式)。
- kb_ingest 工具加 doc 参数;gateway runIngest 把 doc 透传,forceDoc 支持编辑保持笔记名稳定。
编辑/新建:
- gateway POST /kb/note {kb,name,content}:落库 + 以 name 为 doc 重入库(替换旧块,搜索/图谱同步)。
- 前端 VaultPanel:阅读/编辑切换(textarea 预填原文,保存调 saveNote)、新建笔记、乐观更新。
笔记关系图:
- GraphView 加 onNode(节点可点);VaultPanel 阅读/关系图切换,关系图 = 文档间 [[双链]] 三元组
力导向(点节点跳转该笔记)。
验证:curl 编辑 笔记B → 检索只返编辑后内容(旧块已清,不重复)。Preview:关系图渲染
笔记B—链接→项目A概述/模块X 且节点可点;编辑器预填原文可改可存。tsc+vite+后端 build 通过;重建 .app。
注:Milvus 加 doc 字段会触发集合重建(旧向量丢,文库原文在 PG 可重灌);Neo4j 图谱按附加式合并,
编辑删除的实体不会自动消失(图谱倾向增长)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 15:22:03 +08:00
Blizzard
55c85302b6
feat(kb): Obsidian 式文库 —— 笔记浏览 + [[双链]] + 反向链接(Tab 化)
...
把知识库做出 Obsidian 感:入库的每份文件/笔记留原文,可浏览、可读、可互链。
- store: sundynix_doc(owner+kb+name 唯一,存原文),SaveDoc(OnConflict 覆盖)/ListVault。
- gateway: runIngest 留存原文(文件用文件名、文本用首行作笔记名);GET /kb/vault?kb= 取文库(owner 隔离)。
- Markdown 组件:解析 [[名称]] / [[名称|别名]] → onLink 可点(Obsidian 双链)。
- KbView 改 Tab(入库 / 文库 / 检索 / 图谱):
- 文库 = 左文档列表 + 右 Markdown 笔记([[双链]]点击跳转)+ 反向链接面板(扫全库 [[本笔记]])。
- 检索、图谱各占整页;图谱放大到 460。
验证(Preview):入两条带 [[双链]] 的笔记 → 文库列出 2 篇 → 打开「项目A概述」渲染出可点的
[[模块X]][[模块Y]] + 反向链接显示「模块X」→ 点 [[模块X]] 跳转到该笔记、其 [[项目A概述]] 亦可点。
curl 证隔离:alice 取 wt 的 vault → 空。tsc+vite+gateway build 通过;重建 .app 重启窗口。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 15:06:31 +08:00
Blizzard
3a175e46f3
feat(kb): 批量文件入库(文件列表) + 项目/案件知识库 + owner 作用域隔离
...
回应三点诉求:一次入一批文件、按文件夹/项目/案件组织、且只有我能查我的库。
隔离(核心):知识库实际分区键 = "owner/name",owner 由网关从 X-User-ID 注入,
客户端只发库名、发不了 owner —— 故任何人都只能查到自己 owner 前缀下的数据。
- gateway: scopedKB(owner/kb) 注入 ingest/search/graph;ingest/search/graph 全部带身份头。
- store: sundynix_kb 注册表(owner+name 唯一 + kind),ListKB/EnsureKB(OnConflict DoNothing)。
项目/案件组织:
- gateway: GET /kb/list(owner 隔离列表)、POST /kb/create(folder/project/case/general);
入库时 EnsureKB 自动登记。
- 前端: KbView 顶部知识库下拉 + 新建(项目/案件/文件夹/通用),检索/图谱/入库都绑定所选库。
批量文件:
- 前端: 选择文件(multiple) + 选择文件夹(webkitdirectory) + 拖拽一批 → 每文件一个 job,
文件列表实时显示各自状态(排队/解析/向量化/写入/抽取/完成/失败)+ 完成/失败计数。
验证:curl 证隔离 —— wt 入 default→可检索;alice 查同名 default→[] 空;alice 列表不含 wt 案件库。
Preview 证 UI —— 知识库下拉含 案件-2024-001(案件)+default(通用)、owner 隔离徽标、批量/文件夹按钮。
tsc+vite+gateway build 通过;重建 .app 重启窗口。
注:身份目前来自 X-User-ID 头(可信前端),生产应换 JWT 鉴权中间件——隔离机制(owner 前缀)已就位。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 14:50:33 +08:00
Blizzard
72e008bfe8
feat(kb): 入库可视化做厚 —— 文件解析/知识抽取过程 + 力导向知识图谱
...
把"进度条"升级成可观测的入库工作台,回应三点诉求:解析过程、知识抽取过程、丰富图谱。
- contract: IngestEvent 加 Preview(解析文本预览)+ Triples[]TripleView(抽出的三元组)。
- 后端回流:rag.Ingest 抽实体阶段把 LLM 抽出的三元组实时回流(边出现边渲染);
gateway 解析完成回流文件类型 + 文本预览片段。
- 前端 GraphView.tsx:零依赖自建力导向布局(斥力+边弹簧+居中静态收敛),实体=节点
按度着色(枢纽紫/关联青/叶子)、关系=带标签边、hover 高亮邻域、节点过多按度裁剪。
- 前端 KbView 重做:入库从"阶段徽标+进度条"→竖向时间线(解析预览/切块块/向量化进度/
抽取知识三元组 chips + 实时小图谱逐步浮现);右侧知识图谱从扁平列表→GraphView,
入库完成自动刷新整库图谱。
验证(Preview):入库一段多事实文本 → 时间线逐阶段点亮、抽出 17 条三元组实时浮现、
右侧力导向图渲染 sundynix-agentix/知识库 为枢纽 + 带标签关系边。tsc+vite+后端 build 通过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 14:22:50 +08:00
Blizzard
cdc5b3a847
feat(observability): 执行可视化 — 节点级实时轨迹(运行·观测)
...
把任务执行做成可观测:Dispatcher 在每个节点/阶段发结构化 ExecEvent,
经独立 NATS 通道回流,前端逐节点点亮(状态/耗时/工具入参产出)。
- shared: contract.ExecEvent + ExecSubject(sundynix.exec.<id>,与 Token 流分流);
bus.PublishExec/CompleteExec/SubscribeExec(core NATS,复用结束头)
- dispatcher: execTracer(自增 Seq 保序 + span 自动计耗时);
Orchestrator 加 ExecSink;通用图(init 召回 / 各 tool 入参→产出 / prompt / model
首token+token数)与报告编排(规划大纲 / 各章并行 start-end / 渲染)全程埋点
- gateway: SubscribeExec + GET /tasks/:id/exec SSE(与 token 流并行)
- desktop: streamExec + deriveNodes(按 node 归并 start/end/error/info);
复用组件 ExecTrace(竖向轨道,按 kind 着色,运行中脉冲灯);
新 RunsView(运行·观测:轨迹+输出双栏);BottomDrawer 轨迹/工具调用 tab 接真实数据;
ReportView 加执行轨迹栏;左导航「运行」置就绪
实测:
- 报告任务 /exec:规划(2680ms,4章) → 4 章并行(seq 交错,各~7-8s 重叠=真并行,
每章带 docs 知识库检索预览+成稿字数) → 渲染(docx 落盘)
- 通用图 /exec:tool:kb_search(678ms,入参→Milvus 产出) → prompt(2消息) →
model(首token 860ms / 4 tokens)
- 浏览器(Preview):报告页执行轨迹逐节点点亮、章节带耗时/字数/检索片段,完成后下载 Word
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-12 14:29:28 +08:00
Blizzard
ba8c6b3c43
feat(report): 报告生成端到端 — 规划→分章并行检索撰写→渲染真实 Word
...
- shared: 新增 intent=report 任务约定 + ReportPath(跨进程共享落盘目录,零配置对齐)
- dispatcher: handleReport 专用编排(DeepSeek 规划大纲 → 各章并行 RAG 检索+撰写
→ 汇聚 → report_render),Pool.Chat 非流式聚合;进度与正文经 Token 流实时回流
- mcp-go: 用标准库 archive/zip + OOXML 拼出真实可打开的 .docx(零额外依赖),
report_render 工具落盘到共享目录;附 docx 有效性测试
- gateway: POST /reports 触发;GET /reports/:id/download 下发 Word
- desktop: 新增「报告」页(主题→实时编排进度→下载 Word),左导航置为就绪
实测:DeepSeek 生成 5 章报告 → 渲染 5KB docx → file 识别为 Microsoft Word 2007+
→ textutil 提取标题/各章正文完整。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-12 14:02:21 +08:00
Blizzard
d623b8590e
feat: GraphRAG — LLM 抽三元组建 Neo4j 图谱 + 混合检索加图谱第三路
...
混合检索从 2 路(向量+全文)升级为 3 路(+图谱)。入库时 LLM 抽实体/关系建
Neo4j 图,检索时图谱路(实体关联三元组)融进 RRF;UI 可视化图谱。
- mcp-go rag: chat.go(OpenAI 兼容非流式 chat 客户端,抽取用) + graph.go(neo4j-go-driver
连接 + LLM 抽三元组 + MERGE 实体/关系 + 图谱召回/全量三元组) + rag.go(Config 结构;
graph+chat 路;Ingest 加 抽实体/写Neo4j 阶段;Search 三路 RRF 融合;SetChat 热更新)
- mcp-go: Neo4j env(默认 neo4j://localhost:7687, neo4j/sundynix);订阅 chat 控制面配置
(复用 DeepSeek 做抽取);新工具 kb_graph(返回三元组)
- gateway: GET /api/v1/kb/graph;frontend KbView 知识图谱面板(实体—关系→实体)
- 验证: 全模块 build✓ + e2e PASS; live——入库'sundynix用Milvus...'→DeepSeek 抽 4 三元组
→Neo4j(8 实体);检索三路融合 向量=4 全文=2 图谱=1;浏览器图谱面板渲染 4 三元组
- 边界: 实体链接用 CONTAINS 朴素匹配(可升级 LLM 查询实体抽取);全文/图谱重启随入库重建
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-11 11:10:22 +08:00
Blizzard
2d5fd2fca5
feat: 实时入库监控 + 向量拆分可视化(异步入库 + 进度 SSE)
...
入库从同步改为异步流水线 + 进度回流(复用 token 流 NATS streaming)。
UI 实时看到 解析→切块→向量化(分批)→写入 各阶段 + 拆分块预览。
- shared: contract.IngestEvent(stage/done/total/chunks/error)
- mcp-go: rag.Ingest 加 onProgress + 分批向量化(10/批)逐批回报;kb_ingest 带 job_id
把进度发到 sundynix.streams.<job_id> + CompleteStream
- gateway: 入库异步返回 job_id,后台 runIngest 发进度;GET /kb/ingest/:id/stream SSE
- frontend: streamIngest(EventSource);KbView 实时进度面板(阶段徽标+进度条+拆分列表)
- 验证: build✓+e2e PASS; 浏览器 12 行→6 阶段点亮+进度条 12/12+拆分 12 块逐条
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-11 10:33:36 +08:00
Blizzard
3550a22557
feat: 文件入库 — docx/xlsx/pdf/csv 经 mcp-py 解析 → RAG
...
入库从纯文本升级为多文件类型:解析(mcp-py 算法层)与切块/embedding 解耦。
上传文件 → Gateway 按类型路由 → mcp-py parse_document 解析为文本 → kb_ingest。
- mcp-py: parsers.py(docx=python-docx / xlsx=openpyxl / pdf=pypdf / csv / txt→文本);
parse_document 工具做真(base64 文件→文本,线程池跑 CPU 密集解析);pyproject 加依赖
- gateway: POST /api/v1/kb/ingest_file(multipart);parseFile 文本类直读、office/pdf→mcp-py
- nats-server.conf: max_payload 8MB(容纳 base64 文件经工具调用;大文件应走对象存储)
- frontend: KbView 加文件上传(accept docx/xlsx/pdf/csv...);api.ingestFile
- 验证: 全模块 build✓ + e2e PASS; live——4 类文件上传→mcp-py 解析→入库→检索命中:
docx(营收报告)/xlsx(销量表行)/pdf(Q2计划)/csv(城市人口) 全部正确
- 边界: 扫描件/版面 OCR(MinerU/PaddleOCR)推迟;大文件 base64 走 NATS 受 max_payload
限,生产应走对象存储(MinIO)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-11 10:10:07 +08:00
Blizzard
8ff68078b7
feat: 知识库管理界面(入库监控 + 检索台)
...
桌面端「知识库」模块从占位变为可用:入库(切块/embedding/Milvus 监控) +
检索调试台(向量召回,带分数与来源)。
- mcp-go: 新工具 kb_search(返回结构化 JSON [{text,score}]);rag.Hit 加 json 标签
- gateway: POST /api/v1/kb/search → kb_search(结构化命中给检索台)
- desktop: lib/api ingestKb/searchKb;新 KbView(左 入库+监控日志 / 右 检索台命中列表
带 Milvus 来源徽标+分数);App 接 kb 视图;LeftNav 知识库 ready
- 验证: gateway/mcp-go build✓ + e2e PASS + 前端 build✓;真实浏览器——入库3条→监控
'已入库3块';语义查询'存储和搜索向量的组件'→Milvus(0.612)>Neo4j>NATS 排序正确,
全走真实百炼 embedding(控制面下发)+Milvus
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-10 17:40:32 +08:00
Blizzard
7d2891d88a
feat: 前端跑通 React Flow 画布→DSL→提交→SSE + 偏好记忆面板 (④)
...
桌面端前端从骨架变为可用:画布编排 Agent → 导出 DSL → 提交 Gateway →
逐 token 流式展示;偏好记忆面板让用户登记画像(→ memory_upsert)。
- lib/api.ts: submitTask(POST) / streamTokens(EventSource SSE token/done) / setMemory(PUT)
- canvas/AgentCanvas: 加节点(提示词)/连线/运行(导出DSL交上层), React Flow 工具栏
- panels/MemoryPanel: 登记偏好(key/value)→PUT /api/v1/memory
- App: 身份(user/session)+记忆面板+SSE 输出面板,串起提交→流式
- postcss.config + vite-env.d.ts(import.meta.env) 补齐构建;删 WikiPanel(stale Qdrant)
- Gateway: 加 CORS 中间件(放开跨源 + X-User-ID/X-Session-ID 头 + OPTIONS)
- Makefile: web 目标(Vite dev); .claude/launch.json(preview 配置), 忽略 settings.local
验证: npm run build(tsc+vite)✓; 真实浏览器跑通——加节点→运行→SSE 流出含
注入画像(称呼:老王)的回答, 第2轮 UI 显示'已有1轮历史'(短期历史经 Eino 图回灌)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-10 14:32:15 +08:00