Commit Graph

29 Commits

Author SHA1 Message Date
Blizzard d14a10479e fix(desktop): 补回报告页剥离时漏搬的 PDF 导出与完成系统通知
759483b 把报告页剥成纯启动器时,Word/Markdown 导出搬去了运行页,但漏了两个:
printReportHtml(前端打印出 PDF,CJK 零字体依赖)和 notify(完成弹系统通知)
外部调用点归零,成了被孤立的活功能。

- 运行页报告正文面板补 PDF 按钮:previewRef 抓已渲染 DOM 送打印视图,
  与剥离前同一条路径。
- 完成通知挪进 attachRun 的 token 流 done 回调并加 label 参数:原先只有
  报告会通知,但「跑几分钟、人早切走了」对编排任务一样成立,且 attachRun
  是所有运行的唯一汇合点,放这儿不会再漂移。恢复的待审任务也带主题。

验证:tsc 干净、68 个 vitest 全过、两函数调用点恢复非零。
⚠️ 未实机点验(需登录态):PDF 按钮实际点击出打印视图、通知实际弹出,
下次起服务后补验。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 16:28:28 +08:00
Blizzard 759483bf92 refactor(desktop,gateway): 用户端去重 —— 一个功能一个入口,一份数据一个查法
用户反馈「UI 太乱」。数出来的:report/kb/memory 各 4 个入口、studio 5 个;
运行历史两套渲染。乱的机制是同一件事写了两遍,改一处另一处必然掉队。

**一份数据一个查法**
- 工作台「最近任务」和运行页「运行历史」是同一批数据,却各查各的:
  前者走 store.RecentTasks(),后者走 RecentRuns()。于是我给运行历史加的
  topic 字段工作台完全没跟上,还在 mono 显示 report_<hex>;而且 RecentTasks
  没有租户过滤,口径也不一致。现在统一走 RecentRuns,RecentTasks 删掉
  (它只有那一个调用点)。前端 recent_runs 也改用 RunSummary 同一个类型。

**一个功能一个入口**
- 工作台删掉「入库知识/生成报告/管理记忆」按钮排 —— 跳的目标和上面四张
  能力卡片完全重合,同一页给两个入口。
- 「最近任务」现在点击直达运行页对应那条(App 加 goto(view, taskId) →
  RunsView focusTaskId),而不是只把页面切过去让用户自己再找一遍。

**报告归 RUN,只做启动器**
- 报告是「执行」不是「构建」,从 BUILD 组移到 RUN。
- 报告页砍掉「执行轨迹」「报告正文」两个面板 —— 和运行页完全重复,而且
  那套是组件本地 state,切页面就没。现在它只有主题输入框。
- 报告改走 App 的全局运行态(新增 onRunReport,与 onRun 同构、复用 attachRun):
  提交 → 跳「运行 · 观测」→ 实时看轨迹/正文/导出。App 里 onRun 早就写着
  「发起即跳运行页,观测统一收敛在此页」——这条方针一直在,只有报告没遵守。

**顺带清死代码**
- 市场(规划中)从导航下架,ViewKey 里的 "market" 和 Boxes 图标一并删。
- PLACEHOLDERS 整块死代码:它列的 home/kb/report/runs 全都早已真实实现,
  market 是唯一还可能用到的、下架后那个 Placeholder 分支永远走不到
  (tsc 报 "Spread types" 就是因为 PLACEHOLDERS[view] 已成 never)。
  连同 views/Placeholder.tsx 一起删。

live 验证(真账号,桌面端实机):报告页输入主题 → 提交 → 自动跳运行页 →
顶部「当前运行 · live」→ 轨迹实时跑 → 报告正文流式出 + 导出按钮在位 →
report_7a0110a10b534f90 落库带 topic「归口测试」,POST /api/v1/reports → 202。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 14:08:16 +08:00
Blizzard 2eb38d3eaf feat(desktop): 首屏工作台商业化重做(定调)
把"工程师内部控制台"改成"给客户用的产品门面"(精致深色专业版方向):
- 问候式头部(下午好,X · 工作区上下文)+ 主 CTA「新建编排」抬到显眼位
- 指标去黑话:评测均分/忠实 → 「回答质量 89%」;Token → 「今日用量」
- 能力卡改结果语言(不再暴露 Eino/向量·全文·图谱/Word 等架构黑话)
- 删「服务·网关/总线/PG/Redis/Milvus/Neo4j」健康灯带(客户不看数据库名)
- 空态改引导(还没运行记录 → 从新建编排开始 CTA)
- 图标去彩虹化,单色 + hover 才亮 brand,右上箭头暗示可点

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:51:41 +08:00
Blizzard 1efe29aed3 refactor(desktop): 清理死 UI / 假功能(P0 完善)
让桌面端只暴露"真的能用"的东西,提升完成度观感、避免误导:
- 删顶栏假"版本选择器"(通用版/法律版/医疗版)——死 defaultValue、无 onChange
- 删「管理」导航项 + 其占位页/命令——内容是 admin 控制台的事(租户/计费/护栏/模型),
  违背 desktop/admin 产品边界,留着只是让用户点了扑空
