Improve agent provider resilience

This commit is contained in:
Ryan Ward
2026-09-02 17:09:08 -05:00
parent b115946534
commit 7a33cc7e56
72 changed files with 997 additions and 320 deletions
+4 -4
View File
@@ -1189,21 +1189,21 @@ impl Input {
.enumerate()
.map(|(i, msg)| {
let content_str = match &msg.content {
crate::ai::bedrock::convert::MessageContent::Text(t) => {
crate::ai::provider::convert::MessageContent::Text(t) => {
if t.len() > 500 {
format!("{}... ({} chars total)", &t[..500], t.len())
} else {
t.clone()
}
}
crate::ai::bedrock::convert::MessageContent::ToolUse {
crate::ai::provider::convert::MessageContent::ToolUse {
name,
tool_use_id,
..
} => {
format!("ToolUse(name={name}, id={tool_use_id})")
}
crate::ai::bedrock::convert::MessageContent::ToolResult {
crate::ai::provider::convert::MessageContent::ToolResult {
tool_use_id,
content,
is_error,
@@ -1217,7 +1217,7 @@ impl Input {
"ToolResult(id={tool_use_id}, err={is_error}): {truncated}"
)
}
crate::ai::bedrock::convert::MessageContent::MultiPart(parts) => {
crate::ai::provider::convert::MessageContent::MultiPart(parts) => {
format!("MultiPart({} parts)", parts.len())
}
};
+61 -29
View File
@@ -6994,7 +6994,7 @@ impl TerminalView {
}
fn toggle_settings_view(&mut self, ctx: &mut ViewContext<Self>) {
use crate::ai::bedrock::settings_view::SettingsView;
use crate::ai::provider::settings_view::SettingsView;
// If already showing, remove it
if let Some(view_id) = self.settings_view_id.take() {
@@ -10912,7 +10912,7 @@ impl TerminalView {
// Use the configured command, but if it's the bare default ("aws sso login")
// prefer the external config's auth_refresh_command which includes --profile.
let login_command = if settings_command == "aws sso login" {
use crate::ai::bedrock::external_config::ExternalBedrockConfig;
use crate::ai::provider::external_config::ExternalBedrockConfig;
let external = ExternalBedrockConfig::load();
external.auth_refresh_command.unwrap_or(settings_command)
} else {
@@ -10948,34 +10948,37 @@ impl TerminalView {
|_me, result, ctx| {
match result {
Ok(()) => {
log::info!("[bedrock] AWS login completed successfully, refreshing credentials and resuming");
// Refresh credentials from the updated SSO cache
ApiKeyManager::handle(ctx).update(
ctx,
|manager, ctx| {
drop(crate::ai::aws_credentials::refresh_aws_credentials(manager, ctx));
},
);
// Resume the conversation after a short delay to let credentials load
let _ = ctx.spawn(
async move {
tokio::time::sleep(std::time::Duration::from_millis(500)).await;
},
|me, _, ctx| {
// Find the active conversation and resume it directly
let conversation_id = if FeatureFlag::AgentView.is_enabled() {
me.agent_view_controller
.as_ref(ctx)
.agent_view_state()
.active_conversation_id()
} else {
BlocklistAIHistoryModel::as_ref(ctx).last_conversation_id(me.id())
};
if let Some(conversation_id) = conversation_id {
me.handle_resume_conversation(&conversation_id, ctx);
log::info!("[bedrock] AWS login completed successfully; reloading credentials before resuming");
// Refresh through ApiKeyManager and wait for its completion. A fixed
// delay can resume the request while the SDK still has stale SSO data.
let refresh = ApiKeyManager::handle(ctx).update(ctx, |manager, ctx| {
crate::ai::aws_credentials::refresh_aws_credentials(manager, ctx)
});
let _ = ctx.spawn(refresh, |me, result, ctx| {
match result {
Ok(()) => {
log::info!("[bedrock] AWS credentials refreshed; resuming conversation");
let conversation_id = if FeatureFlag::AgentView.is_enabled() {
me.agent_view_controller
.as_ref(ctx)
.agent_view_state()
.active_conversation_id()
} else {
BlocklistAIHistoryModel::as_ref(ctx)
.last_conversation_id(me.id())
};
if let Some(conversation_id) = conversation_id {
me.handle_resume_conversation(&conversation_id, ctx);
}
}
},
);
Err(error) => {
log::error!(
"[bedrock] AWS login succeeded but credential reload failed; not resuming: {error}"
);
}
}
});
}
Err(e) => {
log::error!("[bedrock] AWS login failed: {e}");
@@ -20646,6 +20649,35 @@ impl TerminalView {
AIBlockEvent::RunAwsLoginCommand => {
self.run_aws_login_command(ctx);
}
AIBlockEvent::RefreshAwsCredentials => {
let refresh = ApiKeyManager::handle(ctx).update(ctx, |manager, ctx| {
crate::ai::aws_credentials::refresh_aws_credentials(manager, ctx)
});
let _ = ctx.spawn(refresh, |me, result, ctx| {
match result {
Ok(()) => {
log::info!("[bedrock] AWS credentials reloaded; resuming conversation");
let conversation_id = if FeatureFlag::AgentView.is_enabled() {
me.agent_view_controller
.as_ref(ctx)
.agent_view_state()
.active_conversation_id()
} else {
BlocklistAIHistoryModel::as_ref(ctx).last_conversation_id(me.id())
};
if let Some(conversation_id) = conversation_id {
me.handle_resume_conversation(&conversation_id, ctx);
}
}
Err(error) => {
log::warn!(
"[bedrock] AWS credential reload failed; starting configured login command: {error}"
);
me.run_aws_login_command(ctx);
}
}
});
}
}
ctx.notify();
}