fix(kiro): 修复 Kiro WebSearch MCP 调用 (#344)

* fix(kiro): 接入 Kiro MCP web_search 工具调用

* fix(kiro): 对齐 Kiro IDE MCP 鉴权与 profileArn 头部

* fix(responses): 保留 Responses 嵌套与自定义工具参数

* test(ci): 通过 Rust Action 三项检查
This commit is contained in:
Entropy.Xu
2026-04-27 12:20:26 +08:00
committed by GitHub
parent 488bd08f04
commit 6e1eaf8aec
11 changed files with 1917 additions and 11 deletions

View File

@@ -28,7 +28,7 @@ pub(crate) use crate::ai_pipeline::{
pub(crate) use aether_ai_pipeline::api::{
build_core_error_body_for_client_format, core_error_background_report_kind,
core_error_default_client_api_format, core_success_background_report_kind,
implicit_sync_finalize_report_kind, is_core_error_finalize_kind,
encode_kiro_sse_events, implicit_sync_finalize_report_kind, is_core_error_finalize_kind,
normalize_provider_private_report_context, normalize_provider_private_response_value,
provider_private_response_allows_sync_finalize, resolve_claude_stream_spec,
resolve_claude_sync_spec, resolve_gemini_stream_spec, resolve_gemini_sync_spec,

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@ use serde_json::{Map, Value};
mod constants;
mod fallback;
mod kiro_web_search;
pub(crate) mod ndjson;
mod oauth_retry;
#[cfg(test)]

View File

@@ -51,6 +51,7 @@ use crate::clock::current_unix_ms as current_request_candidate_unix_ms;
use crate::constants::{CONTROL_CANDIDATE_ID_HEADER, CONTROL_REQUEST_ID_HEADER};
use crate::control::GatewayControlDecision;
use crate::execution_runtime::build_direct_execution_frame_stream;
use crate::execution_runtime::kiro_web_search::maybe_execute_kiro_web_search_stream;
use crate::execution_runtime::oauth_retry::refresh_oauth_plan_auth_for_retry;
#[cfg(test)]
use crate::execution_runtime::remote_compat::post_stream_plan_to_remote_execution_runtime;
@@ -384,6 +385,57 @@ pub(crate) async fn execute_execution_runtime_stream(
.and_then(|context| context.candidate_index)
.map(|value| value.to_string())
.unwrap_or_else(|| "-".to_string());
match maybe_execute_kiro_web_search_stream(state, &plan, report_context.as_ref()).await {
Ok(Some(kiro_web_search)) => {
return execute_stream_from_frame_stream(
state,
plan,
trace_id,
decision,
plan_kind,
report_kind,
kiro_web_search.report_context.or(report_context),
candidate_started_unix_secs,
stream_started_at,
kiro_web_search.frame_stream,
)
.await;
}
Ok(None) => {}
Err(err) => {
info!(
event_name = "kiro_web_search_mcp_unavailable",
log_type = "ops",
trace_id = %trace_id,
request_id = %plan_request_id_for_log,
candidate_id = ?plan.candidate_id,
provider_name = provider_name.as_str(),
endpoint_id = %endpoint_id,
key_id = %key_id,
model_name = model_name.as_str(),
candidate_index = candidate_index.as_str(),
error = %err,
"gateway Kiro web_search MCP execution unavailable"
);
let terminal_unix_secs = current_request_candidate_unix_ms();
record_local_request_candidate_status(
state,
&plan,
report_context.as_ref(),
SchedulerRequestCandidateStatusUpdate {
status: RequestCandidateStatus::Failed,
status_code: None,
error_type: Some("kiro_web_search_mcp_unavailable".to_string()),
error_message: Some(format!("{err:?}")),
latency_ms: None,
started_at_unix_ms: Some(candidate_started_unix_secs),
finished_at_unix_ms: Some(terminal_unix_secs),
},
)
.await;
return Ok(None);
}
}
#[cfg(not(test))]
{
let execution = match execute_in_process_stream_with_oauth_retry(