mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-10-07 03:00:29 +00:00
refactor(unwrap): clear non-test workspace warnings
This commit is contained in:
parent
bd0d47ba4d
commit
e0b2d71668
32 changed files with 123 additions and 83 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
"{}",
|
||||
|
|
|
|||
|
|
@ -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!(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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')"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(':') {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue