mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-08-25 14:53:34 +00:00
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:
co-authored by
Claude Opus 4.5
parent
2486065fa7
commit
598dd43b1c
@@ -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
@@ -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
@@ -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
@@ -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_
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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,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.
|
||||||
|
|||||||
@@ -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,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.
|
||||||
|
|||||||
@@ -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,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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -1,4 +1,4 @@
|
|||||||
//! Error types for the NEAR Agent.
|
//! Error types for IronClaw.
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
|||||||
+5
-5
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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?;
|
||||||
|
|||||||
@@ -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
@@ -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(())
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user