use std::path::PathBuf;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum HostedSpoolKind {
Org,
Project,
}
impl HostedSpoolKind {
pub fn is_repo(self) -> bool {
matches!(self, Self::Project)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostedSpoolInfo {
pub spool_id: String,
pub full_path: String,
pub kind: String,
pub is_repo: bool,
pub display_name: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostedNamespaceInfo {
pub namespace_id: String,
pub kind: String,
pub slug: String,
pub parent_id: Option<String>,
pub display_name: Option<String>,
pub full_path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostedRepositoryInfo {
pub repo_id: String,
pub namespace_id: String,
pub slug: String,
pub path: PathBuf,
pub full_path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostedGrantInfo {
pub subject: String,
pub role: String,
#[serde(default)]
pub namespace_path: Option<String>,
#[serde(default)]
pub repo_path: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct HarnessIdentity {
#[serde(default)]
pub harness: Option<String>,
#[serde(default)]
pub provider: Option<String>,
#[serde(default)]
pub model: Option<String>,
#[serde(default)]
pub thinking_level: Option<String>,
#[serde(default)]
pub policy: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct UsageTotals {
#[serde(default)]
pub input_tokens: Option<u64>,
#[serde(default)]
pub output_tokens: Option<u64>,
#[serde(default)]
pub reasoning_tokens: Option<u64>,
#[serde(default)]
pub cache_creation_tokens: Option<u64>,
#[serde(default)]
pub cache_read_tokens: Option<u64>,
#[serde(default)]
pub tool_calls: Option<u32>,
#[serde(default)]
pub cost_micros_usd: Option<u64>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProgressCheckpoint {
#[serde(default)]
pub status: Option<String>,
#[serde(default)]
pub message: Option<String>,
#[serde(default)]
pub completed_steps: Option<u32>,
#[serde(default)]
pub total_steps: Option<u32>,
#[serde(default)]
pub touched_paths: Vec<String>,
pub recorded_at: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TranscriptAttachmentRef {
pub attachment_id: String,
#[serde(default)]
pub kind: Option<String>,
#[serde(default)]
pub summary: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct SessionDiffSummary {
#[serde(default)]
pub changed_file_count: u32,
#[serde(default)]
pub added_files: u32,
#[serde(default)]
pub modified_files: u32,
#[serde(default)]
pub deleted_files: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorktreeChangeBaseline {
pub path: String,
pub kind: String,
}
#[cfg(test)]
mod tests {
use super::HostedSpoolKind;
#[test]
fn hosted_spool_kinds_map_org_and_project_capabilities() {
assert!(!HostedSpoolKind::Org.is_repo());
assert!(HostedSpoolKind::Project.is_repo());
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SessionReportEnvelope {
pub version: u32,
pub heddle_session_id: String,
#[serde(default)]
pub heddle_segment_id: Option<String>,
#[serde(default)]
pub agent_session_id: Option<String>,
#[serde(default)]
pub client_instance_id: Option<String>,
#[serde(default)]
pub native_actor_key: Option<String>,
#[serde(default)]
pub native_parent_actor_key: Option<String>,
#[serde(default)]
pub native_instance_key: Option<String>,
pub repo_root: String,
#[serde(default)]
pub thread: Option<String>,
#[serde(default)]
pub thread_id: Option<String>,
#[serde(default)]
pub task: Option<String>,
#[serde(default)]
pub summary: Option<String>,
pub opened_at: String,
#[serde(default)]
pub closed_at: Option<String>,
#[serde(default)]
pub base_state_at_open: Option<String>,
#[serde(default)]
pub worktree_changes_at_open: Vec<WorktreeChangeBaseline>,
#[serde(default)]
pub head_state_at_close: Option<String>,
pub transport_mode: String,
pub transcript_mode: String,
#[serde(default)]
pub outcome: Option<String>,
#[serde(default)]
pub owns_session: bool,
pub harness: HarnessIdentity,
#[serde(default)]
pub progress: Vec<ProgressCheckpoint>,
#[serde(default)]
pub usage: UsageTotals,
#[serde(default)]
pub touched_paths: Vec<String>,
#[serde(default)]
pub changed_paths: Vec<String>,
#[serde(default)]
pub diff_summary: Option<SessionDiffSummary>,
#[serde(default)]
pub transcript_refs: Vec<TranscriptAttachmentRef>,
#[serde(default)]
pub last_progress_at: Option<String>,
#[serde(default)]
pub report_flush_state: Option<String>,
#[serde(default)]
pub attach_reason: Option<String>,
#[serde(default)]
pub attach_precedence: Vec<String>,
#[serde(default)]
pub winning_attach_rule: Option<String>,
#[serde(default)]
pub probe_source: Option<String>,
#[serde(default)]
pub probe_confidence: Option<f32>,
#[serde(default)]
pub pending_flush: bool,
#[serde(default)]
pub last_flushed_at: Option<String>,
}