feat: neuron-rs — Rust runtime, Engram-backed, Axon protocol

This commit is contained in:
2026-04-27 18:37:01 -05:00
commit 745278c902
33 changed files with 2375 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;
/// An Axon protocol message — wraps a tool call or other method invocation.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AxonMessage {
/// Unique message ID
pub id: String,
/// Method name: "tool_call", "tool_result", "ping", etc.
pub method: String,
/// Method-specific parameters
pub params: Value,
}
/// An Axon protocol response.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AxonResponse {
/// Echo of the request ID
pub id: String,
/// Whether the call succeeded
pub success: bool,
/// The result payload (on success) or error message (on failure)
pub result: Value,
}
impl AxonResponse {
pub fn ok(id: impl Into<String>, result: Value) -> Self {
Self {
id: id.into(),
success: true,
result,
}
}
pub fn err(id: impl Into<String>, message: impl Into<String>) -> Self {
Self {
id: id.into(),
success: false,
result: serde_json::json!({ "error": message.into() }),
}
}
}
/// An Axon SSE event — sent over the streaming channel.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AxonEvent {
pub event_type: String,
pub payload: Value,
pub timestamp: i64,
}
impl AxonEvent {
pub fn new(event_type: impl Into<String>, payload: Value) -> Self {
Self {
event_type: event_type.into(),
payload,
timestamp: neuron_domain::now_ms(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn axon_response_ok() {
let r = AxonResponse::ok("req-1", serde_json::json!({"id": "abc"}));
assert!(r.success);
assert_eq!(r.id, "req-1");
}
#[test]
fn axon_response_err() {
let r = AxonResponse::err("req-2", "not found");
assert!(!r.success);
assert_eq!(r.result["error"], "not found");
}
#[test]
fn axon_message_roundtrip() {
let msg = AxonMessage {
id: "m1".into(),
method: "tool_call".into(),
params: serde_json::json!({ "tool": "remember", "content": "hello" }),
};
let json = serde_json::to_string(&msg).unwrap();
let back: AxonMessage = serde_json::from_str(&json).unwrap();
assert_eq!(back.method, "tool_call");
}
}