refactor(unwrap): clear non-test workspace warnings

This commit is contained in:
Bryan Helmkamp 2026-04-19 20:56:38 -04:00
parent bd0d47ba4d
commit e0b2d71668
No known key found for this signature in database
32 changed files with 123 additions and 83 deletions

View file

@ -38,9 +38,9 @@ pub trait AgentProfile: Send + Sync {
}
fn context_window_size(&self) -> usize {
Catalog::builtin()
.get(self.model())
.map_or(200_000, |m| usize::try_from(m.context_window()).unwrap())
Catalog::builtin().get(self.model()).map_or(200_000, |m| {
usize::try_from(m.context_window()).unwrap_or(usize::MAX)
})
}
fn register_subagent_tools(

View file

@ -195,7 +195,7 @@ impl SubAgentManager {
let join_handle = self
.agents
.get_mut(agent_id)
.unwrap()
.expect("agent should still exist after status check")
.task
.take()
.ok_or_else(|| Error::InvalidState(format!("Agent {agent_id} has no running task")))?;
@ -226,7 +226,10 @@ impl SubAgentManager {
}
// Phase 5: Store result in status and return clone
let agent = self.agents.get_mut(agent_id).unwrap();
let agent = self
.agents
.get_mut(agent_id)
.expect("agent should still exist when storing task result");
agent.status = SubAgentStatus::Finished(task_result);
match &agent.status {
@ -338,7 +341,7 @@ pub fn make_spawn_agent_tool(
let max_turns = args
.get("max_turns")
.and_then(serde_json::Value::as_u64)
.map(|v| usize::try_from(v).unwrap());
.map(|v| usize::try_from(v).unwrap_or(usize::MAX));
// Note: working_dir and model require session factory changes to wire through
let mut session = session_factory();

View file

@ -206,7 +206,7 @@ async fn execute_and_emit_one_tool_with_lookup(
debug!(tool = %tc.name, hook_event = "pre_tool_use", "Calling tool hook");
let start = std::time::Instant::now();
let decision = hooks.pre_tool_use(&tc.name, &tc.arguments).await;
let elapsed = u64::try_from(start.elapsed().as_millis()).unwrap();
let elapsed = u64::try_from(start.elapsed().as_millis()).unwrap_or(u64::MAX);
debug!(tool = %tc.name, hook_event = "pre_tool_use", ?decision, duration_ms = elapsed, "Tool hook complete");
if let ToolHookDecision::Block { reason } = decision {

View file

@ -68,6 +68,15 @@ pub(crate) fn required_str<'a>(args: &'a serde_json::Value, key: &str) -> Result
.ok_or_else(|| format!("Missing required parameter: {key}"))
}
fn optional_usize_arg(args: &serde_json::Value, key: &str) -> Result<Option<usize>, String> {
args.get(key)
.and_then(serde_json::Value::as_u64)
.map(|value| {
usize::try_from(value).map_err(|_| format!("Parameter {key} is too large: {value}"))
})
.transpose()
}
#[must_use]
pub fn make_read_file_tool() -> RegisteredTool {
RegisteredTool {
@ -87,11 +96,8 @@ pub fn make_read_file_tool() -> RegisteredTool {
executor: Arc::new(|args, ctx| {
Box::pin(async move {
let file_path = required_str(&args, "file_path")?;
let offset = args.get("offset").and_then(serde_json::Value::as_u64);
let limit = args.get("limit").and_then(serde_json::Value::as_u64);
let offset_usize = offset.map(|v| usize::try_from(v).unwrap());
let limit_usize = limit.map(|v| usize::try_from(v).unwrap());
let offset_usize = optional_usize_arg(&args, "offset")?;
let limit_usize = optional_usize_arg(&args, "limit")?;
let content = ctx
.env
@ -281,10 +287,13 @@ pub fn make_grep_tool() -> RegisteredTool {
.and_then(serde_json::Value::as_str)
.unwrap_or(".");
let max_results = args
.get("max_results")
.and_then(serde_json::Value::as_u64)
.map(|v| usize::try_from(v).unwrap());
let max_results = args.get("max_results").and_then(serde_json::Value::as_u64);
let max_results = max_results
.map(|value| {
usize::try_from(value)
.map_err(|_| format!("Parameter max_results is too large: {value}"))
})
.transpose()?;
let options = GrepOptions {
glob_filter: args
.get("glob_filter")
@ -402,10 +411,7 @@ pub(crate) fn make_list_dir_tool() -> RegisteredTool {
executor: Arc::new(|args, ctx| {
Box::pin(async move {
let path = required_str(&args, "path")?;
let depth = args
.get("depth")
.and_then(serde_json::Value::as_u64)
.map(|v| usize::try_from(v).unwrap());
let depth = optional_usize_arg(&args, "depth")?;
let entries = ctx.env.list_directory(path, depth).await?;
let lines: Vec<String> = entries

View file

@ -31,7 +31,7 @@ fn patch_nullable(value: &mut serde_json::Value) {
let mut inner = variants.remove(0);
inner
.as_object_mut()
.unwrap()
.expect("oneOf collapse should leave an object schema")
.insert("nullable".to_string(), serde_json::Value::Bool(true));
patch_nullable(&mut inner);
*value = inner;
@ -129,12 +129,9 @@ fn patch_codegen_request_body_media_types(value: &mut serde_json::Value) {
fn spec_path_from_manifest_dir(manifest_dir: &Path) -> PathBuf {
manifest_dir
.parent()
.unwrap()
.parent()
.unwrap()
.parent()
.unwrap()
.ancestors()
.nth(3)
.expect("fabro-api manifest dir should be nested under <repo>/lib/crates/fabro-api")
.join("docs/api-reference/fabro-api.yaml")
}
@ -171,7 +168,7 @@ fn main() {
let syntax_tree = syn::parse2::<syn::File>(tokens).expect("failed to parse generated tokens");
let formatted = prettyplease::unparse(&syntax_tree);
let out_dir = env::var("OUT_DIR").unwrap();
let out_dir = env::var("OUT_DIR").expect("OUT_DIR should be set for build scripts");
let out_path = Path::new(&out_dir).join("codegen.rs");
fs::write(&out_path, formatted).expect("failed to write generated code");
}

View file

@ -158,7 +158,12 @@ fn print_models_table(models: &[Model], styles: &Styles) {
.color_choice(color_choice(use_color))
.border(Border::builder().build())
.separator(Separator::builder().build());
println!("{}", table.display().unwrap());
println!(
"{}",
table
.display()
.expect("rendering the models table should succeed")
);
}
fn model_test_row_from_status(model: &Model, status: &str, result_color: Color) -> ModelTestRow {

View file

@ -398,7 +398,13 @@ async fn print_assets_with_client(
.separator(Separator::builder().build());
fabro_util::printerr!(printer, "\n{}", styles.bold.apply_to("=== Artifacts ==="));
fabro_util::printerr!(printer, "{}", table.display().unwrap());
fabro_util::printerr!(
printer,
"{}",
table
.display()
.expect("rendering the artifacts table should succeed")
);
fabro_util::printerr!(
printer,
"{}",

View file

@ -64,7 +64,11 @@ pub(crate) async fn run(
return Ok(());
}
let target = args.target.as_deref().unwrap().parse::<RewindTarget>()?;
let target_arg = args
.target
.as_deref()
.expect("rewind target should be present unless listing");
let target = target_arg.parse::<RewindTarget>()?;
rewind(&store, &RewindInput {
run_id,
@ -80,7 +84,7 @@ pub(crate) async fn run(
if cli.output.format == OutputFormat::Json {
print_json_pretty(&serde_json::json!({
"run_id": run_id_string,
"target": args.target.as_deref().unwrap(),
"target": target_arg,
}))?;
} else {
fabro_util::printerr!(

View file

@ -50,11 +50,10 @@ pub(crate) async fn run(
if let Some(dl) = deadline {
let now = std::time::Instant::now();
if now >= dl {
bail!(
"Timed out after {}s waiting for run '{}'",
args.timeout.unwrap(),
run_id
);
let timeout_secs = args
.timeout
.expect("deadline should only exist when timeout is set");
bail!("Timed out after {timeout_secs}s waiting for run '{run_id}'");
}
time::sleep(interval.min(dl - now)).await;
} else {

View file

@ -99,9 +99,7 @@ pub(crate) async fn list_command(
None => match run.start_time_dt() {
Some(start) => {
let elapsed = now.signed_duration_since(start);
format_duration_ms(
u64::try_from(elapsed.num_milliseconds().max(0)).unwrap(),
)
format_duration_ms(elapsed.num_milliseconds().max(0).cast_unsigned())
}
None => "-".to_string(),
},

View file

@ -44,12 +44,12 @@ pub(crate) fn parse_duration(s: &str) -> Result<chrono::Duration> {
bail!("empty duration string");
}
let (num_str, unit) = s.split_at(s.len() - 1);
let num: u64 = num_str
let num: i64 = num_str
.parse()
.with_context(|| format!("invalid duration: {s}"))?;
match unit {
"h" => Ok(chrono::Duration::hours(i64::try_from(num).unwrap())),
"d" => Ok(chrono::Duration::days(i64::try_from(num).unwrap())),
"h" => Ok(chrono::Duration::hours(num)),
"d" => Ok(chrono::Duration::days(num)),
_ => bail!("invalid duration unit '{unit}' in '{s}' (expected 'h' or 'd')"),
}
}

View file

@ -129,7 +129,13 @@ fn print_section(
.color_choice(color_choice)
.border(Border::builder().build())
.separator(Separator::builder().build());
fabro_util::printerr!(printer, "{}", table.display().unwrap());
fabro_util::printerr!(
printer,
"{}",
table
.display()
.expect("rendering the workflow table should succeed")
);
}
fn truncate_str(s: &str, max: usize) -> String {

View file

@ -77,7 +77,7 @@ async fn main() {
let start = std::time::Instant::now();
let (command_name, result) = Box::pin(main_inner()).await;
let duration_ms = u64::try_from(start.elapsed().as_millis()).unwrap();
let duration_ms = u64::try_from(start.elapsed().as_millis()).unwrap_or(u64::MAX);
let is_error = result.is_err();
// An empty command_name means no subcommand was invoked (landing was shown);

View file

@ -158,11 +158,9 @@ fn apply_local_daemon_overrides(
}
// Ensure a run.execution table exists so downstream consumers that check
// for explicit dry-run defaults see a well-formed layer.
settings.run.get_or_insert_with(RunLayer::default);
settings
.run
.as_mut()
.unwrap()
.get_or_insert_with(RunLayer::default)
.execution
.get_or_insert_with(RunExecutionLayer::default);
settings

View file

@ -578,7 +578,7 @@ impl DevcontainerResolver {
ports
.iter()
.filter_map(|p| match p {
serde_json::Value::Number(n) => n.as_u64().map(|n| u16::try_from(n).unwrap()),
serde_json::Value::Number(n) => n.as_u64().and_then(|n| u16::try_from(n).ok()),
serde_json::Value::String(s) => {
let s = s.split('/').next().unwrap_or(s); // strip protocol
if let Some((_host, container)) = s.split_once(':') {

View file

@ -20,13 +20,14 @@ const DOT_STYLE_DEFAULTS: &str = r##"
edge [color="#666666", fontname="Helvetica", fontsize=10, fontcolor="#666666"]
"##;
static RANKDIR_RE: LazyLock<regex::Regex> =
LazyLock::new(|| regex::Regex::new(r"rankdir\s*=\s*\w+").unwrap());
static RANKDIR_RE: LazyLock<regex::Regex> = LazyLock::new(|| {
regex::Regex::new(r"rankdir\s*=\s*\w+").expect("hardcoded regex should compile")
});
static WHITE_BG_POLYGON_RE: LazyLock<regex::Regex> = LazyLock::new(|| {
regex::Regex::new(
r#"<polygon\b[^>]*fill="white"[^>]*stroke="none"[^>]*/>|<polygon\b[^>]*stroke="none"[^>]*fill="white"[^>]*/>"#,
)
.unwrap()
.expect("hardcoded regex should compile")
});
/// Rewrite `rankdir=...` in DOT source.

View file

@ -35,6 +35,10 @@ static HOOK_RESPONSE_SCHEMA: LazyLock<serde_json::Value> = LazyLock::new(|| {
})
});
fn duration_ms(duration: std::time::Duration) -> u64 {
u64::try_from(duration.as_millis()).unwrap_or(u64::MAX)
}
/// Trait for executing hooks via different transports.
#[async_trait]
pub trait HookExecutor: Send + Sync {
@ -149,7 +153,7 @@ impl HookExecutorImpl {
}
};
let context_json = serde_json::to_string(context).unwrap_or_default();
let timeout_ms = u64::try_from(definition.timeout().as_millis()).unwrap();
let timeout_ms = duration_ms(definition.timeout());
let mut env_vars = HashMap::new();
env_vars.insert("FABRO_EVENT".to_string(), context.event.to_string());
@ -679,7 +683,7 @@ impl HookExecutor for HookExecutorImpl {
},
};
let duration_ms = u64::try_from(start.elapsed().as_millis()).unwrap();
let duration_ms = duration_ms(start.elapsed());
HookResult {
hook_name: definition.name.clone(),
decision,

View file

@ -190,7 +190,7 @@ fn estimate_reasoning_tokens(content_parts: &[ContentPart]) -> Option<i64> {
})
.sum();
if total_chars > 0 {
Some(i64::try_from((total_chars / 4).max(1)).unwrap())
Some(i64::try_from((total_chars / 4).max(1)).unwrap_or(i64::MAX))
} else {
None
}

View file

@ -39,6 +39,10 @@ async fn build_daytona_client(
daytona_sdk::Client::new_with_config(sdk_config).await
}
fn elapsed_ms(start: &Instant) -> u64 {
u64::try_from(start.elapsed().as_millis()).unwrap_or(u64::MAX)
}
/// Sandbox that runs all operations inside a Daytona cloud sandbox.
pub struct DaytonaSandbox {
config: DaytonaConfig,
@ -952,7 +956,7 @@ impl Sandbox for DaytonaSandbox {
name: f.name,
is_dir: f.is_dir,
size: if f.size > 0 {
Some(u64::try_from(f.size).unwrap())
u64::try_from(f.size).ok()
} else {
None
},
@ -982,7 +986,7 @@ impl Sandbox for DaytonaSandbox {
.map_err(|e| format!("Failed to get process service: {e}"))?;
tracing::info!(
elapsed_ms = u64::try_from(start.elapsed().as_millis()).unwrap(),
elapsed_ms = elapsed_ms(&start),
"exec_command: process service acquired, starting select"
);
@ -1021,7 +1025,7 @@ impl Sandbox for DaytonaSandbox {
let result = tokio::select! {
res = exec_future => {
tracing::info!(
elapsed_ms = u64::try_from(start.elapsed().as_millis()).unwrap(),
elapsed_ms = elapsed_ms(&start),
ok = res.is_ok(),
"exec_command: HTTP response received"
);
@ -1029,7 +1033,7 @@ impl Sandbox for DaytonaSandbox {
}
() = time::sleep(timeout_duration) => {
tracing::info!(
elapsed_ms = u64::try_from(start.elapsed().as_millis()).unwrap(),
elapsed_ms = elapsed_ms(&start),
timeout_ms,
"exec_command: client-side timeout fired"
);
@ -1038,12 +1042,12 @@ impl Sandbox for DaytonaSandbox {
stderr: "Command timed out locally".to_string(),
exit_code: -1,
timed_out: true,
duration_ms: u64::try_from(start.elapsed().as_millis()).unwrap(),
duration_ms: elapsed_ms(&start),
});
}
() = token.cancelled() => {
tracing::info!(
elapsed_ms = u64::try_from(start.elapsed().as_millis()).unwrap(),
elapsed_ms = elapsed_ms(&start),
"exec_command: cancelled via token"
);
return Ok(ExecResult {
@ -1051,12 +1055,12 @@ impl Sandbox for DaytonaSandbox {
stderr: "Command cancelled".to_string(),
exit_code: -1,
timed_out: true,
duration_ms: u64::try_from(start.elapsed().as_millis()).unwrap(),
duration_ms: elapsed_ms(&start),
});
}
};
let duration_ms = u64::try_from(start.elapsed().as_millis()).unwrap();
let duration_ms = elapsed_ms(&start);
// The Daytona SDK returns combined output in `result` field.
// Separate stderr isn't available in the simple execute_command API.

View file

@ -192,7 +192,10 @@ impl DockerSandbox {
.await
.map_err(|e| format!("Failed to inspect exec: {e}"))?;
let exit_code = i32::try_from(inspect.exit_code.unwrap_or(-1)).unwrap();
let exit_code = inspect
.exit_code
.and_then(|code| i32::try_from(code).ok())
.unwrap_or(-1);
Ok((stdout, stderr, exit_code))
}

View file

@ -762,7 +762,7 @@ pub(crate) async fn get_aggregate_billing(
use chrono::{DateTime, Utc};
fn ts(s: &str) -> DateTime<Utc> {
s.parse().unwrap()
s.parse().expect("hardcoded demo timestamp should parse")
}
mod runs {

View file

@ -551,8 +551,10 @@ fn to_sha_wrapper(sha: &str) -> RunFilesMetaToSha {
// constraint. Values we produce (via `git rev-parse HEAD`) always match.
// `try_from` is expected to succeed; fall back to an empty wrapper on
// the impossible failure rather than panicking.
RunFilesMetaToSha::try_from(sha.to_string())
.unwrap_or_else(|_| RunFilesMetaToSha::try_from(String::from("0000000")).unwrap())
RunFilesMetaToSha::try_from(sha.to_string()).unwrap_or_else(|_| {
RunFilesMetaToSha::try_from(String::from("0000000"))
.expect("hardcoded fallback sha should satisfy schema")
})
}
/// Load the run projection from the store, returning a 404 for the IDOR-safe

View file

@ -57,7 +57,7 @@ fn normalize_issue(node: &Value) -> Result<Issue, String> {
.map(std::string::ToString::to_string);
let priority = match node["priority"].as_i64() {
Some(0) | None => None,
Some(n) => Some(i32::try_from(n).unwrap()),
Some(n) => Some(i32::try_from(n).map_err(|_| format!("Priority out of range: {n}"))?),
};
let state = node["state"]["name"]
.as_str()

View file

@ -68,7 +68,7 @@ fn main() {
let toml_content = fs::read_to_string(toml_path).expect("failed to read gitleaks.toml");
let config: Config = toml::from_str(&toml_content).expect("failed to parse gitleaks.toml");
let out_dir = env::var("OUT_DIR").unwrap();
let out_dir = env::var("OUT_DIR").expect("OUT_DIR should be set for build scripts");
let out_path = Path::new(&out_dir).join("rules_generated.rs");
let mut code = String::new();

View file

@ -2823,7 +2823,7 @@ fn epoch_millis() -> i64 {
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis();
i64::try_from(millis).unwrap()
i64::try_from(millis).unwrap_or(i64::MAX)
}
/// Listener callback type for workflow run events.

View file

@ -33,7 +33,7 @@ impl NodeSpec for WorkflowNode {
fn max_visits(&self) -> Option<usize> {
self.0
.max_visits()
.map(|v| usize::try_from(v.max(0)).unwrap())
.map(|v| usize::try_from(v.max(0)).unwrap_or(usize::MAX))
}
}

View file

@ -10,8 +10,7 @@ use crate::event::{Event, StageScope};
use crate::outcome::{Outcome, OutcomeExt};
fn timeout_ms(node: &Node) -> Option<u64> {
node.timeout()
.map(|d| u64::try_from(d.as_millis()).unwrap())
node.timeout().map(crate::millis_u64)
}
/// Shell-escape a string using `shlex::try_quote` (POSIX-safe).
@ -101,9 +100,7 @@ impl Handler for CommandHandler {
&stage_scope,
);
let timeout_ms = node
.timeout()
.map_or(600_000, |d| u64::try_from(d.as_millis()).unwrap());
let timeout_ms = node.timeout().map_or(600_000, crate::millis_u64);
let env_vars = if services.env.is_empty() {
None
} else {

View file

@ -501,8 +501,9 @@ impl Handler for ParallelHandler {
.collect();
successful.sort_by(|a, b| a.id.cmp(&b.id));
if let Some(winner) = successful.first() {
let sha = winner.head_sha.as_ref().unwrap();
git_merge_ff_only(&*services.sandbox, sha).await;
if let Some(sha) = winner.head_sha.as_ref() {
git_merge_ff_only(&*services.sandbox, sha).await;
}
}
}

View file

@ -344,7 +344,10 @@ fn canonical_repo_root_for_path(path: &str) -> Result<PathBuf> {
fn resolve_prefix_matches(prefix: &str, matches: Vec<RunId>) -> Result<RunId> {
match matches.len() {
0 => bail!("no run found matching '{prefix}'"),
1 => Ok(matches.into_iter().next().unwrap()),
1 => Ok(matches
.into_iter()
.next()
.expect("exactly one run should match when len is 1")),
_ => {
let mut msg = format!("ambiguous run ID prefix '{prefix}', matches:\n");
for run_id in &matches {

View file

@ -339,7 +339,10 @@ pub fn find_run_id_by_prefix(repo: &Repository, prefix: &str) -> Result<RunId> {
match matches.len() {
0 => bail!("no run found matching '{prefix}'"),
1 => Ok(matches.into_iter().next().unwrap()),
1 => Ok(matches
.into_iter()
.next()
.expect("exactly one run should match when len is 1")),
_ => {
let mut msg = format!("ambiguous run ID prefix '{prefix}', matches:\n");
for m in &matches {

View file

@ -258,13 +258,13 @@ async fn persist_terminal_engine_failure(
run_store,
final_status,
failure_reason,
u64::try_from(duration.as_millis()).unwrap(),
crate::millis_u64(duration),
None,
)
.await;
if let Err(err) = append_event_to_sink(event_sink, &run_id, &Event::WorkflowRunFailed {
error: error.clone(),
duration_ms: u64::try_from(duration.as_millis()).unwrap(),
duration_ms: crate::millis_u64(duration),
reason: status_reason,
git_commit_sha: None,
final_patch: None,

View file

@ -109,7 +109,7 @@ pub async fn run_retro(options: &RetroOptions, dry_run: bool) -> Option<Retro> {
Err(anyhow::anyhow!("No LLM client available"))
};
let duration_ms = u64::try_from(retro_start.elapsed().as_millis()).unwrap();
let duration_ms = crate::millis_u64(retro_start.elapsed());
match retro_result {
Ok((narrative, response)) => {
retro.apply_narrative(narrative);