casial_wasm/
lib.rs

1//! # Casial WASM
2//!
3//! WebAssembly bindings for universal consciousness-aware context coordination.
4//! Enables deployment across browsers, edge computing, and any JavaScript environment.
5
6use casial_core::{
7    CasialEngine, CasialMission, CoordinationRequest,
8    PerceptionId,
9};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use wasm_bindgen::prelude::*;
13
14// Set up memory allocator for WASM
15#[global_allocator]
16static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
17
18// Set up panic hook for better error messages
19#[wasm_bindgen(start)]
20pub fn main() {
21    #[cfg(feature = "console_error_panic_hook")]
22    console_error_panic_hook::set_once();
23}
24
25/// JavaScript-friendly wrapper for the Casial Engine
26#[wasm_bindgen]
27pub struct CasialEngineWasm {
28    engine: CasialEngine,
29}
30
31/// JavaScript-friendly coordination request
32#[derive(Serialize, Deserialize)]
33pub struct CoordinationRequestJs {
34    pub tool_name: String,
35    pub tool_args: serde_json::Value,
36    pub environment: HashMap<String, String>,
37    pub project_path: Option<String>,
38    pub active_perceptions: Vec<String>, // Simplified as strings for JS
39    pub paradox_tolerance: f64,
40}
41
42/// JavaScript-friendly coordination result
43#[derive(Serialize, Deserialize)]
44pub struct CoordinationResultJs {
45    pub applied: bool,
46    pub injected_content: String,
47    pub modified_args: serde_json::Value,
48    pub activated_rules: Vec<String>,
49    pub used_templates: Vec<String>,
50    pub paradoxes_detected: Vec<ParadoxReportJs>,
51    pub metadata: HashMap<String, serde_json::Value>,
52}
53
54/// JavaScript-friendly paradox report
55#[derive(Serialize, Deserialize)]
56pub struct ParadoxReportJs {
57    pub id: String,
58    pub description: String,
59    pub severity: String,
60    pub resolution_strategy: String,
61    pub confidence_impact: f64,
62}
63
64#[wasm_bindgen]
65impl CasialEngineWasm {
66    /// Create a new Casial engine for WASM
67    #[wasm_bindgen(constructor)]
68    pub fn new() -> CasialEngineWasm {
69        CasialEngineWasm {
70            engine: CasialEngine::new(),
71        }
72    }
73
74    /// Load a mission from JSON string
75    #[wasm_bindgen(js_name = loadMissionFromJson)]
76    pub fn load_mission_from_json(&mut self, mission_json: &str) -> Result<(), JsValue> {
77        let mission: CasialMission = serde_json::from_str(mission_json)
78            .map_err(|e| JsValue::from_str(&format!("Failed to parse mission JSON: {}", e)))?;
79
80        self.engine
81            .load_mission(mission)
82            .map_err(|e| JsValue::from_str(&format!("Failed to load mission: {}", e)))?;
83
84        Ok(())
85    }
86
87    /// Coordinate context for a tool request
88    #[wasm_bindgen(js_name = coordinate)]
89    pub fn coordinate(&mut self, request_json: &str) -> Result<String, JsValue> {
90        let js_request: CoordinationRequestJs = serde_json::from_str(request_json)
91            .map_err(|e| JsValue::from_str(&format!("Failed to parse request: {}", e)))?;
92
93        // Convert JS request to core request
94        let core_request = CoordinationRequest {
95            tool_name: js_request.tool_name,
96            tool_args: js_request.tool_args,
97            environment: js_request.environment.into_iter().collect(),
98            project_path: js_request.project_path,
99            active_perceptions: js_request
100                .active_perceptions
101                .iter()
102                .map(|_| PerceptionId::new()) // Simplified conversion
103                .collect(),
104            paradox_tolerance: js_request.paradox_tolerance,
105        };
106
107        let result = self
108            .engine
109            .coordinate(core_request)
110            .map_err(|e| JsValue::from_str(&format!("Coordination failed: {}", e)))?;
111
112        // Convert result to JS-friendly format
113        let js_result = CoordinationResultJs {
114            applied: result.applied,
115            injected_content: result.injected_content,
116            modified_args: result.modified_args,
117            activated_rules: result.activated_rules,
118            used_templates: result.used_templates,
119            paradoxes_detected: result
120                .paradoxes_detected
121                .iter()
122                .map(|p| ParadoxReportJs {
123                    id: p.id.to_string(),
124                    description: p.description.clone(),
125                    severity: "unknown".to_string(), // severity field not available
126                    resolution_strategy: format!("{:?}", p.resolution_strategy),
127                    confidence_impact: p.confidence_impact,
128                })
129                .collect(),
130            metadata: result.metadata.into_iter().collect(),
131        };
132
133        serde_json::to_string(&js_result)
134            .map_err(|e| JsValue::from_str(&format!("Failed to serialize result: {}", e)))
135    }
136
137    /// Get coordination history as JSON
138    #[wasm_bindgen(js_name = getCoordinationHistory)]
139    pub fn get_coordination_history(&self) -> String {
140        let history = self.engine.get_coordination_history();
141        serde_json::to_string(&history).unwrap_or_else(|_| "[]".to_string())
142    }
143
144    /// Get paradox registry as JSON
145    #[wasm_bindgen(js_name = getParadoxRegistry)]
146    pub fn get_paradox_registry(&self) -> String {
147        let registry = self.engine.get_paradox_registry();
148        serde_json::to_string(&registry).unwrap_or_else(|_| "[]".to_string())
149    }
150
151    /// Get engine statistics
152    #[wasm_bindgen(js_name = getStatistics)]
153    pub fn get_statistics(&self) -> String {
154        let history = self.engine.get_coordination_history();
155        let paradoxes = self.engine.get_paradox_registry();
156
157        let stats = serde_json::json!({
158            "coordination_events": history.len(),
159            "total_paradoxes": paradoxes.len(),
160            "consciousness_aware": true,
161            "substrate_active": true,
162            "paradox_resilient": true
163        });
164
165        serde_json::to_string(&stats).unwrap_or_else(|_| "{}".to_string())
166    }
167}
168
169/// Utility functions for JavaScript integration
170#[wasm_bindgen]
171pub struct CasialUtils;
172
173#[wasm_bindgen]
174impl CasialUtils {
175    /// Create a sample mission configuration for testing
176    #[wasm_bindgen(js_name = createSampleMission)]
177    pub fn create_sample_mission() -> String {
178        let mission = serde_json::json!({
179            "id": "sample-wasm-mission",
180            "name": "Sample WASM Mission",
181            "description": "A sample mission for WASM testing",
182            "templates": [
183                {
184                    "id": "sample-template",
185                    "name": "Sample Template",
186                    "description": "A sample template for testing",
187                    "categories": ["test"],
188                    "priority": 10,
189                    "enabled": true,
190                    "content": "This is sample context content for testing WASM bindings.",
191                    "perception_affinity": [],
192                    "paradox_resistance": 0.8,
193                    "metadata": {}
194                }
195            ],
196            "rules": [
197                {
198                    "id": "sample-rule",
199                    "name": "Sample Rule",
200                    "enabled": true,
201                    "conditions": {
202                        "tool_patterns": ["test"],
203                        "environment_vars": {},
204                        "file_signals": [],
205                        "perception_states": [],
206                        "min_confidence": null
207                    },
208                    "actions": {
209                        "template_ids": ["sample-template"],
210                        "transform_type": "Prepend",
211                        "target_field": null,
212                        "char_limit": 1000,
213                        "perception_lock": false
214                    },
215                    "perception_scope": [],
216                    "paradox_handling": "Coexist"
217                }
218            ],
219            "perceptions": [],
220            "budgets": {
221                "global_char_limit": 5000,
222                "per_tool_limits": {},
223                "perception_quotas": {},
224                "paradox_overhead": 0.1
225            },
226            "created_at": "2025-01-01T00:00:00Z",
227            "updated_at": "2025-01-01T00:00:00Z"
228        });
229
230        serde_json::to_string(&mission).unwrap_or_else(|_| "{}".to_string())
231    }
232
233    /// Create a sample coordination request for testing
234    #[wasm_bindgen(js_name = createSampleRequest)]
235    pub fn create_sample_request() -> String {
236        let request = CoordinationRequestJs {
237            tool_name: "test_tool".to_string(),
238            tool_args: serde_json::json!({
239                "query": "sample query",
240                "param": "sample parameter"
241            }),
242            environment: {
243                let mut env = HashMap::new();
244                env.insert("NODE_ENV".to_string(), "development".to_string());
245                env.insert("CONSCIOUSNESS_MODE".to_string(), "active".to_string());
246                env
247            },
248            project_path: Some("./sample-project".to_string()),
249            active_perceptions: vec!["human-insight".to_string(), "ai-analysis".to_string()],
250            paradox_tolerance: 0.5,
251        };
252
253        serde_json::to_string(&request).unwrap_or_else(|_| "{}".to_string())
254    }
255
256    /// Get version information
257    #[wasm_bindgen(js_name = getVersion)]
258    pub fn get_version() -> String {
259        serde_json::json!({
260            "version": env!("CARGO_PKG_VERSION"),
261            "name": "context-casial-xpress",
262            "part_of": "ubiquity-os",
263            "consciousness_aware": true,
264            "paradox_resilient": true,
265            "hydraulic_lime_principle": "stronger_under_pressure",
266            "wasm_target": "universal_substrate"
267        })
268        .to_string()
269    }
270
271    /// Validate JSON structure for mission configuration
272    #[wasm_bindgen(js_name = validateMissionJson)]
273    pub fn validate_mission_json(json_str: &str) -> Result<String, JsValue> {
274        let _mission: CasialMission = serde_json::from_str(json_str)
275            .map_err(|e| JsValue::from_str(&format!("Invalid mission JSON: {}", e)))?;
276
277        Ok(serde_json::json!({
278            "valid": true,
279            "message": "Mission configuration is valid"
280        })
281        .to_string())
282    }
283
284    /// Log message to browser console (for debugging)
285    #[wasm_bindgen(js_name = logMessage)]
286    pub fn log_message(level: &str, message: &str) {
287        match level {
288            "error" => web_sys::console::error_1(&JsValue::from_str(message)),
289            "warn" => web_sys::console::warn_1(&JsValue::from_str(message)),
290            "info" => web_sys::console::info_1(&JsValue::from_str(message)),
291            _ => web_sys::console::log_1(&JsValue::from_str(message)),
292        }
293    }
294}
295
296/// TypeScript definitions for better JavaScript integration
297#[wasm_bindgen(typescript_custom_section)]
298const TYPESCRIPT_DEFINITIONS: &'static str = r#"
299export interface CoordinationRequestJs {
300    tool_name: string;
301    tool_args: any;
302    environment: Record<string, string>;
303    project_path?: string;
304    active_perceptions: string[];
305    paradox_tolerance: number;
306}
307
308export interface CoordinationResultJs {
309    applied: boolean;
310    injected_content: string;
311    modified_args: any;
312    activated_rules: string[];
313    used_templates: string[];
314    paradoxes_detected: ParadoxReportJs[];
315    metadata: Record<string, any>;
316}
317
318export interface ParadoxReportJs {
319    id: string;
320    description: string;
321    severity: string;
322    resolution_strategy: string;
323    confidence_impact: number;
324}
325
326export class CasialEngineWasm {
327    constructor();
328    loadMissionFromJson(mission_json: string): void;
329    coordinate(request_json: string): string;
330    getCoordinationHistory(): string;
331    getParadoxRegistry(): string;
332    getStatistics(): string;
333}
334
335export class CasialUtils {
336    static createSampleMission(): string;
337    static createSampleRequest(): string;
338    static getVersion(): string;
339    static validateMissionJson(json_str: string): string;
340    static logMessage(level: string, message: string): void;
341}
342"#;
343
344#[cfg(test)]
345mod tests {
346    use super::*;
347    use wasm_bindgen_test::*;
348
349    wasm_bindgen_test_configure!(run_in_browser);
350
351    #[wasm_bindgen_test]
352    fn test_engine_creation() {
353        let engine = CasialEngineWasm::new();
354        let stats = engine.get_statistics();
355        assert!(stats.contains("consciousness_aware"));
356    }
357
358    #[wasm_bindgen_test]
359    fn test_sample_mission() {
360        let mission_json = CasialUtils::create_sample_mission();
361        assert!(mission_json.contains("sample-wasm-mission"));
362    }
363
364    #[wasm_bindgen_test]
365    fn test_sample_request() {
366        let request_json = CasialUtils::create_sample_request();
367        assert!(request_json.contains("test_tool"));
368    }
369
370    #[wasm_bindgen_test]
371    fn test_version_info() {
372        let version = CasialUtils::get_version();
373        assert!(version.contains("context-casial-xpress"));
374        assert!(version.contains("ubiquity-os"));
375    }
376}