main
rs 121 lines 5.29 KB
Raw
1 use super::{BlockId, ParticipantId};
2 use byte_unit::Byte;
3 use serde::{Deserialize, Serialize};
4
5 /// AI metadata for correlating terminal blocks with agent commands.
6 /// This allows viewers in shared sessions to associate terminal command blocks
7 /// with the agent tool calls that triggered them.
8 #[derive(Clone, Debug, Serialize, Deserialize)]
9 pub struct AICommandMetadata {
10 /// The tool call ID from the Multi-Agent API protocol.
11 /// Corresponds to action_id on the sharer side.
12 pub tool_call_id: String,
13
14 /// Whether this command is being monitored by an agent as a long-running command.
15 #[serde(default)]
16 pub is_agent_monitored: bool,
17 }
18
19 /// Types of terminal events that need to be ordered against each other.
20 #[derive(Clone, Deserialize, Serialize)]
21 pub enum OrderedTerminalEventType {
22 /// Bytes read off the sharer's pty (session contents).
23 PtyBytesRead {
24 bytes: Vec<u8>,
25 },
26 /// A command is beginning to execute.
27 CommandExecutionStarted {
28 /// The ID of the participant who ran the command.
29 participant_id: ParticipantId,
30 /// AI metadata if this command was executed by an agent.
31 #[serde(default)]
32 ai_metadata: Option<AICommandMetadata>,
33 },
34 CommandExecutionFinished {
35 next_block_id: BlockId,
36 },
37 /// The sharer's terminal was resized.
38 Resize {
39 window_size: WindowSize,
40 },
41 /// The sharer received an AI agent response event. Response events include all information needed to reconstruct a conversation, including:
42 // * The start and end of individual requests
43 // * Incremental agent output
44 // * Echoed user messages and tool call results
45 /// See https://github.com/warpdotdev/warp-proto-apis/blob/6310871f081b5f44b2d4e3e5d8fdfa3008b750b0/apis/multi_agent/v1/response.proto#L16-L17
46 AgentResponseEvent {
47 /// The ID of the participant who sent the query to initiate this agent response.
48 response_initiator: Option<ParticipantId>,
49 /// The base64-encoded MAA ResponseEvent protocol buffer message.
50 response_event: String,
51 /// For forked conversations, this is the original conversation token that the
52 /// conversation was forked from. Viewers use this to link the new server-assigned
53 /// conversation token to an existing conversation created during historical replay.
54 #[serde(default)]
55 forked_from_conversation_token: Option<String>,
56 },
57 /// Marks the start of historical agent conversation replay.
58 /// Viewers should use this to suppress live-conversation specific actions until replay ends
59 /// (e.g. the insertion of the ambient agent conversation tombstone).
60 AgentConversationReplayStarted,
61 /// Marks the end of historical agent conversation replay.
62 AgentConversationReplayEnded,
63 /// Emitted by the sandboxed Oz AgentDriver when the cloud-mode setup phase is complete but no
64 /// initial LLM turn will follow (e.g. empty-prompt local-to-cloud handoff with `--skip-initial-turn`).
65 CloudModeSetupPhaseEnded,
66 }
67
68 /// Represents the size of a PTY. Mimics the winsize struct that
69 /// can be queried via [ioctl](https://man7.org/linux/man-pages/man2/ioctl_tty.2.html).
70 #[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)]
71 pub struct WindowSize {
72 pub num_rows: usize,
73 pub num_cols: usize,
74 }
75
76 /// Override the Debug impl to avoid accidentally leaking sensitive
77 /// data in logs.
78 impl std::fmt::Debug for OrderedTerminalEventType {
79 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
80 match self {
81 Self::PtyBytesRead { .. } => f.write_str("PtyBytesRead"),
82 Self::CommandExecutionStarted { .. } => f.write_str("CommandExecutionStarted"),
83 Self::CommandExecutionFinished { .. } => f.write_str("CommandExecutionFinished"),
84 Self::Resize { .. } => f.write_str("Resize"),
85 Self::AgentResponseEvent { .. } => f.write_str("AgentResponseEvent"),
86 Self::AgentConversationReplayStarted => f.write_str("AgentConversationReplayStarted"),
87 Self::AgentConversationReplayEnded => f.write_str("AgentConversationReplayEnded"),
88 Self::CloudModeSetupPhaseEnded => f.write_str("CloudModeSetupPhaseEnded"),
89 }
90 }
91 }
92
93 impl OrderedTerminalEventType {
94 pub fn num_bytes(&self) -> Byte {
95 match &self {
96 OrderedTerminalEventType::PtyBytesRead { bytes } => bytes.len().into(),
97 OrderedTerminalEventType::AgentResponseEvent { response_event, .. } => {
98 response_event.len().into()
99 }
100 OrderedTerminalEventType::CommandExecutionStarted { .. }
101 | OrderedTerminalEventType::CommandExecutionFinished { .. }
102 | OrderedTerminalEventType::AgentConversationReplayStarted
103 | OrderedTerminalEventType::AgentConversationReplayEnded
104 | OrderedTerminalEventType::CloudModeSetupPhaseEnded
105 | OrderedTerminalEventType::Resize { .. } => Byte::from_u64(0),
106 }
107 }
108 }
109
110 /// Any terminal event where strict ordering against other terminal events is important.
111 #[derive(Clone, Debug, Deserialize, Serialize)]
112 pub struct OrderedTerminalEvent {
113 pub event_no: usize,
114 pub event_type: OrderedTerminalEventType,
115 }
116
117 impl OrderedTerminalEvent {
118 pub fn num_bytes(&self) -> Byte {
119 self.event_type.num_bytes()
120 }
121 }