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