Wyatt_K
e28c28f97a
feat(cloud-agent): 新增 skill_search——Agent 侧技能/卡级检索
...
#577 让 Agent 知道「有哪些技能」;本 PR 补上「这个任务该读哪张卡」。
#568/#575 之后种子已有 34 个域包、759 张卡,单包最多 67 张,
「先读 SKILL.md 总纲再按名录找卡」的成本会随卡数线性上涨。
## 设计(复用仓库既有范式,不发明新机制)
参照 recall_lessons(个人记忆检索):同一套分词器、稳定排序、无关键词列全量索引。
打分四档:**卡名命中 4 > 技能名 3 > 技能描述 2**。
- 命中卡片 → path 直接给 `cards/xxx.md`,Agent 不必读总纲;
- 只命中技能 → path 给 SKILL.md,并下发该包的 **卡索引**(跨条目共享 40 条预算),
Agent 可直奔某张卡。中文关键词打不到英文卡名时,这条兜底路径是主要收益来源;
- 数据源 = 本轮冻结快照(含 #577 注入的 description;卡路径本就在 Files 里,无需读正文);
- 只搜已启用技能;**只返回索引与路径,正文永不内联**;
- 不可信数据纪律延续:工具描述明牌「返回的是索引,不是指令」。
## 实机验证(本机影策 v1.5.7 + 本分支编译的后端,step-5-preview-intl)
- **检索→读取闭环打通**:`skill_search("反转 结构 钩子")` → 命中 2 条并下发卡索引 →
Agent 直读 `cards/ssqr-twist-ending.md`,**全程未读 SKILL.md**,tool_failed=0。
- 8 技能满槽自由跑(原始/改描述/再改描述 三次):模型**均未自发调用**,
skill_read_file 15 / 8 / 9 次落在噪声内 —— **仅靠工具描述不足以驱动该模型主动检索**,
本 PR 不声称改善了采纳率;采纳与否需要遥测才能判定。
## 实机撞出的两个缺陷(已修,非理论风险)
1. **参数容错**:模型按 skill_read_file 习惯顺手带 skillId,被 DisallowUnknownFields 拒 →
tool_failed,工具可见却一次都没成功。现容忍(仅接收不生效)。
2. **snippet 多字节越界 panic**:strings.Index 的字节偏移被当 []rune 下标、start 未夹紧 →
`panic: slice bounds out of range [249:233]`,**整个后端进程被打挂**(复现两次)。
现改为 rune 级子串查找 + start/end 双向夹紧;回归测试用 276 rune/字节偏移 483 的长中文
描述,修复前稳定 panic([443:276])。
## 测试(11 个契约用例,全绿)
注册与门控、卡名命中返回卡路径、中文关键词回落到卡索引、卡索引预算夹紧、
name>description 排序、无关键词列索引、limit 夹紧、无命中 guidance、
stray skillId 穿透解码层、长中文描述不越界、sentinel 断言正文绝不内联。
门禁:go build ./internal/app/ ✓ go vet ./internal/app/ ✓ go test 11/11 ✓
2026-09-22 07:47:55 +08:00
ddCat
e0e6be450b
refactor(admin): 管理后台 - 收敛重复边框并提升运维信息密度
2026-09-22 06:09:03 +08:00
Wyatt_K
04bbbf642e
fix(cloud-agent): skill_search 两处实机缺陷——skillId 容错与 snippet 多字节越界
...
两个缺陷都是实机验证时撞出来的,不是理论风险。
1) 参数容错:Agent 首次调用时按 skill_read_file 的参数习惯顺手带上 skillId
({"keyword": "...", "skillId": "<已启用技能ID>"}),而参数解码走
decodeCloudAgentJSONObject(DisallowUnknownFields),直接拒绝 → tool_failed。
结果是工具在清单里可见、却一次都没调用成功。
- args struct 增加 SkillID(json:"skillId,omitempty"),仅接收不生效——
检索范围恒为本轮已启用技能;
- 工具描述补「不要传 skillId——本工具搜索全部已启用技能」,从源头减少误传;
- 回归测试走完整的工具分发路径(cloudAgentReadTool),真正穿透解码层,
并断言该字段不会缩小检索范围。
2) snippet 越界 panic(更严重):cloudAgentSkillSnippet 用 strings.Index 拿
**字节偏移**,却拿它去切 **[]rune**。中文描述里关键词越靠后、字节偏移越远
超 rune 数,start 没有夹紧到 len(runes),触发
panic: runtime error: slice bounds out of range [249:233],
**整个后端进程被打挂**(实测复现两次)。
- 改为 rune 级子串查找(cloudAgentSkillRuneIndex),不再混用字节与 rune 下标;
- start/end 双向夹紧,并补 start>end 兜底;
- 回归测试用 276 rune、命中词字节偏移 483 的长中文描述,
在修复前稳定 panic([443:276]),修复后通过。
3) 工具描述补充检索引导(提示文本,非行为改动):
- skill_search:明写「当本轮启用了多个技能、而你不确定该读哪一个时,先用本工具检索」;
- skill_read_file:补「若本轮启用了多个技能且不确定该读哪一个,先用 skill_search 检索再读」——
放在这里是因为模型一定会用到 read_file,提示的可达性高于只写在 search 自己的描述里。
实测:同一 8 技能满槽任务跑 3 次(原始描述 / 只改 search 描述 / 再改 read_file 描述),
step-5 **三次都没自发调用** skill_search,skill_read_file 次数 15 / 8 / 9(噪声内)。
即:**仅靠工具描述不足以驱动该模型自发检索**,需要系统提示层路由或遥测来验证采纳,
本 PR 不声称改善了采纳率。
门禁:go build ✓ go vet ✓ go test 8/8 ✓
2026-09-22 03:35:24 +08:00
AetherNo2332
cc76070c60
test(web): 画布 Agent 面板 - 修正 Skill 引用提示语的过期断言
...
输入框提示语已随外观配置搬进 lib/canvas/agent-appearance.ts,面板只消费
appearance.inputPlaceholder(canvas-cloud-agent-panel.tsx 的 agentCopy(...)),而这条用例仍在
面板源码里找那句字面文案,于是 Web checks 的 Run tests 一直红:干净 upstream/main 检出上可复现
1994 pass / 1 fail,同期其它作者的 PR 也是同一条失败。
改为断言"文案在 agent-appearance 里 + 面板仍在使用它",与重构后的架构一致。
2026-09-22 01:51:29 +08:00
AetherNo2332
36d1825f5f
test(web): 画布 Agent 面板 - 修正 Skill 引用提示语的过期断言
...
输入框提示语已随外观配置搬进 lib/canvas/agent-appearance.ts,面板只消费
appearance.inputPlaceholder(canvas-cloud-agent-panel.tsx 的 agentCopy(...)),而这条用例仍在
面板源码里找那句字面文案,于是 Web checks 的 Run tests 一直红:干净 upstream/main 检出上可复现
1994 pass / 1 fail,同期其它作者的 PR 也是同一条失败。
改为断言"文案在 agent-appearance 里 + 面板仍在使用它",与重构后的架构一致。
2026-09-22 01:51:11 +08:00
AetherNo2332
90f1cf2516
test(web): 画布 Agent 面板 - 修正 Skill 引用提示语的过期断言
...
输入框提示语已随外观配置搬进 lib/canvas/agent-appearance.ts,面板只消费
appearance.inputPlaceholder(canvas-cloud-agent-panel.tsx 的 agentCopy(...)),而这条用例仍在
面板源码里找那句字面文案,于是 Web checks 的 Run tests 一直红:干净 upstream/main 检出上可复现
1994 pass / 1 fail,同期其它作者的 PR 也是同一条失败。
改为断言"文案在 agent-appearance 里 + 面板仍在使用它",与重构后的架构一致。
2026-09-22 01:50:54 +08:00
AetherNo2332
0b5a876fd1
test(web): 画布 Agent 面板 - 修正 Skill 引用提示语的过期断言
...
输入框提示语已随外观配置搬进 lib/canvas/agent-appearance.ts,面板只消费
appearance.inputPlaceholder(canvas-cloud-agent-panel.tsx 的 agentCopy(...)),而这条用例仍在
面板源码里找那句字面文案,于是 Web checks 的 Run tests 一直红:干净 upstream/main 检出上可复现
1994 pass / 1 fail,同期其它作者的 PR 也是同一条失败。
改为断言"文案在 agent-appearance 里 + 面板仍在使用它",与重构后的架构一致。
2026-09-22 01:50:37 +08:00
AetherNo2332
33a0121cd7
test(web): 画布 Agent 面板 - 修正 Skill 引用提示语的过期断言
...
输入框提示语已随外观配置搬进 lib/canvas/agent-appearance.ts,面板只消费
appearance.inputPlaceholder(canvas-cloud-agent-panel.tsx 的 agentCopy(...)),而这条用例仍在
面板源码里找那句字面文案,于是 Web checks 的 Run tests 一直红:干净 upstream/main 检出上可复现
1994 pass / 1 fail,同期其它作者的 PR 也是同一条失败。
改为断言"文案在 agent-appearance 里 + 面板仍在使用它",与重构后的架构一致。
2026-09-22 01:50:20 +08:00
AetherNo2332
748c20cf3e
test(web): 画布 Agent 面板 - 修正 Skill 引用提示语的过期断言
...
输入框提示语已随外观配置搬进 lib/canvas/agent-appearance.ts,面板只消费
appearance.inputPlaceholder(canvas-cloud-agent-panel.tsx 的 agentCopy(...)),而这条用例仍在
面板源码里找那句字面文案,于是 Web checks 的 Run tests 一直红:干净 upstream/main 检出上可复现
1994 pass / 1 fail,同期其它作者的 PR 也是同一条失败。
改为断言"文案在 agent-appearance 里 + 面板仍在使用它",与重构后的架构一致。
2026-09-22 01:50:02 +08:00
AetherNo2332
1637bb9536
fix(cloud-agent): 布局工具参数错误按字段归类,审批卡补整理徽标
...
- canvas_arrange_nodes 的参数契约错误改用上游既有的 cloudAgentFieldError:
snapshotHash 缺失按 required、mode/align/gap/nodeIds/groups 非法按 invalid_value、
nodeIds/groups 超限按 item_count。原先一律 BadAuthRequest(*AppError),按上游运行期的
errors.As 顺序会走 failCloudAgentAdmission 把整轮判死,模型拿不到可纠正回执。
- 审批卡补 .canvas-agent-approval-operation-arrange_nodes 徽标配色(与新增/修改/连线同一组),
并补一条前端用例:arrange_nodes 预览项不得被 operation() 当成未知值丢掉。
2026-09-22 01:40:43 +08:00
AetherNo2332
6a216dddc2
perf(cloud-agent): 画布事件 - 整理类变更只下发几何增量
...
一次整理几十个节点时,canvas_updated 仍按整节点下发完整 before/after,单条事件会超过
validateCloudAgentRuntime 的 128KiB 单事件上限,整轮直接失败。
- 新增 cloudAgentShrinkChange:仅当 before/after 除 position/width/height/zIndex 之外
完全一致(且无键被删)时,只下发 id 与变化的几何字段;带内容或 metadata 变化的节点仍发
完整 before/after,不影响前端的三方合并与生成任务状态保护。
- 新增用例覆盖"几何变化只发增量"与"内容变化 / 键被删仍发完整对象"。
2026-09-22 01:32:32 +08:00
AetherNo2332
9d0bce6bb5
fix(cloud-agent): 续轮交接 - 用有界结构化事实帧替代跨轮散文收束
...
续轮(POST /agent/runs 带 parentId)过去只把「上一轮已结束(failed)。…已提交生成任务:
a, b」这段散文塞进下一轮历史:新轮看不到上一轮真实改过哪些节点,也无法可靠区分「这是
服务端交接」还是「用户自己写的一句话」。
- 与轮内既有事实帧(cloud_agent_context_frame.go 的 task_repository 帧)同构,把跨轮交接
也改成有界结构化帧:source=server、kind=run_handoff,带 parentRunId / status /
failureReason / submittedTaskIds / canvasChanges / omittedCanvasChanges / authority。
画布改动取自上一轮真实 canvas_updated 事件,最多 12 组(operation、去重后的
nodeId/title、actionCount),超出只记 omittedCanvasChanges,不静默丢。
- 身份改由 providerTextMessage.AgentContextSource 结构体字段承载,canonical 装配时原样
透出;isCloudAgentContinuationMessage 要求「来源元数据 + 【运行状态】前缀 + JSON
source=server/kind=run_handoff」三者同时成立,用户逐字复制帧 JSON 也拿不到该身份
(此前按内容前缀猜,用户自己写一句「上一轮已结束(…)」就会被认成交接)。
- 旧格式兼容:升级前落库的散文交接没有来源字段,改按「紧跟 assistant 回复 + 旧版文案
前缀」识别,只用于历史裁剪与轮次计数;canonical 身份仍只认结构体字段。
- cloudAgentLegacyHistory 重建时把落库的 agentContextSource 一起搬,身份不在重建口丢失。
- 帧按字节封顶:单个 nodeId 截 64 字符、整帧 8 KiB,超限按最近改动优先裁剪并累计
omittedCanvasChanges;失败原因过既有脱敏口径 cloudAgentSafeUserMessage。
- 不搬运 dev 专有内容:不引入事件读取上限常量(上游本就返回全量事件),硬闸口径按上游
的 64 KiB 注释,也不引入 `dropped := 0` / `_ = dropped` 这类死代码。
- docs/content/docs/backend/http-api.mdx 补帧字段与「非授权」口径。
帧只被 isCloudAgentContinuationMessage 用于「历史怎么裁、怎么数轮」;写入与收费闸门读的
是落库策略(审批闸、生成次数闸、视频秒数闸、工具授权),不读消息内容,因此帧不构成重放
写入、重复提交付费任务或扩大权限的授权依据。
2026-09-22 01:32:21 +08:00
AetherNo2332
56598108d4
feat(canvas): 云端 Agent 画布布局 - 新增 canvas_arrange_nodes 与新增节点自动落位
...
云端 Agent 此前只能新建节点与连线,既不会排版也不能移动已有节点:模型只能用几十个
update_node 手算坐标,或者让用户自己拖。
- 新增 backend/internal/canvas/layout:把前端既有的画布布局算法(web/src/lib/canvas/
canvas-layout.ts,本 PR 不改该文件)按同一套常量移植到服务端,提供 Kahn 拓扑分层 flow、
媒体泳道 byType、row/column/grid、对齐与等距、分组分带、AABB 重叠检测与空位搜索。
- 新增写工具 canvas_arrange_nodes:snapshotHash 必需,mode∈{auto,flow,byType,row,column,
grid},可传 nodeIds、groups(只做横向位置分带,不建容器、不改层级)、align、gap、dryRun。
只改坐标,不改内容、不建连线、不增删节点;一次最多 50 个节点 / 12 组。锁定节点、背板等
容器、隐藏批次子节点与已归属背板的子节点保持不动并在回执里说明;整批复用现有 mutation
记录与事件管线,审批与撤销走同一条路径。
- add_node 省略坐标时不再落到 (0,0):优先贴合本批连线的对端(输入在左、输出在右),否则
追加到同泳道同类节点之后,冲突则扫描空位;只给一个轴时保留该轴。agentCanvasOp.X/Y 改为
指针以区分"没给坐标"与"坐标 0"。
- update_node 的 patch 新增 x/y(PatchField.Limit 校验 ±1e6),供模型微调单个节点。
- 系统行为策略新增「布局与整理」一节并升版到 8;docs 补工具说明与工具全集;前端同步审批
预览联合类型、面板文案与徽标。
- 工具 schema 预算按实测从 24000 上调到 25000(21 个工具 24788 字节),并改正注释里
"上游约 23.4 KB"的说法(上游 20 个工具实测 22777 字节)。
2026-09-22 01:32:20 +08:00
AetherNo2332
080e4b901e
feat(cloud-agent): 看图工具 canvas_inspect_image 与同批多图工具结果配对
...
云端 Agent 过去只能凭标题或提示词猜画面:上游既有的 image_text_detect / image_annotation_render
是"组织 OCR 请求"和"渲染标注图当参考"两种不同能力,模型自己从不看像素。本 PR 新增只读工具
canvas_inspect_image,把画面本身交给模型。
- 交付走与生成任务参考图同一套短时签名链接(providerResourceURL),Agent 上下文只增长一个
URL,不内联 base64:一张 500 KB 的内联图片会同时顶穿请求体硬限与压缩阈值。
- 能力门控:仅当本轮渠道模型声明 text.references.maxImages > 0 时暴露该工具;VisionEnabled 在
建 run 时按渠道模型合同定格并持久化(工具授权每步从落库状态重建,客户端传入值被忽略)。
- 上下文治理:图片保留最近 3 个工具轮次,同一张图一轮内最多附图 2 次(之后只回执文字,确需
重看传 refresh=true),超出保留轮次换成逐图文字占位符并落 context_images_pruned 事件。
- 视觉锚点:模型看过后写进正文的一句观察记入 ReferenceAssets[].VisualNote 并跨轮继承,下一轮
不必重复看图,也不再对这张图声称"没有视觉识别证据"。
- 同批多图合并成一条 user 消息:图片只能挂 user 消息(tool 角色只接受字符串),逐张 append 会让
历史退化成 tool → user(图) → tool → user(图),被上游以"tool_calls 之后缺少对应 tool 消息"
拒绝。改为先缓冲到 PendingImageInspections,等整批 tool 结果入历史后合并成一条;两个 flush 点
共用同一个幂等助手,ask_user 提前结束路径单独 flush。缓冲必须进检查点:一次推进只执行一个
调用,整批跨越多次转移,每次转移都从 StateJSON 重新解码。
- 附带把上述 400 从"渠道余额不足"归类里拆出来(原文含 insufficient 会落进额度类目掩盖真因),
归为"会话里的工具调用与结果不匹配"。
- 文档补该能力口径与工具全集条目;前端零改动。
2026-09-22 01:32:07 +08:00
AetherNo2332
63c9e32259
feat(cloud-agent): 单步输出上限与秒级墙钟,超时/空输出可自恢复
...
画布 Agent 一轮要跑很多步模型调用,此前只有"按任务类型的分钟级超时":某一步卡住只能等
整轮判死;更根本的是每一步请求根本不带输出上限,不写 max_tokens 时上游按剩余上下文放行,
思考模型可以把单步拖到几分钟,且偶发把整个输出预算花在推理上、正文与工具调用皆空。
- 新增运行时策略 task.agentStepTimeoutSeconds 与 task.agentStepMaxOutputTokens:秒级墙钟
与单步输出上限,都支持环境变量给部署级默认值、管理端热更新;旧配置 JSON 缺字段按默认值
回填,无需数据迁移。
- 单步墙钟到点中止这一步时不再把整轮判死:以可识别标记记为该步失败,运行期关掉上游思考
重试同一步一次(model_failure_recovered / step_timeout_retried),重试仍超时才以可读原因
(model_step_timeout)结束本轮。
- 空输出催办用尽后新增一级升级:关思考 + 放大输出预算重试同一步
(model_failure_recovered / empty_output_escalated),而不是直接判死。放大档在原值上翻倍
并以 131072 封顶,策略值为 0 时用 32768 兜底,让重试仍然有界。
- 输出上限真正下发到上游:textOptions.maxOutputTokens 成为任务信封字段,Agent 的两条请求
路径(内置协议与声明式协议)组装请求体时写入 max_tokens / max_output_tokens,与既有的
input.MaxOutputTokens 取较小值,避免策略上限超过模型声明的物理上限。
- task_worker:执行时限改用带画布 Agent 分支的 taskExecutionTimeout;执行时限到点本身不再
被当成"租约丢失",否则任务会停在 running 等租约过期后被反复重跑(实测一次调用被重跑成
三次上游请求)。续租仍用上游已合入的"不继承父 context 取消"的独立 context。
2026-09-22 01:20:36 +08:00
AetherNo2332
4e2df72eeb
fix(cloud-agent): 工具失败归类与可行动字段
...
工具失败此前只有一句自然语言(tool_failed + text),无法区分"模型自己出的错"和真实的
权限/状态/上游问题:模型拿不到可自纠的反馈,排查时分不清该改提示词、改权限还是等上游。
- 新增 backend/internal/app/cloud_agent_tool_error_class.go:把失败归成
invalid_model_output(幻觉工具名;本轮契约之外、只被 contextScope 挡掉的调用)、
schema_error(缺必填字段/类型错/未知字段/非法 JSON)、state_conflict(画布在读取之后被改动)、
permission_violation(只读轮发起写入等真实授权边界)、upstream_failure(上游 4xx/5xx、
超时、媒体上游拒绝),其余归 tool_error。
- 每类附 retryable 与稳定的 requiredAction(fix_arguments / reread_canvas /
use_advertised_tools / ask_user / report_to_user),写进 tool_failed 的回执与载荷顶层。
只加标注:没有任何放行或拒绝逻辑读它。
- 缺必填字段的通用判定:各工具的校验点抛的多是普通 AppError,从错误类型看不出"模型漏了字段"。
现在用本轮实际暴露的 schema 的 required 与参数比对,命中即按参数契约错误处理(回传 schema 与
guidance 供模型自纠);只在业务侧确实按参数问题拒绝(400/422)时套用,已分类的参数错误不套壳。
- 幻觉工具名的拒绝文案更具体:过去一律"工具未获本轮权限授权",现在指向"不存在的工具 + 只使用
本轮工具表里列出的工具"。
- 前端工具卡失败时显示归类标签,比统一的"执行失败"更能说明下一步该做什么。
2026-09-22 00:53:32 +08:00
AetherNo2332
30bc8f7675
test(cloud-agent): 工具分派 - 新增工具表与运行期分派的一致性守卫
...
工具生效需要同时改三处:compileCloudAgentTools 的 add(...) 注册、advanceCloudAgentTool /
cloudAgentReadTool 的运行期分派、以及 CloudAgentSupportedToolNames() 暴露的平台支持集合。
只改一两处时工具对模型不可见或调用落到 default 分支,而既有测试(含 schema 预算用例与能力
注册表契约用例)依然全绿。
本用例用 go/ast 读源码抽取三条集合后做集合断言:平台支持 ⊆ 分派;注册 == 分派(双向);
cloudAgentWrite 的写操作 ⊆ 注册 ⊆ 分派。解析不到 add(...) 或分派函数被改名/搬走时立即
t.Fatal,守卫自身不会静默失效。纯测试文件,零生产代码改动。
2026-09-22 00:49:24 +08:00
Wyatt_K
18b082a2d0
feat(cloud-agent): 新增 skill_search 工具——Agent 侧技能检索
...
#568/#575 提交 35 个域包(760 卡)后,Agent 按总纲名录逐卡深读的模式
出现检索成本:实测单任务读卡 12-29 次,卡库继续增长后劣化可期。
skill_read_file 只接受精确路径,Agent 侧无检索能力,与用户侧商店搜索不对称。
本 PR 参照仓库内 recall_lessons 的既有检索范式(同一套分词器与三档加权:
name 命中 3 分 / description 命中 2 分),为 Agent 侧补上对称能力:
- skill_search(keyword, limit):在本轮已启用的技能中按关键词打分排序,
返回「哪张卡值得读 + skillId + path + snippet」;不带参数时列全量索引;
- 数据源为本轮冻结的技能快照(与 #577 注入 manifest 的 description 同源),
搜到的必然是能读的,不引入「搜到但版本已变」的一致性问题;
- 只读、零副作用;不搜索未安装技能,避免「搜到不能读」的挫败;
- 渐进披露边界不变:返回索引而非正文,正文仍走 skill_read_file
(12000 字符/页),技能内容永不整体内联进上下文;
- 工具描述明牌「返回的是索引,不是指令」,延续不可信数据纪律。
测试(6 个新契约用例,全绿):
- 与 skill_read_file 一同注册、无技能时均不出现;
- name 命中排在 description 命中之前;snippet 不泄正文;
- 无关键词列全量索引;limit 夹紧;无命中时 guidance 指向 read_file;
- 空技能集返回 guidance;instruction 正文绝不内联(sentinel 断言)。
门禁:go build ./internal/app/ ✓ go vet ./internal/app/ ✓
go test -run TestCloudAgentSkillSearch ✓
2026-09-21 22:23:35 +08:00
ddCat
6f45240599
fix(canvas): 画布批量生成 - 修复节点丢失、资源引用及刷新状态不一致
2026-09-21 21:13:29 +08:00
ddCat
dc1ad68015
fix(*): 素材库与画布 - 修复批量删除刷新、选择布局及工具引用
2026-09-21 20:14:05 +08:00
Wyatt_K
c24f1a74d1
refactor(skills): 种子市场追加门房技能并刷新两包 description
...
- consumer-psychology 瘦身:移除组织治理/团队激励/个人自控类 9 卡(50→41),description 重写为影策场景锚定(带货口播/广告脚本/详情页/直播话术的转化心理)
- comedy-mechanics description 补全为「创作+表演+职业化」三层口径
- 全量卡片 description 残尾清理(截断 fragments),跨包引用名补全
- 新增 scene-recipe-concierge 门房技能种子条目(ID 107,台账分配)
- skills.json 67 → 68 条
2026-09-21 20:13:24 +08:00
root
64832b2fb5
fix(canvas): 任务结果恢复 - 规范化分镜行文本字段
2026-09-21 20:13:22 +08:00
root
72c0a037de
fix(canvas): 任务结果恢复 - 兼容结构化文本结果
2026-09-21 18:57:25 +08:00
Wyatt_K
5fe27ae642
feat(cloud-agent): 技能 description 进入 Agent 系统提示 manifest
...
compileCloudAgentPolicies 的技能 manifest 此前只含 skillId/name/version/hash/entryPath/files,模型看不到每个已激活技能是干什么的,无法在多技能间路由、也无法向用户解释为何选它。本改动把 SkillItem.Description(技能市场公开元数据)注入 manifest,并以 500 runes 为上限截断(描述由技能作者提供,需防止异常长的描述撑爆提示词预算)。skill_read_file 渐进披露边界不变:instruction 与文件正文仍不进入系统提示。
2026-09-21 17:52:49 +08:00
Wyatt_K
5ed345cc7c
refactor(skills): 已合入的 72 条卡级种子重组为 11 个开源域包 + 23 个书籍域包
...
贯彻域包结构结论:一域一包适配每轮 8 技能激活位,种子市场与 judian-skills 仓库口径统一为 34 域包。内容零丢失:86 卡全量保留在仓库 cards/ 目录经 GitHub 安装。ID 治理:1-72 段编号封存永不复用,73-106 段一次到位。skills.json 105 → 67 条(33 官方 + 34 域包)。
2026-09-21 17:08:08 +08:00
Wyatt_K
0021f64d59
feat(skills): 新增 23 个书籍方法论域包种子技能(judian-skills 书籍重铸层)
...
60+ 部经典创作与营销书籍(麦基《故事》《救猫咪》《影响力》《疯传》、奥格威等)的方法论自撰重铸:23 个场景域包共 683 卡,种子条目内嵌域包总纲(何时调用/何时不用/卡片名录/工位边界),完整卡片经 GitHub 一键安装按需深读。skill_id 由 ID 台账续号(73-106 段),与已合入的 72 条卡级种子(#568)互补不冲突。
2026-09-21 16:49:40 +08:00
Codex
d716e3900d
feat(admin): 模型排序 - 支持搜索并移动到指定位置
2026-09-21 15:38:21 +08:00
Codex
691073e173
fix(create): 视频创作 - 恢复参考内容添加与按类型校验
2026-09-21 14:27:16 +08:00
ddCat
c5b81f696c
feat(*): 画布助手 - 新增 Live2D 配置导入与模型渲染支持
2026-09-21 14:11:29 +08:00
ddCat
b8eefdad70
feat(canvas): 模型选择 - 支持彩色展示标签并优化目录与积分交互
2026-09-21 11:11:10 +08:00
ddCat
d5ff22258e
fix(skills): 技能文件包 - 修复元数据截断超限并补充初始化回归
2026-09-21 11:10:58 +08:00
ddCat
4ab43ca6f9
fix(ui): 提示浮层 - 修复键盘触发并补真实交互回归
...
Original-Commit: ff42bb969a037f3271e3da59b752f513c3112b2d
2026-09-21 09:55:26 +08:00
ddCat
8b8ea29148
fix(runtime): 运行稳定性 - 修复技能种子、任务续租与回归检查
...
保留社区技能作者与时间戳修复、Agent 参数约束、资源删除 worker 生命周期、PostgreSQL/Redis 测试门禁及相关回归。
Original-Commit: 0d05ff88bbe6c875d01964041788023a662ff7e8
2026-09-21 09:48:43 +08:00
Codex
15946e5a86
fix(text): 文本生成 - 修复声明式协议流式请求与增量输出 ( #558 )
...
Original-Commit: b2fef297e8a50d519a0480d120a32eb81234a48f
fix(text): 文本生成 - 修复声明式协议流式请求与增量输出
2026-09-21 09:38:11 +08:00
Rou
19c9a207c9
fix(model-picker): 模型选择 - 修复候选报价显示与同渠道模型跳回 ( #556 )
...
Original-Commit: 7a5e17e2112c3c23e081a1ecf3c33a654cf1e907
fix(model-picker): 模型选择 - 修复候选报价显示与同渠道模型跳回
2026-09-21 09:37:51 +08:00
Codex
93bc079b89
fix(video): 创作台视频 - 修正同步音频参数与万有引力结果下载地址 ( #554 )
...
Original-Commit: e85e78fb898be7ef1fcd2027b62ab43c00dfaa2c
fix(video): 创作台视频 - 修正同步音频参数与万有引力结果下载地址
2026-09-21 09:37:35 +08:00
AetherNo2332
5045f7a7e1
ci(quality): 后端测试 - 备齐 Postgres/Redis 依赖并禁止依赖用例静默跳过 ( #571 )
...
Original-Commit: 6bc6d5701f461a7306fd8171e18968c95d7da124
ci(quality): 后端测试 - 备齐 Postgres/Redis 依赖并禁止依赖用例静默跳过
Backend job 既没有 services 也没有 CANVAS_TEST_POSTGRES_DSN,也没装 redis-server,
于是 5 个用例默认静默跳过:PostgreSQL 迁移、素材字节修复、画布版本历史、Redis 租约、
缓存白名单——这些路径在 CI 上从来没被执行过,而 go test ./... 是全绿的。
- 起 postgres:16-alpine service(pg_isready 健康检查)+ 导出 CANVAS_TEST_POSTGRES_DSN;
- 安装 redis-server 可执行文件(用例自起临时实例)并停掉系统服务;
- 新增守卫:单独跑这 5 个用例,出现 --- SKIP 就 ::error:: 并失败;
- 保留既有的 go test -json | tee 与 timings artifact 上传。
2026-09-21 09:37:20 +08:00
AetherNo2332
c09304d905
fix(web): 首屏 favicon - 不再先闪内置品牌图标 ( #570 )
...
Original-Commit: d049f7014d49e93ab0e6aa8b7e715d5155b94dc0
fix(web): 首屏 favicon - 不再先闪内置品牌图标
index.html 静态声明 /logo.svg 作 icon,而 favicon 由 use-appearance-store 在解析出外观后写入
(link[rel~="icon"] + appearanceLogoURL)。自定义品牌部署于是会先闪一下内置 logo。
换成空占位 <link rel="icon" href="data:," />:外观系统照旧覆盖它,占位只是为了不让浏览器去
请求 /favicon.ico(那是一条 404)。代价是外观接口不可用时标签页没有图标,这是有意的取舍。
新增源码级守卫用例(上游原态 1 pass/1 fail,改后 2 pass)。
2026-09-21 09:37:20 +08:00
AetherNo2332
13707c06b9
perf(agent): 工具 schema 瘦身 - 去掉重复 oneOf 并压缩冗余描述 ( #569 )
...
Original-Commit: 042d06f02215c29771360e73bc17c99d132ddfda
perf(agent): 工具 schema 瘦身 - 去掉重复 oneOf 并压缩冗余描述
工具表每一步都要发、还在前缀缓存最前面,属于固定开销:
- canvas_apply_ops 的 ops.items 同时给顶层 type 枚举和一份 oneOf,同一条约束下发两遍;
工具描述与服务端按 action 的强校验已经表达了它,删掉 oneOf。
- generate_media 的 snapshotHash / sourceNodeId / referenceNodeIds 描述压成短句。
- remember_lesson 的 steps[].tool / steps[].note 描述压成短句。
契约不变(字段、required、enum、服务端校验都未动)。实测:20 个工具的平台表
22885 → 22438 字节(−447)。新增体积守卫用例(断言无重复 oneOf + 总体积 ≤24000)。
2026-09-21 09:37:20 +08:00
itsWyatt-K
73ef84ffc8
feat(skills): 社区技能 - 新增 72 个创作方法论技能 ( #568 )
...
Original-Commit: d96d5aa62b68b0f8582f4f2d6a0e588d2794af6d
feat(skills): 新增 70 个社区创作方法论技能并在 README 推荐 judian-skills
- seed/skills.json 追加 70 条目(drama 14 / creative 44 / ecommerce 12),来源为
官方文档(MiniMax H3)与 9 个宽松许可开源项目的结构化蒸馏加自撰方法论,
逐卡带许可署名(metadata.source / license / attribution)
- 与现有 33 个种子技能分工明确:本批负责生成前方法论(节奏校准/提示词组装/
质检/反推),27 个任务域重叠技能带工位边界声明,与 image_text_detect 正交互补
- README 核心能力新增社区技能生态条目,指向 judian-skills 仓库
(技能页 install/GitHub 标签直装)
- 验证:go build ./internal/skills 与 go vet ./internal/skills 均通过;
种子 JSON 无重名/重 ID;A/B 实测五任务全部优于无技能与上游同类技能
Original-Commit: 55e0252e92c65bf9b69891c46313be5a7a02edd7
feat(skills): 种子技能 70 → 72(补装订图文案规范与视觉决策转换层)
新增两条已在社区技能库发布、但此前因 frontmatter 残缺被转换器按私有跳过的技能:
- flux-asset-image(FLUX.2 资产图规范):四层结构 Subject→Action→Style→Context + 五条专属规则(无负向词 / HEX 绑物体 / 外观段逐字重复保角色一致性 / 相机代码提写实感 / 多主体切 JSON)。补上图像侧「生成前方法论」空白。
- vis-to-prompt(视觉决策 → 提示词转换层):把视觉叙事七元素决策(空间选型/影调/色彩/运动)翻译成模型能懂的具象短语,并嵌入 FLUX 四层或 H3 时间轴。补上「设计意图 → 模型语言」的断点。
字段规范:skill_id 由 id_ledger.json 台账分配(...00071 / ...00072),不与既有 70 条串号;tag=creative;status=1;source=3;instruction 末尾附许可与署名页脚。
验证:go build ./... 与 go vet ./... 均 EXIT=0;skills.json 自检无重复 skill_name / skill_id,总条目 33 → 105。
2026-09-21 09:37:20 +08:00
AetherNo2332
04d8b85eec
fix(app): 任务租约 - 续租不再被自己的执行时限打断 ( #567 )
...
Original-Commit: 2b796c403f0c99f3b607b53650b42078964ea753
fix(app): 任务租约 - 续租不再被自己的执行时限打断
续租 context 原来派生自任务执行时限(context.WithTimeout(ctx, 5s)):执行时限一到,
续租请求立刻被取消,失败后被误判成"租约失效、等待其他 worker 恢复",任务停在 running,
租约过期后又被别的 worker 重跑(实测一次上游调用被重跑成三次)。
- taskLeaseRenewContext:用 context.WithoutCancel(parent) + 5s,只继承值、不继承取消与时限;
- 收尾处若我方执行时限已到点,不再直接返回租约错误,而是继续走失败收尾(真丢失时行为不变)。
新增用例在旧写法下失败、修复后通过。
2026-09-21 09:37:20 +08:00
AetherNo2332
fd3fc44d88
fix(agent): 画布写入 - 漏 patch 按参数错误回给模型而不是终止整轮 ( #566 )
...
Original-Commit: a7df2b57c72e479200b82d0af88446d43fa9f9dd
fix(agent): 画布写入 - 漏 patch 按参数错误回给模型而不是终止整轮
审批模式下模型用 canvas_apply_ops 做 update_node 时漏了 patch,准入预检直接返回普通
BadAuthRequest,运行期按"准入失败"处理 → 整轮 failed,用户只看得到一句"更新节点必须提供 patch",
模型没有改正机会。批量创作表、分镜、画布读取参数都已把同类错误包成 cloudAgentArgumentError
(运行期 errors.As 后作为工具结果回给模型重试),这里补齐。
未知画布写操作仍按准入失败终止(既有用例断言不变);新增用例同时钉住这两条。
2026-09-21 09:37:20 +08:00
AetherNo2332
f7a8b9eda5
test(web): Director E2E - 点击前要求目标站稳 300ms ( #565 )
...
Original-Commit: 8af5d28da78feeb30ca673030422a20e4ede0411
test(web): Director E2E - 点击前要求目标站稳 300ms
clickPoint() 原来只要相邻两次读数坐标相同(间隔 100ms)就判定就绪。AntD 弹窗/抽屉有约
200ms 入场动画,动画刚开始、坐标还没动的那一拍会被判成"稳定",真正派发鼠标事件时控件已移位,
点击落到遮罩(mask.closable=false)上无效。
改为要求坐标连续 300ms 不动、等待上限 5000ms→8000ms。上游 main 上连跑两次都失败在
F6「留在导演台」(57/58),打补丁后连跑两次都是 58/58。
2026-09-21 09:37:20 +08:00
AetherNo2332
ea44d445b4
build(deploy): 部署配置 - 转发 CANVAS_PUBLIC_BASE_URL ( #564 )
...
Original-Commit: 1734438cd00963a607795b2a6640ab7827e487e0
build(deploy): 部署配置 - 转发 CANVAS_PUBLIC_BASE_URL
后端读 CANVAS_PUBLIC_BASE_URL(resource.go 用它拼本地存储的短时签名链接,取不到时的报错
也在提示管理员配置它),但 5 个 Compose 文件都没有把它传进容器:按报错操作的管理员把变量
写进 .env 之后没有任何效果,而报错文案仍在让他"去配置"。
5 个编排与 .env.example 一并补齐(默认空值,行为与现状一致),并说明内网部署还需把该主机
放进 CANVAS_ALLOWED_PRIVATE_UPSTREAM_HOSTS。无代码改动。
2026-09-21 09:37:19 +08:00
AetherNo2332
22d65d0192
fix(web): 基础控件 FloatingDock - 宿主没有 matchMedia 时不再渲染失败 ( #563 )
...
Original-Commit: 3da77b3931a675de06b02c1bba93f112d253041b
fix(web): 基础控件 FloatingDock - 宿主没有 matchMedia 时不再渲染失败
`window` 存在不代表 `matchMedia` 存在(SSR 垫片、嵌入式 webview、部分 DOM polyfill),
而 FloatingDock 在渲染期直接取 `window.matchMedia("(pointer: coarse)").matches`,
取不到就抛 TypeError,整个 dock(画布工具栏/素材托盘/缩放控件)渲染失败。
仓库里同一模式已有先例:canvas-workspace-tool-panel 用 typeof 守卫。
抽 coarsePointerQuery():两个都探测,取不到按"非触屏"处理,useEffect 也提前返回;
能取到时行为不变。新增源码级守卫用例(上游原态失败、补丁后通过)。
2026-09-21 09:37:19 +08:00
AetherNo2332
76e02734f1
test(app): 测试库 - 改用 WAL 文件库,消除共享缓存内存库的表级锁 flake ( #562 )
...
Original-Commit: 25931635266ca01843691e87d631b6f2db178e52
test(app): 测试库 - 改用 WAL 文件库,消除共享缓存内存库的表级锁 flake
两处用例夹具用 sqlite 的 `file:…?mode=memory&cache=shared`(表级锁,且不受 _busy_timeout
约束),而它们都会触发后台删除 outbox(go s.drainResourceDeletionJobs),并发时偶发
`database table is locked`(本地并发读写 400 次撞到 70+ 次)。
新增 newSQLiteTestDB(t):文件库 + WAL + busy_timeout=5000,WAL 允许"一写多读"、写冲突退化成
SQLITE_BUSY 并由 busy_timeout 重试;库文件放 os.MkdirTemp(不用 t.TempDir,避免 outbox 仍在写
时清理报 directory not empty)。两处夹具改用它,并新增一条属性用例守住这个选型。
2026-09-21 09:37:19 +08:00
AetherNo2332
6c92c3be7a
chore(web): 前端格式 - 统一十个文件的 Prettier 格式 ( #561 )
...
Original-Commit: ade0049c0b80733dfea563bac2aae9260e373cf0
style(web): 前端格式 - 补 Prettier 格式(10 个文件)
这 10 个文件(3 个组件/样式与设置页、4 个 admin 主题与控件、1 个 lib、2 个测试)
用仓库自带 Prettier 检查会 warn,`bun scripts/check-changed-formatting.mjs` 在改动到它们时
会直接判红。本次只做格式化,不改任何行为:合并的 CSS 声明、去掉多余换行与括号、
统一链式调用换行。
验证:prettier --write 后 `check-changed-formatting.mjs` 通过、typecheck 通过、
1940 条前端测试全过、eslint 通过。
2026-09-21 09:37:19 +08:00
AetherNo2332
5e3bc01161
fix(web): 基础控件 Tooltip - 子元素可触发并保留键盘可达性 ( #560 )
...
Original-Commit: 38b5909fa78902048345ad8d8e00248660830ad5
fix(web): 基础控件 Tooltip - 子元素可触发并保留键盘可达性
react-aria-components 的 TooltipTrigger 通过 context 下发 hover/focus 处理与 triggerRef,
只有消费该上下文的组件才会真正挂上;原来包一层普通 span,既不读 context 也拿不到 ref,
所以悬停/聚焦都不弹气泡(有定位也无基准)。
包装层改为 Focusable + excludeFromTabOrder:悬停与聚焦都能触发、气泡有定位基准,
外层不占 Tab 位,键盘焦点仍落在内层控件上,导航顺序不变。
2026-09-21 09:37:19 +08:00
AetherNo2332
edcf7bc7c0
fix(web): 诊断 - 在没有 window.location 的环境不再抛错 ( #559 )
...
Original-Commit: cdb07ca9cbdd74e63d8e80659f3bdbd6d49b3dff
fix(web): 诊断 - 在没有 window.location 的环境不再抛错
recordDiagnosticEvent / normalizeRoute 用 `typeof window !== "undefined"` 判断"在浏览器里",
但 bun 的测试环境里 window 存在、window.location 不存在,于是每次记录诊断事件都抛
`TypeError: undefined is not an object (evaluating 'window.location.pathname')`,
director-diagnostics-recorder 的 9 条基线用例因此全红。
改成 browserLocation():window 与 window.location 都探测,取不到就当没有地址(路由回落 "/")。
浏览器内的行为完全不变。
2026-09-21 09:37:19 +08:00
dk56dd
13d8f629bb
fix(settings): 工作台浮层 - 修复离开设置页后菜单背景丢失 ( #555 )
...
Original-Commit: 7edc171f36aa77b19d998ffd83d168b5d9169287
fix(settings): 工作台浮层 - 修复离开设置页后菜单背景丢失
Removed useLayoutEffect for body class management.
Original-Commit: 3b555144cc079b403ad36a6df02be5e7ad8c19b9
Update pending-test.mdx with workspace overlay styles
Added new section on workspace overlay styles after exiting settings page, including tasks for removing duplicate overlays and fixing navigation issues.
2026-09-21 09:37:19 +08:00