初始化提交
Some checks failed
CI / Check / macos-latest (push) Has been cancelled
CI / Check / ubuntu-latest (push) Has been cancelled
CI / Check / windows-latest (push) Has been cancelled
CI / Test / macos-latest (push) Has been cancelled
CI / Test / ubuntu-latest (push) Has been cancelled
CI / Test / windows-latest (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Security Audit (push) Has been cancelled
CI / Secrets Scan (push) Has been cancelled
CI / Install Script Smoke Test (push) Has been cancelled
Some checks failed
CI / Check / macos-latest (push) Has been cancelled
CI / Check / ubuntu-latest (push) Has been cancelled
CI / Check / windows-latest (push) Has been cancelled
CI / Test / macos-latest (push) Has been cancelled
CI / Test / ubuntu-latest (push) Has been cancelled
CI / Test / windows-latest (push) Has been cancelled
CI / Clippy (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Security Audit (push) Has been cancelled
CI / Secrets Scan (push) Has been cancelled
CI / Install Script Smoke Test (push) Has been cancelled
This commit is contained in:
361
CONTRIBUTING.md
Normal file
361
CONTRIBUTING.md
Normal file
@@ -0,0 +1,361 @@
|
||||
# Contributing to OpenFang
|
||||
|
||||
Thank you for your interest in contributing to OpenFang. This guide covers everything you need to get started, from setting up your development environment to submitting pull requests.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Development Environment](#development-environment)
|
||||
- [Building and Testing](#building-and-testing)
|
||||
- [Code Style](#code-style)
|
||||
- [Architecture Overview](#architecture-overview)
|
||||
- [How to Add a New Agent Template](#how-to-add-a-new-agent-template)
|
||||
- [How to Add a New Channel Adapter](#how-to-add-a-new-channel-adapter)
|
||||
- [How to Add a New Tool](#how-to-add-a-new-tool)
|
||||
- [Pull Request Process](#pull-request-process)
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
|
||||
---
|
||||
|
||||
## Development Environment
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- **Rust 1.75+** (install via [rustup](https://rustup.rs/))
|
||||
- **Git**
|
||||
- **Python 3.8+** (optional, for Python runtime and skills)
|
||||
- A supported LLM API key (Anthropic, OpenAI, Groq, etc.) for end-to-end testing
|
||||
|
||||
### Clone and Build
|
||||
|
||||
```bash
|
||||
git clone https://github.com/RightNow-AI/openfang.git
|
||||
cd openfang
|
||||
cargo build
|
||||
```
|
||||
|
||||
The first build takes a few minutes because it compiles SQLite (bundled) and Wasmtime. Subsequent builds are incremental.
|
||||
|
||||
### Environment Variables
|
||||
|
||||
For running integration tests that hit a real LLM, set at least one provider key:
|
||||
|
||||
```bash
|
||||
export GROQ_API_KEY=gsk_... # Recommended for fast, free-tier testing
|
||||
export ANTHROPIC_API_KEY=sk-ant-... # For Anthropic-specific tests
|
||||
```
|
||||
|
||||
Tests that require a real LLM key will skip gracefully if the env var is absent.
|
||||
|
||||
---
|
||||
|
||||
## Building and Testing
|
||||
|
||||
### Build the Entire Workspace
|
||||
|
||||
```bash
|
||||
cargo build --workspace
|
||||
```
|
||||
|
||||
### Run All Tests
|
||||
|
||||
```bash
|
||||
cargo test --workspace
|
||||
```
|
||||
|
||||
The test suite is currently 1,744+ tests. All must pass before merging.
|
||||
|
||||
### Run Tests for a Single Crate
|
||||
|
||||
```bash
|
||||
cargo test -p openfang-kernel
|
||||
cargo test -p openfang-runtime
|
||||
cargo test -p openfang-memory
|
||||
```
|
||||
|
||||
### Check for Clippy Warnings
|
||||
|
||||
```bash
|
||||
cargo clippy --workspace --all-targets -- -D warnings
|
||||
```
|
||||
|
||||
The CI pipeline enforces zero clippy warnings.
|
||||
|
||||
### Format Code
|
||||
|
||||
```bash
|
||||
cargo fmt --all
|
||||
```
|
||||
|
||||
Always run `cargo fmt` before committing. CI will reject unformatted code.
|
||||
|
||||
### Run the Doctor Check
|
||||
|
||||
After building, verify your local setup:
|
||||
|
||||
```bash
|
||||
cargo run -- doctor
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Code Style
|
||||
|
||||
- **Formatting**: Use `rustfmt` with default settings. Run `cargo fmt --all` before every commit.
|
||||
- **Linting**: `cargo clippy --workspace -- -D warnings` must pass with zero warnings.
|
||||
- **Documentation**: All public types and functions must have doc comments (`///`).
|
||||
- **Error Handling**: Use `thiserror` for error types. Avoid `unwrap()` in library code; prefer `?` propagation.
|
||||
- **Naming**:
|
||||
- Types: `PascalCase` (e.g., `OpenFangKernel`, `AgentManifest`)
|
||||
- Functions/methods: `snake_case`
|
||||
- Constants: `SCREAMING_SNAKE_CASE`
|
||||
- Crate names: `openfang-{name}` (kebab-case)
|
||||
- **Dependencies**: Workspace dependencies are declared in the root `Cargo.toml`. Prefer reusing workspace deps over adding new ones. If you need a new dependency, justify it in the PR.
|
||||
- **Testing**: Every new feature must include tests. Use `tempfile::TempDir` for filesystem isolation and random port binding for network tests.
|
||||
- **Serde**: All config structs use `#[serde(default)]` for forward compatibility with partial TOML.
|
||||
|
||||
---
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
OpenFang is organized as a Cargo workspace with 14 crates:
|
||||
|
||||
| Crate | Role |
|
||||
|-------|------|
|
||||
| `openfang-types` | Shared type definitions, taint tracking, manifest signing (Ed25519), model catalog, MCP/A2A config types |
|
||||
| `openfang-memory` | SQLite-backed memory substrate with vector embeddings, usage tracking, canonical sessions, JSONL mirroring |
|
||||
| `openfang-runtime` | Agent loop, 3 LLM drivers (Anthropic/Gemini/OpenAI-compat), 38 built-in tools, WASM sandbox, MCP client/server, A2A protocol |
|
||||
| `openfang-hands` | Hands system (curated autonomous capability packages), 7 bundled hands |
|
||||
| `openfang-extensions` | Integration registry (25 bundled MCP templates), AES-256-GCM credential vault, OAuth2 PKCE |
|
||||
| `openfang-kernel` | Assembles all subsystems: workflow engine, RBAC auth, heartbeat monitor, cron scheduler, config hot-reload |
|
||||
| `openfang-api` | REST/WS/SSE API (Axum 0.8), 76 endpoints, 14-page SPA dashboard, OpenAI-compatible `/v1/chat/completions` |
|
||||
| `openfang-channels` | 40 channel adapters (Telegram, Discord, Slack, WhatsApp, and 36 more), formatter, rate limiter |
|
||||
| `openfang-wire` | OFP (OpenFang Protocol): TCP P2P networking with HMAC-SHA256 mutual authentication |
|
||||
| `openfang-cli` | Clap CLI with daemon auto-detect (HTTP mode vs. in-process fallback), MCP server |
|
||||
| `openfang-migrate` | Migration engine for importing from OpenClaw (and future frameworks) |
|
||||
| `openfang-skills` | Skill system: 60 bundled skills, FangHub marketplace, OpenClaw compatibility, prompt injection scanning |
|
||||
| `openfang-desktop` | Tauri 2.0 native desktop app (WebView + system tray + single-instance + notifications) |
|
||||
| `xtask` | Build automation tasks |
|
||||
|
||||
### Key Architectural Patterns
|
||||
|
||||
- **`KernelHandle` trait**: Defined in `openfang-runtime`, implemented on `OpenFangKernel` in `openfang-kernel`. This avoids circular crate dependencies while enabling inter-agent tools.
|
||||
- **Shared memory**: A fixed UUID (`AgentId(Uuid::from_bytes([0..0, 0x01]))`) provides a cross-agent KV namespace.
|
||||
- **Daemon detection**: The CLI checks `~/.openfang/daemon.json` and pings the health endpoint. If a daemon is running, commands use HTTP; otherwise, they boot an in-process kernel.
|
||||
- **Capability-based security**: Every agent operation is checked against the agent's granted capabilities before execution.
|
||||
|
||||
---
|
||||
|
||||
## How to Add a New Agent Template
|
||||
|
||||
Agent templates live in the `agents/` directory. Each template is a folder containing an `agent.toml` manifest.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Create a new directory under `agents/`:
|
||||
|
||||
```
|
||||
agents/my-agent/agent.toml
|
||||
```
|
||||
|
||||
2. Write the manifest:
|
||||
|
||||
```toml
|
||||
name = "my-agent"
|
||||
version = "0.1.0"
|
||||
description = "A brief description of what this agent does."
|
||||
author = "openfang"
|
||||
module = "builtin:chat"
|
||||
tags = ["category"]
|
||||
|
||||
[model]
|
||||
provider = "groq"
|
||||
model = "llama-3.3-70b-versatile"
|
||||
|
||||
[resources]
|
||||
max_llm_tokens_per_hour = 100000
|
||||
|
||||
[capabilities]
|
||||
tools = ["file_read", "file_list", "web_fetch"]
|
||||
memory_read = ["*"]
|
||||
memory_write = ["self.*"]
|
||||
agent_spawn = false
|
||||
```
|
||||
|
||||
3. Include a system prompt if needed by adding it to the `[model]` section:
|
||||
|
||||
```toml
|
||||
[model]
|
||||
provider = "anthropic"
|
||||
model = "claude-sonnet-4-20250514"
|
||||
system_prompt = """
|
||||
You are a specialized agent that...
|
||||
"""
|
||||
```
|
||||
|
||||
4. Test by spawning:
|
||||
|
||||
```bash
|
||||
openfang agent spawn agents/my-agent/agent.toml
|
||||
```
|
||||
|
||||
5. Submit a PR with the new template.
|
||||
|
||||
---
|
||||
|
||||
## How to Add a New Channel Adapter
|
||||
|
||||
Channel adapters live in `crates/openfang-channels/src/`. Each adapter implements the `ChannelAdapter` trait.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Create a new file: `crates/openfang-channels/src/myplatform.rs`
|
||||
|
||||
2. Implement the `ChannelAdapter` trait (defined in `types.rs`):
|
||||
|
||||
```rust
|
||||
use crate::types::{ChannelAdapter, ChannelMessage, ChannelType};
|
||||
use async_trait::async_trait;
|
||||
|
||||
pub struct MyPlatformAdapter {
|
||||
// token, client, config fields
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ChannelAdapter for MyPlatformAdapter {
|
||||
fn channel_type(&self) -> ChannelType {
|
||||
ChannelType::Custom("myplatform".to_string())
|
||||
}
|
||||
|
||||
async fn start(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Start polling/listening for messages
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send(&self, channel_id: &str, content: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// Send a message back to the platform
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn stop(&mut self) {
|
||||
// Clean shutdown
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. Register the module in `crates/openfang-channels/src/lib.rs`:
|
||||
|
||||
```rust
|
||||
pub mod myplatform;
|
||||
```
|
||||
|
||||
4. Wire it up in the channel bridge (`crates/openfang-api/src/channel_bridge.rs`) so the daemon starts it alongside other adapters.
|
||||
|
||||
5. Add configuration support in `openfang-types` config structs (add a `[channels.myplatform]` section).
|
||||
|
||||
6. Add CLI setup wizard instructions in `crates/openfang-cli/src/main.rs` under `cmd_channel_setup`.
|
||||
|
||||
7. Write tests and submit a PR.
|
||||
|
||||
---
|
||||
|
||||
## How to Add a New Tool
|
||||
|
||||
Built-in tools are defined in `crates/openfang-runtime/src/tool_runner.rs`.
|
||||
|
||||
### Steps
|
||||
|
||||
1. Add the tool implementation function:
|
||||
|
||||
```rust
|
||||
async fn tool_my_tool(input: &serde_json::Value) -> Result<String, String> {
|
||||
let param = input["param"]
|
||||
.as_str()
|
||||
.ok_or("Missing 'param' field")?;
|
||||
|
||||
// Tool logic here
|
||||
Ok(format!("Result: {param}"))
|
||||
}
|
||||
```
|
||||
|
||||
2. Register it in the `execute_tool` match block:
|
||||
|
||||
```rust
|
||||
"my_tool" => tool_my_tool(input).await,
|
||||
```
|
||||
|
||||
3. Add the tool definition to `builtin_tool_definitions()`:
|
||||
|
||||
```rust
|
||||
ToolDefinition {
|
||||
name: "my_tool".to_string(),
|
||||
description: "Description shown to the LLM.".to_string(),
|
||||
input_schema: serde_json::json!({
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"param": {
|
||||
"type": "string",
|
||||
"description": "The parameter description"
|
||||
}
|
||||
},
|
||||
"required": ["param"]
|
||||
}),
|
||||
},
|
||||
```
|
||||
|
||||
4. Agents that need the tool must list it in their manifest:
|
||||
|
||||
```toml
|
||||
[capabilities]
|
||||
tools = ["my_tool"]
|
||||
```
|
||||
|
||||
5. Write tests for the tool function.
|
||||
|
||||
6. If the tool requires kernel access (e.g., inter-agent communication), accept `Option<&Arc<dyn KernelHandle>>` and handle the `None` case gracefully.
|
||||
|
||||
---
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. **Fork and branch**: Create a feature branch from `main`. Use descriptive names like `feat/add-matrix-adapter` or `fix/session-restore-crash`.
|
||||
|
||||
2. **Make your changes**: Follow the code style guidelines above.
|
||||
|
||||
3. **Test thoroughly**:
|
||||
- `cargo test --workspace` must pass (all 1,744+ tests).
|
||||
- `cargo clippy --workspace --all-targets -- -D warnings` must produce zero warnings.
|
||||
- `cargo fmt --all --check` must produce no diff.
|
||||
|
||||
4. **Write a clear PR description**: Explain what changed and why. Include before/after examples if applicable.
|
||||
|
||||
5. **One concern per PR**: Keep PRs focused. A single PR should address one feature, one bug fix, or one refactor -- not all three.
|
||||
|
||||
6. **Review process**: At least one maintainer must approve before merge. Address review feedback promptly.
|
||||
|
||||
7. **CI must pass**: All automated checks must be green before merge.
|
||||
|
||||
### Commit Messages
|
||||
|
||||
Use clear, imperative-mood messages:
|
||||
|
||||
```
|
||||
Add Matrix channel adapter with E2EE support
|
||||
Fix session restore crash on kernel reboot
|
||||
Refactor capability manager to use DashMap
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project follows the [Contributor Covenant Code of Conduct](https://www.contributor-covenant.org/version/2/1/code_of_conduct/). By participating, you agree to uphold a welcoming, inclusive, and harassment-free environment for everyone.
|
||||
|
||||
Please report unacceptable behavior to the maintainers.
|
||||
|
||||
---
|
||||
|
||||
## Questions?
|
||||
|
||||
- Open a [GitHub Discussion](https://github.com/RightNow-AI/openfang/discussions) for questions.
|
||||
- Open a [GitHub Issue](https://github.com/RightNow-AI/openfang/issues) for bugs or feature requests.
|
||||
- Check the [docs/](docs/) directory for detailed guides on specific topics.
|
||||
Reference in New Issue
Block a user