diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index 3fc57c933..44366fdb3 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -6595,6 +6595,15 @@ Cocos Creator 根目录由 `package.json.creator.version` 与普通 `assets/` - **验证**:`cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --features=cocos-editor-execute,unity-editor-execute,godot-editor-execute --bin genarrative-ai-game-creator-shell claude_` 34 passed(新增 `claude_code_session_lookup_uses_the_project_directory_and_newest_trace`、`claude_direct_resume_falls_back_to_disk_and_prefers_the_process_map`)。真实环境用随包 `claude.exe`(2.1.285)复验:把项目隔离 home 的 `projects/` 拷进临时 `CLAUDE_CONFIG_DIR`、cwd 设为项目根,`--resume 00000000-…` 立刻回 `No conversation found with session ID`;`--resume f79dae28-…`(磁盘上最新那份)不报找不到,直接进入模型请求,落在本地抓包桩上的请求体里带着完整历史(`messages` 13 条,首条就是 14:23 的「做个废土风的扫雷…」原文)。 - **关联**:`apps/ai-game-creator-shell/src-tauri/src/agent/claude_code_cli.rs`。 +## 2026-10-07 默认模型目录里没有 cc 模型,本地开发栈根本选不到 Claude Code CLI + +- **现象**:本地 `/api/llm/models` 的 14 条模型全部是 `agentMode: "codex"`(`claude-opus-5-5` 也是 `protocol: openai_responses`),cc 模式在本地开发栈里没有可选项,只能靠后台手工加模型;而安装版走 dev 目录时 `claude-opus-5-5` 是 cc 模型。 +- **根因**:默认目录由 `AgcModelCatalog::from_upstream_models` 按上游模型列表生成,所有条目一律落在 `AgcAgentMode::default()`(Codex),"上游模型名 → 执行器"没有任何默认绑定,所以任何全新环境都不会自带 cc 条目。 +- **顺带查到的环境陷阱**:本地 8082 上的 `api-server.exe`(PID 15748)是从**另一个 worktree** 起的 —— `C:\Users\kdletters\.codex\worktrees\5cd1\Genarrative`(分支 `codex/agc-harness-cloud-config`,模型 DTO 多一个 `harnessProfileId`),不是 `F:\Projects\Genarrative` 的 master。所以"本地开发栈"看到的模型目录、字段和 master 不一致,用 master 的现象去对本地结果会得出错误结论;判断本地行为前先看 `Get-CimInstance Win32_Process` 的 `ExecutablePath`。 +- **现行口径**:`from_upstream_models` 为上游的 `claude-opus-5-5` 额外生成一条 `id=claude-opus-5-5-cc`、`alias=claude-opus-5-5 (Claude Code)`、`agentMode=cc`、`protocol=anthropic` 的条目(原 Codex 条目与默认项保留;超过目录项数上限时不再追加)。后台手工保存过的目录不受影响:启动期只在目录缺失或校验不通过时重建,已有合法目录不会因为这行默认值被覆盖。 +- **验证**:`cargo test -p module-runtime --lib agc_models::tests`(新增 `catalog_default_binding_adds_claude_code_cli_for_the_official_cc_model`,断言 cc 条目、`protocol=anthropic`、默认项仍是 Codex 条目,以及非该模型不额外生成)。 +- **关联**:`server-rs/crates/module-runtime/src/agc_models.rs`、`server-rs/crates/api-server/src/agc_models.rs`。 + ## 2026-10-07 cc 模型说"我没有任何可调用的工具":先分清没连上还是模型说错 - **现象**:安装版 0.1.230,新建项目 `gameagent-63d3fda7` 的第一个回合(19:25),模型回答"在当前对话里,我**没有任何可调用的工具**…我能看到的上下文只有工作目录/平台/不是 git 仓库";同一版本 19:22 在 `gameagent-0514673b` 的回合里却真实调用了 `mcp__agc__client_session_info` 与 `mcp__agc__conversation_list` 并拿到回执。**同一个构建既能用工具、又会被模型说成没有工具**,所以"模型自述"不能当证据。 diff --git a/server-rs/crates/module-runtime/src/agc_models.rs b/server-rs/crates/module-runtime/src/agc_models.rs index b6aa1d710..ebbb0a192 100644 --- a/server-rs/crates/module-runtime/src/agc_models.rs +++ b/server-rs/crates/module-runtime/src/agc_models.rs @@ -80,12 +80,29 @@ impl AgcModelCatalog { entries.push(AgcModel { id, alias: model_id.clone(), - model_id, + model_id: model_id.clone(), enabled: true, agent_mode: AgcAgentMode::default(), protocol: None, access: AgcModelAccess::default(), }); + // 默认目录必须带上平台官方 cc(Claude Code CLI)绑定:上游只给模型名,如果不额外 + // 生成这一条,全新环境(含本地开发栈)的模型列表里一个 cc 模型都没有,cc 模式 + // 根本没有可选项。 + if entries.len() < AGC_MODEL_CATALOG_MAX_MODELS { + if let Some((cc_id, cc_alias)) = claude_code_default_binding(&model_id) { + let cc_id = unique_model_id(&cc_id, &mut used_ids); + entries.push(AgcModel { + id: cc_id, + alias: cc_alias, + model_id: model_id.clone(), + enabled: true, + agent_mode: AgcAgentMode::Cc, + protocol: Some(AgcModelProtocol::Anthropic), + access: AgcModelAccess::default(), + }); + } + } } let default_model_id = entries .first() @@ -175,6 +192,21 @@ fn agc_model_id_from_name(model_name: &str) -> String { id } +/// 上游模型名 → 默认目录里额外生成的 Claude Code CLI 绑定:`(目录标识, 显示别名)`。 +/// +/// 平台官方 cc 模型是 `claude-opus-5-5`。默认目录保留它原有的 Codex 绑定(历史目录的默认 +/// 项),同时额外生成一条 `agentMode=cc` + `protocol=anthropic` 的条目,让 cc 模式在全新 +/// 环境和本地开发栈里直接可选:现场证据是本地 `/api/llm/models` 的 14 条全是 +/// `agentMode=codex`,cc 模式在本地没有可选项,只能靠后台手工加模型。 +fn claude_code_default_binding(model_name: &str) -> Option<(String, String)> { + (model_name == "claude-opus-5-5").then(|| { + ( + format!("{model_name}-cc"), + format!("{model_name} (Claude Code)"), + ) + }) +} + /// 生成在本次目录内唯一的标识:同名 slug 追加 `-2`/`-3`,并保证不超过长度上限。 fn unique_model_id(model_name: &str, used_ids: &mut HashSet) -> String { let slug = agc_model_id_from_name(model_name); @@ -225,6 +257,52 @@ mod tests { } } + #[test] + fn catalog_default_binding_adds_claude_code_cli_for_the_official_cc_model() { + let catalog = + AgcModelCatalog::from_upstream_models(upstream(&["claude-opus-5-5", "gpt-5.6-sol"]), 0) + .unwrap(); + // Codex 绑定保留,默认项不变(排序后第一项还是 claude-opus-5-5 的 Codex 条目)。 + assert_eq!(catalog.default_model_id, "claude-opus-5-5"); + assert_eq!( + catalog + .models + .iter() + .map(|entry| ( + entry.id.as_str(), + entry.alias.as_str(), + entry.agent_mode, + entry.resolved_protocol() + )) + .collect::>(), + vec![ + ( + "claude-opus-5-5", + "claude-opus-5-5", + AgcAgentMode::Codex, + AgcModelProtocol::OpenAiResponses + ), + ( + "claude-opus-5-5-cc", + "claude-opus-5-5 (Claude Code)", + AgcAgentMode::Cc, + AgcModelProtocol::Anthropic + ), + ( + "gpt-5-6-sol", + "gpt-5.6-sol", + AgcAgentMode::Codex, + AgcModelProtocol::OpenAiResponses + ), + ] + ); + assert!(catalog.validate().is_ok()); + // 非 cc 模型不额外生成条目。 + let only_codex = + AgcModelCatalog::from_upstream_models(upstream(&["gpt-5.6-sol"]), 0).unwrap(); + assert_eq!(only_codex.models.len(), 1); + } + #[test] fn catalog_builds_from_upstream_models_with_stable_ids() { let catalog = AgcModelCatalog::from_upstream_models(