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
//! Runtime error types.
use thiserror::Error;
use super::run::RunId;
/// Errors that can occur during runtime execution.
///
/// Covers provider resolution, session management, run lifecycle, policy
/// enforcement, tool execution, storage, snapshot recovery, doom-loop
/// detection, and input admission failures.
#[derive(Debug, Error)]
pub enum RuntimeError {
/// The requested provider was not found in the registry.
#[error("provider not found: {0}")]
ProviderNotFound(String),
/// The requested session does not exist.
#[error("session not found: {0}")]
SessionNotFound(uuid::Uuid),
/// The requested run was not found.
#[error("run not found: {0}")]
RunNotFound(RunId),
/// Operation cannot proceed because the run is in an unexpected state.
#[error("invalid run state: expected {expected}, got {actual}")]
InvalidRunState {
/// Expected state descriptor.
expected: String,
/// Actual state descriptor.
actual: String,
},
/// The run exceeded the maximum allowed model call iterations.
#[error("iteration limit exceeded: {0}")]
IterationLimitExceeded(usize),
/// Accumulated token usage exceeded the configured budget.
#[error("token budget exceeded: {used} > {limit}")]
TokenBudgetExceeded {
/// Tokens consumed so far.
used: usize,
/// Maximum allowed tokens.
limit: usize,
},
/// Estimated context size exceeds the model's maximum context window.
#[error("context length exceeded: model context {context}, estimated {estimated}")]
ContextOverflow {
/// Model's maximum context window size.
context: u32,
/// Estimated token usage for the full context.
estimated: usize,
},
/// Session is locked by another concurrent run.
#[error("session busy: {0}")]
SessionBusy(uuid::Uuid),
/// A tool call exceeded its configured execution timeout.
#[error("tool execution timeout: {tool}")]
ToolTimeout {
/// Name of the timed-out tool.
tool: String,
},
/// An error propagated from the provider layer.
#[error(transparent)]
Provider(#[from] crate::error::ProviderError),
/// An error propagated from the context layer.
#[error(transparent)]
Context(#[from] crate::error::ContextError),
/// An error propagated from the storage layer.
#[error(transparent)]
Storage(#[from] crate::error::StorageError),
/// An error propagated from the tool layer.
#[error(transparent)]
Tool(#[from] crate::error::ToolError),
/// Snapshot persistence or recovery failed.
#[error("recovery error: {0}")]
RecoveryFailed(String),
/// Doom loop detected — agent is stuck in a repetitive tool call pattern.
#[error("doom loop detected: {description}")]
DoomLoopDetected {
/// Human-readable description of the detected pattern.
description: String,
},
/// Input was rejected by the admission pipeline.
#[error("input rejected: {input_id} — {reason}")]
InputRejected {
/// Identifier of the rejected input.
input_id: crate::runtime::input::InputId,
/// Reason for rejection.
reason: String,
},
/// Internal error during input admission processing.
#[error("input admission error: {0}")]
InputAdmissionFailed(String),
}
/// Result type for runtime operations.
pub type RuntimeResult<T> = Result<T, RuntimeError>;