acp_utils/conversation/
activity.rs1use agent_client_protocol::schema::{MaybeUndefined, v2 as acp};
2use schemars::JsonSchema;
3use serde::Serialize;
4
5#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, JsonSchema)]
7#[serde(rename_all = "snake_case")]
8pub enum Activity {
9 #[default]
10 Idle,
11 Thinking,
12 Responding,
13 RequiresAction,
14 Working,
15}
16
17impl Activity {
18 pub(super) fn after(update: &acp::SessionUpdate) -> Option<Self> {
19 match update {
20 acp::SessionUpdate::AgentMessageChunk(_)
21 | acp::SessionUpdate::StateUpdate(acp::StateUpdate::Running(_)) => Some(Self::Responding),
22 acp::SessionUpdate::StateUpdate(acp::StateUpdate::RequiresAction(_)) => Some(Self::RequiresAction),
23 acp::SessionUpdate::ToolCallUpdate(_) => Some(Self::Working),
24 acp::SessionUpdate::AgentThoughtChunk(chunk) => match &chunk.content {
25 acp::ContentBlock::Text(text) if !text.text.is_empty() => Some(Self::Thinking),
26 _ => None,
27 },
28 acp::SessionUpdate::AgentThought(message) => match &message.content {
29 MaybeUndefined::Value(blocks) if blocks.iter().any(has_content) => Some(Self::Thinking),
30 _ => None,
31 },
32 _ => None,
33 }
34 }
35}
36
37fn has_content(block: &acp::ContentBlock) -> bool {
38 !matches!(block, acp::ContentBlock::Text(text) if text.text.is_empty())
39}