descry-tool-core 0.2.0

Core traits and types for descry-tool framework
Documentation
 # Descry Tool

A modern, async-first Rust framework for building LLM-compatible tools with zero-cost abstractions and compile-time registration.

## Features

- **Single async Tool trait** - No SyncTool/AsyncTool separation
- **Arc<ToolContext>** - No borrow checker hell, works seamlessly across await points
- **Derive-first design** - One `#[tool]` macro generates everything
- **Thread-safe** - `DashMap` for concurrent extensions
- **Multi-protocol adapters** - Built-in MCP, OpenAI, Anthropic support
- **Tower Service integration** - Middleware ecosystem support (optional)
- **Auto-generated schemas** - Type-safe JSON Schema with thread-local caching

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
descry-tool-core = "0.2"
descry-tool-macros = "0.2"
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "sync"] }

# Optional: for async runtime
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread"] }

# Optional: Tower middleware support
descry-tool-core = { version = "0.2", features = ["tower"] }
tower = "0.5"
tower-http = { version = "0.6", features = ["timeout", "limit"] }

[dev-dependencies]
tokio = { version = "1", features = ["macros", "rt", "rt-multi-thread", "sync"] }

[features]
default = ["macros"]
tower = ["dep:tower"]
```

## Quick Start

### Define a Tool

```rust
use descry_tool_core::{Tool, ToolContext, ToolError};
use descry_tool_macros::tool;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::sync::Arc;

#[derive(Deserialize, JsonSchema)]
struct AddParams {
    a: i32,
    b: i32,
}

#[derive(Serialize, JsonSchema)]
struct AddOutput {
    result: i32,
}

// One macro does it all!
#[tool(
    name = "add",
    description = "Add two numbers"
)]
async fn add(_ctx: Arc<ToolContext>, params: AddParams) -> Result<AddOutput, ToolError> {
    Ok(AddOutput {
        result: params.a + params.b,
    })
}
```

### Use the Tool

```rust
use descry_tool_core::{all_tools, call_tool, tool_names, ToolContext};
use std::sync::Arc;

#[tokio::main]
async fn main() {
    // Tools are automatically registered at compile time!
    let names = tool_names();
    println!("Available tools: {:?}", names);

    // Call a tool
    let ctx = Arc::new(ToolContext::new());
    let params = serde_json::json!({"a": 5, "b": 3});
    let result = call_tool("add", params, ctx).await.unwrap();
    println!("Result: {}", result);
}
```

## Core Concepts

### Tool Trait

The unified `Tool` trait with async-first design:

```rust
pub trait Tool: Send + Sync + 'static {
    type Params: DeserializeOwned + JsonSchema + Send + Sync + 'static;
    type Output: Serialize + JsonSchema + Send + Sync + 'static;

    const NAME: &'static str;
    const DESCRIPTION: &'static str;
    const EXAMPLES: &'static [(&'static str, &'static str)] = &[];

    fn schema() -> &'static serde_json::Value;
    
    async fn call(
        ctx: Arc<ToolContext>,
        params: Self::Params
    ) -> Result<Self::Output, ToolError>;
}
```

### Compile-Time Registration

Tools are automatically registered using `inventory`:

```rust
// No manual registration needed!
// The #[tool] macro automatically generates:
//
// inventory::submit! {
//     ToolMeta {
//         name: "add",
//         description: "Add two numbers",
//         call: |ctx, params| { /* ... */ },
//         schema: || AddTool::schema(),
//         examples: || AddTool::EXAMPLES(),
//     }
// }
```

### Context System

Thread-safe context with `Arc<ToolContext>`:

```rust
use descry_tool_core::ToolContext;
use std::sync::Arc;

let ctx = Arc::new(ToolContext::new());

// Insert extensions
#[derive(Debug)]
struct Database;
ctx.insert(Database);

// Get extensions
let db: Arc<Database> = ctx.get().unwrap();
```

## Multi-Protocol Support

Generate tool specifications for different LLM platforms

```rust
use descry_tool_core::{
    adapters::{McpAdapter, OpenAiAdapter, AnthropicAdapter, ToolAdapter},
    all_tools,
};

// MCP (Model Context Protocol)
let mcp_tools: Vec<_> = all_tools()
    .map(|meta| McpAdapter::to_spec(meta))
    .collect();

// OpenAI Function Calling
let openai_tools: Vec<_> = all_tools()
    .map(|meta| OpenAiAdapter::to_spec(meta))
    .collect();

// Anthropic (Claude)
let anthropic_tools: Vec<_> = all_tools()
    .map(|meta| AnthropicAdapter::to_spec(meta))
    .collect();
```

## Tower Middleware (Optional)
Use Tower middleware for logging, timeouts, rate limiting

```rust
use descry_tool_core::tower::{tool_service, ToolRequest};
use tower::{Service, ServiceBuilder};
use tower_http::{timeout::TimeoutLayer, limit::RateLimitLayer};
use std::time::Duration;

let service = ServiceBuilder::new()
    .layer(TimeoutLayer::new(Duration::from_secs(30)))
    .layer(RateLimitLayer::new(10, Duration::from_secs(1)))
    .service(tool_service());

let response = service.call(request).await?;
```

## Examples

See `descry-tool-core/examples/`:

- `basic.rs` - Basic tool definition and usage
- `macro_example.rs` - Using the `#[tool]` macro
- `complete_example.rs` - Multiple tools with error handling
- `multi_protocol.rs` - Multi-protocol adapter usage
- `tower_basic.rs` - Tower Service integration
- `tower_middleware.rs` - Tower middleware example
- `debug_schema.rs` - Schema generation debugging

## API Reference
### Core Functions
```rust
// Get all registered tools
pub fn all_tools() -> impl Iterator<Item = &'static ToolMeta>

// Find tool by name
pub fn find_tool(name: &str) -> Option<&'static ToolMeta>

// Call a tool
pub async fn call_tool(
    name: &str,
    params: serde_json::Value,
    ctx: Arc<ToolContext>
) -> Result<serde_json::Value, ToolError>

// Get tool names
pub fn tool_names() -> Vec<&'static str>

// Check if tool exists
pub fn tool_exists(name: &str) -> bool
```

## Project Structure
```
descry-tool/
├── descry-tool-core/       # Core traits and types
│   ├── src/
│   │   ├── lib.rs          # Main exports
│   │   ├── tool.rs         # Tool trait
│   │   ├── context.rs      # Arc<ToolContext>
│   │   ├── error.rs        # ToolError
│   │   ├── registry.rs     # inventory registration
│   │   ├── adapters/       # Protocol adapters
│   │   └── tower.rs        # Tower Service (optional)
│   └── examples/           # Usage examples
├── descry-tool-macros/     # Procedural macros
│   └── src/
│       └── tool.rs         # #[tool] macro implementation
└── README.md