///|
pub(all) suberror ModelError {
RequestBuild(String)
Transport(String)
ResponseParse(String)
} derive(Debug)
///|
pub impl Show for ModelError with fn to_string(self) -> String {
match self {
RequestBuild(msg) => "ModelError::RequestBuild(\{msg})"
Transport(msg) => "ModelError::Transport(\{msg})"
ResponseParse(msg) => "ModelError::ResponseParse(\{msg})"
}
}
///|
pub(all) suberror SessionError {
Load(String)
Save(String)
} derive(Debug)
///|
pub impl Show for SessionError with fn to_string(self) -> String {
match self {
Load(msg) => "SessionError::Load(\{msg})"
Save(msg) => "SessionError::Save(\{msg})"
}
}
///|
pub(all) suberror RuntimeError {
UnknownTool(String)
InvocationFailed(String)
Transport(String)
/// `ToolRegistry::register_strict` rejected a duplicate tool name.
ToolAlreadyRegistered(String)
} derive(Debug)
///|
pub impl Show for RuntimeError with fn to_string(self) -> String {
match self {
UnknownTool(msg) => "RuntimeError::UnknownTool(\{msg})"
InvocationFailed(msg) => "RuntimeError::InvocationFailed(\{msg})"
Transport(msg) => "RuntimeError::Transport(\{msg})"
ToolAlreadyRegistered(msg) => "RuntimeError::ToolAlreadyRegistered(\{msg})"
}
}
///|
pub(all) suberror AgentError {
Model(String)
Session(SessionError)
Runtime(RuntimeError)
/// The kernel tool-round budget rejected a batch. `consumed` is the round
/// count at rejection (`limit + 1`); `limit` is the configured bound.
ToolLoopExceeded(consumed~ : Int, limit~ : Int)
HookAborted(String)
} derive(Debug)
///|
pub impl Show for AgentError with fn to_string(self) -> String {
match self {
Model(msg) => "AgentError::Model(\{msg})"
Session(err) => "AgentError::Session(\{err.to_string()})"
Runtime(err) => "AgentError::Runtime(\{err.to_string()})"
ToolLoopExceeded(consumed~, limit~) =>
"AgentError::ToolLoopExceeded(consumed=\{consumed}, limit=\{limit}; raise AgentConfig.max_tool_rounds or set None for unbounded)"
HookAborted(msg) => "AgentError::HookAborted(\{msg})"
}
}
///|
pub(all) suberror MemoryError {
Store(String)
Search(String)
Delete(String)
} derive(Debug)
///|
pub impl Show for MemoryError with fn to_string(self) -> String {
match self {
Store(msg) => "MemoryError::Store(\{msg})"
Search(msg) => "MemoryError::Search(\{msg})"
Delete(msg) => "MemoryError::Delete(\{msg})"
}
}
///|
/// Composition errors raised during Agent::new (manifest aggregation failures).
///
/// Every variant that involves a specific extension carries `manifest_id` so
/// callers can locate the offending extension without guessing. Multi-party
/// collisions carry the list of involved manifest ids.
pub(all) suberror CompositionError {
/// Two extensions declared a tool with the same name. Fail-fast; no
/// last-wins routing. First arg is the tool name, second is a diagnostic
/// message, third is the list of manifest ids that declared it.
ToolCollision(String, String, manifests~ : Array[String])
/// Two extensions declared a slash command with the same id.
CommandCollision(String, manifests~ : Array[String])
/// No extension contributed a ModelPort. Exactly one is required.
MissingModel
/// More than one extension contributed a ModelPort. Multi-model routing
/// must be solved inside a meta-extension (e.g. posoco-ext-llm), not by
/// declaring multiple top-level models.
MultipleModels(manifests~ : Array[String])
/// Empty extension list passed to Agent::new.
EmptyManifests
/// An extension manifest was malformed (e.g. empty id, structural issue).
ManifestSchemaError(manifest_id~ : String, detail~ : String)
/// Legacy: a required port had zero contributors. Kept for compatibility
/// with older composition paths that do not use manifests.
EmptyPort(String)
} derive(Debug)
///|
pub impl Show for CompositionError with fn to_string(self) -> String {
match self {
ToolCollision(name, msg, manifests~) =>
"CompositionError::ToolCollision(\{name}: \{msg}; manifests=\{manifests.join(",")})"
CommandCollision(name, manifests~) =>
"CompositionError::CommandCollision(\{name}; manifests=\{manifests.join(",")})"
MissingModel => "CompositionError::MissingModel"
MultipleModels(manifests~) =>
"CompositionError::MultipleModels(manifests=\{manifests.join(",")})"
EmptyManifests => "CompositionError::EmptyManifests"
ManifestSchemaError(manifest_id~, detail~) =>
"CompositionError::ManifestSchemaError(manifest=\{manifest_id}, detail=\{detail})"
EmptyPort(port) => "CompositionError::EmptyPort(\{port})"
}
}
///|
/// Errors raised by UiPort implementations. `UiPort::request` MUST raise one
/// of these typed variants instead of an untyped error, so that callers can
/// distinguish "user cancelled" from "this UI doesn't support requests".
pub(all) suberror UiError {
/// The UiPort does not support interactive requests at all (e.g. NoopUiPort,
/// or a headless host). Distinct from Cancelled (which means the request
/// was presented to the user and they dismissed it).
Unsupported(detail~ : String)
/// User saw the request and explicitly cancelled it.
Cancelled
/// The request payload was structurally invalid (e.g. Select with empty
/// options). Raised by the UiPort before any user interaction.
InvalidRequest(detail~ : String)
/// The host reported a transport/IO failure while servicing the request.
IoFailure(detail~ : String)
} derive(Debug)
///|
pub impl Show for UiError with fn to_string(self) -> String {
match self {
Unsupported(detail~) => "UiError::Unsupported(\{detail})"
Cancelled => "UiError::Cancelled"
InvalidRequest(detail~) => "UiError::InvalidRequest(\{detail})"
IoFailure(detail~) => "UiError::IoFailure(\{detail})"
}
}
///|
/// Errors raised by CommandPort.invoke: unknown command id, invalid args,
/// or execution failure.
pub(all) suberror CommandError {
NotFound(String)
InvalidArgs(reason~ : String)
ExecutionFailed(String)
} derive(Debug)
///|
pub impl Show for CommandError with fn to_string(self) -> String {
match self {
NotFound(id) => "CommandError::NotFound(\{id})"
InvalidArgs(reason~) => "CommandError::InvalidArgs(\{reason})"
ExecutionFailed(msg) => "CommandError::ExecutionFailed(\{msg})"
}
}