Skip to main content

ahp_types/
actions.rs

1// Generated from types/*.ts — do not edit.
2//
3// Regenerate with: npm run generate:rust
4
5#![allow(missing_docs)]
6
7#[allow(unused_imports)]
8use crate::common::{AnyValue, JsonObject, StringOrMarkdown, Uri};
9#[allow(unused_imports)]
10use serde::{Deserialize, Serialize};
11#[allow(unused_imports)]
12use serde_repr::{Deserialize_repr, Serialize_repr};
13
14#[allow(unused_imports)]
15use crate::state::{
16    AgentInfo, AgentSelection, Annotation, AnnotationEntry, Changeset, ChangesetFile,
17    ChangesetOperation, ChangesetOperationStatus, ChangesetStatus, ChatInputAnswer,
18    ChatInputRequest, ChatInputResponseKind, ChatInteractivity, ChatOrigin, ChatSummary,
19    ConfirmationOption, Customization, ErrorInfo, McpServerState, Message, ModelSelection,
20    PendingMessageKind, ResponsePart, SessionActiveClient, TerminalClaim, TerminalInfo, TextRange,
21    ToolCallCancellationReason, ToolCallConfirmationReason, ToolCallContributor, ToolCallResult,
22    ToolDefinition, ToolResultContent, UsageInfo,
23};
24
25// ─── ActionType ──────────────────────────────────────────────────────
26
27/// Discriminant values for all state actions.
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub enum ActionType {
30    #[serde(rename = "root/agentsChanged")]
31    RootAgentsChanged,
32    #[serde(rename = "root/activeSessionsChanged")]
33    RootActiveSessionsChanged,
34    #[serde(rename = "session/ready")]
35    SessionReady,
36    #[serde(rename = "session/creationFailed")]
37    SessionCreationFailed,
38    #[serde(rename = "session/chatAdded")]
39    SessionChatAdded,
40    #[serde(rename = "session/chatRemoved")]
41    SessionChatRemoved,
42    #[serde(rename = "session/chatUpdated")]
43    SessionChatUpdated,
44    #[serde(rename = "session/defaultChatChanged")]
45    SessionDefaultChatChanged,
46    #[serde(rename = "chat/turnStarted")]
47    ChatTurnStarted,
48    #[serde(rename = "chat/delta")]
49    ChatDelta,
50    #[serde(rename = "chat/responsePart")]
51    ChatResponsePart,
52    #[serde(rename = "chat/toolCallStart")]
53    ChatToolCallStart,
54    #[serde(rename = "chat/toolCallDelta")]
55    ChatToolCallDelta,
56    #[serde(rename = "chat/toolCallReady")]
57    ChatToolCallReady,
58    #[serde(rename = "chat/toolCallConfirmed")]
59    ChatToolCallConfirmed,
60    #[serde(rename = "chat/toolCallComplete")]
61    ChatToolCallComplete,
62    #[serde(rename = "chat/toolCallResultConfirmed")]
63    ChatToolCallResultConfirmed,
64    #[serde(rename = "chat/toolCallContentChanged")]
65    ChatToolCallContentChanged,
66    #[serde(rename = "chat/turnComplete")]
67    ChatTurnComplete,
68    #[serde(rename = "chat/turnCancelled")]
69    ChatTurnCancelled,
70    #[serde(rename = "chat/error")]
71    ChatError,
72    #[serde(rename = "chat/activityChanged")]
73    ChatActivityChanged,
74    #[serde(rename = "session/titleChanged")]
75    SessionTitleChanged,
76    #[serde(rename = "chat/usage")]
77    ChatUsage,
78    #[serde(rename = "chat/reasoning")]
79    ChatReasoning,
80    #[serde(rename = "session/serverToolsChanged")]
81    SessionServerToolsChanged,
82    #[serde(rename = "session/activeClientSet")]
83    SessionActiveClientSet,
84    #[serde(rename = "session/activeClientRemoved")]
85    SessionActiveClientRemoved,
86    #[serde(rename = "chat/pendingMessageSet")]
87    ChatPendingMessageSet,
88    #[serde(rename = "chat/pendingMessageRemoved")]
89    ChatPendingMessageRemoved,
90    #[serde(rename = "chat/queuedMessagesReordered")]
91    ChatQueuedMessagesReordered,
92    #[serde(rename = "chat/draftChanged")]
93    ChatDraftChanged,
94    #[serde(rename = "chat/inputRequested")]
95    ChatInputRequested,
96    #[serde(rename = "chat/inputAnswerChanged")]
97    ChatInputAnswerChanged,
98    #[serde(rename = "chat/inputCompleted")]
99    ChatInputCompleted,
100    #[serde(rename = "session/customizationsChanged")]
101    SessionCustomizationsChanged,
102    #[serde(rename = "session/customizationToggled")]
103    SessionCustomizationToggled,
104    #[serde(rename = "session/customizationUpdated")]
105    SessionCustomizationUpdated,
106    #[serde(rename = "session/customizationRemoved")]
107    SessionCustomizationRemoved,
108    #[serde(rename = "session/mcpServerStateChanged")]
109    SessionMcpServerStateChanged,
110    #[serde(rename = "chat/truncated")]
111    ChatTruncated,
112    #[serde(rename = "session/isReadChanged")]
113    SessionIsReadChanged,
114    #[serde(rename = "session/isArchivedChanged")]
115    SessionIsArchivedChanged,
116    #[serde(rename = "session/activityChanged")]
117    SessionActivityChanged,
118    #[serde(rename = "session/changesetsChanged")]
119    SessionChangesetsChanged,
120    #[serde(rename = "session/configChanged")]
121    SessionConfigChanged,
122    #[serde(rename = "session/metaChanged")]
123    SessionMetaChanged,
124    #[serde(rename = "changeset/statusChanged")]
125    ChangesetStatusChanged,
126    #[serde(rename = "changeset/fileSet")]
127    ChangesetFileSet,
128    #[serde(rename = "changeset/fileRemoved")]
129    ChangesetFileRemoved,
130    #[serde(rename = "changeset/contentChanged")]
131    ChangesetContentChanged,
132    #[serde(rename = "changeset/operationsChanged")]
133    ChangesetOperationsChanged,
134    #[serde(rename = "changeset/operationStatusChanged")]
135    ChangesetOperationStatusChanged,
136    #[serde(rename = "changeset/cleared")]
137    ChangesetCleared,
138    #[serde(rename = "annotations/set")]
139    AnnotationsSet,
140    #[serde(rename = "annotations/updated")]
141    AnnotationsUpdated,
142    #[serde(rename = "annotations/removed")]
143    AnnotationsRemoved,
144    #[serde(rename = "annotations/entrySet")]
145    AnnotationsEntrySet,
146    #[serde(rename = "annotations/entryRemoved")]
147    AnnotationsEntryRemoved,
148    #[serde(rename = "root/terminalsChanged")]
149    RootTerminalsChanged,
150    #[serde(rename = "root/configChanged")]
151    RootConfigChanged,
152    #[serde(rename = "terminal/data")]
153    TerminalData,
154    #[serde(rename = "terminal/input")]
155    TerminalInput,
156    #[serde(rename = "terminal/resized")]
157    TerminalResized,
158    #[serde(rename = "terminal/claimed")]
159    TerminalClaimed,
160    #[serde(rename = "terminal/titleChanged")]
161    TerminalTitleChanged,
162    #[serde(rename = "terminal/cwdChanged")]
163    TerminalCwdChanged,
164    #[serde(rename = "terminal/exited")]
165    TerminalExited,
166    #[serde(rename = "terminal/cleared")]
167    TerminalCleared,
168    #[serde(rename = "terminal/commandDetectionAvailable")]
169    TerminalCommandDetectionAvailable,
170    #[serde(rename = "terminal/commandExecuted")]
171    TerminalCommandExecuted,
172    #[serde(rename = "terminal/commandFinished")]
173    TerminalCommandFinished,
174    #[serde(rename = "resourceWatch/changed")]
175    ResourceWatchChanged,
176}
177
178// ─── Action Envelope ─────────────────────────────────────────────────
179
180/// Identifies the client that originally dispatched an action.
181#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
182#[serde(rename_all = "camelCase")]
183pub struct ActionOrigin {
184    pub client_id: String,
185    pub client_seq: i64,
186}
187
188/// Every action is wrapped in an `ActionEnvelope`.
189///
190/// The envelope identifies the channel the action belongs to (e.g.
191/// `ahp-root://` for root actions, the session URI for session actions, the
192/// terminal URI for terminal actions). Individual action payloads carry only
193/// fields that are intrinsic to the action; the channel comes from the
194/// envelope so that any subscribable resource can route its actions uniformly.
195#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
196#[serde(rename_all = "camelCase")]
197pub struct ActionEnvelope {
198    /// Channel URI this action belongs to.
199    pub channel: Uri,
200    pub action: StateAction,
201    pub server_seq: u64,
202    #[serde(default, skip_serializing_if = "Option::is_none")]
203    pub origin: Option<ActionOrigin>,
204    #[serde(default, skip_serializing_if = "Option::is_none")]
205    pub rejection_reason: Option<String>,
206}
207
208// ─── Action Payloads ─────────────────────────────────────────────────
209
210/// Fired when available agent backends or their models change.
211#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
212#[serde(rename_all = "camelCase")]
213pub struct RootAgentsChangedAction {
214    /// Updated agent list
215    pub agents: Vec<AgentInfo>,
216}
217
218/// Fired when the number of active sessions changes.
219#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
220#[serde(rename_all = "camelCase")]
221pub struct RootActiveSessionsChangedAction {
222    /// Current count of active sessions
223    pub active_sessions: i64,
224}
225
226/// Fired when agent-host configuration values change.
227///
228/// By default, the reducer merges the new values into `state.config.values`.
229/// Set `replace` to `true` to replace all values instead of merging.
230#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
231#[serde(rename_all = "camelCase")]
232pub struct RootConfigChangedAction {
233    /// Updated config values
234    pub config: JsonObject,
235    /// When `true`, replaces all config values instead of merging
236    #[serde(default, skip_serializing_if = "Option::is_none")]
237    pub replace: Option<bool>,
238}
239
240/// Session backend initialized successfully.
241#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
242#[serde(rename_all = "camelCase")]
243pub struct SessionReadyAction {}
244
245/// Session backend failed to initialize.
246#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
247#[serde(rename_all = "camelCase")]
248pub struct SessionCreationFailedAction {
249    /// Error details
250    pub error: ErrorInfo,
251}
252
253/// A chat was added to this session's catalog. Upsert semantics: if a chat
254/// with the same `summary.resource` already exists, the existing entry is
255/// replaced.
256///
257/// Mirrors the root-channel `root/sessionAdded` notification.
258#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
259#[serde(rename_all = "camelCase")]
260pub struct SessionChatAddedAction {
261    /// The full summary of the newly added (or upserted) chat.
262    pub summary: ChatSummary,
263}
264
265/// A chat was removed from this session's catalog. No-op when no entry matches.
266///
267/// Mirrors the root-channel `root/sessionRemoved` notification.
268#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
269#[serde(rename_all = "camelCase")]
270pub struct SessionChatRemovedAction {
271    /// The URI of the chat to remove.
272    pub chat: Uri,
273}
274
275/// One existing chat's summary fields changed.
276///
277/// Partial-update semantics: only fields present in `changes` are written;
278/// omitted fields are preserved. Identity fields (`resource`) MUST NOT be
279/// carried in `changes`. No-op when no entry with `chat` exists — clients
280/// SHOULD then wait for a {@link SessionChatAddedAction | `session/chatAdded`}.
281///
282/// Mirrors the root-channel `root/sessionSummaryChanged` notification.
283#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
284#[serde(rename_all = "camelCase")]
285pub struct SessionChatUpdatedAction {
286    /// The URI of the chat whose summary changed.
287    pub chat: Uri,
288    /// Mutable summary fields that changed; omitted fields are unchanged.
289    ///
290    /// Identity fields (`resource`) never change and MUST be omitted by
291    /// senders; receivers SHOULD ignore them if present.
292    pub changes: PartialChatSummary,
293}
294
295/// The default chat input-routing hint for this session changed.
296#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
297#[serde(rename_all = "camelCase")]
298pub struct SessionDefaultChatChangedAction {
299    /// New default chat URI, or `undefined` to clear the hint.
300    #[serde(default, skip_serializing_if = "Option::is_none")]
301    pub default_chat: Option<Uri>,
302}
303
304/// A new message has been sent to the agent, and a new turn starts.
305///
306/// A client is only allowed to send {@link MessageKind.User} messages.
307#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
308#[serde(rename_all = "camelCase")]
309pub struct ChatTurnStartedAction {
310    /// Turn identifier
311    pub turn_id: String,
312    /// The new message
313    pub message: Message,
314    /// If this turn was auto-started from a queued message, the ID of that message
315    #[serde(default, skip_serializing_if = "Option::is_none")]
316    pub queued_message_id: Option<String>,
317    /// Additional provider-specific metadata for this action.
318    ///
319    /// Clients MAY look for well-known keys here to provide enhanced UI, and
320    /// agent hosts MAY use it to carry per-event context that does not fit any
321    /// other field — for example, attributing the event to a specific agent
322    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
323    /// convention.
324    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
325    pub meta: Option<JsonObject>,
326}
327
328/// Streaming text chunk from the assistant, appended to a specific response part.
329///
330/// The server MUST first emit a `chat/responsePart` to create the target
331/// part (markdown or reasoning), then use this action to append text to it.
332#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
333#[serde(rename_all = "camelCase")]
334pub struct ChatDeltaAction {
335    /// Turn identifier
336    pub turn_id: String,
337    /// Identifier of the response part to append to
338    pub part_id: String,
339    /// Text chunk
340    pub content: String,
341    /// Additional provider-specific metadata for this action.
342    ///
343    /// Clients MAY look for well-known keys here to provide enhanced UI, and
344    /// agent hosts MAY use it to carry per-event context that does not fit any
345    /// other field — for example, attributing the event to a specific agent
346    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
347    /// convention.
348    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
349    pub meta: Option<JsonObject>,
350}
351
352/// Structured content appended to the response.
353#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
354#[serde(rename_all = "camelCase")]
355pub struct ChatResponsePartAction {
356    /// Turn identifier
357    pub turn_id: String,
358    /// Response part (markdown or content ref)
359    pub part: ResponsePart,
360    /// Additional provider-specific metadata for this action.
361    ///
362    /// Clients MAY look for well-known keys here to provide enhanced UI, and
363    /// agent hosts MAY use it to carry per-event context that does not fit any
364    /// other field — for example, attributing the event to a specific agent
365    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
366    /// convention.
367    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
368    pub meta: Option<JsonObject>,
369}
370
371/// A tool call begins — parameters are streaming from the LM.
372///
373/// The server sets {@link ToolCallContributor | `contributor`} to identify
374/// the origin of the tool. For client-provided tools, the named client is
375/// responsible for executing the tool once it reaches the `running` state
376/// and dispatching `chat/toolCallComplete`. For MCP-served tools, the
377/// server executes the call against the named `McpServerCustomization`.
378#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
379#[serde(rename_all = "camelCase")]
380pub struct ChatToolCallStartAction {
381    /// Turn identifier
382    pub turn_id: String,
383    /// Tool call identifier
384    pub tool_call_id: String,
385    /// Additional provider-specific metadata for this tool call.
386    ///
387    /// Clients MAY look for well-known keys here to provide enhanced UI.
388    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
389    /// indicates the tool operated on a terminal (both `input` and `output` may
390    /// contain escape sequences).
391    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
392    pub meta: Option<JsonObject>,
393    /// Internal tool name (for debugging/logging)
394    pub tool_name: String,
395    /// Human-readable tool name
396    pub display_name: String,
397    /// Reference to the contributor of the tool being called. Absent for
398    /// server-side tools that are not contributed by a client or MCP server.
399    #[serde(default, skip_serializing_if = "Option::is_none")]
400    pub contributor: Option<ToolCallContributor>,
401}
402
403/// Streaming partial parameters for a tool call.
404#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
405#[serde(rename_all = "camelCase")]
406pub struct ChatToolCallDeltaAction {
407    /// Turn identifier
408    pub turn_id: String,
409    /// Tool call identifier
410    pub tool_call_id: String,
411    /// Additional provider-specific metadata for this tool call.
412    ///
413    /// Clients MAY look for well-known keys here to provide enhanced UI.
414    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
415    /// indicates the tool operated on a terminal (both `input` and `output` may
416    /// contain escape sequences).
417    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
418    pub meta: Option<JsonObject>,
419    /// Partial parameter content to append
420    pub content: String,
421    /// Updated progress message
422    #[serde(default, skip_serializing_if = "Option::is_none")]
423    pub invocation_message: Option<StringOrMarkdown>,
424}
425
426/// Tool call parameters are complete, or a running tool requires re-confirmation.
427///
428/// When dispatched for a `streaming` tool call, transitions to `pending-confirmation`
429/// or directly to `running` if `confirmed` is set.
430///
431/// When dispatched for a `running` tool call (e.g. mid-execution permission needed),
432/// transitions back to `pending-confirmation`. The `invocationMessage` and `_meta`
433/// SHOULD be updated to describe the specific confirmation needed. Clients use the
434/// standard `chat/toolCallConfirmed` flow to approve or deny.
435///
436/// For client-provided tools, the server typically sets `confirmed` to
437/// `'not-needed'` so the tool transitions directly to `running`, where the
438/// owning client can begin execution immediately.
439#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
440#[serde(rename_all = "camelCase")]
441pub struct ChatToolCallReadyAction {
442    /// Turn identifier
443    pub turn_id: String,
444    /// Tool call identifier
445    pub tool_call_id: String,
446    /// Additional provider-specific metadata for this tool call.
447    ///
448    /// Clients MAY look for well-known keys here to provide enhanced UI.
449    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
450    /// indicates the tool operated on a terminal (both `input` and `output` may
451    /// contain escape sequences).
452    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
453    pub meta: Option<JsonObject>,
454    /// Message describing what the tool will do or what confirmation is needed
455    pub invocation_message: StringOrMarkdown,
456    /// Raw tool input
457    #[serde(default, skip_serializing_if = "Option::is_none")]
458    pub tool_input: Option<String>,
459    /// Short title for the confirmation prompt (e.g. `"Run in terminal"`, `"Write file"`)
460    #[serde(default, skip_serializing_if = "Option::is_none")]
461    pub confirmation_title: Option<StringOrMarkdown>,
462    /// File edits that this tool call will perform, for preview before confirmation
463    #[serde(default, skip_serializing_if = "Option::is_none")]
464    pub edits: Option<AnyValue>,
465    /// Whether the agent host allows the client to edit the tool's input parameters before confirming
466    #[serde(default, skip_serializing_if = "Option::is_none")]
467    pub editable: Option<bool>,
468    /// If set, the tool was auto-confirmed and transitions directly to `running`
469    #[serde(default, skip_serializing_if = "Option::is_none")]
470    pub confirmed: Option<ToolCallConfirmationReason>,
471    /// Options the server offers for this confirmation. When present, the client
472    /// SHOULD render these instead of a plain approve/deny UI. Each option
473    /// belongs to a {@link ConfirmationOptionGroup} so the client can still
474    /// categorise the choices.
475    #[serde(default, skip_serializing_if = "Option::is_none")]
476    pub options: Option<Vec<ConfirmationOption>>,
477}
478
479/// Client approves or denies a pending tool call (merged approved + denied variants).
480#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
481#[serde(rename_all = "camelCase")]
482pub struct ChatToolCallConfirmedAction {
483    pub turn_id: String,
484    pub tool_call_id: String,
485    /// Additional provider-specific metadata for this tool call.
486    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
487    pub meta: Option<JsonObject>,
488    /// Whether the tool call was approved.
489    pub approved: bool,
490    /// How the tool was confirmed (present when approved).
491    #[serde(default, skip_serializing_if = "Option::is_none")]
492    pub confirmed: Option<ToolCallConfirmationReason>,
493    /// Why the tool was cancelled (present when denied).
494    #[serde(default, skip_serializing_if = "Option::is_none")]
495    pub reason: Option<ToolCallCancellationReason>,
496    /// Edited tool input parameters, if the client modified them before confirming.
497    #[serde(default, skip_serializing_if = "Option::is_none")]
498    pub edited_tool_input: Option<String>,
499    /// What the user suggested doing instead (present when denied).
500    #[serde(default, skip_serializing_if = "Option::is_none")]
501    pub user_suggestion: Option<Message>,
502    /// Explanation for the denial.
503    #[serde(default, skip_serializing_if = "Option::is_none")]
504    pub reason_message: Option<StringOrMarkdown>,
505    /// ID of the selected confirmation option, if the server provided options.
506    #[serde(default, skip_serializing_if = "Option::is_none")]
507    pub selected_option_id: Option<String>,
508}
509
510/// Tool execution finished. Transitions to `completed` or `pending-result-confirmation`
511/// if `requiresResultConfirmation` is `true`.
512///
513/// For client-provided tools (whose tool call state carries a client
514/// `ToolCallContributor` with a `clientId`), the owning client dispatches this
515/// action with the execution result. The server SHOULD reject this action if the
516/// dispatching client does not match the contributor's `clientId`.
517///
518/// Servers waiting on a client tool call MAY time out after a reasonable duration
519/// if the implementing client disconnects or becomes unresponsive, and dispatch
520/// this action with `result.success = false` and an appropriate error.
521#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
522#[serde(rename_all = "camelCase")]
523pub struct ChatToolCallCompleteAction {
524    /// Turn identifier
525    pub turn_id: String,
526    /// Tool call identifier
527    pub tool_call_id: String,
528    /// Additional provider-specific metadata for this tool call.
529    ///
530    /// Clients MAY look for well-known keys here to provide enhanced UI.
531    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
532    /// indicates the tool operated on a terminal (both `input` and `output` may
533    /// contain escape sequences).
534    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
535    pub meta: Option<JsonObject>,
536    /// Execution result
537    pub result: ToolCallResult,
538    /// If true, the result requires client approval before finalizing
539    #[serde(default, skip_serializing_if = "Option::is_none")]
540    pub requires_result_confirmation: Option<bool>,
541}
542
543/// Client approves or denies a tool's result.
544///
545/// If `approved` is `false`, the tool transitions to `cancelled` with reason `result-denied`.
546#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
547#[serde(rename_all = "camelCase")]
548pub struct ChatToolCallResultConfirmedAction {
549    /// Turn identifier
550    pub turn_id: String,
551    /// Tool call identifier
552    pub tool_call_id: String,
553    /// Additional provider-specific metadata for this tool call.
554    ///
555    /// Clients MAY look for well-known keys here to provide enhanced UI.
556    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
557    /// indicates the tool operated on a terminal (both `input` and `output` may
558    /// contain escape sequences).
559    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
560    pub meta: Option<JsonObject>,
561    /// Whether the result was approved
562    pub approved: bool,
563}
564
565/// Partial content produced while a tool is still executing.
566///
567/// Replaces the `content` array on the running tool call state. Clients can
568/// use this to display live feedback (e.g. a terminal reference) before the
569/// tool completes.
570///
571/// For client-provided tools (whose tool call state carries a client
572/// `ToolCallContributor` with a `clientId`), the owning client dispatches this
573/// action to stream intermediate content while executing. The server SHOULD
574/// reject this action if the dispatching client does not match the contributor's
575/// `clientId`.
576#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
577#[serde(rename_all = "camelCase")]
578pub struct ChatToolCallContentChangedAction {
579    /// Turn identifier
580    pub turn_id: String,
581    /// Tool call identifier
582    pub tool_call_id: String,
583    /// Additional provider-specific metadata for this tool call.
584    ///
585    /// Clients MAY look for well-known keys here to provide enhanced UI.
586    /// For example, a `ptyTerminal` key with `{ input: string; output: string }`
587    /// indicates the tool operated on a terminal (both `input` and `output` may
588    /// contain escape sequences).
589    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
590    pub meta: Option<JsonObject>,
591    /// The current partial content for the running tool call
592    pub content: Vec<ToolResultContent>,
593}
594
595/// Turn finished — the assistant is idle.
596#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
597#[serde(rename_all = "camelCase")]
598pub struct ChatTurnCompleteAction {
599    /// Turn identifier
600    pub turn_id: String,
601    /// Additional provider-specific metadata for this action.
602    ///
603    /// Clients MAY look for well-known keys here to provide enhanced UI, and
604    /// agent hosts MAY use it to carry per-event context that does not fit any
605    /// other field — for example, attributing the event to a specific agent
606    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
607    /// convention.
608    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
609    pub meta: Option<JsonObject>,
610}
611
612/// Turn was aborted; server stops processing.
613#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
614#[serde(rename_all = "camelCase")]
615pub struct ChatTurnCancelledAction {
616    /// Turn identifier
617    pub turn_id: String,
618    /// Additional provider-specific metadata for this action.
619    ///
620    /// Clients MAY look for well-known keys here to provide enhanced UI, and
621    /// agent hosts MAY use it to carry per-event context that does not fit any
622    /// other field — for example, attributing the event to a specific agent
623    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
624    /// convention.
625    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
626    pub meta: Option<JsonObject>,
627}
628
629/// Error during turn processing.
630#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
631#[serde(rename_all = "camelCase")]
632pub struct ChatErrorAction {
633    /// Turn identifier
634    pub turn_id: String,
635    /// Error details
636    pub error: ErrorInfo,
637    /// Additional provider-specific metadata for this action.
638    ///
639    /// Clients MAY look for well-known keys here to provide enhanced UI, and
640    /// agent hosts MAY use it to carry per-event context that does not fit any
641    /// other field — for example, attributing the event to a specific agent
642    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
643    /// convention.
644    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
645    pub meta: Option<JsonObject>,
646}
647
648/// The activity description of this chat changed.
649///
650/// Dispatched by the server to indicate what the chat is currently doing
651/// (e.g. running a tool, thinking). Clear activity by omitting it or setting it
652/// to `undefined`.
653/// Producers SHOULD also update the parent session's chat catalog with
654/// `session/chatUpdated` so `ChatSummary.activity` stays in sync.
655#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
656#[serde(rename_all = "camelCase")]
657pub struct ChatActivityChangedAction {
658    /// Human-readable description of current activity; omit or set `undefined` to clear
659    #[serde(default, skip_serializing_if = "Option::is_none")]
660    pub activity: Option<String>,
661}
662
663/// Session title updated. Fired by the server when the title is auto-generated
664/// from conversation, or dispatched by a client to rename a session.
665#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
666#[serde(rename_all = "camelCase")]
667pub struct SessionTitleChangedAction {
668    /// New title
669    pub title: String,
670}
671
672/// Token usage report for a turn.
673#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
674#[serde(rename_all = "camelCase")]
675pub struct ChatUsageAction {
676    /// Turn identifier
677    pub turn_id: String,
678    /// Token usage data
679    pub usage: UsageInfo,
680    /// Additional provider-specific metadata for this action.
681    ///
682    /// Clients MAY look for well-known keys here to provide enhanced UI, and
683    /// agent hosts MAY use it to carry per-event context that does not fit any
684    /// other field — for example, attributing the event to a specific agent
685    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
686    /// convention.
687    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
688    pub meta: Option<JsonObject>,
689}
690
691/// Reasoning/thinking text from the model, appended to a specific reasoning response part.
692///
693/// The server MUST first emit a `chat/responsePart` to create the target
694/// reasoning part, then use this action to append text to it.
695#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
696#[serde(rename_all = "camelCase")]
697pub struct ChatReasoningAction {
698    /// Turn identifier
699    pub turn_id: String,
700    /// Identifier of the reasoning response part to append to
701    pub part_id: String,
702    /// Reasoning text chunk
703    pub content: String,
704    /// Additional provider-specific metadata for this action.
705    ///
706    /// Clients MAY look for well-known keys here to provide enhanced UI, and
707    /// agent hosts MAY use it to carry per-event context that does not fit any
708    /// other field — for example, attributing the event to a specific agent
709    /// (such as a sub-agent acting within the turn). Mirrors the MCP `_meta`
710    /// convention.
711    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
712    pub meta: Option<JsonObject>,
713}
714
715/// The read state of the session changed.
716///
717/// Dispatched by a client to mark a session as read (e.g. after viewing it)
718/// or unread (e.g. after new activity since the client last looked at it).
719#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
720#[serde(rename_all = "camelCase")]
721pub struct SessionIsReadChangedAction {
722    /// Whether the session has been read
723    pub is_read: bool,
724}
725
726/// The archived state of the session changed.
727///
728/// Dispatched by a client to archive a session (e.g. the task is
729/// complete) or to unarchive it.
730#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
731#[serde(rename_all = "camelCase")]
732pub struct SessionIsArchivedChangedAction {
733    /// Whether the session is archived
734    pub is_archived: bool,
735}
736
737/// The activity description of the session changed.
738///
739/// Dispatched by the server to indicate what the session is currently doing
740/// (e.g. running a tool, thinking). Clear activity by setting it to `undefined`.
741#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
742#[serde(rename_all = "camelCase")]
743pub struct SessionActivityChangedAction {
744    /// Human-readable description of current activity, or `undefined` to clear
745    #[serde(default, skip_serializing_if = "Option::is_none")]
746    pub activity: Option<String>,
747}
748
749/// The {@link Changeset | catalogue of changesets} the agent host
750/// advertises for this session changed. Replaces
751/// {@link SessionState.changesets | `state.changesets`} entirely
752/// (full-replacement semantics) — set to `undefined` to clear the
753/// catalogue.
754///
755/// Producers dispatch this whenever entries are added or removed. The
756/// fan-out happens through this action so observers see catalogue
757/// mutations in the same {@link ChangesetAction | per-changeset} action
758/// stream they already follow for file-level updates.
759#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
760#[serde(rename_all = "camelCase")]
761pub struct SessionChangesetsChangedAction {
762    /// New catalogue, or `undefined` to clear it
763    #[serde(default, skip_serializing_if = "Option::is_none")]
764    pub changesets: Option<Vec<Changeset>>,
765}
766
767/// Server tools for this session have changed.
768///
769/// Full-replacement semantics: the `tools` array replaces the previous `serverTools` entirely.
770#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
771#[serde(rename_all = "camelCase")]
772pub struct SessionServerToolsChangedAction {
773    /// Updated server tools list (full replacement)
774    pub tools: Vec<ToolDefinition>,
775}
776
777/// An active client for this session was added or updated.
778///
779/// Upsert semantics keyed by {@link SessionActiveClient.clientId | `clientId`}:
780/// a client dispatches this action with its own `SessionActiveClient` to join
781/// the session's active clients or refresh its entry, replacing any existing
782/// entry that has the same `clientId`. Multiple clients may be active at once.
783/// This is also how a client updates its published tools or customizations —
784/// re-dispatch with the full, updated entry. Use
785/// {@link SessionActiveClientRemovedAction | `session/activeClientRemoved`} to
786/// leave. The server SHOULD automatically dispatch that removal when an active
787/// client disconnects.
788#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
789#[serde(rename_all = "camelCase")]
790pub struct SessionActiveClientSetAction {
791    /// The active client to add or update, matched by `clientId`.
792    pub active_client: SessionActiveClient,
793}
794
795/// An active client was removed from this session.
796///
797/// Removes the entry for the client identified by `clientId` from
798/// {@link SessionState.activeClients}; a no-op when no entry matches.
799///
800/// The host SHOULD dispatch this automatically when a client stops participating
801/// in the session — for example when it unsubscribes from the session channel,
802/// when it disconnects and does not reconnect within a host-defined grace
803/// period, or when a `reconnect` command's `subscriptions` omit a session the
804/// client was still active in. When removing a client, the host SHOULD also
805/// cancel that client's in-flight tool calls — those whose tool call state
806/// carries a client `ToolCallContributor` with the matching `clientId` — by
807/// dispatching `chat/toolCallComplete` with `result.success = false`. (There is
808/// no per-tool-call server cancel; a failed completion is the cancellation
809/// mechanism, and the call ends in `completed` status with a failed result.)
810#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
811#[serde(rename_all = "camelCase")]
812pub struct SessionActiveClientRemovedAction {
813    /// The `clientId` of the active client to remove.
814    pub client_id: String,
815}
816
817/// A pending message was set (upsert semantics: creates or replaces).
818///
819/// For steering messages, this always replaces the single steering message.
820/// For queued messages, if a message with the given `id` already exists it is
821/// updated in place; otherwise it is appended to the queue. If the chat is
822/// idle when a queued message is set, the server SHOULD immediately consume it
823/// and start a new turn.
824///
825/// A client is only allowed to send {@link MessageKind.User} messages.
826#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
827#[serde(rename_all = "camelCase")]
828pub struct ChatPendingMessageSetAction {
829    /// Whether this is a steering or queued message
830    pub kind: PendingMessageKind,
831    /// Unique identifier for this pending message
832    pub id: String,
833    /// The message content
834    pub message: Message,
835}
836
837/// A pending message was removed (steering or queued).
838///
839/// Dispatched by clients to cancel a pending message, or by the server when
840/// it consumes a message (e.g. starting a turn from a queued message or
841/// injecting a steering message into the current turn).
842#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
843#[serde(rename_all = "camelCase")]
844pub struct ChatPendingMessageRemovedAction {
845    /// Whether this is a steering or queued message
846    pub kind: PendingMessageKind,
847    /// Identifier of the pending message to remove
848    pub id: String,
849}
850
851/// Reorder the queued messages.
852///
853/// The `order` array contains the IDs of queued messages in their new
854/// desired order. IDs not present in the current queue are ignored.
855/// Queued messages whose IDs are absent from `order` are appended at
856/// the end in their original relative order (so a client with a stale
857/// view of the queue never silently drops messages).
858#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
859#[serde(rename_all = "camelCase")]
860pub struct ChatQueuedMessagesReorderedAction {
861    /// Queued message IDs in the desired order
862    pub order: Vec<String>,
863}
864
865/// The chat's draft input changed.
866///
867/// Clients MAY periodically sync their local input state — the message the user
868/// is composing, including its {@link Message.model | model} /
869/// {@link Message.agent | agent} selection and attachments — into the chat's
870/// {@link ChatState.draft | `draft`} so it survives reloads and is visible to
871/// other clients viewing the same chat. Eager syncing is **not** required;
872/// clients SHOULD debounce and MAY sync only at convenient points. Set `draft`
873/// to `undefined` to clear it (e.g. once the message is sent).
874///
875/// A client is only allowed to draft {@link MessageKind.User} messages.
876#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
877#[serde(rename_all = "camelCase")]
878pub struct ChatDraftChangedAction {
879    /// New draft message, or `undefined` to clear it
880    #[serde(default, skip_serializing_if = "Option::is_none")]
881    pub draft: Option<Message>,
882}
883
884/// A session requested input from the user.
885///
886/// Full-request upsert semantics: the `request` replaces any existing request
887/// with the same `id`, or is appended if it is new. Answer drafts are preserved
888/// unless `request.answers` is provided.
889#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
890#[serde(rename_all = "camelCase")]
891pub struct ChatInputRequestedAction {
892    /// Input request to create or replace
893    pub request: ChatInputRequest,
894}
895
896/// A client updated, submitted, skipped, or removed a single in-progress answer.
897///
898/// Dispatching with `answer: undefined` removes that question's answer draft.
899#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
900#[serde(rename_all = "camelCase")]
901pub struct ChatInputAnswerChangedAction {
902    /// Input request identifier
903    pub request_id: String,
904    /// Question identifier within the input request
905    pub question_id: String,
906    /// Updated answer, or `undefined` to clear an answer draft
907    #[serde(default, skip_serializing_if = "Option::is_none")]
908    pub answer: Option<ChatInputAnswer>,
909}
910
911/// A client accepted, declined, or cancelled a session input request.
912///
913/// If accepted, the server uses `answers` (when provided) plus the request's
914/// synced answer state to resume the blocked operation.
915#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
916#[serde(rename_all = "camelCase")]
917pub struct ChatInputCompletedAction {
918    /// Input request identifier
919    pub request_id: String,
920    /// Completion outcome
921    pub response: ChatInputResponseKind,
922    /// Optional final answer replacement, keyed by question ID
923    #[serde(default, skip_serializing_if = "Option::is_none")]
924    pub answers: Option<std::collections::HashMap<String, ChatInputAnswer>>,
925}
926
927/// The session's customizations have changed.
928///
929/// Full-replacement semantics: the `customizations` array replaces the
930/// previous `customizations` entirely.
931#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
932#[serde(rename_all = "camelCase")]
933pub struct SessionCustomizationsChangedAction {
934    /// Updated customization list (full replacement).
935    pub customizations: Vec<Customization>,
936}
937
938/// A client toggled a container customization on or off.
939///
940/// Targets a top-level container (plugin or directory) by `id`. Only
941/// containers have an `enabled` flag; children are always active when
942/// their container is enabled. Is a no-op when no matching container is
943/// found.
944#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
945#[serde(rename_all = "camelCase")]
946pub struct SessionCustomizationToggledAction {
947    /// The id of the container to toggle.
948    pub id: String,
949    /// Whether to enable or disable the container.
950    pub enabled: bool,
951}
952
953/// Upserts a top-level customization (plugin or directory).
954///
955/// The reducer locates the existing entry by `customization.id`:
956///
957/// - If found, the entry is replaced entirely with `customization`,
958///   including its `children` array. To preserve existing children, the
959///   host must include them on the payload.
960/// - If not found, the entry is appended.
961#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
962#[serde(rename_all = "camelCase")]
963pub struct SessionCustomizationUpdatedAction {
964    /// The customization to upsert (matched by `customization.id`).
965    pub customization: Customization,
966}
967
968/// Removes a customization by id.
969///
970/// Searches every container and its children for the entry. If the entry
971/// is a container, its children are removed with it. Is a no-op when no
972/// matching id is found.
973#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
974#[serde(rename_all = "camelCase")]
975pub struct SessionCustomizationRemovedAction {
976    /// The id of the customization to remove.
977    pub id: String,
978}
979
980/// Updates the runtime fields of an existing
981/// {@link McpServerCustomization} — narrow alternative to
982/// {@link SessionCustomizationUpdatedAction} for the high-frequency
983/// `starting` ↔ `ready` ↔ `authRequired` transitions.
984///
985/// Locates the target entry by `id`, searching both the top-level
986/// customization list and the `children` array of every container.
987/// Replaces the entry's {@link McpServerCustomization.state | `state`}
988/// and {@link McpServerCustomization.channel | `channel`}
989/// (full-replacement semantics: omit `channel` to clear an existing
990/// channel URI). Other fields of the customization are preserved.
991///
992/// Is a no-op when no matching `McpServerCustomization` is found. To
993/// update any other field (name, icons, `mcpApp` capabilities, etc.) use
994/// {@link SessionCustomizationUpdatedAction} instead.
995///
996/// When the transition is to {@link McpServerStatus.AuthRequired}
997/// because of a request issued mid-turn, the host SHOULD also raise
998/// {@link SessionStatus.InputNeeded} on the session — see
999/// {@link McpServerAuthRequiredState} for the rationale.
1000#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1001#[serde(rename_all = "camelCase")]
1002pub struct SessionMcpServerStateChangedAction {
1003    /// The id of the {@link McpServerCustomization} to update.
1004    pub id: String,
1005    /// The new lifecycle state.
1006    pub state: McpServerState,
1007    /// Updated `mcp://` side-channel URI. Full-replacement: omit to clear
1008    /// an existing channel (typical when leaving
1009    /// {@link McpServerStatus.Ready | `Ready`}).
1010    #[serde(default, skip_serializing_if = "Option::is_none")]
1011    pub channel: Option<Uri>,
1012}
1013
1014/// Truncates a session's history. If `turnId` is provided, all turns after that
1015/// turn are removed and the specified turn is kept. If `turnId` is omitted, all
1016/// turns are removed.
1017///
1018/// If there is an active turn it is silently dropped and the chat status
1019/// returns to `idle`.
1020///
1021/// Common use-case: truncate old data then dispatch a new
1022/// `chat/turnStarted` with an edited message.
1023#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1024#[serde(rename_all = "camelCase")]
1025pub struct ChatTruncatedAction {
1026    /// Keep turns up to and including this turn. Omit to clear all turns.
1027    #[serde(default, skip_serializing_if = "Option::is_none")]
1028    pub turn_id: Option<String>,
1029}
1030
1031/// Client changed a mutable config value mid-session.
1032///
1033/// Only properties with `sessionMutable: true` in the config schema may be
1034/// changed. The server validates and broadcasts the action; the reducer merges
1035/// the new values into `state.config.values`.
1036#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1037#[serde(rename_all = "camelCase")]
1038pub struct SessionConfigChangedAction {
1039    /// Updated config values
1040    pub config: JsonObject,
1041    /// When `true`, replaces all config values instead of merging
1042    #[serde(default, skip_serializing_if = "Option::is_none")]
1043    pub replace: Option<bool>,
1044}
1045
1046/// The session's `_meta` side-channel changed. Replaces `state._meta`
1047/// entirely (full-replacement semantics). Producers SHOULD merge any
1048/// keys they wish to preserve into the new value before dispatching.
1049#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1050#[serde(rename_all = "camelCase")]
1051pub struct SessionMetaChangedAction {
1052    /// New `_meta` payload, or `undefined` to clear it
1053    #[serde(rename = "_meta", default, skip_serializing_if = "Option::is_none")]
1054    pub meta: Option<JsonObject>,
1055}
1056
1057/// The {@link ChangesetState.status} for this changeset transitioned (e.g.
1058/// `computing → ready`). The error payload is set together with `status`
1059/// whenever it transitions to {@link ChangesetStatus.Error | Error}.
1060#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1061#[serde(rename_all = "camelCase")]
1062pub struct ChangesetStatusChangedAction {
1063    /// New computation lifecycle status.
1064    pub status: ChangesetStatus,
1065    /// Cause when `status === ChangesetStatus.Error`; otherwise omitted.
1066    #[serde(default, skip_serializing_if = "Option::is_none")]
1067    pub error: Option<ErrorInfo>,
1068}
1069
1070/// Upsert a {@link ChangesetFile} in the changeset — adds a new entry, or
1071/// replaces an existing one identified by {@link ChangesetFile.id}.
1072#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1073#[serde(rename_all = "camelCase")]
1074pub struct ChangesetFileSetAction {
1075    /// The new or replacement file entry.
1076    pub file: ChangesetFile,
1077}
1078
1079/// Remove a {@link ChangesetFile} from the changeset by its id.
1080///
1081/// Typically dispatched when a file is reverted, staged out, or otherwise
1082/// no longer in scope (e.g. a renamed file is replaced by a new entry).
1083#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1084#[serde(rename_all = "camelCase")]
1085pub struct ChangesetFileRemovedAction {
1086    /// The {@link ChangesetFile.id} of the file to remove.
1087    pub file_id: String,
1088}
1089
1090/// The changeset's full content changed. Full replacement semantics: `files`
1091/// replaces the previous file list, and `operations`, when present, replaces
1092/// the previous operation list.
1093///
1094/// Producers SHOULD use this action for initial snapshots and bulk refreshes;
1095/// use {@link ChangesetFileSetAction}, {@link ChangesetFileRemovedAction}, and
1096/// {@link ChangesetOperationsChangedAction} for incremental updates.
1097#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1098#[serde(rename_all = "camelCase")]
1099pub struct ChangesetContentChangedAction {
1100    /// Full replacement file list.
1101    pub files: Vec<ChangesetFile>,
1102    /// Full replacement operation list. Omit when operations are unchanged.
1103    #[serde(default, skip_serializing_if = "Option::is_none")]
1104    pub operations: Option<Vec<ChangesetOperation>>,
1105    /// Error information, if the changeset content change failed.
1106    #[serde(default, skip_serializing_if = "Option::is_none")]
1107    pub error: Option<ErrorInfo>,
1108}
1109
1110/// The set of operations available on this changeset changed. Full
1111/// replacement semantics: `operations` replaces the previous list (or
1112/// removes it entirely when `operations` is `undefined`).
1113#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1114#[serde(rename_all = "camelCase")]
1115pub struct ChangesetOperationsChangedAction {
1116    /// Updated operation list. Pass `undefined` to clear all operations.
1117    #[serde(default, skip_serializing_if = "Option::is_none")]
1118    pub operations: Option<Vec<ChangesetOperation>>,
1119}
1120
1121/// The {@link ChangesetOperation.status} for a single operation transitioned
1122/// (e.g. `idle → running → idle`, or `running → error`). The error payload
1123/// is set together with `status` whenever it transitions to
1124/// {@link ChangesetOperationStatus.Error | Error}, and cleared on any other
1125/// transition.
1126///
1127/// Targets one operation by its {@link ChangesetOperation.id}. If no
1128/// operation with that id is currently present in the changeset, the action
1129/// is a no-op. Use {@link ChangesetOperationsChangedAction} to add, remove,
1130/// or otherwise replace the operation list itself.
1131#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1132#[serde(rename_all = "camelCase")]
1133pub struct ChangesetOperationStatusChangedAction {
1134    /// The {@link ChangesetOperation.id} whose status changed.
1135    pub operation_id: String,
1136    /// New execution status.
1137    pub status: ChangesetOperationStatus,
1138    /// Cause when `status === ChangesetOperationStatus.Error`; otherwise omitted.
1139    #[serde(default, skip_serializing_if = "Option::is_none")]
1140    pub error: Option<ErrorInfo>,
1141}
1142
1143/// Drop every file from the changeset.
1144///
1145/// Two cases use this:
1146/// 1. The underlying source moved (branch switched, fork point invalidated,
1147///    …) and the server is recomputing from scratch — subsequent
1148///    {@link ChangesetFileSetAction} entries will repopulate it.
1149/// 2. The owning session has ended and the URI is becoming
1150///    un-subscribable — the server will unsubscribe all clients shortly
1151///    after dispatching this action.
1152///
1153/// Clients SHOULD release any references on receipt and SHOULD NOT
1154/// distinguish the two cases from the action alone — instead, react to
1155/// the corresponding session-level lifecycle signal (e.g.
1156/// `root/sessionRemoved`) for the "going away" case.
1157#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1158#[serde(rename_all = "camelCase")]
1159pub struct ChangesetClearedAction {}
1160
1161/// Upsert an {@link Annotation} in the annotations channel — adds a new
1162/// annotation, or replaces an existing one identified by
1163/// {@link Annotation.id}.
1164///
1165/// Dispatched by a client to create an annotation (together with its
1166/// mandatory first entry) or to re-anchor / resolve an existing one; the
1167/// dispatching client assigns the {@link Annotation.id} and the id of any
1168/// new entry. When replacing, the full annotation payload (including its
1169/// {@link Annotation.entries | entries} list) is substituted; producers
1170/// SHOULD prefer {@link AnnotationsEntrySetAction} for per-entry edits, and
1171/// {@link AnnotationsUpdatedAction} to resolve / re-anchor an existing
1172/// annotation, to keep wire updates small.
1173#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1174#[serde(rename_all = "camelCase")]
1175pub struct AnnotationsSetAction {
1176    /// The new or replacement annotation. MUST contain at least one entry.
1177    pub annotation: Annotation,
1178}
1179
1180/// Partially update an existing {@link Annotation}'s own properties — a narrow
1181/// alternative to {@link AnnotationsSetAction} for the common case of resolving
1182/// / re-opening or re-anchoring an annotation without resending its
1183/// {@link Annotation.entries | entries}.
1184///
1185/// Targets one annotation by its {@link annotationId}. Only the fields present
1186/// on the action are written; omitted fields leave the corresponding
1187/// {@link Annotation} property unchanged. The annotation's
1188/// {@link Annotation.entries | entries}, {@link Annotation.id | id}, and
1189/// {@link Annotation._meta | _meta} are never touched — dispatch
1190/// {@link AnnotationsSetAction} to replace those, to clear {@link range}
1191/// (re-anchor to the whole file), or {@link AnnotationsEntrySetAction} /
1192/// {@link AnnotationsEntryRemovedAction} to edit individual entries.
1193///
1194/// If {@link annotationId} does not match any current annotation the action is
1195/// a no-op.
1196#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1197#[serde(rename_all = "camelCase")]
1198pub struct AnnotationsUpdatedAction {
1199    /// The {@link Annotation.id} of the annotation to update.
1200    pub annotation_id: String,
1201    /// Re-anchors the annotation to the file versions this turn produced.
1202    /// Matches a {@link Turn.id} on the owning session. Omit to leave the
1203    /// current {@link Annotation.turnId} unchanged.
1204    #[serde(default, skip_serializing_if = "Option::is_none")]
1205    pub turn_id: Option<String>,
1206    /// Re-anchors the annotation to this file. Omit to leave the current
1207    /// {@link Annotation.resource} unchanged.
1208    #[serde(default, skip_serializing_if = "Option::is_none")]
1209    pub resource: Option<Uri>,
1210    /// Narrows the annotation to this range within {@link resource}. Omit to
1211    /// leave the current {@link Annotation.range} unchanged; this action cannot
1212    /// clear an existing range — dispatch {@link AnnotationsSetAction} to
1213    /// re-anchor to the whole file.
1214    #[serde(default, skip_serializing_if = "Option::is_none")]
1215    pub range: Option<TextRange>,
1216    /// Marks the annotation resolved (`true`) or re-opens it (`false`). Omit to
1217    /// leave the current {@link Annotation.resolved} state unchanged.
1218    #[serde(default, skip_serializing_if = "Option::is_none")]
1219    pub resolved: Option<bool>,
1220}
1221
1222/// Remove an {@link Annotation} from the channel by its id.
1223///
1224/// Dispatched to delete an entire annotation and every entry it contains.
1225/// Because the protocol forbids empty annotations, a client that wants to
1226/// remove the last remaining entry dispatches this action — collapsing the
1227/// annotation — rather than {@link AnnotationsEntryRemovedAction}.
1228#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1229#[serde(rename_all = "camelCase")]
1230pub struct AnnotationsRemovedAction {
1231    /// The {@link Annotation.id} of the annotation to remove.
1232    pub annotation_id: String,
1233}
1234
1235/// Upsert an {@link AnnotationEntry} within an existing annotation — adds a
1236/// new entry, or replaces one identified by {@link AnnotationEntry.id}. The
1237/// dispatching client assigns the {@link AnnotationEntry.id} of a new entry.
1238/// If {@link annotationId} does not match any current annotation the action
1239/// is a no-op.
1240#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1241#[serde(rename_all = "camelCase")]
1242pub struct AnnotationsEntrySetAction {
1243    /// The {@link Annotation.id} the entry belongs to.
1244    pub annotation_id: String,
1245    /// The new or replacement entry.
1246    pub entry: AnnotationEntry,
1247}
1248
1249/// Remove a single {@link AnnotationEntry} from an annotation without
1250/// collapsing the annotation itself. Used when more than one entry remains —
1251/// to remove the last entry a client dispatches {@link AnnotationsRemovedAction}
1252/// instead, since the protocol forbids empty annotations.
1253///
1254/// If either {@link annotationId} or {@link entryId} does not match the
1255/// current state the action is a no-op.
1256#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1257#[serde(rename_all = "camelCase")]
1258pub struct AnnotationsEntryRemovedAction {
1259    /// The {@link Annotation.id} the entry belongs to.
1260    pub annotation_id: String,
1261    /// The {@link AnnotationEntry.id} to remove.
1262    pub entry_id: String,
1263}
1264
1265/// Fired when the list of known terminals changes.
1266///
1267/// Full-replacement semantics: the `terminals` array replaces the previous
1268/// `terminals` entirely.
1269#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1270#[serde(rename_all = "camelCase")]
1271pub struct RootTerminalsChangedAction {
1272    /// Updated terminal list (full replacement)
1273    pub terminals: Vec<TerminalInfo>,
1274}
1275
1276/// Terminal output data (pty → client direction).
1277///
1278/// Appends `data` to the terminal's `content` in the reducer.
1279///
1280/// `terminal/data` and `terminal/input` are intentionally separate actions
1281/// because standard write-ahead reconciliation is not safe for terminal I/O.
1282/// A pty is a stateful, mutable process — optimistically applying input or
1283/// predicting output would produce incorrect state. Instead, `terminal/input`
1284/// is a side-effect-only action (client → server → pty), and `terminal/data`
1285/// is server-authoritative output (pty → server → client).
1286#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1287#[serde(rename_all = "camelCase")]
1288pub struct TerminalDataAction {
1289    /// Output data (may contain ANSI escape sequences)
1290    pub data: String,
1291}
1292
1293/// Keyboard input sent to the terminal process (client → pty direction).
1294///
1295/// This is a side-effect-only action: the server forwards the data to the
1296/// terminal's pty. The reducer treats this as a no-op since `terminal/data`
1297/// actions will reflect any resulting output.
1298///
1299/// See `terminal/data` for why these two actions are kept separate.
1300#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1301#[serde(rename_all = "camelCase")]
1302pub struct TerminalInputAction {
1303    /// Input data to send to the pty
1304    pub data: String,
1305}
1306
1307/// Terminal dimensions changed.
1308///
1309/// Dispatchable by clients to request a resize, or by the server to inform
1310/// clients of the actual terminal dimensions.
1311#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1312#[serde(rename_all = "camelCase")]
1313pub struct TerminalResizedAction {
1314    /// Terminal width in columns
1315    pub cols: i64,
1316    /// Terminal height in rows
1317    pub rows: i64,
1318}
1319
1320/// Terminal claim changed. A client or session transfers ownership of the terminal.
1321///
1322/// The server SHOULD reject if the dispatching client does not currently hold
1323/// the claim.
1324#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1325#[serde(rename_all = "camelCase")]
1326pub struct TerminalClaimedAction {
1327    /// The new claim
1328    pub claim: TerminalClaim,
1329}
1330
1331/// Terminal title changed.
1332///
1333/// Fired by the server when the terminal process updates its title (e.g. via
1334/// escape sequences), or dispatched by a client to rename a terminal.
1335#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1336#[serde(rename_all = "camelCase")]
1337pub struct TerminalTitleChangedAction {
1338    /// New terminal title
1339    pub title: String,
1340}
1341
1342/// Terminal working directory changed.
1343#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1344#[serde(rename_all = "camelCase")]
1345pub struct TerminalCwdChangedAction {
1346    /// New working directory
1347    pub cwd: Uri,
1348}
1349
1350/// Terminal process exited.
1351#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1352#[serde(rename_all = "camelCase")]
1353pub struct TerminalExitedAction {
1354    /// Process exit code. `undefined` if the process was killed without an exit code.
1355    #[serde(default, skip_serializing_if = "Option::is_none")]
1356    pub exit_code: Option<i64>,
1357}
1358
1359/// Terminal scrollback buffer cleared.
1360#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1361#[serde(rename_all = "camelCase")]
1362pub struct TerminalClearedAction {}
1363
1364/// Shell integration has loaded and the terminal now supports command
1365/// detection. The server dispatches this when shell integration becomes
1366/// available (which may happen asynchronously after the terminal is created).
1367///
1368/// Clients MUST NOT assume command detection is available until this action
1369/// (or `terminal/commandExecuted`) has been received.
1370#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1371#[serde(rename_all = "camelCase")]
1372pub struct TerminalCommandDetectionAvailableAction {}
1373
1374/// A command has been submitted to the shell and is now executing.
1375/// All subsequent `terminal/data` actions (until the matching
1376/// `terminal/commandFinished`) constitute this command's output.
1377#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1378#[serde(rename_all = "camelCase")]
1379pub struct TerminalCommandExecutedAction {
1380    /// Stable identifier for this command, scoped to the terminal URI.
1381    /// Allows correlating `commandExecuted` → `commandFinished` pairs.
1382    pub command_id: String,
1383    /// The command line text that was submitted
1384    pub command_line: String,
1385    /// Unix timestamp (ms) of when the command started executing, as measured
1386    /// on the server.
1387    pub timestamp: i64,
1388}
1389
1390/// A command has finished executing.
1391///
1392/// The sequence of `terminal/data` actions between the preceding
1393/// `terminal/commandExecuted` (same `commandId`) and this action constitutes
1394/// the complete output of the command.
1395#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1396#[serde(rename_all = "camelCase")]
1397pub struct TerminalCommandFinishedAction {
1398    /// Matches the `commandId` from the corresponding `commandExecuted`
1399    pub command_id: String,
1400    /// Shell exit code. `undefined` if the shell did not report one.
1401    #[serde(default, skip_serializing_if = "Option::is_none")]
1402    pub exit_code: Option<i64>,
1403    /// Wall-clock duration of the command in milliseconds, as measured by the
1404    /// shell integration script on the server side.
1405    #[serde(default, skip_serializing_if = "Option::is_none")]
1406    pub duration_ms: Option<i64>,
1407}
1408
1409/// A batch of resource changes observed by the watcher.
1410///
1411/// Watch events are coalesced into batches by the server to keep the
1412/// action stream tractable; an empty `changes.items` list MUST NOT be
1413/// dispatched. The reducer does not retain change history — these
1414/// actions exist purely to deliver events to subscribers, who consume
1415/// them directly off the action stream and apply their own logic.
1416#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1417#[serde(rename_all = "camelCase")]
1418pub struct ResourceWatchChangedAction {
1419    /// The set of changes in this batch, wrapped for forward compatibility.
1420    pub changes: AnyValue,
1421}
1422
1423// ─── Partial Summaries ────────────────────────────────────────────────
1424
1425/// Partial equivalent of ChatSummary — every field is optional for delta updates.
1426#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1427#[serde(rename_all = "camelCase")]
1428pub struct PartialChatSummary {
1429    /// Chat URI
1430    #[serde(default, skip_serializing_if = "Option::is_none")]
1431    pub resource: Option<Uri>,
1432    /// Chat title
1433    #[serde(default, skip_serializing_if = "Option::is_none")]
1434    pub title: Option<String>,
1435    /// Current chat status (reuses SessionStatus shape)
1436    #[serde(default, skip_serializing_if = "Option::is_none")]
1437    pub status: Option<u32>,
1438    /// Human-readable description of what the chat is currently doing
1439    #[serde(default, skip_serializing_if = "Option::is_none")]
1440    pub activity: Option<String>,
1441    /// Last modification timestamp (ISO 8601, e.g. `"2025-03-10T18:42:03.123Z"`)
1442    #[serde(default, skip_serializing_if = "Option::is_none")]
1443    pub modified_at: Option<String>,
1444    /// How this chat came into existence
1445    #[serde(default, skip_serializing_if = "Option::is_none")]
1446    pub origin: Option<ChatOrigin>,
1447    /// How the user can interact with this chat. See {@link ChatInteractivity}.
1448    ///
1449    /// Supports agent-team patterns where worker chats are read-only or hidden.
1450    /// Absence defaults to {@link ChatInteractivity.Full} for backward
1451    /// compatibility.
1452    #[serde(default, skip_serializing_if = "Option::is_none")]
1453    pub interactivity: Option<ChatInteractivity>,
1454    /// Optional per-chat working directory.
1455    ///
1456    /// If absent, the chat inherits
1457    /// {@link SessionSummary.workingDirectory | the session's working directory}.
1458    /// See {@link ChatState.workingDirectory} for usage notes.
1459    #[serde(default, skip_serializing_if = "Option::is_none")]
1460    pub working_directory: Option<Uri>,
1461}
1462
1463// ─── StateAction Union ───────────────────────────────────────────────
1464
1465/// Discriminated union of every state action.
1466#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1467#[serde(tag = "type")]
1468pub enum StateAction {
1469    #[serde(rename = "root/agentsChanged")]
1470    RootAgentsChanged(RootAgentsChangedAction),
1471    #[serde(rename = "root/activeSessionsChanged")]
1472    RootActiveSessionsChanged(RootActiveSessionsChangedAction),
1473    #[serde(rename = "root/configChanged")]
1474    RootConfigChanged(RootConfigChangedAction),
1475    #[serde(rename = "session/ready")]
1476    SessionReady(SessionReadyAction),
1477    #[serde(rename = "session/creationFailed")]
1478    SessionCreationFailed(SessionCreationFailedAction),
1479    #[serde(rename = "session/chatAdded")]
1480    SessionChatAdded(SessionChatAddedAction),
1481    #[serde(rename = "session/chatRemoved")]
1482    SessionChatRemoved(SessionChatRemovedAction),
1483    #[serde(rename = "session/chatUpdated")]
1484    SessionChatUpdated(SessionChatUpdatedAction),
1485    #[serde(rename = "session/defaultChatChanged")]
1486    SessionDefaultChatChanged(SessionDefaultChatChangedAction),
1487    #[serde(rename = "chat/turnStarted")]
1488    ChatTurnStarted(ChatTurnStartedAction),
1489    #[serde(rename = "chat/delta")]
1490    ChatDelta(ChatDeltaAction),
1491    #[serde(rename = "chat/responsePart")]
1492    ChatResponsePart(ChatResponsePartAction),
1493    #[serde(rename = "chat/toolCallStart")]
1494    ChatToolCallStart(ChatToolCallStartAction),
1495    #[serde(rename = "chat/toolCallDelta")]
1496    ChatToolCallDelta(ChatToolCallDeltaAction),
1497    #[serde(rename = "chat/toolCallReady")]
1498    ChatToolCallReady(ChatToolCallReadyAction),
1499    #[serde(rename = "chat/toolCallConfirmed")]
1500    ChatToolCallConfirmed(ChatToolCallConfirmedAction),
1501    #[serde(rename = "chat/toolCallComplete")]
1502    ChatToolCallComplete(ChatToolCallCompleteAction),
1503    #[serde(rename = "chat/toolCallResultConfirmed")]
1504    ChatToolCallResultConfirmed(ChatToolCallResultConfirmedAction),
1505    #[serde(rename = "chat/toolCallContentChanged")]
1506    ChatToolCallContentChanged(ChatToolCallContentChangedAction),
1507    #[serde(rename = "chat/turnComplete")]
1508    ChatTurnComplete(ChatTurnCompleteAction),
1509    #[serde(rename = "chat/turnCancelled")]
1510    ChatTurnCancelled(ChatTurnCancelledAction),
1511    #[serde(rename = "chat/error")]
1512    ChatError(ChatErrorAction),
1513    #[serde(rename = "chat/activityChanged")]
1514    ChatActivityChanged(ChatActivityChangedAction),
1515    #[serde(rename = "session/titleChanged")]
1516    SessionTitleChanged(SessionTitleChangedAction),
1517    #[serde(rename = "chat/usage")]
1518    ChatUsage(ChatUsageAction),
1519    #[serde(rename = "chat/reasoning")]
1520    ChatReasoning(ChatReasoningAction),
1521    #[serde(rename = "session/isReadChanged")]
1522    SessionIsReadChanged(SessionIsReadChangedAction),
1523    #[serde(rename = "session/isArchivedChanged")]
1524    SessionIsArchivedChanged(SessionIsArchivedChangedAction),
1525    #[serde(rename = "session/activityChanged")]
1526    SessionActivityChanged(SessionActivityChangedAction),
1527    #[serde(rename = "session/changesetsChanged")]
1528    SessionChangesetsChanged(SessionChangesetsChangedAction),
1529    #[serde(rename = "session/serverToolsChanged")]
1530    SessionServerToolsChanged(SessionServerToolsChangedAction),
1531    #[serde(rename = "session/activeClientSet")]
1532    SessionActiveClientSet(SessionActiveClientSetAction),
1533    #[serde(rename = "session/activeClientRemoved")]
1534    SessionActiveClientRemoved(SessionActiveClientRemovedAction),
1535    #[serde(rename = "chat/pendingMessageSet")]
1536    ChatPendingMessageSet(ChatPendingMessageSetAction),
1537    #[serde(rename = "chat/pendingMessageRemoved")]
1538    ChatPendingMessageRemoved(ChatPendingMessageRemovedAction),
1539    #[serde(rename = "chat/queuedMessagesReordered")]
1540    ChatQueuedMessagesReordered(ChatQueuedMessagesReorderedAction),
1541    #[serde(rename = "chat/draftChanged")]
1542    ChatDraftChanged(ChatDraftChangedAction),
1543    #[serde(rename = "chat/inputRequested")]
1544    ChatInputRequested(ChatInputRequestedAction),
1545    #[serde(rename = "chat/inputAnswerChanged")]
1546    ChatInputAnswerChanged(ChatInputAnswerChangedAction),
1547    #[serde(rename = "chat/inputCompleted")]
1548    ChatInputCompleted(ChatInputCompletedAction),
1549    #[serde(rename = "session/customizationsChanged")]
1550    SessionCustomizationsChanged(SessionCustomizationsChangedAction),
1551    #[serde(rename = "session/customizationToggled")]
1552    SessionCustomizationToggled(SessionCustomizationToggledAction),
1553    #[serde(rename = "session/customizationUpdated")]
1554    SessionCustomizationUpdated(Box<SessionCustomizationUpdatedAction>),
1555    #[serde(rename = "session/customizationRemoved")]
1556    SessionCustomizationRemoved(SessionCustomizationRemovedAction),
1557    #[serde(rename = "session/mcpServerStateChanged")]
1558    SessionMcpServerStateChanged(Box<SessionMcpServerStateChangedAction>),
1559    #[serde(rename = "chat/truncated")]
1560    ChatTruncated(ChatTruncatedAction),
1561    #[serde(rename = "session/configChanged")]
1562    SessionConfigChanged(SessionConfigChangedAction),
1563    #[serde(rename = "session/metaChanged")]
1564    SessionMetaChanged(SessionMetaChangedAction),
1565    #[serde(rename = "changeset/statusChanged")]
1566    ChangesetStatusChanged(ChangesetStatusChangedAction),
1567    #[serde(rename = "changeset/fileSet")]
1568    ChangesetFileSet(ChangesetFileSetAction),
1569    #[serde(rename = "changeset/fileRemoved")]
1570    ChangesetFileRemoved(ChangesetFileRemovedAction),
1571    #[serde(rename = "changeset/contentChanged")]
1572    ChangesetContentChanged(Box<ChangesetContentChangedAction>),
1573    #[serde(rename = "changeset/operationsChanged")]
1574    ChangesetOperationsChanged(ChangesetOperationsChangedAction),
1575    #[serde(rename = "changeset/operationStatusChanged")]
1576    ChangesetOperationStatusChanged(ChangesetOperationStatusChangedAction),
1577    #[serde(rename = "changeset/cleared")]
1578    ChangesetCleared(ChangesetClearedAction),
1579    #[serde(rename = "annotations/set")]
1580    AnnotationsSet(AnnotationsSetAction),
1581    #[serde(rename = "annotations/updated")]
1582    AnnotationsUpdated(AnnotationsUpdatedAction),
1583    #[serde(rename = "annotations/removed")]
1584    AnnotationsRemoved(AnnotationsRemovedAction),
1585    #[serde(rename = "annotations/entrySet")]
1586    AnnotationsEntrySet(AnnotationsEntrySetAction),
1587    #[serde(rename = "annotations/entryRemoved")]
1588    AnnotationsEntryRemoved(AnnotationsEntryRemovedAction),
1589    #[serde(rename = "root/terminalsChanged")]
1590    RootTerminalsChanged(RootTerminalsChangedAction),
1591    #[serde(rename = "terminal/data")]
1592    TerminalData(TerminalDataAction),
1593    #[serde(rename = "terminal/input")]
1594    TerminalInput(TerminalInputAction),
1595    #[serde(rename = "terminal/resized")]
1596    TerminalResized(TerminalResizedAction),
1597    #[serde(rename = "terminal/claimed")]
1598    TerminalClaimed(TerminalClaimedAction),
1599    #[serde(rename = "terminal/titleChanged")]
1600    TerminalTitleChanged(TerminalTitleChangedAction),
1601    #[serde(rename = "terminal/cwdChanged")]
1602    TerminalCwdChanged(TerminalCwdChangedAction),
1603    #[serde(rename = "terminal/exited")]
1604    TerminalExited(TerminalExitedAction),
1605    #[serde(rename = "terminal/cleared")]
1606    TerminalCleared(TerminalClearedAction),
1607    #[serde(rename = "terminal/commandDetectionAvailable")]
1608    TerminalCommandDetectionAvailable(TerminalCommandDetectionAvailableAction),
1609    #[serde(rename = "terminal/commandExecuted")]
1610    TerminalCommandExecuted(TerminalCommandExecutedAction),
1611    #[serde(rename = "terminal/commandFinished")]
1612    TerminalCommandFinished(TerminalCommandFinishedAction),
1613    #[serde(rename = "resourceWatch/changed")]
1614    ResourceWatchChanged(ResourceWatchChangedAction),
1615    /// Unknown or future variant — preserved as raw JSON for round-trip fidelity.
1616    /// Reducers treat this as a no-op.
1617    #[serde(untagged)]
1618    Unknown(serde_json::Value),
1619}