recursive/agent/types.rs
1//! Cross-cutting agent types shared by the kernel, runtime, and tools.
2//!
3//! These types were extracted from `agent.rs` during Goal 219. They have
4//! no dependency on the deprecated `Agent` / `StepEvent` types and are
5//! re-exported from `crate::agent::*` for backward compatibility.
6//!
7//! When Goal 219 Commit 2 deletes the deprecated `Agent` path, this
8//! module will be the sole owner of these four types.
9
10use serde::{Deserialize, Serialize};
11
12/// Decision returned by a permission hook to allow, deny, or transform a tool call.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14#[serde(rename_all = "snake_case")]
15pub enum PermissionDecision {
16 /// Let the tool execute with the original arguments.
17 Allow,
18 /// Block execution and return the reason as a tool error to the model.
19 Deny(String),
20 /// Replace the arguments before execution.
21 Transform(serde_json::Value),
22}
23
24/// Controls whether the agent executes tools immediately or presents a plan first.
25#[derive(Debug, Clone, PartialEq, Default)]
26pub enum PlanningMode {
27 /// Execute tool calls immediately (current behavior).
28 #[default]
29 Immediate,
30 /// Buffer tool calls and emit a plan for confirmation before executing.
31 PlanFirst,
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35#[serde(tag = "kind", rename_all = "snake_case")]
36/// Why the agent's run terminated.
37///
38/// # Variants
39///
40/// - `NoMoreToolCalls`: Model produced a response without tool calls (natural completion).
41/// - `BudgetExceeded`: Ran out of steps (hit `max_steps`). Agent likely unfinished.
42/// - `ProviderStop(reason)`: LLM provider stopped unexpectedly. `reason` may be "length"
43/// (truncated by token limit), "stop"/"end_turn", or a provider-specific code.
44/// - `Stuck`: Agent got stuck calling the same tool repeatedly with the same arguments.
45/// `repeated_call` is the tool name, `repeats` is how many times before stopping.
46/// - `TranscriptLimit`: Transcript size hit `max_transcript_chars` hard limit before
47/// compaction could reduce it further. Agent cannot continue. `chars` is final size,
48/// `limit` is the configured maximum.
49#[non_exhaustive]
50pub enum FinishReason {
51 /// Model generated final response without requesting more tools.
52 NoMoreToolCalls,
53 /// Agent exceeded the maximum number of steps allowed.
54 BudgetExceeded,
55 /// LLM provider stopped with a specific reason or status code.
56 ProviderStop(String),
57 /// Agent detected repeated identical tool calls (stuck loop).
58 Stuck {
59 repeated_call: String,
60 repeats: usize,
61 },
62 /// Transcript size exceeded hard limit and cannot be reduced further.
63 TranscriptLimit { chars: usize, limit: usize },
64 /// Agent proposed a plan (PlanFirst mode) and is waiting for confirmation.
65 PlanPending,
66 /// Agent was cancelled by a shutdown signal (SIGINT/SIGTERM).
67 Cancelled,
68
69 /// The auto permission classifier reached its denial limit
70 /// (3 consecutive or 10 total denials). All subsequent tool
71 /// calls are blocked to prevent denial loops.
72 PermissionDenialLimit,
73}