Skip to main content

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};