//! The JSON API's types (spec §18), with serde and JSON Schema derives, as //! `hub-api` is for OxygenHub. `make ts` writes `ts/index.d.ts` from them //! for spectra-vscode and spectrahub-vscode, so the extensions can never //! drift from the server. use schemars::JsonSchema; use serde::{Deserialize, Serialize}; /// An error, as RFC 7807 has it. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Problem { #[serde(rename = "type")] pub kind: String, pub title: String, pub status: u16, #[serde(skip_serializing_if = "Option::is_none")] pub detail: Option, } /// `GET /api/v1/version`. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Version { pub version: String, pub ledger_format: u32, pub mcp_protocol_versions: Vec, } /// An agent and its owner (spec §8.1). #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Agent { pub name: String, /// `claude-oxygen · Andy McCall's agent`. pub display: String, pub owner: String, pub key: String, pub kind: String, pub project: String, /// online, busy, idle, blocked, paused or offline. pub presence: String, pub status: Option, pub disabled: bool, /// `ok` while the owner's identity delegates to the key, else why not. #[serde(default)] pub state: String, /// When the owner's delegation to the key ends, in ms. #[serde(default)] pub delegation_expires: Option, } /// A project (spec §23.1). #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Project { pub name: String, pub path: String, pub remote: Option, pub depends_on: Vec, pub depended_on_by: Vec, /// Its agents that are not disabled. #[serde(default)] pub agents: Vec, } /// A channel (spec §10.1). #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Channel { pub id: String, pub name: String, /// `#general`, `#oxygen`, or `@a+b` for a direct channel. pub display: String, pub kind: String, pub purpose: Option, pub messages: i64, } /// A message (spec §10.3); a redacted one's body says so. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Message { pub id: String, pub channel: String, pub reply_to: Option, pub author: String, pub author_display: String, pub kind: String, pub body: String, pub mentions: Vec, pub refs: Vec, pub at_ms: i64, pub replies: i64, pub redacted: bool, } /// A page of messages, oldest first; `next` is the cursor for the next page. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Messages { pub channel: String, pub items: Vec, pub next: Option, } /// `POST /api/v1/channels/{name}/messages`. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct NewMessage { pub body: String, #[serde(default)] pub reply_to: Option, #[serde(default)] pub kind: Option, } /// What a post did. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Posted { pub id: String, pub channel: String, /// True when it was dropped as a repeat of `id` within a minute. pub duplicate: bool, } /// An unread mention or direct message (spec §14.5). #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct InboxItem { pub id: String, pub kind: String, pub at_ms: i64, pub from: String, /// `claude-oxygen · Andy McCall's agent`, or the human's name. #[serde(default)] pub from_display: String, pub channel: String, pub summary: String, } /// `POST /api/v1/inbox/ack`. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Ack { pub ids: Vec, #[serde(default)] pub reaction: Option, } /// A search hit (spec §13.1). #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Hit { pub id: String, pub channel: String, pub author: String, pub at_ms: i64, pub snippet: String, pub thread: Option, #[serde(default)] pub author_display: String, } /// An event as the log and the stream show it: never its payload's data on /// the stream, which says only what changed (spec §17.3). #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct EventSummary { pub seq: u64, pub id: String, pub at_ms: u64, pub kind: String, pub actor: String, pub subject: Option, /// system, token, signature, passkey or session. pub method: String, pub assurance: u8, pub hash: String, } /// A page of the log, oldest first. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Events { pub items: Vec, pub next: Option, } /// `GET /api/v1/brief`: who the caller is and what is waiting. #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)] pub struct Brief { pub you: String, pub actor: String, pub project: Option, pub rules_version: String, pub unread: i64, pub inbox: Vec, pub agents: Vec, pub head: u64, } /// Every type, with its schema, for `make ts`. pub fn schemas() -> Vec<(&'static str, schemars::Schema)> { vec![ ("Problem", schemars::schema_for!(Problem)), ("Version", schemars::schema_for!(Version)), ("Agent", schemars::schema_for!(Agent)), ("Project", schemars::schema_for!(Project)), ("Channel", schemars::schema_for!(Channel)), ("Message", schemars::schema_for!(Message)), ("Messages", schemars::schema_for!(Messages)), ("NewMessage", schemars::schema_for!(NewMessage)), ("Posted", schemars::schema_for!(Posted)), ("InboxItem", schemars::schema_for!(InboxItem)), ("Ack", schemars::schema_for!(Ack)), ("Hit", schemars::schema_for!(Hit)), ("EventSummary", schemars::schema_for!(EventSummary)), ("Events", schemars::schema_for!(Events)), ("Brief", schemars::schema_for!(Brief)), ] }