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