- 「市场·Packs」标记 ready:false(规划中徽标 + 标题标注),不再伪装成已就绪功能;
  移除其命令面板项(命令面板只列真实可达目的地)
- Agent 节点模型选项去掉假的"占位 Pool/ollama:qwen/vllm:custom",改由已登记模型
  运行时填充(无模型时显示"(无,先创建)"而非可误选的假项);默认 model 置空

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 16:24:56 +08:00
Blizzard 8f766a75a7 feat(space): 桌面端空间成员管理界面 —— 补齐"临时组队协作"前端闭环
此前能建项目空间/切换/启用全员空间,但邀请队友进空间只有后端 API、无界面,
协作故事前端断了一半。本次补上成员管理 UI,让 Space 协作端到端可用。

- api.ts: spaceMembers/addSpaceMember/setSpaceMemberRole/removeSpaceMember + SpaceMemberInfo
- SpaceMembers 弹窗: 列成员(名/邮箱/角色 badge); 空间 admin/owner 可邀请(邮箱+角色)/
  下拉改角色/移除, owner 受保护(无下拉/移除); 非管理员只读提示。复用 Dialog/Button/Select
- 顶栏加"管理成员"入口(UserCog): 活跃空间为 project/tenant 时显示; App 管弹窗开关,
  传 spaceId/spaceName/canManage(空间角色 admin/owner)/selfUserId

实机验证(Wails 桌面 + 全栈后端): demospace(owner)在项目空间邀请 teammate → 成员列表
即时出现(切换器 1人→2人) → 下拉改 teammate 成员→管理员(服务端确认 owner/admin) →
owner 自身受保护无改删入口。tsc + 48 前端测试通过。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:29:28 +08:00
Blizzard 9dab25a5f0 feat(space): 全员空间(tenant-kind) —— 整租户共享的"开关",自动纳入全部成员
补齐 Space 三类型的最后一种:tenant-kind「全员空间」= 用户最初想要的"共享工作区开关"。
与 project 空间的本质区别:自动纳入全租户成员(含之后新加入的),而非手动逐个邀请。

后端:
- EnableTenantSpace(幂等):建 kind=tenant 空间 + 把全部 active 租户成员按租户角色纳入
  (owner→owner…billing_admin→viewer);tenantSpaceID 查询;spaceRoleFromTenant 角色映射
- AddMemberByEmail 加租户成员时 autoJoinTenantSpace:若已启用全员空间则自动补纳新成员
- SpaceCreate handler:kind=tenant 路由到 EnableTenantSpace,且须租户 admin/owner(inline 403)

桌面端:
- 空间切换器加"启用全员空间"入口(Globe 图标):仅租户 admin/owner 且尚未启用时显示,
  带二次确认;启用后该按钮自动隐藏(hasTenantSpace),全员空间进切换器

验证(gateway+docker):member 启用 403 / owner 启用纳入全部现有成员(owner·member·viewer
按租户角色映射) / 新加租户成员自动纳入 / 幂等(再启用返回同一个不重复建) / viewer 在全员空间
入库 403(只读) / owner 建库 200;浏览器实机:启用后全员空间进切换器 + 启用按钮消失

至此 Space 三类型(个人/项目/全员)全部落地。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 13:55:29 +08:00
Blizzard a8c0bb42a7 feat(space): 共享工作区增量3b —— KB 知识库按 Space 共享(存储 re-key)
把 3a 的 Space 作用域推到 KB 层:KB/Doc/DocLink owner→space_id,作用域键
owner/name→space_id/name,同空间成员共享知识库(检索/入库/文库/双链/图谱)。

