Feat/优化 图标规范+生spiritsheet 提示词 #137
Reference in New Issue
Block a user
Delete Branch "feat/better-icon-spiritsheet"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
前端 UI:

图标规范需要llm根据用户输入做推断, 新增了external job id, 让llm推断在worker里进行,确保llm调用在参数余额校验之后
最终生成图标需要 图标规范携带一些元数据用于动态调整提示词, 将其放在generation_input_json.fields[] 里, 生图标时查询获得, 兼容lagacy,对不存在特殊处理.
查询需要稳定的resourceID, 更改了相关接口,类型(原来前后端传递的都是obj key)
依然有 #134 持久化与画布完成操作不具备原子性的问题
历史遗留问题与pr无关, 标注TODO,未处理:
当前 head 仍有以下阻塞,暂不建议合并:
assetKind=image;本 PR 新增的图集引用解析只接受icon-spec,因此用户可见入口得到的引用会被稳定拒绝。请让该入口登记正确的权威类型,并补从上传到提交图集生成的回归测试。editor_image_generation、referenceImageSrc/ objectKey 与“不新增独立任务类型”,而当前实现已经改为独立editor_icon_spec_generation及仅接受正式referenceId。请在同一 PR 内统一更新。468dc1c1、a2b275382使用英文feat/fix前缀;806333a3、10cef9b1使用英文 merge 标题;另有559f4edc、690b6496、41a7182d等只有标题、没有逐行变更正文。请在合并前 squash/reword,使每个最终提交使用中文标题,并在标题后逐行写明各项修改。@@ -117,0 +120,4 @@- 图标规范的 `playSetting / artStyle` 单字段上限统一为 `200` 个 Unicode 字符。浏览器原生 `maxLength` 按 UTF-16 码元计数,与该业务口径不一致,因此图标规范文本域不设置 `maxLength`,只通过按 Unicode 字符截断的 `onChange` 和提交校验限制输入;非法恢复态禁用优化与生成。editor client 在优化请求、优化响应和最终生成提交前再次拒绝超长值;api-server 对两个优化入口和最终图标规范生成入口都执行同一上限校验。LLM 优化请求固定 `1024` 输出 token 上限,容纳推理开销同时限制最多三次调用的输出成本;平台层返回 `EmptyResponse` 时按瞬态空结果进入同一有界重试。LLM 优化结果必须是无标题、解释、Markdown 或 JSON 的可直接使用纯文本,允许分段和换行;非法格式与空文本、超长文本一样作为非法模型输出重试,第三次仍非法返回 `502`。- 上述两个 refine 调用与生成前的 `ExtraParam` 补全均最多执行 3 次完整 LLM 尝试;空文本、格式非法或补全结果非法 JSON 在次数内重试。调用错误只对 timeout、connectivity、transport、上游 `408 / 429 / 5xx` 重试,配置、请求、上游其它 `4xx` 等永久错误立即返回。业务层执行重试时关闭 `LlmClient` 自身的内层重试,避免配置重试与业务重试相乘。- `ExtraParam` 补全 prompt 只把 `playSetting / artStyle` 作为待分析数据,要求 LLM 直接返回且只返回 `{ genre, theme, useCase, targetUser }` JSON 对象。`genre` 必须取 `GameGenre::as_slug()` 定义的 19 个中文值之一,`GameGenre` 的自定义 Serde 也统一按该中文值读写,不接受英文枚举名;`theme` 是可组合、可扩展的中文题材;`useCase` 表示 `PC / mobile / console / Web / handheld` 等实际调用平台;`targetUser` 为结合玩法与美术推断的自由中文用户描述。四项均为非空且不超过 `200` 个 Unicode 字符的字符串,解析后去除首尾空白,不接受 Markdown、数组、`null` 或额外字段。- `POST /api/editor/icon-specs/generations`:业务字段只有 `playSetting / artStyle`;参考图、项目、素材文件夹和 `canvasCompletion` 继续使用统一生成包络。前端不得提交最终 prompt、`kind` 或 `assetKind`。api-server 必须先补全 `ExtraParam`,再构造最终 prompt,随后固定以 `kind=spec / assetKind=icon-spec / gpt-image-2 / 16:9·2K` 调用既有图片生成分发;队列仍只使用 `editor_image_generation`。服务端重建 `generationInputs.fields[]` 为「玩法设定 / 美术风格 / 游戏类型」,其中游戏类型保存 `GameGenre::as_slug()` 返回的中文值;`theme / useCase / targetUser` 只参与 prompt,不进入 metadata。[P2] 同步独立任务类型和引用字段的新合同
本 PR 后续实现已经把图标规范生成迁到独立
editor_icon_spec_generation,图标图集主规范也收紧为正式referenceId;这里新增的文字仍声明队列只用editor_image_generation,下一条仍写referenceImageSrc。这会让后续实现与排障继续按已废止合同工作。请把本节统一更新为当前 job kind、referenceId及只接受项目资源 ID / 素材 ID 的边界。@@ -43,2 +43,2 @@10. 图片快速编辑不展示额外参考图入口;原图或绘制了红框和序号的标注图始终作为 `/api/editor/images/edits` 的 `sourceImageSrc` 直接提交,不作为 `referenceImageSrcs`。11. 快速编辑打开后,画布视口应调整到原图完整展示,且面板位于原图下方并不遮挡原图;原图右侧显示竖向框选工具,支持矩形、椭圆和画笔自由框选。快速编辑进入时不默认启用框选工具,点击工具后出现选中态并保持高亮,再点同一工具取消启用;红色圈选框使用细描边。每完成一次框选,红色圈选框按完成顺序标注 `1 / 2 / 3...`,并在快速编辑提示词中追加一行 `对N号红色圈选框里的内容做以下修改:`。10. 图标规范只使用 `specType="icon"`,历史 `specType="ui"` 快照在恢复边界迁移为 `icon`。表单字段使用 `playSetting / artStyle`,界面标题继续使用「玩法设定 / 美术风格」。两项初始为空且必填,客户端提交前统一 trim 并拒绝空白值;每项独立支持一键优化、处理中锁定自身、成功后单次撤销,操作行最右侧按 Unicode 字符实时显示 `当前数/200`。撤销必须恢复优化前的原始输入(包括首尾空白);手工编辑后立即清除该字段已经失效的撤销快照,失败只保留当前文本与仍然有效的旧撤销快照。LLM 返回空文本、超长文本、Markdown / 结构化内容,或 finish reason 明确表示截断、过滤、失败时,后续有界重试必须携带上次无效输出和对应修正要求,不能把未完成前缀当作成功结果。优化请求必须绑定发起时的生成对象 ID 和请求代次;活动对象身份只在 React effect 提交后更新,并在 cleanup 中失效,丢弃的并发 render 不得改变请求归属;对象切换或新请求取代旧请求后,旧成功或失败结果都不得更新当前面板。任一项处理中或任一项为空时禁用生成。字段标题使用真实 label 关联 textarea,不得把优化 / 撤销按钮包进 label。控件继续使用平台默认样式,不新增图标规范专属 CSS。11. 图标规范最终生成改走 `POST /api/editor/icon-specs/generations`。前端只提交业务字段和统一参考图 / 项目完成包络,不拼最终 prompt,不提交 `kind / assetKind / ExtraParam`;后端固定图片参数。HTTP handler 先调用可复用的图片请求预检,完成参考图稳定性、owner 授权、Provider 配置和运行时定价校验;全部通过后才调用文本 LLM 补齐 `ExtraParam` 和最终 prompt,再把完整图片请求交给既有 `editor_image_generation` inline / queue 分流。不得为图标规范新增独立外部任务类型;最终 worker 仍按执行时事实重新校验,避免排队期间状态变化产生 TOCTOU。[P2] 这里仍描述已被本 PR 取代的队列架构
当前代码与本 PR 的最新决策已经使用独立
editor_icon_spec_generation,不再复用editor_image_generation。这里却明确写“不得新增独立外部任务类型”,与实现直接冲突。请同步为现行队列、计费和 worker 语义,避免这份统一改造方案继续成为错误权威来源。@@ -41,2 +41,4 @@- 前端提交到 `POST /api/editor/icon-spritesheets/generations`。- inline 与持久队列入口共用同一份 `iconDescriptions` prompt 合同:去除空白项后必须保留 `1..100` 条,单条最多 `200` 个 Unicode 字符,以换行拼接后合计最多 `2000` 个 Unicode 字符且不超过 `6144` 个 UTF-8 字节。请求边界校验成功后生成 `ValidatedEditorIconSpritesheetPrompt`,后续 prompt builder 不接受裸字符串。队列入口必须在引用解析、定价和任务持久化前同步拒绝可预测错误,不能把无效任务留给 worker 延迟失败。- worker 解析主 `referenceImageSrc` 时必须通过 `spacetime-client` 的通用窄查询 `resolve_editor_reference` 在同一事务快照内完成引用解析和 owner 校验:资源 ID / 素材 ID 走主键,对象键按规范化 `image_src="/<objectKey>"` 索引定位单条资源或素材,并通过 `asset_object(bucket, object_key)` 复合索引校验对象 owner。同一 ID 若同时命中项目资源和素材必须按协议歧义拒绝,不得静默偏向任一表。procedure 复用既有 `EditorProjectResourceSnapshot` 或 `EditorAssetSnapshot` 返回唯一已验证行,不接收图标业务类型参数、不新建图标专属快照,也不得拉取当前用户的完整工程列表或素材库。`assetKind="icon-spec"` 与 `genre` 都由图标图集业务代码从返回行校验和提取。引用不存在、owner 不匹配、asset object 不存在或数据库调用失败时 procedure 直接失败;业务类型不符或保存的游戏类型无效时 API 失败;合法规范没有已保存游戏类型时允许 `genre=None`。[P2] 主规范引用文档仍允许已禁止的 objectKey /
referenceImageSrc当前实现的窄查询只接收
reference_id,图集请求字段也已经改为referenceId,仅允许当前 owner 的项目资源 ID 或素材 ID;这里新加的段落仍按referenceImageSrc解析 objectKey /image_src索引,后面的请求字段与上传说明也沿用同一旧合同。请统一改为referenceId,并删掉 objectKey、URL / 临时 key 可作为主规范引用的表述;普通附加参考图的referenceImageSrcs边界可单独保留。@@ -10950,0 +9479,4 @@(asset.object_key, asset.generation_inputs, asset.asset_kind)}};if asset_kind.as_deref().map(str::trim) != Some("icon-spec") {[P1] 修复上传入口与这里的
icon-spec强校验不匹配这里收紧为只接受
asset_kind=icon-spec,但useImageCanvasUploadWorkflow.ts的addIconSpecReferenceFiles仍走通用createPersistedReference;后者在第 333 行对图片固定调用resolveUploadedAssetKind('image'),最终把该上传保存成assetKind=image。因此用户点击“图标规范 → 上传图片”后得到的referenceId必然在这里被 400 拒绝。请让这个专用上传目标登记为权威icon-spec(同时覆盖 project resource 与 asset 两条分支),并补一条上传后真实提交图集生成的回归测试。a0b55eda52to6725ee1b8c复审当前 head
6725ee1b8c:上轮提出的三项阻塞均已关闭。authoritativeAssetKind: icon-spec,项目资源和账号素材两条持久化分支都会登记为权威icon-spec,并已补上传后真实提交图集生成的回归测试。editor_icon_spec_generation、正式referenceId以及仅接受当前 owner 项目资源 ID / 素材 ID 的合同。当前 head 的 Repository、Frontend、Backend、Native shell 四项 CI 均为绿色,
git diff --check通过且无合并冲突;本轮未发现新的代码阻塞。仓库分支保护仍要求当前 head 获得 1 个有效批准,本条为普通复审评论,不替代 APPROVE。626baa8d17to5140d82ff4当前 head
f9485b91ff仍需修改,暂不建议合并:referenceId,工具提示仍允许“图标规范或风格参考图”;普通已登记风格图会通过规划和用户确认,随后被图集入队接口的assetKind=icon-spec强校验稳定拒绝。请把权威素材类型带入 Agent 图片上下文,在确认前只允许合法icon-spec,并补普通图片拒绝与 icon-spec 成功的贯通测试。详见行内评论。676bd524ee,git merge-tree --write-tree在ImageCanvasIconSpritesheetComposerView.tsx、ImageCanvasIconSpritesheetComposerView.test.tsx、ImageCanvasSpecGenerationPanelView.tsx、ImageCanvasSpecGenerationPanelView.test.tsx检出冲突;Gitea 当前mergeable=false。请同步最新 master、按现役输入框/滑动条公共实现解决冲突,并重新运行当前 head CI。5140d82ff 调整图标优化按钮样式没有正文;请在合并前 reword 或 squash,确保中文标题后逐行说明本次修改。当前 head 的 CI run
868四项均成功,但它只绑定冲突前的f9485b91ff,不能替代最新 master 合并结果与上述业务合同验证。@@ -727,1 +727,4 @@.map_err(|error| EditorAgentToolError::invalid_args(error.to_string()))?;self.context.image_metadata(&args.reference_image_id).and_then(|metadata| metadata.reference_id.as_deref())[P1] 在确认前校验主规范的权威
assetKind这里把“存在非空
referenceId”当作合法图标主规范,但ImageMetadata/EditorToolContext没有携带权威assetKind,现役工具提示还明确允许“图标规范或风格参考图”。因此普通已登记风格图会通过规划、展示和用户确认,prepare_job随后把它作为referenceId入队,而enqueue_editor_icon_spritesheet_generation_for_owner会因它不是icon-spec返回 400。当前 TODO 已承认这个缺口,不能延后到合并后处理;请把权威类型带入附件/工具上下文,在确认前拒绝或正确引导非icon-spec引用,并补普通图片失败、icon-spec成功的贯通测试。c663514da7tod1562ab65f请求修改。当前复审绑定 head
d19792f692ee011f6e5dd9de3d9eb266048362bf、base6cb13b3884e66460885d78bbc672b0f145e954a0。此前的icon-spec上传类型、三份编辑器文档合同和 Agent 权威assetKind校验均已修复,merge-tree 与git diff --check通过。当前仍有两个 P1 阻塞:
referenceId,但现役 AI Game Creator 仍发送referenceImageSrc,其请求会在入队前因缺少必填字段失败。请在同一变更中更新正式调用方及测试,并为 External v1 选择兼容字段/弃用期或新版本方案,不能只替换现役 v1 字段。every_provider_inline_route_defers_billing_until_durable_completion期望editor_project.rs命中 3 次,实际为 4 次(845/846 通过)。请修正门禁期望并重新跑绿当前 head。提交历史也再次出现英文空正文 merge commit
48bbaede99,以及e93f30ebea、d19792f692等空正文提交,不符合仓库提交规范。@@ -3651,3 +3651,3 @@"type": "object","required": ["referenceImageSrc","referenceId",[P1] 不能只替换 External v1 字段而漏掉现役 AGC 调用方
这里把
referenceId改为必填,Rust DTO 的reference_id: String也会在缺失时直接拒绝请求;但现役apps/ai-game-creator-shell/src-tauri/src/agent/generation/canvas_generation.rs仍发送referenceImageSrc,对应测试也锁定旧字段,因此真实 AI Game Creator 图集生成会在入队前返回 400。请同 PR 更新调用方、提示/测试,并为仍命名为 v1 的外部契约提供兼容迁移或新版本方案。@@ -929,3 +929,3 @@fn every_provider_inline_route_defers_billing_until_durable_completion() {for (source, expected_calls) in [(include_str!("editor_project.rs"), 4),(include_str!("editor_project.rs"), 3),[P1] 修正 durable billing 门禁的错误期望值
当前
editor_project.rs实际仍有 4 处with_editor_generation_durable_billing_boundary(,这里改成 3 后使 run 905 的 Backend CI 稳定失败:845 项通过、仅此断言left=4 / right=3失败。请恢复与当前源码一致的期望,并保留editor_project_icon.rs新增入口的独立覆盖后重跑 required CI。262698f5b9to02b4b6955d已与 PR #135 一并手工集成到 master。master 提交:2412700e665ecb90e93575670399a46f72a728d7;已保留本 PR 最新 head
badb886790的完整历史,并在集成分支解决与 #135、master 的冲突。Pull request closed