feat(folder): unify workspace state streaming for tree and git panels

Introduce a shared workspace-state backend stream with snapshot/delta APIs for file tree and git changes.

Migrate both aux panels to a common frontend workspace store with lifecycle-safe stream handling.

Apply batched watch throttling, path-aware git refresh gating, no-op delta suppression, and bounded history compaction to improve runtime stability.
This commit is contained in:
xintaofei
2026-04-14 22:26:36 +08:00
parent 90e8bb645a
commit b5e8fd8acb
15 changed files with 2856 additions and 1419 deletions

View File

@@ -142,27 +142,6 @@ pub async fn get_file_tree(
Ok(Json(result))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RootPathParams {
pub root_path: String,
}
pub async fn start_file_tree_watch(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<RootPathParams>,
) -> Result<Json<()>, AppCommandError> {
folder_commands::start_file_tree_watch_core(state.emitter.clone(), params.root_path).await?;
Ok(Json(()))
}
pub async fn stop_file_tree_watch(
Json(params): Json<RootPathParams>,
) -> Result<Json<()>, AppCommandError> {
folder_commands::stop_file_tree_watch(params.root_path).await?;
Ok(Json(()))
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OpenSettingsWindowParams {

View File

@@ -1,7 +1,7 @@
mod error;
pub mod acp;
pub mod chat_channel;
pub mod conversations;
mod error;
pub mod experts;
pub mod files;
pub mod folder_commands;
@@ -14,3 +14,4 @@ pub mod system_settings;
pub mod terminal;
pub mod version_control;
pub mod web_server;
pub mod workspace_state;

View File

@@ -0,0 +1,50 @@
use std::sync::Arc;
use axum::{extract::Extension, Json};
use serde::Deserialize;
use crate::app_error::AppCommandError;
use crate::app_state::AppState;
use crate::commands::workspace_state as workspace_state_commands;
use crate::workspace_state::WorkspaceSnapshotResponse;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceRootPathParams {
pub root_path: String,
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceSnapshotParams {
pub root_path: String,
pub since_seq: Option<u64>,
}
pub async fn start_workspace_state_stream(
Extension(state): Extension<Arc<AppState>>,
Json(params): Json<WorkspaceRootPathParams>,
) -> Result<Json<WorkspaceSnapshotResponse>, AppCommandError> {
let result = workspace_state_commands::start_workspace_state_stream_core(
state.emitter.clone(),
params.root_path,
)
.await?;
Ok(Json(result))
}
pub async fn stop_workspace_state_stream(
Json(params): Json<WorkspaceRootPathParams>,
) -> Result<Json<()>, AppCommandError> {
workspace_state_commands::stop_workspace_state_stream_core(params.root_path).await?;
Ok(Json(()))
}
pub async fn get_workspace_snapshot(
Json(params): Json<WorkspaceSnapshotParams>,
) -> Result<Json<WorkspaceSnapshotResponse>, AppCommandError> {
let result =
workspace_state_commands::get_workspace_snapshot_core(params.root_path, params.since_seq)
.await?;
Ok(Json(result))
}