Commit Graph

2863 Commits

Author SHA1 Message Date
k88936 dd115778e9 Cocos 执行错误去掉多余的 to_string
- cocos_execute/error.rs CodeInvalid 直接 clone 已拥有的 cause
2026-10-02 14:40:19 +08:00
k88936 8f07ff9379 浏览器试玩错误去掉多余的 to_string
- browser_playtest/error.rs PlaytestFailed 直接 clone 已拥有的 cause
2026-10-02 14:40:19 +08:00
k88936 bca9b97acd 统一错误事件返回值复用已脱敏的 message
- runtime_error.rs persist_agent_runtime_error 返回的 message 改用 safe_message

- 与 error 字段口径一致,返回值即使被序列化也不会泄露绝对路径/凭据
2026-10-02 14:40:11 +08:00
k88936 b1d16b5683 错误回显不再给字符串套 JSON 引号
- arguments.rs not_text_repr 对字符串直接回显原文

- 非字符串仍按 bounded_echo 序列化后截断
2026-10-02 14:39:59 +08:00
k88936 85d51a074e 内置工具分页 offset 加绝对上限,避免 nextOffset 溢出
- arguments.rs 新增 MAX_PAGE_OFFSET 常量

- page() 在 max_offset 为 None 时也按 MAX_PAGE_OFFSET 封顶,挡住 offset + page.len() 的溢出
2026-10-02 14:39:46 +08:00
k88936 3d68d56524 内存里的工具观察保持原文,落盘那份按存储口径脱敏
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m10s
Project CI / Backend tests (pull_request) Failing after 16s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m1s
Project CI / Frontend tests (pull_request) Successful in 2m16s
Project CI / Repository checks (pull_request) Failing after 13s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 5m57s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m10s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 8m6s
Project CI / Native shell tests (pull_request) Successful in 6m36s
- `build_game_creator_agent_runtime_pending_tool_action` 在嵌入 observations 前按存储口径脱敏:pending ledger 受 fail-closed 门禁保护,工具原文里的项目绝对路径会让整次持久化被拒
- `runtime_driver/main_loop`、`runtime_state` 的过期续跑、`runtime_actions/parallel_read` 不再把脱敏结果写回内存观察向量,prompt 继续用原文
- `parallel_read` 的前缀核对仍用脱敏投影比较,只是不再覆盖内存向量
- 持久化侧(context bundle / pending action)自己脱敏,内存与落盘两份从此解耦
2026-10-02 10:56:32 +08:00
k88936 7224bd0dc0 直连工具结果与计划回灌不再脱敏,只做长度收口
- `direct_validation`:浏览器/命令验证回执里的 error/output 原文返回给 Codex
- `direct_patch`:补丁工具输出原文返回
- `direct_delivery`:计划步文案、`contract.scope`、未过验收的缺口清单原文返回
- `direct_runtime`:浏览器事实证据(diagnostic / console.error / exception / fatal request)、陶泥儿整包完成告警、可返修错误的反馈提示原文返回
- `provider_request_builders`:回灌给模型的 `thinkingSummary` / `fallbackResponse` 原文返回
- 两个测试改为断言原文进入 prompt(`browser_diagnostics_go_verbatim_to_the_model_before_same_thread_repair`、`completed_regeneration_replays_the_exact_lost_response`)
- 去掉因不再脱敏而失去用途的 `root` 形参:`update_plan`、`bound_for_completed_workflow_at` / `validate_completed_workflow_result_at`
- 审计/诊断侧照旧脱敏:`record_direct_codex_failure`、`DirectTurnTerminal::failed`、`persist_agent_runtime_error`、`codex_app_server` 日志
2026-10-01 19:21:57 +08:00
k88936 b0ec155401 委派回执给模型的明细不再脱敏,审计记录自己脱敏
- `build_static_delegate_result_for_child_at` / `publish_game_creator_agent_delegate_result` 的结果明细只做长度上限
- 回执任务文案不再 `sanitize_prompt_context`,父子 run 之间传的是原文
- `record_game_creator_agent_delegate_result_success` 在写 `resultPreview` 审计时自行脱敏
- 抑制态回执任务的 `task` / `terminalDetail` 与 `agent.schedule_ready` 观察改为长度收口
2026-10-01 18:55:04 +08:00
k88936 f8ba46fa4f Runtime 工具观察只做长度收口,脱敏只留给审计写入
- 各工具构造 `AgentRuntimeToolObservation` 时不再调用 `sanitize_agent_runtime_text` / `redact_agent_runtime_project_paths`,改为只做长度上限的 `truncate_agent_runtime_text`
- 保留 `append_agent_db_record` / 事件 / `append_patchset_audit` 等审计写入处的脱敏
- `agent.action_history` 读取的账本仍按写入侧口径脱敏,读取路径不再二次脱敏
- 委派(`agent.delegate` / `agent.spawn_isolated`)与 `agent.schedule_ready` 的结果明细原样进回执
- 去掉因参数失去用途的 `root` 形参:`canvas_durable_result_reconciliation_observation`、`rejected`、`error_observation`、`error_observation_with_revision_advance`
2026-10-01 18:54:11 +08:00
k88936 cf6ed72f34 工具观察原样进 prompt:去掉按 token 预算的脱敏与截断
- 删除 `bound_observation_for_prompt` 与 `truncate_to_estimated_tokens`
- `prepare_game_creator_agent_runtime_prompt_history` 去掉 `tool_output_token_limit` 参数,观察原样进 prompt
- 调用处同步去掉该参数:`provider_request_builders`、`tests/runtime_state`
- 删除只验证旧有界行为的 `tool_output_is_bounded_by_token_limit` 测试
- 脱敏仍只发生在写审计/持久化时(`sanitize_game_creator_agent_runtime_context_observations_for_storage`)
2026-10-01 18:53:40 +08:00
k88936 214055e319 给模型的工具结果不再脱敏或截断,脱敏只留在诊断侧
- bridge_tool_failure 原样回传 typed 错误的 message,去掉 redact_agent_runtime_error
- compose_direct_tool_outcome 只在写诊断时按 ToolFailure::redact_limit 脱敏截断,模型面用原文
- 编辑器执行与 Cocos 执行的成功回执去掉脱敏/路径替换,report 原样进工具结果
- 账号素材导入的 failures、生成/抠图/美术准备的 warnings 不再脱敏
- 删除随之失效的 bridge_safe_warning_messages 及其断言脱敏的测试
2026-10-01 18:31:21 +08:00
k88936 6af95b8a22 回退「工具回执进 message 前先按各自预算做有界序列化」
- 撤销 004889f27:给模型的工具结果不做任何截断,报告原文完整回给模型
- 撤销 tool/error.rs 的 bounded_report_text 及 browser_playtest / cocos_execute / environment_check / editor_execute 四处调用
- 截断与脱敏只保留在诊断/审计侧(persist_agent_runtime_error)
2026-10-01 18:28:26 +08:00
k88936 31fbadf260 交付类工具的裸 cause 补工具前缀
- delivery_status 的 StatusUnavailable 文案改为「交付状态读取失败:{cause}」
- register_delivery_contract 的 ContractRejected 文案改为「登记交付合同失败:{cause}」
- update_plan 的 PlanRejected 文案改为「更新计划失败:{cause}」
- 这些 cause 是 direct_delivery 的内部机器码(如 delivery-status-worker-exited),原来单独回给模型时没有任何工具上下文
2026-10-01 17:56:33 +08:00
k88936 004889f273 工具回执进 message 前先按各自预算做有界序列化
- tool/error.rs 新增 bounded_report_text:把 JSON 载荷按给定预算先截断再拼进文案
- browser_playtest / cocos_execute / environment_check / editor_execute 的 report 变体改用该 helper,预算取变体自己的 redact_limit
- 最终可见的头部内容不变,只是不再把整份大载荷搬进多趟脱敏;超长报告被截掉的尾部本来也不会出现在最终文案里
2026-10-01 17:56:16 +08:00
k88936 7eb62b09e2 编辑器执行 code 的三种校验失败拆成独立变体
- EditorExecuteError 的 CodeInvalid 拆成 CodeEmpty / CodeContainsNul / CodeTooLong{got_bytes,max_bytes},每个 case 一个变体
- editor_execute/error.rs 新增 EDITOR_CODE_MAX_BYTES 常量,direct_tool_bridge 的校验改用该常量并分别返回对应变体
- 模型能从文案看出具体违反了哪条规则,不再只看到一句话笼统覆盖三种失败
2026-10-01 17:55:41 +08:00
k88936 bab88d62e0 includeSequenceFrames 类型错回显改用 not_text_repr
- direct_tool_bridge 里 IncludeSequenceFramesNotBoolean.got 由 value.to_string() 换成 not_text_repr(value)
- 与该工具其它「字段给了错误类型」的变体同一口径:回显按 120 字符截断
2026-10-01 17:55:04 +08:00
k88936 47b6454696 web_search 的 maxResults 类型错回显改用 not_text_repr
- direct_tool_bridge 里 MaxResultsNotInteger.got 由 value.to_string() 换成 not_text_repr(value)
- 与 query 的 QueryNotText 一致:不受信回显按 120 字符截断,不再把整段值带进错误消息与序列化 typed error
2026-10-01 17:54:51 +08:00
k88936 75e3152412 agc_generate_image 的 kind 不合法时回显截到 120 字符
- KindUnsupported 的 got 原来把整段 kind 原样带进文案与序列化错误;这条路径没有长度校验,与上方 KindNotText 的 not_text_repr 口径也不一致
- 改用 bounded_echo(kind),与其它不受信回显同一上限;仍保留开头的原值,模型能看出自己传了什么

