diff --git a/docs/interactive-capabilities/README.md b/docs/interactive-capabilities/README.md index 5bcfc9a2f7..9f92a6129e 100644 --- a/docs/interactive-capabilities/README.md +++ b/docs/interactive-capabilities/README.md @@ -27,9 +27,9 @@ BitFun Playbook currently contains **22 features**, **16 settings pages**, and * - Generated per-item interaction audit: `docs/interactive-capabilities/technical/product-control-open-audit.json` - Generated low-level audit map: `docs/interactive-capabilities/technical/tauri-command-map.json` -说明书、网站、搜索和 Agent 只看“功能 + 设置 + 子能力”。每项子能力都必须引用已注册 Tauri Command 或可解析的源码标记;这些证据不会进入公开目录。当前 **653** 个 Tauri 命令只用于实现覆盖审计。产品 UI 交互源码会在生成和检查时扫描并校验,但不会保存成随普通 UI 改动频繁变化的版本化快照。 +说明书、网站、搜索和 Agent 只看“功能 + 设置 + 子能力”。每项子能力都必须引用已注册 Tauri Command 或可解析的源码标记;这些证据不会进入公开目录。当前 **642** 个 Tauri 命令只用于实现覆盖审计。产品 UI 交互源码会在生成和检查时扫描并校验,但不会保存成随普通 UI 改动频繁变化的版本化快照。 -Docs, website, search, and agents see only features, settings, and documented sub-capabilities. Every sub-capability must reference a registered Tauri command or a resolvable source marker; evidence is stripped from public projections. The **653** Tauri commands remain implementation-audit evidence only. Product UI interaction sources are scanned and validated during generation and checks, but are not stored as a versioned snapshot that churns with ordinary UI changes. +Docs, website, search, and agents see only features, settings, and documented sub-capabilities. Every sub-capability must reference a registered Tauri command or a resolvable source marker; evidence is stripped from public projections. The **642** Tauri commands remain implementation-audit evidence only. Product UI interaction sources are scanned and validated during generation and checks, but are not stored as a versioned snapshot that churns with ordinary UI changes. ## 控制边界 / Control boundary diff --git a/docs/interactive-capabilities/technical/tauri-command-map.json b/docs/interactive-capabilities/technical/tauri-command-map.json index 55299214ee..0a6533e330 100644 --- a/docs/interactive-capabilities/technical/tauri-command-map.json +++ b/docs/interactive-capabilities/technical/tauri-command-map.json @@ -2,12 +2,12 @@ "schemaVersion": 2, "generatedFrom": "src/shared/interactive-capabilities/catalog.json", "catalogDigest": "b915ffcb329182de3e033d8e48186a1dbd5c683d975484567d9dfe9b9c595c13", - "commandCount": 653, + "commandCount": 642, "coverage": { - "commandCount": 653, + "commandCount": 642, "documentedCommandCount": 615, - "implementationCommandCount": 38, - "implementationDigest": "965d441b20c0092bc25c1dd48db3e31f72a977479fe9d1ff7c788d8e17d7395b" + "implementationCommandCount": 27, + "implementationDigest": "4d3b2e8145a6a97b622fdb78cf1c25275881328eb7ccbc3c92ae95bf798cb190" }, "commands": [ { @@ -1280,34 +1280,6 @@ "signature": "fn cleanup_invalid_workspaces( state: State<'_, AppState>, app: tauri::AppHandle, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result", "remoteWorkspacePolicy": "LegacyUnaudited" }, - { - "id": "cleanup_storage", - "moduleId": "storage_commands", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "cleanup_storage", - "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", - "signature": "fn cleanup_storage(state: State<'_, AppState>) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, - { - "id": "cleanup_storage_with_policy", - "moduleId": "storage_commands", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "cleanup_storage_with_policy", - "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", - "signature": "fn cleanup_storage_with_policy( state: State<'_, AppState>, policy: CleanupPolicy, ) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "clear_mcp_remote_auth", "moduleId": "mcp", @@ -3497,20 +3469,6 @@ "signature": "fn get_project_permission_rules( state: State<'_, AppState>, request: PermissionProjectRequest, ) -> Result", "remoteWorkspacePolicy": "RemoteRouted" }, - { - "id": "get_project_storage_paths", - "moduleId": "storage_commands", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "get_project_storage_paths", - "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", - "signature": "fn get_project_storage_paths( state: State<'_, AppState>, workspace_path: String, ) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "get_readonly_tools_info", "moduleId": "tool", @@ -3799,34 +3757,6 @@ "signature": "fn get_statistics( state: State<'_, AppState>, ) -> Result", "remoteWorkspacePolicy": "LegacyUnaudited" }, - { - "id": "get_storage_paths", - "moduleId": "storage_commands", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "get_storage_paths", - "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", - "signature": "fn get_storage_paths(state: State<'_, AppState>) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, - { - "id": "get_storage_statistics", - "moduleId": "storage_commands", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "get_storage_statistics", - "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", - "signature": "fn get_storage_statistics(state: State<'_, AppState>) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "get_subagent_detail", "moduleId": "subagent", @@ -4673,34 +4603,6 @@ "signature": "fn initialize_mcp_servers_non_destructive( state: State<'_, AppState>, startup_trace: State<'_, DesktopStartupTrace>, ) -> Result<(), String>", "remoteWorkspacePolicy": "LegacyUnaudited" }, - { - "id": "initialize_project_storage", - "moduleId": "storage_commands", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "initialize_project_storage", - "sourceFile": "src/apps/desktop/src/api/storage_commands.rs", - "signature": "fn initialize_project_storage( state: State<'_, AppState>, workspace_path: String, ) -> Result<(), String>", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, - { - "id": "initialize_snapshot", - "moduleId": "snapshot_service", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "initialize_snapshot", - "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", - "signature": "fn initialize_snapshot( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: SnapshotInitRequest, ) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "initialize_tray_after_startup", "moduleId": "system", @@ -6680,20 +6582,6 @@ "signature": "fn read_mcp_resource( state: State<'_, AppState>, request: ReadMCPResourceRequest, ) -> Result", "remoteWorkspacePolicy": "LegacyUnaudited" }, - { - "id": "record_file_change", - "moduleId": "snapshot_service", - "capabilityId": "feature.files-editor", - "capabilityIds": [ - "feature.files-editor" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "record_file_change", - "sourceFile": "src/apps/desktop/src/api/snapshot_service.rs", - "signature": "fn record_file_change( app_handle: AppHandle, runtime: State<'_, DesktopRuntimeContext>, request: RecordFileChangeRequest, ) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "recover_interrupted_dialog_turn", "moduleId": "agentic", @@ -6933,20 +6821,6 @@ "signature": "fn reload_custom_agents( state: State<'_, AppState>, request: ReloadCustomAgentsRequest, ) -> Result<(), String>", "remoteWorkspacePolicy": "LegacyUnaudited" }, - { - "id": "reload_global_config", - "moduleId": "commands", - "capabilityId": "feature.projects", - "capabilityIds": [ - "feature.projects" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "reload_global_config", - "sourceFile": "src/apps/desktop/src/api/commands.rs", - "signature": "fn reload_global_config() -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "reload_session_context", "moduleId": "agentic", @@ -9624,20 +9498,6 @@ "signature": "fn submit_user_answers( runtime: State<'_, DesktopRuntimeContext>, tool_id: String, answers: serde_json::Value, ) -> Result<(), String>", "remoteWorkspacePolicy": "LegacyUnaudited" }, - { - "id": "subscribe_config_updates", - "moduleId": "commands", - "capabilityId": "feature.projects", - "capabilityIds": [ - "feature.projects" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "subscribe_config_updates", - "sourceFile": "src/apps/desktop/src/api/commands.rs", - "signature": "fn subscribe_config_updates() -> Result<(), String>", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "subscribe_permission_requests", "moduleId": "agentic", @@ -9654,20 +9514,6 @@ "signature": "fn subscribe_permission_requests( app: AppHandle, runtime: State<'_, DesktopRuntimeContext>, ) -> Result<(), String>", "remoteWorkspacePolicy": "WorkspaceAgnostic" }, - { - "id": "sync_config_to_global", - "moduleId": "config", - "capabilityId": "setting.application.general", - "capabilityIds": [ - "setting.application.general" - ], - "documentedItemIds": [], - "visibility": "implementation", - "rustPath": "sync_config_to_global", - "sourceFile": "src/apps/desktop/src/api/config_api.rs", - "signature": "fn sync_config_to_global(_state: State<'_, AppState>) -> Result", - "remoteWorkspacePolicy": "LegacyUnaudited" - }, { "id": "terminal_ack", "moduleId": "terminal", diff --git a/src/apps/desktop/src/api/commands.rs b/src/apps/desktop/src/api/commands.rs index 087daab1d1..c1e2137c07 100644 --- a/src/apps/desktop/src/api/commands.rs +++ b/src/apps/desktop/src/api/commands.rs @@ -4974,39 +4974,11 @@ pub async fn cancel_search( Ok(()) } -#[tauri::command] -pub async fn reload_global_config() -> Result { - match bitfun_core::service::config::reload_global_config().await { - Ok(_) => { - info!("Global config reloaded"); - Ok("Configuration reloaded successfully".to_string()) - } - Err(e) => { - error!("Failed to reload global config: {}", e); - Err(format!("Failed to reload configuration: {}", e)) - } - } -} - #[tauri::command] pub async fn get_global_config_status() -> Result { Ok(bitfun_core::service::config::GlobalConfigManager::is_initialized()) } -#[tauri::command] -pub async fn subscribe_config_updates() -> Result<(), String> { - if let Some(mut receiver) = bitfun_core::service::config::subscribe_config_updates() { - tokio::spawn(async move { - while let Ok(event) = receiver.recv().await { - debug!("Config update event: {:?}", event); - } - }); - Ok(()) - } else { - Err("Config update subscription not available".to_string()) - } -} - #[tauri::command] pub async fn get_model_configs( state: State<'_, AppState>, diff --git a/src/apps/desktop/src/api/config_api.rs b/src/apps/desktop/src/api/config_api.rs index 30bc125042..b12c2f21cb 100644 --- a/src/apps/desktop/src/api/config_api.rs +++ b/src/apps/desktop/src/api/config_api.rs @@ -348,20 +348,6 @@ pub async fn reload_config(state: State<'_, AppState>) -> Result } } -#[tauri::command] -pub async fn sync_config_to_global(_state: State<'_, AppState>) -> Result { - match bitfun_core::service::config::reload_global_config().await { - Ok(_) => { - info!("Config synced to global service"); - Ok("Configuration synced to global service".to_string()) - } - Err(e) => { - error!("Failed to sync config to global service: {}", e); - Err(format!("Failed to sync config to global service: {}", e)) - } - } -} - #[tauri::command] pub async fn get_global_config_health() -> Result { Ok(bitfun_core::service::config::GlobalConfigManager::is_initialized()) diff --git a/src/apps/desktop/src/api/mod.rs b/src/apps/desktop/src/api/mod.rs index 85c9986458..b0a3e7343f 100644 --- a/src/apps/desktop/src/api/mod.rs +++ b/src/apps/desktop/src/api/mod.rs @@ -49,7 +49,6 @@ pub mod skill_api; pub mod snapshot_service; pub mod speech_api; pub mod ssh_api; -pub mod storage_commands; pub mod subagent_api; pub mod system_api; pub mod terminal_api; diff --git a/src/apps/desktop/src/api/remote_workspace_policy.rs b/src/apps/desktop/src/api/remote_workspace_policy.rs index 32398ec5a2..dc18ce8432 100644 --- a/src/apps/desktop/src/api/remote_workspace_policy.rs +++ b/src/apps/desktop/src/api/remote_workspace_policy.rs @@ -303,11 +303,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "cleanup_invalid_workspaces", RemoteWorkspacePolicy::LegacyUnaudited, ), - ("cleanup_storage", RemoteWorkspacePolicy::LegacyUnaudited), - ( - "cleanup_storage_with_policy", - RemoteWorkspacePolicy::LegacyUnaudited, - ), ( "clear_mcp_remote_auth", RemoteWorkspacePolicy::LegacyUnaudited, @@ -703,10 +698,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "get_pending_announcements", RemoteWorkspacePolicy::WorkspaceAgnostic, ), - ( - "get_project_storage_paths", - RemoteWorkspacePolicy::LegacyUnaudited, - ), ( "get_readonly_tools_info", RemoteWorkspacePolicy::LegacyUnaudited, @@ -761,11 +752,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = RemoteWorkspacePolicy::WorkspaceAgnostic, ), ("get_statistics", RemoteWorkspacePolicy::LegacyUnaudited), - ("get_storage_paths", RemoteWorkspacePolicy::LegacyUnaudited), - ( - "get_storage_statistics", - RemoteWorkspacePolicy::LegacyUnaudited, - ), ( "get_subagent_detail", RemoteWorkspacePolicy::LegacyUnaudited, @@ -875,14 +861,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "initialize_mcp_servers_non_destructive", RemoteWorkspacePolicy::LegacyUnaudited, ), - ( - "initialize_project_storage", - RemoteWorkspacePolicy::LegacyUnaudited, - ), - ( - "initialize_snapshot", - RemoteWorkspacePolicy::LegacyUnaudited, - ), ( "initialize_tray_after_startup", RemoteWorkspacePolicy::LocalOnly, @@ -1260,7 +1238,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = ), ("read_file_content", RemoteWorkspacePolicy::LegacyUnaudited), ("read_mcp_resource", RemoteWorkspacePolicy::LegacyUnaudited), - ("record_file_change", RemoteWorkspacePolicy::LegacyUnaudited), ( "refresh_model_client", RemoteWorkspacePolicy::LegacyUnaudited, @@ -1304,10 +1281,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "reload_custom_agents", RemoteWorkspacePolicy::LegacyUnaudited, ), - ( - "reload_global_config", - RemoteWorkspacePolicy::LegacyUnaudited, - ), ( "reload_session_context", RemoteWorkspacePolicy::RemoteRouted, @@ -1848,14 +1821,6 @@ pub const REMOTE_WORKSPACE_COMMAND_POLICIES: &[(&str, RemoteWorkspacePolicy)] = "submit_user_answers", RemoteWorkspacePolicy::LegacyUnaudited, ), - ( - "subscribe_config_updates", - RemoteWorkspacePolicy::LegacyUnaudited, - ), - ( - "sync_config_to_global", - RemoteWorkspacePolicy::LegacyUnaudited, - ), ("terminal_ack", RemoteWorkspacePolicy::RemoteRouted), ("terminal_close", RemoteWorkspacePolicy::RemoteRouted), ("terminal_create", RemoteWorkspacePolicy::RemoteRouted), @@ -2200,8 +2165,6 @@ mod tests { "check_git_isolation", "check_path_exists", "cleanup_invalid_workspaces", - "cleanup_storage", - "cleanup_storage_with_policy", "clear_mcp_remote_auth", "clear_session_thread_goal", "close_workspace", @@ -2283,7 +2246,6 @@ mod tests { "get_opened_workspaces", "get_operation_diff", "get_operation_summary", - "get_project_storage_paths", "get_readonly_tools_info", "get_recent_workspaces", "get_runtime_capabilities", @@ -2299,8 +2261,6 @@ mod tests { "get_snapshot_sessions", "get_snapshot_system_stats", "get_statistics", - "get_storage_paths", - "get_storage_statistics", "get_subagent_detail", "get_tool_info", "get_turn_files", @@ -2313,8 +2273,6 @@ mod tests { "initialize_ai", "initialize_mcp_servers", "initialize_mcp_servers_non_destructive", - "initialize_project_storage", - "initialize_snapshot", "initialize_workspace_startup_state", "install_acp_client_cli", "list_agent_companion_pets", @@ -2379,13 +2337,11 @@ mod tests { "read_background_command_output", "read_file_content", "read_mcp_resource", - "record_file_change", "refresh_model_client", "reject_file", "reject_operation", "reload_config", "reload_custom_agents", - "reload_global_config", "reload_subagents", "remove_recent_workspace", "rename_file", @@ -2442,8 +2398,6 @@ mod tests { "submit_acp_permission_response", "submit_mcp_interaction_response", "submit_user_answers", - "subscribe_config_updates", - "sync_config_to_global", "terminal_get", "terminal_get_shells", "terminal_list", diff --git a/src/apps/desktop/src/api/snapshot_service.rs b/src/apps/desktop/src/api/snapshot_service.rs index 681dc4caea..dfda97eda3 100644 --- a/src/apps/desktop/src/api/snapshot_service.rs +++ b/src/apps/desktop/src/api/snapshot_service.rs @@ -7,7 +7,7 @@ use bitfun_core::service::remote_ssh::workspace_state::is_remote_path; use bitfun_core::service::snapshot::{ ensure_snapshot_manager_for_workspace, get_snapshot_manager_for_workspace, initialize_snapshot_manager_for_workspace, open_snapshot_manager_for_view, FileChangeEntry, - OperationType, SnapshotConfig, SnapshotManager, + OperationType, SnapshotManager, }; use bitfun_runtime_ports::{AgentSessionWorkspaceLocation, SessionStoragePathRequest}; use log::{info, warn}; @@ -53,33 +53,6 @@ async fn ensure_local_runtime_ownership( .map_err(|error| error.to_string()) } -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct SnapshotInitRequest { - #[serde(alias = "workspacePath")] - pub workspace_path: String, - pub config: Option, - #[serde(flatten)] - pub remote_scope: SnapshotRemoteScope, -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct RecordFileChangeRequest { - #[serde(alias = "sessionId")] - pub session_id: String, - #[serde(alias = "turnIndex")] - pub turn_index: usize, - #[serde(alias = "filePath")] - pub file_path: String, - #[serde(alias = "operationType")] - pub operation_type: String, // "Create", "Modify", "Delete", "Rename" - #[serde(alias = "toolName")] - pub tool_name: String, - #[serde(alias = "workspacePath")] - pub workspace_path: String, - #[serde(flatten)] - pub remote_scope: SnapshotRemoteScope, -} - #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RollbackSessionRequest { #[serde(alias = "sessionId")] @@ -240,48 +213,6 @@ pub struct SnapshotWorkspaceRequest { pub remote_scope: SnapshotRemoteScope, } -#[tauri::command] -pub async fn initialize_snapshot( - app_handle: AppHandle, - runtime: State<'_, DesktopRuntimeContext>, - request: SnapshotInitRequest, -) -> Result { - // Remote workspaces don't support snapshot system - if request.remote_scope.declares_remote() || is_remote_path(&request.workspace_path).await { - return Ok(serde_json::json!({ - "success": true, - "message": "Snapshot system skipped for remote workspace" - })); - } - ensure_local_runtime_ownership(runtime.inner(), &request.workspace_path).await?; - - let workspace_dir = PathBuf::from(&request.workspace_path); - - if !workspace_dir.exists() { - return Err(format!( - "Workspace directory does not exist: {}", - request.workspace_path - )); - } - - initialize_snapshot_manager_for_workspace(workspace_dir, request.config) - .await - .map_err(|e| format!("Failed to initialize snapshot system: {}", e))?; - - let _ = app_handle.emit( - "snapshot_initialized", - serde_json::json!({ - "workspace_path": request.workspace_path, - "timestamp": chrono::Utc::now().to_rfc3339() - }), - ); - - Ok(serde_json::json!({ - "success": true, - "message": "Snapshot system initialized" - })) -} - async fn resolve_workspace_dir(workspace_path: &str) -> Result { if workspace_path.trim().is_empty() { return Err("workspacePath is required".to_string()); @@ -479,88 +410,6 @@ async fn begin_snapshot_history_mutation( }) } -async fn begin_snapshot_record_mutation( - runtime: &DesktopRuntimeContext, - workspace_path: &str, - session_id: &str, -) -> Result { - let compatibility = runtime.session_application().compatibility(); - let storage_path = compatibility - .resolve_persisted_session_storage_path(SessionStoragePathRequest { - workspace_path: PathBuf::from(workspace_path), - remote_connection_id: None, - remote_ssh_host: None, - }) - .await - .map_err(|error| { - format!("Failed to resolve session storage before snapshot recording: {error}") - })?; - let mutation = compatibility - .begin_persisted_session_mutation(&storage_path, session_id) - .await - .map_err(|error| format!("Failed to lock snapshot recording: {error}"))?; - compatibility - .ensure_snapshot_record_allowed(&mutation) - .await - .map_err(|error| format!("Failed to admit snapshot recording: {error}"))?; - Ok(mutation) -} - -#[tauri::command] -pub async fn record_file_change( - app_handle: AppHandle, - runtime: State<'_, DesktopRuntimeContext>, - request: RecordFileChangeRequest, -) -> Result { - ensure_local_snapshot_mutation_path(&request.workspace_path, &request.remote_scope).await?; - ensure_local_runtime_ownership(runtime.inner(), &request.workspace_path).await?; - let manager = - ensure_snapshot_manager_ready_for(&request.workspace_path, "record_file_change").await?; - - let operation_type = match request.operation_type.as_str() { - "Create" => OperationType::Create, - "Modify" => OperationType::Modify, - "Delete" => OperationType::Delete, - "Rename" => OperationType::Rename, - _ => { - return Err(format!( - "Unknown operation type: {}", - request.operation_type - )); - } - }; - - let _record_mutation = begin_snapshot_record_mutation( - runtime.inner(), - &request.workspace_path, - &request.session_id, - ) - .await?; - - let snapshot_id = manager - .record_file_change( - &request.session_id, - request.turn_index, - PathBuf::from(&request.file_path), - operation_type, - request.tool_name.clone(), - ) - .await - .map_err(|e| format!("Failed to record file change: {}", e))?; - - let _ = app_handle.emit( - "file_change_recorded", - serde_json::json!({ - "session_id": request.session_id, - "turn_index": request.turn_index, - "file_path": request.file_path, - "snapshot_id": snapshot_id, - }), - ); - - Ok(snapshot_id) -} - #[tauri::command] pub async fn rollback_session( app_handle: AppHandle, @@ -1484,15 +1333,6 @@ mod tests { !targeted_rollback.contains("begin_snapshot_history_mutation"), "targeted rollback must not reacquire the Session mutation owned by the Agent Session transaction" ); - - let record = source - .split_once("pub async fn record_file_change") - .expect("record_file_change remains present") - .1 - .split_once("pub async fn rollback_session") - .expect("rollback_session remains present") - .0; - assert!(record.contains("begin_snapshot_record_mutation")); } #[tokio::test] diff --git a/src/apps/desktop/src/api/storage_commands.rs b/src/apps/desktop/src/api/storage_commands.rs deleted file mode 100644 index cfbdf77fa3..0000000000 --- a/src/apps/desktop/src/api/storage_commands.rs +++ /dev/null @@ -1,177 +0,0 @@ -//! Storage Management API - -use crate::api::AppState; -use bitfun_core::infrastructure::storage::{CleanupPolicy, CleanupResult, CleanupService}; -use serde::{Deserialize, Serialize}; -use std::path::PathBuf; -use tauri::State; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct StoragePathsInfo { - pub user_config_dir: PathBuf, - pub user_data_dir: PathBuf, - pub cache_root: PathBuf, - pub logs_dir: PathBuf, - pub temp_dir: PathBuf, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct StorageStats { - pub total_size_mb: f64, - pub config_size_mb: f64, - pub cache_size_mb: f64, - pub logs_size_mb: f64, - pub temp_size_mb: f64, -} - -#[tauri::command] -pub async fn get_storage_paths(state: State<'_, AppState>) -> Result { - let workspace_service = &state.workspace_service; - let path_manager = workspace_service.path_manager(); - - Ok(StoragePathsInfo { - user_config_dir: path_manager.user_config_dir(), - user_data_dir: path_manager.user_data_dir(), - cache_root: path_manager.cache_root(), - logs_dir: path_manager.logs_dir(), - temp_dir: path_manager.temp_dir(), - }) -} - -#[tauri::command] -pub async fn get_project_storage_paths( - state: State<'_, AppState>, - workspace_path: String, -) -> Result { - let workspace_service = &state.workspace_service; - let path_manager = workspace_service.path_manager(); - - let workspace_path = PathBuf::from(workspace_path); - - Ok(ProjectStoragePathsInfo { - project_root: path_manager.project_root(&workspace_path), - runtime_root: path_manager.project_runtime_root(&workspace_path), - agents_dir: path_manager.project_agents_dir(&workspace_path), - sessions_dir: path_manager.project_sessions_dir(&workspace_path), - plans_dir: path_manager.project_plans_dir(&workspace_path), - }) -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ProjectStoragePathsInfo { - pub project_root: PathBuf, - pub runtime_root: PathBuf, - pub agents_dir: PathBuf, - pub sessions_dir: PathBuf, - pub plans_dir: PathBuf, -} - -#[tauri::command] -pub async fn cleanup_storage(state: State<'_, AppState>) -> Result { - let workspace_service = &state.workspace_service; - let path_manager = workspace_service.path_manager(); - - let policy = CleanupPolicy::default(); - let cleanup_service = CleanupService::new((**path_manager).clone(), policy); - - cleanup_service - .cleanup_all() - .await - .map_err(|e| format!("Cleanup failed: {}", e)) -} - -#[tauri::command] -pub async fn cleanup_storage_with_policy( - state: State<'_, AppState>, - policy: CleanupPolicy, -) -> Result { - let workspace_service = &state.workspace_service; - let path_manager = workspace_service.path_manager(); - - let cleanup_service = CleanupService::new((**path_manager).clone(), policy); - - cleanup_service - .cleanup_all() - .await - .map_err(|e| format!("Cleanup failed: {}", e)) -} - -#[tauri::command] -pub async fn get_storage_statistics(state: State<'_, AppState>) -> Result { - let workspace_service = &state.workspace_service; - let path_manager = workspace_service.path_manager(); - - let config_size = calculate_dir_size(&path_manager.user_config_dir()).await?; - let cache_size = calculate_dir_size(&path_manager.cache_root()).await?; - let logs_size = calculate_dir_size(&path_manager.logs_dir()).await?; - let temp_size = calculate_dir_size(&path_manager.temp_dir()).await?; - - let total_size = config_size + cache_size + logs_size + temp_size; - - Ok(StorageStats { - total_size_mb: bytes_to_mb(total_size), - config_size_mb: bytes_to_mb(config_size), - cache_size_mb: bytes_to_mb(cache_size), - logs_size_mb: bytes_to_mb(logs_size), - temp_size_mb: bytes_to_mb(temp_size), - }) -} - -#[tauri::command] -pub async fn initialize_project_storage( - state: State<'_, AppState>, - workspace_path: String, -) -> Result<(), String> { - let workspace_service = &state.workspace_service; - let runtime_service = workspace_service.runtime_service(); - - let workspace_path = PathBuf::from(workspace_path); - - runtime_service - .ensure_local_workspace_runtime(&workspace_path) - .await - .map(|_| ()) - .map_err(|e| format!("Failed to initialize project runtime: {}", e)) -} - -fn calculate_dir_size( - dir: &std::path::Path, -) -> std::pin::Pin> + Send + '_>> { - Box::pin(async move { - let mut total = 0u64; - - if !dir.exists() { - return Ok(0); - } - - let mut read_dir = tokio::fs::read_dir(dir) - .await - .map_err(|e| format!("Failed to read directory: {}", e))?; - - while let Some(entry) = read_dir - .next_entry() - .await - .map_err(|e| format!("Failed to read directory entry: {}", e))? - { - let metadata = entry - .metadata() - .await - .map_err(|e| format!("Failed to get metadata: {}", e))?; - - if metadata.is_dir() { - total += calculate_dir_size(&entry.path()).await?; - } else { - total += metadata.len(); - } - } - - Ok(total) - }) -} - -fn bytes_to_mb(bytes: u64) -> f64 { - bytes as f64 / 1_048_576.0 -} diff --git a/src/apps/desktop/src/lib.rs b/src/apps/desktop/src/lib.rs index da8082f1cc..8be1547450 100644 --- a/src/apps/desktop/src/lib.rs +++ b/src/apps/desktop/src/lib.rs @@ -87,7 +87,6 @@ use api::session_api::*; use api::skill_api::*; use api::snapshot_service::*; use api::speech_api::*; -use api::storage_commands::*; use api::subagent_api::*; use api::system_api::*; use api::tool_api::*; @@ -1570,7 +1569,6 @@ pub async fn run() { import_config, validate_config, reload_config, - sync_config_to_global, get_global_config_health, get_runtime_logging_info, export_diagnostics_bundle, @@ -1672,8 +1670,6 @@ pub async fn run() { compute_diff, apply_patch, save_merged_diff_content, - initialize_snapshot, - record_file_change, rollback_session, rollback_session_to_turn, accept_session, @@ -1696,12 +1692,6 @@ pub async fn run() { get_file_change_history, get_all_modified_files, get_baseline_snapshot_diff, - get_storage_paths, - get_project_storage_paths, - cleanup_storage, - cleanup_storage_with_policy, - get_storage_statistics, - initialize_project_storage, // Session persistence API list_persisted_sessions, search_session_content, @@ -1761,9 +1751,7 @@ pub async fn run() { get_acp_session_commands, set_acp_session_model, set_acp_session_config_option, - reload_global_config, get_global_config_status, - subscribe_config_updates, get_model_configs, get_ai_model_catalog, project_ai_model_reasoning_catalog, diff --git a/src/apps/desktop/src/runtime/mod.rs b/src/apps/desktop/src/runtime/mod.rs index edc899f395..d83296fb3c 100644 --- a/src/apps/desktop/src/runtime/mod.rs +++ b/src/apps/desktop/src/runtime/mod.rs @@ -308,8 +308,6 @@ mod tests { } for mutation in [ - "pub async fn initialize_snapshot", - "pub async fn record_file_change", "pub async fn rollback_session", "pub async fn rollback_session_to_turn", "pub async fn accept_session", diff --git a/src/shared/interactive-capabilities/catalog.json b/src/shared/interactive-capabilities/catalog.json index 5ead54c5b8..912bd19ba8 100644 --- a/src/shared/interactive-capabilities/catalog.json +++ b/src/shared/interactive-capabilities/catalog.json @@ -186,35 +186,22 @@ "check_command_exists", "check_commands_exist" ], - "storageMaintenance": [ - "cleanup_storage", - "cleanup_storage_with_policy", - "get_project_storage_paths", - "get_storage_paths", - "get_storage_statistics" - ], "runtimeLifecycle": [ "ensure_assistant_bootstrap", "ensure_coordinator_session", "initialize_ai", "initialize_mcp_servers", "initialize_mcp_servers_non_destructive", - "initialize_project_storage", - "initialize_snapshot", "initialize_tray_after_startup", "initialize_workspace_startup_state", - "reload_config", - "reload_global_config", - "subscribe_config_updates" + "reload_config" ], "genericConfigPrimitives": [ "get_config", "get_configs", - "set_config", - "sync_config_to_global" + "set_config" ], "persistencePrimitives": [ - "record_file_change", "save_session_metadata", "save_session_turn", "touch_session_activity" @@ -8960,9 +8947,6 @@ "browser": { "capabilityId": "feature.browser" }, - "storage_commands": { - "capabilityId": "feature.files-editor" - }, "announcement": { "capabilityId": "setting.application.general" },