Fix cursor focus and selection in input box, add AWS env var warning box, and remove AWS Bedrock login banner

This commit is contained in:
2026-07-02 14:54:15 -05:00
parent 4770ac06b5
commit 3769646ca6
1194 changed files with 5312 additions and 8032 deletions
+49 -11
View File
@@ -2,17 +2,17 @@ use std::sync::{Arc, Mutex};
use anyhow::Result;
use aws_config::BehaviorVersion;
use aws_credential_types::provider::ProvideCredentials;
use aws_sdk_bedrockruntime::config::Region;
use aws_sdk_bedrockruntime::Client as BedrockRuntimeClient;
use crate::settings::ai::BedrockAuthMethod;
use super::convert::{build_converse_request, CachingConfig, ConversationMessage, ToolDefinition};
use super::diagnostic::BedrockDiagnosticLogger;
use super::external_config::ExternalBedrockConfig;
use super::models::apply_cross_region_prefix;
use super::response_translator::bedrock_stream_to_response_events;
use crate::ai::agent::api::ResponseStream;
use crate::settings::ai::BedrockAuthMethod;
fn strip_context_marker(model_id: &str) -> String {
if let Some(base) = model_id.strip_suffix("[1m]") {
@@ -36,6 +36,7 @@ pub struct BedrockClientConfig {
pub region: String,
pub access_key_id: String,
pub secret_access_key: String,
pub session_token: Option<String>,
pub cross_region_inference: bool,
}
@@ -86,10 +87,23 @@ pub enum BedrockError {
impl BedrockClient {
pub async fn from_config(config: BedrockClientConfig) -> Result<Self, BedrockError> {
log::info!(
"[bedrock] from_config input: auth_method={:?}, profile={:?}, region={:?}, access_key_id_set={}, secret_access_key_set={}, session_token_set={}",
config.auth_method,
config.profile,
config.region,
!config.access_key_id.is_empty(),
!config.secret_access_key.is_empty(),
config.session_token.is_some(),
);
let aws_config = match config.auth_method {
BedrockAuthMethod::Profile | BedrockAuthMethod::Sso => {
let mut loader =
aws_config::defaults(BehaviorVersion::latest()).profile_name(&config.profile);
let mut loader = aws_config::defaults(BehaviorVersion::latest());
if !config.profile.is_empty() && config.profile != "default" {
loader = loader.profile_name(&config.profile);
}
if !config.region.is_empty() {
loader = loader.region(Region::new(config.region.clone()));
@@ -105,7 +119,7 @@ impl BedrockClient {
let creds = aws_credential_types::Credentials::new(
&config.access_key_id,
&config.secret_access_key,
None,
config.session_token,
None,
"warp-bedrock-static",
);
@@ -123,6 +137,24 @@ impl BedrockClient {
}
};
if let Some(provider) = aws_config.credentials_provider() {
match provider.provide_credentials().await {
Ok(creds) => {
log::info!(
"[bedrock] Resolved AWS credentials successfully: access_key_id={:?}, has_session_token={}, expiry={:?}",
creds.access_key_id(),
creds.session_token().is_some(),
creds.expiry(),
);
}
Err(e) => {
log::warn!("[bedrock] Failed to resolve AWS credentials from provider: {e:?}");
}
}
} else {
log::warn!("[bedrock] No credentials provider found in resolved AWS config");
}
let region = aws_config
.region()
.map(|r| r.to_string())
@@ -136,6 +168,7 @@ impl BedrockClient {
})
}
#[allow(clippy::too_many_arguments)]
pub async fn converse_stream(
&self,
model_id: &str,
@@ -174,6 +207,13 @@ impl BedrockClient {
tools.len()
);
log::info!(
"[bedrock] Sending request payload to Bedrock:\nSystem Prompt: {:?}\nMessages: {:#?}\nTools: {:#?}",
system_prompt,
messages,
tools
);
let converted = build_converse_request(
messages.clone(),
system_prompt.clone(),
@@ -302,12 +342,10 @@ impl BedrockClient {
})?;
let mut response_text = String::new();
if let Some(output_msg) = output.output() {
if let aws_sdk_bedrockruntime::types::ConverseOutput::Message(msg) = output_msg {
for block in msg.content() {
if let aws_sdk_bedrockruntime::types::ContentBlock::Text(text) = block {
response_text.push_str(text);
}
if let Some(aws_sdk_bedrockruntime::types::ConverseOutput::Message(msg)) = output.output() {
for block in msg.content() {
if let aws_sdk_bedrockruntime::types::ContentBlock::Text(text) = block {
response_text.push_str(text);
}
}
}
+1 -1
View File
@@ -10,7 +10,6 @@ use aws_smithy_types::Document;
use serde_json::Value as JsonValue;
use super::external_config::ExternalBedrockConfig;
// Re-export shared provider types so existing imports from bedrock::convert continue to work.
pub use crate::ai::provider::types::{
ContentPart, ConversationMessage, MessageContent, MessageRole, ToolDefinition,
@@ -47,6 +46,7 @@ pub struct ConvertedRequest {
pub tool_config: Option<ToolConfiguration>,
}
#[allow(clippy::too_many_arguments)]
pub fn build_converse_request(
messages: Vec<ConversationMessage>,
system_prompt: Option<String>,
+1 -1
View File
@@ -1,4 +1,4 @@
use aws_sdk_bedrockruntime::types::{ContentBlock, ConversationRole};
use aws_sdk_bedrockruntime::types::{ContentBlock, ConversationRole, SystemContentBlock, Tool};
use serde_json::json;
use super::convert::*;
+5 -2
View File
@@ -1,10 +1,13 @@
use chrono::{Local, Utc};
use serde_json::Value as JsonValue;
#![allow(dead_code)]
use std::fs::{self, File, OpenOptions};
use std::io::{BufWriter, Read, Seek, SeekFrom, Write};
use std::path::{Path, PathBuf};
use std::sync::Mutex;
use chrono::{Local, Utc};
use serde_json::Value as JsonValue;
use super::convert::{ConversationMessage, MessageContent, MessageRole, ToolDefinition};
const ENV_VAR: &str = "GALAXY_BEDROCK_DIAGNOSTICS";
+40 -37
View File
@@ -1,13 +1,13 @@
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
use futures::StreamExt;
use serde_json::json;
use std::path::PathBuf;
use warp_multi_agent_api as api;
use super::client::{BedrockClient, BedrockClientConfig};
use super::convert::{ConversationMessage, MessageContent, MessageRole, ToolDefinition};
use crate::settings::ai::BedrockAuthMethod;
use warp_multi_agent_api as api;
fn make_user_query_message(id: &str, task_id: &str, query: &str) -> api::Message {
api::Message {
@@ -24,6 +24,7 @@ fn make_user_query_message(id: &str, task_id: &str, query: &str) -> api::Message
mode: None,
intended_agent: 0,
})),
..Default::default()
}
}
@@ -54,6 +55,7 @@ fn make_tool_call_run_shell(
},
)),
})),
..Default::default()
}
}
@@ -81,6 +83,7 @@ fn make_tool_call_read_files(
},
)),
})),
..Default::default()
}
}
@@ -113,12 +116,14 @@ fn make_tool_result_shell(
output: output.into(),
exit_code,
command_id: String::new(),
..Default::default()
},
)),
},
)),
},
)),
..Default::default()
}
}
@@ -155,6 +160,7 @@ fn make_tool_result_read_files(
)),
},
)),
..Default::default()
}
}
@@ -217,6 +223,7 @@ fn make_settings(model: &str) -> api::request::Settings {
supports_bundled_skills: false,
supports_research_agent: false,
supports_orchestration_v2: false,
..Default::default()
}
}
@@ -260,6 +267,7 @@ fn get_test_config() -> Option<BedrockClientConfig> {
region,
access_key_id: String::new(),
secret_access_key: String::new(),
session_token: None,
cross_region_inference: false,
})
}
@@ -691,7 +699,7 @@ impl AgentSimulation {
match name {
"run_shell_command" => {
let command = input["command"].as_str().unwrap_or("echo 'no command'");
let output = std::process::Command::new("sh")
let output = command::blocking::Command::new("sh")
.arg("-c")
.arg(command)
.current_dir(&self.project_path)
@@ -759,7 +767,7 @@ impl AgentSimulation {
.unwrap_or(self.project_path.to_str().unwrap_or("."));
let mut result = String::new();
for query in queries {
let output = std::process::Command::new("grep")
let output = command::blocking::Command::new("grep")
.args(["-rn", query, path])
.output();
if let Ok(out) = output {
@@ -999,7 +1007,7 @@ async fn test_agent_multi_turn_tool_use_produces_output() {
let tool_use_id = format!("tool_{}", total_turns);
let (result, is_error) = match tool.name.as_str() {
"run_shell_command" => {
let ls_output = std::process::Command::new("ls")
let ls_output = command::blocking::Command::new("ls")
.arg("-la")
.current_dir(&project_path)
.output()
@@ -1075,7 +1083,7 @@ async fn test_agent_multi_turn_tool_use_produces_output() {
// 2. No partial reasoning fragments leak to the UI
// 3. The stream protocol is correct (Init, CreateTask, content, Finished)
assert!(
sim.all_text_output.len() > 0 || total_turns > 1,
!sim.all_text_output.is_empty() || total_turns > 1,
"Agent should either produce text or make multiple tool calls to explore"
);
@@ -1160,39 +1168,34 @@ async fn test_reasoning_model_produces_substantial_output() {
while let Some(event_result) = stream.next().await {
event_count += 1;
let event = event_result.expect("event should be Ok");
if let Some(event_type) = &event.r#type {
match event_type {
api::response_event::Type::ClientActions(actions) => {
for action in &actions.actions {
if let Some(action_type) = &action.action {
match action_type {
api::client_action::Action::CreateTask(_) => {
had_create_task = true;
if let Some(api::response_event::Type::ClientActions(actions)) = &event.r#type {
for action in &actions.actions {
if let Some(action_type) = &action.action {
match action_type {
api::client_action::Action::CreateTask(_) => {
had_create_task = true;
}
api::client_action::Action::AddMessagesToTask(add) => {
for msg in &add.messages {
if let Some(api::message::Message::AgentOutput(output)) =
&msg.message
{
total_text.push_str(&output.text);
}
api::client_action::Action::AddMessagesToTask(add) => {
for msg in &add.messages {
if let Some(api::message::Message::AgentOutput(output)) =
&msg.message
{
total_text.push_str(&output.text);
}
}
}
api::client_action::Action::AppendToMessageContent(append) => {
if let Some(msg) = &append.message {
if let Some(api::message::Message::AgentOutput(output)) =
&msg.message
{
total_text.push_str(&output.text);
}
}
}
_ => {}
}
}
api::client_action::Action::AppendToMessageContent(append) => {
if let Some(msg) = &append.message {
if let Some(api::message::Message::AgentOutput(output)) =
&msg.message
{
total_text.push_str(&output.text);
}
}
}
_ => {}
}
}
_ => {}
}
}
}
@@ -1610,7 +1613,7 @@ async fn test_slash_create_new_project() {
if !events.is_empty() {
assert!(
text.len() > 0
!text.is_empty()
|| events
.iter()
.any(|e| matches!(e.event_type, StreamEventType::ToolCallMessage { .. })),
@@ -1645,7 +1648,7 @@ async fn test_slash_auto_code_diff() {
assert_valid_stream(&events, "slash_auto_code_diff");
if !events.is_empty() {
let has_action = text.len() > 0
let has_action = !text.is_empty()
|| events
.iter()
.any(|e| matches!(e.event_type, StreamEventType::ToolCallMessage { .. }));
@@ -1775,7 +1778,7 @@ async fn test_slash_query_with_canned_response() {
assert_valid_stream(&events, "slash_query_with_canned_response");
if !events.is_empty() {
let has_output = text.len() > 0
let has_output = !text.is_empty()
|| events
.iter()
.any(|e| matches!(e.event_type, StreamEventType::ToolCallMessage { .. }));
-1
View File
@@ -144,7 +144,6 @@ fn parse_claude_code_model_map(
model_id: arn,
display_name,
vision_supported: true,
context_size: 200_000,
}
})
.collect()
+109 -17
View File
@@ -22,6 +22,7 @@ fn get_test_config() -> Option<BedrockClientConfig> {
region,
access_key_id: String::new(),
secret_access_key: String::new(),
session_token: None,
cross_region_inference: false,
})
}
@@ -81,6 +82,7 @@ async fn collect_stream_output(
while let Some(event) = stream.next().await {
let event = event.expect("stream event should be Ok");
if let Some(event_type) = event.r#type {
use warp_multi_agent_api::message::Message;
use warp_multi_agent_api::response_event::Type;
match event_type {
Type::ClientActions(actions) => {
@@ -90,24 +92,16 @@ async fn collect_stream_output(
match action_type {
Action::AddMessagesToTask(add) => {
for msg in add.messages {
if let Some(msg_content) = msg.message {
use warp_multi_agent_api::message::Message;
match msg_content {
Message::AgentOutput(output) => {
text.push_str(&output.text);
}
_ => {}
}
if let Some(Message::AgentOutput(output)) = msg.message {
text.push_str(&output.text);
}
}
}
Action::AppendToMessageContent(append) => {
if let Some(msg) = append.message {
if let Some(msg_content) = msg.message {
if let Message::AgentOutput(output) = msg_content {
text.push_str(&output.text);
}
}
if let Some(Message::AgentOutput(output)) =
append.message.and_then(|m| m.message)
{
text.push_str(&output.text);
}
}
_ => {}
@@ -553,9 +547,10 @@ async fn test_arn_based_model() {
return;
};
let arn = std::env::var("BEDROCK_TEST_ARN").unwrap_or_else(|_| {
"arn:aws:bedrock:us-east-1:156729649053:application-inference-profile/1tim45pgo320".into()
});
let Some(arn) = std::env::var("BEDROCK_TEST_ARN").ok() else {
eprintln!("Skipping: BEDROCK_TEST_ARN not set");
return;
};
let client = BedrockClient::from_config(config)
.await
@@ -696,3 +691,100 @@ async fn test_all_tools_visible_to_model() {
tools.len()
);
}
#[tokio::test]
async fn test_bedrock_integration_live_stream() {
let Some(config) = get_test_config() else {
eprintln!("Skipping: BEDROCK_INTEGRATION_TEST not set");
return;
};
println!("[live-test] Initializing Bedrock client...");
let client = BedrockClient::from_config(config)
.await
.expect("client creation");
let model = get_test_model();
println!("[live-test] Using model: {model}");
let messages = vec![ConversationMessage {
role: MessageRole::User,
content: MessageContent::Text(
"Write a 2-line poem about antigravity. Output only the poem.".into(),
),
}];
println!("[live-test] Requesting stream response from Bedrock...");
let stream = client
.converse_stream(
&model,
"live-test-task-id",
true,
messages,
None,
None,
vec![],
1024,
None,
false,
None,
None,
Arc::new(Mutex::new(Vec::new())),
Vec::new(),
)
.await
.expect("converse_stream should succeed");
let mut full_text = String::new();
let mut stream = stream;
while let Some(event) = stream.next().await {
let event = event.expect("stream event should be Ok");
if let Some(event_type) = event.r#type {
use warp_multi_agent_api::message::Message;
use warp_multi_agent_api::response_event::Type;
match event_type {
Type::ClientActions(actions) => {
for action in actions.actions {
if let Some(action_type) = action.action {
use warp_multi_agent_api::client_action::Action;
match action_type {
Action::AddMessagesToTask(add) => {
for msg in add.messages {
if let Some(Message::AgentOutput(output)) = msg.message {
print!("{}", output.text);
full_text.push_str(&output.text);
}
}
}
Action::AppendToMessageContent(append) => {
if let Some(Message::AgentOutput(output)) =
append.message.and_then(|m| m.message)
{
print!("{}", output.text);
full_text.push_str(&output.text);
}
}
_ => {}
}
}
}
}
Type::Finished(finished) => {
println!(
"\n[live-test] Stream finished. Reason: {:?}",
finished.reason
);
if let Some(meta) = finished.conversation_usage_metadata {
if let Some(usage) = meta.byok_token_usage.get("bedrock") {
println!("[live-test] Token Usage - Total: {}", usage.total_tokens);
}
}
}
_ => {}
}
}
}
println!("[live-test] Received full response:\n{}", full_text.trim());
assert!(!full_text.is_empty(), "Model returned an empty response");
}
+2 -3
View File
@@ -1,6 +1,7 @@
use crate::settings::ai::BedrockModelConfig;
#![allow(dead_code)]
use super::external_config::ExternalBedrockConfig;
use crate::settings::ai::BedrockModelConfig;
pub struct DefaultModel {
pub model_id: &'static str,
@@ -128,7 +129,6 @@ pub fn get_effective_models(user_models: &[BedrockModelConfig]) -> Vec<BedrockMo
model_id: m.model_id.to_string(),
display_name: m.display_name.to_string(),
vision_supported: m.vision_supported,
context_size: m.context_size,
})
.collect();
for default in defaults {
@@ -145,7 +145,6 @@ pub fn get_effective_models(user_models: &[BedrockModelConfig]) -> Vec<BedrockMo
model_id: m.model_id.to_string(),
display_name: m.display_name.to_string(),
vision_supported: m.vision_supported,
context_size: m.context_size,
})
.collect()
}
-1
View File
@@ -92,7 +92,6 @@ fn test_get_effective_models_custom_overrides() {
model_id: "custom.model-v1:0".to_string(),
display_name: "Custom Model".to_string(),
vision_supported: false,
context_size: 200_000,
}];
let models = get_effective_models(&custom);
assert_eq!(models.len(), 1);
+12 -3
View File
@@ -1,3 +1,7 @@
#![allow(dead_code)]
use std::collections::HashSet;
use warp_multi_agent_api as api;
use super::convert::{
@@ -357,6 +361,7 @@ fn extract_input_messages(request: &api::Request) -> Vec<api::Message> {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::ToolCallResult(
api::message::ToolCallResult {
tool_call_id: result.tool_call_id.clone(),
@@ -382,6 +387,7 @@ fn extract_input_messages(request: &api::Request) -> Vec<api::Message> {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::UserQuery(
api::message::UserQuery {
query: query.query.clone(),
@@ -422,6 +428,7 @@ fn extract_input_messages(request: &api::Request) -> Vec<api::Message> {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::UserQuery(
api::message::UserQuery {
query: query_text,
@@ -445,6 +452,7 @@ fn extract_input_messages(request: &api::Request) -> Vec<api::Message> {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::UserQuery(api::message::UserQuery {
query: query.query.clone(),
..Default::default()
@@ -462,6 +470,7 @@ fn extract_input_messages(request: &api::Request) -> Vec<api::Message> {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::ToolCallResult(
api::message::ToolCallResult {
tool_call_id: result.tool_call_id.clone(),
@@ -492,6 +501,7 @@ fn extract_input_messages(request: &api::Request) -> Vec<api::Message> {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::UserQuery(api::message::UserQuery {
query: prompt,
..Default::default()
@@ -728,7 +738,6 @@ fn ensure_starts_with_user_message(messages: &mut Vec<ConversationMessage>) {
/// 4. Removes trailing assistant tool_use messages that have no following user message.
/// 5. Ensures strict user/assistant role alternation.
fn ensure_tool_results_paired(messages: &mut Vec<ConversationMessage>) {
// Collect all tool_result IDs that exist anywhere in the conversation.
let mut all_result_ids = HashSet::new();
for msg in messages.iter() {
@@ -1035,7 +1044,7 @@ pub fn extract_tools(request: &api::Request) -> Vec<ToolDefinition> {
let input_schema = tool
.input_schema
.as_ref()
.map(|s| prost_struct_to_json(s))
.map(prost_struct_to_json)
.unwrap_or_else(|| serde_json::json!({"type": "object", "properties": {}}));
tools.push(ToolDefinition {
name,
@@ -1057,7 +1066,7 @@ pub fn extract_tools(request: &api::Request) -> Vec<ToolDefinition> {
let input_schema = tool
.input_schema
.as_ref()
.map(|s| prost_struct_to_json(s))
.map(prost_struct_to_json)
.unwrap_or_else(|| serde_json::json!({"type": "object", "properties": {}}));
tools.push(ToolDefinition {
name,
+45 -41
View File
@@ -1,3 +1,5 @@
#![allow(dead_code)]
use std::sync::{Arc, Mutex};
use aws_sdk_bedrockruntime::operation::converse_stream::ConverseStreamOutput;
@@ -10,11 +12,10 @@ use uuid::Uuid;
use warp_multi_agent_api::response_event::stream_finished;
use warp_multi_agent_api::{self as api, ClientAction, ResponseEvent};
use crate::ai::agent::api::Event;
use crate::server::server_api::AIApiError;
use super::convert::{ContentPart, ConversationMessage, MessageContent, MessageRole};
use super::diagnostic::BedrockDiagnosticLogger;
use crate::ai::agent::api::Event;
use crate::server::server_api::AIApiError;
fn json_to_prost_struct(value: &serde_json::Value) -> prost_types::Struct {
let fields = match value.as_object() {
@@ -57,6 +58,7 @@ pub fn context_window_for_model(model_id: &str) -> u32 {
}
}
#[allow(clippy::too_many_arguments)]
pub fn bedrock_stream_to_response_events(
mut output: ConverseStreamOutput,
task_id: String,
@@ -129,41 +131,36 @@ pub fn bedrock_stream_to_response_events(
}
StreamEvent::ContentBlockStart(block_start) => {
log::debug!("[bedrock] Event #{event_count}: ContentBlockStart");
if let Some(start) = block_start.start() {
match start {
ContentBlockStart::ToolUse(tool_start) => {
_has_tool_calls = true;
if !buffered_text.is_empty() {
let msg_id = current_text_message_id
.clone()
.unwrap_or_else(|| Uuid::new_v4().to_string());
if !text_flushed {
current_text_message_id = Some(msg_id.clone());
text_flushed = true;
log::debug!("[bedrock] Flushing buffered text ({} chars) before tool call", buffered_text.len());
let add_msg = build_add_agent_output_message(
&task_id,
&msg_id,
&buffered_text,
);
yield Ok(add_msg);
} else {
log::debug!("[bedrock] Flushing remaining buffered text ({} chars) as append before tool call", buffered_text.len());
let append = build_append_text(
&task_id,
&msg_id,
&buffered_text,
);
yield Ok(append);
}
buffered_text.clear();
}
current_tool_use_id = tool_start.tool_use_id().to_string();
current_tool_name = tool_start.name().to_string();
current_tool_input_json.clear();
if let Some(ContentBlockStart::ToolUse(tool_start)) = block_start.start() {
_has_tool_calls = true;
if !buffered_text.is_empty() {
let msg_id = current_text_message_id
.clone()
.unwrap_or_else(|| Uuid::new_v4().to_string());
if !text_flushed {
current_text_message_id = Some(msg_id.clone());
text_flushed = true;
log::debug!("[bedrock] Flushing buffered text ({} chars) before tool call", buffered_text.len());
let add_msg = build_add_agent_output_message(
&task_id,
&msg_id,
&buffered_text,
);
yield Ok(add_msg);
} else {
log::debug!("[bedrock] Flushing remaining buffered text ({} chars) as append before tool call", buffered_text.len());
let append = build_append_text(
&task_id,
&msg_id,
&buffered_text,
);
yield Ok(append);
}
_ => {}
buffered_text.clear();
}
current_tool_use_id = tool_start.tool_use_id().to_string();
current_tool_name = tool_start.name().to_string();
current_tool_input_json.clear();
}
}
StreamEvent::ContentBlockDelta(delta) => {
@@ -187,7 +184,7 @@ pub fn bedrock_stream_to_response_events(
// AddMessagesToTask carries enough content for
// the exchange to be fully registered before
// subsequent AppendToMessageContent events arrive.
if buffered_text.len() >= 1 {
if !buffered_text.is_empty() {
let msg_id = Uuid::new_v4().to_string();
current_text_message_id = Some(msg_id.clone());
text_flushed = true;
@@ -201,10 +198,8 @@ pub fn bedrock_stream_to_response_events(
}
}
}
ContentBlockDelta::ReasoningContent(reasoning) => {
if let ReasoningContentBlockDelta::Text(text) = reasoning {
log::trace!("[bedrock] Reasoning delta ({} chars) - not displayed to user", text.len());
}
ContentBlockDelta::ReasoningContent(ReasoningContentBlockDelta::Text(text)) => {
log::trace!("[bedrock] Reasoning delta ({} chars) - not displayed to user", text.len());
}
ContentBlockDelta::ToolUse(tool_delta) => {
current_tool_input_json.push_str(tool_delta.input());
@@ -593,6 +588,7 @@ fn build_user_query_message(task_id: &str, query_text: &str) -> ResponseEvent {
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::UserQuery(api::message::UserQuery {
query: query_text.to_string(),
..Default::default()
@@ -682,10 +678,14 @@ pub fn build_stream_finished(
context_window_usage: context_usage,
summarized: is_summarization,
credits_spent: 0.0,
platform_credits_spent: 0.0,
total_input_tokens: input_tokens as u32,
token_usage: vec![],
tool_usage_metadata: None,
warp_token_usage: std::collections::HashMap::new(),
byok_token_usage,
custom_endpoint_token_usage: std::collections::HashMap::new(),
context_window_segments: vec![],
});
ResponseEvent {
@@ -757,6 +757,7 @@ fn build_add_agent_output_message(
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::AgentOutput(
api::message::AgentOutput {
text: initial_text.to_string(),
@@ -790,6 +791,7 @@ fn build_append_text(task_id: &str, message_id: &str, text_delta: &str) -> Respo
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::AgentOutput(
api::message::AgentOutput {
text: text_delta.to_string(),
@@ -1227,6 +1229,7 @@ pub fn build_tool_call_message(
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::ToolCall(api::message::ToolCall {
tool_call_id: effective_tool_call_id,
tool: Some(tool_variant),
@@ -1243,6 +1246,7 @@ pub fn build_tool_call_message(
timestamp: None,
server_message_data: String::new(),
citations: vec![],
fetched_memories: vec![],
message: Some(api::message::Message::AgentOutput(
api::message::AgentOutput {
text: format!(
@@ -1,4 +1,5 @@
use warp_multi_agent_api::{self as api, response_event::stream_finished};
use warp_multi_agent_api::response_event::stream_finished;
use warp_multi_agent_api::{self as api};
use super::response_translator::*;
+5 -4
View File
@@ -1,11 +1,12 @@
use galaxyui::elements::{
Container, CornerRadius, CrossAxisAlignment, Flex, ParentElement, Radius, Text,
};
use galaxyui::{AppContext, Element, Entity, SingletonEntity, TypedActionView, View, ViewContext};
use crate::ai::bedrock::convert::CachingConfig;
use crate::ai::bedrock::external_config::ExternalBedrockConfig;
use crate::appearance::Appearance;
use crate::ui_components::blended_colors;
use galaxyui::{
elements::{Container, CornerRadius, CrossAxisAlignment, Flex, ParentElement, Radius, Text},
AppContext, Element, Entity, SingletonEntity, TypedActionView, View, ViewContext,
};
pub struct SettingsView {
external_config: ExternalBedrockConfig,
@@ -9,16 +9,5 @@ pub fn multiply(a: i32, b: i32) -> i32 {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_multiply() {
assert_eq!(multiply(3, 4), 12);
}
}
#[path = "lib_tests.rs"]
mod tests;
@@ -0,0 +1,11 @@
use super::*;
#[test]
fn test_add() {
assert_eq!(add(2, 3), 5);
}
#[test]
fn test_multiply() {
assert_eq!(multiply(3, 4), 12);
}
+2
View File
@@ -1,3 +1,5 @@
#![allow(dead_code)]
use std::sync::{Arc, Mutex};
use warp_multi_agent_api as api;