feat: Add hooks, workflow, MCP support and core modules

Phase 2: Hooks System
- Event-driven execution with HookEvent/HookAction types
- HookManager for registration and execution

Phase 3: Multi-Agent Workflow
- Workflow orchestration with dependency graphs
- WorkflowStep with conditions and retry support

Phase 4: MCP (Model Context Protocol) Support
- McpServer for external tool servers
- McpManager for multiple server management

Also includes core modules: cache, error_policy, feature_flags,
git, logger, plugin, retry, rules

662 tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Shunsuke Hayashi 2025-11-22 23:37:14 +09:00
parent 3f6fbeb498
commit 48dfa915c7
27 changed files with 4793 additions and 34 deletions

215
README.md
View file

@ -166,23 +166,218 @@ Agent mode features:
- Iteration limits for safety
- JSON output format option
## Core Library Features
The `miyabi-core` crate provides powerful utilities for building AI applications.
### Git Utilities
```rust
use miyabi_core::{find_git_root, get_current_branch, is_in_git_repo};
// Find repository root
let root = find_git_root()?;
// Get current branch
let branch = get_current_branch(&root)?;
// Check if in git repo
if is_in_git_repo(&path) {
println!("In a git repository");
}
```
### Logger System
```rust
use miyabi_core::{init_logger, LogLevel, LogFormat};
// Initialize with defaults
init_logger();
// Or with custom config
use miyabi_core::LoggerConfig;
let config = LoggerConfig {
level: LogLevel::Debug,
format: LogFormat::Json,
..Default::default()
};
init_logger_with_config(config);
```
### Retry with Backoff
```rust
use miyabi_core::{retry_with_backoff, BackoffRetryConfig};
let config = BackoffRetryConfig::default();
let result = retry_with_backoff(config, || async {
// Your operation that might fail
make_api_call().await
}).await?;
```
### Circuit Breaker
```rust
use miyabi_core::{CircuitBreaker, CircuitState};
let breaker = CircuitBreaker::default();
let result = breaker.call(|| {
Box::pin(async {
// Your operation
Ok::<_, std::io::Error>(())
})
}).await;
// Check state
match breaker.state().await {
CircuitState::Closed => println!("Normal operation"),
CircuitState::Open => println!("Circuit open - blocking calls"),
CircuitState::HalfOpen => println!("Testing recovery"),
}
```
### Rules System (.miyabirules)
Support for project-specific rules via `.miyabirules` files:
```yaml
# .miyabirules
version: 1
rules:
- name: "no-unwrap"
pattern: ".unwrap()"
suggestion: "Use ? operator or proper error handling"
file_extensions: ["rs"]
severity: "warning"
agent_preferences:
codegen:
style: "functional"
error_handling: "result"
```
```rust
use miyabi_core::{RulesLoader, MiyabiRules};
let loader = RulesLoader::new(project_root);
let rules = loader.load_or_default()?;
// Get rules for a file
let applicable = rules.rules_for_file(Path::new("src/main.rs"));
```
### Cache System
```rust
use miyabi_core::{create_llm_cache, create_api_cache, LLMCacheKey};
// LLM response cache (1 hour TTL)
let cache = create_llm_cache();
let key = LLMCacheKey::new("prompt", "model", Some(0.7));
cache.insert(key.clone(), "response".to_string()).await;
let cached = cache.get(&key).await;
// API cache (30 min TTL)
let api_cache = create_api_cache();
```
### Plugin System
```rust
use miyabi_core::{Plugin, PluginManager, PluginMetadata, PluginContext, PluginResult};
use anyhow::Result;
struct MyPlugin;
impl Plugin for MyPlugin {
fn metadata(&self) -> PluginMetadata {
PluginMetadata {
name: "my-plugin".to_string(),
version: "1.0.0".to_string(),
description: Some("My custom plugin".to_string()),
author: None,
}
}
fn init(&mut self) -> Result<()> {
Ok(())
}
fn execute(&self, ctx: &PluginContext) -> Result<PluginResult> {
Ok(PluginResult {
success: true,
message: Some("Done".to_string()),
data: None,
})
}
}
// Register and execute
let manager = PluginManager::new();
manager.register(Box::new(MyPlugin))?;
let result = manager.execute("my-plugin", &PluginContext::default())?;
```
### Feature Flags
```rust
use miyabi_core::{FeatureFlagManager, FeatureFlag};
let flags = FeatureFlagManager::new();
// Simple flag
flags.set_flag("new_feature", true);
if flags.is_enabled("new_feature") {
// Use new feature
}
// With rollout percentage
flags.set_flag_with_options(
"beta_feature",
true,
Some("Beta testing".to_string()),
Some(0.5), // 50% rollout
);
// Load from config
use std::collections::HashMap;
let mut config = HashMap::new();
config.insert("flag1".to_string(), true);
flags.load_from_map(config);
```
## Project Structure
```
miyabi-cli-standalone/
├── crates/
│ ├── miyabi-cli/ # CLI entry point
│ ├── miyabi-core/ # Core library
│ │ ├── agent/ # Agent system
│ │ ├── config.rs # Configuration
│ │ ├── session.rs # Session management
│ ├── miyabi-cli/ # CLI entry point
│ ├── miyabi-core/ # Core library
│ │ ├── agent.rs # Agent system
│ │ ├── anthropic.rs # Anthropic API client
│ │ ├── cache.rs # TTL cache system
│ │ ├── config.rs # Configuration
│ │ ├── error_policy.rs # Circuit breaker
│ │ ├── feature_flags.rs # Feature flag management
│ │ ├── git.rs # Git utilities
│ │ ├── logger.rs # Logging system
│ │ ├── plugin.rs # Plugin system
│ │ ├── retry.rs # Retry with backoff
│ │ ├── rules.rs # .miyabirules support
│ │ ├── session.rs # Session management
│ │ ├── tools.rs # Built-in tools
│ │ └── ...
│ └── miyabi-tui/ # TUI implementation
│ ├── app.rs # Main application
│ ├── views.rs # UI views
│ └── miyabi-tui/ # TUI implementation
│ ├── app.rs # Main application
│ ├── views.rs # UI views
│ └── ...
├── .miyabi/ # Local config
├── Cargo.toml # Workspace config
├── .miyabi/ # Local config
├── Cargo.toml # Workspace config
└── README.md
```