Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 26 additions & 23 deletions src/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,40 @@
//!
//! # Traits
//!
//! | Trait | Purpose |
//! |--------------------|-------------------------------------------------------|
//! | [`AgentObserver`] | Lifecycle event hooks for monitoring agents |
//! | Trait | Purpose |
//! |--------------------|-----------------------------------------------------|
//! | [`AgentCore`] | Main lifecycle trait for all agent types |
//! | [`AgentMemory`] | Interface for agent memory backends |
//! | [`AgentObserver`] | Lifecycle event hooks for monitoring agents |
//!
//! # Supporting Types
//!
//! | Type | Purpose |
//! |-------------------|-------------------------------------------------------|
//! | [`AgentError`] | Unified error type for all framework operations |
//! | [`AgentConfig`] | Configuration for an agent session |
//! | [`AgentState`] | Lifecycle state machine for agents |
//! | [`TurnResult`] | Result of a single agent turn |
//! | [`SessionResult`] | Summary of a complete agent session |
//! | [`StopReason`] | Why the API stopped generating |
//! | [`ToolCall`] | A tool call requested by the agent |
//! | [`ToolCallResult`]| Result of a single tool execution |
//! | [`Correction`] | Correction produced by the reflection system |
//! | [`CompactReason`] | Why context compaction was triggered |
//! | [`CorrectionType`]| Category of fix strategy for a correction |
//! | [`CorrectionResult`]| Outcome of applying a correction |
//! | Type | Purpose |
//! |-----------------------|---------------------------------------------------|
//! | [`AgentConfig`] | Configuration for an agent session |
//! | [`AgentError`] | Unified error type for all framework operations |
//! | [`AgentState`] | Lifecycle state machine for agents |
//! | [`Correction`] | Correction produced by the reflection system |
//! | [`CompactReason`] | Why context compaction was triggered |
//! | [`CorrectionResult`] | Outcome of applying a correction |
//! | [`ConsolidationStats`]| Statistics from a memory consolidation pass |
//! | [`CorrectionType`] | Category of fix strategy for a correction |
//! | [`MemoryCategory`] | Category of a memory entry |
//! | [`MemoryEntry`] | A single memory entry with metadata |
//! | [`StopReason`] | Why the API stopped generating |
//! | [`SessionResult`] | Summary of a complete agent session |
//! | [`ToolCall`] | A tool call requested by the agent |
//! | [`ToolCallResult`] | Result of a single tool execution |
//! | [`TurnResult`] | Result of a single agent turn |

pub mod agent_core;
pub mod agent_memory;
pub mod agent_observer;
pub mod error;
// TODO: add remaining modules
// pub mod agent_core;
// pub mod agent_memory;
pub mod types;

pub use agent_core::*;
pub use agent_memory::*;
pub use agent_observer::*;
pub use error::*;
// TODO: add remaining pub use re-exports as modules are migrated
// pub use agent_core::*;
// pub use agent_memory::*;
pub use types::*;
128 changes: 128 additions & 0 deletions src/core/agent_core.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
//! Agent core trait — the main lifecycle interface for agents.
//!
//! This trait defines the fundamental operations every agent must support.
//! Different agent types (chat, coding, research) implement this trait
//! while sharing the framework's infrastructure (managers, observers, etc.).
//!
//! # Lifecycle
//!
//! ```text
//! initialize(config)
//! → process_turn(input) [repeated]
//! → process_turn(input)
//! → ...
//! → should_continue() → false
//! finalize()
//! ```
//!
//! # Implementing
//!
//! At a minimum you must provide [`initialize`](AgentCore::initialize),
//! [`process_turn`](AgentCore::process_turn),
//! [`should_continue`](AgentCore::should_continue),
//! [`finalize`](AgentCore::finalize),
//! [`state`](AgentCore::state), and
//! [`cancel`](AgentCore::cancel).

use crate::core::error::AgentError;
use crate::core::types::{AgentConfig, AgentState, SessionResult, TurnResult};
use std::future::Future;
use std::pin::Pin;

/// The core agent lifecycle trait.
///
/// Implement this trait to create a new type of agent. The framework
/// provides shared infrastructure for context management, tool execution,
/// reflection, and observability, so implementations only need to define
/// the core processing logic.
///
/// # Lifecycle
///
/// ```text
/// initialize(config)
/// → process_turn(input) [repeated]
/// → process_turn(input)
/// → ...
/// → should_continue() → false
/// finalize()
/// ```
///
/// # Example
///
/// ```rust,ignore
/// use loopctl::core::agent_core::AgentCore;
/// use loopctl::core::error::AgentError;
/// use loopctl::core::types::{AgentConfig, AgentState, SessionResult, TurnResult};
///
/// struct MyAgent {
/// state: MyState,
/// }
///
/// impl AgentCore for MyAgent {
/// fn initialize<'a>(&'a mut self, config: &'a AgentConfig) -> Pin<Box<dyn Future<Output = Result<(), AgentError>> + Send + 'a>> {
/// Box::pin(async { Ok(()) })
/// }
/// fn process_turn<'a>(&'a mut self, input: &'a str) -> Pin<Box<dyn Future<Output = Result<TurnResult, AgentError>> + Send + 'a>> {
/// Box::pin(async { Ok(TurnResult::completed("Done!")) })
/// }
/// fn should_continue(&self) -> bool {
/// !self.state.is_complete
/// }
/// fn finalize<'a>(&'a mut self) -> Pin<Box<dyn Future<Output = Result<SessionResult, AgentError>> + Send + 'a>> {
/// Box::pin(async { Ok(SessionResult::success(self.state.session_id)) })
/// }
/// fn state(&self) -> AgentState {
/// AgentState::Idle
/// }
/// fn cancel(&self) {}
/// }
/// ```
pub trait AgentCore: Send + Sync {
/// Initialize the agent with the given configuration.
///
/// Called once before any turns are processed. Use this to set up
/// internal state, validate configuration, and prepare resources.
fn initialize<'a>(
&'a mut self,
config: &'a AgentConfig,
) -> Pin<Box<dyn Future<Output = Result<(), AgentError>> + Send + 'a>>;

/// Process a single user message / turn.
///
/// This is the main entry point for agent logic. It receives the user's
/// input and returns a [`TurnResult`] describing what happened.
fn process_turn<'a>(
&'a mut self,
input: &'a str,
) -> Pin<Box<dyn Future<Output = Result<TurnResult, AgentError>> + Send + 'a>>;

/// Check whether the agent should continue processing turns.
///
/// Called after each turn. Return `false` to end the session.
fn should_continue(&self) -> bool;

/// Finalize the agent session and produce a summary.
///
/// Called once after the last turn. Use this to clean up resources
/// and produce a final [`SessionResult`].
fn finalize<'a>(
&'a mut self,
) -> Pin<Box<dyn Future<Output = Result<SessionResult, AgentError>> + Send + 'a>>;

/// Get the current state of the agent.
///
/// Used by the framework to drive the state machine and by observers
/// to report status.
fn state(&self) -> AgentState;

/// Cancel the agent's current operation.
///
/// Implementations must use thread-safe interior mutability (e.g.
/// [`AtomicBool`](std::sync::atomic::AtomicBool), `Mutex<bool>`) to
/// store the cancellation flag, since this method takes `&self`. The
/// flag should be set in a non-blocking fashion so that
/// [`process_turn`](AgentCore::process_turn) and
/// [`should_continue`](AgentCore::should_continue) can observe it
/// and return promptly across threads.
fn cancel(&self);
}
Loading
Loading