修复 AGC Claude 执行认证与错误诊断

官方 Claude 模型复用当前平台会话令牌

保留 Claude 失败终态摘要并增加回归测试

补充 AGC 排障记忆
This commit is contained in:
kdletters
2026-10-01 13:21:57 +08:00
parent 66ff5bf4b7
commit 127def0a8a
2 changed files with 70 additions and 4 deletions
@@ -385,12 +385,44 @@ fn configure_claude_code_environment(
{
command.env("ANTHROPIC_AUTH_TOKEN", llm.api_key.trim());
}
// Official AGC model entries use the account session rather than a
// user-supplied API key. The Claude SDK only reads Anthropic auth
// from its child-process environment, so bridge the already-held
// platform token without persisting or exposing it in argv/logs.
if llm.api_key.trim().is_empty()
&& !llm.custom_enabled
&& std::env::var_os("ANTHROPIC_API_KEY").is_none()
&& std::env::var_os("ANTHROPIC_AUTH_TOKEN").is_none()
{
if let Some(session) = crate::platform_session::current_platform_session() {
command.env("ANTHROPIC_AUTH_TOKEN", session.access_token);
}
}
if !llm.model.trim().is_empty() {
command.env("ANTHROPIC_MODEL", llm.model.trim());
}
}
}
fn claude_result_error_detail(value: &serde_json::Value) -> Option<String> {
let candidates = [
value.get("result").and_then(serde_json::Value::as_str),
value.get("error").and_then(serde_json::Value::as_str),
value.get("message").and_then(serde_json::Value::as_str),
value
.get("errors")
.and_then(serde_json::Value::as_array)
.and_then(|errors| errors.first())
.and_then(serde_json::Value::as_str),
];
candidates
.into_iter()
.flatten()
.map(str::trim)
.find(|detail| !detail.is_empty())
.map(|detail| detail.chars().take(512).collect())
}
fn configure_claude_code_process(command: &mut tokio::process::Command) {
super::codex_cli::configure_game_creator_codex_cli_process(command);
}
@@ -495,9 +527,12 @@ fn parse_claude_code_result(
platform_llm::LlmError::Deserialize("Claude Code JSON 输出无效".to_string())
})?;
if value.get("is_error").and_then(serde_json::Value::as_bool) == Some(true) {
return Err(platform_llm::LlmError::Transport(
"Claude Code 返回失败终态".to_string(),
));
let detail = claude_result_error_detail(&value)
.map(|detail| format!(":{detail}"))
.unwrap_or_default();
return Err(platform_llm::LlmError::Transport(format!(
"Claude Code 返回失败终态{detail}"
)));
}
let response_id = value
.get("session_id")
@@ -829,7 +864,10 @@ fn parse_direct_stream_result(
}
} else if event_type == Some("result") {
if event.get("is_error").and_then(serde_json::Value::as_bool) == Some(true) {
return Err("Claude Code 返回失败终态".to_string());
let detail = claude_result_error_detail(&event)
.map(|detail| format!(":{detail}"))
.unwrap_or_default();
return Err(format!("Claude Code 返回失败终态{detail}"));
}
result = event
.get("result")
@@ -884,6 +922,16 @@ mod tests {
assert_eq!(response.tool_calls[0].name, "runtime_tool_file_read");
}
#[test]
fn preserves_claude_terminal_error_detail() {
let error = parse_claude_code_result(
br#"{"is_error":true,"result":"Authentication failed"}"#,
&request(false),
)
.expect_err("failed terminal must be rejected");
assert!(error.to_string().contains("Authentication failed"));
}
#[test]
fn parses_direct_stream_result_and_final_text() {
let mut observed = Vec::new();
@@ -903,4 +951,16 @@ mod tests {
[DirectCodexTurnObservation::AgentMessageSegment { .. }]
));
}
#[test]
fn preserves_direct_stream_terminal_error_detail() {
let error = parse_direct_stream_result(
br#"{"type":"result","is_error":true,"result":"Authentication failed"}
"#,
"turn-1",
None,
)
.expect_err("failed terminal must be rejected");
assert!(error.contains("Authentication failed"));
}
}
@@ -6158,3 +6158,9 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/`
- **同时**:主站顶栏(`platform-desktop-topbar`)在窄屏必须保持单行——加 `flex-wrap` 后新增一个动作入口就会让品牌折到第二行;窄屏降级靠 `< 640px` 图标化下载入口、`< 480px` 只留品牌 IP 标识。
- **验证**:真机尺寸下用 `document.elementFromPoint(按钮中心)` 断言命中的是按钮自身而不是底部菜单(`overlay.parentElement === document.body`);顶栏断点矩阵(320–768)断言单行且无横向溢出。
- **关联**:`src/components/common/SquareImageCropModal.tsx`、`src/components/platform-entry/PlatformProfileModalShell.tsx`、`src/components/platform-entry/PlatformEntryActiveFlowShell.tsx`、`src/index.css`。
## 2026-10-01 AGC 官方 Claude 模型缺少账号令牌会被误报为通道断开
- **现象**:模型目录把回合路由到 `cc`,本地 `game-creator.config.json` 的 `llm.apiKey` 为空时,Claude Agent SDK 返回失败终态;界面只显示“执行通道未能建立或已断开”。
- **根因**:Claude sidecar 只从 `ANTHROPIC_API_KEY` / `ANTHROPIC_AUTH_TOKEN` 或本地 `llm.apiKey` 读取认证,没有复用已登录的 AGC 平台会话;同时失败终态解析丢弃了上游错误摘要。
- **处理**:官方模型且未启用自定义目录时,将当前平台会话令牌仅注入 sidecar 子进程环境;保留最多 512 字符的 Claude 终态错误摘要,继续由统一诊断层脱敏,避免凭据落盘。