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
1 change: 1 addition & 0 deletions src/apps/cli/src/agent/core_adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ impl Agent for CoreAgentAdapter {
self.agent_type.clone(),
None,
DialogSubmissionPolicy::for_source(DialogTriggerSource::Cli),
None,
)
.await?;

Expand Down
66 changes: 66 additions & 0 deletions src/apps/desktop/src/api/agentic_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use bitfun_core::agentic::coordination::{
SubagentTimeoutAction,
};
use bitfun_core::agentic::core::*;
use bitfun_core::agentic::deep_review_policy::{
apply_deep_review_queue_control, default_review_team_definition, DeepReviewQueueControlAction,
ReviewTeamDefinition,
};
use bitfun_core::agentic::image_analysis::ImageContextData;
use bitfun_core::agentic::tools::image_context::get_image_context;
#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -84,6 +88,8 @@ pub struct StartDialogTurnRequest {
pub turn_id: Option<String>,
#[serde(default)]
pub image_contexts: Option<Vec<ImageContextData>>,
#[serde(default)]
pub user_message_metadata: Option<serde_json::Value>,
}

#[derive(Debug, Serialize)]
Expand Down Expand Up @@ -176,6 +182,37 @@ pub struct SteerDialogTurnResponse {
pub steering_id: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ControlDeepReviewQueueRequest {
pub session_id: String,
pub dialog_turn_id: String,
pub tool_id: String,
pub action: ControlDeepReviewQueueActionDTO,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ControlDeepReviewQueueActionDTO {
Pause,
Continue,
Cancel,
SkipOptional,
}

impl From<ControlDeepReviewQueueActionDTO> for DeepReviewQueueControlAction {
fn from(value: ControlDeepReviewQueueActionDTO) -> Self {
match value {
ControlDeepReviewQueueActionDTO::Pause => DeepReviewQueueControlAction::Pause,
ControlDeepReviewQueueActionDTO::Continue => DeepReviewQueueControlAction::Continue,
ControlDeepReviewQueueActionDTO::Cancel => DeepReviewQueueControlAction::Cancel,
ControlDeepReviewQueueActionDTO::SkipOptional => {
DeepReviewQueueControlAction::SkipOptional
}
}
}
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CancelSessionRequest {
Expand Down Expand Up @@ -416,6 +453,7 @@ pub async fn start_dialog_turn(
workspace_path,
turn_id,
image_contexts,
user_message_metadata,
} = request;

let policy = DialogSubmissionPolicy::for_source(DialogTriggerSource::DesktopUi);
Expand All @@ -439,6 +477,7 @@ pub async fn start_dialog_turn(
workspace_path,
policy,
None,
user_message_metadata,
resolved_images,
)
.await
Expand Down Expand Up @@ -669,6 +708,28 @@ pub async fn steer_dialog_turn(
})
}

#[tauri::command]
pub async fn control_deep_review_queue(
request: ControlDeepReviewQueueRequest,
) -> Result<(), String> {
if request.session_id.trim().is_empty() {
return Err("Missing session_id".to_string());
}
if request.dialog_turn_id.trim().is_empty() {
return Err("Missing dialog_turn_id".to_string());
}
if request.tool_id.trim().is_empty() {
return Err("Missing tool_id".to_string());
}

apply_deep_review_queue_control(
&request.dialog_turn_id,
&request.tool_id,
request.action.into(),
);
Ok(())
}

#[tauri::command]
pub async fn cancel_session(
coordinator: State<'_, Arc<ConversationCoordinator>>,
Expand Down Expand Up @@ -896,6 +957,11 @@ pub async fn get_available_modes(state: State<'_, AppState>) -> Result<Vec<ModeI
Ok(dtos)
}

#[tauri::command]
pub async fn get_default_review_team_definition() -> Result<ReviewTeamDefinition, String> {
Ok(default_review_team_definition())
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ModeInfoDTO {
Expand Down
29 changes: 27 additions & 2 deletions src/apps/desktop/src/api/git_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
use crate::api::app_state::AppState;
use bitfun_core::infrastructure::storage::StorageOptions;
use bitfun_core::service::git::{
GitAddParams, GitCommitParams, GitDiffParams, GitLogParams, GitPullParams, GitPushParams,
GitService,
GitAddParams, GitChangedFile, GitChangedFilesParams, GitCommitParams, GitDiffParams,
GitLogParams, GitPullParams, GitPushParams, GitService,
};
use bitfun_core::service::git::{
GitBranch, GitCommit, GitOperationResult, GitRepository, GitStatus,
Expand Down Expand Up @@ -91,6 +91,13 @@ pub struct GitDiffRequest {
pub params: GitDiffParams,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GitChangedFilesRequest {
pub repository_path: String,
pub params: GitChangedFilesParams,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GitResetFilesRequest {
Expand Down Expand Up @@ -371,6 +378,24 @@ pub async fn git_get_diff(
})
}

#[tauri::command]
pub async fn git_get_changed_files(
_state: State<'_, AppState>,
request: GitChangedFilesRequest,
) -> Result<Vec<GitChangedFile>, String> {
info!(
"Getting changed Git files for repository: {}",
request.repository_path
);

GitService::get_changed_files(&request.repository_path, &request.params)
.await
.map_err(|e| {
error!("Failed to get changed Git files: {}", e);
e.to_string()
})
}

#[tauri::command]
pub async fn git_reset_files(
_state: State<'_, AppState>,
Expand Down
22 changes: 21 additions & 1 deletion src/apps/desktop/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ pub async fn run() {
api::agentic_api::ensure_assistant_bootstrap,
api::agentic_api::cancel_dialog_turn,
api::agentic_api::steer_dialog_turn,
api::agentic_api::control_deep_review_queue,
api::agentic_api::cancel_session,
api::agentic_api::set_subagent_timeout,
api::agentic_api::delete_session,
Expand All @@ -572,6 +573,7 @@ pub async fn run() {
api::agentic_api::cancel_tool,
api::agentic_api::generate_session_title,
api::agentic_api::get_available_modes,
api::agentic_api::get_default_review_team_definition,
api::btw_api::btw_ask_stream,
api::btw_api::btw_cancel,
api::editor_ai_api::editor_ai_stream,
Expand Down Expand Up @@ -693,6 +695,7 @@ pub async fn run() {
git_create_branch,
git_delete_branch,
git_get_diff,
git_get_changed_files,
git_reset_files,
git_reset_to_commit,
git_get_file_content,
Expand Down Expand Up @@ -1077,12 +1080,29 @@ async fn init_agentic_system() -> anyhow::Result<(
tool_pipeline.clone(),
));

// Get execution config from global settings
let exec_config = match bitfun_core::service::config::get_global_config_service().await {
Ok(config_service) => {
match config_service
.get_config::<bitfun_core::service::config::types::GlobalConfig>(None)
.await
{
Ok(global_config) => execution::ExecutionEngineConfig {
max_rounds: global_config.ai.max_rounds,
..Default::default()
},
Err(_) => Default::default(),
}
}
Err(_) => Default::default(),
};

let execution_engine = Arc::new(execution::ExecutionEngine::new(
round_executor,
event_queue.clone(),
session_manager.clone(),
context_compressor,
execution::ExecutionEngineConfig::default(),
exec_config,
));

let coordinator = Arc::new(coordination::ConversationCoordinator::new(
Expand Down
33 changes: 33 additions & 0 deletions src/apps/server/src/rpc_dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use anyhow::{Result, anyhow};
use bitfun_core::agentic::agents::SubAgentSource;
use bitfun_core::agentic::coordination::{DialogSubmissionPolicy, DialogTriggerSource};
use bitfun_core::agentic::core::SessionConfig;
use bitfun_core::agentic::deep_review_policy::{
DeepReviewQueueControlAction, apply_deep_review_queue_control,
};
use bitfun_core::service::config::types::SubAgentConfig;
use bitfun_core::service::i18n::{LocaleId, LocaleMetadata, sync_global_i18n_service_locale};
use std::collections::HashMap;
Expand Down Expand Up @@ -380,6 +383,36 @@ pub async fn dispatch(
.map_err(|e| anyhow!("{}", e))?;
Ok(serde_json::json!({ "success": true }))
}
"control_deep_review_queue" => {
let request = extract_request(&params)?;
let session_id = get_string(&request, "sessionId")?;
let dialog_turn_id = get_string(&request, "dialogTurnId")?;
let tool_id = get_string(&request, "toolId")?;
let action_raw = get_string(&request, "action")?;
let action = match action_raw.as_str() {
"pause" => DeepReviewQueueControlAction::Pause,
"continue" => DeepReviewQueueControlAction::Continue,
"cancel" => DeepReviewQueueControlAction::Cancel,
"skip_optional" => DeepReviewQueueControlAction::SkipOptional,
other => {
return Err(anyhow!(
"Invalid DeepReview queue control action: {}",
other
));
}
};
if session_id.trim().is_empty() {
return Err(anyhow!("Missing sessionId"));
}
if dialog_turn_id.trim().is_empty() {
return Err(anyhow!("Missing dialogTurnId"));
}
if tool_id.trim().is_empty() {
return Err(anyhow!("Missing toolId"));
}
apply_deep_review_queue_control(&dialog_turn_id, &tool_id, action);
Ok(serde_json::json!({ "success": true }))
}
"cancel_session" => {
let request = extract_request(&params)?;
let session_id = get_string(&request, "sessionId")?;
Expand Down
2 changes: 2 additions & 0 deletions src/crates/acp/src/runtime/prompt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl BitfunAcpRuntime {
acp_session.mode_id.clone(),
Some(acp_session.cwd.clone()),
DialogSubmissionPolicy::for_source(DialogTriggerSource::Cli),
None,
)
.await
.map_err(Self::internal_error)?;
Expand All @@ -66,6 +67,7 @@ impl BitfunAcpRuntime {
acp_session.mode_id.clone(),
Some(acp_session.cwd.clone()),
DialogSubmissionPolicy::for_source(DialogTriggerSource::Cli),
None,
)
.await
.map_err(Self::internal_error)?;
Expand Down
Loading
Loading