后端:
- store: KB/Doc/DocLink 加 space_id,唯一索引 (owner,*)→(space_id,*),owner 降级创建人;
  查询全改 space 作用域;SaveDoc/ListVault/GetDocByID/DeleteDocByID/ReplaceDocLinks/
  ResolveInboundLinks/ListLinks 改 space;tenantIDForSpace 补异步入库租户
- MigrateKBSpaces 启动迁移(space_id 回填 + 唯一索引换新,同 Agent 顺序坑规避)
- scopedKB owner/name→space_id/name;IngestJob 契约加 SpaceID;enqueueIngest/runIngest
  穿 space;MinIO 对象键改 space/kb/doc(避免跨空间同名撞键,老键不透明不迁)
- KB 写路由(create/ingest/ingest_file/note/delete)挂 RequireSpaceRole(member):viewer 只读
- 存储层重灌迁移端点 POST /admin/migrate-kb-storage(异步):为存量文档入队新 space
  作用域的重灌作业(复用 JetStream 入库 worker 池),先删旧键;避免同步重嵌撑爆 HTTP 超时

桌面端:
- KbView 收 spaceId(变则重拉库)+spaceReadOnly(viewer 禁建库/入库/文件/笔记);VaultPanel 同

验证(gateway+mcp-go+Milvus/Neo4j/embedding 全栈):
- PG 迁移: 20/21 KB + 50/54 doc 回填 space_id(4 未迁=pre-多租户 owner='wt' 空租户遗留,
  正确跳过),唯一索引 idx_kb_sn/idx_doc_skn 换新、旧索引删除
- KB 共享: member 见共享库 / viewer 建库·入库 403 / 切回个人空间隔离(看不到)
- 全向量链路: RagA 入库(真 dashscope embedding)→ RagB(空间member)检索命中 RagA 内容
- 存储重灌: 端点异步入队 49 作业(worker 池背压处理),重灌后老文档在新 space 键可检索

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 13:00:34 +08:00
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 bf5be08e96 feat(rbac): 租户角色门控落地(极简版) —— viewer/billing_admin 只读不可提交任务
角色此前能分配但不生效(viewer 也能烧租户积分)。本次让角色真正挡动作:

- store.RoleRank 角色层级:owner(4)>admin(3)>member(2)>viewer/billing_admin(1),
  未知/非成员=0;billing_admin 定位为「财务只读」不跑任务
- 可复用中间件 RequireTenantRole(db, minRole),抽 MemberRoleResolver 小接口便于单测
- POST /tasks 挂 ≥member 门控:唯一会烧租户积分的入口(KB 入库不计租户),挡住即够
- 桌面端 StudioView 收 readOnly:viewer 时「运行」禁用+只读提示(UX 兜底,真闸在后端)
- 测试:RoleRank 纯逻辑 + 中间件 7 门控 case(owner/admin/member 放行,
  viewer/billing_admin/非成员 403,未登录 401)

实机验证(gateway+docker):viewer 提交 403 → 升 member 202 → 降回 viewer 403 →
owner 自租户 202(solo 用户不受影响),三态可逆、角色驱动、中间件先于 handler。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 09:49:24 +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 fcefecd10d fix(desktop): 轮询命中终态时同步 phase —— 运行按钮不再永卡「运行中」
attachRun 的状态轮询此前只更新 lifecycle、不动 phase。token 流没收到 done 的场景
(如恢复的在途任务、或任务被外部置终态)→ phase 永卡 streaming → Studio 运行按钮
永远禁用「运行中…」,看似不能跑新编排。

修复:轮询命中终态(done/failed/timeout/rejected)时把 phase 也置 done/error,
释放运行按钮。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 16:48:50 +08:00
Blizzard 49d19d9b59 fix(desktop): 刷新/重开后恢复在途待审任务 —— HITL 审批条可跨会话重现
HITL 持久化中断后审批可跨重启、等数小时,但前端 ApprovalBar 只绑定内存里的
live run:用户一刷新页面/重开 app,run 清空 → 审批条消失 → 那个 waiting 任务
再也点不到批准(历史页只读回放、无审批入口)。这是 durable 模型下的真实 UX 洞。

- App: 抽出 attachRun(状态轮询 + exec 流 + token 流),新发起与恢复共用。
- 登录后探测 waiting 任务并 attachRun 挂回 → 全局审批条重现、可批准/拒绝,
  续跑 token 经重订阅的流回显(网关从 Redis 回放 exec 补回审批摘要)。
