agent_types/guard.rs
1//! Guard-related pure types: GuardDecision, GuardCtx.
2
3use serde::{Deserialize, Serialize};
4
5use crate::execution::FinishReason;
6use crate::session::SessionId;
7
8/// Guard decision — returned by guard, executed by base loop.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub enum GuardDecision {
11 /// Continue loop, optionally inject nudge message
12 Continue { nudge: Option<String> },
13 /// Normal completion (fire_turn_end + RunOutcome::Completed)
14 Complete,
15 /// Abnormal termination (fire_guard_fail + RunOutcome::Failed)
16 Fail { error: String },
17
18 // ─── Thinking control ─────────────────────────────────────
19 /// Temporarily disable thinking functionality
20 ///
21 /// Used for reasoning-only loop scenarios: model keeps thinking but produces no output.
22 /// After calling, runtime will:
23 /// 1. Set thinking_disabled_for_rest_of_run = true
24 /// 2. Inject nudge message
25 /// 3. Continue loop
26 DisableThinking { nudge: String },
27
28 /// Restore thinking functionality to previous state
29 ///
30 /// Used for thinking recovery scenarios: model starts working normally (has text or tool call).
31 /// After calling, runtime will:
32 /// 1. Restore thinking_disabled_for_rest_of_run to original state
33 /// 2. Reset related counters
34 RestoreThinking,
35}
36
37/// Guard context information — built by runtime, passed to guard.
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct GuardCtx {
40 pub session_id: SessionId,
41 pub turn_count: u32,
42 pub user_input: String,
43 pub model_response: String,
44 pub finish_reason: FinishReason,
45 pub available_tools: Vec<String>,
46 // RunState information
47 pub reasoning_only_strikes: usize,
48 pub empty_response_strikes: usize,
49 pub run_has_tool_calls: bool,
50 /// All user messages in the current session, ordered oldest-first.
51 /// Guards can use this to reconstruct full conversation context
52 /// (e.g. "继续" after a multi-turn discussion).
53 pub all_user_inputs: Vec<String>,
54 // Scene hints (runtime detected, guard can trust or ignore)
55 pub is_reasoning_only: bool,
56 pub is_empty_response: bool,
57 pub is_text_only: bool,
58 // Environment state
59 pub thinking_disabled: bool,
60 /// Original thinking configuration (for restoration)
61 ///
62 /// From RunState.original_thinking_enabled
63 pub original_thinking_enabled: bool,
64 /// Remaining turns before hitting max_turns limit
65 ///
66 /// Guards can use this to nudge the model to wrap up when running low on turns.
67 /// When remaining_turns == 0, the run will be terminated with MaxTurnsExceeded.
68 pub remaining_turns: u32,
69}