1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! # agent-code-lib
//!
//! The complete AI coding agent engine as a reusable library.
//!
//! This crate contains everything needed to build an AI coding agent:
//! LLM providers, tools, the query engine, memory, permissions, and
//! all supporting services. The `agent` CLI binary is a thin wrapper
//! over this library.
//!
//! ## Modules
//!
//! | Module | Purpose |
//! |--------|---------|
//! | [`config`] | Configuration loading and schema (TOML, layered merge) |
//! | [`error`] | Unified error types (`LlmError`, `ToolError`, `ConfigError`) |
//! | [`hooks`] | Lifecycle hooks (pre/post tool use, session events) |
//! | [`llm`] | LLM communication: streaming client, message types, providers, retry |
//! | [`memory`] | Persistent context: project (AGENTS.md) and user memory |
//! | [`permissions`] | Permission system: rules, modes, protected directories |
//! | [`query`] | Agent loop: call LLM → execute tools → compact → repeat |
//! | [`services`] | Cross-cutting: tokens, compaction, sessions, git, MCP, plugins, diagnostics |
//! | [`skills`] | Custom workflow loading from markdown files |
//! | [`state`] | Session state: messages, usage tracking, cost |
//! | [`tools`] | 32 built-in tools and the `Tool` trait for custom tools |
//!
//! ## Quick Example
//!
//! ```rust,no_run
//! use agent_code_lib::config::Config;
//! use agent_code_lib::tools::registry::ToolRegistry;
//! use agent_code_lib::state::AppState;
//!
//! let config = Config::default();
//! let tools = ToolRegistry::default_tools();
//! let state = AppState::new(config);
//! // state.messages, state.total_cost_usd, etc. are now available
//! ```
//!
//! ## Adding a Custom Tool
//!
//! Implement the [`tools::Tool`] trait:
//!
//! ```rust,ignore
//! use async_trait::async_trait;
//! use agent_code_lib::tools::{Tool, ToolContext, ToolResult};
//!
//! struct MyTool;
//!
//! #[async_trait]
//! impl Tool for MyTool {
//! fn name(&self) -> &'static str { "MyTool" }
//! fn description(&self) -> &'static str { "Does something useful" }
//! fn input_schema(&self) -> serde_json::Value {
//! serde_json::json!({"type": "object", "properties": {}})
//! }
//! fn is_read_only(&self) -> bool { true }
//! async fn call(
//! &self,
//! input: serde_json::Value,
//! ctx: &ToolContext,
//! ) -> Result<ToolResult, agent_code_lib::error::ToolError> {
//! Ok(ToolResult { content: "done".into(), is_error: false })
//! }
//! }
//! ```
//!
//! Then register it: `registry.register(Arc::new(MyTool));`