summaryrefslogtreecommitdiff
path: root/src/api/schema
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-07-13 03:26:03 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-07-13 03:30:13 +0300
commit5cfe5e5e730246948b0c9428ad876b6938590aad (patch)
tree53d4bbe1aff6887f63f279eed1b5e4e11e7331b7 /src/api/schema
parent7f3364a468f7dcfd8c9c84e5737fe5699f0e3a93 (diff)
feat: add configurable sidebar metadata tokens
Diffstat (limited to 'src/api/schema')
-rw-r--r--src/api/schema/agents.rs9
-rw-r--r--src/api/schema/common.rs22
-rw-r--r--src/api/schema/events.rs22
-rw-r--r--src/api/schema/panes.rs19
-rw-r--r--src/api/schema/tests.rs10
-rw-r--r--src/api/schema/workspaces.rs16
6 files changed, 82 insertions, 16 deletions
diff --git a/src/api/schema/agents.rs b/src/api/schema/agents.rs
index e5f319e0..969383c4 100644
--- a/src/api/schema/agents.rs
+++ b/src/api/schema/agents.rs
@@ -57,14 +57,19 @@ pub struct AgentInfo {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
+ pub terminal_title: Option<String>,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub terminal_title_stripped: Option<String>,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
pub display_agent: Option<String>,
pub agent_status: AgentStatus,
#[serde(default, skip_serializing_if = "super::is_false")]
pub screen_detection_skipped: bool,
- #[serde(default, skip_serializing_if = "Option::is_none")]
- pub custom_status: Option<String>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub state_labels: HashMap<String, String>,
+ #[serde(default, skip_serializing_if = "HashMap::is_empty")]
+ #[schemars(schema_with = "super::common::metadata_token_values_schema")]
+ pub tokens: HashMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_session: Option<AgentSessionInfo>,
pub workspace_id: String,
diff --git a/src/api/schema/common.rs b/src/api/schema/common.rs
index 3d8376ed..e22fa1b3 100644
--- a/src/api/schema/common.rs
+++ b/src/api/schema/common.rs
@@ -1,5 +1,27 @@
use serde::{Deserialize, Serialize};
+pub(super) fn metadata_token_patch_schema(
+ _generator: &mut schemars::SchemaGenerator,
+) -> schemars::Schema {
+ schemars::json_schema!({
+ "type": "object",
+ "maxProperties": 16,
+ "propertyNames": { "pattern": "^[A-Za-z0-9_-]{1,32}$" },
+ "additionalProperties": { "type": ["string", "null"] }
+ })
+}
+
+pub(super) fn metadata_token_values_schema(
+ _generator: &mut schemars::SchemaGenerator,
+) -> schemars::Schema {
+ schemars::json_schema!({
+ "type": "object",
+ "maxProperties": 32,
+ "propertyNames": { "pattern": "^[A-Za-z0-9_-]{1,32}$" },
+ "additionalProperties": { "type": "string" }
+ })
+}
+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema, Default)]
pub struct EmptyParams {}
diff --git a/src/api/schema/events.rs b/src/api/schema/events.rs
index 41b9907d..25ccc8ec 100644
--- a/src/api/schema/events.rs
+++ b/src/api/schema/events.rs
@@ -20,6 +20,8 @@ pub enum Subscription {
WorkspaceCreated {},
#[serde(rename = "workspace.updated")]
WorkspaceUpdated {},
+ #[serde(rename = "workspace.metadata_updated")]
+ WorkspaceMetadataUpdated {},
#[serde(rename = "workspace.renamed")]
WorkspaceRenamed {},
#[serde(rename = "workspace.moved")]
@@ -48,6 +50,8 @@ pub enum Subscription {
PaneCreated {},
#[serde(rename = "pane.closed")]
PaneClosed {},
+ #[serde(rename = "pane.updated")]
+ PaneUpdated {},
#[serde(rename = "pane.focused")]
PaneFocused {},
#[serde(rename = "pane.moved")]
@@ -188,6 +192,7 @@ pub enum EventMatch {
pub enum EventKind {
WorkspaceCreated,
WorkspaceUpdated,
+ WorkspaceMetadataUpdated,
WorkspaceClosed,
WorkspaceRenamed,
WorkspaceMoved,
@@ -202,6 +207,7 @@ pub enum EventKind {
TabFocused,
PaneCreated,
PaneClosed,
+ PaneUpdated,
PaneFocused,
PaneMoved,
PaneOutputChanged,
@@ -216,6 +222,7 @@ impl EventKind {
match self {
EventKind::WorkspaceCreated => "workspace.created",
EventKind::WorkspaceUpdated => "workspace.updated",
+ EventKind::WorkspaceMetadataUpdated => "workspace.metadata_updated",
EventKind::WorkspaceClosed => "workspace.closed",
EventKind::WorkspaceRenamed => "workspace.renamed",
EventKind::WorkspaceMoved => "workspace.moved",
@@ -230,6 +237,7 @@ impl EventKind {
EventKind::TabFocused => "tab.focused",
EventKind::PaneCreated => "pane.created",
EventKind::PaneClosed => "pane.closed",
+ EventKind::PaneUpdated => "pane.updated",
EventKind::PaneFocused => "pane.focused",
EventKind::PaneMoved => "pane.moved",
EventKind::PaneOutputChanged => "pane.output_changed",
@@ -245,6 +253,7 @@ impl EventKind {
pub const KNOWN_EVENT_KINDS: &[EventKind] = &[
EventKind::WorkspaceCreated,
EventKind::WorkspaceUpdated,
+ EventKind::WorkspaceMetadataUpdated,
EventKind::WorkspaceClosed,
EventKind::WorkspaceRenamed,
EventKind::WorkspaceMoved,
@@ -259,6 +268,7 @@ pub const KNOWN_EVENT_KINDS: &[EventKind] = &[
EventKind::TabFocused,
EventKind::PaneCreated,
EventKind::PaneClosed,
+ EventKind::PaneUpdated,
EventKind::PaneFocused,
EventKind::PaneMoved,
EventKind::PaneOutputChanged,
@@ -336,6 +346,8 @@ mod known_event_name_tests {
let names = plugin_hook_event_names();
assert!(!names.contains(&"pane.output_changed"));
assert!(!names.contains(&"layout.updated"));
+ assert!(!names.contains(&"workspace.metadata_updated"));
+ assert!(!names.contains(&"pane.updated"));
assert!(names.contains(&"pane.moved"));
}
}
@@ -385,8 +397,6 @@ pub struct PaneAgentStatusChangedEvent {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
- pub custom_status: Option<String>,
- #[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub display_agent: Option<String>,
@@ -410,6 +420,9 @@ pub enum EventData {
WorkspaceUpdated {
workspace: WorkspaceInfo,
},
+ WorkspaceMetadataUpdated {
+ workspace: WorkspaceInfo,
+ },
WorkspaceClosed {
workspace_id: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
@@ -472,6 +485,9 @@ pub enum EventData {
pane_id: String,
workspace_id: String,
},
+ PaneUpdated {
+ pane: PaneInfo,
+ },
PaneFocused {
pane_id: String,
workspace_id: String,
@@ -515,8 +531,6 @@ pub enum EventData {
title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
display_agent: Option<String>,
- #[serde(default, skip_serializing_if = "Option::is_none")]
- custom_status: Option<String>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
state_labels: HashMap<String, String>,
},
diff --git a/src/api/schema/panes.rs b/src/api/schema/panes.rs
index 42a640ef..2e37e734 100644
--- a/src/api/schema/panes.rs
+++ b/src/api/schema/panes.rs
@@ -266,8 +266,6 @@ pub struct PaneReportAgentParams {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub message: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
- pub custom_status: Option<String>,
- #[serde(default, skip_serializing_if = "Option::is_none")]
pub seq: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_session_id: Option<String>,
@@ -302,21 +300,21 @@ pub struct PaneReportMetadataParams {
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub display_agent: Option<String>,
- #[serde(default, skip_serializing_if = "Option::is_none")]
- pub custom_status: Option<String>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub state_labels: HashMap<String, String>,
+ #[serde(default, skip_serializing_if = "HashMap::is_empty")]
+ #[schemars(schema_with = "super::common::metadata_token_patch_schema")]
+ pub tokens: HashMap<String, Option<String>>,
#[serde(default)]
pub clear_title: bool,
#[serde(default)]
pub clear_display_agent: bool,
#[serde(default)]
- pub clear_custom_status: bool,
- #[serde(default)]
pub clear_state_labels: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub seq: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
+ #[schemars(range(min = 1, max = 86_400_000))]
pub ttl_ms: Option<u64>,
}
@@ -356,12 +354,17 @@ pub struct PaneInfo {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
+ pub terminal_title: Option<String>,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub terminal_title_stripped: Option<String>,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
pub display_agent: Option<String>,
pub agent_status: AgentStatus,
- #[serde(default, skip_serializing_if = "Option::is_none")]
- pub custom_status: Option<String>,
#[serde(default, skip_serializing_if = "HashMap::is_empty")]
pub state_labels: HashMap<String, String>,
+ #[serde(default, skip_serializing_if = "HashMap::is_empty")]
+ #[schemars(schema_with = "super::common::metadata_token_values_schema")]
+ pub tokens: HashMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub agent_session: Option<AgentSessionInfo>,
#[serde(default, skip_serializing_if = "Option::is_none")]
diff --git a/src/api/schema/tests.rs b/src/api/schema/tests.rs
index 5f603a18..adc7e61c 100644
--- a/src/api/schema/tests.rs
+++ b/src/api/schema/tests.rs
@@ -596,6 +596,7 @@ fn worktree_request_and_response_round_trip() {
tab_count: 1,
active_tab_id: "w_1:1".into(),
agent_status: AgentStatus::Unknown,
+ tokens: HashMap::new(),
worktree: Some(WorkspaceWorktreeInfo {
repo_key: "/repo/herdr/.git".into(),
repo_name: "herdr".into(),
@@ -624,10 +625,12 @@ fn worktree_request_and_response_round_trip() {
label: None,
agent: None,
title: None,
+ terminal_title: None,
+ terminal_title_stripped: None,
display_agent: None,
agent_status: AgentStatus::Unknown,
- custom_status: None,
state_labels: HashMap::new(),
+ tokens: HashMap::new(),
agent_session: None,
scroll: None,
revision: 0,
@@ -679,6 +682,7 @@ fn worktree_lifecycle_events_round_trip() {
tab_count: 1,
active_tab_id: "w_2:1".into(),
agent_status: AgentStatus::Unknown,
+ tokens: HashMap::new(),
worktree: Some(WorkspaceWorktreeInfo {
repo_key: "/repo/herdr/.git".into(),
repo_name: "herdr".into(),
@@ -1032,10 +1036,12 @@ fn create_response_round_trips_with_root_pane() {
label: None,
agent: None,
title: None,
+ terminal_title: None,
+ terminal_title_stripped: None,
display_agent: None,
agent_status: AgentStatus::Unknown,
- custom_status: None,
state_labels: HashMap::new(),
+ tokens: HashMap::new(),
agent_session: None,
scroll: None,
revision: 0,
diff --git a/src/api/schema/workspaces.rs b/src/api/schema/workspaces.rs
index 6934539c..a6177982 100644
--- a/src/api/schema/workspaces.rs
+++ b/src/api/schema/workspaces.rs
@@ -29,6 +29,19 @@ pub struct WorkspaceMoveParams {
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
+pub struct WorkspaceReportMetadataParams {
+ pub workspace_id: String,
+ pub source: String,
+ #[schemars(schema_with = "super::common::metadata_token_patch_schema")]
+ pub tokens: HashMap<String, Option<String>>,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ pub seq: Option<u64>,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
+ #[schemars(range(min = 1, max = 86_400_000))]
+ pub ttl_ms: Option<u64>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, schemars::JsonSchema)]
pub struct WorkspaceInfo {
pub workspace_id: String,
pub number: usize,
@@ -38,6 +51,9 @@ pub struct WorkspaceInfo {
pub tab_count: usize,
pub active_tab_id: String,
pub agent_status: AgentStatus,
+ #[serde(default, skip_serializing_if = "HashMap::is_empty")]
+ #[schemars(schema_with = "super::common::metadata_token_values_schema")]
+ pub tokens: HashMap<String, String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub worktree: Option<WorkspaceWorktreeInfo>,
}