Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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: 4 additions & 1 deletion src/apps/desktop/src/api/terminal_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use tokio::sync::Mutex;

use bitfun_core::service::remote_ssh::workspace_state::get_remote_workspace_manager;
use bitfun_core::service::runtime::RuntimeManager;
use bitfun_core::service::config::load_terminal_env_vars;
use bitfun_core::service::terminal::TerminalEvent;
use bitfun_core::service::terminal::{
AcknowledgeRequest as CoreAcknowledgeRequest, CloseSessionRequest as CoreCloseSessionRequest,
Expand Down Expand Up @@ -424,12 +425,14 @@ pub async fn terminal_create(
let api = state.get_or_init_api().await?;

let parsed_shell_type = request.shell_type.and_then(|s| parse_shell_type(&s));
let mut env = request.env.unwrap_or_default();
env.extend(load_terminal_env_vars().await);
let core_request = CoreCreateSessionRequest {
session_id: request.session_id,
name: request.name,
shell_type: parsed_shell_type,
working_directory: request.working_directory,
env: request.env,
env: if env.is_empty() { None } else { Some(env) },
cols: request.cols,
rows: request.rows,
remote_connection_id: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::infrastructure::events::event_system::BackendEvent::{
ToolExecutionProgress, ToolTerminalReady,
};
use crate::infrastructure::events::{emit_global_event, BackendEvent};
use crate::service::config::global::get_global_config_service;
use crate::service::config::global::{get_global_config_service, load_terminal_env_vars};
use crate::service_agent_runtime::CoreServiceAgentRuntime;
use crate::util::elapsed_ms_u64;
use crate::util::errors::{BitFunError, BitFunResult};
Expand Down Expand Up @@ -714,6 +714,8 @@ Usage notes:

// 3. Foreground: get or create the primary terminal session
let terminal_ready_started_at = Instant::now();
let mut session_env = Self::noninteractive_env();
session_env.extend(load_terminal_env_vars().await);
let primary_session_id = binding
.get_or_create(
chat_session_id,
Expand All @@ -725,7 +727,7 @@ Usage notes:
&chat_session_id[..8.min(chat_session_id.len())]
)),
shell_type: shell_type.clone(),
env: Some(Self::noninteractive_env()),
env: Some(session_env),
source: Some(SessionSource::Agent),
..Default::default()
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::agentic::tools::framework::{Tool, ToolResult, ToolUseContext, Validat
use crate::infrastructure::events::event_system::{
get_global_event_system, BackendEvent::BackgroundCommandLifecycle,
};
use crate::service::config::load_terminal_env_vars;
use crate::util::errors::{BitFunError, BitFunResult};
use crate::util::types::event::BackgroundCommandLifecycleInfo;
use async_trait::async_trait;
Expand Down Expand Up @@ -661,10 +662,12 @@ Output:
None
};

let mut command_env = Self::command_env();
command_env.extend(load_terminal_env_vars().await);
let request = TerminalExecCommandRequest {
argv: Self::argv_for_shell(&shell.path, &shell.shell_type, cmd),
cwd: workdir.clone(),
env: Self::command_env(),
env: command_env,
tty,
yield_time_ms: Some(yield_time_ms),
max_output_chars: None,
Expand Down
17 changes: 17 additions & 0 deletions src/crates/assembly/core/src/service/config/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,23 @@ pub async fn get_global_config_service() -> BitFunResult<Arc<ConfigService>> {
GlobalConfigManager::get_service().await
}

/// Load user-defined terminal environment variables (`terminal.env_vars`)
/// from the global configuration. Returns an empty map when the config
/// service is unavailable or the key is unset, so callers can always merge
/// the result over a base environment.
pub async fn load_terminal_env_vars() -> std::collections::HashMap<String, String> {
let Ok(config_service) = get_global_config_service().await else {
return std::collections::HashMap::new();
};
match config_service
.get_config::<super::types::TerminalConfig>(Some("terminal"))
.await
{
Ok(cfg) => cfg.env_vars,
Err(_) => std::collections::HashMap::new(),
}
}

/// Convenience helper: initialize the global configuration service.
pub async fn initialize_global_config() -> BitFunResult<()> {
GlobalConfigManager::initialize().await
Expand Down
4 changes: 2 additions & 2 deletions src/crates/assembly/core/src/service/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub use app_language::{
};
pub use factory::ConfigFactory;
pub use global::{
get_global_config_service, initialize_global_config, reload_global_config,
subscribe_config_updates, ConfigUpdateEvent, GlobalConfigManager,
get_global_config_service, initialize_global_config, load_terminal_env_vars,
reload_global_config, subscribe_config_updates, ConfigUpdateEvent, GlobalConfigManager,
};
pub use manager::{ConfigManager, ConfigManagerSettings, ConfigStatistics};
#[cfg(feature = "product-full")]
Expand Down
5 changes: 5 additions & 0 deletions src/crates/assembly/core/src/service/config/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ pub struct TerminalConfig {
/// Terminal ANSI palette/defaults. This keeps the historical
/// `terminal.theme` config key but is not the GUI theme contract.
pub theme: TerminalThemeConfig,

/// User-defined environment variables applied to every new terminal
/// session and to agent/tool one-shot command execution.
pub env_vars: HashMap<String, String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -1468,6 +1472,7 @@ impl Default for TerminalConfig {
cursor_style: "block".to_string(),
scrollback: 1000,
theme: TerminalThemeConfig::default(),
env_vars: HashMap::new(),
}
}
}
Expand Down
62 changes: 62 additions & 0 deletions src/web-ui/src/infrastructure/config/components/BasicsConfig.scss
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,65 @@
font-size: var(--font-size-sm);
}
}

.bitfun-env-vars-config {
&__content {
display: flex;
flex-direction: column;
gap: $size-gap-4;
}

&__actions {
display: flex;
align-items: center;
gap: 8px;
}

&__table {
display: flex;
flex-direction: column;
gap: 8px;
}

&__row {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) 40px;
align-items: center;
gap: 8px;

&--header {
.bitfun-env-vars-config__cell {
color: var(--color-text-muted);
font-size: var(--font-size-xs);
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
}
}
}

&__cell {
min-width: 0;

&--action {
display: flex;
align-items: center;
justify-content: center;
}
}

&__empty {
padding: 12px 16px;
border: 1px dashed var(--border-base);
border-radius: $size-radius-sm;
color: var(--color-text-muted);
font-size: var(--font-size-sm);
}

&__footer {
display: flex;
align-items: center;
gap: 8px;
margin-top: 4px;
}
}
Loading
Loading