Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/config/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub struct Config {
#[serde(default)]
pub model_providers: HashMap<String, ModelProviderConfig>,
/// Default model temperature (0.0–2.0). Default: `0.7`.
#[serde(default = "default_temperature")]
pub default_temperature: f64,

/// Observability backend configuration (`[observability]`).
Expand Down Expand Up @@ -268,6 +269,10 @@ pub struct DelegateAgentConfig {
pub max_iterations: usize,
}

fn default_temperature() -> f64 {
0.7
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

fn default_max_depth() -> u32 {
3
}
Expand Down
88 changes: 74 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,9 @@ Examples:
#[arg(long)]
model: Option<String>,

/// Temperature (0.0 - 2.0)
#[arg(short, long, default_value = "0.7", value_parser = parse_temperature)]
temperature: f64,
/// Temperature override (0.0 - 2.0). Defaults to config.default_temperature when omitted.
#[arg(short, long, value_parser = parse_temperature)]
temperature: Option<f64>,

/// Attach a peripheral (board:path, e.g. nucleo-f401re:/dev/ttyACM0)
#[arg(long)]
Expand Down Expand Up @@ -775,17 +775,25 @@ async fn main() -> Result<()> {
model,
temperature,
peripheral,
} => agent::run(
config,
message,
provider,
model,
temperature,
peripheral,
true,
)
.await
.map(|_| ()),
} => {
// Implement temperature fallback logic:
// 1. Use --temperature if provided
// 2. Use config.default_temperature if --temperature not provided
// 3. Use hardcoded 0.7 if config.default_temperature not set (from Config::default())
let final_temperature = temperature.unwrap_or(config.default_temperature);

agent::run(
config,
message,
provider,
model,
final_temperature,
Comment thread
coderabbitai[bot] marked this conversation as resolved.
peripheral,
true,
)
.await
.map(|_| ())
}

Commands::Gateway { port, host } => {
let port = port.unwrap_or(config.gateway.port);
Expand Down Expand Up @@ -1974,4 +1982,56 @@ mod tests {
other => panic!("expected estop resume command, got {other:?}"),
}
}

#[test]
fn agent_command_parses_with_temperature() {
let cli = Cli::try_parse_from(["zeroclaw", "agent", "--temperature", "0.5"])
.expect("agent command with temperature should parse");

match cli.command {
Commands::Agent { temperature, .. } => {
assert_eq!(temperature, Some(0.5));
}
other => panic!("expected agent command, got {other:?}"),
}
}

#[test]
fn agent_command_parses_without_temperature() {
let cli = Cli::try_parse_from(["zeroclaw", "agent", "--message", "hello"])
.expect("agent command without temperature should parse");

match cli.command {
Commands::Agent { temperature, .. } => {
assert_eq!(temperature, None);
}
other => panic!("expected agent command, got {other:?}"),
}
}

#[test]
fn agent_fallback_uses_config_default_temperature() {
// Test that when user doesn't provide --temperature,
// the fallback logic works correctly
let mut config = Config::default(); // default_temperature = 0.7
config.default_temperature = 1.5;

// Simulate None temperature (user didn't provide --temperature)
let user_temperature: Option<f64> = None;
let final_temperature = user_temperature.unwrap_or(config.default_temperature);

assert!((final_temperature - 1.5).abs() < f64::EPSILON);
}

#[test]
fn agent_fallback_uses_hardcoded_when_config_uses_default() {
// Test that when config uses default value (0.7), fallback still works
let config = Config::default(); // default_temperature = 0.7

// Simulate None temperature (user didn't provide --temperature)
let user_temperature: Option<f64> = None;
let final_temperature = user_temperature.unwrap_or(config.default_temperature);

assert!((final_temperature - 0.7).abs() < f64::EPSILON);
}
}
8 changes: 5 additions & 3 deletions tests/config_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,12 +218,14 @@ fn autonomy_config_toml_roundtrip() {
// ─────────────────────────────────────────────────────────────────────────────

#[test]
fn config_empty_toml_requires_temperature() {
fn config_empty_toml_uses_default_temperature() {
let result: Result<Config, _> = toml::from_str("");
assert!(
result.is_err(),
"empty TOML should fail because default_temperature is required"
result.is_ok(),
"empty TOML should succeed and use default temperature"
);
let config = result.unwrap();
assert!((config.default_temperature - 0.7).abs() < f64::EPSILON);
}

#[test]
Expand Down