- 坑:StrictMode(dev)双调用 effect,原 cancelled 守卫会把首次 async 的恢复误吞
  (restoredRef 已保证只跑一次,App 是根组件不卸载)→ 去掉 cancelled。

真实 UI 验证(preview 驱动 :5173):提交 HITL 任务→waiting→刷新页面→审批条
自动重现→点批准→从 checkpoint 续跑→done,真实出稿 + 评测 1.00。tsc + vitest 绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 14:50:47 +08:00
Blizzard 7cc7f5fd26 refactor(desktop): 观测收敛进「运行」页(tab 切换),删全局底部抽屉
底部抽屉与新版运行页重复,且默认展开常驻占 ~176px、引用/评测还是空壳。按高内聚收敛:

- 运行·观测 详情区改 tab 切换:执行轨迹 / 模型输出 / 工具调用 / 评测(去掉没接的「引用」空标签);
  OutputView(含 chart 渲染) + ToolCalls 从抽屉并入运行页;评测标签接 taskEval 全量展示。
- 删除全局 BottomDrawer,释放底部空间。
- HITL 审批条抽成独立 shell/ApprovalBar,全局常驻于 TopBar 下(审批中断必须随处可见可操作)。
- 发起运行自动跳「运行」页 + 新运行自动切回「当前运行」,实时观测不丢。

tsc+vite 构建通过;wails HMR 热加载生效。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 16:56:52 +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 8c980d2b37 feat(desktop,ci): GitHub Releases 分发 + 桌面端检查更新
让桌面端像开源项目一样用 GitHub Releases 分发,旧版用户自动获知更新:
- CD:.github/workflows/release.yml —— 打 vX.Y.Z 标签触发,macOS(universal)/
  Windows(amd64) 用 wails build 出安装包,softprops/action-gh-release 发布到
  GitHub Release(GOWORK=off,因 desktop 不在工作区)。
- 桌面端检查更新:lib/version.ts(APP_VERSION + 查 GitHub /releases/latest +
  语义版本比较 + openExternal 走 Wails BrowserOpenURL);UpdateBanner 启动时
  检查,有新版顶部横幅「前往下载」。404/限流/离线均静默不打扰。

注:未签名/公证(macOS Gatekeeper / Win SmartScreen 需后续证书);release
workflow 需真实 tag push 才能验证(GitHub 侧运行)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 16:26:02 +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 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 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 84efa0a11c feat(desktop): 命令面板 ⌘K —— 键盘优先工作站入口
Pillar ① 交互骨架升级第一步:全局命令面板。

- components/CommandPalette.tsx:⌘K/Ctrl+K 唤起,搜索 + 多词子串过滤 + 分组(页面/动作)
  + 键盘上下选择 + Enter 执行 + Esc 关闭 + 选中项滚动入视野,纯前端两模式通用。
- App:全局 keydown 监听切换面板;命令清单(8 个页面跳转 + 生成报告/入库知识/新建编排动作)。
- TopBar:加「搜索与命令 ⌘K」触发 pill。

验证(Preview):⌘K/点 pill 唤起 → 输入“报告”过滤出 2 条 → 点「前往·报告生成」自动跳转
报告页并关闭面板。tsc + vite build 通过;重建 .app 重启原生窗口。

注:OS 级全局唤起(⌥Space 后台常驻 + 系统托盘)受 Wails v2 主线程模型限制(与
golang.design/x/hotkey 抢主线程冲突),留作 Wails v3 / cgo 助手的后续,不在本次。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-13 14:32:36 +08:00
Blizzard 72bd43965f feat(desktop): 工业化升级 A —— 设计系统地基(primitives + lucide + 语义令牌)
把"手搓内联 class + Unicode 字符图标"换成统一组件与真实图标,为后续工业化打底。

- 依赖:装 lucide-react(描线图标,按需 tree-shake)
- 令牌:tailwind.config 加语义色 brand/accent/success/warn/danger + 圆角档位;
  强调色字面量(violet/cyan/emerald…)收敛到令牌,便于整体换肤
- primitives(src/ui,零重依赖自建):Button/Input/Textarea/Select/Field/Card/Panel/
  Badge/Dot/Tabs/Skeleton/EmptyState/Dialog/Toast(+useToast)/cn,桶文件统一引入
- 迁移:TopBar/LeftNav/BottomDrawer + Home/Report/Runs/Kb/Placeholder/ExecTrace/
  MemoryPanel/StudioView 全部换 primitives + lucide 图标;导航/能力卡/按钮告别
  ▤◆▣▦ 等 Unicode 字符;错误改用全局 Toast;空状态用 EmptyState
