mirror of
https://github.com/outbackdingo/optimclaw.git
synced 2026-09-01 17:19:24 +00:00
refactor: decouple modules, add resilience middleware and state bus [skip-regression-check]
Break circular dependencies between agent, db, channels, and context modules by extracting shared domain types to neutral locations: - Extract routine types to src/models/routine.rs - Extract ToolFailureRecord to src/models/tool_failure.rs - Move SseEvent to src/events.rs as DomainEvent - Move HttpInterceptor to src/observability/ - Move truncate_preview to src/util.rs Add generic resilience middleware (src/resilience/): - ErrorClassifier, RetryLayer, CircuitBreakerLayer, HealthTracker Add state invalidation bus (src/state_bus.rs) Add boundary chaos tests (tests/boundary_chaos.rs) Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
757d24bd90
commit
b04d14b114
+5
-43
@@ -51,32 +51,10 @@ pub struct MemorySnapshotEntry {
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
/// A recorded HTTP request/response pair.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HttpExchange {
|
||||
pub request: HttpExchangeRequest,
|
||||
pub response: HttpExchangeResponse,
|
||||
}
|
||||
|
||||
/// The request side of an HTTP exchange.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HttpExchangeRequest {
|
||||
pub method: String,
|
||||
pub url: String,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub headers: Vec<(String, String)>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub body: Option<String>,
|
||||
}
|
||||
|
||||
/// The response side of an HTTP exchange.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct HttpExchangeResponse {
|
||||
pub status: u16,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub headers: Vec<(String, String)>,
|
||||
pub body: String,
|
||||
}
|
||||
// Re-export HTTP exchange types from their canonical location in observability.
|
||||
pub use crate::observability::http_interceptor::{
|
||||
HttpExchange, HttpExchangeRequest, HttpExchangeResponse, HttpInterceptor,
|
||||
};
|
||||
|
||||
/// A single step in the trace.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -144,23 +122,7 @@ pub struct ExpectedToolResult {
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
// ── HTTP interceptor ───────────────────────────────────────────────
|
||||
|
||||
/// Trait for intercepting HTTP requests from tools.
|
||||
///
|
||||
/// During recording, the interceptor captures exchanges after the real
|
||||
/// request completes. During replay, it short-circuits with a recorded response.
|
||||
#[async_trait]
|
||||
pub trait HttpInterceptor: Send + Sync + std::fmt::Debug {
|
||||
/// Called before making an HTTP request.
|
||||
///
|
||||
/// Return `Some(response)` to short-circuit (replay mode).
|
||||
/// Return `None` to let the real request proceed (recording mode).
|
||||
async fn before_request(&self, request: &HttpExchangeRequest) -> Option<HttpExchangeResponse>;
|
||||
|
||||
/// Called after a real HTTP request completes (recording mode only).
|
||||
async fn after_response(&self, request: &HttpExchangeRequest, response: &HttpExchangeResponse);
|
||||
}
|
||||
// ── HTTP interceptor impls ─────────────────────────────────────────
|
||||
|
||||
/// Records HTTP exchanges during a live session.
|
||||
#[derive(Debug)]
|
||||
|
||||
Reference in New Issue
Block a user