Complete Rig tool lifecycle migration
This commit is contained in:
+20
-2
@@ -24,7 +24,7 @@ use mcp::TemplatableMCPServerInfo;
|
||||
pub use r#impl::generate_multi_agent_output;
|
||||
use serde::Serialize;
|
||||
|
||||
use super::{AIAgentInput, MCPContext, MCPServer, RequestMetadata, Suggestions};
|
||||
use super::{AIAgentAction, AIAgentInput, MCPContext, MCPServer, RequestMetadata, Suggestions};
|
||||
use crate::ai::agent::conversation::AIConversationId;
|
||||
use crate::ai::ambient_agents::AmbientAgentTaskId;
|
||||
use crate::ai::blocklist::{BlocklistAIPermissions, RequestInput, SessionContext};
|
||||
@@ -162,17 +162,35 @@ pub struct RequestParams {
|
||||
pub global_rules: Vec<(String, String)>,
|
||||
}
|
||||
|
||||
pub type Event = Result<warp_multi_agent_api::ResponseEvent, Arc<AIApiError>>;
|
||||
/// Provider/runtime events consumed by the local conversation controller.
|
||||
///
|
||||
/// The legacy response envelope remains at the UI boundary while the local Rig runtime emits
|
||||
/// executable tool proposals directly as Galaxy domain actions. This avoids translating Rig tool
|
||||
/// calls into protobuf only to immediately translate them back before execution.
|
||||
#[derive(Debug)]
|
||||
pub enum StreamEvent {
|
||||
Response(warp_multi_agent_api::ResponseEvent),
|
||||
ToolProposed(AIAgentAction),
|
||||
}
|
||||
|
||||
pub type Event = Result<StreamEvent, Arc<AIApiError>>;
|
||||
pub type LegacyEvent = Result<warp_multi_agent_api::ResponseEvent, Arc<AIApiError>>;
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub type ResponseStream = Pin<Box<dyn Stream<Item = Event> + Send + 'static>>;
|
||||
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub type LegacyResponseStream = Pin<Box<dyn Stream<Item = LegacyEvent> + Send + 'static>>;
|
||||
|
||||
// The WASM version of this type has no bound on `Send`, which is an unnecessary bound when
|
||||
// targeting wasm because the browser is single-threaded (and we don't leverage WebWorkers for async
|
||||
// execution in WoW).
|
||||
#[cfg(target_family = "wasm")]
|
||||
pub type ResponseStream = Pin<Box<dyn Stream<Item = Event>>>;
|
||||
|
||||
#[cfg(target_family = "wasm")]
|
||||
pub type LegacyResponseStream = Pin<Box<dyn Stream<Item = LegacyEvent>>>;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ConversationData {
|
||||
pub id: AIConversationId,
|
||||
|
||||
@@ -6,7 +6,7 @@ use galaxy_core::features::FeatureFlag;
|
||||
use warp_multi_agent_api as api;
|
||||
|
||||
use super::convert_to::convert_input;
|
||||
use super::{ConvertToAPITypeError, RequestParams, ResponseStream};
|
||||
use super::{ConvertToAPITypeError, RequestParams, ResponseStream, StreamEvent};
|
||||
use crate::ai::agent::redaction;
|
||||
use crate::ai::openai::translator as openai_translator;
|
||||
use crate::ai::provider::ProviderConfig;
|
||||
@@ -164,7 +164,9 @@ pub async fn generate_multi_agent_output(
|
||||
|
||||
match openai_translator::execute(translator_request, &mut request).await {
|
||||
Ok(stream) => {
|
||||
let output_stream = stream.take_until(cancellation_rx);
|
||||
let output_stream = stream
|
||||
.map(|event| event.map(StreamEvent::Response))
|
||||
.take_until(cancellation_rx);
|
||||
Ok(Box::pin(output_stream))
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -196,7 +198,9 @@ pub async fn generate_multi_agent_output(
|
||||
|
||||
match crate::ai::bedrock::translator::execute(translator_request, &mut request).await {
|
||||
Ok(stream) => {
|
||||
let output_stream = stream.take_until(cancellation_rx);
|
||||
let output_stream = stream
|
||||
.map(|event| event.map(StreamEvent::Response))
|
||||
.take_until(cancellation_rx);
|
||||
Ok(Box::pin(output_stream))
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
@@ -2227,6 +2227,47 @@ impl AIConversation {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply_domain_tool_proposal(
|
||||
&mut self,
|
||||
stream_id: &ResponseStreamId,
|
||||
terminal_surface_id: EntityId,
|
||||
action: AIAgentAction,
|
||||
ctx: &mut ModelContext<BlocklistAIHistoryModel>,
|
||||
) -> Result<(), UpdateConversationError> {
|
||||
let added_exchanges = self
|
||||
.added_exchanges_by_response
|
||||
.get(stream_id)
|
||||
.ok_or(UpdateConversationError::NoPendingRequest)?;
|
||||
let exchange_id = added_exchanges
|
||||
.iter()
|
||||
.find(|added| added.task_id == action.task_id)
|
||||
.map(|added| added.exchange_id)
|
||||
.ok_or(UpdateConversationError::TaskNotFound)?;
|
||||
let message_id = MessageId::new(action.id.to_string());
|
||||
let exchange = self.get_exchange_to_update(exchange_id)?;
|
||||
match &exchange.output_status {
|
||||
AIAgentOutputStatus::Streaming {
|
||||
output: Some(output),
|
||||
} => output
|
||||
.get_mut()
|
||||
.messages
|
||||
.push(AIAgentOutputMessage::action(message_id, action)),
|
||||
AIAgentOutputStatus::Streaming { output: None } => {
|
||||
return Err(UpdateConversationError::OutputNeverInitialized);
|
||||
}
|
||||
AIAgentOutputStatus::Finished { .. } => {
|
||||
return Err(UpdateConversationError::OutputAlreadyFinished);
|
||||
}
|
||||
}
|
||||
ctx.emit(BlocklistAIHistoryEvent::UpdatedStreamingExchange {
|
||||
exchange_id,
|
||||
terminal_surface_id,
|
||||
conversation_id: self.id,
|
||||
is_hidden: self.hidden_exchanges.contains(&exchange_id),
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn update_cost_and_usage_for_request(
|
||||
&mut self,
|
||||
request_cost: Option<RequestCost>,
|
||||
|
||||
Reference in New Issue
Block a user