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, MessageAttachment, ModelSelection, SessionActiveClient,
19    SessionConfigSchema, SessionSummary, Snapshot, SnapshotState, TelemetryCapabilities,
20    TerminalClaim, 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/// Encoding of fetched content data.
35#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
36pub enum ContentEncoding {
37    #[serde(rename = "base64")]
38    Base64,
39    #[serde(rename = "utf-8")]
40    Utf8,
41}
42
43/// The kind of completion items being requested.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
45pub enum CompletionItemKind {
46    /// Completions for the text of a {@link Message} the user is composing.
47    /// Each returned item carries an attachment that gets associated with the
48    /// message when accepted.
49    #[serde(rename = "userMessage")]
50    UserMessage,
51}
52
53/// Discriminant for {@link ResourceResolveResult.type}.
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
55pub enum ResourceType {
56    #[serde(rename = "file")]
57    File,
58    #[serde(rename = "directory")]
59    Directory,
60    #[serde(rename = "symlink")]
61    Symlink,
62}
63
64/// How {@link ResourceWriteParams.data} is placed within the target file.
65///
66/// Each mode interprets {@link ResourceWriteParams.position} differently:
67///
68/// - `truncate` (default): rooted at the **start** of the file. The file is
69///   truncated at `position` (0 by default) and `data` is written from that
70///   offset, so the resulting file is `existing[0..position] + data`. With
71///   `position` omitted this is a full overwrite.
72/// - `append`: rooted at the **end** of the file. `position` counts bytes
73///   backwards from EOF, so `position: 0` (the default) writes at EOF —
74///   POSIX append — and `position: 5` inserts `data` 5 bytes before the
75///   current EOF, shifting those trailing 5 bytes after the inserted region.
76///   The server MUST evaluate the effective EOF and write atomically with
77///   respect to other appenders so concurrent `append` writes do not
78///   clobber each other.
79/// - `insert`: rooted at the **start** of the file. `position` (0 by default)
80///   is the byte offset at which `data` is spliced in; bytes at or after
81///   `position` are shifted right by `data.length`. `insert` always grows
82///   the file — use `truncate` to overwrite bytes in place.
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
84pub enum ResourceWriteMode {
85    #[serde(rename = "truncate")]
86    Truncate,
87    #[serde(rename = "append")]
88    Append,
89    #[serde(rename = "insert")]
90    Insert,
91}
92
93// ─── Command Payloads ─────────────────────────────────────────────────
94
95/// Establishes a new connection and negotiates the protocol version.
96/// This MUST be the first message sent by the client.
97#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
98#[serde(rename_all = "camelCase")]
99pub struct InitializeParams {
100    /// Channel URI this command targets.
101    pub channel: Uri,
102    /// Protocol versions the client is willing to speak, ordered from most
103    /// preferred to least preferred. Each entry is a [SemVer](https://semver.org)
104    /// `MAJOR.MINOR.PATCH` string (e.g. `"0.1.0"`).
105    ///
106    /// The server selects one entry and returns it as `InitializeResult.protocolVersion`.
107    /// If the server cannot speak any of the offered versions, it MUST return
108    /// error code `-32005` (`UnsupportedProtocolVersion`).
109    pub protocol_versions: Vec<String>,
110    /// Unique client identifier
111    pub client_id: String,
112    /// URIs to subscribe to during handshake
113    #[serde(default, skip_serializing_if = "Option::is_none")]
114    pub initial_subscriptions: Option<Vec<Uri>>,
115    /// IETF BCP 47 language tag indicating the client's preferred locale
116    /// (e.g. `"en-US"`, `"ja"`). The server SHOULD use this to localise
117    /// user-facing strings such as confirmation option labels.
118    #[serde(default, skip_serializing_if = "Option::is_none")]
119    pub locale: Option<String>,
120    /// Optional client capability declarations.
121    ///
122    /// Servers SHOULD only advertise features whose corresponding client
123    /// capability is set here. Absent means "not declared" — the server
124    /// MUST assume the client does not support the feature.
125    #[serde(default, skip_serializing_if = "Option::is_none")]
126    pub capabilities: Option<ClientCapabilities>,
127}
128
129/// Result of the `initialize` command.
130///
131/// `protocolVersion` is the version the server has selected from the client's
132/// `protocolVersions` list. The client and server MUST use this version for
133/// the rest of the connection. If the server cannot speak any of the offered
134/// versions it MUST return error code `-32005` (`UnsupportedProtocolVersion`)
135/// instead of a result.
136#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
137#[serde(rename_all = "camelCase")]
138pub struct InitializeResult {
139    /// Protocol version selected by the server. MUST be one of the entries in
140    /// `InitializeParams.protocolVersions`. Formatted as a [SemVer](https://semver.org)
141    /// `MAJOR.MINOR.PATCH` string (e.g. `"0.1.0"`).
142    pub protocol_version: String,
143    /// Current server sequence number
144    pub server_seq: i64,
145    /// Snapshots for each `initialSubscriptions` URI
146    pub snapshots: Vec<Snapshot>,
147    /// Suggested default directory for remote filesystem browsing
148    #[serde(default, skip_serializing_if = "Option::is_none")]
149    pub default_directory: Option<Uri>,
150    /// Characters that, when typed in a {@link Message} input, SHOULD cause
151    /// the client to issue a `completions` request with
152    /// {@link CompletionItemKind.UserMessage}. Typically includes characters like
153    /// `'@'` or `'/'`.
154    #[serde(default, skip_serializing_if = "Option::is_none")]
155    pub completion_trigger_characters: Option<Vec<String>>,
156    /// OTLP telemetry channels the host emits, if any. Each populated field is
157    /// either a literal `ahp-otlp:` channel URI or an RFC 6570 URI template a
158    /// client expands before subscribing (currently only the `logs` channel
159    /// defines a template variable, `{level}`, for subscriber-side severity
160    /// filtering). Clients MAY ignore signals they cannot process.
161    #[serde(default, skip_serializing_if = "Option::is_none")]
162    pub telemetry: Option<TelemetryCapabilities>,
163}
164
165/// Optional capabilities a client declares during `initialize`.
166///
167/// Each field is a presence flag: an empty object `{}` means "supported",
168/// absence means "not supported". Sub-fields on individual capabilities
169/// are reserved for future per-capability options.
170#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
171#[serde(rename_all = "camelCase")]
172pub struct ClientCapabilities {
173    /// Client can render
174    /// [MCP Apps](https://github.com/modelcontextprotocol/ext-apps) — i.e.
175    /// it can host the View sandbox, run the `ui/*` protocol against it,
176    /// and forward `mcp://`-channel traffic on the App's behalf.
177    ///
178    /// Hosts SHOULD only populate
179    /// {@link McpServerCustomization.mcpApp | `McpServerCustomization.mcpApp`}
180    /// (and expose the corresponding
181    /// {@link McpServerCustomization.channel | `mcp://` channel}) when this
182    /// capability is declared. Clients that omit it MUST treat
183    /// App-bearing tool calls as ordinary MCP tool calls.
184    #[serde(default, skip_serializing_if = "Option::is_none")]
185    pub mcp_apps: Option<JsonObject>,
186}
187
188/// Re-establishes a dropped connection. The server replays missed actions or
189/// provides fresh snapshots.
190#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
191#[serde(rename_all = "camelCase")]
192pub struct ReconnectParams {
193    /// Channel URI this command targets.
194    pub channel: Uri,
195    /// Client identifier from the original connection
196    pub client_id: String,
197    /// Last `serverSeq` the client received
198    pub last_seen_server_seq: i64,
199    /// URIs the client was subscribed to
200    pub subscriptions: Vec<Uri>,
201}
202
203/// Reconnect result when the server can replay from the requested sequence.
204///
205/// The server MUST include all replayed data in the response.
206#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
207#[serde(rename_all = "camelCase")]
208pub struct ReconnectReplayResult {
209    /// Missed action envelopes since `lastSeenServerSeq`
210    pub actions: Vec<ActionEnvelope>,
211    /// URIs from `ReconnectParams.subscriptions` that the server cannot resume.
212    /// This includes resources that no longer exist (e.g. disposed sessions or
213    /// terminals) as well as resources the client is no longer permitted to
214    /// observe. Clients SHOULD drop these from their local subscription set.
215    pub missing: Vec<Uri>,
216}
217
218/// Reconnect result when the gap exceeds the replay buffer.
219#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
220#[serde(rename_all = "camelCase")]
221pub struct ReconnectSnapshotResult {
222    /// Fresh snapshots for each subscription
223    pub snapshots: Vec<Snapshot>,
224}
225
226/// Subscribe to a URI-identified channel.
227///
228/// A channel MAY have state associated with it (e.g. root, sessions,
229/// terminals) or be stateless (pure pub/sub for streaming data). For
230/// state-bearing channels the result includes a snapshot; for stateless
231/// channels `snapshot` is omitted.
232#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
233#[serde(rename_all = "camelCase")]
234pub struct SubscribeParams {
235    /// Channel URI this command targets.
236    pub channel: Uri,
237}
238
239/// Result of the `subscribe` command.
240///
241/// `snapshot` is present when the subscribed channel has associated state, and
242/// absent for stateless channels.
243#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
244#[serde(rename_all = "camelCase")]
245pub struct SubscribeResult {
246    /// Snapshot of the subscribed channel's state (omitted for stateless channels)
247    #[serde(default, skip_serializing_if = "Option::is_none")]
248    pub snapshot: Option<Snapshot>,
249}
250
251/// Creates a new session with the specified agent provider.
252///
253/// If the session URI already exists, the server MUST return an error with code
254/// `-32003` (`SessionAlreadyExists`).
255///
256/// After creation, the client should subscribe to the session URI to receive state
257/// updates. The server also broadcasts a `root/sessionAdded` notification to all
258/// clients.
259#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
260#[serde(rename_all = "camelCase")]
261pub struct SessionForkSource {
262    /// URI of the existing session to fork from
263    pub session: Uri,
264    /// Turn ID in the source session; content up to and including this turn's response is copied
265    pub turn_id: String,
266}
267
268#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
269#[serde(rename_all = "camelCase")]
270pub struct CreateSessionParams {
271    /// Channel URI this command targets.
272    pub channel: Uri,
273    /// Agent provider ID
274    #[serde(default, skip_serializing_if = "Option::is_none")]
275    pub provider: Option<String>,
276    /// Model selection (ID and optional model-specific configuration)
277    #[serde(default, skip_serializing_if = "Option::is_none")]
278    pub model: Option<ModelSelection>,
279    /// Initial custom agent selection for the new session.
280    ///
281    /// Omit to start the session with no custom agent selected (provider default).
282    #[serde(default, skip_serializing_if = "Option::is_none")]
283    pub agent: Option<AgentSelection>,
284    /// Working directory for the session
285    #[serde(default, skip_serializing_if = "Option::is_none")]
286    pub working_directory: Option<Uri>,
287    /// Fork from an existing session. The new session is populated with content
288    /// from the source session up to and including the specified turn's response.
289    #[serde(default, skip_serializing_if = "Option::is_none")]
290    pub fork: Option<SessionForkSource>,
291    /// Agent-specific configuration values collected via `resolveSessionConfig`.
292    /// Keys and values correspond to the schema returned by the server.
293    #[serde(default, skip_serializing_if = "Option::is_none")]
294    pub config: Option<JsonObject>,
295    /// Eagerly claim the active client role for the new session.
296    ///
297    /// When provided, the server initializes the session with this client as the
298    /// active client, equivalent to dispatching a `session/activeClientChanged`
299    /// action immediately after creation. The `clientId` MUST match the
300    /// `clientId` the creating client supplied in `initialize`.
301    #[serde(default, skip_serializing_if = "Option::is_none")]
302    pub active_client: Option<SessionActiveClient>,
303}
304
305/// Disposes a session and cleans up server-side resources.
306///
307/// The server broadcasts a `root/sessionRemoved` notification to all clients.
308#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
309#[serde(rename_all = "camelCase")]
310pub struct DisposeSessionParams {
311    /// Channel URI this command targets.
312    pub channel: Uri,
313}
314
315/// Returns a list of session summaries. Used to populate session lists and sidebars.
316///
317/// The session list is **not** part of the state tree because it can be arbitrarily
318/// large. Clients fetch it imperatively and maintain a local cache updated by
319/// `root/sessionAdded` and `root/sessionRemoved` notifications.
320#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
321#[serde(rename_all = "camelCase")]
322pub struct ListSessionsParams {
323    /// Channel URI this command targets.
324    pub channel: Uri,
325    /// Optional filter criteria
326    #[serde(default, skip_serializing_if = "Option::is_none")]
327    pub filter: Option<AnyValue>,
328}
329
330/// Result of the `listSessions` command.
331#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
332#[serde(rename_all = "camelCase")]
333pub struct ListSessionsResult {
334    /// The list of session summaries.
335    pub items: Vec<SessionSummary>,
336}
337
338/// Reads the content of a resource by URI.
339///
340/// Content references keep the state tree small by storing large data (images,
341/// long tool outputs) by reference rather than inline.
342///
343/// Binary content (images, etc.) MUST use `base64` encoding. Text content MAY
344/// use `utf-8` encoding.
345///
346/// Like all `resource*` methods, `resourceRead` is symmetrical and MAY be
347/// sent in either direction. Hosts use it to fetch content from a
348/// client-published URI (e.g. `virtual://my-client/...` plugins); clients
349/// use it to read host-side files. The receiver enforces access via the
350/// same permission/`resourceRequest` flow regardless of which peer initiated.
351#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
352#[serde(rename_all = "camelCase")]
353pub struct ResourceReadParams {
354    /// Channel URI this command targets.
355    pub channel: Uri,
356    /// Content URI from a `ContentRef`
357    pub uri: String,
358    /// Preferred encoding for the returned data (default: server-chosen)
359    #[serde(default, skip_serializing_if = "Option::is_none")]
360    pub encoding: Option<ContentEncoding>,
361}
362
363/// Result of the `resourceRead` command.
364///
365/// The server SHOULD honor the `encoding` requested in the params. If the
366/// server cannot provide the requested encoding, it MUST fall back to either
367/// `base64` or `utf-8`.
368#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
369#[serde(rename_all = "camelCase")]
370pub struct ResourceReadResult {
371    /// Content encoded as a string
372    pub data: String,
373    /// How `data` is encoded
374    pub encoding: ContentEncoding,
375    /// Content type (e.g. `"image/png"`, `"text/plain"`)
376    #[serde(default, skip_serializing_if = "Option::is_none")]
377    pub content_type: Option<String>,
378}
379
380/// Writes content to a file on the server's filesystem.
381///
382/// Binary content (images, etc.) MUST use `base64` encoding. Text content MAY
383/// use `utf-8` encoding.
384///
385/// If the file does not exist, it is created. If the file already exists, the
386/// effect on existing bytes depends on {@link ResourceWriteParams.mode}:
387/// `truncate` (default) overwrites from the chosen offset onward, `append`
388/// preserves all existing bytes and adds `data` at a position rooted at EOF,
389/// and `insert` preserves all existing bytes and splices `data` in at an
390/// offset rooted at the start of the file.
391///
392/// Like all `resource*` methods, `resourceWrite` is symmetrical and MAY be
393/// sent in either direction.
394#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
395#[serde(rename_all = "camelCase")]
396pub struct ResourceWriteParams {
397    /// Channel URI this command targets.
398    pub channel: Uri,
399    /// Target file URI on the server filesystem
400    pub uri: Uri,
401    /// Content encoded as a string
402    pub data: String,
403    /// How `data` is encoded
404    pub encoding: ContentEncoding,
405    /// Content type (e.g. `"text/plain"`, `"image/png"`)
406    #[serde(default, skip_serializing_if = "Option::is_none")]
407    pub content_type: Option<String>,
408    /// If `true`, the server MUST fail if the file already exists instead of
409    /// overwriting it. Useful for safe creation of new files.
410    #[serde(default, skip_serializing_if = "Option::is_none")]
411    pub create_only: Option<bool>,
412    /// How `data` is placed within the target file. Defaults to `'truncate'`
413    /// (full overwrite) when omitted. See {@link ResourceWriteMode} for the
414    /// meaning of each mode and how it interprets {@link position}.
415    #[serde(default, skip_serializing_if = "Option::is_none")]
416    pub mode: Option<ResourceWriteMode>,
417    /// Byte offset interpreted according to {@link mode}. Defaults to `0`.
418    /// - `truncate`: offset from the start of the file at which to truncate
419    ///   before writing.
420    /// - `append`: bytes back from EOF at which to insert `data`.
421    /// - `insert`: offset from the start of the file at which to splice in
422    ///   `data`.
423    #[serde(default, skip_serializing_if = "Option::is_none")]
424    pub position: Option<i64>,
425    /// Optimistic-concurrency token previously returned by
426    /// {@link ResourceResolveResult.etag}. When set, the server MUST fail with
427    /// `Conflict` if the current `etag` does not match — preventing lost
428    /// updates between a `resourceResolve` and a subsequent `resourceWrite`.
429    #[serde(default, skip_serializing_if = "Option::is_none")]
430    pub if_match: Option<String>,
431}
432
433/// Result of the `resourceWrite` command.
434///
435/// An empty object on success.
436#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
437#[serde(rename_all = "camelCase")]
438pub struct ResourceWriteResult {}
439
440/// Lists directory entries at a file URI on the server's filesystem.
441///
442/// This is intended for remote folder pickers and similar UI that needs to let
443/// users navigate the server's local filesystem.
444///
445/// The server MUST return success only if the target exists and is a directory.
446/// If the target does not exist, is not a directory, or cannot be accessed, the
447/// server MUST return a JSON-RPC error.
448///
449/// Like all `resource*` methods, `resourceList` is symmetrical and MAY be
450/// sent in either direction.
451#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
452#[serde(rename_all = "camelCase")]
453pub struct ResourceListParams {
454    /// Channel URI this command targets.
455    pub channel: Uri,
456    /// Directory URI on the server filesystem
457    pub uri: Uri,
458}
459
460/// Result of the `resourceList` command.
461#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
462#[serde(rename_all = "camelCase")]
463pub struct ResourceListResult {
464    /// Entries directly contained in the requested directory
465    pub entries: Vec<DirectoryEntry>,
466}
467
468/// Directory entry returned by `resourceList`.
469#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
470#[serde(rename_all = "camelCase")]
471pub struct DirectoryEntry {
472    /// Base name of the entry
473    pub name: String,
474    /// Whether the entry is a file or directory
475    pub r#type: String,
476}
477
478/// Copies a resource from one URI to another on the server's filesystem.
479///
480/// If the destination already exists, it is overwritten unless `failIfExists`
481/// is set.
482///
483/// Like all `resource*` methods, `resourceCopy` is symmetrical and MAY be
484/// sent in either direction.
485#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
486#[serde(rename_all = "camelCase")]
487pub struct ResourceCopyParams {
488    /// Channel URI this command targets.
489    pub channel: Uri,
490    /// Source URI to copy from
491    pub source: Uri,
492    /// Destination URI to copy to
493    pub destination: Uri,
494    /// If `true`, the server MUST fail if the destination already exists instead
495    /// of overwriting it.
496    #[serde(default, skip_serializing_if = "Option::is_none")]
497    pub fail_if_exists: Option<bool>,
498}
499
500/// Result of the `resourceCopy` command.
501///
502/// An empty object on success.
503#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
504#[serde(rename_all = "camelCase")]
505pub struct ResourceCopyResult {}
506
507/// Deletes a resource at a URI on the server's filesystem.
508///
509/// Like all `resource*` methods, `resourceDelete` is symmetrical and MAY be
510/// sent in either direction.
511#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
512#[serde(rename_all = "camelCase")]
513pub struct ResourceDeleteParams {
514    /// Channel URI this command targets.
515    pub channel: Uri,
516    /// URI of the resource to delete
517    pub uri: Uri,
518    /// If `true` and the target is a directory, delete it and all its contents
519    /// recursively. If `false` (default), deleting a non-empty directory MUST fail.
520    #[serde(default, skip_serializing_if = "Option::is_none")]
521    pub recursive: Option<bool>,
522}
523
524/// Result of the `resourceDelete` command.
525///
526/// An empty object on success.
527#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
528#[serde(rename_all = "camelCase")]
529pub struct ResourceDeleteResult {}
530
531/// Moves (renames) a resource from one URI to another on the server's filesystem.
532///
533/// If the destination already exists, it is overwritten unless `failIfExists`
534/// is set.
535///
536/// Like all `resource*` methods, `resourceMove` is symmetrical and MAY be
537/// sent in either direction.
538#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
539#[serde(rename_all = "camelCase")]
540pub struct ResourceMoveParams {
541    /// Channel URI this command targets.
542    pub channel: Uri,
543    /// Source URI to move from
544    pub source: Uri,
545    /// Destination URI to move to
546    pub destination: Uri,
547    /// If `true`, the server MUST fail if the destination already exists instead
548    /// of overwriting it.
549    #[serde(default, skip_serializing_if = "Option::is_none")]
550    pub fail_if_exists: Option<bool>,
551}
552
553/// Result of the `resourceMove` command.
554///
555/// An empty object on success.
556#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
557#[serde(rename_all = "camelCase")]
558pub struct ResourceMoveResult {}
559
560/// Resolves a resource — the combination of POSIX `stat` and `realpath`.
561///
562/// `resourceResolve` returns metadata about the resource together with its
563/// canonical URI after symlink resolution. Use this in place of any
564/// `resourceExists` shim: a missing resource MUST surface as a `NotFound`
565/// JSON-RPC error rather than a success with a sentinel value. Callers that
566/// truly need a boolean check should attempt `resourceResolve` and treat
567/// `NotFound` as "does not exist".
568///
569/// Like all `resource*` methods, `resourceResolve` is symmetrical and MAY be
570/// sent in either direction.
571#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
572#[serde(rename_all = "camelCase")]
573pub struct ResourceResolveParams {
574    /// Channel URI this command targets.
575    pub channel: Uri,
576    /// URI to resolve
577    pub uri: Uri,
578    /// When `true` (default), follow symlinks and report the metadata of the
579    /// link target — and set `uri` in the result to the canonical (realpath)
580    /// URI. When `false`, stat the link itself (lstat semantics) and report
581    /// `type: 'symlink'`.
582    #[serde(default, skip_serializing_if = "Option::is_none")]
583    pub follow_symlinks: Option<bool>,
584}
585
586/// Result of the `resourceResolve` command.
587#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
588#[serde(rename_all = "camelCase")]
589pub struct ResourceResolveResult {
590    /// Canonical URI after symlink resolution. Equal to the requested URI when
591    /// `followSymlinks` is `false` or the URI does not traverse a symlink.
592    pub uri: Uri,
593    /// Resource kind.
594    pub r#type: ResourceType,
595    /// Size in bytes. Omitted for directories when the provider cannot
596    /// cheaply compute it.
597    #[serde(default, skip_serializing_if = "Option::is_none")]
598    pub size: Option<i64>,
599    /// Last-modified time in ISO 8601 format, when known.
600    #[serde(default, skip_serializing_if = "Option::is_none")]
601    pub mtime: Option<String>,
602    /// Creation time in ISO 8601 format, when known.
603    #[serde(default, skip_serializing_if = "Option::is_none")]
604    pub ctime: Option<String>,
605    /// Sniffed MIME type, when known (e.g. `"text/plain"`, `"image/png"`).
606    #[serde(default, skip_serializing_if = "Option::is_none")]
607    pub content_type: Option<String>,
608    /// Opaque per-provider version token. When present, pass it as
609    /// {@link ResourceWriteParams.ifMatch} on a subsequent `resourceWrite` to
610    /// detect concurrent modifications.
611    #[serde(default, skip_serializing_if = "Option::is_none")]
612    pub etag: Option<String>,
613}
614
615/// Creates a directory on the server's filesystem with `mkdir -p` semantics.
616///
617/// The server MUST create any missing parent directories. Creating a
618/// directory that already exists is a no-op success. If `uri` already
619/// exists but is **not** a directory, the server MUST fail with
620/// `AlreadyExists`.
621///
622/// Like all `resource*` methods, `resourceMkdir` is symmetrical and MAY be
623/// sent in either direction.
624#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
625#[serde(rename_all = "camelCase")]
626pub struct ResourceMkdirParams {
627    /// Channel URI this command targets.
628    pub channel: Uri,
629    /// Directory URI to create (parents created as needed).
630    pub uri: Uri,
631}
632
633/// Result of the `resourceMkdir` command.
634///
635/// An empty object on success.
636#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
637#[serde(rename_all = "camelCase")]
638pub struct ResourceMkdirResult {}
639
640/// Requests permission to access a resource on the receiver's filesystem.
641///
642/// `resourceRequest` is symmetrical and MAY be sent in either direction: a
643/// client asks the server to grant access to a server-side resource, or a
644/// server asks the client to grant access to a client-side resource. The
645/// receiver decides whether to allow, deny, or prompt the user for the
646/// requested access.
647///
648/// If the receiver denies access, it MUST respond with `PermissionDenied`
649/// (-32009). The error data MAY include a `ResourceRequestParams` value
650/// describing the access the caller would need to be granted for the
651/// operation to succeed; see `PermissionDeniedErrorData` in
652/// `types/errors.ts`.
653///
654/// After a successful `resourceRequest`, the caller MAY use the corresponding
655/// `resource*` commands (e.g. `resourceRead`, `resourceWrite`) to perform the
656/// operation. Receivers MAY rescind access at any time by returning
657/// `PermissionDenied` on subsequent operations.
658///
659/// Either `read`, `write`, or both SHOULD be set to `true`. A request with
660/// neither flag set is treated as `read: true` by receivers.
661#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
662#[serde(rename_all = "camelCase")]
663pub struct ResourceRequestParams {
664    /// Channel URI this command targets.
665    pub channel: Uri,
666    /// Resource URI being requested. Typically a `file:` URI on the receiver's
667    /// filesystem, but any URI scheme that the receiver mediates access to is
668    /// allowed.
669    pub uri: Uri,
670    /// Whether the caller needs read access to the resource.
671    #[serde(default, skip_serializing_if = "Option::is_none")]
672    pub read: Option<bool>,
673    /// Whether the caller needs write access to the resource.
674    #[serde(default, skip_serializing_if = "Option::is_none")]
675    pub write: Option<bool>,
676}
677
678/// Result of the `resourceRequest` command.
679///
680/// An empty object on success.
681#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
682#[serde(rename_all = "camelCase")]
683pub struct ResourceRequestResult {}
684
685/// Creates a resource watcher on the receiver's filesystem.
686///
687/// The receiver allocates an `ahp-resource-watch:/<id>` channel URI and
688/// returns it on {@link CreateResourceWatchResult.channel}. The caller then
689/// [`subscribe`](./subscriptions)s to that channel to receive
690/// `resourceWatch/changed` actions over the standard action envelope.
691///
692/// The watch lifecycle is tied to subscription: when every subscriber has
693/// unsubscribed (or the underlying connection drops), the receiver MUST
694/// release the watcher. There is no explicit dispose command — `unsubscribe`
695/// is the only handle the caller needs.
696///
697/// Like the rest of the `resource*` family, `createResourceWatch` is
698/// symmetrical and MAY be sent in either direction. Access is gated through
699/// the same permission flow as `resourceRead`/`resourceWrite`.
700#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
701#[serde(rename_all = "camelCase")]
702pub struct CreateResourceWatchParams {
703    /// Channel URI this command targets.
704    pub channel: Uri,
705    /// URI to watch.
706    pub uri: Uri,
707    /// If `true`, the receiver MUST report changes for descendants of `uri`.
708    /// If `false` (default), only changes to `uri` itself — and, when `uri`
709    /// is a directory, its direct children — are reported.
710    #[serde(default, skip_serializing_if = "Option::is_none")]
711    pub recursive: Option<bool>,
712    /// Glob patterns or paths relative to `uri` to exclude from reporting.
713    /// Wrapped in `{ items }` for forward compatibility.
714    #[serde(default, skip_serializing_if = "Option::is_none")]
715    pub excludes: Option<AnyValue>,
716    /// Glob patterns or paths relative to `uri` to restrict reporting to.
717    /// Omit to report every change under `uri` subject to `excludes`.
718    /// Wrapped in `{ items }` for forward compatibility.
719    #[serde(default, skip_serializing_if = "Option::is_none")]
720    pub includes: Option<AnyValue>,
721}
722
723/// Result of the `createResourceWatch` command.
724#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
725#[serde(rename_all = "camelCase")]
726pub struct CreateResourceWatchResult {
727    /// Receiver-assigned watch channel URI (`ahp-resource-watch:/<id>`). The
728    /// caller subscribes to this URI to start receiving change events and
729    /// unsubscribes to release the watcher.
730    pub channel: Uri,
731}
732
733/// Fetches historical turns for a session. Used for lazy loading of conversation
734/// history.
735#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
736#[serde(rename_all = "camelCase")]
737pub struct FetchTurnsParams {
738    /// Channel URI this command targets.
739    pub channel: Uri,
740    /// Turn ID to fetch before (exclusive). Omit to fetch from the most recent turn.
741    #[serde(default, skip_serializing_if = "Option::is_none")]
742    pub before: Option<String>,
743    /// Maximum number of turns to return. Server MAY impose its own upper bound.
744    #[serde(default, skip_serializing_if = "Option::is_none")]
745    pub limit: Option<i64>,
746}
747
748/// Result of the `fetchTurns` command.
749#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
750#[serde(rename_all = "camelCase")]
751pub struct FetchTurnsResult {
752    /// The requested turns, ordered oldest-first
753    pub turns: Vec<Turn>,
754    /// Whether more turns exist before the returned range
755    pub has_more: bool,
756}
757
758/// Stop receiving updates for a channel.
759#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
760#[serde(rename_all = "camelCase")]
761pub struct UnsubscribeParams {
762    /// Channel URI to unsubscribe from
763    pub channel: Uri,
764}
765
766/// Fire-and-forget action dispatch (write-ahead). The client applies actions
767/// optimistically to local state and the server echoes them back as an
768/// {@link ActionEnvelope} once accepted.
769///
770/// The client → server method is named `dispatchAction`; the server's reply
771/// arrives on the server → client `action` notification (params:
772/// {@link ActionEnvelope}).
773#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
774#[serde(rename_all = "camelCase")]
775pub struct DispatchActionParams {
776    /// Channel URI this action targets
777    pub channel: Uri,
778    /// Client sequence number
779    pub client_seq: i64,
780    /// The action to dispatch
781    pub action: StateAction,
782}
783
784/// Pushes a Bearer token for a protected resource. The `resource` field MUST
785/// match a `ProtectedResourceMetadata.resource` value declared by an agent
786/// in `AgentInfo.protectedResources`.
787///
788/// Tokens are delivered using [RFC 6750](https://datatracker.ietf.org/doc/html/rfc6750)
789/// (Bearer Token Usage) semantics. The client obtains the token from the
790/// authorization server(s) listed in the resource's metadata and pushes it
791/// to the server via this command.
792#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
793#[serde(rename_all = "camelCase")]
794pub struct AuthenticateParams {
795    /// Channel URI this command targets.
796    pub channel: Uri,
797    /// The protected resource identifier. MUST match a `resource` value from
798    /// `ProtectedResourceMetadata` declared in `AgentInfo.protectedResources`.
799    pub resource: String,
800    /// Bearer token obtained from the resource's authorization server
801    pub token: String,
802}
803
804/// Result of the `authenticate` command.
805///
806/// An empty object on success. If the token is invalid or the resource is
807/// unrecognized, the server MUST return a JSON-RPC error (e.g. `AuthRequired`
808/// `-32007` or `InvalidParams` `-32602`).
809#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
810#[serde(rename_all = "camelCase")]
811pub struct AuthenticateResult {}
812
813/// Creates a new terminal on the server.
814///
815/// After creation, the client should subscribe to the terminal URI to receive
816/// state updates. The server dispatches `root/terminalsChanged` to update the
817/// root terminal list.
818#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
819#[serde(rename_all = "camelCase")]
820pub struct CreateTerminalParams {
821    /// Channel URI this command targets.
822    pub channel: Uri,
823    /// Initial owner of the terminal
824    pub claim: TerminalClaim,
825    /// Human-readable terminal name
826    #[serde(default, skip_serializing_if = "Option::is_none")]
827    pub name: Option<String>,
828    /// Initial working directory URI
829    #[serde(default, skip_serializing_if = "Option::is_none")]
830    pub cwd: Option<Uri>,
831    /// Initial terminal width in columns
832    #[serde(default, skip_serializing_if = "Option::is_none")]
833    pub cols: Option<i64>,
834    /// Initial terminal height in rows
835    #[serde(default, skip_serializing_if = "Option::is_none")]
836    pub rows: Option<i64>,
837}
838
839/// Disposes a terminal and kills its process if still running.
840///
841/// The server dispatches `root/terminalsChanged` to remove the terminal from
842/// the root terminal list.
843#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
844#[serde(rename_all = "camelCase")]
845pub struct DisposeTerminalParams {
846    /// Channel URI this command targets.
847    pub channel: Uri,
848}
849
850/// Iteratively resolves the session configuration schema. The client sends the
851/// current partial session config and any user-filled metadata values. The server
852/// returns a property schema describing what additional metadata is needed,
853/// contextual to the current selections.
854///
855/// The client calls this command whenever the user changes a significant input
856/// (e.g. picks a working directory, toggles a property). Each response returns
857/// the full current property set (not a delta). The returned `values` contain
858/// server-resolved defaults to pass to `createSession`.
859#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
860#[serde(rename_all = "camelCase")]
861pub struct ResolveSessionConfigParams {
862    /// Channel URI this command targets.
863    pub channel: Uri,
864    /// Agent provider ID
865    #[serde(default, skip_serializing_if = "Option::is_none")]
866    pub provider: Option<String>,
867    /// Working directory for the session
868    #[serde(default, skip_serializing_if = "Option::is_none")]
869    pub working_directory: Option<Uri>,
870    /// Current user-filled configuration values
871    #[serde(default, skip_serializing_if = "Option::is_none")]
872    pub config: Option<JsonObject>,
873}
874
875/// Result of the `resolveSessionConfig` command.
876#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
877#[serde(rename_all = "camelCase")]
878pub struct ResolveSessionConfigResult {
879    /// JSON Schema describing available configuration properties given the current context
880    pub schema: SessionConfigSchema,
881    /// Current configuration values (echoed back with server-resolved defaults applied)
882    pub values: JsonObject,
883}
884
885/// Queries the server for allowed values of a dynamic session config property.
886///
887/// Used when a property in the schema returned by `resolveSessionConfig` has
888/// `enumDynamic: true`. The client sends a search query and receives matching
889/// values with display metadata.
890#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
891#[serde(rename_all = "camelCase")]
892pub struct SessionConfigCompletionsParams {
893    /// Channel URI this command targets.
894    pub channel: Uri,
895    /// Agent provider ID
896    #[serde(default, skip_serializing_if = "Option::is_none")]
897    pub provider: Option<String>,
898    /// Working directory for the session
899    #[serde(default, skip_serializing_if = "Option::is_none")]
900    pub working_directory: Option<Uri>,
901    /// Current user-filled configuration values (provides context for the query)
902    #[serde(default, skip_serializing_if = "Option::is_none")]
903    pub config: Option<JsonObject>,
904    /// Property id from the schema to query values for
905    pub property: String,
906    /// Search filter text (empty or omitted returns default/recent values)
907    #[serde(default, skip_serializing_if = "Option::is_none")]
908    pub query: Option<String>,
909}
910
911/// Result of the `sessionConfigCompletions` command.
912#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
913#[serde(rename_all = "camelCase")]
914pub struct SessionConfigCompletionsResult {
915    /// Matching value items
916    pub items: Vec<SessionConfigValueItem>,
917}
918
919/// A single value item returned by `sessionConfigCompletions`.
920#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
921#[serde(rename_all = "camelCase")]
922pub struct SessionConfigValueItem {
923    /// The value to store in config
924    pub value: String,
925    /// Human-readable display label
926    pub label: String,
927    /// Optional secondary description
928    #[serde(default, skip_serializing_if = "Option::is_none")]
929    pub description: Option<String>,
930}
931
932/// Requests completion items for a partially-typed input (e.g. a user message
933/// the user is currently composing). Used to power `@`-mention pickers,
934/// file/symbol references, and similar inline-completion experiences.
935///
936/// Servers SHOULD treat this command as best-effort and return promptly. The
937/// client SHOULD debounce calls to avoid flooding the server with requests on
938/// every keystroke.
939#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
940#[serde(rename_all = "camelCase")]
941pub struct CompletionsParams {
942    /// Channel URI this command targets.
943    pub channel: Uri,
944    /// What kind of completion is being requested.
945    pub kind: CompletionItemKind,
946    /// The complete text of the input being completed (e.g. the full user
947    /// message text typed so far).
948    pub text: String,
949    /// The character offset within `text` at which the completion is requested,
950    /// measured in UTF-16 code units. MUST satisfy `0 <= offset <= text.length`.
951    pub offset: i64,
952}
953
954/// A single completion item returned by the `completions` command.
955///
956/// When the user accepts an item, the client SHOULD:
957/// 1. Replace the range `[rangeStart, rangeEnd)` in the input with `insertText`
958///    (or insert `insertText` at the cursor when the range is omitted).
959/// 2. Associate the item's `attachment` with the resulting {@link Message}.
960#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
961#[serde(rename_all = "camelCase")]
962pub struct CompletionItem {
963    /// The text inserted into the input when this item is accepted.
964    pub insert_text: String,
965    /// If defined, the start of the range in the input's `text` that is replaced
966    /// by `insertText`. The range is the half-open interval
967    /// `[rangeStart, rangeEnd)` of character offsets, measured in UTF-16 code
968    /// units.
969    ///
970    /// When omitted, the client SHOULD insert `insertText` at the cursor.
971    ///
972    /// Note: this range refers to positions in the *current* input. The
973    /// attachment's own `rangeStart`/`rangeEnd` (when present) refer to
974    /// positions in the final {@link Message.text} after the item is
975    /// accepted.
976    #[serde(default, skip_serializing_if = "Option::is_none")]
977    pub range_start: Option<i64>,
978    /// The end of the range in the input's `text` that is replaced by
979    /// `insertText`. See {@link rangeStart}.
980    #[serde(default, skip_serializing_if = "Option::is_none")]
981    pub range_end: Option<i64>,
982    /// The attachment associated with this completion item.
983    pub attachment: MessageAttachment,
984}
985
986/// Result of the `completions` command.
987#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
988#[serde(rename_all = "camelCase")]
989pub struct CompletionsResult {
990    /// The completion items, in the order the server suggests displaying them.
991    pub items: Vec<CompletionItem>,
992}
993
994/// Invokes a server-defined {@link ChangesetOperation} against a changeset,
995/// a single file, or a line range.
996///
997/// The server validates that `operationId` exists in the changeset's
998/// current `operations` list and that the requested `target.kind` is
999/// contained in the operation's `scopes`. Invalid combinations result in a
1000/// JSON-RPC error.
1001///
1002/// State changes resulting from invocation flow back through the normal
1003/// `changeset/*` action stream on the relevant changeset URIs. Clients
1004/// SHOULD NOT synthesise local optimistic changes for invocations unless
1005/// the server explicitly opts in via a future capability.
1006#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1007#[serde(rename_all = "camelCase")]
1008pub struct InvokeChangesetOperationParams {
1009    /// Channel URI this command targets.
1010    pub channel: Uri,
1011    /// Matches {@link ChangesetOperation.id} from the changeset's `operations` list.
1012    pub operation_id: String,
1013    /// Target of the operation. Required iff the chosen scope is
1014    /// `'resource'` or `'range'`. Omit for changeset-scoped operations.
1015    #[serde(default, skip_serializing_if = "Option::is_none")]
1016    pub target: Option<ChangesetOperationTarget>,
1017}
1018
1019/// Result of the {@link InvokeChangesetOperationParams | `invokeChangesetOperation`}
1020/// command.
1021///
1022/// Success is implicit: the server returns this result when it accepted
1023/// the operation. Failure is signalled by rejecting the JSON-RPC request
1024/// with an appropriate error code, not by any field on this result. The
1025/// operation MAY still produce subsequent failure feedback through the
1026/// {@link ChangesetStatusChangedAction | `changeset/statusChanged`} stream.
1027#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
1028#[serde(rename_all = "camelCase")]
1029pub struct InvokeChangesetOperationResult {
1030    /// Optional human-readable message describing the result.
1031    #[serde(default, skip_serializing_if = "Option::is_none")]
1032    pub message: Option<StringOrMarkdown>,
1033    /// Optional follow-up: a URI to open (e.g. a PR), a content ref, etc.
1034    #[serde(default, skip_serializing_if = "Option::is_none")]
1035    pub follow_up: Option<ChangesetOperationFollowUp>,
1036}
1037
1038/// Optional follow-up surfaced by the server after an operation completes —
1039/// a {@link ContentRef} the client can fetch and display.
1040///
1041/// Set `external` to `true` to open the content in the user's preferred
1042/// external handler (e.g. browser); otherwise the client is expected to
1043/// surface it inline.
1044#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1045#[serde(rename_all = "camelCase")]
1046pub struct ChangesetOperationFollowUp {
1047    pub content: ContentRef,
1048    /// When `true`, open in an external handler rather than inline.
1049    #[serde(default, skip_serializing_if = "Option::is_none")]
1050    pub external: Option<bool>,
1051}
1052
1053// ─── ReconnectResult Union ────────────────────────────────────────────
1054
1055/// Result of the `reconnect` command.
1056#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1057#[serde(tag = "type")]
1058pub enum ReconnectResult {
1059    #[serde(rename = "replay")]
1060    Replay(ReconnectReplayResult),
1061    #[serde(rename = "snapshot")]
1062    Snapshot(ReconnectSnapshotResult),
1063}
1064
1065// ─── Changeset Operation Unions ───────────────────────────────────────
1066
1067/// Identifies the file or range a `ChangesetOperation` should act on.
1068#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1069#[serde(tag = "kind")]
1070pub enum ChangesetOperationTarget {
1071    #[serde(rename = "resource")]
1072    Resource {
1073        resource: Uri,
1074        #[serde(default, skip_serializing_if = "Option::is_none")]
1075        side: Option<String>,
1076    },
1077    #[serde(rename = "range")]
1078    Range {
1079        resource: Uri,
1080        #[serde(default, skip_serializing_if = "Option::is_none")]
1081        side: Option<String>,
1082        range: ChangesetOperationTargetRange,
1083    },
1084}
1085
1086#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1087pub struct ChangesetOperationTargetRange {
1088    pub start: i64,
1089    pub end: i64,
1090}