fix cross-repo path deps; remove el compiler from neuron-lang/
- neuron-runtime, neuron-store, neuron-migrate: fix path deps (products/engram/ → foundation/engram/engrams/, products/el/ → foundation/el/engrams/) - neuron-rs workspace: fix axon-events/axon-protocol paths (../../../platform/ → ../../platform/, paths were off by one level) - neuron-lang/compiler/ removed (el self-hosting compiler now lives in foundation/el/el-compiler/)
This commit is contained in:
@@ -2,18 +2,20 @@
|
||||
name = "neuron-protocol"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "Thin re-export shim — delegates to the canonical axon-protocol and axon-events platform crates."
|
||||
|
||||
[dependencies]
|
||||
# Canonical platform crates — all real types live here
|
||||
axon-protocol = { workspace = true }
|
||||
axon-events = { workspace = true }
|
||||
|
||||
# Retained for any neuron-rs–specific protocol extensions
|
||||
neuron-domain = { path = "../neuron-domain" }
|
||||
neuron-store = { path = "../neuron-store" }
|
||||
axon-events = { path = "../axon-events" }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
axum = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
|
||||
@@ -1,266 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// AxonMethod
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/// Typed method discriminant for Axon protocol messages.
|
||||
///
|
||||
/// Replaces the raw `method: String` field — callers that need a string
|
||||
/// representation can use [`AxonMethod::as_str`] or the `Display` impl.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AxonMethod {
|
||||
/// Invoke a named tool.
|
||||
ToolCall,
|
||||
/// Return value from a tool invocation.
|
||||
ToolResult,
|
||||
/// Deliver a typed Axon event envelope.
|
||||
Event,
|
||||
/// Liveness check.
|
||||
Ping,
|
||||
/// Liveness reply.
|
||||
Pong,
|
||||
/// Subscribe to an event stream.
|
||||
Subscribe,
|
||||
/// Cancel a subscription.
|
||||
Unsubscribe,
|
||||
}
|
||||
|
||||
impl AxonMethod {
|
||||
/// Return the canonical lowercase string for this method.
|
||||
pub fn as_str(self) -> &'static str {
|
||||
match self {
|
||||
Self::ToolCall => "tool_call",
|
||||
Self::ToolResult => "tool_result",
|
||||
Self::Event => "event",
|
||||
Self::Ping => "ping",
|
||||
Self::Pong => "pong",
|
||||
Self::Subscribe => "subscribe",
|
||||
Self::Unsubscribe => "unsubscribe",
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a string into an `AxonMethod`, returning `None` on mismatch.
|
||||
pub fn from_str(s: &str) -> Option<Self> {
|
||||
match s {
|
||||
"tool_call" => Some(Self::ToolCall),
|
||||
"tool_result" => Some(Self::ToolResult),
|
||||
"event" => Some(Self::Event),
|
||||
"ping" => Some(Self::Ping),
|
||||
"pong" => Some(Self::Pong),
|
||||
"subscribe" => Some(Self::Subscribe),
|
||||
"unsubscribe" => Some(Self::Unsubscribe),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AxonMethod {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// AxonMessage
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/// An Axon protocol message — wraps a tool call, event delivery, or
|
||||
/// other method invocation.
|
||||
///
|
||||
/// The `method` field is now typed as [`AxonMethod`]. For backward
|
||||
/// compatibility the raw string representation is available via
|
||||
/// [`AxonMessage::method_str`].
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AxonMessage {
|
||||
/// Unique message ID.
|
||||
pub id: String,
|
||||
/// Typed method discriminant.
|
||||
pub method: AxonMethod,
|
||||
/// Method-specific parameters.
|
||||
pub params: Value,
|
||||
}
|
||||
|
||||
impl AxonMessage {
|
||||
/// Return the canonical string representation of the method (e.g.
|
||||
/// `"tool_call"`, `"ping"`). Useful when serialising to a transport
|
||||
/// that expects a raw string rather than a tagged enum.
|
||||
pub fn method_str(&self) -> &'static str {
|
||||
self.method.as_str()
|
||||
}
|
||||
|
||||
/// Construct a ping message.
|
||||
pub fn ping(id: impl Into<String>) -> Self {
|
||||
Self {
|
||||
id: id.into(),
|
||||
method: AxonMethod::Ping,
|
||||
params: Value::Object(Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// AxonResponse
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/// 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() }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// AxonEvent (legacy SSE event — kept for backward compat)
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
/// 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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Tests
|
||||
// ------------------------------------------------------------------
|
||||
|
||||
#[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_with_method_enum() {
|
||||
let msg = AxonMessage {
|
||||
id: "m1".into(),
|
||||
method: AxonMethod::ToolCall,
|
||||
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, AxonMethod::ToolCall);
|
||||
assert_eq!(back.method_str(), "tool_call");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn axon_method_as_str_all_variants() {
|
||||
let cases = [
|
||||
(AxonMethod::ToolCall, "tool_call"),
|
||||
(AxonMethod::ToolResult, "tool_result"),
|
||||
(AxonMethod::Event, "event"),
|
||||
(AxonMethod::Ping, "ping"),
|
||||
(AxonMethod::Pong, "pong"),
|
||||
(AxonMethod::Subscribe, "subscribe"),
|
||||
(AxonMethod::Unsubscribe, "unsubscribe"),
|
||||
];
|
||||
for (method, expected) in cases {
|
||||
assert_eq!(method.as_str(), expected);
|
||||
assert_eq!(method.to_string(), expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn axon_method_from_str_roundtrip() {
|
||||
let variants = [
|
||||
AxonMethod::ToolCall,
|
||||
AxonMethod::ToolResult,
|
||||
AxonMethod::Event,
|
||||
AxonMethod::Ping,
|
||||
AxonMethod::Pong,
|
||||
AxonMethod::Subscribe,
|
||||
AxonMethod::Unsubscribe,
|
||||
];
|
||||
for v in variants {
|
||||
let s = v.as_str();
|
||||
assert_eq!(AxonMethod::from_str(s), Some(v));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn axon_method_from_str_unknown() {
|
||||
assert_eq!(AxonMethod::from_str("mystery"), None);
|
||||
assert_eq!(AxonMethod::from_str(""), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn axon_method_serde_roundtrip() {
|
||||
let m = AxonMethod::Subscribe;
|
||||
let json = serde_json::to_string(&m).unwrap();
|
||||
let back: AxonMethod = serde_json::from_str(&json).unwrap();
|
||||
assert_eq!(back, AxonMethod::Subscribe);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn axon_message_ping_helper() {
|
||||
let msg = AxonMessage::ping("p-1");
|
||||
assert_eq!(msg.method, AxonMethod::Ping);
|
||||
assert_eq!(msg.id, "p-1");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn axon_method_all_variants_have_unique_str() {
|
||||
use std::collections::HashSet;
|
||||
let strs: HashSet<&str> = [
|
||||
AxonMethod::ToolCall,
|
||||
AxonMethod::ToolResult,
|
||||
AxonMethod::Event,
|
||||
AxonMethod::Ping,
|
||||
AxonMethod::Pong,
|
||||
AxonMethod::Subscribe,
|
||||
AxonMethod::Unsubscribe,
|
||||
]
|
||||
.iter()
|
||||
.map(|m| m.as_str())
|
||||
.collect();
|
||||
assert_eq!(strs.len(), 7);
|
||||
}
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
use crate::axon::{AxonMessage, AxonMethod, AxonResponse};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
type ToolFn = Arc<dyn Fn(Value) -> Value + Send + Sync>;
|
||||
|
||||
/// Routes Axon method names to handler functions.
|
||||
///
|
||||
/// Each handler takes the `params` field of an AxonMessage and returns
|
||||
/// a JSON Value to be wrapped in an AxonResponse.
|
||||
pub struct AxonHandler {
|
||||
tools: HashMap<String, ToolFn>,
|
||||
}
|
||||
|
||||
impl AxonHandler {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
tools: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a tool handler by name.
|
||||
pub fn register<F>(&mut self, name: impl Into<String>, f: F)
|
||||
where
|
||||
F: Fn(Value) -> Value + Send + Sync + 'static,
|
||||
{
|
||||
self.tools.insert(name.into(), Arc::new(f));
|
||||
}
|
||||
|
||||
/// Dispatch an AxonMessage to the appropriate handler.
|
||||
pub fn dispatch(&self, msg: AxonMessage) -> AxonResponse {
|
||||
match msg.method {
|
||||
AxonMethod::ToolCall => {
|
||||
let tool_name = msg
|
||||
.params
|
||||
.get("tool")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("");
|
||||
let tool_params = msg
|
||||
.params
|
||||
.get("params")
|
||||
.cloned()
|
||||
.unwrap_or(Value::Object(Default::default()));
|
||||
|
||||
if let Some(f) = self.tools.get(tool_name) {
|
||||
let result = f(tool_params);
|
||||
AxonResponse::ok(msg.id, result)
|
||||
} else {
|
||||
AxonResponse::err(msg.id, format!("unknown tool: {}", tool_name))
|
||||
}
|
||||
}
|
||||
AxonMethod::Ping => {
|
||||
AxonResponse::ok(msg.id, serde_json::json!({ "pong": true }))
|
||||
}
|
||||
other => {
|
||||
AxonResponse::err(msg.id, format!("unknown method: {}", other.as_str()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// List all registered tool names.
|
||||
pub fn tool_names(&self) -> Vec<String> {
|
||||
let mut names: Vec<_> = self.tools.keys().cloned().collect();
|
||||
names.sort();
|
||||
names
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AxonHandler {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dispatch_ping() {
|
||||
let handler = AxonHandler::new();
|
||||
let msg = AxonMessage {
|
||||
id: "1".into(),
|
||||
method: AxonMethod::Ping,
|
||||
params: serde_json::json!({}),
|
||||
};
|
||||
let resp = handler.dispatch(msg);
|
||||
assert!(resp.success);
|
||||
assert_eq!(resp.result["pong"], true);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_tool_call() {
|
||||
let mut handler = AxonHandler::new();
|
||||
handler.register("remember", |params| {
|
||||
serde_json::json!({ "stored": params.get("content").cloned().unwrap_or_default() })
|
||||
});
|
||||
|
||||
let msg = AxonMessage {
|
||||
id: "2".into(),
|
||||
method: AxonMethod::ToolCall,
|
||||
params: serde_json::json!({ "tool": "remember", "params": { "content": "hello" } }),
|
||||
};
|
||||
let resp = handler.dispatch(msg);
|
||||
assert!(resp.success);
|
||||
assert_eq!(resp.result["stored"], "hello");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_unknown_tool() {
|
||||
let handler = AxonHandler::new();
|
||||
let msg = AxonMessage {
|
||||
id: "3".into(),
|
||||
method: AxonMethod::ToolCall,
|
||||
params: serde_json::json!({ "tool": "nonexistent", "params": {} }),
|
||||
};
|
||||
let resp = handler.dispatch(msg);
|
||||
assert!(!resp.success);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dispatch_unhandled_method() {
|
||||
let handler = AxonHandler::new();
|
||||
let msg = AxonMessage {
|
||||
id: "4".into(),
|
||||
method: AxonMethod::Subscribe,
|
||||
params: serde_json::json!({}),
|
||||
};
|
||||
let resp = handler.dispatch(msg);
|
||||
assert!(!resp.success);
|
||||
assert!(resp.result["error"].as_str().unwrap().contains("unknown method"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_names_sorted() {
|
||||
let mut handler = AxonHandler::new();
|
||||
handler.register("remember", |_| Value::Null);
|
||||
handler.register("recall", |_| Value::Null);
|
||||
handler.register("plan_work", |_| Value::Null);
|
||||
let names = handler.tool_names();
|
||||
let mut expected = vec!["plan_work", "recall", "remember"];
|
||||
expected.sort();
|
||||
assert_eq!(names, expected);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,20 @@
|
||||
pub mod axon;
|
||||
pub mod handler;
|
||||
pub mod sse;
|
||||
pub mod tools;
|
||||
//! `neuron-protocol` — re-export shim for the canonical Axon platform crates.
|
||||
//!
|
||||
//! All types now live in:
|
||||
//! - `axon-protocol` (`platform/protocols/axon/crates/axon-protocol`)
|
||||
//! - `axon-events` (`platform/protocols/axon/crates/axon-events`)
|
||||
//!
|
||||
//! This crate re-exports everything so existing neuron-rs crates that import
|
||||
//! `neuron_protocol::*` continue to compile without changes.
|
||||
|
||||
pub use axon::{AxonEvent, AxonMessage, AxonMethod, AxonResponse};
|
||||
pub use handler::AxonHandler;
|
||||
pub use tools::ProjectType;
|
||||
// Re-export wire-protocol types
|
||||
pub use axon_protocol::handler::AxonHandler;
|
||||
pub use axon_protocol::message::{AxonEvent, AxonMessage, AxonMethod, AxonResponse};
|
||||
pub use axon_protocol::sse::SseChannel;
|
||||
pub use axon_protocol::tools::{self, ProjectType, ALL_TOOLS};
|
||||
|
||||
// Re-export event schema
|
||||
pub use axon_events::{
|
||||
AxonEnvelope, AxonError, AxonRouter, AxonSubscription, EventId, ProjectContext, Severity,
|
||||
Timestamp,
|
||||
};
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
use crate::axon::AxonEvent;
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
/// SSE channel — broadcasts AxonEvents to all connected SSE clients.
|
||||
#[derive(Clone)]
|
||||
pub struct SseChannel {
|
||||
sender: broadcast::Sender<String>,
|
||||
}
|
||||
|
||||
impl SseChannel {
|
||||
pub fn new(capacity: usize) -> Self {
|
||||
let (sender, _) = broadcast::channel(capacity);
|
||||
Self { sender }
|
||||
}
|
||||
|
||||
/// Send an event to all subscribers.
|
||||
pub fn send(&self, event: &AxonEvent) -> Result<(), String> {
|
||||
let json = serde_json::to_string(event).map_err(|e| e.to_string())?;
|
||||
// Ignore errors when no receivers are connected
|
||||
let _ = self.sender.send(json);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Subscribe to the SSE channel.
|
||||
pub fn subscribe(&self) -> broadcast::Receiver<String> {
|
||||
self.sender.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn sse_channel_broadcast() {
|
||||
let ch = SseChannel::new(16);
|
||||
let mut rx = ch.subscribe();
|
||||
|
||||
let event = AxonEvent::new("test", serde_json::json!({ "msg": "hello" }));
|
||||
ch.send(&event).unwrap();
|
||||
|
||||
let received = rx.recv().await.unwrap();
|
||||
let parsed: serde_json::Value = serde_json::from_str(&received).unwrap();
|
||||
assert_eq!(parsed["event_type"], "test");
|
||||
assert_eq!(parsed["payload"]["msg"], "hello");
|
||||
}
|
||||
}
|
||||
@@ -1,219 +0,0 @@
|
||||
/// Tool name constants — must match the existing MCP tool names so services
|
||||
/// can switch over without configuration changes.
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Memory tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const REMEMBER: &str = "remember";
|
||||
pub const RECALL: &str = "recall";
|
||||
pub const SEARCH_ENTITIES: &str = "search_entities";
|
||||
pub const INSPECT_MEMORIES: &str = "inspect_memories";
|
||||
pub const EVOLVE_MEMORY: &str = "evolve_memory";
|
||||
pub const FORGET: &str = "forget";
|
||||
pub const PIN_NODE: &str = "pin_node";
|
||||
pub const INSPECT_GRAPH: &str = "inspect_graph";
|
||||
pub const SEARCH_GRAPH: &str = "search_graph";
|
||||
pub const TRAVERSE_GRAPH: &str = "traverse_graph";
|
||||
pub const REBUILD_GRAPH: &str = "rebuild_graph";
|
||||
pub const LINK_ENTITIES: &str = "link_entities";
|
||||
pub const LINK_CAUSAL: &str = "link_causal";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Knowledge tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const CAPTURE_KNOWLEDGE: &str = "capture_knowledge";
|
||||
pub const SEARCH_KNOWLEDGE: &str = "search_knowledge";
|
||||
pub const RETRIEVE_KNOWLEDGE: &str = "retrieve_knowledge";
|
||||
pub const BROWSE_KNOWLEDGE: &str = "browse_knowledge";
|
||||
pub const EVOLVE_KNOWLEDGE: &str = "evolve_knowledge";
|
||||
pub const REMOVE_KNOWLEDGE: &str = "remove_knowledge";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Backlog / work tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const PLAN_WORK: &str = "plan_work";
|
||||
pub const REVIEW_BACKLOG: &str = "review_backlog";
|
||||
pub const TRACK_WORK: &str = "track_work";
|
||||
pub const BEGIN_WORK: &str = "begin_work";
|
||||
pub const PROGRESS_WORK: &str = "progress_work";
|
||||
pub const CHECK_WORK: &str = "check_work";
|
||||
pub const LIST_WORK: &str = "list_work";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Session / context tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const BEGIN_SESSION: &str = "begin_session";
|
||||
pub const COMPILE_CTX: &str = "compile_ctx";
|
||||
pub const CONSOLIDATE: &str = "consolidate";
|
||||
pub const PROJECT_CONTEXT: &str = "project_context";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Artifact tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const DRAFT_ARTIFACT: &str = "draft_artifact";
|
||||
pub const FIND_ARTIFACTS: &str = "find_artifacts";
|
||||
pub const RETRIEVE_ARTIFACT: &str = "retrieve_artifact";
|
||||
pub const REVISE_ARTIFACT: &str = "revise_artifact";
|
||||
pub const MANAGE_ARTIFACT: &str = "manage_artifact";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Process tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const BROWSE_PROCESSES: &str = "browse_processes";
|
||||
pub const DEFINE_PROCESS: &str = "define_process";
|
||||
pub const RETRIEVE_PROCESS: &str = "retrieve_process";
|
||||
pub const EXECUTE_PROCESS: &str = "execute_process";
|
||||
pub const EXPORT_PROCESS: &str = "export_process";
|
||||
pub const DELETE_PROCESS: &str = "delete_process";
|
||||
pub const LIST_PROCESSES: &str = "list_processes";
|
||||
pub const CATALOG_ROUTES: &str = "catalog_routes";
|
||||
pub const REGISTER_ROUTE: &str = "register_route";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Event / ISE tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const LOG_INTERNAL_STATE_EVENT: &str = "log_internal_state_event";
|
||||
pub const LIST_INTERNAL_STATE_EVENTS: &str = "list_internal_state_events";
|
||||
pub const GET_INTERNAL_STATE_EVENT: &str = "get_internal_state_event";
|
||||
pub const CHECK_EVENTS: &str = "check_events";
|
||||
pub const ACKNOWLEDGE_EVENT: &str = "acknowledge_event";
|
||||
pub const INSPECT_EVENT: &str = "inspect_event";
|
||||
pub const PROCESS_EVENTS: &str = "process_events";
|
||||
pub const SEND_NOTIFICATION: &str = "send_notification";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// Config tools
|
||||
// ------------------------------------------------------------------
|
||||
pub const INSPECT_CONFIG: &str = "inspect_config";
|
||||
pub const TUNE_CONFIG: &str = "tune_config";
|
||||
pub const GET_INSTRUCTIONS: &str = "get_instructions";
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// All tools in canonical alphabetical order
|
||||
// ------------------------------------------------------------------
|
||||
pub const ALL_TOOLS: &[&str] = &[
|
||||
ACKNOWLEDGE_EVENT,
|
||||
BEGIN_SESSION,
|
||||
BEGIN_WORK,
|
||||
BROWSE_KNOWLEDGE,
|
||||
BROWSE_PROCESSES,
|
||||
CAPTURE_KNOWLEDGE,
|
||||
CATALOG_ROUTES,
|
||||
CHECK_EVENTS,
|
||||
CHECK_WORK,
|
||||
COMPILE_CTX,
|
||||
CONSOLIDATE,
|
||||
DEFINE_PROCESS,
|
||||
DELETE_PROCESS,
|
||||
DRAFT_ARTIFACT,
|
||||
EVOLVE_KNOWLEDGE,
|
||||
EVOLVE_MEMORY,
|
||||
EXECUTE_PROCESS,
|
||||
EXPORT_PROCESS,
|
||||
FIND_ARTIFACTS,
|
||||
FORGET,
|
||||
GET_INSTRUCTIONS,
|
||||
GET_INTERNAL_STATE_EVENT,
|
||||
INSPECT_CONFIG,
|
||||
INSPECT_EVENT,
|
||||
INSPECT_GRAPH,
|
||||
INSPECT_MEMORIES,
|
||||
LINK_CAUSAL,
|
||||
LINK_ENTITIES,
|
||||
LIST_INTERNAL_STATE_EVENTS,
|
||||
LIST_PROCESSES,
|
||||
LIST_WORK,
|
||||
LOG_INTERNAL_STATE_EVENT,
|
||||
MANAGE_ARTIFACT,
|
||||
PIN_NODE,
|
||||
PLAN_WORK,
|
||||
PROCESS_EVENTS,
|
||||
PROGRESS_WORK,
|
||||
PROJECT_CONTEXT,
|
||||
REBUILD_GRAPH,
|
||||
RECALL,
|
||||
REGISTER_ROUTE,
|
||||
REMEMBER,
|
||||
REMOVE_KNOWLEDGE,
|
||||
RETRIEVE_ARTIFACT,
|
||||
RETRIEVE_KNOWLEDGE,
|
||||
RETRIEVE_PROCESS,
|
||||
REVIEW_BACKLOG,
|
||||
REVISE_ARTIFACT,
|
||||
SEARCH_ENTITIES,
|
||||
SEARCH_GRAPH,
|
||||
SEARCH_KNOWLEDGE,
|
||||
SEND_NOTIFICATION,
|
||||
TRACK_WORK,
|
||||
TRAVERSE_GRAPH,
|
||||
TUNE_CONFIG,
|
||||
];
|
||||
|
||||
// Re-export ProjectType from axon-events for convenient protocol-level access.
|
||||
pub use axon_events::ProjectType;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn all_tools_count() {
|
||||
// Ensure the list has grown to cover the full Neuron MCP surface.
|
||||
assert!(ALL_TOOLS.len() >= 50, "expected 50+ tools, got {}", ALL_TOOLS.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tool_names_are_non_empty() {
|
||||
for name in ALL_TOOLS {
|
||||
assert!(!name.is_empty(), "tool name must not be empty");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_tools_are_unique() {
|
||||
use std::collections::HashSet;
|
||||
let set: HashSet<&&str> = ALL_TOOLS.iter().collect();
|
||||
assert_eq!(set.len(), ALL_TOOLS.len(), "duplicate tool name detected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn all_tools_are_sorted() {
|
||||
let mut sorted = ALL_TOOLS.to_vec();
|
||||
sorted.sort_unstable();
|
||||
assert_eq!(ALL_TOOLS, sorted.as_slice(), "ALL_TOOLS must be in alphabetical order");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn original_14_tools_still_present() {
|
||||
let original = [
|
||||
REMEMBER,
|
||||
RECALL,
|
||||
SEARCH_ENTITIES,
|
||||
CAPTURE_KNOWLEDGE,
|
||||
SEARCH_KNOWLEDGE,
|
||||
RETRIEVE_KNOWLEDGE,
|
||||
PLAN_WORK,
|
||||
REVIEW_BACKLOG,
|
||||
TRACK_WORK,
|
||||
BEGIN_WORK,
|
||||
PROGRESS_WORK,
|
||||
CHECK_WORK,
|
||||
LOG_INTERNAL_STATE_EVENT,
|
||||
LIST_INTERNAL_STATE_EVENTS,
|
||||
];
|
||||
for name in original {
|
||||
assert!(
|
||||
ALL_TOOLS.contains(&name),
|
||||
"original tool '{}' missing from ALL_TOOLS",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn project_type_importable_from_tools() {
|
||||
// Ensure the re-export compiles and is usable.
|
||||
let _ = ProjectType::NeuronRs;
|
||||
let _ = ProjectType::EngramLang;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user