验证:cargo fmt --check 通过
2026-10-01 17:52:38 +08:00
k88936 0354fd353c assetIds/localPaths 与 sliceCount 的类型错回显改用 not_text_repr
- ImportAccountAssetsField::not_string_array 与 GenerateImageError::SliceCountInvalid 原来把整个值 to_string() 后嵌进错误,MCP 预检又原样回给调用方,超大数组会整份被反射
- 改用共享的 not_text_repr(120 字符截断),与其它「给错类型」的回显同一口径

验证:cargo fmt --check 通过
2026-10-01 17:52:06 +08:00
k88936 6a4efa15ee 未登记的客户端工具名在构造处截到 120 字符
- dispatch 兜底分支构造 UnknownClientToolRejection 时改用 bounded_echo,客户端给的超长工具名不再原样进 to_user_msg 与序列化诊断
- 该名字在构造处就有界,后续 clone/序列化都受同一上限约束

验证:cargo check --bin genarrative-ai-game-creator-shell --tests 通过;cargo fmt --check 通过
2026-10-01 17:51:44 +08:00
k88936 7d51504e09 不认识的字段名回显限长到 120 字符,回显口径收进 tool/error.rs
- ToolArgumentsRejection::check 构造 UnknownField 时改成 bounded_echo(field),超长键名不再整份进文案与诊断
- 有界回显的常量与 bounded_echo 从 arguments.rs 移到公共 tool/error.rs(BOUNDED_ECHO_MAX_CHARS=120),not_text_repr 变成它的 JSON 值封装,实现仍只有一份

