Skip to main content

ahp_types/
commands.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::actions::{ActionEnvelope, StateAction};
16#[allow(unused_imports)]
17use crate::state::{
18    AgentSelection, ContentRef, Message, MessageAttachment, ModelSelection, SessionActiveClient,
19    SessionConfigSchema, SessionSummary, SideChatSelection, Snapshot, SnapshotState,
20    TelemetryCapabilities, TerminalClaim, TextRange, Turn,
21};
22
23// ─── Enums ────────────────────────────────────────────────────────────
24
25/// Discriminant for reconnect result types.
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
27pub enum ReconnectResultType {
28    #[serde(rename = "replay")]
29    Replay,
30    #[serde(rename = "snapshot")]
31    Snapshot,
32}
33
34/// How a new chat uses its source chat and turn.
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36pub enum ChatSourceKind {
37    /// Copy source history through the referenced turn into the new chat.
38    #[serde(rename = "fork")]
39    Fork,
40    /// Supply source context without copying it into the new chat's visible history.
41    #[serde(rename = "sideChat")]
42    SideChat,
43}
44
45/// Encoding of fetched content data.
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
47pub enum ContentEncoding {
48    #[serde(rename = "base64")]
49    Base64,
50    #[serde(rename = "utf-8")]
51    Utf8,
52}
53
54/// The kind of completion items being requested.
55#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
56pub enum CompletionItemKind {
57    /// Completions for the text of a {@link Message} the user is composing.
58    /// Each returned item carries an attachment that gets associated with the
59    /// message when accepted.
60    #[serde(rename = "userMessage")]
61    UserMessage,
62}
63
64/// Discriminant for {@link ResourceResolveResult.type}.
65#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
66pub enum ResourceType {
67    #[serde(rename = "file")]
68    File,
69    #[serde(rename = "directory")]
70    Directory,
71    #[serde(rename = "symlink")]
72    Symlink,
73}
74
75/// How {@link ResourceWriteParams.data} is placed within the target file.
76///
77/// Each mode interprets {@link ResourceWriteParams.position} differently:
78///
79/// - `truncate` (default): rooted at the **start** of the file. The file is
80///   truncated at `position` (0 by default) and `data` is written from that
81///   offset, so the resulting file is `existing[0..position] + data`. With
82///   `position` omitted this is a full overwrite.
83/// - `append`: rooted at the **end** of the file. `position` counts bytes
84///   backwards from EOF, so `position: 0` (the default) writes at EOF —
85///   POSIX append — and `position: 5` inserts `data` 5 bytes before the
86///   current EOF, shifting those trailing 5 bytes after the inserted region.
87///   The server MUST evaluate the effective EOF and write atomically with
88///   respect to other appenders so concurrent `append` writes do not
89///   clobber each other.
90/// - `insert`: rooted at the **start** of the file. `position` (0 by default)
91///   is the byte offset at which `data` is spliced in; bytes at or after
92///   `position` are shifted right by `data.length`. `insert` always grows
93///   the file — use `truncate` to overwrite bytes in place.
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
95pub enum ResourceWriteMode {
96    #[serde(rename = "truncate")]
97    Truncate,
98    #[serde(rename = "append")]
99    Append,
100    #[serde(rename = "insert")]
101    Insert,
102}
103
104// ─── Command Payloads ─────────────────────────────────────────────────
105
106/// Establishes a new connection and negotiates the protocol version.
107/// This MUST be the first message sent by the client.
108#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
109#[serde(rename_all = "camelCase")]
110pub struct InitializeParams {
111    /// Channel URI this command targets.
112    pub channel: Uri,
113    /// Protocol versions the client is willing to speak, ordered from most
114    /// preferred to least preferred. Each entry is a [SemVer](https://semver.org)
115    /// `MAJOR.MINOR.PATCH` string (e.g. `"0.1.0"`).
116    ///
117    /// The server selects one entry and returns it as `InitializeResult.protocolVersion`.
118    /// If the server cannot speak any of the offered versions, it MUST return
119    /// error code `-32005` (`UnsupportedProtocolVersion`).
120    pub protocol_versions: Vec<String>,
121    /// Unique client identifier
122    pub client_id: String,
123    /// Optional identity of the client implementation (name and version).
124    /// Informational only — see {@link Implementation} for how it may and may not
125    /// be used. Distinct from {@link InitializeParams.clientId | `clientId`},
126    /// which is an opaque per-connection identifier used for reconnection, not a
127    /// human-readable implementation name.
128    #[serde(default, skip_serializing_if = "Option::is_none")]
129    pub client_info: Option<Implementation>,
130    /// URIs to subscribe to during handshake
131    #[serde(default, skip_serializing_if = "Option::is_none")]
132    pub initial_subscriptions: Option<Vec<Uri>>,
133    /// IETF BCP 47 language tag indicating the client's preferred locale
134    /// (e.g. `"en-US"`, `"ja"`). The server SHOULD use this to localise
135    /// user-facing strings such as confirmation option labels.
136    #[serde(default, skip_serializing_if = "Option::is_none")]
137    pub locale: Option<String>,
138    /// Optional client capability declarations.
139    ///
140    /// Servers SHOULD only advertise features whose corresponding client
141    /// capability is set here. Absent means "not declared" — the server
142    /// MUST assume the client does not support the feature.
143    #[serde(default, skip_serializing_if = "Option::is_none")]
144    pub capabilities: Option<ClientCapabilities>,
145}
146
147/// Result of the `initialize` command.
148///
149/// `protocolVersion` is the version the server has selected from the client's
150/// `protocolVersions` list. The client and server MUST use this version for
151/// the rest of the connection. If the server cannot speak any of the offered
152/// versions it MUST return error code `-32005` (`UnsupportedProtocolVersion`)
153/// instead of a result.
154#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
155#[serde(rename_all = "camelCase")]
156pub struct InitializeResult {
157    /// Protocol version selected by the server. MUST be one of the entries in
158    /// `InitializeParams.protocolVersions`. Formatted as a [SemVer](https://semver.org)
159    /// `MAJOR.MINOR.PATCH` string (e.g. `"0.1.0"`).
160    pub protocol_version: String,
161    /// Current server sequence number
162    pub server_seq: i64,
163    /// Optional identity of the server implementation (name and version).
164    /// Informational only — see {@link Implementation} for how it may and may not
165    /// be used. Whereas {@link InitializeResult.protocolVersion | `protocolVersion`}
166    /// identifies the negotiated protocol, `serverInfo` identifies the host
167    /// software behind it.
168    #[serde(default, skip_serializing_if = "Option::is_none")]
169    pub server_info: Option<Implementation>,
170    /// Snapshots for each `initialSubscriptions` URI
171    pub snapshots: Vec<Snapshot>,
172    /// Suggested default directory for remote filesystem browsing
173    #[serde(default, skip_serializing_if = "Option::is_none")]
174    pub default_directory: Option<Uri>,
175    /// Characters that, when typed in a {@link Message} input, SHOULD cause
176    /// the client to issue a `completions` request with
177    /// {@link CompletionItemKind.UserMessage}. Typically includes characters like
178    /// `'@'` or `'/'`.
179    #[serde(default, skip_serializing_if = "Option::is_none")]
180    pub completion_trigger_characters: Option<Vec<String>>,
181    /// Prefix that the host recognizes at the start of a user {@link Message.text}
182    /// as a shorthand for executing the remainder as a terminal command. Currently
183    /// the standardized convention is `"!"`; absence means the host does not
184    /// support command prefixes.
185    #[serde(default, skip_serializing_if = "Option::is_none")]
186    pub terminal_command_prefix: Option<String>,
187    /// OTLP telemetry channels the host emits, if any. Each populated field is
188    /// either a literal `ahp-otlp:` channel URI or an RFC 6570 URI template a
189    /// client expands before subscribing (currently only the `logs` channel
190    /// defines a template variable, `{level}`, for subscriber-side severity
191    /// filtering). Clients MAY ignore signals they cannot process.
192    #[serde(default, skip_serializing_if = "Option::is_none")]
193    pub telemetry: Option<TelemetryCapabilities>,
194}
195
196/// Optional capabilities a client declares during `initialize`.
197///
198/// Each field is a presence flag: an empty object `{}` means "supported",
199/// absence means "not supported". Sub-fields on individual capabilities
200/// are reserved for future per-capability options.
201#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
202#[serde(rename_all = "camelCase")]
203pub struct ClientCapabilities {
204    /// Client can render
205    /// [MCP Apps](https://github.com/modelcontextprotocol/ext-apps) — i.e.
206    /// it can host the View sandbox, run the `ui/*` protocol against it,
207    /// and forward `mcp://`-channel traffic on the App's behalf.
208    ///
209    /// Hosts SHOULD only populate
210    /// {@link McpServerCustomization.mcpApp | `McpServerCustomization.mcpApp`}
211    /// (and expose the corresponding
212    /// {@link McpServerCustomization.channel | `mcp://` channel}) when this
213    /// capability is declared. Clients that omit it MUST treat
214    /// App-bearing tool calls as ordinary MCP tool calls.
215    #[serde(default, skip_serializing_if = "Option::is_none")]
216    pub mcp_apps: Option<JsonObject>,
217}
218
219/// Identifies a protocol implementation — the software (and build) on one end
220/// of the connection, as distinct from the {@link AgentInfo | agent persona} it
221/// hosts. Carried as {@link InitializeParams.clientInfo | `clientInfo`} on the
222/// client side and {@link InitializeResult.serverInfo | `serverInfo`} on the
223/// server side, mirroring LSP's `clientInfo`/`serverInfo` and MCP's
224/// `Implementation`.
225///
226/// This is **informational only**: it exists for logging, telemetry, an
227/// about/status affordance, and — as a last resort — a known-issue workaround
228/// for a specific buggy build. It is **not** a feature-detection mechanism.
229/// Feature availability stays with the capability model
230/// ({@link ClientCapabilities} and the various `*.capabilities` declarations);
231/// implementations SHOULD NOT gate protocol behaviour on parsing
232/// {@link Implementation.version | `version`}.
233#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
234#[serde(rename_all = "camelCase")]
235pub struct Implementation {
236    /// Implementation name, e.g. a product or package identifier.
237    pub name: String,
238    /// Implementation version. A [SemVer](https://semver.org) string is
239    /// recommended but not required.
240    #[serde(default, skip_serializing_if = "Option::is_none")]
241    pub version: Option<String>,
242    /// Optional human-readable display name.
243    #[serde(default, skip_serializing_if = "Option::is_none")]
244    pub title: Option<String>,
245}
246
247/// Re-establishes a dropped connection. The server replays missed actions or
248/// provides fresh snapshots.
249#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
250#[serde(rename_all = "camelCase")]
251pub struct ReconnectParams {
252    /// Channel URI this command targets.
253    pub channel: Uri,
254    /// Client identifier from the original connection
255    pub client_id: String,
256    /// Last `serverSeq` the client received
257    pub last_seen_server_seq: i64,
258    /// URIs the client was subscribed to
259    pub subscriptions: Vec<Uri>,
260}
261
262/// Reconnect result when the server can replay from the requested sequence.
263///
264/// The server MUST include all replayed data in the response.
265#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
266#[serde(rename_all = "camelCase")]
267pub struct ReconnectReplayResult {
268    /// Missed action envelopes since `lastSeenServerSeq`
269    pub actions: Vec<ActionEnvelope>,
270    /// URIs from `ReconnectParams.subscriptions` that the server cannot resume.
271    /// This includes resources that no longer exist (e.g. disposed sessions or
272    /// terminals) as well as resources the client is no longer permitted to
273    /// observe. Clients SHOULD drop these from their local subscription set.
274    pub missing: Vec<Uri>,
275}
276
277/// Reconnect result when the gap exceeds the replay buffer.
278#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
279#[serde(rename_all = "camelCase")]
280pub struct ReconnectSnapshotResult {
281    /// Fresh snapshots for each subscription
282    pub snapshots: Vec<Snapshot>,
283}
284
285/// Subscribe to a URI-identified channel.
286///
287/// A channel MAY have state associated with it (e.g. root, sessions,
288/// terminals) or be stateless (pure pub/sub for streaming data). For
289/// state-bearing channels the result includes a snapshot; for stateless
290/// channels `snapshot` is omitted.
291#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
292#[serde(rename_all = "camelCase")]
293pub struct SubscribeParams {
294    /// Channel URI this command targets.
295    pub channel: Uri,
296    /// Optional delivery preferences for this subscription.
297    ///
298    /// Servers MAY use these preferences to buffer and coalesce high-frequency
299    /// updates while preserving the same reduced state. Omit this field for the
300    /// server's default delivery behavior.
301    #[serde(default, skip_serializing_if = "Option::is_none")]
302    pub delivery: Option<SubscriptionDeliveryOptions>,
303    /// Optional client-requested shape for the returned snapshot.
304    ///
305    /// Servers that do not understand a requested view ignore it and return their
306    /// default snapshot. Clients MUST tolerate receiving more state than requested.
307    #[serde(default, skip_serializing_if = "Option::is_none")]
308    pub view: Option<SubscribeView>,
309}
310
311impl SubscribeParams {
312    /// Create subscribe params with default delivery behavior.
313    pub fn new(channel: impl Into<Uri>) -> Self {
314        Self {
315            channel: channel.into(),
316            delivery: None,
317            view: None,
318        }
319    }
320
321    /// Create subscribe params with advisory delivery preferences.
322    pub fn with_delivery(channel: impl Into<Uri>, delivery: SubscriptionDeliveryOptions) -> Self {
323        Self {
324            channel: channel.into(),
325            delivery: Some(delivery),
326            view: None,
327        }
328    }
329
330    /// Create subscribe params with snapshot-shaping preferences.
331    pub fn with_view(channel: impl Into<Uri>, view: SubscribeView) -> Self {
332        Self {
333            channel: channel.into(),
334            delivery: None,
335            view: Some(view),
336        }
337    }
338}
339
340/// Optional client-requested shape for a subscription snapshot.
341#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
342#[serde(rename_all = "camelCase")]
343pub struct SubscribeView {
344    /// Advisory number of most-recent completed turns to expose in a chat
345    /// snapshot.
346    ///
347    /// Servers MAY return more or fewer turns than requested. When omitted, the
348    /// host MUST return all retained turns. When older turns remain available, the
349    /// returned {@link ChatState} carries `turnsNextCursor`; clients pass that
350    /// cursor to `fetchTurns` to ask the host to page more turns into the chat
351    /// state.
352    #[serde(default, skip_serializing_if = "Option::is_none")]
353    pub turns: Option<i64>,
354}
355
356/// Advisory delivery preferences for a single subscription.
357#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
358#[serde(rename_all = "camelCase")]
359pub struct SubscriptionDeliveryOptions {
360    /// Maximum time, in milliseconds, that the server may intentionally delay
361    /// delivery while buffering/coalescing updates for this subscription.
362    ///
363    /// A value of `0` requests immediate delivery with no intentional coalescing.
364    #[serde(default, skip_serializing_if = "Option::is_none")]
365    pub max_latency_ms: Option<i64>,
366}
367
368/// Result of the `subscribe` command.
369///
370/// `snapshot` is present when the subscribed channel has associated state, and
371/// absent for stateless channels.
372#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
373#[serde(rename_all = "camelCase")]
374pub struct SubscribeResult {
375    /// Snapshot of the subscribed channel's state (omitted for stateless channels)
376    #[serde(default, skip_serializing_if = "Option::is_none")]
377    pub snapshot: Option<Snapshot>,
378}
379
380/// Creates a new session with the specified agent provider.
381///
382/// If the session URI already exists, the server MUST return an error with code
383/// `-32003` (`SessionAlreadyExists`).
384///
385/// After creation, the client should subscribe to the session URI to receive state
386/// updates. The server also broadcasts a `root/sessionAdded` notification to all
387/// clients.
388#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
389#[serde(rename_all = "camelCase")]
390pub struct SessionForkSource {
391    /// URI of the existing session to fork from
392    pub session: Uri,
393    /// Turn ID in the source session; content up to and including this turn's response is copied
394    pub turn_id: String,
395}
396
397#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
398#[serde(rename_all = "camelCase")]
399pub struct CreateSessionParams {
400    /// Channel URI this command targets.
401    pub channel: Uri,
402    /// Agent provider ID
403    #[serde(default, skip_serializing_if = "Option::is_none")]
404    pub provider: Option<String>,
405    /// The working directories the session's agent is granted tool access to.
406    /// A session may span multiple directories; they are equal peers except when
407    /// the agent advertises
408    /// {@link MultipleWorkingDirectoriesCapability.immutablePrimary} (in which case
409    /// the first entry is a fixed process root).
410    ///
411    /// A client MUST NOT supply more than one entry unless the agent advertises
412    /// {@link AgentCapabilities.multipleWorkingDirectories}; a server without that
413    /// capability treats only the first entry as the session's working directory
414    /// and ignores the rest. Dispatch `session/workingDirectorySet` /
415    /// `session/workingDirectoryRemoved` to change the set after the session has
416    /// started.
417    ///
418    /// Ignored for forked sessions — a fork inherits its working directories
419    /// from the source session identified by `fork`.
420    #[serde(default, skip_serializing_if = "Option::is_none")]
421    pub working_directories: Option<Vec<Uri>>,
422    /// Fork from an existing session. The new session is populated with content
423    /// from the source session up to and including the specified turn's response.
424    #[serde(default, skip_serializing_if = "Option::is_none")]
425    pub fork: Option<SessionForkSource>,
426    /// Agent-specific configuration values collected via `resolveSessionConfig`.
427    /// Keys and values correspond to the schema returned by the server.
428    #[serde(default, skip_serializing_if = "Option::is_none")]
429    pub config: Option<JsonObject>,
430    /// Eagerly claim an active client role for the new session.
431    ///
432    /// When provided, the server initializes the session with this client as an
433    /// active client, equivalent to dispatching a `session/activeClientSet`
434    /// action immediately after creation. The `clientId` MUST match the
435    /// `clientId` the creating client supplied in `initialize`.
436    #[serde(default, skip_serializing_if = "Option::is_none")]
437    pub active_client: Option<SessionActiveClient>,
438    /// Opt-in progress token. When set, the client is offering to receive
439    /// `progress` notifications (see `ProgressParams`) for any long-running work
440    /// the server does to bring this session up — most notably the lazy,
441    /// first-use download of the provider's native SDK. The server echoes this
442    /// exact token on every `progress` frame so the client can correlate it to
443    /// this `createSession` call (and the UI awaiting it).
444    ///
445    /// The token MUST be unique across the client's active requests. The server
446    /// MAY ignore it (e.g. when nothing long-running is needed), in which case no
447    /// `progress` notifications are emitted.
448    #[serde(default, skip_serializing_if = "Option::is_none")]
449    pub progress_token: Option<String>,
450}
451
452/// Disposes a session and cleans up server-side resources.
453///
454/// The server broadcasts a `root/sessionRemoved` notification to all clients.
455#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
456#[serde(rename_all = "camelCase")]
457pub struct DisposeSessionParams {
458    /// Channel URI this command targets.
459    pub channel: Uri,
460}
461
462/// Copies source history through a completed turn into the new chat.
463#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
464#[serde(rename_all = "camelCase")]
465pub struct ForkChatSource {
466    /// URI of the existing source chat.
467    pub chat: Uri,
468    /// Completed turn identifier in the source chat.
469    ///
470    /// Content through this turn is copied into the new chat's visible `turns`.
471    pub turn_id: String,
472}
473
474/// Supplies source context to a new side chat without copying it into the side
475/// chat's visible history.
476#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
477#[serde(rename_all = "camelCase")]
478pub struct SideChatSource {
479    /// URI of the existing source chat.
480    pub chat: Uri,
481    /// Stable source-turn identifier in the source chat.
482    ///
483    /// Hosts resolve this id against the source chat's current `activeTurn` or its
484    /// retained `turns` when accepting `createChat`. If it names the current
485    /// active turn, the host snapshots the source chat's retained history plus
486    /// that turn's current user message and any partial assistant response already
487    /// available. Once that turn later becomes historical, it is still referenced
488    /// by this same identifier.
489    pub turn_id: String,
490    /// Optional immutable selected-text snapshot to carry into the created side
491    /// chat's origin.
492    ///
493    /// When present, the host MUST snapshot and preserve this exact selection when
494    /// it accepts `createChat`; later source-turn deltas do not alter it.
495    #[serde(default, skip_serializing_if = "Option::is_none")]
496    pub selection: Option<SideChatSelection>,
497}
498
499/// Creates a new chat within a session.
500#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
501#[serde(rename_all = "camelCase")]
502pub struct CreateChatParams {
503    /// Channel URI this command targets.
504    pub channel: Uri,
505    /// Chat URI (client-chosen, e.g. `ahp-chat:/<uuid>`).
506    pub chat: Uri,
507    /// Optional initial message for the new chat.
508    #[serde(default, skip_serializing_if = "Option::is_none")]
509    pub initial_message: Option<Message>,
510    /// Optional source chat and source turn.
511    ///
512    /// The source chat MUST belong to this session. Clients MUST only request
513    /// `kind: "fork"` when the selected agent advertises
514    /// `capabilities.multipleChats.fork`, and `kind: "sideChat"` when the
515    /// selected agent advertises `capabilities.multipleChats.sideChat`. Both
516    /// source forms carry a stable top-level `turnId`. Forks target completed
517    /// turns. Side chats also carry a stable `turnId`, which the host resolves
518    /// against the source chat's current active turn or retained history. If it
519    /// resolves to the active turn, the host snapshots the currently available
520    /// partial response when accepting `createChat`. When
521    /// `source.kind === "sideChat"` and `source.selection` is present, the host
522    /// also snapshots and preserves that exact selected text in the created chat's
523    /// origin; any `responsePartId` there is provenance only, not a live range.
524    #[serde(default, skip_serializing_if = "Option::is_none")]
525    pub source: Option<ChatSource>,
526    /// Initial working-directory subset for this chat. Every entry MUST be
527    /// present in the owning session's `workingDirectories`; the server MUST
528    /// reject any entry that is not. When absent, the chat inherits the full
529    /// session set. Forked chats (those whose `source.kind` is `"fork"`) inherit
530    /// the source chat's `workingDirectories`; this field is ignored for forks.
531    ///
532    /// A client MUST NOT supply this field unless the agent advertises
533    /// {@link AgentCapabilities.multipleWorkingDirectories}.
534    #[serde(default, skip_serializing_if = "Option::is_none")]
535    pub working_directories: Option<Vec<Uri>>,
536}
537
538/// Disposes a chat and cleans up server-side resources.
539#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
540#[serde(rename_all = "camelCase")]
541pub struct DisposeChatParams {
542    /// Channel URI this command targets.
543    pub channel: Uri,
544}
545
546/// Returns a list of session summaries. Used to populate session lists and sidebars.
547///
548/// The session list is **not** part of the state tree because it can be arbitrarily
549/// large. Clients fetch it imperatively and maintain a local cache updated by
550/// `root/sessionAdded` and `root/sessionRemoved` notifications.
551///
552/// A large catalogue can be fetched incrementally via the {@link PaginatedParams}
553/// `limit`/`cursor` inputs (see that type for the full pagination contract). The
554/// server SHOULD return most-recently-modified entries first, so the first page
555/// is the immediately useful one. The `root/session*` notifications keep an
556/// already-fetched page live; pagination governs only the initial and backfill
557/// fetches.
558#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
559#[serde(rename_all = "camelCase")]
560pub struct ListSessionsParams {
561    /// Channel URI this command targets.
562    pub channel: Uri,
563    /// Maximum number of entries to return in this page. The server SHOULD respect
564    /// this bound but MAY return fewer entries and MAY impose its own upper cap.
565    /// Omit to let the server choose the page size.
566    #[serde(default, skip_serializing_if = "Option::is_none")]
567    pub limit: Option<i64>,
568    /// Opaque pagination cursor from a previous {@link PaginatedResult.nextCursor}.
569    /// Omit to fetch the first page. Cursors are server-defined and MUST be treated
570    /// as opaque — do not parse, modify, or persist them across connections. An
571    /// unrecognised cursor SHOULD be rejected with an `InvalidParams` error.
572    #[serde(default, skip_serializing_if = "Option::is_none")]
573    pub cursor: Option<String>,
574}
575
576/// Result of the `listSessions` command.
577#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
578#[serde(rename_all = "camelCase")]
579pub struct ListSessionsResult {
580    /// Opaque cursor for the next page. Present when more entries exist beyond the
581    /// returned page; absent signals the end of the collection. Pass it back as
582    /// {@link PaginatedParams.cursor} to fetch the following page.
583    #[serde(default, skip_serializing_if = "Option::is_none")]
584    pub next_cursor: Option<String>,
585    /// The list of session summaries. The server SHOULD order them
586    /// most-recently-modified first.
587    pub items: Vec<SessionSummary>,
588}
589
590/// Reads the content of a resource by URI.
591///
592/// Content references keep the state tree small by storing large data (images,
593/// long tool outputs) by reference rather than inline.
594///
595/// Binary content (images, etc.) MUST use `base64` encoding. Text content MAY
596/// use `utf-8` encoding.
597///
598/// Like all `resource*` methods, `resourceRead` is symmetrical and MAY be
599/// sent in either direction. Hosts use it to fetch content from a
600/// client-published URI (e.g. `virtual://my-client/...` plugins); clients
601/// use it to read host-side files. The receiver enforces access via the
602/// same permission/`resourceRequest` flow regardless of which peer initiated.
603#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
604#[serde(rename_all = "camelCase")]
605pub struct ResourceReadParams {
606    /// Channel URI this command targets.
607    pub channel: Uri,
608    /// Content URI from a `ContentRef`
609    pub uri: String,
610    /// Preferred encoding for the returned data (default: server-chosen)
611    #[serde(default, skip_serializing_if = "Option::is_none")]
612    pub encoding: Option<ContentEncoding>,
613}
614
615/// Result of the `resourceRead` command.
616///
617/// The server SHOULD honor the `encoding` requested in the params. If the
618/// server cannot provide the requested encoding, it MUST fall back to either
619/// `base64` or `utf-8`.
620#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
621#[serde(rename_all = "camelCase")]
622pub struct ResourceReadResult {
623    /// Content encoded as a string
624    pub data: String,
625    /// How `data` is encoded
626    pub encoding: ContentEncoding,
627    /// Content type (e.g. `"image/png"`, `"text/plain"`)
628    #[serde(default, skip_serializing_if = "Option::is_none")]
629    pub content_type: Option<String>,
630}
631
632/// Writes content to a file on the server's filesystem.
633///
634/// Binary content (images, etc.) MUST use `base64` encoding. Text content MAY
635/// use `utf-8` encoding.
636///
637/// If the file does not exist, it is created. If the file already exists, the
638/// effect on existing bytes depends on {@link ResourceWriteParams.mode}:
639/// `truncate` (default) overwrites from the chosen offset onward, `append`
640/// preserves all existing bytes and adds `data` at a position rooted at EOF,
641/// and `insert` preserves all existing bytes and splices `data` in at an
642/// offset rooted at the start of the file.
643///
644/// Like all `resource*` methods, `resourceWrite` is symmetrical and MAY be
645/// sent in either direction.
646#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
647#[serde(rename_all = "camelCase")]
648pub struct ResourceWriteParams {
649    /// Channel URI this command targets.
650    pub channel: Uri,
651    /// Target file URI on the server filesystem
652    pub uri: Uri,
653    /// Content encoded as a string
654    pub data: String,
655    /// How `data` is encoded
656    pub encoding: ContentEncoding,
657    /// Content type (e.g. `"text/plain"`, `"image/png"`)
658    #[serde(default, skip_serializing_if = "Option::is_none")]
659    pub content_type: Option<String>,
660    /// If `true`, the server MUST fail if the file already exists instead of
661    /// overwriting it. Useful for safe creation of new files.
662    #[serde(default, skip_serializing_if = "Option::is_none")]
663    pub create_only: Option<bool>,
664    /// How `data` is placed within the target file. Defaults to `'truncate'`
665    /// (full overwrite) when omitted. See {@link ResourceWriteMode} for the
666    /// meaning of each mode and how it interprets {@link position}.
667    #[serde(default, skip_serializing_if = "Option::is_none")]
668    pub mode: Option<ResourceWriteMode>,
669    /// Byte offset interpreted according to {@link mode}. Defaults to `0`.
670    /// - `truncate`: offset from the start of the file at which to truncate
671    ///   before writing.
672    /// - `append`: bytes back from EOF at which to insert `data`.
673    /// - `insert`: offset from the start of the file at which to splice in
674    ///   `data`.
675    #[serde(default, skip_serializing_if = "Option::is_none")]
676    pub position: Option<i64>,
677    /// Optimistic-concurrency token previously returned by
678    /// {@link ResourceResolveResult.etag}. When set, the server MUST fail with
679    /// `Conflict` if the current `etag` does not match — preventing lost
680    /// updates between a `resourceResolve` and a subsequent `resourceWrite`.
681    #[serde(default, skip_serializing_if = "Option::is_none")]
682    pub if_match: Option<String>,
683}
684
685/// Result of the `resourceWrite` command.
686///
687/// An empty object on success.
688#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
689#[serde(rename_all = "camelCase")]
690pub struct ResourceWriteResult {}
691
692/// Lists directory entries at a file URI on the server's filesystem.
693///
694/// This is intended for remote folder pickers and similar UI that needs to let
695/// users navigate the server's local filesystem.
696///
697/// The server MUST return success only if the target exists and is a directory.
698/// If the target does not exist, is not a directory, or cannot be accessed, the
699/// server MUST return a JSON-RPC error.
700///
701/// Like all `resource*` methods, `resourceList` is symmetrical and MAY be
702/// sent in either direction.
703#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
704#[serde(rename_all = "camelCase")]
705pub struct ResourceListParams {
706    /// Channel URI this command targets.
707    pub channel: Uri,
708    /// Directory URI on the server filesystem
709    pub uri: Uri,
710}
711
712/// Result of the `resourceList` command.
713#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
714#[serde(rename_all = "camelCase")]
715pub struct ResourceListResult {
716    /// Entries directly contained in the requested directory
717    pub entries: Vec<DirectoryEntry>,
718}
719
720/// Directory entry returned by `resourceList`.
721#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
722#[serde(rename_all = "camelCase")]
723pub struct DirectoryEntry {
724    /// Base name of the entry
725    pub name: String,
726    /// Whether the entry is a file or directory
727    pub r#type: String,
728}
729
730/// Copies a resource from one URI to another on the server's filesystem.
731///
732/// If the destination already exists, it is overwritten unless `failIfExists`
733/// is set.
734///
735/// Like all `resource*` methods, `resourceCopy` is symmetrical and MAY be
736/// sent in either direction.
737#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
738#[serde(rename_all = "camelCase")]
739pub struct ResourceCopyParams {
740    /// Channel URI this command targets.
741    pub channel: Uri,
742    /// Source URI to copy from
743    pub source: Uri,
744    /// Destination URI to copy to
745    pub destination: Uri,
746    /// If `true`, the server MUST fail if the destination already exists instead
747    /// of overwriting it.
748    #[serde(default, skip_serializing_if = "Option::is_none")]
749    pub fail_if_exists: Option<bool>,
750}
751
752/// Result of the `resourceCopy` command.
753///
754/// An empty object on success.
755#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
756#[serde(rename_all = "camelCase")]
757pub struct ResourceCopyResult {}
758
759/// Deletes a resource at a URI on the server's filesystem.
760///
761/// Like all `resource*` methods, `resourceDelete` is symmetrical and MAY be
762/// sent in either direction.
763#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
764#[serde(rename_all = "camelCase")]
765pub struct ResourceDeleteParams {
766    /// Channel URI this command targets.
767    pub channel: Uri,
768    /// URI of the resource to delete
769    pub uri: Uri,
770    /// If `true` and the target is a directory, delete it and all its contents
771    /// recursively. If `false` (default), deleting a non-empty directory MUST fail.
772    #[serde(default, skip_serializing_if = "Option::is_none")]
773    pub recursive: Option<bool>,
774}
775
776/// Result of the `resourceDelete` command.
777///
778/// An empty object on success.
779#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
780#[serde(rename_all = "camelCase")]
781pub struct ResourceDeleteResult {}
782
783/// Moves (renames) a resource from one URI to another on the server's filesystem.
784///
785/// If the destination already exists, it is overwritten unless `failIfExists`
786/// is set.
787///
788/// Like all `resource*` methods, `resourceMove` is symmetrical and MAY be
789/// sent in either direction.
790#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
791#[serde(rename_all = "camelCase")]
792pub struct ResourceMoveParams {
793    /// Channel URI this command targets.
794    pub channel: Uri,
795    /// Source URI to move from
796    pub source: Uri,
797    /// Destination URI to move to
798    pub destination: Uri,
799    /// If `true`, the server MUST fail if the destination already exists instead
800    /// of overwriting it.
801    #[serde(default, skip_serializing_if = "Option::is_none")]
802    pub fail_if_exists: Option<bool>,
803}
804
805/// Result of the `resourceMove` command.
806///
807/// An empty object on success.
808#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
809#[serde(rename_all = "camelCase")]
810pub struct ResourceMoveResult {}
811
812/// Resolves a resource — the combination of POSIX `stat` and `realpath`.
813///
814/// `resourceResolve` returns metadata about the resource together with its
815/// canonical URI after symlink resolution. Use this in place of any
816/// `resourceExists` shim: a missing resource MUST surface as a `NotFound`
817/// JSON-RPC error rather than a success with a sentinel value. Callers that
818/// truly need a boolean check should attempt `resourceResolve` and treat
819/// `NotFound` as "does not exist".
820///
821/// Like all `resource*` methods, `resourceResolve` is symmetrical and MAY be
822/// sent in either direction.
823#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
824#[serde(rename_all = "camelCase")]
825pub struct ResourceResolveParams {
826    /// Channel URI this command targets.
827    pub channel: Uri,
828    /// URI to resolve
829    pub uri: Uri,
830    /// When `true` (default), follow symlinks and report the metadata of the
831    /// link target — and set `uri` in the result to the canonical (realpath)
832    /// URI. When `false`, stat the link itself (lstat semantics) and report
833    /// `type: 'symlink'`.
834    #[serde(default, skip_serializing_if = "Option::is_none")]
835    pub follow_symlinks: Option<bool>,
836}
837
838/// Result of the `resourceResolve` command.
839#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
840#[serde(rename_all = "camelCase")]
841pub struct ResourceResolveResult {
842    /// Canonical URI after symlink resolution. Equal to the requested URI when
843    /// `followSymlinks` is `false` or the URI does not traverse a symlink.
844    pub uri: Uri,
845    /// Resource kind.
846    pub r#type: ResourceType,
847    /// Size in bytes. Omitted for directories when the provider cannot
848    /// cheaply compute it.
849    #[serde(default, skip_serializing_if = "Option::is_none")]
850    pub size: Option<i64>,
851    /// Last-modified time in ISO 8601 format, when known.
852    #[serde(default, skip_serializing_if = "Option::is_none")]
853    pub mtime: Option<String>,
854    /// Creation time in ISO 8601 format, when known.
855    #[serde(default, skip_serializing_if = "Option::is_none")]
856    pub ctime: Option<String>,
857    /// Sniffed MIME type, when known (e.g. `"text/plain"`, `"image/png"`).
858    #[serde(default, skip_serializing_if = "Option::is_none")]
859    pub content_type: Option<String>,
860    /// Opaque per-provider version token. When present, pass it as
861    /// {@link ResourceWriteParams.ifMatch} on a subsequent `resourceWrite` to
862    /// detect concurrent modifications.
863    #[serde(default, skip_serializing_if = "Option::is_none")]
864    pub etag: Option<String>,
865}
866
867/// Creates a directory on the server's filesystem with `mkdir -p` semantics.
868///
869/// The server MUST create any missing parent directories. Creating a
870/// directory that already exists is a no-op success. If `uri` already
871/// exists but is **not** a directory, the server MUST fail with
872/// `AlreadyExists`.
873///
874/// Like all `resource*` methods, `resourceMkdir` is symmetrical and MAY be
875/// sent in either direction.
876#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
877#[serde(rename_all = "camelCase")]
878pub struct ResourceMkdirParams {
879    /// Channel URI this command targets.
880    pub channel: Uri,
881    /// Directory URI to create (parents created as needed).
882    pub uri: Uri,
883}
884
885/// Result of the `resourceMkdir` command.
886///
887/// An empty object on success.
888#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
889#[serde(rename_all = "camelCase")]
890pub struct ResourceMkdirResult {}
891
892/// Requests permission to access a resource on the receiver's filesystem.
893///
894/// `resourceRequest` is symmetrical and MAY be sent in either direction: a
895/// client asks the server to grant access to a server-side resource, or a
896/// server asks the client to grant access to a client-side resource. The
897/// receiver decides whether to allow, deny, or prompt the user for the
898/// requested access.
899///
900/// If the receiver denies access, it MUST respond with `PermissionDenied`
901/// (-32009). The error data MAY include a `ResourceRequestParams` value
902/// describing the access the caller would need to be granted for the
903/// operation to succeed; see `PermissionDeniedErrorData` in
904/// `types/errors.ts`.
905///
906/// After a successful `resourceRequest`, the caller MAY use the corresponding
907/// `resource*` commands (e.g. `resourceRead`, `resourceWrite`) to perform the
908/// operation. Receivers MAY rescind access at any time by returning
909/// `PermissionDenied` on subsequent operations.
910///
911/// Either `read`, `write`, or both SHOULD be set to `true`. A request with
912/// neither flag set is treated as `read: true` by receivers.
913#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
914#[serde(rename_all = "camelCase")]
915pub struct ResourceRequestParams {
916    /// Channel URI this command targets.
917    pub channel: Uri,
918    /// Resource URI being requested. Typically a `file:` URI on the receiver's
919    /// filesystem, but any URI scheme that the receiver mediates access to is
920    /// allowed.
921    pub uri: Uri,
922    /// Whether the caller needs read access to the resource.
923    #[serde(default, skip_serializing_if = "Option::is_none")]
924    pub read: Option<bool>,
925    /// Whether the caller needs write access to the resource.
926    #[serde(default, skip_serializing_if = "Option::is_none")]
927    pub write: Option<bool>,
928}
929
930/// Result of the `resourceRequest` command.
931///
932/// An empty object on success.
933#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
934#[serde(rename_all = "camelCase")]
935pub struct ResourceRequestResult {}
936
937/// Creates a resource watcher on the receiver's filesystem.
938///
939/// The receiver allocates an `ahp-resource-watch:/<id>` channel URI and
940/// returns it on {@link CreateResourceWatchResult.channel}. The caller then
941/// [`subscribe`](./subscriptions)s to that channel to receive
942/// `resourceWatch/changed` actions over the standard action envelope.
943///
944/// The watch lifecycle is tied to subscription: when every subscriber has
945/// unsubscribed (or the underlying connection drops), the receiver MUST
946/// release the watcher. There is no explicit dispose command — `unsubscribe`
947/// is the only handle the caller needs.
948///
949/// Like the rest of the `resource*` family, `createResourceWatch` is
950/// symmetrical and MAY be sent in either direction. Access is gated through
951/// the same permission flow as `resourceRead`/`resourceWrite`.
952#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
953#[serde(rename_all = "camelCase")]
954pub struct CreateResourceWatchParams {
955    /// Channel URI this command targets.
956    pub channel: Uri,
957    /// URI to watch.
958    pub uri: Uri,
959    /// If `true`, the receiver MUST report changes for descendants of `uri`.
960    /// If `false` (default), only changes to `uri` itself — and, when `uri`
961    /// is a directory, its direct children — are reported.
962    #[serde(default, skip_serializing_if = "Option::is_none")]
963    pub recursive: Option<bool>,
964    /// Glob patterns or paths relative to `uri` to exclude from reporting.
965    /// Wrapped in `{ items }` for forward compatibility.
966    #[serde(default, skip_serializing_if = "Option::is_none")]
967    pub excludes: Option<AnyValue>,
968    /// Glob patterns or paths relative to `uri` to restrict reporting to.
969    /// Omit to report every change under `uri` subject to `excludes`.
970    /// Wrapped in `{ items }` for forward compatibility.
971    #[serde(default, skip_serializing_if = "Option::is_none")]
972    pub includes: Option<AnyValue>,
973}
974
975/// Result of the `createResourceWatch` command.
976#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
977#[serde(rename_all = "camelCase")]
978pub struct CreateResourceWatchResult {
979    /// Receiver-assigned watch channel URI (`ahp-resource-watch:/<id>`). The
980    /// caller subscribes to this URI to start receiving change events and
981    /// unsubscribes to release the watcher.
982    pub channel: Uri,
983}
984
985/// Requests that the host load older historical turns into a chat state.
986///
987/// The command result does not carry turns. Instead, before responding, the host
988/// MUST dispatch `chat/turnsLoaded` to insert any loaded turns into the chat
989/// channel's `turns` state, ahead of the already-loaded window, and update or
990/// clear `turnsNextCursor`.
991///
992/// Before applying any operation that references a turn outside the currently
993/// loaded window, the host MUST eagerly load enough older turns into state for
994/// that operation to reduce against valid state.
995#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
996#[serde(rename_all = "camelCase")]
997pub struct FetchTurnsParams {
998    /// Channel URI this command targets.
999    pub channel: Uri,
1000    /// Opaque cursor from `ChatState.turnsNextCursor`.
1001    ///
1002    /// The host MUST reject unrecognised cursors with `InvalidParams`. Omit only
1003    /// when asking the host to opportunistically load its next older page for the
1004    /// chat, if any.
1005    #[serde(default, skip_serializing_if = "Option::is_none")]
1006    pub cursor: Option<String>,
1007}
1008
1009/// Result of the `fetchTurns` command.
1010#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1011#[serde(rename_all = "camelCase")]
1012pub struct FetchTurnsResult {}
1013
1014/// Stop receiving updates for a channel.
1015#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1016#[serde(rename_all = "camelCase")]
1017pub struct UnsubscribeParams {
1018    /// Channel URI to unsubscribe from
1019    pub channel: Uri,
1020}
1021
1022/// Fire-and-forget action dispatch (write-ahead). The client applies actions
1023/// optimistically to local state and the server echoes them back as an
1024/// {@link ActionEnvelope} once accepted.
1025///
1026/// The client → server method is named `dispatchAction`; the server's reply
1027/// arrives on the server → client `action` notification (params:
1028/// {@link ActionEnvelope}).
1029#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1030#[serde(rename_all = "camelCase")]
1031pub struct DispatchActionParams {
1032    /// Channel URI this action targets
1033    pub channel: Uri,
1034    /// Client sequence number
1035    pub client_seq: i64,
1036    /// The action to dispatch
1037    pub action: StateAction,
1038}
1039
1040/// Pushes a Bearer token for a protected resource. The `resource` field MUST
1041/// match a protected-resource identifier the client has discovered from the
1042/// server — whether declared statically in `AgentInfo.protectedResources`,
1043/// or discovered dynamically from a live `McpServerAuthRequiredState.resource`
1044/// or `ToolCallAuthRequiredState.auth.resource` (both surfaced only once the
1045/// corresponding MCP server or tool call actually challenges for auth).
1046/// Servers MUST accept any `resource` value they have themselves advertised
1047/// through one of these three mechanisms.
1048///
1049/// Tokens are delivered using [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750)
1050/// (Bearer Token Usage) semantics. The client obtains the token from the
1051/// authorization server(s) listed in the resource's metadata and pushes it
1052/// to the server via this command.
1053#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1054#[serde(rename_all = "camelCase")]
1055pub struct AuthenticateParams {
1056    /// Channel URI this command targets.
1057    pub channel: Uri,
1058    /// The protected resource identifier. MUST match a `resource` value the
1059    /// server has advertised — via `ProtectedResourceMetadata` in
1060    /// `AgentInfo.protectedResources`, or via a live
1061    /// `McpServerAuthRequiredState.resource` / `ToolCallAuthRequiredState.auth.resource`.
1062    pub resource: String,
1063    /// Bearer token obtained from the resource's authorization server
1064    pub token: String,
1065    /// OAuth scopes the token grants, when known. Lets the server determine
1066    /// whether a specific challenge — e.g. the `requiredScopes` on a live
1067    /// `McpServerAuthRequiredState` or `ToolCallAuthRequiredState.auth` — is
1068    /// satisfied without decoding the (opaque, server-specific) token itself.
1069    /// Omit when the client doesn't track granted scopes separately from the
1070    /// token.
1071    #[serde(default, skip_serializing_if = "Option::is_none")]
1072    pub scopes: Option<Vec<String>>,
1073}
1074
1075/// Result of the `authenticate` command.
1076///
1077/// An empty object on success. If the token is invalid or the resource is
1078/// unrecognized, the server MUST return a JSON-RPC error (e.g. `AuthRequired`
1079/// `-32007` or `InvalidParams` `-32602`).
1080#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1081#[serde(rename_all = "camelCase")]
1082pub struct AuthenticateResult {}
1083
1084/// Creates a new terminal on the server.
1085///
1086/// After creation, the client should subscribe to the terminal URI to receive
1087/// state updates. The server dispatches `root/terminalsChanged` to update the
1088/// root terminal list.
1089#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1090#[serde(rename_all = "camelCase")]
1091pub struct CreateTerminalParams {
1092    /// Channel URI this command targets.
1093    pub channel: Uri,
1094    /// Initial owner of the terminal
1095    pub claim: TerminalClaim,
1096    /// Human-readable terminal name
1097    #[serde(default, skip_serializing_if = "Option::is_none")]
1098    pub name: Option<String>,
1099    /// Initial working directory URI
1100    #[serde(default, skip_serializing_if = "Option::is_none")]
1101    pub cwd: Option<Uri>,
1102    /// Initial terminal width in columns
1103    #[serde(default, skip_serializing_if = "Option::is_none")]
1104    pub cols: Option<i64>,
1105    /// Initial terminal height in rows
1106    #[serde(default, skip_serializing_if = "Option::is_none")]
1107    pub rows: Option<i64>,
1108}
1109
1110/// Disposes a terminal and kills its process if still running.
1111///
1112/// The server dispatches `root/terminalsChanged` to remove the terminal from
1113/// the root terminal list.
1114#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1115#[serde(rename_all = "camelCase")]
1116pub struct DisposeTerminalParams {
1117    /// Channel URI this command targets.
1118    pub channel: Uri,
1119}
1120
1121/// Iteratively resolves the session configuration schema. The client sends the
1122/// current partial session config and any user-filled metadata values. The server
1123/// returns a property schema describing what additional metadata is needed,
1124/// contextual to the current selections.
1125///
1126/// The client calls this command whenever the user changes a significant input
1127/// (e.g. picks a working directory, toggles a property). Each response returns
1128/// the full current property set (not a delta). The returned `values` contain
1129/// server-resolved defaults to pass to `createSession`.
1130#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1131#[serde(rename_all = "camelCase")]
1132pub struct ResolveSessionConfigParams {
1133    /// Channel URI this command targets.
1134    pub channel: Uri,
1135    /// Agent provider ID
1136    #[serde(default, skip_serializing_if = "Option::is_none")]
1137    pub provider: Option<String>,
1138    /// Working directory for the session
1139    #[serde(default, skip_serializing_if = "Option::is_none")]
1140    pub working_directory: Option<Uri>,
1141    /// Current user-filled configuration values
1142    #[serde(default, skip_serializing_if = "Option::is_none")]
1143    pub config: Option<JsonObject>,
1144}
1145
1146/// Result of the `resolveSessionConfig` command.
1147#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1148#[serde(rename_all = "camelCase")]
1149pub struct ResolveSessionConfigResult {
1150    /// JSON Schema describing available configuration properties given the current context
1151    pub schema: SessionConfigSchema,
1152    /// Current configuration values (echoed back with server-resolved defaults applied)
1153    pub values: JsonObject,
1154}
1155
1156/// Queries the server for allowed values of a dynamic session config property.
1157///
1158/// Used when a property in the schema returned by `resolveSessionConfig` has
1159/// `enumDynamic: true`. The client sends a search query and receives matching
1160/// values with display metadata.
1161#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1162#[serde(rename_all = "camelCase")]
1163pub struct SessionConfigCompletionsParams {
1164    /// Channel URI this command targets.
1165    pub channel: Uri,
1166    /// Agent provider ID
1167    #[serde(default, skip_serializing_if = "Option::is_none")]
1168    pub provider: Option<String>,
1169    /// Working directory for the session
1170    #[serde(default, skip_serializing_if = "Option::is_none")]
1171    pub working_directory: Option<Uri>,
1172    /// Current user-filled configuration values (provides context for the query)
1173    #[serde(default, skip_serializing_if = "Option::is_none")]
1174    pub config: Option<JsonObject>,
1175    /// Property id from the schema to query values for
1176    pub property: String,
1177    /// Search filter text (empty or omitted returns default/recent values)
1178    #[serde(default, skip_serializing_if = "Option::is_none")]
1179    pub query: Option<String>,
1180}
1181
1182/// Result of the `sessionConfigCompletions` command.
1183#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1184#[serde(rename_all = "camelCase")]
1185pub struct SessionConfigCompletionsResult {
1186    /// Matching value items
1187    pub items: Vec<SessionConfigValueItem>,
1188}
1189
1190/// A single value item returned by `sessionConfigCompletions`.
1191#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1192#[serde(rename_all = "camelCase")]
1193pub struct SessionConfigValueItem {
1194    /// The value to store in config
1195    pub value: String,
1196    /// Human-readable display label
1197    pub label: String,
1198    /// Optional secondary description
1199    #[serde(default, skip_serializing_if = "Option::is_none")]
1200    pub description: Option<String>,
1201}
1202
1203/// Requests completion items for a partially-typed input (e.g. a user message
1204/// the user is currently composing). Used to power `@`-mention pickers,
1205/// file/symbol references, and similar inline-completion experiences.
1206///
1207/// Servers SHOULD treat this command as best-effort and return promptly. The
1208/// client SHOULD debounce calls to avoid flooding the server with requests on
1209/// every keystroke.
1210#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1211#[serde(rename_all = "camelCase")]
1212pub struct CompletionsParams {
1213    /// Channel URI this command targets.
1214    pub channel: Uri,
1215    /// What kind of completion is being requested.
1216    pub kind: CompletionItemKind,
1217    /// The complete text of the input being completed (e.g. the full user
1218    /// message text typed so far).
1219    pub text: String,
1220    /// The character offset within `text` at which the completion is requested,
1221    /// measured in UTF-16 code units. MUST satisfy `0 <= offset <= text.length`.
1222    pub offset: i64,
1223}
1224
1225/// A single completion item returned by the `completions` command.
1226///
1227/// When the user accepts an item, the client SHOULD:
1228/// 1. Replace the range `[rangeStart, rangeEnd)` in the input with `insertText`
1229///    (or insert `insertText` at the cursor when the range is omitted).
1230/// 2. Associate the item's `attachment` with the resulting {@link Message}.
1231#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1232#[serde(rename_all = "camelCase")]
1233pub struct CompletionItem {
1234    /// The text inserted into the input when this item is accepted.
1235    pub insert_text: String,
1236    /// If defined, the start of the range in the input's `text` that is replaced
1237    /// by `insertText`. The range is the half-open interval
1238    /// `[rangeStart, rangeEnd)` of character offsets, measured in UTF-16 code
1239    /// units.
1240    ///
1241    /// When omitted, the client SHOULD insert `insertText` at the cursor.
1242    ///
1243    /// Note: this range refers to positions in the *current* input. The
1244    /// attachment's own `rangeStart`/`rangeEnd` (when present) refer to
1245    /// positions in the final {@link Message.text} after the item is
1246    /// accepted.
1247    #[serde(default, skip_serializing_if = "Option::is_none")]
1248    pub range_start: Option<i64>,
1249    /// The end of the range in the input's `text` that is replaced by
1250    /// `insertText`. See {@link rangeStart}.
1251    #[serde(default, skip_serializing_if = "Option::is_none")]
1252    pub range_end: Option<i64>,
1253    /// The attachment associated with this completion item.
1254    pub attachment: MessageAttachment,
1255}
1256
1257/// Result of the `completions` command.
1258#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1259#[serde(rename_all = "camelCase")]
1260pub struct CompletionsResult {
1261    /// The completion items, in the order the server suggests displaying them.
1262    pub items: Vec<CompletionItem>,
1263}
1264
1265/// Invokes a server-defined {@link ChangesetOperation} against a changeset,
1266/// a single file, or a line range.
1267///
1268/// The server validates that `operationId` exists in the changeset's
1269/// current `operations` list and that the requested `target.kind` is
1270/// contained in the operation's `scopes`. Invalid combinations result in a
1271/// JSON-RPC error.
1272///
1273/// State changes resulting from invocation flow back through the normal
1274/// `changeset/*` action stream on the relevant changeset URIs. Clients
1275/// SHOULD NOT synthesise local optimistic changes for invocations unless
1276/// the server explicitly opts in via a future capability.
1277#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1278#[serde(rename_all = "camelCase")]
1279pub struct InvokeChangesetOperationParams {
1280    /// Channel URI this command targets.
1281    pub channel: Uri,
1282    /// Matches {@link ChangesetOperation.id} from the changeset's `operations` list.
1283    pub operation_id: String,
1284    /// Target of the operation. Required iff the chosen scope is
1285    /// `'resource'` or `'range'`. Omit for changeset-scoped operations.
1286    #[serde(default, skip_serializing_if = "Option::is_none")]
1287    pub target: Option<ChangesetOperationTarget>,
1288}
1289
1290/// Result of the {@link InvokeChangesetOperationParams | `invokeChangesetOperation`}
1291/// command.
1292///
1293/// Success is implicit: the server returns this result when it accepted
1294/// the operation. Failure is signalled by rejecting the JSON-RPC request
1295/// with an appropriate error code, not by any field on this result. The
1296/// operation MAY still produce subsequent failure feedback through the
1297/// {@link ChangesetStatusChangedAction | `changeset/statusChanged`} stream.
1298#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1299#[serde(rename_all = "camelCase")]
1300pub struct InvokeChangesetOperationResult {
1301    /// Optional human-readable message describing the result.
1302    #[serde(default, skip_serializing_if = "Option::is_none")]
1303    pub message: Option<StringOrMarkdown>,
1304    /// Optional follow-up: a URI to open (e.g. a PR), a content ref, etc.
1305    #[serde(default, skip_serializing_if = "Option::is_none")]
1306    pub follow_up: Option<ChangesetOperationFollowUp>,
1307}
1308
1309/// Optional follow-up surfaced by the server after an operation completes —
1310/// a {@link ContentRef} the client can fetch and display.
1311///
1312/// Set `external` to `true` to open the content in the user's preferred
1313/// external handler (e.g. browser); otherwise the client is expected to
1314/// surface it inline.
1315#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1316#[serde(rename_all = "camelCase")]
1317pub struct ChangesetOperationFollowUp {
1318    pub content: ContentRef,
1319    /// When `true`, open in an external handler rather than inline.
1320    #[serde(default, skip_serializing_if = "Option::is_none")]
1321    pub external: Option<bool>,
1322}
1323
1324// ─── ChatSource Union ─────────────────────────────────────────────────
1325
1326/// How a new chat uses a source chat.
1327#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1328#[serde(tag = "kind")]
1329pub enum ChatSource {
1330    #[serde(rename = "fork")]
1331    Fork(ForkChatSource),
1332    #[serde(rename = "sideChat")]
1333    SideChat(SideChatSource),
1334}
1335
1336// ─── ReconnectResult Union ────────────────────────────────────────────
1337
1338/// Result of the `reconnect` command.
1339#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1340#[serde(tag = "type")]
1341pub enum ReconnectResult {
1342    #[serde(rename = "replay")]
1343    Replay(ReconnectReplayResult),
1344    #[serde(rename = "snapshot")]
1345    Snapshot(ReconnectSnapshotResult),
1346}
1347
1348// ─── Changeset Operation Unions ───────────────────────────────────────
1349
1350/// Identifies the file or range a `ChangesetOperation` should act on.
1351#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1352#[serde(tag = "kind")]
1353pub enum ChangesetOperationTarget {
1354    #[serde(rename = "resource")]
1355    Resource {
1356        resource: Uri,
1357        #[serde(default, skip_serializing_if = "Option::is_none")]
1358        side: Option<String>,
1359    },
1360    #[serde(rename = "range")]
1361    Range {
1362        resource: Uri,
1363        #[serde(default, skip_serializing_if = "Option::is_none")]
1364        side: Option<String>,
1365        range: TextRange,
1366    },
1367}