rhema_coding_agent/config.rs
1//! The agent's configuration: model, prompt, workspace, turn budget.
2
3use std::path::PathBuf;
4
5use rhema_core::request::ThinkingEffort;
6
7/// Everything a [`CodingAgent`](crate::CodingAgent) needs besides the
8/// provider.
9#[derive(Debug, Clone)]
10pub struct CodingAgentConfig {
11 /// Model identifier, passed through to
12 /// [`ChatParams`](rhema_core::ChatParams).
13 pub model: String,
14 /// System prompt stamped into every request. `None` uses the base
15 /// prompt — [`base_system`](Self::base_system) when set, the
16 /// built-in default otherwise; setting it *replaces* everything, it
17 /// does not append.
18 pub system: Option<String>,
19 /// The base prompt from the user's `SYSTEM.md`, a Jinja template
20 /// rendered by [`render_system`](crate::render_system) — a template
21 /// error fails the agent's construction. `None` uses the built-in
22 /// [`default_system`](crate::default_system).
23 pub base_system: Option<String>,
24 /// Root all tools are scoped to; paths that escape it are rejected
25 /// in-band to the model.
26 pub workspace: PathBuf,
27 /// Cap on steps per turn; a turn still requesting tools past it fails
28 /// with `AgentError::MaxIterations`.
29 pub max_turn_steps: u32,
30 /// How much reasoning the model should do; providers without a knob
31 /// ignore it, and [`ThinkingEffort::Default`] sends nothing.
32 pub thinking: ThinkingEffort,
33}
34
35impl CodingAgentConfig {
36 /// Default for `max_turn_steps`. Long autonomous sessions — builds,
37 /// rebases, multi-package sweeps — routinely run hundreds of steps on
38 /// cheap models under a watching eye; the cap exists to end a runaway
39 /// loop, not to ration the model. `--max-steps` is the tighter leash
40 /// for unattended turns on expensive models.
41 pub const DEFAULT_MAX_TURN_STEPS: u32 = 2048;
42
43 /// Config naming `model`, rooted at `workspace`, defaults elsewhere.
44 pub fn new(model: impl Into<String>, workspace: impl Into<PathBuf>) -> Self {
45 Self {
46 model: model.into(),
47 system: None,
48 base_system: None,
49 workspace: workspace.into(),
50 max_turn_steps: Self::DEFAULT_MAX_TURN_STEPS,
51 thinking: ThinkingEffort::Default,
52 }
53 }
54}