验证:cargo check --bin genarrative-ai-game-creator-shell --tests 通过;cargo fmt --check 通过
2026-10-01 17:50:57 +08:00
k88936 0e60ecb769 共享入参解析器补「入参必须是对象」的契约断言与文档
- optional_text/required_text/page 加 debug_assert!(arguments.is_object()):非对象时 Value::get 恒为 None,会把 NotObject 静默判成「没给字段」或默认分页
- 文档写明调用方必须先跑 ToolArgumentsRejection::check;所有现有调用点已满足,release 行为不变

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: agent::direct_tools_mcp:: 72 passed / 0 failed;cargo fmt --check 通过
2026-10-01 17:49:25 +08:00
k88936 b7d77053ea 分页 offset/limit 的类型错回显改用 not_text_repr,与其它字段同一限长口径
- arguments::page 的 OffsetNotInteger / LimitNotInteger 原来用 value.to_string() 无界回显,超大对象/字符串会整份进错误消息与诊断
- 改用共享的 not_text_repr(120 字符截断),与 optional_text 及内联判类型的字段一致

验证:cargo fmt --check 通过
2026-10-01 17:47:23 +08:00
k88936 ae3811a8aa 部分导入按失败回的口径落注释:不再按 write_permit 区分 isError
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m35s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m19s
Project CI / Backend tests (pull_request) Failing after 18s
Project CI / Frontend tests (pull_request) Successful in 2m0s
Project CI / Repository checks (pull_request) Failing after 21s
Project CI / AI game creator shell web tests (pull_request) Successful in 1m48s
Project CI / Native shell tests (pull_request) Successful in 5m44s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 10m38s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 11m15s
- bridge_import_account_assets 的 failed/partial 分支补注释,说明 partial 与 failed 一样按失败回是有意为之,口径已确认
- 只加注释,不改行为:report 仍在消息里,Direct 回合与外部 MCP 客户端的 isError 保持一致
2026-10-01 17:16:36 +08:00
k88936 ede3457464 edit_image 的派生失败转发内层前缀:补注释说明这是有意为之
- ResourceEdit 继续原样转发 CreateOrDeriveResourceError 的「生成或派生资源失败:…」,不改文案
- 注释写清理由:该路径与 agc_create_or_derive_resource 同源,内层文案指向真实失败环节;调用方身份由运行时错误事件的 code(工具名)承担,不靠前缀区分工具
2026-10-01 17:13:44 +08:00
k88936 5b59d50a8c 错误事件 sidecar 的 error 字段递归脱敏,保留 typed 错误的 JSON 形状
- persist_agent_runtime_error 落盘前对 error 的字符串叶子走与 message 同一条脱敏流水线(URL/项目路径/绝对路径/密钥),键、类型、数组长度都不动
- 每个叶子有 4000 字符预算(AGENT_RUNTIME_ERROR_MAX_ERROR_TEXT_CHARS),sidecar 本身的 16 KiB 上限不变
- 返回的 AgentRuntimeErrorEvent.error 与落盘内容一致;应用日志那条 error 行原本就已脱敏,行为不变
- 新增回归测试:形状留住(变体名/字段名/数字/布尔),叶子脱敏(<absolute-path>、<redacted-url>、无 token)
- 更新原测试里「typed 错误原样进 sidecar」的注释

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::runtime_error:: 4 passed / 0 failed;cargo fmt --check 通过
2026-10-01 17:12:32 +08:00
k88936 c7da67ed47 非字符串回显限长补齐到内联判类型的四处(承接上一提交)
- arguments.rs 导出 not_text_repr,optional_text 与内联判类型的字段共用同一份截断口径
- 抠图 backgroundMode / screenColor、美术准备 mode、生成图片 kind 这四处原来直接 value.to_string(),现在同样限长到 120 字符
- 测试补一条:art_preparation_mode 的超大数组回显必须带截断标记且长度可控

