Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,41 @@ Make sure you have installed a virtualized environment with GUI, then you can re
| Novita | [All Models](https://novita.ai/models/llm) | ✅ | model-name | novita | NOVITA_API_KEY |

## Reference
\n+## 🔧 Experimental Rust Rewrite (aios-rs)
An early experimental Rust scaffold lives in `aios-rs/` providing trait definitions and minimal placeholder implementations (context, memory, storage, tool, scheduler, llm). This is NOT feature-parity yet; it's a foundation for incremental porting and performance-focused components.

### Try It
```bash
cd aios-rs
cargo build
cargo test
```

### Example (Echo LLM + Noop Scheduler)
```rust
use aios_rs::prelude::*;

fn main() -> anyhow::Result<()> {
let llm = std::sync::Arc::new(EchoLLM);
let memory = std::sync::Arc::new(std::sync::Mutex::new(InMemoryMemoryManager::new()));
let storage = std::sync::Arc::new(FsStorageManager::new("/tmp/aios_store"));
let tool = std::sync::Arc::new(NoopToolManager);
let mut scheduler = NoopScheduler::new(llm, memory, storage, tool);
scheduler.start()?;
scheduler.stop()?;
Ok(())
}
```

### Roadmap Snapshot
- [x] Core trait scaffolding
- [ ] Async runtime + channels
- [ ] Vector store abstraction
- [ ] Python bridge (pyo3 / IPC)
- [ ] Port FIFO / RR schedulers
- [ ] Benchmarks & feature flags

Contributions welcome via focused PRs extending this scaffold. See `aios-rs/README.md` for details.
```
@article{mei2025litecua,
title={LiteCUA: Computer as MCP Server for Computer-Use Agent on AIOS},
Expand Down
16 changes: 16 additions & 0 deletions aios-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions aios-rs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "aios-rs"
version = "0.1.0"
edition = "2024"
description = "Experimental Rust rewrite scaffold of the AIOS framework"
license = "Apache-2.0"
repository = "https://github.com/agiresearch/AIOS"
readme = "README.md"

[dependencies]
anyhow = "1"
54 changes: 54 additions & 0 deletions aios-rs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# aios-rs

Experimental Rust rewrite scaffold of the AIOS framework. This is an early foundation providing core trait definitions and minimal reference implementations so that the Python system can be incrementally ported / inter-operated.

## Status
- Traits defined: context, memory, storage, tool, scheduler, llm adapter
- Minimal in-memory / filesystem / echo implementations
- No async runtime yet (Tokio not added)
- No vector DB / embedding integration yet
- No FFI bridge to Python yet

## Goals (incremental roadmap)
1. Flesh out trait contracts (streaming, structured errors, async)
2. Provide concrete async implementations (Tokio + channels)
3. Add vector store abstraction + pluggable backends
4. Introduce pyo3 / JSON-RPC bridge for hybrid operation
5. Port scheduling strategies (FIFO, RR) with test parity
6. Add feature flags: `vector`, `python-bridge`, `tokio-scheduler`
7. Performance + memory benchmarks

## Quick Start
```bash
# In repository root
cd aios-rs
cargo test
```

Add to another crate (path dependency while developing):
```toml
[dependencies]
aios-rs = { path = "../aios-rs" }
```

Example usage:
```rust
use aios_rs::prelude::*;

fn main() -> anyhow::Result<()> {
let llm = std::sync::Arc::new(EchoLLM);
let memory = std::sync::Arc::new(std::sync::Mutex::new(InMemoryMemoryManager::new()));
let storage = std::sync::Arc::new(FsStorageManager::new("/tmp/aios_store"));
let tool = std::sync::Arc::new(NoopToolManager);
let mut scheduler = NoopScheduler::new(llm, memory, storage, tool);
scheduler.start()?;
scheduler.stop()?;
Ok(())
}
```

## Contributing
This scaffold intentionally keeps scope narrow; please open an issue or discussion before expanding new subsystems. Focus areas welcome: async design, error model, bridging strategy, test parity with Python.

## License
Apache-2.0
31 changes: 31 additions & 0 deletions aios-rs/src/context.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//! Context subsystem (snapshot + recovery) trait definitions.
use std::path::PathBuf;

pub trait ContextManager: Send + Sync {
fn start(&mut self) -> anyhow::Result<()> { Ok(()) }
fn gen_snapshot(&self, pid: u64, context: &str) -> anyhow::Result<PathBuf>;
fn gen_recover(&self, pid: u64) -> anyhow::Result<Option<String>>;
fn stop(&mut self) -> anyhow::Result<()> { Ok(()) }
}

/// A minimal in-memory context manager placeholder.
pub struct InMemoryContextManager {
root: PathBuf,
}

impl InMemoryContextManager {
pub fn new(root: impl Into<PathBuf>) -> Self { Self { root: root.into() } }
}

impl ContextManager for InMemoryContextManager {
fn gen_snapshot(&self, pid: u64, context: &str) -> anyhow::Result<PathBuf> {
let file = self.root.join(format!("ctx_{pid}.txt"));
std::fs::create_dir_all(&self.root)?;
std::fs::write(&file, context)?;
Ok(file)
}
fn gen_recover(&self, pid: u64) -> anyhow::Result<Option<String>> {
let file = self.root.join(format!("ctx_{pid}.txt"));
if file.exists() { Ok(Some(std::fs::read_to_string(file)?)) } else { Ok(None) }
}
}
45 changes: 45 additions & 0 deletions aios-rs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//! aios-rs: Experimental Rust rewrite scaffold of the AIOS framework.
//!
//! This crate currently provides trait definitions and minimal placeholder
//! implementations mirroring the Python architecture (context, memory,
//! scheduler, storage, tool, llm adapter). The goal is to iteratively port
//! functionality while keeping a clear boundary for mixed-language operation.
//!
//! Roadmap (high-level):
//! 1. Define core traits (done in this scaffold)
//! 2. Implement in-memory versions + simple examples
//! 3. Provide FFI / IPC bridge (e.g., via pyo3 or JSON-RPC) to allow gradual
//! replacement of Python components
//! 4. Optimize concurrency (Tokio) and memory management
//! 5. Add feature flags for optional subsystems (vector db, scheduler variants)
//!
//! The code here is intentionally minimal; it is a foundation for further PRs.

pub mod context;
pub mod memory;
pub mod scheduler;
pub mod storage;
pub mod tool;
pub mod llm;
pub mod prelude;

// Re-export common traits for ergonomics.
pub use context::ContextManager;
pub use memory::{MemoryManager, MemoryNote, MemoryQuery, MemoryResponse};
pub use scheduler::Scheduler;
pub use storage::StorageManager;
pub use tool::ToolManager;
pub use llm::{LLMAdapter, LLMRequest, LLMResponse};

/// Version of the Rust rewrite scaffold (distinct from crate version if needed)
pub const AIOS_RS_SCAFFOLD_VERSION: &str = "0.0.1-alpha";

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn version_constant_present() {
assert_eq!(AIOS_RS_SCAFFOLD_VERSION, "0.0.1-alpha");
}
}
18 changes: 18 additions & 0 deletions aios-rs/src/llm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//! LLM adapter trait and simple echo implementation.
use anyhow::Result;

pub trait LLMAdapter: Send + Sync {
fn infer(&self, request: LLMRequest) -> Result<LLMResponse>;
}

#[derive(Debug, Clone)]
pub struct LLMRequest { pub prompt: String }
#[derive(Debug, Clone)]
pub struct LLMResponse { pub content: String }

pub struct EchoLLM;
impl LLMAdapter for EchoLLM {
fn infer(&self, request: LLMRequest) -> Result<LLMResponse> {
Ok(LLMResponse { content: format!("echo: {}", request.prompt) })
}
}
83 changes: 83 additions & 0 deletions aios-rs/src/memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! Memory subsystem mirroring Python base memory manager (simplified).
use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};

#[derive(Debug, Clone)]
pub struct MemoryNote {
pub id: String,
pub content: String,
pub keywords: Vec<String>,
pub tags: Vec<String>,
pub category: Option<String>,
pub timestamp: u64,
}

impl MemoryNote {
pub fn new(id: impl Into<String>, content: impl Into<String>) -> Self {
Self {
id: id.into(),
content: content.into(),
keywords: vec![],
tags: vec![],
category: None,
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs(),
}
}
}

#[derive(Debug, Clone)]
pub struct MemoryQuery {
pub operation: String,
pub params: HashMap<String, String>,
}

#[derive(Debug, Clone)]
pub struct MemoryResponse {
pub success: bool,
pub memory_id: Option<String>,
pub content: Option<String>,
pub error: Option<String>,
}

impl MemoryResponse {
pub fn ok_id(id: impl Into<String>) -> Self { Self { success: true, memory_id: Some(id.into()), content: None, error: None } }
pub fn ok_content(content: impl Into<String>) -> Self { Self { success: true, memory_id: None, content: Some(content.into()), error: None } }
pub fn err(e: impl Into<String>) -> Self { Self { success: false, memory_id: None, content: None, error: Some(e.into()) } }
}

pub trait MemoryManager: Send + Sync {
fn add_memory(&mut self, note: MemoryNote) -> MemoryResponse;
fn remove_memory(&mut self, id: &str) -> MemoryResponse;
fn update_memory(&mut self, note: MemoryNote) -> MemoryResponse;
fn get_memory(&self, id: &str) -> MemoryResponse;
}

pub struct InMemoryMemoryManager {
notes: HashMap<String, MemoryNote>,
}

impl InMemoryMemoryManager { pub fn new() -> Self { Self { notes: HashMap::new() } } }

impl MemoryManager for InMemoryMemoryManager {
fn add_memory(&mut self, note: MemoryNote) -> MemoryResponse {
let id = note.id.clone();
self.notes.insert(id.clone(), note);
MemoryResponse::ok_id(id)
}
fn remove_memory(&mut self, id: &str) -> MemoryResponse {
if self.notes.remove(id).is_some() { MemoryResponse::ok_id(id) } else { MemoryResponse::err("not found") }
}
fn update_memory(&mut self, note: MemoryNote) -> MemoryResponse {
let id = note.id.clone();
if self.notes.contains_key(&id) {
self.notes.insert(id.clone(), note);
MemoryResponse::ok_id(id)
} else { MemoryResponse::err("not found") }
}
fn get_memory(&self, id: &str) -> MemoryResponse {
self.notes.get(id).map(|n| MemoryResponse::ok_content(n.content.clone())).unwrap_or_else(|| MemoryResponse::err("not found"))
}
}
7 changes: 7 additions & 0 deletions aios-rs/src/prelude.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//! Convenience prelude re-exporting primary traits & structs.
pub use crate::context::{ContextManager, InMemoryContextManager};
pub use crate::memory::{MemoryManager, InMemoryMemoryManager, MemoryNote, MemoryQuery, MemoryResponse};
pub use crate::scheduler::{Scheduler, NoopScheduler};
pub use crate::storage::{StorageManager, FsStorageManager};
pub use crate::tool::{ToolManager, NoopToolManager};
pub use crate::llm::{LLMAdapter, EchoLLM, LLMRequest, LLMResponse};
30 changes: 30 additions & 0 deletions aios-rs/src/scheduler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//! Scheduler trait (simplified placeholder).
use crate::{LLMAdapter, MemoryManager, StorageManager, ToolManager};
use std::sync::Arc;

pub trait Scheduler: Send + Sync {
fn start(&mut self) -> anyhow::Result<()>;
fn stop(&mut self) -> anyhow::Result<()>;
}

pub struct NoopScheduler {
pub llm: Arc<dyn LLMAdapter>,
pub memory: Arc<std::sync::Mutex<dyn MemoryManager>>,
pub storage: Arc<dyn StorageManager>,
pub tool: Arc<dyn ToolManager>,
running: bool,
}

impl NoopScheduler {
pub fn new(
llm: Arc<dyn LLMAdapter>,
memory: Arc<std::sync::Mutex<dyn MemoryManager>>,
storage: Arc<dyn StorageManager>,
tool: Arc<dyn ToolManager>,
) -> Self { Self { llm, memory, storage, tool, running: false } }
}

impl Scheduler for NoopScheduler {
fn start(&mut self) -> anyhow::Result<()> { self.running = true; Ok(()) }
fn stop(&mut self) -> anyhow::Result<()> { self.running = false; Ok(()) }
}
23 changes: 23 additions & 0 deletions aios-rs/src/storage.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//! Storage manager trait (placeholder) analogous to Python storage subsystem.
use std::path::PathBuf;

pub trait StorageManager: Send + Sync {
fn put(&self, key: &str, data: &[u8]) -> anyhow::Result<()>;
fn get(&self, key: &str) -> anyhow::Result<Option<Vec<u8>>>;
}

pub struct FsStorageManager { root: PathBuf }
impl FsStorageManager { pub fn new(root: impl Into<PathBuf>) -> Self { Self { root: root.into() } } }

impl StorageManager for FsStorageManager {
fn put(&self, key: &str, data: &[u8]) -> anyhow::Result<()> {
let path = self.root.join(key);
if let Some(parent) = path.parent() { std::fs::create_dir_all(parent)?; }
std::fs::write(path, data)?;
Ok(())
}
fn get(&self, key: &str) -> anyhow::Result<Option<Vec<u8>>> {
let path = self.root.join(key);
if path.exists() { Ok(Some(std::fs::read(path)?)) } else { Ok(None) }
}
}
13 changes: 13 additions & 0 deletions aios-rs/src/tool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Tool subsystem placeholder.
use anyhow::Result;

pub trait ToolManager: Send + Sync {
fn invoke(&self, name: &str, input: &str) -> Result<String>;
}

pub struct NoopToolManager;
impl ToolManager for NoopToolManager {
fn invoke(&self, name: &str, input: &str) -> Result<String> {
Ok(format!("tool:{name} echo -> {input}"))
}
}
Loading