Fix child startup readiness and ordered provider tools
Wait for shell bootstrap before dispatching child prompts, serialize provider preprocessing, and make permission callbacks idempotent. Restrict task lists to concrete multistep plans and stop inferring completion from tool activity. Update regression fixtures and resolve existing lint and test-layout failures. Verified formatting, both presubmit Clippy commands, and 354 targeted nextest tests.
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
use galaxy_agent_core::{AgentErrorKind, StopReason};
|
||||
use rig_core::completion::CompletionError;
|
||||
|
||||
use super::{
|
||||
completion_error_stop_reason, domain_tool_call, is_keepalive_event, map_completion_error,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn domain_tool_call_prefers_responses_call_id() {
|
||||
let tool_call = rig_core::message::ToolCall::new(
|
||||
"fc_item_123".to_string(),
|
||||
rig_core::message::ToolFunction {
|
||||
name: "read_files".to_string(),
|
||||
arguments: serde_json::json!({"files": ["Cargo.toml"]}),
|
||||
},
|
||||
)
|
||||
.with_call_id("call_123".to_string());
|
||||
|
||||
let call = domain_tool_call(tool_call);
|
||||
|
||||
assert_eq!(call.id, "call_123");
|
||||
assert_eq!(call.name, "read_files");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn domain_tool_call_falls_back_to_wire_id_without_responses_call_id() {
|
||||
let tool_call = rig_core::message::ToolCall::new(
|
||||
"fc_item_123".to_string(),
|
||||
rig_core::message::ToolFunction {
|
||||
name: "read_files".to_string(),
|
||||
arguments: serde_json::json!({"files": ["Cargo.toml"]}),
|
||||
},
|
||||
);
|
||||
|
||||
let call = domain_tool_call(tool_call);
|
||||
|
||||
assert_eq!(call.id, "fc_item_123");
|
||||
assert_eq!(call.name, "read_files");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_context_window_error_maps_to_semantic_stop_reason_and_kind() {
|
||||
let status = rig_core::http_client::Response::builder()
|
||||
.status(400)
|
||||
.body(())
|
||||
.unwrap()
|
||||
.status();
|
||||
let error = CompletionError::from_http_response(
|
||||
status,
|
||||
r#"{"error":{"message":"Your input exceeds the context window of this model. Please adjust your input and try again.","code":"400"}}"#,
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
completion_error_stop_reason(&error),
|
||||
Some(StopReason::ContextWindowExceeded)
|
||||
);
|
||||
let mapped = map_completion_error(error);
|
||||
assert_eq!(mapped.kind, AgentErrorKind::ContextWindowExceeded);
|
||||
assert!(!mapped.recoverable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_context_length_string_maps_to_semantic_stop_reason() {
|
||||
let error = CompletionError::ProviderError(
|
||||
"context_length_exceeded: maximum context length is 128000 tokens".to_string(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
completion_error_stop_reason(&error),
|
||||
Some(StopReason::ContextWindowExceeded)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_keepalive_event_is_a_transport_heartbeat() {
|
||||
assert!(is_keepalive_event(&serde_json::json!({
|
||||
"type": "keepalive",
|
||||
"sequence_number": 3,
|
||||
})));
|
||||
assert!(!is_keepalive_event(&serde_json::json!({
|
||||
"type": "unsupported",
|
||||
})));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn provider_server_error_is_recoverable() {
|
||||
let status = rig_core::http_client::Response::builder()
|
||||
.status(503)
|
||||
.body(())
|
||||
.unwrap()
|
||||
.status();
|
||||
let error = CompletionError::from_http_response(
|
||||
status,
|
||||
r#"{"error":{"message":"Service temporarily unavailable"}}"#,
|
||||
);
|
||||
|
||||
let mapped = map_completion_error(error);
|
||||
assert_eq!(mapped.kind, AgentErrorKind::Provider);
|
||||
assert!(mapped.recoverable);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn flattened_bedrock_credential_errors_are_authentication_failures() {
|
||||
for message in [
|
||||
r#"{"__type":"ExpiredTokenException","message":"The security token included in the request is expired"}"#,
|
||||
"UnrecognizedClientException: The security token included in the request is invalid",
|
||||
"AccessDeniedException: not authorized to perform bedrock:ConverseStream",
|
||||
] {
|
||||
let mapped = map_completion_error(CompletionError::ProviderError(message.to_string()));
|
||||
assert_eq!(mapped.kind, AgentErrorKind::Authentication);
|
||||
assert!(!mapped.recoverable);
|
||||
assert!(mapped.user_message.is_some());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user