Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c526222

Browse files
feat: add FORGE_DUMP_AUTO_OPEN env variable (tailcallhq#1537)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent f73a26c commit c526222

12 files changed

Lines changed: 362 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ Configuring the tool calls settings:
413413
```bash
414414
# .env
415415
FORGE_TOOL_TIMEOUT=300 # Maximum execution time in seconds for a tool before it is terminated to prevent hanging the session. (default: 300)
416+
FORGE_DUMP_AUTO_OPEN=false # Automatically open dump files in browser (default: false)
416417
```
417418

418419
</details>

crates/forge_app/src/fmt/fmt_output.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ mod tests {
9393
http: Default::default(),
9494
max_file_size: 0,
9595
forge_api_url: Url::parse("http://forgecode.dev/api").unwrap(),
96+
auto_open_dump: false,
9697
}
9798
}
9899

crates/forge_app/src/operation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,7 @@ mod tests {
559559
http: Default::default(),
560560
max_file_size: 256 << 10, // 256 KiB
561561
forge_api_url: Url::parse("http://forgecode.dev/api").unwrap(),
562+
auto_open_dump: false,
562563
}
563564
}
564565

crates/forge_app/src/orch_spec/orch_setup.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ impl TestContext {
7777
max_file_size: 1024 * 1024 * 5,
7878
max_search_result_bytes: 200,
7979
stdout_max_line_length: 200, // 5 MB
80+
auto_open_dump: false,
8081
},
8182
title: Some("test-conversation".into()),
8283
agent: Agent::new(AgentId::new("forge"))

crates/forge_domain/src/env.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ pub struct Environment {
5555
/// Maximum execution time in seconds for a single tool call.
5656
/// Controls how long a tool can run before being terminated.
5757
pub tool_timeout: u64,
58+
/// Whether to automatically open HTML dump files in the browser.
59+
/// Controlled by FORGE_DUMP_AUTO_OPEN environment variable.
60+
pub auto_open_dump: bool,
5861
}
5962

