Skip to main content

heartbit_core/
lib.rs

1//! # heartbit-core
2//!
3//! The Rust agentic framework — agents, tools, LLM providers, memory, evaluation.
4//!
5//! Documentation lands here as the crate's docs.rs preamble. The README
6//! is rendered above this on docs.rs.
7
8#![deny(missing_docs)]
9
10// Modules are added one at a time as subsequent tasks move them in.
11pub mod agent;
12pub mod auth;
13pub mod browser;
14pub mod channel;
15pub mod codegen;
16pub mod config;
17pub mod error;
18pub mod eval;
19pub mod execution_context;
20pub mod http;
21pub mod knowledge;
22pub mod llm;
23pub mod lsp;
24pub mod memory;
25pub mod persona;
26pub mod sandbox;
27#[cfg(unix)]
28pub mod signal;
29pub mod skill;
30pub mod store;
31pub mod template;
32pub mod tool;
33pub(crate) mod types;
34pub(crate) mod util;
35pub mod workspace;
36
37// --- Agent re-exports ---
38pub use agent::audit::{AuditMode, AuditRecord, AuditTrail, InMemoryAuditTrail};
39pub use agent::batch::{BatchConfig, BatchExecutor, BatchExecutorBuilder, BatchResult};
40pub use agent::blackboard::{Blackboard, InMemoryBlackboard};
41pub use agent::cache::ResponseCache;
42pub use agent::context::ContextStrategy;
43pub use agent::context_recall::{ContextRecallStore, RecallHit};
44pub use agent::dag::{DagAgent, DagAgentBuilder};
45pub use agent::debate::{DebateAgent, DebateAgentBuilder};
46pub use agent::evaluator::{EvaluatorOptimizerAgent, EvaluatorOptimizerAgentBuilder};
47pub use agent::events::{AgentEvent, OnEvent};
48pub use agent::goal::{GoalCondition, GoalSlot, GoalVerdict};
49pub use agent::guardrail::{GuardAction, Guardrail};
50#[allow(deprecated)]
51pub use agent::guardrails::ContentFenceGuardrail;
52pub use agent::guardrails::tool_policy::{InputConstraint, ToolRule};
53pub use agent::guardrails::{
54    ActionBudgetGuardrail, ActionBudgetGuardrailBuilder, BehaviorRule, BehavioralMonitorGuardrail,
55    BehavioralMonitorGuardrailBuilder, BudgetRule, ConditionalGuardrail, GuardrailChain,
56    GuardrailMode, InjectionClassifierGuardrail, LlmJudgeGuardrail, LlmJudgeGuardrailBuilder,
57    PiiAction, PiiDetector, PiiGuardrail, ScopeGuard, SecretAction, SecretScannerGuardrail,
58    SecretScannerGuardrailBuilder, SensorSecurityGuardrail, ToolPolicyGuardrail, WarnToDeny,
59};
60pub use agent::handoff::{HandoffRunner, HandoffRunnerBuilder, make_handoff_tool};
61pub use agent::instructions::{
62    discover_instruction_files, load_instructions, prepend_instructions,
63};
64pub use agent::mixture::{MixtureOfAgentsAgent, MixtureOfAgentsAgentBuilder};
65pub use agent::observability::ObservabilityMode;
66pub use agent::orchestrator::{
67    Orchestrator, OrchestratorBuilder, SubAgentConfig, SubAgentContextConfig,
68};
69pub use agent::permission::{
70    LearnedPermissions, PermissionAction, PermissionRule, PermissionRuleset,
71};
72pub use agent::prompts::MULTI_AGENT_COLLAB_PROMPT;
73pub use agent::pruner::SessionPruneConfig;
74pub use agent::routing::{
75    AgentCapability, ComplexitySignals, KeywordRoutingStrategy, RoutingDecision, RoutingMode,
76    RoutingStrategy, TaskComplexityAnalyzer, resolve_routing_mode, should_escalate,
77};
78pub use agent::tenant_tracker::{TenantTokenState, TenantTokenTracker, TokenReservation};
79pub use agent::tool_filter::ToolProfile;
80pub use agent::voting::{VoteResult, VotingAgent, VotingAgentBuilder};
81pub use agent::workflow::{
82    LoopAgent, LoopAgentBuilder, ParallelAgent, ParallelAgentBuilder, SequentialAgent,
83    SequentialAgentBuilder, WorkflowRouter, WorkflowType,
84};
85pub use agent::workflow_tool::{
86    RunWorkflowTool, WorkflowRecipe, WorkflowRegistry, default_registry,
87};
88pub use agent::{
89    AgentOutput, AgentRunner, AgentRunnerBuilder, DelegationNudge, InterruptHandle, OnInput,
90};
91// Deterministic verify→repair: runs a build/test command and reports
92// VERIFY_RESULT: PASS/FAIL — reusable beyond the codegen builder so any agent can
93// self-verify (pair with a GoalCondition for an autonomous repair loop, or the
94// tool + a prompt nudge for interactive self-correction).
95pub use codegen::verify::VerifyCommandTool;
96
97// --- Dynamic-workflow combinator core (P1) ---
98// The free functions (`agent`, `parallel`, `pipeline`, `phase`, `log`, `thunk`)
99// are reached via the `flow` namespace because `flow::agent` would collide with
100// the `agent` module at the crate root. The data types are re-exported at root
101// for discoverability, matching the workflow-agent re-exports above.
102pub use agent::flow;
103pub use agent::flow::agent::{
104    AgentCall, AgentOpts, Isolation, NoSchema, RawJson, StructuredSchema,
105};
106pub use agent::flow::ctx::{ControlBreach, ProviderFactory, WorkflowCtx, WorkflowCtxBuilder};
107pub use agent::flow::event::{OnWorkflowEvent, PhaseGuard, WorkflowEvent};
108pub use agent::flow::journal::{ResumeMode, RunJournal};
109pub use agent::flow::parallel::BoxThunk;
110pub use agent::flow::pipeline::PipelineBuilder;
111pub use agent::flow::progress::{PhaseProgress, ProgressTracker, RunProgress};
112
113// --- Error re-exports ---
114pub use error::Error;
115
116// --- Execution context re-exports ---
117pub use execution_context::{AuditSink, CredentialResolver, ExecutionContext, Secret};
118
119// --- Eval re-exports ---
120pub use eval::{
121    CaseComparison, CostScorer, EvalCase, EvalComparison, EvalResult, EvalRunner, EvalScorer,
122    EvalSummary, EventCollector, KeywordScorer, LatencyScorer, SafetyScorer, ScorerResult,
123    SimilarityScorer, ToolCallCountScorer, TrajectoryScorer, build_eval_agent, clear_events,
124};
125
126// --- Sandbox re-exports ---
127pub use sandbox::{CorePathPolicy, CorePathPolicyBuilder};
128
129// --- Knowledge re-exports ---
130pub use knowledge::in_memory::InMemoryKnowledgeBase;
131pub use knowledge::{Chunk, DocumentSource, KnowledgeBase, KnowledgeQuery, SearchResult};
132
133// --- LLM re-exports ---
134pub use llm::ApprovalDecision;
135pub use llm::LlmProvider;
136pub use llm::OnApproval;
137pub use llm::OnReasoning;
138pub use llm::OnText;
139pub use llm::anthropic::AnthropicProvider;
140pub use llm::cascade::{CascadingProvider, ConfidenceGate, HeuristicGate};
141pub use llm::circuit::{
142    CircuitBreakerProvider, CircuitConfig, CircuitKey, CircuitPermit, CircuitTracker,
143    ProviderCircuit, is_circuit_failure,
144};
145pub use llm::error_class::{ErrorClass, classify as classify_error};
146pub use llm::gemini::GeminiProvider;
147pub use llm::openai_compat::{AuthStyle, OpenAiCompatProvider};
148pub use llm::openrouter::OpenRouterProvider;
149pub use llm::pricing::estimate_cost;
150pub use llm::registry::{
151    ProviderInfo, detect_available_provider, get_provider, known_providers as known_llm_providers,
152    resolve_api_key,
153};
154pub use llm::retry::{OnRetry, RetryConfig, RetryingProvider};
155pub use llm::types::{
156    CompletionRequest, CompletionResponse, ContentBlock, Message, ReasoningEffort, Role,
157    StopReason, TokenUsage, ToolCall, ToolChoice, ToolDefinition, ToolResult,
158};
159pub use llm::{BoxedProvider, DynLlmProvider};
160
161// --- LSP re-exports ---
162pub use lsp::{Diagnostic as LspDiagnostic, LspManager};
163
164// --- Memory re-exports ---
165pub use memory::Confidentiality;
166pub use memory::consolidation::{
167    ConsolidationPipeline, ConsolidationResult, DEFAULT_SUMMARY_MAX_TOKENS, cluster_by_keywords,
168};
169pub use memory::embedding::{EmbeddingMemory, EmbeddingProvider, NoopEmbedding, OpenAiEmbedding};
170pub use memory::hybrid::{cosine_similarity, rrf_fuse};
171pub use memory::in_memory::InMemoryStore;
172pub use memory::namespaced::NamespacedMemory;
173pub use memory::pruning::{DEFAULT_MIN_STRENGTH, default_min_age, prune_weak_entries};
174pub use memory::reflection::ReflectionTracker;
175pub use memory::scoring::ScoringWeights;
176pub use memory::{Memory, MemoryEntry, MemoryQuery, MemoryType};
177
178// --- Persona re-exports ---
179pub use persona::{
180    AuthorshipMode, Persona, PersonaExpansion, PersonaParams, PersonaRegistry, ReviewSpec,
181    TopicContextProvider, TriggerSpec,
182};
183
184// --- Tool re-exports ---
185#[cfg(feature = "a2a")]
186pub use tool::a2a::A2aClient;
187pub use tool::advisor::AdvisorTool;
188#[cfg(feature = "ghost-domain-config")]
189pub use tool::builtins::TwitterCredentials;
190pub use tool::builtins::handoff::SessionHandoffTool;
191pub use tool::builtins::{
192    BuiltinToolsConfig, FileTracker, OnQuestion, Question, QuestionOption, QuestionRequest,
193    QuestionResponse, TodoPriority, TodoStatus, TodoStore, ToolRisk, builtin_tools,
194};
195pub use tool::handoff::{HandoffContextMode, HandoffTarget, HandoffTool};
196pub use tool::mcp::{
197    AuthProvider, AuthResolver, DirectAuthProvider, DynamicAuthResolver, McpClient,
198    McpPromptArgument, McpPromptDef, McpPromptMessage, McpPromptMessageContent, McpResourceContent,
199    McpResourceDef, McpRoot, McpTransportPool, SamplingContent, SamplingHandler, SamplingMessage,
200    SamplingModelHint, SamplingModelPreferences, SamplingRequest, StaticAuthProvider,
201    StaticAuthResolver, TokenExchangeAuthProvider,
202};
203pub use tool::mcp_presets::{
204    McpPreset, check_preset_env, connect_preset, connect_preset_with_args, known_presets,
205    resolve_preset,
206};
207pub use tool::mcp_server::{McpServer, McpServerConfig, ServerResource};
208pub use tool::set_goal::SetGoalTool;
209pub use tool::set_scope::SetScopeTool;
210pub use tool::{Tool, ToolOutput, validate_tool_input};
211
212// --- Workspace re-exports ---
213pub use workspace::Workspace;
214
215// --- Benchmark-only helpers ---
216//
217// Thin wrappers over crate-internal hot paths exposed exclusively for
218// criterion benchmarks under `crates/heartbit-core/benches/`. Gated
219// behind the `bench-internals` feature so downstream consumers cannot
220// accidentally rely on this surface; the wrappers allocate their own
221// internal state and never leak crate-private types across the boundary.
222#[cfg(feature = "bench-internals")]
223#[doc(hidden)]
224pub mod __bench {
225    #![allow(missing_docs)]
226
227    /// Feed `chunk` to a fresh `SseParser` and return the number of
228    /// emitted events. Used to benchmark per-chunk allocation overhead
229    /// in the Anthropic SSE hot path (P-LLM-2, P-LLM-14).
230    pub fn sse_parse_chunk(chunk: &str) -> usize {
231        let mut parser = crate::llm::anthropic::SseParser::new();
232        parser.feed(chunk).len()
233    }
234
235    /// Mock LLM provider that returns the same canned response on every
236    /// call (no draining). Designed for the agent-ReAct-turn bench
237    /// (Bench-NEW-1 in `tasks/perf-audit-v2-bench-gaps.md`) where each
238    /// criterion sample needs a fresh `execute()` against an identical
239    /// provider response — different from the test-only `MockProvider`
240    /// which drains a queue.
241    pub struct BenchMockProvider {
242        response: crate::llm::types::CompletionResponse,
243    }
244
245    impl BenchMockProvider {
246        /// Build a provider that always returns a single text response.
247        pub fn new_text(text: impl Into<String>) -> Self {
248            use crate::llm::types::{CompletionResponse, ContentBlock, StopReason, TokenUsage};
249            Self {
250                response: CompletionResponse {
251                    content: vec![ContentBlock::Text { text: text.into() }],
252                    stop_reason: StopReason::EndTurn,
253                    reasoning: None,
254                    usage: TokenUsage {
255                        input_tokens: 64,
256                        output_tokens: 16,
257                        ..Default::default()
258                    },
259                    model: None,
260                },
261            }
262        }
263    }
264
265    impl crate::llm::LlmProvider for BenchMockProvider {
266        async fn complete(
267            &self,
268            _request: crate::llm::types::CompletionRequest,
269        ) -> Result<crate::llm::types::CompletionResponse, crate::error::Error> {
270            Ok(self.response.clone())
271        }
272
273        fn model_name(&self) -> Option<&str> {
274            Some("bench-mock")
275        }
276    }
277}