1use casial_core::{
7 CasialEngine, CasialMission, CoordinationRequest,
8 PerceptionId,
9};
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12use wasm_bindgen::prelude::*;
13
14#[global_allocator]
16static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
17
18#[wasm_bindgen(start)]
20pub fn main() {
21 #[cfg(feature = "console_error_panic_hook")]
22 console_error_panic_hook::set_once();
23}
24
25#[wasm_bindgen]
27pub struct CasialEngineWasm {
28 engine: CasialEngine,
29}
30
31#[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>, pub paradox_tolerance: f64,
40}
41
42#[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#[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 #[wasm_bindgen(constructor)]
68 pub fn new() -> CasialEngineWasm {
69 CasialEngineWasm {
70 engine: CasialEngine::new(),
71 }
72 }
73
74 #[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 #[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 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()) .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 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(), 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 #[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 #[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(®istry).unwrap_or_else(|_| "[]".to_string())
149 }
150
151 #[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#[wasm_bindgen]
171pub struct CasialUtils;
172
173#[wasm_bindgen]
174impl CasialUtils {
175 #[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 #[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 #[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 #[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 #[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#[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}