验证:cargo test --bin genarrative-ai-game-creator-shell -- non_text_field_values 通过;cargo fmt --check 通过
2026-10-01 16:55:29 +08:00
k88936 a22e3448a6 抠图的 backgroundMode / screenColor 类型错改成「必须是字符串」
- BackgroundModeNotText、ScreenColorNotText 只在入参不是字符串时触发,文案却回的是取值白名单,模型会以为类型对了、只是值不对
- 改成与本模块其它 *NotText 变体一致的「必须是字符串」;取值白名单仍由 BackgroundModeUnsupported / ScreenColorMalformed 承担
- 文案字面变化:backgroundMode「必须是 complex 或 flat」→「必须是字符串」;screenColor「必须是 auto 或 #RRGGBB」→「必须是字符串」

验证:cargo fmt --all --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --check 通过
2026-10-01 16:52:42 +08:00
k88936 97c3fc83c1 非字符串入参的回显截断到 120 字符,不再把整个对象原样带进诊断
- arguments::optional_text 里的 not_text 改为传截断后的序列化值:类型错只需要看出「传了什么」
- got 同时出现在 to_user_msg 与序列化 error 里,限长后工具结果与诊断 sidecar 都不会被超大数组/对象灌爆
- 复用 runtime_state::truncate_agent_runtime_text,不新增第二套截断实现
- 测试补一条:超大数组回显必须带截断标记且长度可控

