新增 AGC 模型 Agent 模式与 Claude Agent SDK sidecar
Project CI / AI game creator shell Rust lane 1/2 (push) Failing after 57s
Project CI / AI game creator shell Rust lane 2/2 (push) Has been cancelled
Project CI / AI game creator shell Rust crates (push) Has been cancelled
Project CI / Backend tests (push) Has been cancelled
Project CI / Native shell tests (push) Has been cancelled
Project CI / Frontend tests (push) Has been cancelled
Project CI / Repository checks (push) Has been cancelled
Project CI / AI game creator shell web tests (push) Has been cancelled
Project CI / AI game creator shell Rust smoke (push) Has been cancelled

后台模型目录增加 codex/cc 执行模式绑定,旧目录缺省兼容 Codex

AGC 客户端按模型绑定路由 Codex app-server 或 Claude Agent SDK sidecar

随包携带 Node runtime、Claude Agent SDK 与匹配平台 Claude runtime

补充模型配置、客户端选择、运行时适配、MCP 取消和定向测试

同步 AGC 模型配置规范、里程碑计划与共享决策记录
This commit is contained in:
2026-09-30 13:49:09 +08:00
parent 5e2d47919e
commit fb130d1847
38 changed files with 3417 additions and 118 deletions
+35 -9
View File
@@ -8,7 +8,7 @@ use axum::{
http::StatusCode,
};
use module_runtime::{
AGC_MODEL_CATALOG_CONFLICT, AGC_MODEL_CATALOG_NOT_INITIALIZED, AgcModelCatalog,
AGC_MODEL_CATALOG_CONFLICT, AGC_MODEL_CATALOG_NOT_INITIALIZED, AgcAgentMode, AgcModelCatalog,
};
use shared_contracts::admin::{AdminAgcModel, AdminAgcModelCatalog};
use spacetime_client::SpacetimeClientError;
@@ -228,19 +228,26 @@ pub async fn admin_save_agc_models(
) -> Result<Json<serde_json::Value>, AppError> {
// 目录只来自上游同步:未初始化时后台写入同样失败关闭,避免出现第二条绕过同步的写入口。
load_catalog(&state).await?;
let catalog = AgcModelCatalog {
revision: payload.revision,
default_model_id: payload.default_model_id,
models: payload
.models
.into_iter()
.map(|m| module_runtime::AgcModel {
let models = payload
.models
.into_iter()
.map(|m| {
let agent_mode = AgcAgentMode::parse(&m.agent_mode).map_err(|message| {
AppError::from_status(StatusCode::BAD_REQUEST).with_message(message)
})?;
Ok(module_runtime::AgcModel {
id: m.id,
alias: m.alias,
model_id: m.model_id,
enabled: m.enabled,
agent_mode,
})
.collect(),
})
.collect::<Result<Vec<_>, AppError>>()?;
let catalog = AgcModelCatalog {
revision: payload.revision,
default_model_id: payload.default_model_id,
models,
};
catalog
.validate()
@@ -275,6 +282,7 @@ fn catalog_dto(catalog: AgcModelCatalog) -> AdminAgcModelCatalog {
alias: m.alias,
model_id: m.model_id,
enabled: m.enabled,
agent_mode: m.agent_mode.as_str().to_string(),
})
.collect(),
}
@@ -285,6 +293,24 @@ mod tests {
use super::*;
use serde_json::json;
#[test]
fn catalog_dto_maps_agent_mode_and_legacy_admin_payload_defaults_to_codex() {
let mut catalog =
AgcModelCatalog::from_upstream_models(vec!["model-a".to_string()], 4).unwrap();
catalog.models[0].agent_mode = AgcAgentMode::Cc;
let payload = serde_json::to_value(catalog_dto(catalog)).unwrap();
assert_eq!(payload["models"][0]["agentMode"], "cc");
let legacy: AdminAgcModel = serde_json::from_value(json!({
"id": "model-a",
"alias": "model-a",
"modelId": "model-a",
"enabled": true
}))
.unwrap();
assert_eq!(legacy.agent_mode, "codex");
}
#[test]
fn upstream_model_names_come_from_pricing_data_array() {
let payload = json!({
+2 -1
View File
@@ -48,7 +48,7 @@ mod model_catalog_tests {
// 客户端拿到稳定标识 + 别名(别名就是上游原始模型名),实际模型名不下发。
assert_eq!(
payload["models"],
json!([{"id": "gpt-5-6-sol", "displayName": "gpt-5.6-sol"}])
json!([{"id": "gpt-5-6-sol", "displayName": "gpt-5.6-sol", "agentMode": "codex"}])
);
assert_eq!(payload["defaultModelId"], "gpt-5-6-sol");
assert_eq!(payload["revision"], json!(7));
@@ -202,6 +202,7 @@ fn public_model_catalog(catalog: module_runtime::AgcModelCatalog) -> LlmModelsRe
id: model.id,
// 初始目录里别名就是上游原始模型名(不再填“高质量/快速”这类人工别名)。
display_name: model.alias,
agent_mode: model.agent_mode.as_str().to_string(),
})
.collect(),
revision: catalog.revision,