Skip to main content
Glama
8b-is
by 8b-is
mod.rs•7.05 kB
//! Universal Input Adapter System for Smart Tree //! //! Transform any context source into visualizable trees: //! - File systems (traditional) //! - QCP quantum contexts //! - SSE event streams //! - OpenAPI specifications //! - MEM8 consciousness streams //! - And more... use anyhow::Result; use async_trait::async_trait; use serde::{Deserialize, Serialize}; use std::path::PathBuf; pub mod filesystem; pub mod mem8; pub mod openapi; pub mod qcp; pub mod sse; /// Represents any kind of context node #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ContextNode { /// Unique identifier pub id: String, /// Display name pub name: String, /// Node type (file, api_endpoint, quantum_state, event, etc.) pub node_type: NodeType, /// Quantum properties if applicable pub quantum_state: Option<QuantumState>, /// Child nodes pub children: Vec<ContextNode>, /// Metadata specific to the input type pub metadata: serde_json::Value, /// Entanglements with other nodes pub entanglements: Vec<Entanglement>, } #[derive(Debug, Clone, Serialize, Deserialize)] pub enum NodeType { // Traditional Directory, File, // API-related ApiEndpoint, ApiSchema, WebSocketChannel, // Quantum QuantumWave, EntangledState, Superposition, // Event streams EventSource, EventType, // MEM8 MemoryWave, ConsciousnessStream, EmotionalContext, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct QuantumState { /// Wave amplitude (0.0 - 1.0) pub amplitude: f64, /// Frequency in Hz pub frequency: f64, /// Phase offset pub phase: f64, /// Collapse probability pub collapse_probability: f64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Entanglement { /// ID of entangled node pub target_id: String, /// Strength of entanglement (0.0 - 1.0) pub strength: f64, /// Type of relationship pub relationship: String, } /// Trait for all input adapters #[async_trait] pub trait InputAdapter: Send + Sync { /// Name of the adapter fn name(&self) -> &'static str; /// Supported input formats/extensions fn supported_formats(&self) -> Vec<&'static str>; /// Can this adapter handle the given input? async fn can_handle(&self, input: &InputSource) -> bool; /// Parse input into context nodes async fn parse(&self, input: InputSource) -> Result<ContextNode>; /// Get quantum wave signature if applicable fn wave_signature(&self) -> Option<String> { None } } /// Represents an input source #[derive(Debug, Clone)] pub enum InputSource { /// Local file system path Path(PathBuf), /// URL (HTTP/HTTPS/WSS) Url(String), /// Raw data with format hint Raw { data: Vec<u8>, format_hint: Option<String>, }, /// QCP endpoint with query QcpQuery { endpoint: String, query: String }, /// MEM8 consciousness stream Mem8Stream { stream_id: String, temporal_range: Option<(i64, i64)>, }, } /// Universal input processor pub struct InputProcessor { adapters: Vec<Box<dyn InputAdapter>>, } impl Default for InputProcessor { fn default() -> Self { Self::new() } } impl InputProcessor { /// Create a new input processor with all adapters pub fn new() -> Self { Self { adapters: vec![ Box::new(filesystem::FileSystemAdapter), Box::new(qcp::QcpAdapter::new()), Box::new(sse::SseAdapter), Box::new(openapi::OpenApiAdapter), Box::new(mem8::Mem8Adapter), ], } } /// Process any input source into context nodes pub async fn process(&self, input: InputSource) -> Result<ContextNode> { // Find the first adapter that can handle this input for adapter in &self.adapters { if adapter.can_handle(&input).await { eprintln!("🌊 Using {} adapter for input", adapter.name()); return adapter.parse(input).await; } } anyhow::bail!("No adapter found for input source") } /// Auto-detect input type from string pub fn detect_input_type(input: &str) -> InputSource { if input.starts_with("http://") || input.starts_with("https://") { InputSource::Url(input.to_string()) } else if input.starts_with("qcp://") { let parts: Vec<&str> = input.splitn(2, "://").collect(); InputSource::QcpQuery { endpoint: "https://qcp.q8.is".to_string(), query: parts.get(1).unwrap_or(&"").to_string(), } } else if input.starts_with("mem8://") { let stream_id = input.trim_start_matches("mem8://"); InputSource::Mem8Stream { stream_id: stream_id.to_string(), temporal_range: None, } } else { InputSource::Path(PathBuf::from(input)) } } } /// Convert context nodes to Smart Tree's FileNode format pub fn context_to_file_nodes(context: ContextNode) -> Vec<crate::FileNode> { let mut nodes = Vec::new(); convert_node(&context, &mut nodes, 0); nodes } fn convert_node(context: &ContextNode, nodes: &mut Vec<crate::FileNode>, depth: usize) { use crate::scanner::FileType; use crate::{FileCategory, FileNode, FilesystemType}; use std::time::SystemTime; let node = FileNode { path: PathBuf::from(&context.id), is_dir: !context.children.is_empty(), size: context .metadata .get("size") .and_then(|s| s.as_u64()) .unwrap_or(0), modified: SystemTime::now(), // Use metadata time if available permissions: 0o755, uid: 1000, gid: 1000, is_symlink: false, is_hidden: false, permission_denied: false, is_ignored: false, depth, file_type: match context.node_type { NodeType::Directory => FileType::Directory, NodeType::File => FileType::RegularFile, NodeType::ApiEndpoint => FileType::RegularFile, NodeType::QuantumWave => FileType::RegularFile, NodeType::EventSource => FileType::RegularFile, NodeType::MemoryWave => FileType::RegularFile, _ => FileType::RegularFile, }, category: match context.node_type { NodeType::ApiEndpoint => FileCategory::Json, NodeType::QuantumWave => FileCategory::Binary, NodeType::EventSource => FileCategory::Json, NodeType::MemoryWave => FileCategory::Binary, _ => FileCategory::Unknown, }, search_matches: None, filesystem_type: FilesystemType::Unknown, }; nodes.push(node); // Recursively convert children for child in &context.children { convert_node(child, nodes, depth + 1); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/8b-is/smart-tree'

If you have feedback or need assistance with the MCP directory API, please join our Discord server