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}