Skip to main content

spn_core/
lib.rs

1//! spn-core: Core types and validation for the SuperNovae ecosystem.
2//!
3//! This crate provides:
4//! - Provider definitions (20+ LLM and MCP service providers)
5//! - Model definitions (curated models for native inference)
6//! - Model storage trait (download-only, no inference)
7//! - Key format validation with detailed error messages
8//! - MCP server configuration types
9//! - Package registry types
10//!
11//! # Design Principles
12//!
13//! - **Zero dependencies**: Pure Rust, fast compilation, WASM-compatible
14//! - **Single source of truth**: All provider and model definitions in one place
15//! - **Shared types**: Used by spn-cli, spn-client, spn-keyring, spn-native, and nika
16//!
17//! # Example
18//!
19//! ```
20//! use spn_core::{
21//!     Provider, ProviderCategory, KNOWN_PROVIDERS,
22//!     find_provider, provider_to_env_var,
23//!     validate_key_format, mask_key, ValidationResult,
24//! };
25//!
26//! // Find a provider
27//! let provider = find_provider("anthropic").unwrap();
28//! assert_eq!(provider.env_var, "ANTHROPIC_API_KEY");
29//!
30//! // Validate a key format
31//! match validate_key_format("anthropic", "sk-ant-api03-xxx") {
32//!     ValidationResult::Valid => println!("Key is valid!"),
33//!     ValidationResult::InvalidPrefix { expected, .. } => {
34//!         println!("Key should start with: {}", expected);
35//!     }
36//!     _ => {}
37//! }
38//!
39//! // Mask a key for display
40//! let masked = mask_key("sk-ant-secret-key-12345");
41//! assert_eq!(masked, "sk-ant-••••••••");
42//! ```
43//!
44//! # Model Resolution
45//!
46//! ```
47//! use spn_core::{find_model, resolve_model, ResolvedModel, Quantization};
48//!
49//! // Find a curated model
50//! let model = find_model("qwen3:8b").unwrap();
51//! assert_eq!(model.model_type.name(), "Text");
52//!
53//! // Resolve model (curated or HuggingFace passthrough)
54//! match resolve_model("hf:bartowski/Qwen3-8B-GGUF") {
55//!     Some(ResolvedModel::HuggingFace { repo }) => {
56//!         println!("HF repo: {}", repo);
57//!     }
58//!     Some(ResolvedModel::Curated(model)) => {
59//!         println!("Curated: {}", model.name);
60//!     }
61//!     None => {}
62//! }
63//!
64//! // Auto-select quantization based on RAM
65//! use spn_core::auto_select_quantization;
66//! let model = find_model("qwen3:8b").unwrap();
67//! let quant = auto_select_quantization(model, 16); // 16GB RAM
68//! assert_eq!(quant, Quantization::Q8_0);
69//! ```
70
71#![forbid(unsafe_code)]
72#![warn(missing_docs)]
73#![warn(clippy::all)]
74
75mod backend;
76mod backup;
77mod mcp;
78mod model;
79mod providers;
80mod registry;
81mod storage;
82mod validation;
83
84// Re-export everything at crate root for ergonomic imports
85pub use providers::{
86    find_provider, provider_to_env_var, providers_by_category, Provider, ProviderCategory,
87    KNOWN_PROVIDERS,
88};
89
90pub use validation::{mask_key, validate_key_format, ValidationResult};
91
92pub use mcp::{McpConfig, McpServer, McpServerType, McpSource};
93
94pub use registry::{PackageManifest, PackageRef, PackageType, Source};
95
96pub use backend::{
97    BackendError, ChatMessage, ChatOptions, ChatResponse, ChatRole, EmbeddingResponse, GpuInfo,
98    LoadConfig, ModelInfo, PullProgress, Quantization, RunningModel,
99};
100
101pub use model::{
102    auto_select_quantization, detect_available_ram_gb, find_model, models_by_type, resolve_model,
103    KnownModel, ModelArchitecture, ModelType, ResolvedModel, KNOWN_MODELS,
104};
105
106pub use storage::{
107    default_model_dir, DownloadRequest, DownloadResult, ModelStorage, ProgressCallback,
108};
109
110pub use backup::{
111    BackupContents, BackupError, BackupInfo, BackupManifest, ComponentVersions, NikaContents,
112    NovaNetContents, RestoreInfo, SpnContents,
113};