Skip to main content

systemprompt_agent/models/
context.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use systemprompt_identifiers::{ContextId, McpExecutionId, MessageId, SkillId, TaskId};
4
5pub use systemprompt_models::{
6    CreateContextRequest, UpdateContextRequest, UserContext, UserContextWithStats,
7};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ContextMessage {
11    pub message_id: MessageId,
12    pub role: String,
13    pub created_at: DateTime<Utc>,
14    pub sequence_number: i32,
15    pub parts: Vec<serde_json::Value>,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct ContextDetail {
20    pub context: UserContext,
21    pub messages: Vec<ContextMessage>,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(tag = "type", rename_all = "snake_case")]
26pub enum ContextStateEvent {
27    ToolExecutionCompleted {
28        context_id: ContextId,
29        execution_id: McpExecutionId,
30        tool_name: String,
31        server_name: String,
32        output: Option<String>,
33        #[serde(skip_serializing_if = "Option::is_none")]
34        artifact: Option<super::a2a::Artifact>,
35        status: String,
36        timestamp: DateTime<Utc>,
37    },
38    TaskStatusChanged {
39        task: super::a2a::Task,
40        context_id: ContextId,
41        timestamp: DateTime<Utc>,
42    },
43    ArtifactCreated {
44        artifact: super::a2a::Artifact,
45        task_id: TaskId,
46        context_id: ContextId,
47        timestamp: DateTime<Utc>,
48    },
49    SkillLoaded {
50        skill_id: SkillId,
51        skill_name: String,
52        description: String,
53        request_context: systemprompt_models::execution::context::RequestContext,
54        tool_name: Option<String>,
55        timestamp: DateTime<Utc>,
56    },
57    ContextCreated {
58        context_id: ContextId,
59        context: UserContext,
60        timestamp: DateTime<Utc>,
61    },
62    ContextUpdated {
63        context_id: ContextId,
64        name: String,
65        timestamp: DateTime<Utc>,
66    },
67    ContextDeleted {
68        context_id: ContextId,
69        timestamp: DateTime<Utc>,
70    },
71    Heartbeat {
72        timestamp: DateTime<Utc>,
73    },
74    CurrentAgent {
75        context_id: ContextId,
76        agent_name: Option<String>,
77        timestamp: DateTime<Utc>,
78    },
79}
80
81impl ContextStateEvent {
82    pub fn context_id(&self) -> Option<&str> {
83        match self {
84            Self::ToolExecutionCompleted { context_id, .. } => Some(context_id.as_str()),
85            Self::TaskStatusChanged { context_id, .. } => Some(context_id.as_str()),
86            Self::ArtifactCreated { context_id, .. } => Some(context_id.as_str()),
87            Self::SkillLoaded {
88                request_context, ..
89            } => Some(request_context.context_id().as_str()),
90            Self::ContextCreated { context_id, .. } => Some(context_id.as_str()),
91            Self::ContextUpdated { context_id, .. } => Some(context_id.as_str()),
92            Self::ContextDeleted { context_id, .. } => Some(context_id.as_str()),
93            Self::Heartbeat { .. } => None,
94            Self::CurrentAgent { context_id, .. } => Some(context_id.as_str()),
95        }
96    }
97
98    pub const fn timestamp(&self) -> DateTime<Utc> {
99        match self {
100            Self::ToolExecutionCompleted { timestamp, .. } => *timestamp,
101            Self::TaskStatusChanged { timestamp, .. } => *timestamp,
102            Self::ArtifactCreated { timestamp, .. } => *timestamp,
103            Self::SkillLoaded { timestamp, .. } => *timestamp,
104            Self::ContextCreated { timestamp, .. } => *timestamp,
105            Self::ContextUpdated { timestamp, .. } => *timestamp,
106            Self::ContextDeleted { timestamp, .. } => *timestamp,
107            Self::Heartbeat { timestamp } => *timestamp,
108            Self::CurrentAgent { timestamp, .. } => *timestamp,
109        }
110    }
111}