Blizzard
8b19c572f4
feat(desktop): 办公室换 AI 立绘素材(告别手绘 SVG 小人)
...
用户三次反馈手绘 SVG 不好看 —— 是对的,我不是插画师,程序化矢量画不出
商用品质。技术栈换来换去(3D/Lottie/Spine)都绕不开这点:卡的是美术。
素材:用户用 Nano Banana 生成,链式参考锁风格(先出主管定基准,其余 5 个
+ 桌子 + 房间都拿它当参考图)。版权归用户账号,干净。
为什么最终没上 Spine(用户原本要求照搬 ai-office-react 的实现):
- Spine 运行时不是 MIT。原文要求"每个用户须自购 Spine Editor 授权",
对要卖的产品等于不可行;走另一条要我们买 $69/$330 按座授权。
- 那套 chibi-stickers 素材是 Spine 官方示例(皮肤名里有 spineboy 和
Spine 团队成员名),只授权用于评估学习。参考项目 README 自己写着
"注意素材版权问题!"。
有了立绘就不需要骨骼动画:走位/时序/状态全是现成的 CSS 关键帧,
Chibi 那个口直接换贴图,零 Pixi 零 Spine 零授权。
抠像(scratchpad/art/key.py):只抠「与画面边缘连通」的绿。
绿衬衫角色实测 (41,184,60) vs 绿幕 (9,240,2) —— 两者都"绿压过红蓝",
按颜色阈值必然把衣服抠出洞(实测躯干 81.3% 被误杀);连通域一刀切干净,
对绿植/绿屏同样安全。含软边 + 去绿边,7 张残留绿毛均为 0 像素。
体积:PNG 540KB → WebP 117KB(-78%,平涂+透明是 WebP 强项)。
桌子按「桌面」锚点而非底边:底边贴地时桌宽 200 会让显示器顶到 y=-136
糊住人脸。按桌面对齐后桌子下半截自然超出脚线 —— 这是对的,桌子比人更
靠近镜头本就该更低。铭牌/副标题都压在挡板内(实测 local -27~+23),
掉出去会骑在下边线上被切半截。状态辉光改画在贴图之下、用径向渐变,
硬边色斑糊在显示器背壳上物理讲不通也像贴纸。
手绘版保留为 sprite 缺省时的回落,未删。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-16 10:34:05 +08:00
Blizzard
c2811e79a3
fix(desktop,dispatcher): 从编排执行的多 agent 图看不到「团队」tab
...
现象:编排里并排三个 agent(研究/撰写/审查)跑完,运行页没有团队 tab。
两处卡住,不是一处:
1) isMultiAgent 只认 coordinator: 节点。用户自己在图里并排多个 agent 也是
团队,却被整个漏掉。改成:有协调者,或 ≥2 个 agent: 节点。
2) 就算放宽 1,deriveTeam 仍按 kind==="agent" 挑工位——而两条产生 agent 的
路径 kind 并不一致:协调者派发的专家是 kind=agent,图里的 agent 节点是
kind=model。改成按节点名前缀(agent:/tool:)判,这本来就是后端一直遵守的
约定;顺带天然把 retriever:/map:/render: 这些同为 kind=tool 的节点挡在
工位之外(之前它们会混进来当工位)。
连带修一个更要命的:runAgent 把轨迹标签写死成"模型流式推理"、runReactAgent
写死成"ReAct 智能体(自主调工具)",用户在编排里给节点起的名字(研究 Agent /
撰写 Agent / 审查 Agent)整个丢了。后果不止办公室:执行轨迹里三行同名,根本
分不出谁是谁;团队视图只能退回节点 ID,工位显示成 r/w/rev。
改成一律 labelOf(n, 兜底) 由调用方传入,+2 单测钉住。
另:没有协调者时不再凭空画一个"协调者"小人(白板改挂「任务产出」),也不演
递简报那一程(没人可递),✓ 气泡改为收工即冒。
注意:已存的历史轨迹是落库的,仍是旧标签;只有新跑的任务才有节点名。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-15 17:41:21 +08:00
Blizzard
02608bb6a4
feat(desktop): 办公室加走位编排(进场 / 敲键盘 / 递简报)
...
专家被派发 → 从门口走进来 → 在工位敲键盘 → 干完起身走到协调者桌前
递简报(手里真拿一页) → 回工位。协调者的白板仍是思考/综合流。
为什么做这个:重看参考项目(ai-office-react),它的 Spine 动画只有 idle
和 walking 两个——"好玩"来自角色在房间里走动,不是画质。上一版把人钉死
在工位上只让手动,这才是不好玩的根因。
实现:全 CSS 关键帧,无 rAF / 无定时器 / 无状态机。
- 直播(streaming):工位随事件到达而挂载,延迟一律 0,动画即真实进度。
- 复盘:按事件时间戳算出各自的出场/交付时刻,整段压进 PLAY_MS 当一出戏放;
敲击次数由"工作时长 ÷ 敲击周期"换算,所以快的人敲几下、慢的人敲一路。
- 收工时刻强制不早于"进门 + 敲一下",否则压缩比大时人还没进门就来递简报。
- 角色层与桌子层分开画,人才能走到别人桌前而不被自己那张桌子焊死。
- 补了腿:原来是"永远被桌子挡住的半身像",一走出工位就成了悬空上半身。
- reduced-motion 直接就位不演。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-15 17:41:21 +08:00
Blizzard
225fee5519
feat(desktop): 团队视图加「卡通办公室」皮肤(手绘 SVG 贴纸风)
...
多智能体协调演成办公室:协调者在白板前统筹(白板即思考/综合流),
专家在工位敲键盘,完成打✓、失败挂!、派发走虚线。
风格对齐 ai-office-react(粗描边+平涂+大头身),但用手写 SVG 而非
PixiJS+Spine:零外部素材、无 Spine 运行时授权问题、几 KB 进包。
先试过 three.js 真 3D,低模程序化角色出来是玩具味,已弃并卸干净依赖。
数据与「卡片看板」同源(deriveTeam),换皮不换数据,后端零改动。
动效=状态编码(敲键盘/思考流/辉光),守 prefers-reduced-motion。
顺带修一个真 bug:并发时间轴复盘卡在 running 的旧任务时,未收口工位
会一路量到 Date.now(),跨度爆表(实测 32103562.4s)。抽 teamNow():
直播用此刻、复盘用最后一个事件时间戳;两个皮肤共用,+3 单测。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-15 17:41:21 +08:00
Blizzard
0152e7837a
feat(desktop): 多智能体「团队」视图(运行·观测新增,轨迹仍默认)
...
把多智能体协调画成「协调者居中 + 专家工位环绕」,让最难读的一段——并行派发与综合
——变得一眼可读。执行轨迹保持默认视图;「团队」tab 只在多智能体运行时出现,
普通任务不塞多余 tab。
- lib/run.ts 加 isMultiAgent()(据 coordinator: 节点判定) + deriveTeam():
从现有执行事件流派生协调者/工位模型。与 deriveNodes 的区别是保留 start/end 时间戳,
才能画并发时间轴;并解析专家收尾 detail("简报 X → Y")还原简报与产出。
- components/TeamView.tsx:径向布局(工位按角度均分环绕,>6 个降级为网格)、
协调者实时思考流(接 token 流 + 闪烁光标)、并发时间轴(重叠一眼可见)。
动效只标活跃态(派发链路流动/工位脉冲)——是状态编码不是装饰,带 prefers-reduced-motion 守卫。
专家(kind=agent)与工具(kind=tool)图标区分。
- 零后端改动:数据全部来自现有 exec 事件(coordinator:/agent:/tool:)。
补 9 个单测覆盖派生逻辑(简报解析/失败态/时间窗/lead 不混入工位)。
实机经回放路径验证渲染(径向布局/简报/并发条/tab 条件出现)。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-15 17:41:21 +08:00
Blizzard
11bf7d2756
fix(desktop): wails3 绑定 .js→.ts + 实机验证通过
...
wails3 build 重新生成绑定为 TypeScript(比 standalone generate 的 .js 更规范,
tsconfig allowJs 保留以兼容两种)。整体迁移实机验证:
- wails3 build 全过(前端 build → 绑定生成 → go build -tags production 原生编译 → 打包)
- 原生二进制 bin/sundynix_desktop 启动,窗口开、进程稳、日志无 error/panic
- app 前端加载后自动登录(持久态)并打通后端:gateway 收到 /spaces/current、
/me/spaces、/me/tenants、/stats/overview、/runs、/health 一整串鉴权请求全 200
- runtime 版本号不一致(npm alpha.97 vs CLI alpha2.117)未导致问题
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-14 10:55:21 +08:00
Blizzard
1f487c3163
feat(desktop): 迁移 Wails v2 → v3(架构/目录/绑定重写)[WIP]
...
从 wails/v2 v2.12.0 迁到 v3 v3.0.0-alpha2.117,采用 v3 工程规范:
Go 侧:
- main.go:wails.Run(options.App) → application.New(Options{Services,Assets,Mac})
+ app.Window.NewWithOptions(WebviewWindowOptions) + app.Run();窗口选项照搬
(1440×900/min 1100×700/#0b0d12/Mac TitleBarHiddenInset)
- app.go:App 结构体绑定 → v3 Service(application.NewService);去 startup/ctx 注入;
SaveFileDialog 改 v3 链式 API(application.Get().Dialog.SaveFile().SetFilename().
AddFilter().PromptForSingleSelection());5 个原生方法保留
- go.mod wails/v2→v3、go 1.25
构建:
- wails.json → Taskfile.yml + build/(config.yml 填产品信息 + 各平台配置)
- 删移动端脚手架(ios/android),桌面端只留 darwin/windows/linux
- .gitignore 改为只忽略 build/bin(build/ 构建系统需提交)
前端:
- vite.config 接 @wailsio/runtime/plugins/vite 插件 + WAILS_VITE_PORT
- package.json 加 @wailsio/runtime;wails3 generate bindings → frontend/bindings/
- desktop.ts:window.go.main.App → import { App } from bindings;桌面态检测改
window._wails.environment(原生注入);isMacDesktop 用 System.IsMac()
- version.ts:runtime.BrowserOpenURL → @wailsio/runtime Browser.OpenURL;测试同步更新
- tsconfig 加 allowJs(消费 JSDoc 绑定)
验证进度:Go 编译过 + tsc 干净 + 48 前端测试绿 + 前端 vite build 通过。
**未完成:整体 wails3 build/dev 原生窗口实跑 + 原生能力(另存为/打开/外链)联调**——下次续。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-13 18:00:45 +08:00
Blizzard
8f1aefe13e
refactor(desktop): 去黑话 + 收基建灯(商业化语言铺开)
...
把首屏定的"去黑话+精致克制"语言铺到其余页面:
- 顶栏 5 盏基建灯(Gateway/DB/NATS/Milvus/Neo4j)→ 一枚「系统正常」状态点
(客户不看数据库名;异常时 tooltip 提示项数,顺带缓解窄屏拥挤)
- 知识库:入库阶段标签去实现名(写入向量库/Milvus/Bleve/Neo4j → 建立语义索引/
全文索引/构建知识关系);检索台「混合召回+rerank」→「在库中搜索」,命中分数
0.83→83%,"RAG 未配置"→"该库可能为空";图谱去「Neo4j·力导向」
- 运行:流式中→生成中;"token 在此流式呈现"→"回复逐字呈现";忠实→可信度/引用
- 编排节点「检索(RAG)」→「知识检索」,描述去"混合检索"
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-07-13 16:57:24 +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
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
158fe094ab
fix(hitl): 审批复盘轨迹补全 —— 中断不关 exec 流,resume 事件续录
...
现象:已完成的审批任务,复盘轨迹停在「已中断等待审批」、审批节点永远转圈,看着
像卡住(实际任务已 done、有输出)。
根因:任务中断时 Handle 的 defer tr.done() 给 exec 流发了 CompleteExec → 网关 exec
录制器关闭。resume 是另一次独立调用,其 exec 事件(审批通过/拒绝、续跑节点)发到
同一主题时录制器已关 → 没录进去。(token 流中断时特意没关,所以输出录到了;exec
流却被关了,不对称。)
- exec.go: execTracer 加 suspended 标志,done() 挂起时不关流。
- orchestrator.go: 中断分支置 tr.suspended=true(与 token 流一致)。
- ExecTrace.tsx: 前端兜底——运行已完成(phase done)时把悬挂的 waiting/running 节点
收敛为 done,修旧任务(已 done、轨迹缺 resume 事件)的转圈假象。
live 验证:审批任务批准后复盘轨迹完整呈现 approval await→end「批准:放行」→
agent start→推理→end,审批节点不再转圈。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 16:57:11 +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
e8dc2e02c3
fix(desktop): 审批条提交后不再永卡「提交中」+ 按 taskId 重挂载
...
复现:登录恢复待审任务时若捞到一个无法续跑的任务(如早期 KV 冒号 bug 留下的无
resume 记录的孤儿),点批准 → 决定发出但消费者找不到记录 → 任务永远 waiting →
审批条 busy 状态成功后从不复位 → 永卡「提交中…」spinner,看似整个应用卡死。
- decide 成功后置 submitted 并在 finally 复位 busy(此前只在 catch 复位)。
- submitted 时显示「决定已发出,等待续跑…(若长时间无响应,该任务可能已失效)」
而非停在 spinner —— 诚实反映状态,不误导成 hang。
- Bar 加 key={taskId}:换审批任务时重挂载,避免上一个的 submitted 残留。
(孤儿任务本身已在 PG 标记 failed 清理;冒号 bug 早已修复,不再产生新孤儿。)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-29 16:40:07 +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
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
594be6a317
fix(desktop): 模型输出渲染图表 + Markdown 支持表格/代码围栏;ReAct 步数提至可配 12
...
针对运行页输出的两个渲染缺口 + 一个节点报错:
- 图表:模型输出走 chart 块分段渲染(文本 Markdown,```chart 块用 ChartView 出图),
不再把图表 spec 显示成原始代码。
- 表格:轻量 Markdown 组件原本不支持 GFM 表格(| … | 显示成原始竖线)与 ``` 围栏代码,
现补上:表格解析成 <table>、围栏渲染成 <pre>。
- ReAct 步数:reactMaxStep 由常量 8 改 env 可配(REACT_MAX_STEP,默认 12)。研究型任务
(搜索→抓取→推理多轮)8 步偏紧易触顶报 exceeds max steps;提到 12 覆盖多数。
tsc+vite 通过,dispatcher build/vet 绿;wails 重启加载。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-26 17:33:58 +08:00
Blizzard
101d3f9bc9
refactor(desktop): 运行页改三栏 —— 模型输出固定右侧(Markdown),中间 tab 只留轨迹/工具/评测
...
按反馈调整运行·观测布局:模型输出不进 tab,恢复成独立右侧面板用 Markdown 渲染(与旧版一致);
中间 tab 切换 执行轨迹/工具调用/评测,标签行右上保留运行状态指示(完成✓/流式中…/出错)。
三栏:运行历史 | tab详情+状态 | 模型输出。
tsc+vite 通过;预览自查布局正确(左历史/中tab+状态/右Markdown输出),wails 重启加载新版。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-26 17:12:48 +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
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
82b1d3e802
Revert "feat(desktop): 底部抽屉可拖拽调高/最大化 + 输出渲染 Markdown"
...
This reverts commit 429b04d64a .
2026-06-25 14:12:25 +08:00
Blizzard
429b04d64a
feat(desktop): 底部抽屉可拖拽调高/最大化 + 输出渲染 Markdown
...
解决两个真实体验问题(编排页底部输出区):
- 抽屉太矮(176px)长输出放不下:改为可拖拽顶边调高(140px~85vh) + 一键最大化(82vh)/还原。
- 输出原样显示 markdown 未渲染:接入现有轻量 Markdown 组件(标题/加粗/斜/码/列表/引用/分隔/双链,
随主题),替换 <pre>;含 ```chart 块时文本段渲 Markdown、图表段渲 SVG,保持顺序。
复用现成组件,未引重依赖(react-markdown 试装后回退),bundle 不涨。
tsc + 生产构建 + vitest 48 全过;桌面端已 HMR。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-25 12:57:51 +08:00
Blizzard
760ca06667
feat(desktop/studio): Tier1 编排画布主题化 + 节点精修(产品灵魂打磨)
...
react-flow 此前 colorMode 写死 dark、背景/连线/控件全用库默认,换肤下不协调。改为:
- colorMode 绑定当前主题 → 控件/连线/手柄/选区自动随亮暗切换。
- Background 点阵色、MiniMap 遮罩随主题;隐藏库水印(proOptions.hideAttribution,更干净)。
- index.css 精修 react-flow:控件(细边/圆角/themed hover)、连线(中性描边+选中紫)、迷你图边框,对齐设计系统。
- TypedNode:卡面落到表面色(ink-850)、选中环用 brand 令牌(替硬编码紫)、加 hover 描边、手柄themed。
- 工具栏/调色板/检查器已用新 Button + 令牌类,自动一致。
tsc + 生产构建通过;桌面端已 HMR。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-25 12:47:48 +08:00
Blizzard
94f04bd204
refactor(desktop/ui): 组件库对齐 shadcn 画廊基调
...
按已定稿的组件画廊精修 ui/ 基础组件(均走主题令牌,亮/暗自适应):
- Button:主按钮去掉霓虹 shadow-glow(玩具感残留)→ 扁平 + active 微缩;
次按钮落到 ink-850 表面。
- Input/Textarea/Select:底色对齐表面(ink-900) + 焦点环改 ring-2 ring-brand/25(更柔的聚焦)。
- 新增 Table/Tr/Td:细分隔线 + 弱化表头 + 行 hover,运维/数据场景标准呈现。
- EmptyState/Skeleton/Badge/Tabs/Card 已主题化,沿用。
页面经 ui/ 桶引入,组件升级即全页生效。tsc + 生产构建 + vitest 48 全过。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-25 11:23:59 +08:00
Blizzard
ca7ce4c26f
feat(desktop): 亮/暗主题切换 —— 默认亮色,一处令牌驱动全 app 换肤
...
把高频硬编码色(ink 表面 / line 边框 / slate 文字)重定义为 CSS 变量(RGB 三元组,
保留 /透明度 修饰符),:root(亮) 与 .dark(暗) 两套值切换——改 tailwind.config + index.css
两处即让全 app 换肤,无需逐文件迁移。
- 亮色走 shadcn 中性灰(zinc:zinc-50 底/白卡/zinc-200 边/zinc-900 字);
暗色精炼为中性 zinc 暗(替代原偏蓝 ink),顺带提质感。
- lib/theme.ts:useTheme + applyInitialTheme(main 启动前设类,避免首屏闪烁)+ localStorage 持久化,默认亮色。
- TopBar 加 Sun/Moon 切换钮;滚动条/输入控件 color-scheme 随主题。
- 修亮色下会失效的 bg-white/5 → bg-ink-800(Tabs/Badge/ExecTrace 的中性微底);
模态遮罩 bg-black/55 两模式皆宜,保留。
验证:tsc + vitest 48 过 + 生产构建通过(var 色全解析)。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-25 10:39:36 +08:00
Blizzard
592b2a3d97
feat(tools): chart 图表工具 —— 工具产出 JSON spec,前端 SVG 渲染(职责分离)
...
按「工具只产数据、渲染交前端」设计:
- 后端 chart 工具(mcp-go):校验并返回规范化图表 JSON(type=bar/line/pie + labels + series,
校验类型/长度一致/pie 取首系列)。工具说明指示 agent 用 ```chart 围栏原样包裹返回的 JSON。
- 前端:lib/chartspec.ts 从输出抽取 ```chart 块(解析失败回退为文本不丢内容);
components/ChartView.tsx 自绘 SVG 柱/线/饼图(无第三方图表依赖);
BottomDrawer 输出区含图表块时分段渲染(文本 + SVG),否则纯文本。
测试:前端 chartspec 单测 12 例(isChartSpec 校验、分段抽取、非法块回退、多块、hasChart);
tsc 干净,vitest 48 过。live 自主 agent:chart 工具产出 {"type":"bar",...},
agent 正确用 ```chart 围栏嵌入答复,前端据此渲染。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-24 17:24:41 +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
f37d046f2c
test(desktop): 前端单元 + 关键组件测试(Vitest + RTL,31 例)
...
测试基建:vite.config.ts 加 test 配置(jsdom + setup),package.json 加
test/test:watch 脚本,src/test/setup.ts 引 jest-dom;tsconfig 把测试文件 exclude,
使 CI 现有 tsc --noEmit 不检查测试文件(仍绿),测试由 Vitest 自跑(先不接 CI)。
覆盖(31 例 / 4 文件):
- dsl:exportDsl 节点/边映射 + config 兜底 + branch 真假边 sourceHandle 条件;
validate 空画布/孤立节点/必填项缺失。
- version:isNewer 版本比较矩阵;checkUpdate 有更新/同版/旧版/404限流/离线异常;
openExternal Wails / 浏览器双路径。
- run:deriveNodes start→running、end→done+耗时、error、error 不被 start 覆盖、
info 累计 notes、首现顺序、label 更新。
- UpdateBanner(RTL):无更新不渲染、有更新显版本+点下载调 openExternal、点忽略消失。
小改:version.ts 导出 isNewer(原私有)以便直接测版本判定矩阵。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-24 11:53:54 +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
95f4752d9e
feat(desktop): Agent 节点加「自主工具 (ReAct)」开关
...
前端补上 Phase B 的 UI 接缝:agent 节点 nodeCatalog 增 autonomous checkbox
(默认 false)。勾选 → exportDsl 带 config.autonomous=true → dispatcher
走 ReAct 自主调工具。此前能力在后端但画布点不到。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com >
2026-06-23 14:29:37 +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
1bd187874d
feat(orchestration): Phase2 —— map 真并行 fan-out + branch 真/假边标签精确选路
...
Phase1 让引擎按图执行后,本轮补上两块:
1) map 并行 fan-out(dispatcher)
- map 节点:planItems 把主题拆成 3–6 子项 → 复用 report 的 writeSections
有界并发(4)逐项撰写 → 结构化 sections 存黑板 + 拼进 answer + 流式呈现。
- 检索节点记下 owner 作用域库名(b.kb),供 map 各项并行检索复用。
- render 节点优先用 map 产出的多章 sections 渲染,否则整段成稿当单章。
2) branch 真/假边标签(前端 + DSL + dispatcher)
- TypedNode:分支节点渲染两个出口手柄 真(绿)/假(红),连线各带 sourceHandle。
- exportDsl / TaskDsl:边导出携带 sourceHandle。
- dispatcher dsl.Edge 增 SourceHandle;branchNode 优先按 true/false 标签精确
选路,无标签的旧图退回"出边顺序"约定,向后兼容。
实测(gateway+dispatcher+DeepSeek 真跑):
- map:input→map→render,DeepSeek 拆出 5 章并行撰写(347–512字),trace 见
section:0..4 并发 + 有界并发(section3 等槽);render 因 mcp-go 不在优雅降级 ✓
- branch 标签:把 true 边故意列第二位,条件真仍走 true 标签的分支A、假走分支B,
证明按标签而非边序选路 ✓
- 桌面端:分支节点正确渲染 真/假 两手柄,无 console 报错 ✓
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-15 14:01:51 +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
e1cac0eb69
fix(studio): 载入编排防御兜底,避免损坏图导致黑屏
...
点击「我的编排」里某条若其 graph 缺 position/type/data(旧数据/外部写入),
React Flow 缺 position 会直接崩成黑屏。loadGraph 改为对每个节点兜底:
补 type=typed、缺失或非法 position 给网格默认坐标、data.kind 不识别则回退 output、
补 label/config/status;边过滤掉两端不存在或缺 source/target 的,自动补 id。
验证(Preview):故意存一条节点全缺字段的「损坏测试」→ 载入渲染为 2 节点·1 连线、
渲染器正常(不再黑屏);正常「尽调问答 Agent」4 节点·3 连线照常载入。tsc+vite 通过;重建 .app。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 16:28:21 +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
a222ca5f9e
feat(kb): 知识图谱换 react-force-graph-2d(活物理 + 拖拽 + 缩放)
...
把自建静态 SVG 力导向换成 react-force-graph-2d(canvas + d3-force)——真实物理、
可拖拽节点、滚轮缩放、悬停高亮邻域。实体图谱与笔记关系图同一组件,全部升级。
- GraphView 重写:ForceGraph2D,nodeCanvasObject 自绘节点(按度着色/缩放)+标签,
linkCanvasObject 放大后显示关系文字,onNodeHover 高亮邻域、onNodeClick→onNode(笔记图跳转)。
- 调力:charge=-180 / link distance=52 拉开布局;onEngineStop zoomToFit 自动取景。
- 保持原 props(triples/height/onNode),三处调用零改动。
验证(Preview):笔记关系图渲染 笔记B/项目A概述/模块X 大节点 + 链接边、自动取景、可拖拽缩放。
(实体图谱在 default 库因累积了几十个测试实体显得密,新建干净库则清爽。)tsc+vite 通过;重建 .app。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com >
2026-06-13 15:55:34 +08:00