Complete agent monitoring and Galaxy Control integration

- expose command-monitor conversations and preserve visible agent transcripts
- add bounded polling and a dedicated shell interrupt tool
- improve direct-provider images, skills, tool history, and usage handling
- package and brand Galaxy Control across releases, installers, persistence, and docs
This commit is contained in:
2026-07-29 15:04:58 -05:00
parent 100f1eff1c
commit dbfa8bcd48
172 changed files with 6357 additions and 3825 deletions
@@ -9,7 +9,6 @@ use galaxyui::{AppContext, SingletonEntity};
use lazy_static::lazy_static;
use regex::Regex;
use crate::ai::agent::conversation::AIConversationId;
use crate::ai::agent::{
AIAgentAttachment, AIAgentContext, DocumentContentAttachmentSource, DriveObjectPayload,
};
@@ -17,7 +16,7 @@ use crate::ai::block_context::BlockContext;
use crate::ai::blocklist::{BlocklistAIContextModel, SessionContext};
use crate::ai::document::ai_document_model::{AIDocumentId, AIDocumentModel};
use crate::ai::facts::CloudAIFactModel;
use crate::ai::skills::list_skills_if_changed;
use crate::ai::skills::list_skills_for_request;
use crate::cloud_object::model::generic_string_model::{CloudStringObject, GenericStringObjectId};
use crate::cloud_object::model::persistence::CloudModel;
use crate::cloud_object::{
@@ -48,7 +47,6 @@ pub(super) fn input_context_for_request(
is_user_query: bool,
context_model: &BlocklistAIContextModel,
active_session: &ActiveSession,
conversation_id: Option<AIConversationId>,
additional_context: Vec<AIAgentContext>,
app: &AppContext,
) -> Arc<[AIAgentContext]> {
@@ -80,16 +78,12 @@ pub(super) fn input_context_for_request(
if FeatureFlag::ListSkills.is_enabled() {
let path_origin = SessionContext::from_session(active_session, app).skill_path_origin();
let skills = list_skills_if_changed(
let skills = list_skills_for_request(
current_working_directory_location.as_ref(),
&path_origin,
conversation_id,
app,
);
if let Some(skills) = skills {
context.push(AIAgentContext::Skills { skills });
}
context.push(AIAgentContext::Skills { skills });
}
context.extend(additional_context);
@@ -20,7 +20,7 @@ use crate::ai::llms::LLMPreferences;
use crate::ai::openai::client::OpenAIClientConfig;
use crate::ai::provider::ProviderConfig;
use crate::network::NetworkStatus;
use crate::server::server_api::{AIApiError, ServerApiProvider};
use crate::server::server_api::AIApiError;
use crate::{report_error, send_telemetry_from_ctx, AISettings};
/// Maximum number of times a single MAA request is re-sent before the failure is
@@ -159,6 +159,7 @@ impl ResponseStream {
id,
params: api::RequestParams::new_for_test(),
retry_count: 0,
coding_model_fallback_attempted: false,
start_time: Local::now(),
time_to_latest_event: TimeDelta::seconds(0),
cancellation_tx: Some(cancellation_tx),
@@ -233,17 +234,10 @@ impl ResponseStream {
let request_id = Uuid::new_v4();
let provider_config = Self::resolve_provider_config(params.model.as_str(), ctx);
let server_api = ServerApiProvider::as_ref(ctx).get_ai_client().clone();
let params_clone = params.clone();
let _ = ctx.spawn(
async move {
generate_multi_agent_output(
provider_config,
server_api,
params_clone,
cancellation_rx,
)
.await
generate_multi_agent_output(provider_config, params_clone, cancellation_rx).await
},
move |me, stream, ctx| {
me.handle_response_stream_result(request_id, stream, ctx);
@@ -323,18 +317,17 @@ impl ResponseStream {
let request_id = Uuid::new_v4();
self.current_request_id = Some(request_id);
let mut params = self.params.clone();
let params = self.params.clone();
let provider_config = Self::resolve_provider_config(params.model.as_str(), ctx);
let server_api = ServerApiProvider::as_ref(ctx).get_ai_client().clone();
let _ = ctx.spawn(
async move {
generate_multi_agent_output(provider_config, server_api, params, cancellation_rx)
.await
},
move |me, stream, ctx| {
me.handle_response_stream_result(request_id, stream, ctx);
},
);
let _ =
ctx.spawn(
async move {
generate_multi_agent_output(provider_config, params, cancellation_rx).await
},
move |me, stream, ctx| {
me.handle_response_stream_result(request_id, stream, ctx);
},
);
}
fn should_fallback_to_coding_model(
@@ -503,7 +496,7 @@ impl ResponseStream {
self.original_error = Some(format!("{e:?}"));
}
if self.should_fallback_to_coding_model(&e) {
if self.should_fallback_to_coding_model(e) {
log::warn!(
"Thinking model rate-limited; retrying with the profile coding model"
);
@@ -104,7 +104,6 @@ impl SlashCommandRequest {
is_invoke_skill,
controller.context_model.as_ref(ctx),
controller.active_session.as_ref(ctx),
conversation_id,
image_context,
ctx,
);