diff options
Diffstat (limited to 'src/api/schema')
| -rw-r--r-- | src/api/schema/commands.rs | 16 | ||||
| -rw-r--r-- | src/api/schema/common.rs | 19 | ||||
| -rw-r--r-- | src/api/schema/integrations.rs | 17 | ||||
| -rw-r--r-- | src/api/schema/panes.rs | 80 | ||||
| -rw-r--r-- | src/api/schema/response.rs | 29 | ||||
| -rw-r--r-- | src/api/schema/tests.rs | 75 | ||||
| -rw-r--r-- | src/api/schema/workspaces.rs | 3 |
7 files changed, 230 insertions, 9 deletions
diff --git a/src/api/schema/commands.rs b/src/api/schema/commands.rs new file mode 100644 index 00000000..c9ccd4bc --- /dev/null +++ b/src/api/schema/commands.rs @@ -0,0 +1,16 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct CommandInvokeParams { + /// Opaque endpoint-issued command identifier from the client-shell projection. + pub command_id: String, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub workspace_id: Option<String>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub tab_id: Option<String>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub pane_id: Option<String>, + /// Client-owned selection coordinates, validated against the pane's content revision. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub selection: Option<super::PaneSelectionReadParams>, +} diff --git a/src/api/schema/common.rs b/src/api/schema/common.rs index 7313002c..15f56e6c 100644 --- a/src/api/schema/common.rs +++ b/src/api/schema/common.rs @@ -36,6 +36,17 @@ pub struct PaneTarget { } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct ProductAnnouncementDismissParams { + pub version: String, + pub id: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct ReleaseNotesDismissParams { + pub version: String, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct TabTarget { pub tab_id: String, } @@ -109,14 +120,6 @@ impl NotificationShowSound { pub fn is_none(&self) -> bool { matches!(self, Self::None) } - - pub fn to_sound(self) -> Option<crate::sound::Sound> { - match self { - Self::None => None, - Self::Done => Some(crate::sound::Sound::Done), - Self::Request => Some(crate::sound::Sound::Request), - } - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] diff --git a/src/api/schema/integrations.rs b/src/api/schema/integrations.rs index 6151dedb..0fce2913 100644 --- a/src/api/schema/integrations.rs +++ b/src/api/schema/integrations.rs @@ -1,5 +1,22 @@ use serde::{Deserialize, Serialize}; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum IntegrationState { + NotInstalled, + Current, + Outdated, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct IntegrationInfo { + pub target: IntegrationTarget, + pub label: String, + pub command: String, + pub available: bool, + pub state: IntegrationState, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct IntegrationInstallParams { pub target: IntegrationTarget, diff --git a/src/api/schema/panes.rs b/src/api/schema/panes.rs index 6435a422..517870f7 100644 --- a/src/api/schema/panes.rs +++ b/src/api/schema/panes.rs @@ -48,6 +48,17 @@ pub struct PaneInputSetParams { pub right_click: PaneRightClickTarget, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneLinkActivateParams { + pub pane_id: String, + pub viewport_row: u16, + pub col: u16, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub content_revision: Option<u64>, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub offset_from_bottom: Option<u64>, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] #[serde(rename_all = "snake_case")] pub enum PaneDirection { @@ -231,6 +242,75 @@ pub struct PaneResizeParams { pub amount: Option<f32>, } +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneScrollParams { + pub pane_id: String, + pub offset_from_bottom: u64, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneTextPoint { + pub row: u32, + pub col: u16, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneSelectionReadParams { + pub pane_id: String, + pub anchor: PaneTextPoint, + pub cursor: PaneTextPoint, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub content_revision: Option<u64>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum PaneCopyMotion { + LineEnd, + FirstNonBlank, + NextWordStart, + PreviousWordStart, + NextWordEnd, + NextBigWordStart, + PreviousBigWordStart, + NextBigWordEnd, + PreviousParagraph, + NextParagraph, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneCopyMotionParams { + pub pane_id: String, + pub cursor: PaneTextPoint, + pub motion: PaneCopyMotion, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub content_revision: Option<u64>, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum PaneCopySearchDirection { + Forward, + Backward, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneTextRange { + pub start: PaneTextPoint, + pub end: PaneTextPoint, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] +pub struct PaneCopySearchParams { + pub pane_id: String, + pub query: String, + pub direction: PaneCopySearchDirection, + pub cursor: PaneTextPoint, + pub content_revision: u64, + #[serde(default, skip_serializing_if = "Option::is_none")] + pub previous: Option<PaneTextRange>, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema, Default)] pub struct PaneListParams { #[serde(default, skip_serializing_if = "Option::is_none")] diff --git a/src/api/schema/response.rs b/src/api/schema/response.rs index da2813a6..180d6645 100644 --- a/src/api/schema/response.rs +++ b/src/api/schema/response.rs @@ -9,7 +9,7 @@ use super::integrations::{ use super::panes::{ LayoutDescription, PaneEdgesResult, PaneFocusDirectionResult, PaneInfo, PaneLayoutSnapshot, PaneMoveResult, PaneNeighborResult, PaneProcessInfo, PaneReadResult, PaneResizeResult, - PaneSwapResult, PaneZoomResult, + PaneSwapResult, PaneTextPoint, PaneTextRange, PaneZoomResult, }; use super::plugins::{ InstalledPluginInfo, PluginActionInfo, PluginCommandLogInfo, PluginInvocationContext, @@ -162,6 +162,25 @@ pub enum ResponseResult { PaneRead { read: PaneReadResult, }, + PaneSelection { + pane_id: String, + text: String, + }, + PaneCopyMotion { + pane_id: String, + cursor: PaneTextPoint, + content_revision: u64, + }, + PaneCopySearch { + pane_id: String, + content_revision: u64, + matches: Vec<PaneTextRange>, + total: u64, + #[serde(default, skip_serializing_if = "Option::is_none")] + current: Option<u32>, + #[serde(default, skip_serializing_if = "Option::is_none")] + current_global: Option<u64>, + }, PaneGraphicsFrameAck { sequence: u64, revision: u64, @@ -210,6 +229,9 @@ pub enum ResponseResult { changed: bool, reason: ClientWindowTitleReason, }, + IntegrationList { + integrations: Vec<super::integrations::IntegrationInfo>, + }, IntegrationInstall { target: IntegrationTarget, details: IntegrationInstallResult, @@ -252,6 +274,11 @@ pub enum ResponseResult { context: PluginInvocationContext, log: PluginCommandLogInfo, }, + PaneLinkActivated { + #[serde(default, skip_serializing_if = "Option::is_none")] + url: Option<String>, + handled: bool, + }, PluginLogList { logs: Vec<PluginCommandLogInfo>, }, diff --git a/src/api/schema/tests.rs b/src/api/schema/tests.rs index 663f3fc4..e4a7f2a3 100644 --- a/src/api/schema/tests.rs +++ b/src/api/schema/tests.rs @@ -50,6 +50,7 @@ fn request_uses_dot_method_names() { let request = Request { id: "req_1".into(), method: Method::WorkspaceCreate(WorkspaceCreateParams { + source_workspace_id: None, cwd: Some("/tmp".into()), focus: true, label: Some("api".into()), @@ -273,6 +274,54 @@ fn request_round_trips_for_agent_explain() { } #[test] +fn integration_list_request_and_response_round_trip() { + let request = Request { + id: "req_integrations".into(), + method: Method::IntegrationList(EmptyParams::default()), + }; + let json = serde_json::to_value(&request).unwrap(); + assert_eq!(json["method"], "integration.list"); + assert_eq!(serde_json::from_value::<Request>(json).unwrap(), request); + + let response = SuccessResponse { + id: "req_integrations".into(), + result: ResponseResult::IntegrationList { + integrations: vec![IntegrationInfo { + target: IntegrationTarget::Codex, + label: "codex".into(), + command: "codex".into(), + available: true, + state: IntegrationState::Outdated, + }], + }, + }; + let json = serde_json::to_value(&response).unwrap(); + assert_eq!(json["result"]["type"], "integration_list"); + assert_eq!(json["result"]["integrations"][0]["state"], "outdated"); + assert_eq!( + serde_json::from_value::<SuccessResponse>(json).unwrap(), + response + ); +} + +#[test] +fn command_invoke_request_round_trips_without_command_text() { + let request = Request { + id: "req_command".into(), + method: Method::CommandInvoke(CommandInvokeParams { + command_id: "cmd_0123456789abcdef0123456789abcdef".into(), + workspace_id: Some("w1".into()), + tab_id: Some("w1:t1".into()), + pane_id: Some("w1:p1".into()), + selection: None, + }), + }; + let json = serde_json::to_value(&request).unwrap(); + assert_eq!(json["method"], "command.invoke"); + assert_eq!(serde_json::from_value::<Request>(json).unwrap(), request); +} + +#[test] fn notification_show_request_parses() { let json = r#"{"id":"req_1","method":"notification.show","params":{"title":"build failed","body":"api workspace","position":"top-left","sound":"request"}}"#; let request: Request = serde_json::from_str(json).unwrap(); @@ -1264,6 +1313,32 @@ fn event_wait_parses_typed_match() { } #[test] +fn pane_link_activate_round_trips() { + let request = Request { + id: "req_pane_link".into(), + method: Method::PaneLinkActivate(PaneLinkActivateParams { + pane_id: "w1:p1".into(), + viewport_row: 3, + col: 7, + content_revision: Some(42), + offset_from_bottom: Some(5), + }), + }; + let json = serde_json::to_value(&request).unwrap(); + assert_eq!(json["method"], "pane.link.activate"); + let restored: Request = serde_json::from_value(json).unwrap(); + assert_eq!(restored, request); + + let response = ResponseResult::PaneLinkActivated { + url: Some("https://example.test".into()), + handled: false, + }; + let json = serde_json::to_string(&response).unwrap(); + let restored: ResponseResult = serde_json::from_str(&json).unwrap(); + assert_eq!(restored, response); +} + +#[test] fn plugin_action_list_and_invoke_round_trips() { let list = Request { id: "req_plugin_action_list".into(), diff --git a/src/api/schema/workspaces.rs b/src/api/schema/workspaces.rs index bfc63252..1b7132c4 100644 --- a/src/api/schema/workspaces.rs +++ b/src/api/schema/workspaces.rs @@ -6,6 +6,9 @@ use super::common::AgentStatus; #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)] pub struct WorkspaceCreateParams { + /// Workspace whose focused pane supplies the `follow` cwd policy. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub source_workspace_id: Option<String>, #[serde(default, skip_serializing_if = "Option::is_none")] pub cwd: Option<String>, #[serde(default)] |
