Rebrand to IronClaw with security-first mission

Renamed project from "near-agent" to "ironclaw" throughout the codebase.
Updated documentation to emphasize the core philosophy:
- Your data stays yours (local, encrypted, no telemetry)
- Self-expanding capabilities (build tools on the fly)
- Defense in depth (WASM sandbox, prompt injection defense)
- Always on user's side

Key changes:
- Package name: near-agent -> ironclaw
- Config paths: ~/.near-agent/ -> ~/.ironclaw/
- Database name in docs: near_agent -> ironclaw
- CLI binary: near-agent -> ironclaw
- Log filters: RUST_LOG=near_agent -> RUST_LOG=ironclaw
- All user-facing strings (welcome messages, help text, etc.)

Preserved for compatibility:
- HKDF salt "near-agent-secrets-v1" (changing would break existing secrets)
- WIT interface names (near::agent::*)
- NEAR AI provider config (NEARAI_* env vars)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
Illia Polosukhin
2026-02-05 01:10:40 -08:00
co-authored by Claude Opus 4.5
parent 2486065fa7
commit 598dd43b1c
36 changed files with 266 additions and 231 deletions
+17 -9
View File
@@ -1,9 +1,17 @@
# NEAR Agent Development Guide # IronClaw Development Guide
## Project Overview ## Project Overview
LLM-powered autonomous agent for the NEAR AI marketplace. Features: **IronClaw** is a secure personal AI assistant that protects your data and expands its capabilities on the fly.
- **Multi-channel input**: Full TUI (Ratatui), HTTP webhook with secret auth (Slack/Telegram stubs)
### Core Philosophy
- **User-first security** - Your data stays yours, encrypted and local
- **Self-expanding** - Build new tools dynamically without vendor dependency
- **Defense in depth** - Multiple security layers against prompt injection and data exfiltration
- **Always available** - Multi-channel access with proactive background execution
### Features
- **Multi-channel input**: TUI (Ratatui), HTTP webhooks, Telegram, WhatsApp, Slack (WASM channels)
- **Parallel job execution** with state machine and self-repair for stuck jobs - **Parallel job execution** with state machine and self-repair for stuck jobs
- **Extensible tools**: Built-in tools, WASM sandbox, MCP client, dynamic builder - **Extensible tools**: Built-in tools, WASM sandbox, MCP client, dynamic builder
- **Persistent memory**: Workspace with hybrid search (FTS + vector via RRF) - **Persistent memory**: Workspace with hybrid search (FTS + vector via RRF)
@@ -26,7 +34,7 @@ cargo test
cargo test test_name cargo test test_name
# Run with logging # Run with logging
RUST_LOG=near_agent=debug cargo run RUST_LOG=ironclaw=debug cargo run
``` ```
## Project Structure ## Project Structure
@@ -201,7 +209,7 @@ Pending -> InProgress -> Completed -> Submitted -> Accepted
Environment variables (see `.env.example`): Environment variables (see `.env.example`):
```bash ```bash
DATABASE_URL=postgres://user:pass@localhost/near_agent DATABASE_URL=postgres://user:pass@localhost/ironclaw
# NEAR AI (required) # NEAR AI (required)
NEARAI_SESSION_TOKEN=sess_... NEARAI_SESSION_TOKEN=sess_...
@@ -209,7 +217,7 @@ NEARAI_MODEL=claude-3-5-sonnet-20241022
NEARAI_BASE_URL=https://private.near.ai NEARAI_BASE_URL=https://private.near.ai
# Agent settings # Agent settings
AGENT_NAME=near-agent AGENT_NAME=ironclaw
MAX_PARALLEL_JOBS=5 MAX_PARALLEL_JOBS=5
# Embeddings (for semantic memory search) # Embeddings (for semantic memory search)
@@ -328,13 +336,13 @@ Key test patterns:
```bash ```bash
# Verbose logging # Verbose logging
RUST_LOG=near_agent=trace cargo run RUST_LOG=ironclaw=trace cargo run
# Just the agent module # Just the agent module
RUST_LOG=near_agent::agent=debug cargo run RUST_LOG=ironclaw::agent=debug cargo run
# With HTTP request logging # With HTTP request logging
RUST_LOG=near_agent=debug,tower_http=debug cargo run RUST_LOG=ironclaw=debug,tower_http=debug cargo run
``` ```
## Code Style ## Code Style
Generated
+56 -56
View File
@@ -1876,6 +1876,62 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "ironclaw"
version = "0.1.0"
dependencies = [
"aes-gcm",
"aho-corasick",
"anyhow",
"async-trait",
"axum",
"blake3",
"bollard",
"bytes",
"chrono",
"clap",
"crossterm",
"deadpool-postgres",
"dirs 6.0.0",
"dotenvy",
"futures",
"hkdf",
"http-body-util",
"hyper",
"hyper-util",
"open",
"pgvector",
"postgres-types",
"pretty_assertions",
"rand 0.8.5",
"ratatui",
"refinery",
"regex",
"reqwest",
"rust_decimal",
"rust_decimal_macros",
"secrecy",
"serde",
"serde_json",
"sha2",
"tempfile",
"testcontainers-modules",
"thiserror 2.0.18",
"tokio",
"tokio-postgres",
"tokio-stream",
"tokio-test",
"tower",
"tower-http",
"tracing",
"tracing-subscriber",
"urlencoding",
"uuid",
"wasmparser 0.220.1",
"wasmtime",
"wasmtime-wasi",
]
[[package]] [[package]]
name = "is-docker" name = "is-docker"
version = "0.2.0" version = "0.2.0"
@@ -2127,62 +2183,6 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "near-agent"
version = "0.1.0"
dependencies = [
"aes-gcm",
"aho-corasick",
"anyhow",
"async-trait",
"axum",
"blake3",
"bollard",
"bytes",
"chrono",
"clap",
"crossterm",
"deadpool-postgres",
"dirs 6.0.0",
"dotenvy",
"futures",
"hkdf",
"http-body-util",
"hyper",
"hyper-util",
"open",
"pgvector",
"postgres-types",
"pretty_assertions",
"rand 0.8.5",
"ratatui",
"refinery",
"regex",
"reqwest",
"rust_decimal",
"rust_decimal_macros",
"secrecy",
"serde",
"serde_json",
"sha2",
"tempfile",
"testcontainers-modules",
"thiserror 2.0.18",
"tokio",
"tokio-postgres",
"tokio-stream",
"tokio-test",
"tower",
"tower-http",
"tracing",
"tracing-subscriber",
"urlencoding",
"uuid",
"wasmparser 0.220.1",
"wasmtime",
"wasmtime-wasi",
]
[[package]] [[package]]
name = "nu-ansi-term" name = "nu-ansi-term"
version = "0.50.3" version = "0.50.3"
+2 -2
View File
@@ -1,9 +1,9 @@
[package] [package]
name = "near-agent" name = "ironclaw"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
rust-version = "1.85" rust-version = "1.85"
description = "LLM-powered autonomous agent for the NEAR AI marketplace" description = "Secure personal AI assistant that protects your data and expands its capabilities on the fly"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
[dependencies] [dependencies]
+2 -2
View File
@@ -208,7 +208,7 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
| Dynamic loading | ✅ | ✅ | WASM modules | | Dynamic loading | ✅ | ✅ | WASM modules |
| Manifest validation | ✅ | ✅ | WASM metadata | | Manifest validation | ✅ | ✅ | WASM metadata |
| HTTP path registration | ✅ | ❌ | Plugin routes | | HTTP path registration | ✅ | ❌ | Plugin routes |
| Workspace-relative install | ✅ | ✅ | ~/.near-agent/tools/ | | Workspace-relative install | ✅ | ✅ | ~/.ironclaw/tools/ |
| Channel plugins | ✅ | ✅ | WASM channels | | Channel plugins | ✅ | ✅ | WASM channels |
| Auth plugins | ✅ | ❌ | | | Auth plugins | ✅ | ❌ | |
| Memory plugins | ✅ | ❌ | Custom backends | | Memory plugins | ✅ | ❌ | Custom backends |
@@ -233,7 +233,7 @@ This document tracks feature parity between IronClaw (Rust implementation) and O
| Config validation/schema | ✅ | ✅ | Type-safe Config struct | | Config validation/schema | ✅ | ✅ | Type-safe Config struct |
| Hot-reload | ✅ | ❌ | | | Hot-reload | ✅ | ❌ | |
| Legacy migration | ✅ | | | | Legacy migration | ✅ | | |
| State directory | ✅ `~/.openclaw-state/` | ✅ `~/.near-agent/` | | | State directory | ✅ `~/.openclaw-state/` | ✅ `~/.ironclaw/` | |
| Credentials directory | ✅ | ✅ | Session files | | Credentials directory | ✅ | ✅ | Session files |
### Owner: _Unassigned_ ### Owner: _Unassigned_
+96 -71
View File
@@ -5,58 +5,60 @@
<h1 align="center">IronClaw</h1> <h1 align="center">IronClaw</h1>
<p align="center"> <p align="center">
<strong>LLM-powered autonomous agent for the NEAR AI marketplace</strong> <strong>Your secure personal AI assistant, always on your side</strong>
</p> </p>
<p align="center"> <p align="center">
<a href="#philosophy">Philosophy</a> •
<a href="#features">Features</a> • <a href="#features">Features</a> •
<a href="#openclaw-feature-parity">Parity</a> •
<a href="#installation">Installation</a> • <a href="#installation">Installation</a> •
<a href="#configuration">Configuration</a> • <a href="#configuration">Configuration</a> •
<a href="#architecture">Architecture</a> • <a href="#security">Security</a> •
<a href="#security">Security</a> <a href="#architecture">Architecture</a>
</p> </p>
--- ---
## Philosophy
IronClaw is built on a simple principle: **your AI assistant should work for you, not against you**.
In a world where AI systems are increasingly opaque about data handling and aligned with corporate interests, IronClaw takes a different approach:
- **Your data stays yours** - All information is stored locally, encrypted, and never leaves your control
- **Transparency by design** - Open source, auditable, no hidden telemetry or data harvesting
- **Self-expanding capabilities** - Build new tools on the fly without waiting for vendor updates
- **Defense in depth** - Multiple security layers protect against prompt injection and data exfiltration
IronClaw is the AI assistant you can actually trust with your personal and professional life.
## Features ## Features
- **Multi-channel input** - CLI, HTTP webhooks, Slack, Telegram ### Security First
- **Parallel job execution** - Concurrent task processing with isolated contexts
- **Extensible tools** - Built-in tools + MCP protocol + WASM sandbox
- **Persistent memory** - Hybrid search (FTS + vector) with chunked documents
- **Prompt injection defense** - Pattern detection, content sanitization, policy enforcement
- **Self-repair** - Automatic detection and recovery of stuck jobs
- **Heartbeat system** - Proactive periodic execution for background tasks
## OpenClaw Feature Parity - **WASM Sandbox** - Untrusted tools run in isolated WebAssembly containers with capability-based permissions
- **Credential Protection** - Secrets are never exposed to tools; injected at the host boundary with leak detection
- **Prompt Injection Defense** - Pattern detection, content sanitization, and policy enforcement
- **Endpoint Allowlisting** - HTTP requests only to explicitly approved hosts and paths
IronClaw is a Rust reimplementation inspired by [OpenClaw](https://github.com/openclaw/openclaw). See [FEATURE_PARITY.md](FEATURE_PARITY.md) for the complete tracking matrix. ### Always Available
### Status Summary - **Multi-channel** - Reach your assistant via CLI, Telegram, WhatsApp, Slack, or HTTP webhooks
- **Heartbeat System** - Proactive background execution for monitoring and maintenance tasks
- **Parallel Jobs** - Handle multiple requests concurrently with isolated contexts
- **Self-repair** - Automatic detection and recovery of stuck operations
| Category | Status | Notes | ### Self-Expanding
|----------|--------|-------|
| **Core Agent** | ✅ Complete | Sessions, workers, routing, context compaction |
| **Channels** | 🚧 Partial | TUI, HTTP, REPL, WASM channels done; messaging platforms pending |
| **Tools** | ✅ Complete | Built-in, MCP, WASM sandbox, dynamic builder |
| **Memory** | ✅ Complete | Hybrid search, embeddings, workspace filesystem |
| **Security** | ✅ Complete | WASM sandbox, prompt injection, leak detection |
| **Automation** | 🚧 Partial | Heartbeat done; cron, hooks pending |
| **Gateway** | ❌ Pending | WebSocket control plane, service management |
| **Web UI** | ❌ Pending | Control dashboard, WebChat |
| **Mobile/Desktop** | 🚫 Out of scope | Focus on server-side initially |
### Key Differences from OpenClaw - **Dynamic Tool Building** - Describe what you need, and IronClaw builds it as a WASM tool
- **MCP Protocol** - Connect to Model Context Protocol servers for additional capabilities
- **Plugin Architecture** - Drop in new WASM tools and channels without restarting
- **Rust vs TypeScript** - Native performance, single binary ### Persistent Memory
- **WASM sandbox vs Docker** - Lightweight, capability-based security
- **PostgreSQL vs SQLite** - Production-ready persistence
- **NEAR AI primary** - Session-based auth with model proxy
### Contributing - **Hybrid Search** - Full-text + vector search using Reciprocal Rank Fusion
- **Workspace Filesystem** - Flexible path-based storage for notes, logs, and context
Pick an unassigned feature area in [FEATURE_PARITY.md](FEATURE_PARITY.md) and claim it. - **Identity Files** - Maintain consistent personality and preferences across sessions
## Installation ## Installation
@@ -64,14 +66,14 @@ Pick an unassigned feature area in [FEATURE_PARITY.md](FEATURE_PARITY.md) and cl
- Rust 1.85+ - Rust 1.85+
- PostgreSQL 15+ with pgvector extension - PostgreSQL 15+ with pgvector extension
- NEAR AI session token - NEAR AI session token (or other LLM provider)
### Build ### Build
```bash ```bash
# Clone the repository # Clone the repository
git clone https://github.com/nearai/near-agent.git git clone https://github.com/nearai/ironclaw.git
cd near-agent cd ironclaw
# Build # Build
cargo build --release cargo build --release
@@ -84,10 +86,10 @@ cargo test
```bash ```bash
# Create database # Create database
createdb near_agent createdb ironclaw
# Enable pgvector # Enable pgvector
psql near_agent -c "CREATE EXTENSION IF NOT EXISTS vector;" psql ironclaw -c "CREATE EXTENSION IF NOT EXISTS vector;"
# Run migrations # Run migrations
refinery migrate -c refinery.toml refinery migrate -c refinery.toml
@@ -99,12 +101,13 @@ Copy `.env.example` to `.env` and configure:
```bash ```bash
# Required # Required
DATABASE_URL=postgres://user:pass@localhost/near_agent DATABASE_URL=postgres://user:pass@localhost/ironclaw
NEARAI_SESSION_TOKEN=sess_... NEARAI_SESSION_TOKEN=sess_...
# Optional: Enable channels # Optional: Enable channels
SLACK_BOT_TOKEN=xoxb-...
TELEGRAM_BOT_TOKEN=... TELEGRAM_BOT_TOKEN=...
WHATSAPP_ACCESS_TOKEN=...
SLACK_BOT_TOKEN=xoxb-...
HTTP_PORT=8080 HTTP_PORT=8080
``` ```
@@ -118,15 +121,51 @@ HTTP_PORT=8080
| `AGENT_MAX_PARALLEL_JOBS` | Max concurrent jobs (default: 5) | No | | `AGENT_MAX_PARALLEL_JOBS` | Max concurrent jobs (default: 5) | No |
| `SECRETS_MASTER_KEY` | 32+ byte key for secret encryption | For secrets | | `SECRETS_MASTER_KEY` | 32+ byte key for secret encryption | For secrets |
## Security
IronClaw implements defense in depth to protect your data and prevent misuse.
### WASM Sandbox
All untrusted tools run in isolated WebAssembly containers:
- **Capability-based permissions** - Explicit opt-in for HTTP, secrets, tool invocation
- **Endpoint allowlisting** - HTTP requests only to approved hosts/paths
- **Credential injection** - Secrets injected at host boundary, never exposed to WASM code
- **Leak detection** - Scans requests and responses for secret exfiltration attempts
- **Rate limiting** - Per-tool request limits to prevent abuse
- **Resource limits** - Memory, CPU, and execution time constraints
```
WASM ──► Allowlist ──► Leak Scan ──► Credential ──► Execute ──► Leak Scan ──► WASM
Validator (request) Injector Request (response)
```
### Prompt Injection Defense
External content passes through multiple security layers:
- Pattern-based detection of injection attempts
- Content sanitization and escaping
- Policy rules with severity levels (Block/Warn/Review/Sanitize)
- Tool output wrapping for safe LLM context injection
### Data Protection
- All data stored locally in your PostgreSQL database
- Secrets encrypted with AES-256-GCM
- No telemetry, analytics, or data sharing
- Full audit log of all tool executions
## Architecture ## Architecture
``` ```
┌─────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────┐
│ Channels │ │ Channels │
│ ┌─────┐ ┌──────┐ ┌───────┐ ┌──────────┐ │ ┌─────┐ ┌──────────┐ ┌──────────┐ ┌───────┐
│ │ CLI │ │ HTTP │ │ Slack │ │ Telegram │ │ │ CLI │ │ Telegram │ │ WhatsApp │ │ Slack │
│ └──┬──┘ └─────┘ └───┬───┘ └────┬─────┘ │ └──┬──┘ └────┬─────┘ └────┬─────┘ └───┬───┘
│ └──────────────────┴───────────┘ │ └──────────┴─────────────┴───────────┘ │
│ │ │ │ │ │
│ ┌────▼────┐ │ │ ┌────▼────┐ │
│ │ Router │ Intent classification │ │ │ Router │ Intent classification │
@@ -165,31 +204,6 @@ HTTP_PORT=8080
| **Workspace** | Persistent memory with hybrid search | | **Workspace** | Persistent memory with hybrid search |
| **Safety Layer** | Prompt injection defense and content sanitization | | **Safety Layer** | Prompt injection defense and content sanitization |
## Security
### WASM Sandbox
Untrusted tools run in a sandboxed WASM environment with:
- **Capability-based permissions** - Explicit opt-in for HTTP, secrets, tool invocation
- **Endpoint allowlisting** - HTTP requests only to approved hosts/paths
- **Credential injection** - Secrets injected at host boundary, never exposed to WASM
- **Leak detection** - Scans requests and responses for secret exfiltration
- **Rate limiting** - Per-tool request limits (per-minute and per-hour)
- **Resource limits** - Memory, CPU, and execution time constraints
```
WASM ──► Allowlist ──► Leak Scan ──► Credential ──► Execute ──► Leak Scan ──► WASM
Validator (request) Injector Request (response)
```
### Prompt Injection Defense
- Pattern-based detection of injection attempts
- Content sanitization and escaping
- Policy rules with severity levels (Block/Warn/Review/Sanitize)
- Tool output wrapping for LLM context
## Usage ## Usage
### CLI Mode ### CLI Mode
@@ -199,7 +213,7 @@ WASM ──► Allowlist ──► Leak Scan ──► Credential ──► Exec
cargo run cargo run
# With debug logging # With debug logging
RUST_LOG=near_agent=debug cargo run RUST_LOG=ironclaw=debug cargo run
``` ```
### HTTP Server ### HTTP Server
@@ -211,7 +225,7 @@ HTTP_PORT=8080 cargo run
# Send a request # Send a request
curl -X POST http://localhost:8080/webhook \ curl -X POST http://localhost:8080/webhook \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{"message": "Hello, agent!"}' -d '{"message": "Hello, IronClaw!"}'
``` ```
## Development ## Development
@@ -230,6 +244,17 @@ cargo test
cargo test test_name cargo test test_name
``` ```
## OpenClaw Heritage
IronClaw is a Rust reimplementation inspired by [OpenClaw](https://github.com/openclaw/openclaw). See [FEATURE_PARITY.md](FEATURE_PARITY.md) for the complete tracking matrix.
Key differences:
- **Rust vs TypeScript** - Native performance, memory safety, single binary
- **WASM sandbox vs Docker** - Lightweight, capability-based security
- **PostgreSQL vs SQLite** - Production-ready persistence
- **Security-first design** - Multiple defense layers, credential protection
## License ## License
Licensed under either of: Licensed under either of:
+1 -1
View File
@@ -2,7 +2,7 @@
name = "slack-channel" name = "slack-channel"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "Slack Events API channel for NEAR Agent" description = "Slack Events API channel for IronClaw"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
[lib] [lib]
+1 -1
View File
@@ -1,4 +1,4 @@
//! Slack Events API channel for NEAR Agent. //! Slack Events API channel for IronClaw.
//! //!
//! This WASM component implements the channel interface for handling Slack //! This WASM component implements the channel interface for handling Slack
//! webhooks and sending messages back to Slack. //! webhooks and sending messages back to Slack.
+1 -1
View File
@@ -2,7 +2,7 @@
name = "telegram-channel" name = "telegram-channel"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "Telegram Bot API channel for NEAR Agent" description = "Telegram Bot API channel for IronClaw"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
[lib] [lib]
+1 -1
View File
@@ -1,7 +1,7 @@
// Telegram API types have fields reserved for future use (entities, reply threading, etc.) // Telegram API types have fields reserved for future use (entities, reply threading, etc.)
#![allow(dead_code)] #![allow(dead_code)]
//! Telegram Bot API channel for NEAR Agent. //! Telegram Bot API channel for IronClaw.
//! //!
//! This WASM component implements the channel interface for handling Telegram //! This WASM component implements the channel interface for handling Telegram
//! webhooks and sending messages back via the Bot API. //! webhooks and sending messages back via the Bot API.
+1 -1
View File
@@ -2,7 +2,7 @@
name = "whatsapp-channel" name = "whatsapp-channel"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "WhatsApp channel for near-agent using the Cloud API" description = "WhatsApp Cloud API channel for IronClaw"
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib"]
+1 -1
View File
@@ -1,7 +1,7 @@
// WhatsApp API types have fields reserved for future use (contacts, statuses, etc.) // WhatsApp API types have fields reserved for future use (contacts, statuses, etc.)
#![allow(dead_code)] #![allow(dead_code)]
//! WhatsApp Cloud API channel for NEAR Agent. //! WhatsApp Cloud API channel for IronClaw.
//! //!
//! This WASM component implements the channel interface for handling WhatsApp //! This WASM component implements the channel interface for handling WhatsApp
//! webhooks and sending messages back via the Cloud API. //! webhooks and sending messages back via the Cloud API.
+6 -6
View File
@@ -1,6 +1,6 @@
# Building WASM Channels # Building WASM Channels
This guide covers how to build WASM channel modules for the NEAR Agent. This guide covers how to build WASM channel modules for IronClaw.
## Overview ## Overview
@@ -19,7 +19,7 @@ channels/ # Or channels-src/
After building, deploy to: After building, deploy to:
``` ```
~/.near-agent/channels/ ~/.ironclaw/channels/
├── my-channel.wasm ├── my-channel.wasm
└── my-channel.capabilities.json └── my-channel.capabilities.json
``` ```
@@ -31,7 +31,7 @@ After building, deploy to:
name = "my-channel" name = "my-channel"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "My messaging platform channel for NEAR Agent" description = "My messaging platform channel for IronClaw"
[lib] [lib]
crate-type = ["cdylib"] crate-type = ["cdylib"]
@@ -251,9 +251,9 @@ Create `my-channel.capabilities.json`:
cd channels/my-channel cd channels/my-channel
cargo component build --release cargo component build --release
# Deploy to ~/.near-agent/channels/ # Deploy to ~/.ironclaw/channels/
cp target/wasm32-wasip1/release/my_channel.wasm ~/.near-agent/channels/my-channel.wasm cp target/wasm32-wasip1/release/my_channel.wasm ~/.ironclaw/channels/my-channel.wasm
cp my-channel.capabilities.json ~/.near-agent/channels/ cp my-channel.capabilities.json ~/.ironclaw/channels/
``` ```
## Host Functions Available ## Host Functions Available
+1 -1
View File
@@ -2,7 +2,7 @@
name = "slack-tool" name = "slack-tool"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "Slack integration tool for NEAR Agent (WASM component)" description = "Slack integration tool for IronClaw (WASM component)"
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
publish = false publish = false
+8 -8
View File
@@ -1,6 +1,6 @@
# Slack WASM Tool # Slack WASM Tool
A standalone WASM component that provides Slack integration for NEAR Agent. This serves as both a functional tool and a template for building custom WASM tools. A standalone WASM component that provides Slack integration for IronClaw. This serves as both a functional tool and a template for building custom WASM tools.
## Features ## Features
@@ -50,9 +50,9 @@ target/wasm32-wasip2/release/slack_tool.wasm
Copy the WASM and capabilities files to the agent's tools directory: Copy the WASM and capabilities files to the agent's tools directory:
```bash ```bash
mkdir -p ~/.near-agent/tools mkdir -p ~/.ironclaw/tools
cp target/wasm32-wasip2/release/slack_tool.wasm ~/.near-agent/tools/slack.wasm cp target/wasm32-wasip2/release/slack_tool.wasm ~/.ironclaw/tools/slack.wasm
cp slack.capabilities.json ~/.near-agent/tools/ cp slack.capabilities.json ~/.ironclaw/tools/
``` ```
### Option B: Database Storage (Production) ### Option B: Database Storage (Production)
@@ -60,7 +60,7 @@ cp slack.capabilities.json ~/.near-agent/tools/
Use the agent CLI or API to store the tool: Use the agent CLI or API to store the tool:
```bash ```bash
near-agent tool install \ ironclaw tool install \
--name slack \ --name slack \
--wasm target/wasm32-wasip2/release/slack_tool.wasm \ --wasm target/wasm32-wasip2/release/slack_tool.wasm \
--capabilities slack.capabilities.json --capabilities slack.capabilities.json
@@ -71,7 +71,7 @@ near-agent tool install \
Store your Slack bot token as a secret: Store your Slack bot token as a secret:
```bash ```bash
near-agent secret set slack_bot_token "xoxb-your-token-here" ironclaw secret set slack_bot_token "xoxb-your-token-here"
``` ```
Or via SQL: Or via SQL:
@@ -88,7 +88,7 @@ VALUES ('your_user_id', 'slack_bot_token', ...);
{ {
"action": "send_message", "action": "send_message",
"channel": "#general", "channel": "#general",
"text": "Hello from the NEAR Agent!" "text": "Hello from IronClaw!"
} }
``` ```
@@ -214,7 +214,7 @@ world sandboxed-tool {
Ensure you've stored the secret: Ensure you've stored the secret:
```bash ```bash
near-agent secret set slack_bot_token "xoxb-..." ironclaw secret set slack_bot_token "xoxb-..."
``` ```
### "Endpoint not in allowlist" ### "Endpoint not in allowlist"
+1 -1
View File
@@ -1,4 +1,4 @@
//! Slack WASM Tool for NEAR Agent. //! Slack WASM Tool for IronClaw.
//! //!
//! This is a standalone WASM component that provides Slack integration. //! This is a standalone WASM component that provides Slack integration.
//! It demonstrates how to build external tools that can be dynamically //! It demonstrates how to build external tools that can be dynamically
+1 -1
View File
@@ -147,7 +147,7 @@ impl AppState {
Self { Self {
mode: InputMode::Editing, mode: InputMode::Editing,
messages: vec![ChatMessage::system( messages: vec![ChatMessage::system(
"Welcome to NEAR Agent. Type a message or /help for commands.", "Welcome to IronClaw. Type a message or /help for commands.",
)], )],
composer: ChatComposer::new(), composer: ChatComposer::new(),
approval: None, approval: None,
+2 -2
View File
@@ -64,7 +64,7 @@ impl Default for ReplChannel {
fn print_help() { fn print_help() {
println!( println!(
r#" r#"
NEAR Agent REPL - Interactive debugging mode IronClaw REPL - Interactive debugging mode
Commands: Commands:
/help Show this help message /help Show this help message
@@ -116,7 +116,7 @@ impl Channel for ReplChannel {
let stdin = io::stdin(); let stdin = io::stdin();
let mut stdout = io::stdout(); let mut stdout = io::stdout();
println!("NEAR Agent REPL - Type /help for commands, /quit to exit"); println!("IronClaw REPL - Type /help for commands, /quit to exit");
println!(); println!();
loop { loop {
+3 -3
View File
@@ -1,6 +1,6 @@
//! WASM channel loader for loading channels from files or directories. //! WASM channel loader for loading channels from files or directories.
//! //!
//! Loads WASM channel modules from the filesystem (default: ~/.near-agent/channels/). //! Loads WASM channel modules from the filesystem (default: ~/.ironclaw/channels/).
//! Each channel consists of: //! Each channel consists of:
//! - `<name>.wasm` - The compiled WASM component //! - `<name>.wasm` - The compiled WASM component
//! - `<name>.capabilities.json` - Channel capabilities and configuration //! - `<name>.capabilities.json` - Channel capabilities and configuration
@@ -329,12 +329,12 @@ pub struct DiscoveredChannel {
/// Get the default channels directory path. /// Get the default channels directory path.
/// ///
/// Returns ~/.near-agent/channels/ /// Returns ~/.ironclaw/channels/
#[allow(dead_code)] #[allow(dead_code)]
pub fn default_channels_dir() -> PathBuf { pub fn default_channels_dir() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join(".near-agent") .join(".ironclaw")
.join("channels") .join("channels")
} }
+2 -2
View File
@@ -63,14 +63,14 @@
//! # Example Usage //! # Example Usage
//! //!
//! ```ignore //! ```ignore
//! use near_agent::channels::wasm::{WasmChannelLoader, WasmChannelRuntime}; //! use ironclaw::channels::wasm::{WasmChannelLoader, WasmChannelRuntime};
//! //!
//! // Create runtime (can share engine with tool runtime) //! // Create runtime (can share engine with tool runtime)
//! let runtime = WasmChannelRuntime::new(config)?; //! let runtime = WasmChannelRuntime::new(config)?;
//! //!
//! // Load channels from directory //! // Load channels from directory
//! let loader = WasmChannelLoader::new(runtime); //! let loader = WasmChannelLoader::new(runtime);
//! let channels = loader.load_from_dir(Path::new("~/.near-agent/channels/")).await?; //! let channels = loader.load_from_dir(Path::new("~/.ironclaw/channels/")).await?;
//! //!
//! // Add to channel manager //! // Add to channel manager
//! for channel in channels { //! for channel in channels {
+4 -2
View File
@@ -13,8 +13,10 @@ pub use tool::{ToolCommand, run_tool_command};
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(name = "near-agent")] #[command(name = "ironclaw")]
#[command(about = "LLM-powered autonomous agent for the NEAR AI marketplace")] #[command(
about = "Secure personal AI assistant that protects your data and expands its capabilities"
)]
#[command(version)] #[command(version)]
pub struct Cli { pub struct Cli {
#[command(subcommand)] #[command(subcommand)]
+8 -8
View File
@@ -13,8 +13,8 @@ use crate::tools::wasm::{CapabilitiesFile, compute_binary_hash};
/// Default tools directory. /// Default tools directory.
fn default_tools_dir() -> PathBuf { fn default_tools_dir() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.map(|h| h.join(".near-agent").join("tools")) .map(|h| h.join(".ironclaw").join("tools"))
.unwrap_or_else(|| PathBuf::from(".near-agent/tools")) .unwrap_or_else(|| PathBuf::from(".ironclaw/tools"))
} }
#[derive(Subcommand, Debug, Clone)] #[derive(Subcommand, Debug, Clone)]
@@ -32,7 +32,7 @@ pub enum ToolCommand {
#[arg(long)] #[arg(long)]
capabilities: Option<PathBuf>, capabilities: Option<PathBuf>,
/// Target directory for installation (default: ~/.near-agent/tools/) /// Target directory for installation (default: ~/.ironclaw/tools/)
#[arg(short, long)] #[arg(short, long)]
target: Option<PathBuf>, target: Option<PathBuf>,
@@ -51,7 +51,7 @@ pub enum ToolCommand {
/// List installed tools /// List installed tools
List { List {
/// Directory to list tools from (default: ~/.near-agent/tools/) /// Directory to list tools from (default: ~/.ironclaw/tools/)
#[arg(short, long)] #[arg(short, long)]
dir: Option<PathBuf>, dir: Option<PathBuf>,
@@ -65,7 +65,7 @@ pub enum ToolCommand {
/// Name of the tool to remove /// Name of the tool to remove
name: String, name: String,
/// Directory to remove tool from (default: ~/.near-agent/tools/) /// Directory to remove tool from (default: ~/.ironclaw/tools/)
#[arg(short, long)] #[arg(short, long)]
dir: Option<PathBuf>, dir: Option<PathBuf>,
}, },
@@ -75,7 +75,7 @@ pub enum ToolCommand {
/// Name of the tool or path to .wasm file /// Name of the tool or path to .wasm file
name_or_path: String, name_or_path: String,
/// Directory to look for tool (default: ~/.near-agent/tools/) /// Directory to look for tool (default: ~/.ironclaw/tools/)
#[arg(short, long)] #[arg(short, long)]
dir: Option<PathBuf>, dir: Option<PathBuf>,
}, },
@@ -420,7 +420,7 @@ async fn list_tools(dir: Option<PathBuf>, verbose: bool) -> anyhow::Result<()> {
if !tools_dir.exists() { if !tools_dir.exists() {
println!("No tools directory found at {}", tools_dir.display()); println!("No tools directory found at {}", tools_dir.display());
println!("Install a tool with: near-agent tool install <path>"); println!("Install a tool with: ironclaw tool install <path>");
return Ok(()); return Ok(());
} }
@@ -674,7 +674,7 @@ mod tests {
#[test] #[test]
fn test_default_tools_dir() { fn test_default_tools_dir() {
let dir = default_tools_dir(); let dir = default_tools_dir();
assert!(dir.to_string_lossy().contains(".near-agent")); assert!(dir.to_string_lossy().contains(".ironclaw"));
assert!(dir.to_string_lossy().contains("tools")); assert!(dir.to_string_lossy().contains("tools"));
} }
} }
+11 -11
View File
@@ -1,4 +1,4 @@
//! Configuration for the NEAR Agent. //! Configuration for IronClaw.
use std::path::PathBuf; use std::path::PathBuf;
use std::time::Duration; use std::time::Duration;
@@ -192,7 +192,7 @@ pub struct NearAiConfig {
pub base_url: String, pub base_url: String,
/// Base URL for auth/refresh endpoints (default: https://private.near.ai) /// Base URL for auth/refresh endpoints (default: https://private.near.ai)
pub auth_base_url: String, pub auth_base_url: String,
/// Path to session file (default: ~/.near-agent/session.json) /// Path to session file (default: ~/.ironclaw/session.json)
pub session_path: PathBuf, pub session_path: PathBuf,
/// API mode: "responses" (chat-api) or "chat_completions" (cloud-api) /// API mode: "responses" (chat-api) or "chat_completions" (cloud-api)
pub api_mode: NearAiApiMode, pub api_mode: NearAiApiMode,
@@ -297,11 +297,11 @@ impl EmbeddingsConfig {
} }
} }
/// Get the default session file path (~/.near-agent/session.json). /// Get the default session file path (~/.ironclaw/session.json).
fn default_session_path() -> PathBuf { fn default_session_path() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join(".near-agent") .join(".ironclaw")
.join("session.json") .join("session.json")
} }
@@ -310,7 +310,7 @@ fn default_session_path() -> PathBuf {
pub struct ChannelsConfig { pub struct ChannelsConfig {
pub cli: CliConfig, pub cli: CliConfig,
pub http: Option<HttpConfig>, pub http: Option<HttpConfig>,
/// Directory containing WASM channel modules (default: ~/.near-agent/channels/). /// Directory containing WASM channel modules (default: ~/.ironclaw/channels/).
pub wasm_channels_dir: std::path::PathBuf, pub wasm_channels_dir: std::path::PathBuf,
/// Whether WASM channels are enabled. /// Whether WASM channels are enabled.
pub wasm_channels_enabled: bool, pub wasm_channels_enabled: bool,
@@ -371,11 +371,11 @@ impl ChannelsConfig {
} }
} }
/// Get the default channels directory (~/.near-agent/channels/). /// Get the default channels directory (~/.ironclaw/channels/).
fn default_channels_dir() -> PathBuf { fn default_channels_dir() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join(".near-agent") .join(".ironclaw")
.join("channels") .join("channels")
} }
@@ -395,7 +395,7 @@ pub struct AgentConfig {
impl AgentConfig { impl AgentConfig {
fn from_env() -> Result<Self, ConfigError> { fn from_env() -> Result<Self, ConfigError> {
Ok(Self { Ok(Self {
name: optional_env("AGENT_NAME")?.unwrap_or_else(|| "near-agent".to_string()), name: optional_env("AGENT_NAME")?.unwrap_or_else(|| "ironclaw".to_string()),
max_parallel_jobs: parse_optional_env("AGENT_MAX_PARALLEL_JOBS", 5)?, max_parallel_jobs: parse_optional_env("AGENT_MAX_PARALLEL_JOBS", 5)?,
job_timeout: Duration::from_secs(parse_optional_env("AGENT_JOB_TIMEOUT_SECS", 3600)?), job_timeout: Duration::from_secs(parse_optional_env("AGENT_JOB_TIMEOUT_SECS", 3600)?),
stuck_threshold: Duration::from_secs(parse_optional_env( stuck_threshold: Duration::from_secs(parse_optional_env(
@@ -447,7 +447,7 @@ impl SafetyConfig {
pub struct WasmConfig { pub struct WasmConfig {
/// Whether WASM tool execution is enabled. /// Whether WASM tool execution is enabled.
pub enabled: bool, pub enabled: bool,
/// Directory containing installed WASM tools (default: ~/.near-agent/tools/). /// Directory containing installed WASM tools (default: ~/.ironclaw/tools/).
pub tools_dir: PathBuf, pub tools_dir: PathBuf,
/// Default memory limit in bytes (default: 10 MB). /// Default memory limit in bytes (default: 10 MB).
pub default_memory_limit: u64, pub default_memory_limit: u64,
@@ -521,11 +521,11 @@ impl Default for WasmConfig {
} }
} }
/// Get the default tools directory (~/.near-agent/tools/). /// Get the default tools directory (~/.ironclaw/tools/).
fn default_tools_dir() -> PathBuf { fn default_tools_dir() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join(".near-agent") .join(".ironclaw")
.join("tools") .join("tools")
} }
+1 -1
View File
@@ -1,4 +1,4 @@
//! Error types for the NEAR Agent. //! Error types for IronClaw.
use std::time::Duration; use std::time::Duration;
+5 -5
View File
@@ -1,7 +1,7 @@
//! Session management for NEAR AI authentication. //! Session management for NEAR AI authentication.
//! //!
//! Handles session token persistence, expiration detection, and renewal via //! Handles session token persistence, expiration detection, and renewal via
//! OAuth flow. Tokens are stored in `~/.near-agent/session.json` and refreshed //! OAuth flow. Tokens are stored in `~/.ironclaw/session.json` and refreshed
//! automatically when expired. //! automatically when expired.
use std::path::PathBuf; use std::path::PathBuf;
@@ -29,7 +29,7 @@ pub struct SessionData {
pub struct SessionConfig { pub struct SessionConfig {
/// Base URL for auth endpoints (e.g., https://private.near.ai). /// Base URL for auth endpoints (e.g., https://private.near.ai).
pub auth_base_url: String, pub auth_base_url: String,
/// Path to session file (e.g., ~/.near-agent/session.json). /// Path to session file (e.g., ~/.ironclaw/session.json).
pub session_path: PathBuf, pub session_path: PathBuf,
/// Port range for OAuth callback server. /// Port range for OAuth callback server.
pub callback_port_range: (u16, u16), pub callback_port_range: (u16, u16),
@@ -45,11 +45,11 @@ impl Default for SessionConfig {
} }
} }
/// Get the default session file path (~/.near-agent/session.json). /// Get the default session file path (~/.ironclaw/session.json).
pub fn default_session_path() -> PathBuf { pub fn default_session_path() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join(".near-agent") .join(".ironclaw")
.join("session.json") .join("session.json")
} }
@@ -631,6 +631,6 @@ mod tests {
fn test_default_session_path() { fn test_default_session_path() {
let path = default_session_path(); let path = default_session_path();
assert!(path.ends_with("session.json")); assert!(path.ends_with("session.json"));
assert!(path.to_string_lossy().contains(".near-agent")); assert!(path.to_string_lossy().contains(".ironclaw"));
} }
} }
+6 -6
View File
@@ -1,11 +1,11 @@
//! NEAR Agent - Main entry point. //! IronClaw - Main entry point.
use std::sync::Arc; use std::sync::Arc;
use clap::Parser; use clap::Parser;
use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt}; use tracing_subscriber::{EnvFilter, layer::SubscriberExt, util::SubscriberInitExt};
use near_agent::{ use ironclaw::{
agent::{Agent, AgentDeps}, agent::{Agent, AgentDeps},
channels::{ channels::{
AppEvent, ChannelManager, HttpChannel, ReplChannel, TuiChannel, AppEvent, ChannelManager, HttpChannel, ReplChannel, TuiChannel,
@@ -74,7 +74,7 @@ async fn main() -> anyhow::Result<()> {
// automatically run the setup wizard // automatically run the setup wizard
if !cli.no_setup { if !cli.no_setup {
let settings = Settings::load(); let settings = Settings::load();
let session_path = near_agent::llm::session::default_session_path(); let session_path = ironclaw::llm::session::default_session_path();
if !settings.setup_completed && !session_path.exists() { if !settings.setup_completed && !session_path.exists() {
println!("First run detected. Starting setup wizard..."); println!("First run detected. Starting setup wizard...");
@@ -102,7 +102,7 @@ async fn main() -> anyhow::Result<()> {
// Initialize tracing and channels based on mode // Initialize tracing and channels based on mode
let env_filter = EnvFilter::try_from_default_env() let env_filter = EnvFilter::try_from_default_env()
.unwrap_or_else(|_| EnvFilter::new("near_agent=info,tower_http=debug")); .unwrap_or_else(|_| EnvFilter::new("ironclaw=info,tower_http=debug"));
// Determine which mode to use: REPL, single message, or TUI // Determine which mode to use: REPL, single message, or TUI
let use_repl = cli.repl || cli.message.is_some(); let use_repl = cli.repl || cli.message.is_some();
@@ -150,7 +150,7 @@ async fn main() -> anyhow::Result<()> {
(None, None, None) (None, None, None)
}; };
tracing::info!("Starting NEAR Agent..."); tracing::info!("Starting IronClaw...");
tracing::info!("Loaded configuration for agent: {}", config.agent.name); tracing::info!("Loaded configuration for agent: {}", config.agent.name);
tracing::info!("NEAR AI session authenticated"); tracing::info!("NEAR AI session authenticated");
@@ -578,7 +578,7 @@ async fn main() -> anyhow::Result<()> {
/// ///
/// Returns the number of credentials injected. /// Returns the number of credentials injected.
async fn inject_channel_credentials( async fn inject_channel_credentials(
channel: &Arc<near_agent::channels::wasm::WasmChannel>, channel: &Arc<ironclaw::channels::wasm::WasmChannel>,
secrets: &dyn SecretsStore, secrets: &dyn SecretsStore,
channel_name: &str, channel_name: &str,
) -> anyhow::Result<usize> { ) -> anyhow::Result<usize> {
+1 -1
View File
@@ -49,7 +49,7 @@
//! # Example //! # Example
//! //!
//! ```rust,no_run //! ```rust,no_run
//! use near_agent::sandbox::{SandboxManager, SandboxManagerBuilder, SandboxPolicy}; //! use ironclaw::sandbox::{SandboxManager, SandboxManagerBuilder, SandboxPolicy};
//! use std::collections::HashMap; //! use std::collections::HashMap;
//! use std::path::Path; //! use std::path::Path;
//! //!
+1 -1
View File
@@ -31,7 +31,7 @@
//! # Example //! # Example
//! //!
//! ```ignore //! ```ignore
//! use near_agent::secrets::{SecretsStore, PostgresSecretsStore, SecretsCrypto, CreateSecretParams}; //! use ironclaw::secrets::{SecretsStore, PostgresSecretsStore, SecretsCrypto, CreateSecretParams};
//! use secrecy::SecretString; //! use secrecy::SecretString;
//! //!
//! // Initialize crypto with master key from environment //! // Initialize crypto with master key from environment
+3 -3
View File
@@ -1,6 +1,6 @@
//! User settings persistence. //! User settings persistence.
//! //!
//! Stores user preferences like selected model in ~/.near-agent/settings.json. //! Stores user preferences like selected model in ~/.ironclaw/settings.json.
use std::path::PathBuf; use std::path::PathBuf;
@@ -55,11 +55,11 @@ pub struct ChannelSettings {
} }
impl Settings { impl Settings {
/// Get the default settings file path (~/.near-agent/settings.json). /// Get the default settings file path (~/.ironclaw/settings.json).
pub fn default_path() -> PathBuf { pub fn default_path() -> PathBuf {
dirs::home_dir() dirs::home_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join(".near-agent") .join(".ironclaw")
.join("settings.json") .join("settings.json")
} }
+2 -2
View File
@@ -1,4 +1,4 @@
//! Interactive setup wizard for NEAR Agent. //! Interactive setup wizard for IronClaw.
//! //!
//! Provides a guided setup experience for: //! Provides a guided setup experience for:
//! - NEAR AI authentication //! - NEAR AI authentication
@@ -8,7 +8,7 @@
//! # Example //! # Example
//! //!
//! ```ignore //! ```ignore
//! use near_agent::setup::SetupWizard; //! use ironclaw::setup::SetupWizard;
//! //!
//! let mut wizard = SetupWizard::new(); //! let mut wizard = SetupWizard::new();
//! wizard.run().await?; //! wizard.run().await?;
+1 -1
View File
@@ -259,7 +259,7 @@ pub fn confirm(prompt: &str, default: bool) -> io::Result<bool> {
/// # Example /// # Example
/// ///
/// ```ignore /// ```ignore
/// print_header("NEAR Agent Setup Wizard"); /// print_header("IronClaw Setup Wizard");
/// ``` /// ```
pub fn print_header(text: &str) { pub fn print_header(text: &str) {
let width = text.len() + 4; let width = text.len() + 4;
+5 -5
View File
@@ -53,7 +53,7 @@ pub struct SetupConfig {
pub channels_only: bool, pub channels_only: bool,
} }
/// Interactive setup wizard for NEAR Agent. /// Interactive setup wizard for IronClaw.
pub struct SetupWizard { pub struct SetupWizard {
config: SetupConfig, config: SetupConfig,
settings: Settings, settings: Settings,
@@ -87,7 +87,7 @@ impl SetupWizard {
/// Run the setup wizard. /// Run the setup wizard.
pub async fn run(&mut self) -> Result<(), SetupError> { pub async fn run(&mut self) -> Result<(), SetupError> {
print_header("NEAR Agent Setup Wizard"); print_header("IronClaw Setup Wizard");
let total_steps = if self.config.channels_only { 1 } else { 3 }; let total_steps = if self.config.channels_only { 1 } else { 3 };
let mut current_step = 1; let mut current_step = 1;
@@ -336,7 +336,7 @@ impl SetupWizard {
// Discover available WASM channels // Discover available WASM channels
let channels_dir = dirs::home_dir() let channels_dir = dirs::home_dir()
.unwrap_or_default() .unwrap_or_default()
.join(".near-agent/channels"); .join(".ironclaw/channels");
let discovered_channels = discover_wasm_channels(&channels_dir).await; let discovered_channels = discover_wasm_channels(&channels_dir).await;
@@ -438,7 +438,7 @@ impl SetupWizard {
})?; })?;
println!(); println!();
print_success("Configuration saved to ~/.near-agent/"); print_success("Configuration saved to ~/.ironclaw/");
println!(); println!();
// Print summary // Print summary
@@ -476,7 +476,7 @@ impl SetupWizard {
println!(); println!();
println!("To start the agent, run:"); println!("To start the agent, run:");
println!(" near-agent"); println!(" ironclaw");
println!(); println!();
Ok(()) Ok(())
+1 -1
View File
@@ -218,7 +218,7 @@ pub struct BuilderConfig {
impl Default for BuilderConfig { impl Default for BuilderConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
build_dir: std::env::temp_dir().join("near-agent-builds"), build_dir: std::env::temp_dir().join("ironclaw-builds"),
max_iterations: 10, max_iterations: 10,
timeout: Duration::from_secs(600), // 10 minutes timeout: Duration::from_secs(600), // 10 minutes
cleanup_on_failure: false, // Keep for debugging cleanup_on_failure: false, // Keep for debugging
+2 -2
View File
@@ -7,7 +7,7 @@
//! # Example: Loading from Directory //! # Example: Loading from Directory
//! //!
//! ```text //! ```text
//! ~/.near-agent/tools/ //! ~/.ironclaw/tools/
//! ├── slack.wasm //! ├── slack.wasm
//! ├── slack.capabilities.json //! ├── slack.capabilities.json
//! ├── github.wasm //! ├── github.wasm
@@ -16,7 +16,7 @@
//! //!
//! ```ignore //! ```ignore
//! let loader = WasmToolLoader::new(runtime, registry); //! let loader = WasmToolLoader::new(runtime, registry);
//! loader.load_from_dir(Path::new("~/.near-agent/tools/")).await?; //! loader.load_from_dir(Path::new("~/.ironclaw/tools/")).await?;
//! ``` //! ```
//! //!
//! # Security //! # Security
+2 -2
View File
@@ -51,8 +51,8 @@
//! # Example //! # Example
//! //!
//! ```ignore //! ```ignore
//! use near_agent::tools::wasm::{WasmToolRuntime, WasmRuntimeConfig, WasmToolWrapper}; //! use ironclaw::tools::wasm::{WasmToolRuntime, WasmRuntimeConfig, WasmToolWrapper};
//! use near_agent::tools::wasm::Capabilities; //! use ironclaw::tools::wasm::Capabilities;
//! use std::sync::Arc; //! use std::sync::Arc;
//! //!
//! // Create runtime //! // Create runtime
+7 -7
View File
@@ -9,8 +9,8 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc; use std::sync::Arc;
use near_agent::channels::Channel; use ironclaw::channels::Channel;
use near_agent::channels::wasm::{ use ironclaw::channels::wasm::{
ChannelCapabilities, EmitRateLimitConfig, PreparedChannelModule, RegisteredEndpoint, ChannelCapabilities, EmitRateLimitConfig, PreparedChannelModule, RegisteredEndpoint,
WasmChannel, WasmChannelRouter, WasmChannelRuntime, WasmChannelRuntimeConfig, WasmChannel, WasmChannelRouter, WasmChannelRuntime, WasmChannelRuntimeConfig,
}; };
@@ -238,7 +238,7 @@ mod loader_tests {
async fn test_discover_channels_empty_dir() { async fn test_discover_channels_empty_dir() {
let dir = TempDir::new().expect("Failed to create temp dir"); let dir = TempDir::new().expect("Failed to create temp dir");
let channels = near_agent::channels::wasm::discover_channels(dir.path()) let channels = ironclaw::channels::wasm::discover_channels(dir.path())
.await .await
.expect("Discovery failed"); .expect("Discovery failed");
@@ -253,7 +253,7 @@ mod loader_tests {
std::fs::File::create(dir.path().join("slack.wasm")).expect("Failed to create file"); std::fs::File::create(dir.path().join("slack.wasm")).expect("Failed to create file");
std::fs::File::create(dir.path().join("telegram.wasm")).expect("Failed to create file"); std::fs::File::create(dir.path().join("telegram.wasm")).expect("Failed to create file");
let channels = near_agent::channels::wasm::discover_channels(dir.path()) let channels = ironclaw::channels::wasm::discover_channels(dir.path())
.await .await
.expect("Discovery failed"); .expect("Discovery failed");
@@ -284,7 +284,7 @@ mod loader_tests {
) )
.expect("Failed to write capabilities"); .expect("Failed to write capabilities");
let channels = near_agent::channels::wasm::discover_channels(dir.path()) let channels = ironclaw::channels::wasm::discover_channels(dir.path())
.await .await
.expect("Discovery failed"); .expect("Discovery failed");
@@ -301,7 +301,7 @@ mod loader_tests {
std::fs::File::create(dir.path().join("config.json")).expect("Failed to create file"); std::fs::File::create(dir.path().join("config.json")).expect("Failed to create file");
std::fs::File::create(dir.path().join("channel.wasm")).expect("Failed to create file"); std::fs::File::create(dir.path().join("channel.wasm")).expect("Failed to create file");
let channels = near_agent::channels::wasm::discover_channels(dir.path()) let channels = ironclaw::channels::wasm::discover_channels(dir.path())
.await .await
.expect("Discovery failed"); .expect("Discovery failed");
@@ -388,7 +388,7 @@ mod capabilities_tests {
mod message_emission_tests { mod message_emission_tests {
use super::*; use super::*;
use near_agent::channels::wasm::{ChannelHostState, EmittedMessage}; use ironclaw::channels::wasm::{ChannelHostState, EmittedMessage};
#[test] #[test]
fn test_emit_message_basic() { fn test_emit_message_basic() {
+3 -3
View File
@@ -1,15 +1,15 @@
//! Integration tests for the workspace module. //! Integration tests for the workspace module.
//! //!
//! Requires a running PostgreSQL with pgvector extension. //! Requires a running PostgreSQL with pgvector extension.
//! Set DATABASE_URL=postgres://localhost/near_agent_test //! Set DATABASE_URL=postgres://localhost/ironclaw_test
use std::sync::Arc; use std::sync::Arc;
use near_agent::workspace::{MockEmbeddings, SearchConfig, Workspace, paths}; use ironclaw::workspace::{MockEmbeddings, SearchConfig, Workspace, paths};
fn get_pool() -> deadpool_postgres::Pool { fn get_pool() -> deadpool_postgres::Pool {
let database_url = std::env::var("DATABASE_URL") let database_url = std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://localhost/near_agent_test".to_string()); .unwrap_or_else(|_| "postgres://localhost/ironclaw_test".to_string());
let config: tokio_postgres::Config = database_url.parse().expect("Invalid DATABASE_URL"); let config: tokio_postgres::Config = database_url.parse().expect("Invalid DATABASE_URL");