axor 0.1.2

Core of the Axor framework: agent-based business logic with typed operations and injection.
Documentation
# Axor

**Axor** is a zero-overhead, modular backend framework based on agents.

It helps you structure your backend logic into isolated, injectable components — called **agents** — that expose typed operations and can be invoked either directly or dynamically via RPC.

> _“Give me six hours to chop down a tree and I will spend the first four sharpening the axe.”_  
> — Abraham Lincoln

Axor is your sharpened axe: focus on business logic, not boilerplate.

✅ Clean design  
🧪 No ceremony  
🚀 Zero runtime cost when calling directly  
🌐 RPC-style invocation when needed  
🔌 Inject and share **any service**, with **no trait or macro required**

Agents are exposed to the runtime. Services, in contrast, can be injected and shared without being registered as public operations — keeping your context clean and focused.

---

## ✨ Features

- **Strongly-typed agents** with auto-injection
- 🔌 **Service/Agent DI** via `Inject<T>`
- ⚙️ **Operations** with `#[operation]`, exposed automatically
- 🧪 **Business logic is testable** directly (no runtime required)
- 🚀 **Zero overhead** in direct mode, thanks to static dispatch
- 🌐 **Optional RPC-style interface** via `Payload`

> Use `axor::prelude::*` for a complete, developer-friendly import.

---

## 📦 Installation

```toml
[dependencies]
axor = "0.1"
axor-macros = "0.1" # Required for attribute macros
````

> ⚠️ You must declare `axor-macros` in your `Cargo.toml`,
> but you don't need to import it in your source code — just use the prelude:

```rust
use axor::prelude::*;
```

---

## 🛠️ Basic usage

### 1. Define a service and an agent

```rust
use std::sync::Arc;
use axor::prelude::*;

trait Logger: Send + Sync {
    fn log(&self, message: &str);
}

struct ConsoleLogger;
impl Logger for ConsoleLogger {
    fn log(&self, message: &str) {
        println!("[LOG] {}", message);
    }
}

#[agent]
struct HelloAgent {
    logger: Inject<Arc<dyn Logger>>,
}

#[agent_impl]
impl HelloAgent {
    #[operation]
    fn hello(&self) -> &'static str {
        self.logger.resolve().log("Saying hello");
        "Hello, world!"
    }
}
```

---

### 2. Register and run

```rust
let mut context = AxorContext::new();
context.register(HelloAgent::default());
context.register_service::<Arc<dyn Logger>>(Arc::new(ConsoleLogger));
context.init();

// Direct call (zero overhead)
let agent = context.resolve::<HelloAgent>();
assert_eq!(agent.hello(), "Hello, world!");

// RPC-style used by web, cli and tauri runtimes
let payload = Payload::new("HelloAgent.hello");
let result = context.invoke(payload);
assert!(result.success);
```

---

## 📜 Manifest support

Introspect all registered agents and operations:

```rust
let manifest = context.manifest();
println!("{}", serde_json::to_string_pretty(&manifest).unwrap());
```

---

## ⚠️ Limitations

### ❌ No reflection

Rust doesn’t provide reflection. You must:

* Add `#[agent]` to your struct
* Add `#[agent_impl]` to your impl block
* Use `#[operation]` to expose methods

### 🎯 Operation constraints

Each operation may take **zero or one input**, which must:

* Be `DeserializeOwned`
* Not be a reference (e.g., use `String`, not `&str`)

Return values must be `Serialize`, but they are **optional**.

### 🔄 Runtime cost only when using `Payload`

In direct mode, everything is statically dispatched and compiled away.
RPC-style invocation uses `serde_json::Value`, which involves serialization overhead — by design.

---

## 🧭 Roadmap

* [x] Core agent system and macros
* [x] Dependency injection with `Inject<T>`
* [x] Operation exposure
* [x] Manifest generation
* [ ] Type metadata for operations
* [ ] `axor-web` (RPC over HTTP)
* [ ] `axor-cli` (invoke agents from CLI)
* [ ] `axor-tauri` (bindings for desktop apps)
* [ ] TypeScript client generator
* [ ] `axor-doc` for endpoint documentation

---

## 🔗 License

MIT © 2025 — Made with ❤️ in Rust