6063
impl Environment {
@@ -149,6 +152,7 @@ mod tests {
149152
http: HttpConfig::default(),
150153
max_file_size: 104857600,
151154
tool_timeout: 300,
155+
auto_open_dump: false,
152156
};
153157

154158
let actual = fixture.agent_cwd_path();
@@ -179,6 +183,7 @@ mod tests {
179183
http: HttpConfig::default(),
180184
max_file_size: 104857600,
181185
tool_timeout: 300,
186+
auto_open_dump: false,
182187
};
183188

184189
let agent_path = fixture.agent_path();

crates/forge_infra/src/env.rs

Lines changed: 176 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ impl ForgeEnvironmentInfra {
6868
stdout_max_prefix_length: 200,
6969
stdout_max_suffix_length: 200,
7070
tool_timeout: parse_env::<u64>("FORGE_TOOL_TIMEOUT").unwrap_or(300),
71+
auto_open_dump: parse_env::<bool>("FORGE_DUMP_AUTO_OPEN").unwrap_or(false),
7172
stdout_max_line_length: parse_env::<usize>("FORGE_STDOUT_MAX_LINE_LENGTH")
7273
.unwrap_or(2000),
7374
http: resolve_http_config(),
@@ -109,11 +110,49 @@ impl EnvironmentInfra for ForgeEnvironmentInfra {
109110
}
110111
}
111112

112-
fn parse_env<T: FromStr>(name: &str) -> Option<T> {
113+
/// Trait for parsing environment variable values with custom logic for
114+
/// different types
115+
trait FromEnvStr: Sized {
116+
fn from_env_str(s: &str) -> Option<Self>;
117+
}
118+
119+
/// Custom implementation for bool with support for multiple truthy values
120+
/// Supports: "true", "1", "yes" (case-insensitive) as true; everything else as
121+
/// false
122+
impl FromEnvStr for bool {
123+
fn from_env_str(s: &str) -> Option<Self> {
124+
Some(matches!(s.to_lowercase().as_str(), "true" | "1" | "yes"))
125+
}
126+
}
127+
128+
// Macro to implement FromEnvStr for types that already implement FromStr
129+
macro_rules! impl_from_env_str_via_from_str {
130+
($($t:ty),* $(,)?) => {
131+
$(
132+
impl FromEnvStr for $t {
133+
fn from_env_str(s: &str) -> Option<Self> {
134+
<$t as FromStr>::from_str(s).ok()
135+
}
136+
}
137+
)*
138+
};
139+
}
140+
141+
// Implement FromEnvStr for commonly used types
142+
impl_from_env_str_via_from_str! {
143+
u8, u16, u32, u64, u128, usize,
144+
i8, i16, i32, i64, i128, isize,
145+
f32, f64,
146+
String,
147+
forge_domain::TlsBackend,
148+
forge_domain::TlsVersion,
149+
}
150+
151+
/// Parse environment variable using custom FromEnvStr trait
152+
fn parse_env<T: FromEnvStr>(name: &str) -> Option<T> {
113153
std::env::var(name)
114-
.as_ref()
115154
.ok()
116-
.and_then(|var| T::from_str(var).ok())
155+
.and_then(|val| T::from_env_str(&val))
117156
}
118157

119158
/// Resolves retry configuration from environment variables or returns defaults
@@ -469,6 +508,94 @@ mod tests {
469508
}
470509
}
471510

511+
#[test]
512+
#[serial]
513+
fn test_auto_open_dump_env_var() {
514+
let cwd = tempdir().unwrap().path().to_path_buf();
515+
let infra = ForgeEnvironmentInfra::new(false, cwd);
516+
517+
// Test default value when env var is not set
518+
{
519+
unsafe {
520+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
521+
}
522+
let env = infra.get_environment();
523+
assert_eq!(env.auto_open_dump, false);
524+
}
525+
526+
// Test enabled with "true"
527+
{
528+
unsafe {
529+
env::set_var("FORGE_DUMP_AUTO_OPEN", "true");
530+
}
531+
let env = infra.get_environment();
532+
assert_eq!(env.auto_open_dump, true);
533+
unsafe {
534+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
535+
}
536+
}
537+
538+
// Test enabled with "1"
539+
{
540+
unsafe {
541+
env::set_var("FORGE_DUMP_AUTO_OPEN", "1");
542+
}
543+
let env = infra.get_environment();
544+
assert_eq!(env.auto_open_dump, true);
545+
unsafe {
546+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
547+
}
548+
}
549+
550+
// Test case insensitive "TRUE"
551+
{
552+
unsafe {
553+
env::set_var("FORGE_DUMP_AUTO_OPEN", "TRUE");
554+
}
555+
let env = infra.get_environment();
556+
assert_eq!(env.auto_open_dump, true);
557+
unsafe {
558+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
559+
}
560+
}
561+
562+
// Test disabled with "false"
563+
{
564+
unsafe {
565+
env::set_var("FORGE_DUMP_AUTO_OPEN", "false");
566+
}
567+
let env = infra.get_environment();
568+
assert_eq!(env.auto_open_dump, false);
569+
unsafe {
570+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
571+
}
572+
}
573+
574+
// Test disabled with "0"
575+
{
576+
unsafe {
577+
env::set_var("FORGE_DUMP_AUTO_OPEN", "0");
578+
}
579+
let env = infra.get_environment();
580+
assert_eq!(env.auto_open_dump, false);
581+
unsafe {
582+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
583+
}
584+
}
585+
586+
// Test fallback to default for invalid value
587+
{
588+
unsafe {
589+
env::set_var("FORGE_DUMP_AUTO_OPEN", "invalid");
590+
}
591+
let env = infra.get_environment();
592+
assert_eq!(env.auto_open_dump, false);
593+
unsafe {
594+
env::remove_var("FORGE_DUMP_AUTO_OPEN");
595+
}
596+
}
597+
}
598+
472599
#[test]
473600
#[serial]
474601
fn test_tool_timeout_env_var() {
@@ -508,4 +635,50 @@ mod tests {
508635
}
509636
}
510637
}
638+
#[test]
639+
#[serial]
640+
fn test_unified_parse_env_functionality() {
641+
// Test that the unified parse_env works for different types
642+
643+
// Test boolean parsing with custom logic
644+
unsafe {
645+
env::set_var("TEST_BOOL_TRUE", "yes");
646+
env::set_var("TEST_BOOL_FALSE", "no");
647+
}
648+
649+
assert_eq!(parse_env::<bool>("TEST_BOOL_TRUE"), Some(true));
650+
assert_eq!(parse_env::<bool>("TEST_BOOL_FALSE"), Some(false));
651+
652+
// Test numeric parsing
653+
unsafe {
654+
env::set_var("TEST_U64", "123");
655+
env::set_var("TEST_F64", "45.67");
656+
}
657+
658+
assert_eq!(parse_env::<u64>("TEST_U64"), Some(123));
659+
assert_eq!(parse_env::<f64>("TEST_F64"), Some(45.67));
660+
661+
// Test string parsing
662+
unsafe {
663+
env::set_var("TEST_STRING", "hello world");
664+
}
665+
666+
assert_eq!(
667+
parse_env::<String>("TEST_STRING"),
668+
Some("hello world".to_string())
669+
);
670+
671+
// Test missing env var
672+
assert_eq!(parse_env::<bool>("NONEXISTENT_VAR"), None);
673+
assert_eq!(parse_env::<u64>("NONEXISTENT_VAR"), None);
674+
675+
// Clean up
676+
unsafe {
677+
env::remove_var("TEST_BOOL_TRUE");
678+
env::remove_var("TEST_BOOL_FALSE");
679+
env::remove_var("TEST_U64");
680+
env::remove_var("TEST_F64");
681+
env::remove_var("TEST_STRING");
682+
}
683+
}
511684
}

crates/forge_infra/src/executor.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ mod tests {
226226
tool_timeout: 300,
227227
max_file_size: 10_000_000,
228228
forge_api_url: Url::parse("http://forgecode.dev/api").unwrap(),
229+
auto_open_dump: false,
229230
}
230231
}
231232

crates/forge_main/src/info.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ mod tests {
431431
tool_timeout: 300,
432432
http: Default::default(),
433433
max_file_size: 1000,
434+
auto_open_dump: false,
434435
}
435436
}
436437

crates/forge_main/src/ui.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,9 @@ impl<A: API + 'static, F: Fn() -> A> UI<A, F> {
812812
.sub_title(path.to_string()),
813813
)?;
814814

815-
open::that(path.as_str()).ok();
815+
if self.api.environment().auto_open_dump {
816+
open::that(path.as_str()).ok();
817+
}
816818

817819
return Ok(());
818820
}
@@ -827,7 +829,9 @@ impl<A: API + 'static, F: Fn() -> A> UI<A, F> {
827829
.sub_title(path.to_string()),
828830
)?;
829831

830-
open::that(path.as_str()).ok();
832+
if self.api.environment().auto_open_dump {
833+
open::that(path.as_str()).ok();
834+
}
831835
};
832836
} else {
833837
return Err(anyhow::anyhow!("Could not create dump"))

crates/forge_services/src/attachment.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ pub mod tests {
123123
http: Default::default(),
124124
max_file_size: 10_000_000,
125125
forge_api_url: Url::parse("http://forgecode.dev/api").unwrap(),
126+
auto_open_dump: false,
126127
}
127128
}
128129

0 commit comments

Comments
 (0)