feat(state): Alirkan mention_index lewat ToolCtx dan AppStateRest, bangun index di background thread
Menambahkan field mention_index: MentionIndex ke ToolCtx/ToolCtxBuilder dan AppStateRest, mengikuti pola dir_cache yang sudah ada. AppStateRest::new() sekarang men-spawn thread background yang men-walk setiap workspace root via ignore::Walk, membangun daftar path file (dengan prefix [N] untuk root selain yang pertama) dan mengisi mention_index — data ini yang akan dipakai fitur autocomplete @file-mention.
This commit is contained in:
+42
-1
@@ -9,7 +9,7 @@ use std::path::PathBuf;
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
use super::misc::{DirCache, InputState, MiscState, ScrollState};
|
use super::misc::{DirCache, InputState, MentionIndex, MiscState, ScrollState};
|
||||||
use super::runtime::{SessionRuntime, TurnEvent};
|
use super::runtime::{SessionRuntime, TurnEvent};
|
||||||
use super::types::{Origin, Toast, TranscriptCache};
|
use super::types::{Origin, Toast, TranscriptCache};
|
||||||
use crate::app::lsp::LspManager;
|
use crate::app::lsp::LspManager;
|
||||||
@@ -54,6 +54,7 @@ pub struct AppStateRest {
|
|||||||
pub memory_dir: PathBuf,
|
pub memory_dir: PathBuf,
|
||||||
pub worktrees_dir: PathBuf,
|
pub worktrees_dir: PathBuf,
|
||||||
pub dir_cache: Arc<RwLock<DirCache>>,
|
pub dir_cache: Arc<RwLock<DirCache>>,
|
||||||
|
pub mention_index: MentionIndex,
|
||||||
pub edit_log: EditLog,
|
pub edit_log: EditLog,
|
||||||
pub session_runtime: Option<SessionRuntime>,
|
pub session_runtime: Option<SessionRuntime>,
|
||||||
pub sessions: Vec<crate::model::session::Session>,
|
pub sessions: Vec<crate::model::session::Session>,
|
||||||
@@ -110,6 +111,7 @@ impl AppStateRest {
|
|||||||
turn_in_flight: Arc::new(Mutex::new(false)),
|
turn_in_flight: Arc::new(Mutex::new(false)),
|
||||||
abort_flag: Arc::new(std::sync::atomic::AtomicBool::new(false)),
|
abort_flag: Arc::new(std::sync::atomic::AtomicBool::new(false)),
|
||||||
dir_cache: Arc::new(RwLock::new(dir_cache)),
|
dir_cache: Arc::new(RwLock::new(dir_cache)),
|
||||||
|
mention_index: MentionIndex::new(),
|
||||||
edit_log: EditLog::new(session_dir),
|
edit_log: EditLog::new(session_dir),
|
||||||
session_runtime: Some(SessionRuntime::new(session_dir.to_path_buf())),
|
session_runtime: Some(SessionRuntime::new(session_dir.to_path_buf())),
|
||||||
workflow_engine: WorkflowEngine::new(),
|
workflow_engine: WorkflowEngine::new(),
|
||||||
@@ -204,6 +206,44 @@ impl AppStateRest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fire-and-forget background file index build for `@file` mention
|
||||||
|
// autocomplete.
|
||||||
|
//
|
||||||
|
// Flow: spawn OS thread -> `ignore::Walk` each workspace root,
|
||||||
|
// collecting file paths (workspace-index-prefixed for roots beyond
|
||||||
|
// the first, matching `resolve_path`'s `[N]path` convention) -> stop
|
||||||
|
// once 50,000 entries are collected -> store the result in
|
||||||
|
// `mention_index`.
|
||||||
|
//
|
||||||
|
// Why a raw thread and not a background tokio task: there is no
|
||||||
|
// persistent async runtime driving the render loop, and this is
|
||||||
|
// blocking filesystem I/O -- a dedicated thread keeps startup
|
||||||
|
// non-blocking. Not joined, same rationale as the LSP provisioning
|
||||||
|
// thread above: a slow/huge repo must not delay the TUI appearing.
|
||||||
|
{
|
||||||
|
let mention_index = state.mention_index.clone();
|
||||||
|
let roots = state.workspace_roots.clone();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
const MAX_MENTION_ENTRIES: usize = 50_000;
|
||||||
|
let mut paths = Vec::new();
|
||||||
|
'roots: for (i, root) in roots.iter().enumerate() {
|
||||||
|
for entry in ignore::Walk::new(root).flatten() {
|
||||||
|
if !entry.path().is_file() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let rel = entry.path().strip_prefix(root).unwrap_or(entry.path());
|
||||||
|
let rel_str = rel.display().to_string();
|
||||||
|
let formatted = if i == 0 { rel_str } else { format!("[{i}]{rel_str}") };
|
||||||
|
paths.push(formatted);
|
||||||
|
if paths.len() >= MAX_MENTION_ENTRIES {
|
||||||
|
break 'roots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mention_index.set(paths);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,6 +318,7 @@ impl AppStateRest {
|
|||||||
memory_dir: self.memory_dir.clone(),
|
memory_dir: self.memory_dir.clone(),
|
||||||
worktrees_dir: self.worktrees_dir.clone(),
|
worktrees_dir: self.worktrees_dir.clone(),
|
||||||
dir_cache: self.dir_cache.clone(),
|
dir_cache: self.dir_cache.clone(),
|
||||||
|
mention_index: self.mention_index.clone(),
|
||||||
origin,
|
origin,
|
||||||
graduated_checks: Vec::new(),
|
graduated_checks: Vec::new(),
|
||||||
lsp_manager: self.lsp_manager.clone(),
|
lsp_manager: self.lsp_manager.clone(),
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ pub struct ToolCtx {
|
|||||||
pub memory_dir: PathBuf,
|
pub memory_dir: PathBuf,
|
||||||
pub worktrees_dir: PathBuf,
|
pub worktrees_dir: PathBuf,
|
||||||
pub dir_cache: std::sync::Arc<tokio::sync::RwLock<super::app::state::misc::DirCache>>,
|
pub dir_cache: std::sync::Arc<tokio::sync::RwLock<super::app::state::misc::DirCache>>,
|
||||||
|
pub mention_index: super::app::state::misc::MentionIndex,
|
||||||
pub origin: crate::app::state::types::Origin,
|
pub origin: crate::app::state::types::Origin,
|
||||||
pub graduated_checks: Vec<GraduatedCheck>,
|
pub graduated_checks: Vec<GraduatedCheck>,
|
||||||
pub lsp_manager: Arc<Mutex<crate::app::lsp::LspManager>>,
|
pub lsp_manager: Arc<Mutex<crate::app::lsp::LspManager>>,
|
||||||
@@ -94,6 +95,7 @@ pub struct ToolCtxBuilder {
|
|||||||
pub memory_dir: PathBuf,
|
pub memory_dir: PathBuf,
|
||||||
pub worktrees_dir: PathBuf,
|
pub worktrees_dir: PathBuf,
|
||||||
pub dir_cache: std::sync::Arc<tokio::sync::RwLock<super::app::state::misc::DirCache>>,
|
pub dir_cache: std::sync::Arc<tokio::sync::RwLock<super::app::state::misc::DirCache>>,
|
||||||
|
pub mention_index: super::app::state::misc::MentionIndex,
|
||||||
pub origin: crate::app::state::types::Origin,
|
pub origin: crate::app::state::types::Origin,
|
||||||
pub graduated_checks: Vec<GraduatedCheck>,
|
pub graduated_checks: Vec<GraduatedCheck>,
|
||||||
pub lsp_manager: Arc<Mutex<crate::app::lsp::LspManager>>,
|
pub lsp_manager: Arc<Mutex<crate::app::lsp::LspManager>>,
|
||||||
@@ -110,6 +112,7 @@ impl Default for ToolCtxBuilder {
|
|||||||
memory_dir: PathBuf::new(),
|
memory_dir: PathBuf::new(),
|
||||||
worktrees_dir: PathBuf::new(),
|
worktrees_dir: PathBuf::new(),
|
||||||
dir_cache: std::sync::Arc::new(tokio::sync::RwLock::new(super::app::state::misc::DirCache::new())),
|
dir_cache: std::sync::Arc::new(tokio::sync::RwLock::new(super::app::state::misc::DirCache::new())),
|
||||||
|
mention_index: super::app::state::misc::MentionIndex::new(),
|
||||||
origin: crate::app::state::types::Origin::Main,
|
origin: crate::app::state::types::Origin::Main,
|
||||||
graduated_checks: Vec::new(),
|
graduated_checks: Vec::new(),
|
||||||
lsp_manager: Arc::new(Mutex::new(crate::app::lsp::LspManager::new())),
|
lsp_manager: Arc::new(Mutex::new(crate::app::lsp::LspManager::new())),
|
||||||
@@ -138,6 +141,7 @@ impl ToolCtxBuilder {
|
|||||||
memory_dir: self.memory_dir,
|
memory_dir: self.memory_dir,
|
||||||
worktrees_dir: self.worktrees_dir,
|
worktrees_dir: self.worktrees_dir,
|
||||||
dir_cache: self.dir_cache,
|
dir_cache: self.dir_cache,
|
||||||
|
mention_index: self.mention_index,
|
||||||
origin: self.origin,
|
origin: self.origin,
|
||||||
graduated_checks: self.graduated_checks,
|
graduated_checks: self.graduated_checks,
|
||||||
lsp_manager: self.lsp_manager,
|
lsp_manager: self.lsp_manager,
|
||||||
|
|||||||
Reference in New Issue
Block a user