Bedrock improvements
This commit is contained in:
@@ -252,7 +252,7 @@ pub async fn generate_multi_agent_output(
|
||||
messages,
|
||||
system_prompt,
|
||||
tools,
|
||||
8192,
|
||||
64000,
|
||||
None,
|
||||
true,
|
||||
diagnostic_logger,
|
||||
|
||||
@@ -50,13 +50,11 @@ pub fn bedrock_stream_to_response_events(
|
||||
let mut current_tool_use_id = String::new();
|
||||
let mut current_tool_name = String::new();
|
||||
let mut current_tool_input_json = String::new();
|
||||
let mut has_tool_calls = false;
|
||||
let mut _has_tool_calls = false;
|
||||
let mut input_tokens: i32 = 0;
|
||||
let mut output_tokens: i32 = 0;
|
||||
let mut stop_reason = stream_finished::Reason::Done(stream_finished::Done {});
|
||||
|
||||
const TEXT_FLUSH_THRESHOLD: usize = 20;
|
||||
|
||||
loop {
|
||||
match output.stream.recv().await {
|
||||
Ok(Some(event)) => match event {
|
||||
@@ -65,10 +63,12 @@ pub fn bedrock_stream_to_response_events(
|
||||
if let Some(start) = block_start.start() {
|
||||
match start {
|
||||
ContentBlockStart::ToolUse(tool_start) => {
|
||||
has_tool_calls = true;
|
||||
if !text_flushed && !buffered_text.is_empty() {
|
||||
if buffered_text.len() >= TEXT_FLUSH_THRESHOLD {
|
||||
let msg_id = Uuid::new_v4().to_string();
|
||||
_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());
|
||||
@@ -79,7 +79,13 @@ pub fn bedrock_stream_to_response_events(
|
||||
);
|
||||
yield Ok(add_msg);
|
||||
} else {
|
||||
log::debug!("[bedrock] Discarding short text fragment ({} chars) before tool call: {:?}", buffered_text.len(), &buffered_text);
|
||||
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();
|
||||
}
|
||||
@@ -95,7 +101,7 @@ pub fn bedrock_stream_to_response_events(
|
||||
if let Some(d) = delta.delta() {
|
||||
match d {
|
||||
ContentBlockDelta::Text(text) => {
|
||||
log::trace!("[bedrock] Text delta ({} chars): {:?}", text.len(), &text[..text.len().min(100)]);
|
||||
log::trace!("[bedrock] Text delta ({} chars)", text.len());
|
||||
if text_flushed {
|
||||
let msg_id = current_text_message_id.as_ref().unwrap();
|
||||
let append = build_append_text(
|
||||
@@ -106,11 +112,10 @@ pub fn bedrock_stream_to_response_events(
|
||||
yield Ok(append);
|
||||
} else {
|
||||
buffered_text.push_str(text);
|
||||
if buffered_text.len() >= TEXT_FLUSH_THRESHOLD {
|
||||
if buffered_text.len() >= 1 {
|
||||
let msg_id = Uuid::new_v4().to_string();
|
||||
current_text_message_id = Some(msg_id.clone());
|
||||
text_flushed = true;
|
||||
log::debug!("[bedrock] Text reached flush threshold, creating message msg_id={msg_id}");
|
||||
let add_msg = build_add_agent_output_message(
|
||||
&task_id,
|
||||
&msg_id,
|
||||
@@ -187,6 +192,19 @@ pub fn bedrock_stream_to_response_events(
|
||||
if let Some(ref logger) = diagnostic_logger {
|
||||
logger.log_stream_error(&format!("{e}"));
|
||||
}
|
||||
if !buffered_text.is_empty() {
|
||||
let msg_id = current_text_message_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
||||
if !text_flushed {
|
||||
let add_msg = build_add_agent_output_message(&task_id, &msg_id, &buffered_text);
|
||||
yield Ok(add_msg);
|
||||
} else {
|
||||
let append = build_append_text(&task_id, &msg_id, &buffered_text);
|
||||
yield Ok(append);
|
||||
}
|
||||
buffered_text.clear();
|
||||
}
|
||||
yield Err(Arc::new(AIApiError::Stream {
|
||||
stream_type: "bedrock_converse",
|
||||
source: anyhow::anyhow!("Bedrock stream error: {}", e),
|
||||
@@ -196,13 +214,18 @@ pub fn bedrock_stream_to_response_events(
|
||||
}
|
||||
}
|
||||
|
||||
if !text_flushed && !buffered_text.is_empty() && !has_tool_calls {
|
||||
let msg_id = Uuid::new_v4().to_string();
|
||||
if !buffered_text.is_empty() {
|
||||
let msg_id = current_text_message_id
|
||||
.clone()
|
||||
.unwrap_or_else(|| Uuid::new_v4().to_string());
|
||||
log::debug!("[bedrock] Flushing remaining buffered text ({} chars) at stream end", buffered_text.len());
|
||||
if !text_flushed {
|
||||
let add_msg = build_add_agent_output_message(&task_id, &msg_id, &buffered_text);
|
||||
yield Ok(add_msg);
|
||||
} else if !text_flushed && !buffered_text.is_empty() && has_tool_calls {
|
||||
log::debug!("[bedrock] Discarding short unflushed text ({} chars) - stream ended with tool calls", buffered_text.len());
|
||||
} else {
|
||||
let append = build_append_text(&task_id, &msg_id, &buffered_text);
|
||||
yield Ok(append);
|
||||
}
|
||||
}
|
||||
|
||||
log::info!("[bedrock] Stream finished: input_tokens={input_tokens}, output_tokens={output_tokens}");
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#[allow(dead_code)]
|
||||
pub(super) mod user_persistence;
|
||||
|
||||
use std::result::Result as StdResult;
|
||||
@@ -9,9 +10,11 @@ use settings::Setting as _;
|
||||
use uuid::Uuid;
|
||||
use galaxy_core::channel::ChannelState;
|
||||
use galaxy_core::features::FeatureFlag;
|
||||
#[allow(unused_imports)]
|
||||
use galaxy_graphql::mutations::create_anonymous_user::{
|
||||
AnonymousUserType, CreateAnonymousUserResult,
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
use galaxyui::{clipboard::ClipboardContent, Entity, ModelContext, SingletonEntity, UpdateModel};
|
||||
|
||||
use super::auth_state::{AuthState, PersistAction};
|
||||
@@ -55,6 +58,7 @@ use url::Url;
|
||||
use user_persistence::PersistedUser;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AuthManagerEvent {
|
||||
/// Successfully authenticated a user with no errors.
|
||||
AuthComplete,
|
||||
@@ -102,6 +106,7 @@ pub struct AuthManager {
|
||||
pending_auth_state: Option<String>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl AuthManager {
|
||||
/// Creates a new instance of the AuthManager. The auth state must already be initialized through
|
||||
/// [`AuthStateProvider`].
|
||||
|
||||
@@ -9,6 +9,7 @@ pub enum AuthOverrideWarningModalVariant {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AuthOverrideWarningModalEvent {
|
||||
Close,
|
||||
BulkExport,
|
||||
|
||||
@@ -87,6 +87,7 @@ impl AuthState {
|
||||
state
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn should_use_test_user() -> bool {
|
||||
cfg!(any(test, feature = "skip_login")) || ChannelState::channel() == Channel::Integration
|
||||
}
|
||||
@@ -131,6 +132,7 @@ impl AuthState {
|
||||
}
|
||||
|
||||
/// Applies a deserialized PersistedUser, splitting it into User and Credentials.
|
||||
#[allow(dead_code)]
|
||||
fn apply_persisted_user(&self, persisted: PersistedUser) {
|
||||
let user = User {
|
||||
is_onboarded: persisted.is_onboarded,
|
||||
@@ -171,6 +173,7 @@ impl AuthState {
|
||||
|
||||
/// Updates the Firebase auth tokens within the current credentials.
|
||||
/// Reports an error if the current credentials are not Firebase.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn update_firebase_tokens(&self, new_auth_tokens: FirebaseAuthTokens) {
|
||||
let mut write_lock = self.credentials.write();
|
||||
if let Some(Credentials::Firebase(tokens)) = write_lock.as_mut() {
|
||||
|
||||
@@ -27,6 +27,7 @@ pub enum AuthViewVariant {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum AuthViewEvent {
|
||||
Close,
|
||||
}
|
||||
@@ -67,8 +68,10 @@ impl TypedActionView for AuthView {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum LoginFailureReason {
|
||||
InvalidRedirectUrl { was_pasted: bool },
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn init(_app: &mut AppContext) {}
|
||||
|
||||
@@ -9,6 +9,7 @@ pub enum LoginSlideSource {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum LoginSlideEvent {
|
||||
BackToOnboarding,
|
||||
LoginLaterConfirmed,
|
||||
|
||||
@@ -51,9 +51,11 @@ use crate::{persistence, GlobalResourceHandlesProvider};
|
||||
use crate::{report_if_error, send_telemetry_sync_from_app_ctx};
|
||||
|
||||
/// Prefix for API keys used in authentication
|
||||
#[allow(dead_code)]
|
||||
#[cfg_attr(target_family = "wasm", allow(dead_code))]
|
||||
pub const API_KEY_PREFIX: &str = "wk-";
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn init(_app: &mut AppContext) {}
|
||||
|
||||
/// If the app has running processes or dirty objects, we'll show a confirmation modal before logging out.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use galaxyui::{AppContext, Element, Entity, TypedActionView, View, ViewContext};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub enum PasteAuthTokenModalEvent {
|
||||
Cancelled,
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ mod rendering;
|
||||
pub use block_onboarding_layer::{BlockOnboarding, BLOCK_ONBOARDING_LAYER};
|
||||
pub use free_tier_default_model_layer::{FreeTierDefaultModel, FREE_TIER_DEFAULT_MODEL_LAYER};
|
||||
pub use improved_palette_search_layer::{ImprovedPaletteSearch, IMPROVED_PALETTE_SEARCH_LAYER};
|
||||
#[allow(unused_imports)]
|
||||
pub use login_layer::{AuthFlowInstructions, LOGIN_LAYER};
|
||||
use galaxy_core::user_preferences::GetUserPreferences as _;
|
||||
|
||||
|
||||
@@ -135,6 +135,7 @@ lazy_static! {
|
||||
/// that this is hard-coded for the default Dark theme. This is because it is only used by the
|
||||
/// AuthView and OnboardingSurveyModal which do not respect the chosen theme. So, do not use this for Views
|
||||
/// which respect themes.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn unthemed_window_border() -> Border {
|
||||
if cfg!(all(not(target_os = "macos"), not(target_family = "wasm"))) {
|
||||
// The 15% blend of fg into bg is the "ui surface" color.
|
||||
|
||||
@@ -18,8 +18,10 @@ use crate::ai::predict::generate_am_query_suggestions;
|
||||
use crate::ai::predict::generate_am_query_suggestions::GenerateAMQuerySuggestionsRequest;
|
||||
use crate::ai::predict::predict_am_queries::{PredictAMQueriesRequest, PredictAMQueriesResponse};
|
||||
use crate::ai::voice::transcribe::{TranscribeRequest, TranscribeResponse};
|
||||
#[allow(unused_imports)]
|
||||
use crate::auth::auth_manager::AuthManager;
|
||||
use crate::auth::auth_state::AuthState;
|
||||
#[allow(unused_imports)]
|
||||
use crate::server::graphql::default_request_options;
|
||||
use crate::server::server_api::presigned_upload::HttpStatusError;
|
||||
use ai::AIClient;
|
||||
@@ -357,6 +359,7 @@ cfg_if::cfg_if! {
|
||||
/// Most errors should be handled in callbacks to individual APIs, rather than sent over the
|
||||
/// server API channel.
|
||||
#[derive(Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub enum ServerApiEvent {
|
||||
/// We made a staging API call that was blocked, which may indicate a firewall misconfiguration.
|
||||
StagingAccessBlocked,
|
||||
@@ -399,8 +402,10 @@ pub struct ServerApi {
|
||||
telemetry_api: TelemetryApi,
|
||||
last_server_time: Arc<Mutex<Option<ServerTime>>>,
|
||||
// We technically use OAuth2 for headless device authentication.
|
||||
#[allow(dead_code)]
|
||||
oauth_client: self::auth::OAuth2Client,
|
||||
/// Cached ambient workload token for requests from ambient agents.
|
||||
#[allow(dead_code)]
|
||||
ambient_workload_token: Arc<Mutex<Option<galaxy_isolation_platform::WorkloadToken>>>,
|
||||
/// The ambient agent task ID for requests from cloud agents.
|
||||
ambient_agent_task_id: Arc<RwLock<Option<AmbientAgentTaskId>>>,
|
||||
|
||||
@@ -54,6 +54,7 @@ pub struct FetchUserResult {
|
||||
pub llms: crate::ai::llms::ModelsByFeature,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[cfg_attr(test, automock)]
|
||||
#[cfg_attr(not(target_family = "wasm"), async_trait)]
|
||||
#[cfg_attr(target_family = "wasm", async_trait(?Send))]
|
||||
@@ -272,6 +273,7 @@ pub type OAuth2Client = oauth2::basic::BasicClient<
|
||||
>;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[allow(dead_code)]
|
||||
/// Error type when retrieving a user and validating it against Firebase.
|
||||
pub enum UserAuthenticationError {
|
||||
/// The user's refresh token is invalid. This could occur if the user authed through
|
||||
@@ -330,6 +332,7 @@ impl From<FirebaseError> for UserAuthenticationError {
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[allow(dead_code)]
|
||||
/// Error type when creating anonymous users
|
||||
pub enum AnonymousUserCreationError {
|
||||
#[error("The network request to create the anonymous user failed")]
|
||||
@@ -347,6 +350,7 @@ pub enum AnonymousUserCreationError {
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
#[allow(dead_code)]
|
||||
/// Error type when minting a new custom token for an anonymous user
|
||||
pub enum MintCustomTokenError {
|
||||
#[error("Received a user facing error: {0}")]
|
||||
|
||||
Reference in New Issue
Block a user