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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
// ABOUTME: Standalone LLM runner library wrapping AI CLI tools and ACP as providers
// ABOUTME: Re-exports runners, agent loop, fallback chains, metrics, quality gates, MCP bridge, and structured output
//
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2026 dravr.ai
//! # Embacle — LLM Runners
//!
//! Standalone library providing pluggable [`LlmProvider`](types::LlmProvider)
//! implementations that delegate to CLI tools (Claude Code, Copilot, Cursor Agent,
//! `OpenCode`, Gemini, Codex, Goose, Cline, Continue, Warp, Kiro, Kilo Code), an HTTP API client
//! (OpenAI-compatible), and ACP (Copilot Headless) for LLM completions.
//!
//! CLI runners wrap a binary, build prompts from [`ChatMessage`](types::ChatMessage)
//! sequences, parse JSON output, and manage session continuity. The Copilot Headless
//! runner communicates via NDJSON-framed JSON-RPC with `copilot --acp`.
//!
//! Two companion binary crates build on this library:
//! - **`embacle-server`** — OpenAI-compatible REST API + MCP Streamable HTTP on a single port
//! - **`embacle-mcp`** — standalone MCP server over stdio or HTTP
//!
//! ## Quick Start
//!
//! ```rust,no_run
//! use std::path::PathBuf;
//! use embacle::{ClaudeCodeRunner, RunnerConfig};
//! use embacle::types::{ChatMessage, ChatRequest, LlmProvider};
//!
//! # async fn example() -> Result<(), embacle::types::RunnerError> {
//! let config = RunnerConfig::new(PathBuf::from("claude"));
//! let runner = ClaudeCodeRunner::new(config);
//! let request = ChatRequest::new(vec![ChatMessage::user("Hello!")]);
//! let response = runner.complete(&request).await?;
//! println!("{}", response.content);
//! # Ok(())
//! # }
//! ```
//!
//! ## Fallback Chains
//!
//! Try multiple providers in order — first success wins:
//!
//! ```rust,no_run
//! use std::path::PathBuf;
//! use embacle::{ClaudeCodeRunner, CopilotRunner, RunnerConfig};
//! use embacle::fallback::FallbackProvider;
//! use embacle::types::{ChatMessage, ChatRequest, LlmProvider};
//!
//! # async fn example() -> Result<(), embacle::types::RunnerError> {
//! let claude = ClaudeCodeRunner::new(RunnerConfig::new(PathBuf::from("claude")));
//! let copilot = CopilotRunner::new(RunnerConfig::new(PathBuf::from("copilot"))).await;
//!
//! let provider = FallbackProvider::new(vec![
//! Box::new(claude),
//! Box::new(copilot),
//! ])?;
//!
//! // If claude fails, copilot handles it — same interface
//! let request = ChatRequest::new(vec![ChatMessage::user("Hello!")]);
//! let response = provider.complete(&request).await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## Structured Output
//!
//! Schema-validated JSON from any provider, with retry on validation failure:
//!
//! ```rust,no_run
//! use embacle::structured_output::{request_structured_output, StructuredOutputRequest};
//! use embacle::types::{ChatMessage, ChatRequest, LlmProvider};
//! use serde_json::json;
//!
//! # async fn example(runner: &dyn LlmProvider) -> Result<(), embacle::types::RunnerError> {
//! let schema = json!({
//! "type": "object",
//! "properties": {
//! "city": {"type": "string"},
//! "temperature": {"type": "number"}
//! },
//! "required": ["city", "temperature"]
//! });
//!
//! let request = ChatRequest::new(vec![
//! ChatMessage::user("What's the weather in Paris?"),
//! ]);
//!
//! let data = request_structured_output(
//! runner,
//! &StructuredOutputRequest { request, schema, max_retries: 2 },
//! ).await?;
//!
//! assert!(data["city"].is_string());
//! assert!(data["temperature"].is_number());
//! # Ok(())
//! # }
//! ```
//!
//! ## Modules
//!
//! ### Core
//!
//! - [`types`] — `LlmProvider` trait, messages, requests, responses, errors
//! - [`config`] — `RunnerConfig`, `CliRunnerType` enum
//! - [`factory`] — Runner factory, provider parsing, `ALL_PROVIDERS` constant
//!
//! ### Higher-Level Features
//!
//! - [`agent`] — Multi-turn agent loop with configurable tool calling
//! - [`fallback`] — Ordered provider failover chains
//! - [`metrics`] — Latency, token, and error tracking decorator
//! - [`quality_gate`] — Response validation with retry on refusal
//! - [`structured_output`] — Schema-enforced JSON extraction from any provider
//! - [`tool_simulation`] — XML-based text tool calling for CLI runners without native function calling
//! - [`mcp_tool_bridge`] — MCP tool definitions to text-tool-simulation bridge
//! - [`capability_guard`] — Request/provider capability validation
//! - [`guardrail`] — Pluggable pre/post request validation middleware
//! - [`cache`] — Response caching with TTL and capacity limits
//!
//! ### Runner Infrastructure
//!
//! - [`auth`] — Readiness and authentication checking
//! - [`discovery`] — Automatic binary detection on the host
//! - [`process`] — Subprocess spawning with timeout and output limits
//! - [`sandbox`] — Environment variable whitelisting and working directory control
//! - [`prompt`] — Prompt building from `ChatMessage` slices
//! - [`compat`] — Version compatibility and capability detection
//! - [`container`] — Container-based execution backend
//!
//! ### CLI Runners
//!
//! - [`claude_code`] — Claude Code CLI runner
//! - [`copilot`] — GitHub Copilot CLI runner
//! - [`cursor_agent`] — Cursor Agent CLI runner
//! - [`opencode`] — `OpenCode` CLI runner
//! - [`gemini_cli`] — Gemini CLI runner
//! - [`codex_cli`] — Codex CLI runner
//! - [`goose_cli`] — Goose CLI runner
//! - [`cline_cli`] — Cline CLI runner
//! - [`continue_cli`] — Continue CLI runner
//! - [`warp_cli`] — Warp terminal `oz` CLI runner
//! - [`kiro_cli`] — Kiro CLI runner
//! - [`kilo_cli`] — Kilo Code CLI runner
//!
//! ### Feature-Flagged Runners
//!
//! - `openai_api` — OpenAI-compatible HTTP API client (requires `openai-api` feature)
//! - `copilot_headless` — GitHub Copilot Headless ACP runner (requires `copilot-headless` feature)
/// Core types: traits, messages, requests, responses, and errors
/// Configurable agent loop with multi-turn tool calling
/// Auth readiness checking for CLI runners
/// Response caching decorator
/// Request/provider capability validation
/// Claude Code CLI runner
/// Shared base struct and macro for CLI runner boilerplate
/// Cline CLI runner
/// Codex CLI runner
/// Version compatibility and capability detection
/// Shared configuration types for CLI runners
/// Container-based execution backend
/// Continue CLI runner
/// GitHub Copilot CLI runner
/// Cursor Agent CLI runner
/// Binary auto-detection and discovery
/// Runner factory, provider parsing, and provider enumeration
/// Provider fallback chains
/// Gemini CLI runner
/// Goose CLI runner
/// Pluggable guardrail middleware for request/response validation
/// Kilo Code CLI runner
/// Kiro CLI runner
/// MCP tool definition to text-tool-simulation bridge
/// Cost/latency normalization decorator
/// `OpenCode` CLI runner
/// Subprocess spawning with safety limits
/// Prompt construction from `ChatMessage` sequences
/// Response quality validation with retry
/// Environment sandboxing and tool policy
/// Stream wrapper for child process lifecycle management
/// Schema-enforced JSON output from any provider
/// Text-based tool simulation for CLI runners without native function calling
/// Warp terminal `oz` CLI runner
// Config file module (behind feature flag)
/// TOML-based declarative configuration file loading
// OpenAI API module (behind feature flag)
/// OpenAI-compatible HTTP API client runner
// Copilot Headless modules (behind feature flag)
/// Configuration for the Copilot Headless (ACP) provider
/// Configuration types for the Copilot Headless provider
// C FFI bindings (behind feature flag)
// Re-export the runner structs for ergonomic access
pub use ;
pub use ProviderReadiness;
pub use ;
pub use validate_capabilities;
pub use ClaudeCodeRunner;
pub use CliRunnerBase;
pub use ClineCliRunner;
pub use CodexCliRunner;
pub use CliCapabilities;
pub use ;
pub use ;
pub use ContinueCliRunner;
pub use ;
pub use CursorAgentRunner;
pub use ;
pub use ;
pub use ;
pub use GeminiCliRunner;
pub use GooseCliRunner;
pub use ;
pub use KiloCliRunner;
pub use KiroCliRunner;
pub use ;
pub use ;
pub use OpenCodeRunner;
pub use ;
pub use ;
pub use WarpCliRunner;
// Core tool calling type re-exports
pub use ;
// Tool simulation re-exports
pub use ;
// Config file re-exports (behind feature flag)
pub use ;
// OpenAI API re-exports (behind feature flag)
pub use ;
// Copilot Headless re-exports (behind feature flag)
pub use ;
pub use ;