Skip to main content

qualia_client_core/
qapp_registry.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5pub const QAPP_PACKAGE_MANIFEST: &str = "qapp.json";
6pub const QAPPS_DIR: &str = "Qapps";
7
8#[derive(Serialize, Deserialize, Clone, Debug)]
9pub enum QappTarget {
10    LocalDevDirectory(PathBuf),
11    LocalProxyPort(u16),
12    IsolatedVault(String),
13}
14
15#[derive(Serialize, Deserialize, Clone, Debug, Default)]
16pub struct QappLaunchRequirement {
17    pub capability: String,
18    #[serde(default)]
19    pub required: bool,
20}
21
22#[derive(Serialize, Deserialize, Clone, Debug, Default)]
23pub struct QappWasmConfig {
24    #[serde(default, skip_serializing_if = "String::is_empty")]
25    pub engine_package: String,
26    #[serde(default, skip_serializing_if = "Vec::is_empty")]
27    pub expected_exports: Vec<String>,
28}
29
30#[derive(Serialize, Deserialize, Clone, Debug, Default)]
31pub struct QappDaemonConfig {
32    #[serde(default, skip_serializing_if = "String::is_empty")]
33    pub health_path: String,
34    #[serde(default, skip_serializing_if = "String::is_empty")]
35    pub query_path: String,
36    #[serde(default, skip_serializing_if = "String::is_empty")]
37    pub websocket_path: String,
38    #[serde(default)]
39    pub requires_token: bool,
40}
41
42#[derive(Serialize, Deserialize, Clone, Debug, Default)]
43pub struct QappChatIntegrationConfig {
44    #[serde(default, skip_serializing_if = "String::is_empty")]
45    pub intent: String,
46    #[serde(default, skip_serializing_if = "String::is_empty")]
47    pub payload_version: String,
48    #[serde(default)]
49    pub supports_launch_from_chat: bool,
50    #[serde(default)]
51    pub supports_return_to_chat: bool,
52}
53
54#[derive(Serialize, Deserialize, Clone, Debug, Default)]
55pub struct QappRepresentationContract {
56    #[serde(default, skip_serializing_if = "Vec::is_empty")]
57    pub accepts: Vec<String>,
58}
59
60/// Configuration for 1.58-bit ternary quantized PINN models
61#[derive(Serialize, Deserialize, Clone, Debug, Default)]
62pub struct QappPinnModelConfig {
63    #[serde(default, skip_serializing_if = "String::is_empty")]
64    pub model_name: String,
65    #[serde(default, skip_serializing_if = "String::is_empty")]
66    pub model_path: String,
67    #[serde(default, skip_serializing_if = "String::is_empty")]
68    pub model_type: String,
69    /// Quantization precision in bits (e.g., "1.58")
70    #[serde(default, skip_serializing_if = "String::is_empty")]
71    pub quantization_bits: String,
72    /// Compression ratio achieved through ternary quantization
73    #[serde(default)]
74    pub compression_ratio: f32,
75    /// SMX format version for model serialization
76    #[serde(default, skip_serializing_if = "String::is_empty")]
77    pub smx_version: String,
78    /// Physics domain for the PINN model
79    #[serde(default, skip_serializing_if = "String::is_empty")]
80    pub physics_domain: String,
81    /// Input dimensions for the model
82    #[serde(default)]
83    pub input_dim: usize,
84    /// Output dimensions for the model
85    #[serde(default)]
86    pub output_dim: usize,
87    /// Whether the model uses ternary quantization
88    #[serde(default)]
89    pub uses_ternary_quantization: bool,
90    /// Memory requirements in MB
91    #[serde(default)]
92    pub memory_requirement_mb: u32,
93    /// VRAM requirements in MB
94    #[serde(default)]
95    pub vram_requirement_mb: Option<u32>,
96    /// Supported operations for this model
97    #[serde(default, skip_serializing_if = "Vec::is_empty")]
98    pub supported_operations: Vec<String>,
99    /// Model metadata including training information
100    #[serde(default, skip_serializing_if = "Option::is_none")]
101    pub training_metadata: Option<QappPinnTrainingMetadata>,
102    /// Performance characteristics
103    #[serde(default, skip_serializing_if = "Option::is_none")]
104    pub performance_metrics: Option<QappPinnPerformanceMetrics>,
105}
106
107/// Training metadata for PINN models
108#[derive(Serialize, Deserialize, Clone, Debug, Default)]
109pub struct QappPinnTrainingMetadata {
110    #[serde(default)]
111    pub epochs: u32,
112    #[serde(default)]
113    pub final_loss: f64,
114    #[serde(default)]
115    pub convergence_rate: f64,
116    #[serde(default)]
117    pub validation_accuracy: f64,
118    #[serde(default, skip_serializing_if = "String::is_empty")]
119    pub training_dataset: String,
120    #[serde(default, skip_serializing_if = "String::is_empty")]
121    pub training_date: String,
122}
123
124/// Performance metrics for PINN models
125#[derive(Serialize, Deserialize, Clone, Debug, Default)]
126pub struct QappPinnPerformanceMetrics {
127    /// Inference speedup from ternary quantization
128    #[serde(default)]
129    pub inference_speedup: f32,
130    /// Memory savings percentage
131    #[serde(default)]
132    pub memory_savings: f32,
133    /// Quantization error rate
134    #[serde(default)]
135    pub quantization_error: f64,
136    /// Sparsity ratio (percentage of zero weights)
137    #[serde(default)]
138    pub sparsity_ratio: f32,
139    /// Average inference time in milliseconds
140    #[serde(default)]
141    pub avg_inference_time_ms: f32,
142    /// Throughput in operations per second
143    #[serde(default)]
144    pub throughput_ops_per_sec: f64,
145}
146
147#[derive(Serialize, Deserialize, Clone, Debug, Default)]
148pub struct QappHostExtension {
149    #[serde(default, skip_serializing_if = "String::is_empty")]
150    pub app_id: String,
151    #[serde(default, skip_serializing_if = "String::is_empty")]
152    pub display_name: String,
153    #[serde(default, skip_serializing_if = "String::is_empty")]
154    pub category: String,
155    #[serde(default, skip_serializing_if = "Vec::is_empty")]
156    pub launch_modes: Vec<String>,
157    #[serde(default, skip_serializing_if = "String::is_empty")]
158    pub preferred_launch_mode: String,
159    #[serde(default)]
160    pub supports_offline: bool,
161    #[serde(default, skip_serializing_if = "Vec::is_empty")]
162    pub requires: Vec<QappLaunchRequirement>,
163    #[serde(default, skip_serializing_if = "Vec::is_empty")]
164    pub required_ontologies: Vec<String>,
165    #[serde(default, skip_serializing_if = "Vec::is_empty")]
166    pub optional_remote_endpoints: Vec<String>,
167    #[serde(default, skip_serializing_if = "String::is_empty")]
168    pub max_sensitivity_clearance: String,
169    #[serde(default, skip_serializing_if = "Vec::is_empty")]
170    pub required_models: Vec<String>,
171    #[serde(default, skip_serializing_if = "HashMap::is_empty")]
172    pub entrypoints: HashMap<String, String>,
173    #[serde(default, skip_serializing_if = "Option::is_none")]
174    pub wasm: Option<QappWasmConfig>,
175    #[serde(default, skip_serializing_if = "Option::is_none")]
176    pub local_daemon: Option<QappDaemonConfig>,
177    #[serde(default, skip_serializing_if = "Option::is_none")]
178    pub chat_integration: Option<QappChatIntegrationConfig>,
179    #[serde(default, skip_serializing_if = "Option::is_none")]
180    pub representation_contract: Option<QappRepresentationContract>,
181    #[serde(default, skip_serializing_if = "Option::is_none")]
182    pub pinn_model: Option<QappPinnModelConfig>,
183    #[serde(default, skip_serializing_if = "Vec::is_empty")]
184    pub ui_surfaces: Vec<String>,
185    #[serde(default, skip_serializing_if = "Vec::is_empty")]
186    pub notes: Vec<String>,
187    /// Named pages/views this QApp exposes. Empty = single-page (entrypoints.web).
188    #[serde(default, skip_serializing_if = "Vec::is_empty")]
189    pub pages: Vec<QappPage>,
190    /// Export targets: "embedded" | "wasm-mobile" | "tauri-desktop"
191    #[serde(default, skip_serializing_if = "Vec::is_empty")]
192    pub export_targets: Vec<String>,
193    /// did:git identity for this QApp repo (enables Gitmark validation + qualia:// sharing)
194    #[serde(default, skip_serializing_if = "Option::is_none")]
195    pub did_git: Option<String>,
196}
197
198/// A single named view within a multi-page QApp.
199#[derive(Serialize, Deserialize, Clone, Debug, Default)]
200pub struct QappPage {
201    pub name: String,
202    pub path: String,
203    #[serde(default, skip_serializing_if = "String::is_empty")]
204    pub title: String,
205    #[serde(default, skip_serializing_if = "String::is_empty")]
206    pub icon: String,
207}
208
209/// Developer-authored on-disk package manifest (`qapp.json`).
210#[derive(Serialize, Deserialize, Clone, Debug)]
211pub struct QappPackageManifest {
212    pub name: String,
213    pub version: String,
214    pub required_shapes: Vec<String>,
215    #[serde(default, skip_serializing_if = "Option::is_none")]
216    pub dev_port: Option<u16>,
217    #[serde(default, skip_serializing_if = "Option::is_none")]
218    pub x_qualia: Option<QappHostExtension>,
219}
220
221#[derive(Serialize, Deserialize, Clone, Debug)]
222pub struct RegisteredQapp {
223    pub did: String,
224    pub manifest: QappPackageManifest,
225    pub target: QappTarget,
226}
227
228#[derive(Serialize, Deserialize, Clone, Default, Debug)]
229pub struct QappRegistryState {
230    pub installed_qapps: HashMap<String, RegisteredQapp>,
231}
232
233impl QappRegistryState {
234    pub fn new() -> Self {
235        Self {
236            installed_qapps: HashMap::new(),
237        }
238    }
239}