diff --git a/apps/aether-gateway/src/tests/ai_execute/sync/search.rs b/apps/aether-gateway/src/tests/ai_execute/sync/search.rs index c8b6d1947..fa9412d16 100644 --- a/apps/aether-gateway/src/tests/ai_execute/sync/search.rs +++ b/apps/aether-gateway/src/tests/ai_execute/sync/search.rs @@ -628,8 +628,9 @@ fn gateway_executes_codex_memories_with_responses_permission_and_native_json() { candidate_row("openai:responses"), ])); let mut memory_provider = provider(); - memory_provider.config = - Some(json!({"codex":{"fingerprint_convergence_enabled":true}})); + memory_provider.config = Some( + json!({"codex":{"fingerprint_convergence_enabled":true},"failover_rules":{"stop_status_codes":[400]}}), + ); let catalog = Arc::new(InMemoryProviderCatalogReadRepository::seed( vec![memory_provider], vec![endpoint("openai:responses")], @@ -694,7 +695,8 @@ fn gateway_executes_codex_memories_with_responses_permission_and_native_json() { .send() .await .expect("error response"); - assert_eq!(error.status(), StatusCode::BAD_REQUEST); + let error_status = error.status(); + assert_eq!(error_status, StatusCode::BAD_REQUEST); assert_eq!( error.json::().await.expect("error JSON"), json!({"error":{"type":"invalid_request_error","message":"synthetic invalid trace","code":"invalid_trace"},"future_error_field":{"enabled":true}}) diff --git a/crates/aether-ai/formats/src/formats/openai/responses/codex.rs b/crates/aether-ai/formats/src/formats/openai/responses/codex.rs index b2f8b8b43..5182fccc1 100644 --- a/crates/aether-ai/formats/src/formats/openai/responses/codex.rs +++ b/crates/aether-ai/formats/src/formats/openai/responses/codex.rs @@ -2072,6 +2072,7 @@ mod tests { .unwrap(); assert_eq!(card["context_window"], 272_000); assert_eq!(card["max_context_window"], 872_000); + assert_eq!(card["comp_hash"], "3000"); assert_eq!(card["minimal_client_version"], "0.153.0"); assert_eq!( card["supported_reasoning_levels"] @@ -2088,7 +2089,6 @@ mod tests { "installation_id", "cookie", "authorization", - "comp_hash", ] { assert!( card.get(private).is_none(), diff --git a/crates/aether-ai/formats/src/formats/openai/responses/codex_models_0_159_3.json b/crates/aether-ai/formats/src/formats/openai/responses/codex_models_0_159_3.json index c046504ed..8a313d328 100644 --- a/crates/aether-ai/formats/src/formats/openai/responses/codex_models_0_159_3.json +++ b/crates/aether-ai/formats/src/formats/openai/responses/codex_models_0_159_3.json @@ -33,6 +33,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-6-Astra", "description": "Frontier intelligence for the most demanding work.", @@ -123,6 +124,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-6.1-Sol", "description": "Latest workhorse model for coding and everyday work.", @@ -216,6 +218,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-6-Sol", "description": "Previous generation workhorse model.", @@ -306,6 +309,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-6-Luna", "description": "Fast and affordable model for easier tasks.", @@ -393,6 +397,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-5.6-Sol", "description": "Older generation workhorse model.", @@ -485,6 +490,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-5.6-Terra", "description": "Older balanced model for straightforward work.", @@ -577,6 +583,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "GPT-5.6-Luna", "description": "Older fast and efficient model.", @@ -661,6 +668,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "Daybreak Blue", "description": "Latest frontier agentic coding model for broad defensive cybersecurity work.", @@ -736,6 +744,7 @@ "context_window": 372000, "max_context_window": 372000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "Daybreak Red", "description": "Cyber-permissive variant of our latest frontier agentic coding model for advanced, authorized cybersecurity research.", @@ -815,6 +824,7 @@ "context_window": 272000, "max_context_window": 272000, "auto_compact_token_limit": null, + "comp_hash": "2911", "default_reasoning_summary": "none", "display_name": "GPT-5.5", "description": "Legacy coding model.", @@ -899,6 +909,7 @@ "context_window": 272000, "max_context_window": 872000, "auto_compact_token_limit": null, + "comp_hash": "3000", "default_reasoning_summary": "none", "display_name": "Codex Auto Review", "description": "Automatic approval review model for Codex.", diff --git a/crates/aether-model-fetch/src/logic.rs b/crates/aether-model-fetch/src/logic.rs index 3ed021ea1..a8fccfa86 100644 --- a/crates/aether-model-fetch/src/logic.rs +++ b/crates/aether-model-fetch/src/logic.rs @@ -1900,7 +1900,7 @@ mod tests { .find(|model| model["id"] == model_id) .expect("GPT-5.6 Codex preset"); assert_eq!(model["shell_type"], "shell_command"); - assert!(model.get("comp_hash").is_none()); + assert_eq!(model["comp_hash"], "3000"); assert_eq!(model["experimental_supported_tools"], json!([])); assert_eq!(model["tool_mode"], "code_mode_only"); assert_eq!(model["prefer_websockets"], true); diff --git a/docs/operations/codex-cli-alignment.md b/docs/operations/codex-cli-alignment.md index 259f33f7e..d707c90f6 100644 --- a/docs/operations/codex-cli-alignment.md +++ b/docs/operations/codex-cli-alignment.md @@ -14,7 +14,7 @@ | 上游账户配额 | `codex.rate_limits` 继续进入账户级熔断与持久化路径,不当作网关用户自己的配额公开 | | 原生记忆接口 | `POST /v1/memories/trace_summarize` 复用 Responses 权限及调度,执行原生同步操作,保留 traces、output 数组和未来字段,不注入 Responses 的 input/store/include 或流式默认值 | -公开快照来源为 `codex-rs/models-manager/models.json`。未复制提示词、账户套餐可见性或编译哈希;没有引入个人用户标识、已有会话 UUID、Cookie、访问令牌或账户凭据。运行时鉴权和账户字段仍由提供商密钥配置产生。 +公开快照来源为 `codex-rs/models-manager/models.json`。未复制提示词或账户套餐可见性;保留官方公开的 `comp_hash` 压缩兼容性标记,以支持 CLI Guardian 的压缩上下文复用;没有引入个人用户标识、已有会话 UUID、Cookie、访问令牌或账户凭据。运行时鉴权和账户字段仍由提供商密钥配置产生。 新增模型能力快照不等于授权访问该模型。可用模型应通过正式管理界面的上游模型查询、全局模型和提供商模型配置,以及密钥模型限制来设置。远端目录及实际账户权限决定上游是否支持模型,不能通过修改 `/models` 列表绕过。 @@ -30,4 +30,4 @@ cargo test --locked -p aether-ai-formats -p aether-oauth -p aether-model-fetch - cargo test --locked -p aether-gateway --lib ``` -原生记忆端到端测试覆盖真实网关的权限、候选调度、执行计划、模型指令、原生 JSON、成功候选状态与上游错误响应;执行端使用本地测试服务器,实际账户网络可用性须在部署现场单独验证。 +原生记忆端到端测试覆盖真实网关的权限、候选调度、执行计划、模型指令、原生 JSON、成功候选状态与明确停止重试策略下的上游错误响应;执行端使用本地测试服务器,实际账户网络可用性须在部署现场单独验证。