验证:cargo test --bin genarrative-ai-game-creator-shell -- non_text_field_values 通过;cargo fmt --check 通过
2026-10-01 16:51:50 +08:00
k88936 8834f844e6 分页助手加 debug_assert,默认 limit 配到上限之上会在测试期炸出来
- arguments::page 增加 debug_assert!(default_limit <= max_limit):默认值本身越界时不再让省略 limit 的请求静默地每次都报 LimitOutOfRange
- 文档注释写清这条调用点契约;三个列表工具当前都满足(50/100 对 100)

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: agent::direct_tools_mcp:: 72 passed / 0 failed;cargo fmt --check 通过
2026-10-01 16:47:32 +08:00
k88936 9bdeed13a0 kind 白名单从 DirectResourceGenerationKind::ALL 取,删掉第二份字符串清单
- DirectResourceGenerationKind 新增 ALL: [Self; 5],顺序与 parse/as_str 一致
- KindUnsupported 的「只允许 …」改为由 ALL 生成,新增 kind 时不再需要手动同步这句文案
- 文案字面不变:image、video、character-animation、sound-effect、background-music

验证:cargo fmt --all --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --check 通过
2026-10-01 16:45:10 +08:00
k88936 3c2dc57c57 未登记资源指引抽到 tool/error.rs,生成与抠图共用同一份文案
- UNREGISTERED_SOURCE_HINT 从 create_or_derive_resource/error.rs 移到公共 tool/error.rs
- remove_background 的 SourceAssetNotRegistered 改为拼接同一常量,去掉逐字复制的副本
- 两个工具的 SourceAssetNotRegistered 文案字面不变(前缀各自保留「生成或派生资源失败:」/「抠图失败:」)
- remove_background/error.rs 一处 format! 收口改动使该 match 触发 rustfmt 重排,随该文件一并 rustfmt(只此一个文件,其余文件未动)

