Skip to main content

systemprompt_models/a2a/
stream.rs

1//! A2A streaming and send-message result wire types: task status and
2//! artifact update events, the `StreamResponse` oneof, and the
3//! `SendMessageResponse` oneof.
4//!
5//! Copyright (c) systemprompt.io — Business Source License 1.1.
6//! See <https://systemprompt.io> for licensing details.
7
8use serde::{Deserialize, Serialize};
9use systemprompt_identifiers::{ContextId, TaskId};
10
11use super::artifact::Artifact;
12use super::message::Message;
13use super::task::{Task, TaskStatus};
14
15#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
16#[serde(rename_all = "camelCase")]
17pub struct TaskStatusUpdateEvent {
18    pub task_id: TaskId,
19    pub context_id: ContextId,
20    pub status: TaskStatus,
21    // JSON: A2A `TaskStatusUpdateEvent.metadata` is spec-defined as a free-form object.
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
24}
25
26impl TaskStatusUpdateEvent {
27    #[must_use]
28    pub const fn new(task_id: TaskId, context_id: ContextId, status: TaskStatus) -> Self {
29        Self {
30            task_id,
31            context_id,
32            status,
33            metadata: None,
34        }
35    }
36}
37
38#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
39#[serde(rename_all = "camelCase")]
40pub struct TaskArtifactUpdateEvent {
41    pub task_id: TaskId,
42    pub context_id: ContextId,
43    pub artifact: Artifact,
44    #[serde(default)]
45    pub append: bool,
46    #[serde(default)]
47    pub last_chunk: bool,
48    // JSON: A2A `TaskArtifactUpdateEvent.metadata` is spec-defined as a free-form object.
49    #[serde(default, skip_serializing_if = "Option::is_none")]
50    pub metadata: Option<serde_json::Map<String, serde_json::Value>>,
51}
52
53impl TaskArtifactUpdateEvent {
54    #[must_use]
55    pub const fn new(task_id: TaskId, context_id: ContextId, artifact: Artifact) -> Self {
56        Self {
57            task_id,
58            context_id,
59            artifact,
60            append: false,
61            last_chunk: true,
62            metadata: None,
63        }
64    }
65
66    #[must_use]
67    pub const fn chunk(mut self, append: bool, last_chunk: bool) -> Self {
68        self.append = append;
69        self.last_chunk = last_chunk;
70        self
71    }
72}
73
74#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
75#[serde(rename_all = "camelCase")]
76pub enum StreamResponse {
77    Task(Task),
78    Message(Message),
79    StatusUpdate(TaskStatusUpdateEvent),
80    ArtifactUpdate(TaskArtifactUpdateEvent),
81}
82
83#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
84#[serde(rename_all = "camelCase")]
85pub enum SendMessageResult {
86    Task(Box<Task>),
87    Message(Box<Message>),
88}