use schemars::{JsonSchema, Schema, SchemaGenerator};
use serde::Serialize;
#[derive(Serialize, JsonSchema)]
pub struct DiscussionOutput {
pub id: String,
pub title: String,
pub anchor: AnchorOutput,
pub anchor_status: &'static str,
pub visibility: String,
pub thread_ref: Option<String>,
pub status: &'static str,
pub resolution: Option<ResolutionOutput>,
pub conflict_operation_ids: Vec<String>,
pub head_operation_ids: Vec<String>,
pub display_head_operation_id: String,
pub turns: Vec<TurnOutput>,
}
#[derive(Serialize, JsonSchema)]
#[serde(rename_all = "snake_case", tag = "kind")]
pub enum AnchorOutput {
Source {
state_id: Option<String>,
git_commit_oid: Option<String>,
path: String,
symbol_id: String,
start_line: Option<u32>,
end_line: Option<u32>,
},
Repository,
State {
state_id: String,
},
Change {
change_id: String,
},
Path {
state_id: String,
path: String,
},
Symbol {
state_id: String,
path: String,
symbol: String,
},
}
#[derive(Serialize, JsonSchema)]
#[serde(rename_all = "snake_case", tag = "kind")]
pub enum ResolutionOutput {
AddressedByState {
state_id: String,
},
AddressedByChange {
change_id: String,
},
Dismissed {
reason: String,
},
IntoContext {
context_id: String,
content: String,
#[schemars(schema_with = "annotation_tags_schema")]
tags: Vec<objects::object::AnnotationTag>,
},
IntoAnnotation {
annotation_kind: String,
content: String,
tags: Vec<String>,
},
Annotation {
annotation_id: String,
},
}
#[derive(Serialize, JsonSchema)]
pub struct TurnOutput {
pub operation_id: String,
pub author_name: String,
pub author_email: String,
pub agent: Option<String>,
pub occurred_at_ms: i64,
pub body: String,
pub content_hash: String,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "DiscussionWriteSchema")]
pub struct DiscussionWriteOutput {
pub output_kind: &'static str,
pub operation_id: String,
pub disposition: repo::CollaborationWriteDisposition,
pub discussion: DiscussionOutput,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "DiscussionShowSchema")]
pub struct DiscussionShowOutput {
pub output_kind: &'static str,
pub discussion: DiscussionOutput,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "DiscussionListSchema")]
pub struct DiscussionListOutput {
pub output_kind: &'static str,
pub discussions: Vec<DiscussionOutput>,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "DiscussWaitLineSchema")]
pub struct DiscussWaitLineOutput {
pub output_kind: &'static str,
pub status: &'static str,
pub event_id: i64,
pub event_type: String,
pub discussion_id: Option<String>,
pub applied: bool,
pub after_event_id: i64,
#[serde(skip_serializing_if = "Option::is_none")]
pub skip_reason: Option<String>,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "ReviewShowSchema")]
pub struct ReviewShowOutput {
pub output_kind: &'static str,
pub state_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub base: Option<String>,
pub headline: String,
pub agent_narrative: Option<String>,
pub files_changed: u32,
pub in_budget_signals: Vec<SignalView>,
pub all_signals: Vec<SignalView>,
pub discussions: Vec<DiscussionView>,
pub signing_kinds: Vec<String>,
pub signatures: Vec<SignatureView>,
}
#[derive(Serialize, JsonSchema)]
pub struct SignalView {
pub kind: String,
pub file: String,
pub symbol: String,
pub reason: String,
pub producer: String,
pub visibility: String,
}
#[derive(Serialize, JsonSchema)]
pub struct DiscussionView {
pub id: String,
pub file: String,
pub symbol: String,
pub status: String,
pub body_changed_since_open: bool,
pub anchor_ambiguous: bool,
pub orphaned: bool,
}
#[derive(Serialize, JsonSchema)]
pub struct SignatureView {
pub actor_name: String,
pub actor_email: String,
pub kind: String,
#[serde(skip_serializing_if = "str::is_empty")]
pub glyph: &'static str,
pub is_agent: bool,
pub signed_at_secs: i64,
pub scope_kind: String,
pub scope_symbols: Vec<String>,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "ReviewSignSchema")]
pub struct ReviewSignOutput {
pub output_kind: &'static str,
pub signature_id: String,
pub state_id: String,
}
#[derive(Clone, Debug, Serialize, JsonSchema)]
pub struct NextStateView {
pub state_id: String,
pub headline: String,
pub existing_signatures: u32,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "ReviewNextSchema")]
pub struct ReviewNextOutput {
pub output_kind: &'static str,
#[serde(skip_serializing_if = "Option::is_none")]
pub state_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub headline: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub existing_signatures: Option<u32>,
pub next: RequiredNullableNextState,
}
#[derive(Debug, Serialize)]
#[serde(transparent)]
pub struct RequiredNullableNextState(pub Option<NextStateView>);
impl JsonSchema for RequiredNullableNextState {
fn schema_name() -> std::borrow::Cow<'static, str> {
std::borrow::Cow::Borrowed("RequiredNullableNextState")
}
fn json_schema(generator: &mut SchemaGenerator) -> Schema {
<Option<NextStateView> as JsonSchema>::json_schema(generator)
}
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "ReviewHealthSchema")]
pub struct ReviewHealthOutput {
pub output_kind: &'static str,
pub entries: Vec<HealthEntry>,
pub window_states: usize,
}
#[derive(Serialize, JsonSchema)]
pub struct HealthEntry {
pub module_id: String,
pub fire_rate: f64,
pub warn: bool,
}
#[derive(Serialize, JsonSchema)]
#[schemars(rename = "WatchLineSchema")]
pub struct WatchLineOutput {
pub ts: String,
pub thread: Option<String>,
pub kind: String,
pub state_id: Option<String>,
pub intent: Option<String>,
pub confidence: Option<f32>,
pub actor: Option<WatchActorInfo>,
pub id: u64,
}
#[derive(Clone, Debug, Serialize, JsonSchema)]
pub struct WatchActorInfo {
pub provider: String,
pub model: String,
}
fn annotation_tags_schema(_: &mut SchemaGenerator) -> Schema {
schemars::json_schema!({
"type": "array", "maxItems": 128,
"items": {
"oneOf": [
{ "type": "object", "required": ["kind", "text"], "properties": { "kind": { "const": "text" }, "text": { "type": "string" } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "name", "target"], "properties": { "kind": { "const": "symbol" }, "name": { "type": "string" }, "target": { "type": ["object", "null"], "description": "Scoped original source reference; current target resolution is separate." } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "target"], "properties": { "kind": { "const": "source" }, "target": { "type": "object", "description": "Scoped original source reference." } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "target"], "properties": { "kind": { "const": "entity" }, "target": { "type": "object", "description": "Typed collaboration entity reference." } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "key", "value"], "properties": { "kind": { "const": "property" }, "key": { "type": "string", "pattern": "^[A-Za-z0-9_.\\/-]{1,128}$" }, "value": { "oneOf": [
{ "type": "object", "required": ["kind", "value"], "properties": { "kind": { "const": "text" }, "value": { "type": "string" } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "value"], "properties": { "kind": { "const": "boolean" }, "value": { "type": "boolean" } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "value"], "properties": { "kind": { "const": "integer" }, "value": { "type": "integer" } }, "additionalProperties": false },
{ "type": "object", "required": ["kind", "value"], "properties": { "kind": { "const": "decimal" }, "value": { "type": "object", "required": ["coefficient", "scale"], "properties": { "coefficient": { "type": "integer" }, "scale": { "type": "integer", "minimum": 0, "maximum": 9 } }, "additionalProperties": false } }, "additionalProperties": false }
] } }, "additionalProperties": false }
]
}
})
}