Skip to main content

hematite/
lib.rs

1pub mod agent;
2pub mod memory;
3pub mod runtime;
4pub mod telemetry;
5pub mod tools;
6pub mod ui;
7
8pub const HEMATITE_VERSION: &str = env!("CARGO_PKG_VERSION");
9const HEMATITE_GIT_COMMIT_SHORT_RAW: &str = env!("HEMATITE_GIT_COMMIT_SHORT");
10const HEMATITE_GIT_EXACT_TAG_RAW: &str = env!("HEMATITE_GIT_EXACT_TAG");
11const HEMATITE_GIT_DIRTY_RAW: &str = env!("HEMATITE_GIT_DIRTY");
12
13pub fn hematite_git_commit_short() -> Option<&'static str> {
14    (!HEMATITE_GIT_COMMIT_SHORT_RAW.is_empty()).then_some(HEMATITE_GIT_COMMIT_SHORT_RAW)
15}
16
17pub fn hematite_git_exact_tag() -> Option<&'static str> {
18    (!HEMATITE_GIT_EXACT_TAG_RAW.is_empty()).then_some(HEMATITE_GIT_EXACT_TAG_RAW)
19}
20
21pub fn hematite_git_dirty() -> bool {
22    HEMATITE_GIT_DIRTY_RAW.eq_ignore_ascii_case("true")
23}
24
25pub fn hematite_build_descriptor() -> String {
26    let release_tag = format!("v{}", HEMATITE_VERSION);
27    let exact_release = matches!(hematite_git_exact_tag(), Some(tag) if tag == release_tag);
28
29    if exact_release && !hematite_git_dirty() {
30        "release".to_string()
31    } else {
32        match (hematite_git_commit_short(), hematite_git_dirty()) {
33            (Some(commit), true) => format!("dev+{}-dirty", commit),
34            (Some(commit), false) => format!("dev+{}", commit),
35            (None, true) => "dev-dirty".to_string(),
36            (None, false) => "dev".to_string(),
37        }
38    }
39}
40
41pub fn hematite_version_display() -> String {
42    format!("v{} [{}]", HEMATITE_VERSION, hematite_build_descriptor())
43}
44
45pub fn hematite_version_report() -> String {
46    let mut lines = vec![
47        format!("Hematite v{}", HEMATITE_VERSION),
48        format!("Build: {}", hematite_build_descriptor()),
49    ];
50    if let Some(commit) = hematite_git_commit_short() {
51        lines.push(format!("Commit: {}", commit));
52    }
53    lines.push(format!(
54        "Built from a dirty worktree: {}",
55        if hematite_git_dirty() { "yes" } else { "no" }
56    ));
57    lines.push(format!(
58        "Exact release tag at build time: {}",
59        hematite_git_exact_tag().unwrap_or("none")
60    ));
61    lines.join("\n")
62}
63
64// Standard imports for library users
65pub use agent::config::HematiteConfig;
66pub use agent::conversation::ConversationManager;
67pub use agent::inference::InferenceEngine;
68
69use clap::Parser;
70
71#[derive(Parser, Debug, Clone)]
72#[command(author, version, about = "Hematite CLI - Local AI Pair Programmer", long_about = None)]
73pub struct CliCockpit {
74    #[arg(long, help = "Bypasses the high-risk modal (Danger mode)")]
75    pub yolo: bool,
76
77    #[arg(
78        long,
79        default_value_t = 3,
80        help = "Sets max parallel workers (default 3)"
81    )]
82    pub swarm_size: usize,
83
84    #[arg(
85        long,
86        help = "Forces the Vigil Brief Mode for concise, high-speed output"
87    )]
88    pub brief: bool,
89
90    #[arg(
91        long,
92        help = "Pass a custom salt to reroll the deterministic species hash"
93    )]
94    pub reroll: Option<String>,
95
96    #[arg(
97        long,
98        help = "Rusty Mode: Enables the Rusty personality system, snark, and companion features"
99    )]
100    pub rusty: bool,
101
102    #[arg(long, help = "Show Rusty stats and exit")]
103    pub stats: bool,
104
105    #[arg(
106        long,
107        help = "Skip the blocking splash screen and enter the TUI immediately"
108    )]
109    pub no_splash: bool,
110
111    #[arg(
112        long,
113        help = "Optional model ID for simple tasks (overrides auto-detect)"
114    )]
115    pub fast_model: Option<String>,
116
117    #[arg(
118        long,
119        help = "Optional model ID for complex tasks (overrides auto-detect)"
120    )]
121    pub think_model: Option<String>,
122
123    #[arg(
124        long,
125        default_value = "http://localhost:1234/v1",
126        help = "The base URL for the OpenAI-compatible API"
127    )]
128    pub url: String,
129
130    #[arg(long, hide = true)]
131    pub pdf_extract_helper: Option<String>,
132}
133
134#[cfg(test)]
135mod tests {
136    #[test]
137    fn version_report_contains_release_version() {
138        let report = crate::hematite_version_report();
139        assert!(report.contains(crate::HEMATITE_VERSION));
140        assert!(report.contains("Build:"));
141    }
142}