- App 包 ToastProvider

验证:tsc + vite build 通过;浏览器(Preview)走查工作台/报告页——真实图标、统一卡片/
按钮/输入;跑报告端到端正常(执行轨迹 lucide 状态图标点亮、章节耗时/字数/检索片段、
完成弹 Toast + 下载 Word)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 16:39:42 +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 2291f60380 feat(desktop): 深色 AI 控制台视觉改造 + 工作台仪表盘
桌面端从扁平 dev 工具风改为深色高端 AI 控制台:分层表面 + 紫青强调 + 微光 +
首页仪表盘,提升第一印象与吸引力。

- 设计 tokens: tailwind ink 分层调色板 + glow/card 阴影; index.css 深色基底 +
  品牌渐变 + 深色滚动条
- shell: TopBar(品牌渐变+毛玻璃+发光健康灯) / LeftNav(激活态紫色高亮+左光条) /
  BottomDrawer(深色+状态色)
- 新 views/Home 工作台仪表盘: 渐变 hero + 4 状态卡 + 3 能力卡 + 快速开始(默认首页)
- 画布: TypedNode 深色节点卡; StudioView ReactFlow colorMode=dark + 深色工具栏/面板/
  MiniMap; Inspector 深色表单
- KbView/MemoryView/MemoryPanel/Placeholder 全深色化; 进度条改紫青渐变
- 纯前端改造, npm build✓; 浏览器验证: 仪表盘 + 编排画布深色呈现

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11 16:56:04 +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 61c1177eba feat(desktop): MVP 驾驶舱外壳 + 类型化节点 Studio + 运行抽屉
按 desktop-ui-plan.md 落 MVP:五区外壳 + 编排 Studio + 底部抽屉 + 健康灯。

- shell: TopBar(垂直切换/健康灯[Gateway/DB 实时,余规划]/身份会话) +
  LeftNav(BUILD/RUN/MANAGE 分组,未就绪模块灰显) + BottomDrawer(输出/轨迹/工具调用/引用/评测)
- studio: 类型化节点目录(输入/检索RAG/Agent/工具/记忆/分支/并行/汇聚/渲染/输出,
  按类配色) + 自定义 TypedNode(状态徽标) + Inspector(按类型渲染配置表单) +
  校验(孤立节点/必填项) + 运行
- views: MemoryView(复用偏好面板) + Placeholder(规划中模块,露出 IA 与依赖)
- lib: run(运行状态机) + health(轮询 billing) + dsl(导出类型化 DSL + validate)
- 删旧 AgentCanvas(被 StudioView 取代)

验证: npm run build(tsc+vite)✓; 真实浏览器跑通——加类型化节点→校验(标出孤立)→运行
→SSE 注入画像(老王)+历史 流入抽屉, 健康灯 Gateway/DB 实时绿

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 15:00: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
Blizzard c7a02c3905 feat: 初始化 sundynix-agentix 分层式 AI Agent 平台脚手架
5 层 + 1 条 NATS 零拷贝消息总线的 monorepo(Monolith First → Microservices Morph B)。
纵向主干(任务流 + Token 流回流)已真实跑通,横向各层能力为带注释的桩。

已贯通(real code):
- sundynix-shared: 共享契约 + JetStream/core NATS 真实收发(bus) + 内嵌 NATS(devnats) + e2e 测试
- sundynix-gateway: Gin 接入 + DSL 解析组装 + NATS Publish + SSE 流式输出
- sundynix-dispatcher: NATS 消费 + Eino Orchestrator 流式回流 + 熔断器 + LLM Pool 占位流式
- 链路: HTTP POST → DSL → sundynix.tasks.* → Dispatcher → Token 经 sundynix.streams.<id> 回流 → SSE
- 基础设施: docker-compose(nats/postgres/redis/neo4j/milvus) + Makefile(make demo/e2e)

待填(桩):
- Eino 图编排 compose.NewGraph、LLM Pool 接 vLLM/Ollama
- Gateway store 换真实 pgx/redis
- sundynix-mcp-go: Bleve+Milvus+Neo4j 混合检索 / UniOffice / 外部 API
- sundynix-mcp-py: gVisor 沙箱 / MinerU(PaddleOCR) / Docker 解释器
- sundynix-desktop: React Flow 画布 → DSL 导出 → SSE 展示
2026-06-10 11:00:29 +08:00