修正 Response item content 类型投影

区分 turn/start 的 text 与历史 message 的 input_text

将 AGC 私有引用转换为标准 input_text

新增回归测试避免未知 variant text
This commit is contained in:
2026-09-15 16:57:04 +08:00
committed by kdletters
parent 051c2ec898
commit 6f23293ca5
@@ -20,9 +20,7 @@ pub(crate) fn direct_codex_user_item_to_response_item(
}
let canonical: DirectCodexUserItem = serde_json::from_value(item.clone())
.map_err(|error| format!("DirectProject user item 无法转换为 Codex item{error}"))?;
let Value::Array(content) = direct_codex_user_item_to_wire_input(root, &canonical)? else {
return Err("DirectProject user item wire content 不是数组".to_string());
};
let content = direct_codex_user_item_to_response_content(root, &canonical)?;
let mut projected = serde_json::json!({
"type": "message",
"role": "user",
@@ -34,6 +32,25 @@ pub(crate) fn direct_codex_user_item_to_response_item(
Ok(projected)
}
fn direct_codex_user_item_to_response_content(
root: &Path,
item: &DirectCodexUserItem,
) -> Result<Vec<Value>, String> {
let Value::Array(input) = direct_codex_user_item_to_wire_input(root, item)? else {
return Err("DirectProject user item wire content 不是数组".to_string());
};
input
.into_iter()
.map(|part| {
let text = part
.get("text")
.and_then(Value::as_str)
.ok_or_else(|| "DirectProject user item wire part 缺少 text".to_string())?;
Ok(serde_json::json!({ "type": "input_text", "text": text }))
})
.collect()
}
/// 将 canonical user item 转为 app-server `turn/start.input` 可接受的文本数组。
/// AGC 私有 part 只在这里投影为安全摘要,canonical item 本身不被修改。
pub(crate) fn direct_codex_user_item_to_wire_input(
@@ -131,6 +148,23 @@ mod tests {
);
}
#[test]
fn response_item_projection_uses_input_text_not_turn_input_text() {
let root = tempfile::tempdir().expect("temp project");
crate::init_local_game_project_at(root.path(), "wire-test", "wire 投影测试")
.expect("init project");
let item = json!({
"type": "message",
"role": "user",
"id": "turn-1:user",
"content": [{"type": "input_text", "text": "你好"}]
});
let projected = direct_codex_user_item_to_response_item(root.path(), &item)
.expect("user response item should project");
assert_eq!(projected["content"][0]["type"], "input_text");
assert_ne!(projected["content"][0]["type"], "text");
}
#[test]
fn history_item_without_type_fails_closed() {
let error = direct_codex_user_item_to_response_item(