Carry parent findings into subagents and show follow-up conversation panels

This commit is contained in:
2026-09-17 17:52:29 -05:00
parent 76d492aa75
commit e261258a2f
10 changed files with 390 additions and 20 deletions
+25
View File
@@ -2222,6 +2222,31 @@ impl AIBlock {
.or_default();
}
if let AIAgentActionType::SendMessageToAgent { addresses, .. } = &action.action {
if let [address] = addresses.as_slice() {
let history = BlocklistAIHistoryModel::as_ref(ctx);
let child_id = history
.child_conversations_of(self.client_ids.conversation_id)
.into_iter()
.find(|child| {
child.id().to_string() == *address
|| child.orchestration_agent_id().as_deref()
== Some(address.as_str())
})
.map(|child| child.id());
if let Some(child_id) = child_id {
self.state_handles
.subagent_panel_states
.entry(action.id.clone())
.or_insert_with(|| {
super::agent_view::subagent_inline_panel::SubagentPanelState::new(
child_id,
)
});
}
}
}
if let AIAgentActionType::RunAgents(req) = &action.action {
self.ensure_run_agents_card_view(&action.id, req, ctx);
}
@@ -427,17 +427,6 @@ fn participant_display_names(participants: &[OrchestrationParticipant]) -> Strin
.join(", ")
}
fn participant_for_agent_ids(
agent_ids: &[String],
orchestrator_agent_id: Option<&str>,
app: &AppContext,
) -> Vec<OrchestrationParticipant> {
agent_ids
.iter()
.map(|agent_id| participant_for_agent_id(agent_id, orchestrator_agent_id, app))
.collect()
}
fn render_transcript_row_with_spacing(
data: TranscriptRowData<'_>,
props: Props,
@@ -456,6 +445,36 @@ pub(super) fn render_send_message(
message: &str,
message_id: &MessageId,
app: &AppContext,
) -> Box<dyn Element> {
let message_row =
render_send_message_body(props, action_id, address, subject, message, message_id, app);
let Some(panel) = props.state_handles.subagent_panel_states.get(action_id) else {
return message_row;
};
Flex::column()
.with_cross_axis_alignment(CrossAxisAlignment::Stretch)
.with_child(message_row)
.with_child(
crate::ai::blocklist::agent_view::subagent_inline_panel::render_subagent_inline_panel(
panel,
action_id,
props.terminal_view_id,
app,
)
.with_agent_output_item_spacing(app)
.finish(),
)
.finish()
}
fn render_send_message_body(
props: Props,
action_id: &AIAgentActionId,
address: &[String],
subject: &str,
message: &str,
message_id: &MessageId,
app: &AppContext,
) -> Box<dyn Element> {
let appearance = Appearance::as_ref(app);
let theme = appearance.theme();
@@ -467,8 +486,17 @@ pub(super) fn render_send_message(
.model
.conversation(app)
.and_then(|conversation| orchestrator_agent_id_for_conversation(conversation, app));
let recipient_participants =
participant_for_agent_ids(address, orchestrator_agent_id.as_deref(), app);
let recipient_participants: Vec<_> = address
.iter()
.map(|agent_id| {
participant_for_agent_id_in_orchestration(
agent_id,
orchestrator_agent_id.as_deref(),
props.conversation_id,
app,
)
})
.collect();
let recipients = participant_display_names(&recipient_participants);
if let Some(AIActionStatus::Finished(result)) = &status {
+18
View File
@@ -7646,6 +7646,24 @@ impl BlocklistAIController {
.collect::<HashMap<_, _>>();
let (mut converted_actions, invalid_results) =
convert_provider_tool_batch(&run.action_context, &batch);
// Seed each worker from the current durable transcript, including discoveries
// made in this run that have not reached the persisted conversation yet.
let history = BlocklistAIHistoryModel::as_ref(ctx);
if let Some(parent) = history.conversation(&conversation_id) {
for (action, is_recovery) in &mut converted_actions {
if *is_recovery {
continue;
}
if let AIAgentActionType::RunAgents(request) = &mut action.action {
crate::ai::runtime::add_parent_context(
request,
run.coordinator.run().transcript(),
parent.tool_result_archive(),
parent.progressive_summary(),
);
}
}
}
for result in &invalid_results {
if let Err(error) = run
.coordinator