heddle-wire 0.15.0

An AI-native version control system
Documentation
// SPDX-License-Identifier: Apache-2.0
//! Local projections retained after hosted protocol mapping.

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 {
    /// Whether the spool can store repository content.
    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>,
}