gba_core/lib.rs
1//! GBA Core Execute Engine
2//!
3//! This crate provides the core execution engine for the GBA agent system,
4//! wrapping the Claude Agent SDK for programmatic access to Claude's capabilities.
5//!
6//! # Overview
7//!
8//! The GBA core engine orchestrates AI-assisted workflows by:
9//!
10//! 1. Loading task configurations from the `tasks/` directory
11//! 2. Rendering system and user prompts using Jinja templates
12//! 3. Configuring and invoking the Claude agent
13//! 4. Processing responses and extracting results
14//!
15//! The engine supports two modes of operation:
16//!
17//! - **Single-shot tasks**: Execute predefined tasks with [`Engine::run()`] or
18//! [`Engine::run_stream()`] for streaming output.
19//! - **Interactive sessions**: Multi-turn conversations with [`Session`] for
20//! conversational workflows with history tracking.
21//!
22//! # Architecture
23//!
24//! ```text
25//! ┌─────────────────┐ ┌──────────────────┐ ┌────────────────────┐
26//! │ Task │────▶│ Engine │────▶│ Claude Agent SDK │
27//! └─────────────────┘ └──────────────────┘ └────────────────────┘
28//! │ │
29//! │ ┌───────┴───────┐
30//! │ ▼ ▼
31//! │ ┌──────────────┐ ┌─────────────┐
32//! │ │ run() │ │ session() │
33//! │ │ run_stream()│ │ │
34//! │ └──────────────┘ └──────┬──────┘
35//! │ │
36//! │ ▼
37//! │ ┌─────────────┐
38//! │ │ Session │
39//! │ │ send() │
40//! │ │ send_stream│
41//! │ └─────────────┘
42//! │
43//! ▼
44//! ┌──────────────────┐
45//! │ PromptManager │
46//! │ (gba-pm) │
47//! └──────────────────┘
48//! ```
49//!
50//! # Example: Single-shot Task
51//!
52//! ```no_run
53//! use gba_core::{Engine, EngineConfig, Task, TaskKind};
54//! use gba_pm::PromptManager;
55//! use serde_json::json;
56//!
57//! # async fn example() -> gba_core::Result<()> {
58//! // Create and configure the prompt manager
59//! let mut prompts = PromptManager::new();
60//! prompts.load_dir("./tasks")?;
61//!
62//! // Create the engine
63//! let config = EngineConfig::builder()
64//! .workdir(".")
65//! .prompts(prompts)
66//! .build();
67//! let engine = Engine::new(config)?;
68//!
69//! // Create and run a task
70//! let task = Task::new(
71//! TaskKind::Init,
72//! json!({"repo_path": "."}),
73//! );
74//! let result = engine.run(task).await?;
75//!
76//! println!("Success: {}", result.success);
77//! println!("Output: {}", result.output);
78//! println!("Turns: {}", result.stats.turns);
79//! println!("Cost: ${:.4}", result.stats.cost_usd);
80//! # Ok(())
81//! # }
82//! ```
83//!
84//! # Example: Streaming Task
85//!
86//! ```no_run
87//! use gba_core::{Engine, EngineConfig, Task, TaskKind};
88//! use gba_core::event::PrintEventHandler;
89//! use gba_pm::PromptManager;
90//! use serde_json::json;
91//!
92//! # async fn example() -> gba_core::Result<()> {
93//! let mut prompts = PromptManager::new();
94//! prompts.load_dir("./tasks")?;
95//!
96//! let config = EngineConfig::builder()
97//! .workdir(".")
98//! .prompts(prompts)
99//! .build();
100//! let engine = Engine::new(config)?;
101//!
102//! let task = Task::new(TaskKind::Init, json!({"repo_path": "."}));
103//! let mut handler = PrintEventHandler::new().with_auto_flush();
104//! let result = engine.run_stream(task, &mut handler).await?;
105//! # Ok(())
106//! # }
107//! ```
108//!
109//! # Example: Interactive Session
110//!
111//! ```no_run
112//! use gba_core::{Engine, EngineConfig};
113//! use gba_core::event::PrintEventHandler;
114//! use gba_pm::PromptManager;
115//!
116//! # async fn example() -> gba_core::Result<()> {
117//! let prompts = PromptManager::new();
118//! let config = EngineConfig::builder()
119//! .workdir(".")
120//! .prompts(prompts)
121//! .build();
122//! let engine = Engine::new(config)?;
123//!
124//! // Create a session for multi-turn conversation
125//! let mut session = engine.session(None)?;
126//!
127//! // Send messages
128//! let response = session.send("What is Rust?").await?;
129//! println!("Claude: {}", response);
130//!
131//! // Follow-up (Claude remembers context)
132//! let mut handler = PrintEventHandler::new().with_auto_flush();
133//! let response = session.send_stream("Tell me about ownership", &mut handler).await?;
134//!
135//! // View stats
136//! let stats = session.stats();
137//! println!("Total turns: {}", stats.turns);
138//! println!("Total cost: ${:.4}", stats.cost_usd);
139//!
140//! session.disconnect().await?;
141//! # Ok(())
142//! # }
143//! ```
144//!
145//! # Task Configuration
146//!
147//! Each task type has a corresponding directory under `tasks/` containing:
148//!
149//! - `config.yml` - Task configuration (preset, tools, disallowed tools)
150//! - `system.j2` - System prompt template
151//! - `user.j2` - User prompt template
152//!
153//! Example task configuration:
154//!
155//! ```yaml
156//! preset: true # Use claude_code preset
157//! tools: [] # Empty = all tools allowed
158//! disallowedTools: # Tools to disallow
159//! - Write
160//! - Edit
161//! ```
162
163mod config;
164mod engine;
165mod error;
166pub mod event;
167pub mod git;
168pub mod session;
169mod task;
170
171pub use config::{EngineConfig, TaskConfig};
172pub use engine::Engine;
173pub use error::{EngineError, Result};
174pub use session::{ConversationMessage, Session};
175pub use task::{Artifact, Task, TaskKind, TaskResult, TaskStats};