验证:cargo fmt --all --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml -- --check 通过
2026-10-01 16:44:25 +08:00
k88936 6a1973b0e3 Merge remote-tracking branch 'origin/master' into feat/typed-tool-error
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m44s
Project CI / AI game creator shell Rust smoke (pull_request) Successful in 2m19s
Project CI / Backend tests (pull_request) Successful in 3m55s
Project CI / Frontend tests (pull_request) Successful in 2m16s
Project CI / Native shell tests (pull_request) Successful in 6m55s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Successful in 10m2s
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Successful in 10m28s
Project CI / Repository checks (pull_request) Successful in 2m57s
Project CI / AI game creator shell web tests (pull_request) Successful in 2m18s
# Conflicts:
#	apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs
#	docs/project-memory/shared-memory/decision-log.md
2026-10-01 16:04:30 +08:00
k88936 a723d10ce3 回退列表工具 offset 上限的收窄,agc_list_registered_assets 恢复无上限
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Failing after 38s
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Failing after 47s
Project CI / AI game creator shell Rust smoke (pull_request) Failing after 43s
Project CI / Backend tests (pull_request) Failing after 15s
Project CI / AI game creator shell Rust crates (pull_request) Successful in 1m17s
Project CI / Repository checks (pull_request) Failing after 28s
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
- 回退 4e5adb2a3:page 的 max_offset 恢复成 Option<usize>,删掉 TOOL_PAGE_MAX_OFFSET 常量
- agc_list_registered_assets 传 None(offset 无上限,与它原本的行为一致),agc_list_project_files / agc_list_account_assets 仍传原来的 Some(500)
- agc_list_registered_assets 的 inputSchema offset 去掉 maximum: 500,恢复到原公开入参范围

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: 41 passed / 0 failed
2026-10-01 15:56:49 +08:00
k88936 75d9e25634 首尾换行回到按空白裁剪,不再当控制字符报错
- 回退 3f70c6911 的收紧:optional_text 恢复成先 trim、再查 is_control
- prompt 末尾带 \n(\r\n 等)视为普通首尾空白裁掉,与首尾空格同口径;中间的控制字符仍然报 has_control_characters
- 测试改为断言行尾换行被接受且裁成 "生成过场",另加一条中间换行仍被拒的断言

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: 41 passed / 0 failed
2026-10-01 15:56:12 +08:00
k88936 7c67a6fcc0 agc_generate_image 的 kind 传了非字符串不再静默当成 image
- bridge_image_generation_kind 原来用 and_then(Value::as_str)…unwrap_or("image"):{"kind":true}、{"kind":5}、{"kind":[]} 都会被当成 image 继续生成;空串也会被静默当默认值
- 改成按 schema 语义区分:缺省与显式 null 用默认 image;字符串按原值走 canonical 校验(空串/未知值走 KindUnsupported);其它类型返回新的 GenerateImageError::KindNotText { got }
- 测试补四条断言:kind=true 报「kind 必须是字符串」、kind="" 报「不是受支持的素材类型」、缺省与 null 仍解析为 image

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: 41 passed;agent:: tests::project:: 1078 passed(两条失败为既有 flaky:art_director_request_exposes_canvas_only_for_the_keyed_owner_route / background_agent_runtime_can_generate_platform_art_asset,单独重跑通过)
2026-10-01 15:39:56 +08:00
lhk229 55375b1406 清理测试编译warning (#509)
Project CI / AI game creator shell Rust crates (push) Successful in 1m18s
Project CI / AI game creator shell Rust smoke (push) Successful in 1m30s
Project CI / Backend tests (push) Successful in 3m58s
Project CI / AI game creator shell Rust lane 1/2 (push) Successful in 10m12s
Project CI / Native shell tests (push) Successful in 5m49s
Project CI / Frontend tests (push) Successful in 2m18s
Project CI / AI game creator shell Rust lane 2/2 (push) Successful in 9m50s
Project CI / AI game creator shell web tests (push) Failing after 2m11s
Project CI / Repository checks (push) Successful in 2m55s
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/509
Co-authored-by: Linghong <ink29535@proton.me>
Co-committed-by: Linghong <ink29535@proton.me>
2026-10-01 15:29:23 +08:00
k88936 3f70c69119 首尾的控制字符不再被 trim 静默吞掉,统一按控制字符报错
- optional_text 原来先 trim 再查 is_control:`"prompt\n"`、`"\tprompt"` 这类落在首尾的控制字符被静默裁掉、当成合法值,而同一个字符出现在中间却会报错
- 改成先按原串查控制字符,再用 trim 做空值与长度判定:控制字符在哪个位置都报 has_control_characters
- 纯空白值("\n\t"、"   ")仍然算空值、报原来的 empty 错误;首尾的普通空格仍按原样裁掉
- 测试补三条断言:prompt 末尾带 \n 必须被拒、纯空白 brief 仍报空、brief 首尾普通空格仍会被裁剪

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent:: 953 passed / 0 failed
2026-10-01 15:18:02 +08:00
k88936 66e4ece692 入参给了非字符串值时按字段报类型错,不再混进「不能为空」
- ToolTextField 增加 not_text(got),optional_text 在 as_str() 失败时返回它;原来数字/布尔/数组/对象会和空串、null 一起落到 field.empty(),{"prompt":5} 报成「prompt 不能为空」
- 9 个工具 enum 按字段各加一个 NotText 变体(KindNotText、PromptNotText、AspectRatioNotText…),文案形如「生成图片失败:aspectRatio 必须是字符串,当前是「5」。」,仍是一 case 一变体、文案写在变体上
- GenerateImageTextField 改为实现 ToolTextField,删掉 generate_image_optional_text / generate_image_required_text 这两份与共享实现重复的拷贝,generate_image 改走 optional_text / required_text
- 空串 / null / 缺省仍按原来的空值语义处理,只有「有值但不是字符串」换成类型错
- 新增 non_text_field_values_report_a_type_error_instead_of_an_empty_value 覆盖 create_or_derive、prepare_game_art、generate_image 三条路径

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: 41 passed;全量 agent:: 952 passed(唯一失败 concurrent_distinct_frozen_root_steers_create_only_one_replacement 是既有 flaky,单独重跑通过)
2026-10-01 15:01:20 +08:00
k88936 4e5adb2a30 分页 offset 上限收成必填参数与单一常量,三个列表工具口径一致
- arguments::page 的 max_offset 由 Option<usize> 改成 usize:调用点必须显式给出上限,不能靠漏传 Option 变成无上限
- 新增 TOOL_PAGE_MAX_OFFSET = 500(与 agc_list_project_files / agc_list_account_assets 的 inputSchema offset.maximum 一致),三个列表工具统一传它;agc_list_registered_assets 原来传 None(无上限),现在同样收敛到 500
- agc_list_registered_assets 的 inputSchema offset 同步补 maximum: 500,保持 schema 与校验一致(这是一个公开入参范围的收窄)
- 只改 offset 边界来源;limit 默认值与上限、分页语义不变

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent:: 952 passed / 0 failed
2026-10-01 14:41:17 +08:00
k88936 1359c7c2b3 去掉 list_registered_assets 的 kind 错误里那份会漂移的示例清单
- KindNotManifestClass 原文案列举 9 个示例 kind,而真实白名单是 GameCreationAppAssetKind 的 19 个值,枚举演进后没人会回来同步这句
- 按「不维护第二份清单」的口径,文案只保留「必须用 canonical kind」,取值示例由 kind 参数的 schema description(direct-tools.json 的 agc_list_registered_assets.parameters.kind)承担
- 只改文案,判定逻辑不变

验证:cargo check --bin genarrative-ai-game-creator-shell --tests 通过
2026-10-01 14:37:03 +08:00
k88936 0d21f838ed 生成图片的允许值与边界提成常量,校验与诊断文案共用同一份
- 新增 GENERATE_IMAGE_ASPECT_RATIOS / _IMAGE_SIZES / _SLICE_MODES 与 grid 轴、sliceCount 的 MIN/MAX 常量,放在 direct_tool_bridge 的 GENERATE_IMAGE_ARGUMENTS 旁
- generate_image_input 的 aspectRatio / imageSize / sliceMode / grid 轴区间 / sliceCount 区间校验改为读常量;generate_image/error.rs 的对应文案也改为读同一批常量(KindUnsupported 早已从 PLATFORM_ART_ASSET_GENERATION_KINDS 派生,这次把其余几组对齐)
- 只改取值来源,判定范围与文案取值不变
- 未纳入本次:commands.rs 的 LOCAL_PROJECT_ASSET_ASPECT_RATIOS/_IMAGE_SIZES 与 agent_native_tools.rs 的 canvas.asset_generate schema 仍是各自的副本(面向非 agent 的栏目画布入口),统一它们属于另一次改动

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: agent::direct_tools_mcp:: 71 passed
2026-10-01 14:35:53 +08:00
k88936 235adde72c 联网搜索响应超限的诊断带上实际收到的字节数
- WebSearchError::ResponseTooLarge 原来只记 max_bytes,用户只看到「超过上限 524288 bytes」,不知道实际多大
- 两个构造点都已拿到真实大小:content_length() 与 bytes.len() + chunk.len(),变体加 got_bytes 并写进文案
- 判定与两个构造点位置不变,仅补上实际值

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge::tests::search_parser_accepts_only_bounded_public_https_results 通过
2026-10-01 14:14:29 +08:00
k88936 23a111985a 联网搜索 maxResults 非整数的诊断上限改为随变体携带,不再写死 5
- WebSearchError::MaxResultsNotInteger 原文案把上限写死成「1 到 5」,同一份文件里 MaxResultsOutOfRange 却是从 DIRECT_TOOL_BRIDGE_MAX_SEARCH_RESULTS 取 {max};常量一改,两条诊断就会自相矛盾
- 变体加上 max: u64,构造点传 DIRECT_TOOL_BRIDGE_MAX_SEARCH_RESULTS as u64,文案改成「1 到 {max}」
- 只影响这一条诊断的取值来源,判定区间不变

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge::tests::search_parser_accepts_only_bounded_public_https_results 通过
2026-10-01 14:11:27 +08:00
k88936 b2d01ef8c1 write_file 入参形状校验收进 write_file_input,MCP 预检不再漏掉未知字段
- 其它 *_input 解析器都先调 ToolArgumentsRejection::check,只有 write_file_input 没有;工具桥路径靠 bridge_write_file_with_permit 里另一次 check 兜住,但独立客户端 MCP 预检 validate_write_file_arguments 只调 write_file_input,带未知字段的入参能通过预检、要等回客户端桥才被拒
- 在 write_file_input 开头补上同一份 check(path/content 白名单),两个入口共用一条规则;写文件门禁里的那次 check 保留,保证「先查形状、再过权限」的现有顺序不变
- 测试补一条:{"path":"game/index.html","content":"…","unexpected":1} 必须被 validate_write_file_arguments 拒绝

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge:: 40 passed;agent::direct_tools_mcp::tests::tool_catalog_preserves_reviewed_resource_contracts 通过
2026-10-01 14:08:52 +08:00
k88936 c9e4a7e397 美术准备模式缺省时直接构造 ReuseOrCreate,去掉生产路径的 expect
- art_preparation_mode 在 mode 缺省时走 from_tool_value(None).expect("default art preparation mode"),依赖「None 必然映射为 ReuseOrCreate」这条隐式不变式
- 缺省值就是 ReuseOrCreate,直接返回该变体即可;显式传入 mode 的解析路径不变,少一条潜在 panic 分支
- bridge_argument_bounds_are_deterministic 断言缺省模式仍为 ReuseOrCreate,继续通过

验证:cargo check --bin genarrative-ai-game-creator-shell --tests;cargo test -- agent::direct_tool_bridge::tests::bridge_argument_bounds_are_deterministic 通过
2026-10-01 14:03:43 +08:00
k88936 822e89bdc0 生成图片的 gridX/gridY 解析不再把超大整数截断成合法网格
- generate_image_grid_axis 原来用 `value as u32`,u64 直接截断:4294967297(2^32+1)会变成 1,随后 1..=32 的区间校验把这个巨大输入当成合法网格静默接受
- 改成 u32::try_from,超出 u32 的值直接落到 GridAxisNotInteger 拒绝分支,不再依赖截断后的值
- 补一条回归测试:gridX=4294967297 必须被拒绝,gridX=4/gridY=4 仍通过

验证:cargo test --bin genarrative-ai-game-creator-shell -- agent::direct_tool_bridge::tests::generate_image_grid_axis_rejects_values_beyond_u32 通过
2026-10-01 14:00:03 +08:00
k88936 28f6ddc7dc 去掉权限策略不可用诊断里重复的「读取项目权限策略失败」前缀
- ProjectPermissionRejection::PolicyUnavailable 的 cause 来自 read_project_permission_policy_at,本身多数已带「读取/解析项目权限策略失败:」,包装文案再拼一次会得到「读取项目权限策略失败,无法确认……:读取项目权限策略失败:…」
- 包装文案只保留「无法确认该动作是否被允许,本次操作未执行:」,cause 原样保留;判定与变体结构不变

验证:cargo check --bin genarrative-ai-game-creator-shell --tests 通过
2026-10-01 13:53:06 +08:00
k88936 6788a75ca6 分页 limit 的诊断改成「非负整数」,与 offset 保持一致
- ToolPageRejection::LimitNotInteger 原文案说 limit「必须是整数」,但负数(如 -1)走到这个分支时本身就是整数,读起来自相矛盾
- 解析用的是 as_u64,真实约束是非负;文案改成与 OffsetNotInteger 相同的「非负整数」,只改措辞,判定与变体结构不变

验证:cargo check --bin genarrative-ai-game-creator-shell --tests 通过
2026-10-01 13:52:52 +08:00
k88936 cf90d7a8db 修正美术重生成「已绑定另一项美术重生成请求」文案里多余的「稳定」
- prepare_game_art/error.rs 的 BoundToAnotherBrief 变体描述的是当前客户端回合已绑定另一项美术重生成请求,「稳定」是残留错译,会让模型误以为存在「稳定/不稳定」两种请求
- 只改这一处用户可见文案,判定逻辑与变体结构不变

验证:cargo check --bin genarrative-ai-game-creator-shell --tests 通过
2026-10-01 13:52:29 +08:00