删除 DirectProject 图片专用 content part
- 移除 DirectCodexUserContentPart 的 agc_image_reference 分支与对应 ts-rs 绑定 - Rust 校验与 Codex wire 投影只保留 agc_attachment_reference - 更新附件顺序投影测试的用例名、输入与断言 - 同步聊天素材功能说明、用户 Response item 里程碑与实施计划 - 在决策日志记录上传文件统一走附件 part、不保留图片兼容分支
This commit is contained in:
@@ -39,8 +39,6 @@ pub(crate) enum DirectCodexUserContentPart {
|
||||
/// Uploaded project attachment kept inline in canonical content.
|
||||
#[serde(rename = "agc_attachment_reference")]
|
||||
AgcAttachmentReference(DirectCodexUserAttachmentReferencePart),
|
||||
#[serde(rename = "agc_image_reference")]
|
||||
AgcImageReference(DirectCodexUserAttachmentReferencePart),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, TS)]
|
||||
|
||||
@@ -40,8 +40,7 @@ pub(crate) fn validate_direct_codex_user_item(
|
||||
reference_count = reference_count.saturating_add(1);
|
||||
validate_runtime_region_reference(&manifest, reference)?;
|
||||
}
|
||||
DirectCodexUserContentPart::AgcAttachmentReference(reference)
|
||||
| DirectCodexUserContentPart::AgcImageReference(reference) => {
|
||||
DirectCodexUserContentPart::AgcAttachmentReference(reference) => {
|
||||
if reference.name.trim().is_empty() {
|
||||
return Err("附件缺少文件名".to_string());
|
||||
}
|
||||
|
||||
@@ -100,8 +100,7 @@ pub(crate) fn direct_codex_user_item_to_wire_input(
|
||||
summary.push(']');
|
||||
summary
|
||||
}
|
||||
DirectCodexUserContentPart::AgcAttachmentReference(reference)
|
||||
| DirectCodexUserContentPart::AgcImageReference(reference) => {
|
||||
DirectCodexUserContentPart::AgcAttachmentReference(reference) => {
|
||||
let mut summary = format!(
|
||||
"[附件:名称={};类型={};大小={} 字节",
|
||||
reference.name.trim(),
|
||||
@@ -191,7 +190,7 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_and_image_parts_remain_in_canonical_order_when_projected() {
|
||||
fn attachment_parts_remain_in_canonical_order_when_projected() {
|
||||
let root = tempfile::tempdir().expect("temp project");
|
||||
crate::init_local_game_project_at(root.path(), "wire-test", "wire 投影测试")
|
||||
.expect("init project");
|
||||
@@ -201,16 +200,14 @@ mod tests {
|
||||
"id": "turn-1:user",
|
||||
"content": [
|
||||
{"type": "input_text", "text": "先看"},
|
||||
{"type": "agc_image_reference", "name": "hero.png", "mediaType": "image/png", "size": 12, "localPath": "assets/hero.png", "status": "imported"},
|
||||
{"type": "agc_attachment_reference", "name": "notes.txt", "mediaType": "text/plain", "size": 4, "localPath": "assets/notes.txt", "status": "imported"}
|
||||
]
|
||||
});
|
||||
let projected = direct_codex_user_item_to_response_item(root.path(), &item)
|
||||
.expect("user response item should project");
|
||||
let content = projected["content"].as_array().expect("content array");
|
||||
assert_eq!(content.len(), 3);
|
||||
assert_eq!(content.len(), 2);
|
||||
assert!(content[0]["text"].as_str().unwrap().contains("先看"));
|
||||
assert!(content[1]["text"].as_str().unwrap().contains("hero.png"));
|
||||
assert!(content[2]["text"].as_str().unwrap().contains("notes.txt"));
|
||||
assert!(content[1]["text"].as_str().unwrap().contains("notes.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -10,5 +10,4 @@ export type DirectCodexUserContentPart =
|
||||
} & DirectCodexUserRuntimeRegionPart)
|
||||
| ({
|
||||
type: 'agc_attachment_reference';
|
||||
} & DirectCodexUserAttachmentReferencePart)
|
||||
| ({ type: 'agc_image_reference' } & DirectCodexUserAttachmentReferencePart);
|
||||
} & DirectCodexUserAttachmentReferencePart);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
- 允许修改:AGC 壳 Rust agent 输入合同、DirectProject 历史适配、前端聊天引用模型、ts-rs 生成配置、当前聊天素材文档。
|
||||
- 明确不修改:assistant 返回协议、工具 activity、附件/图片上传 DTO、SpacetimeDB、HTTP API;上传 DTO 仅在入口转换为 canonical `content[]`,不再以 sidecar 文本追加。
|
||||
- 本切片明确:不根据 MIME 类型判断图片,不生成 `agc_image_reference`;所有上传文件统一映射为 `agc_attachment_reference`。
|
||||
|
||||
## 实现顺序
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
- `agc_runtime_region_reference` 保留运行区域语义摘要。
|
||||
- Rust 在持久化前完成白名单、manifest 与路径校验。
|
||||
- 现有标准 `response_item` 原样兼容;legacy conversation 行不提供 fallback。
|
||||
- 保持 assistant 返回、工具 activity 与上传 DTO 不变;但 DirectProject canonical user item 不再保存附件 sidecar,附件和图片必须作为 `content[]` 中按顺序排列的 `agc_attachment_reference` / `agc_image_reference`。
|
||||
- 保持 assistant 返回、工具 activity 与上传 DTO 不变;DirectProject canonical user item 不再保存附件 sidecar,所有本地上传文件(包括图片)统一作为 `content[]` 中按顺序排列的 `agc_attachment_reference`。
|
||||
|
||||
## 不在范围内
|
||||
|
||||
- assistant item 前端投影或 Tauri 返回值改造。
|
||||
- 工具 item、reasoning、file change、MCP item 的 UI 模型化。
|
||||
- 附件/图片 content part:本里程碑明确新增并生成绑定;上传 DTO 只作为输入适配,不作为历史事实源。
|
||||
- 不新增图片专用 content part;上传 DTO 只作为输入适配,不作为历史事实源。
|
||||
- SpacetimeDB schema 或 HTTP API 变更。
|
||||
|
||||
## 依赖与前置条件
|
||||
@@ -42,7 +42,7 @@
|
||||
- [x] 未知 part、失效资源或非法路径在持久化前失败关闭。
|
||||
- [x] canonical item 以 `response_item` 写入历史,标准旧 item 原样可读。
|
||||
- [x] Codex wire input 不含 AGC 私有 part,且顺序与 canonical content 一致。
|
||||
- [x] assistant、附件和工具链路行为无变化;附件与图片按 content 顺序内联,附件-only 输入也能进入 DirectProject prompt。
|
||||
- [x] assistant、附件和工具链路行为无变化;所有上传文件按 content 顺序内联,附件-only 输入也能进入 DirectProject prompt。
|
||||
|
||||
## 证据要求
|
||||
|
||||
|
||||
@@ -8769,3 +8769,9 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
|
||||
|
||||
- 决策:采用后台继续运行语义。Direct 回合由进程内项目身份锁持有,页面离开不取消;重进项目通过活动回合只读快照与 Thread Manager bootstrap/consume 恢复忙碌态和进度。左上角面板复用同一快照列出正在运行的 Direct 项目并支持进入。
|
||||
- 边界:快照不写项目文件、不进入公共 API、不跨应用重启恢复;读取失败保留上一份结果并单独提示,不改写成权限或审批失败。身份锁排他性、付费身份和项目写锁不变。
|
||||
|
||||
## 2026-09-16 DirectProject 上传文件统一使用附件 content part
|
||||
|
||||
- 决策:DirectProject 本地上传不区分图片与其它文件。用户使用同一个文件入口,前端不按 `mediaType` 做图片判断,所有上传文件统一写成 `agc_attachment_reference`;项目资源 `@` 引用仍使用 `agc_resource_reference`。
|
||||
- 原因:原 `agc_image_reference` 与附件 payload 完全相同,Rust wire 投影也把两者合并成同一段文本,不能代表真实的多模态图片输入。保留该 discriminator 只会制造错误语义。
|
||||
- 边界:本次不新增 `input_image`,不保留图片类型兼容分支,不迁移旧历史;图片多模态能力未来单独设计独立 payload 与 wire 投影。
|
||||
|
||||
@@ -15,6 +15,8 @@ AGC 聊天输入框支持以结构化引用标记当前项目已登记素材。
|
||||
|
||||
提交时前端把 Lexical 草稿直接编码为受限 Response API user `message` item:`input_text` 与 AGC 引用 part 按编辑顺序内联在同一个 `content[]` 中。资源引用只携带稳定 `resourceId`;运行画面引用携带区域语义摘要及关联资源 ID。Rust 是唯一 schema source(通过 `ts-rs` 生成 TypeScript 绑定),在发起回合前完成 item 白名单、字段边界、manifest 归属和路径安全校验;校验失败时本轮不持久化、不发送。通过校验的 canonical item 以 `response_item` envelope 写入项目历史,随后由 Rust 将 AGC part 临时转换为 Codex 可接受的 `input_text`,保持原始 content 顺序。已有标准 `response_item` 原样读取与复用;旧 legacy conversation 行不再提供 fallback。
|
||||
|
||||
本地上传入口不区分图片和其它文件:用户从同一个文件选择器提交任意附件,前端不做 MIME 类型分流,所有上传文件统一编码为 `agc_attachment_reference`。图片不会因为扩展名或 MIME 类型获得另一种 canonical part;只有未来真正支持 Codex 多模态 `input_image` 投影时,才另行设计图片协议。
|
||||
|
||||
当前已完成:
|
||||
|
||||
- 三个聊天入口共用 `ResourceReferenceInput`;
|
||||
|
||||
Reference in New Issue
Block a user