Files
zesdex/crates/zesdex-backend/src/app/lsp/provisioner/config.rs
T
asepharyana 9a67137954 refactor: massive codebase restructuring — naming, splitting, DRY
Crate renames:
  - zesdex-entities::seaorm → domain (misleading name, no SeaORM used)
  - zesdex-dto → merged into zesdex-entities (100% re-exports)
  - zesdex-libs → zesdex-infra (vague name)

Module renames:
  - app/harness → guard (misleading: safety gatekeeper, not test harness)
  - runtime/commands → action_dispatch (name clashed with controller/command)
  - resources → prompts (embedded prompt text, not general resources)
  - tool/seqthink → sequential_think (unreadable abbreviation)
  - msglog/query → insert (module only inserts, never queries)

Dead code removal:
  - app/mode/help.rs (orphaned — not declared in mod.rs)
  - app/mode/loading.rs (orphaned — not declared in mod.rs)

File splitting (71 new files, avg ~115 lines/file):
  - app/runtime/actions/: 1→8 files (was 2030 lines)
  - view/overlays/: 1→16 files (was 1167 lines)
  - tool/lsp/: 1→8 per-tool files (was 909 lines)
  - main.rs: 1→5 files (session, daemon, attach, event_loop)
  - workflow/engine + hive_mind: 2→10 files
  - subagent/engine + auto: 2→9 files
  - lsp/provisioner: 1→5 files
  - review/: 1→6 files
  - guard/: 1→2 files (extracted patterns)
  - state/misc: 1→3 files (input, scroll)
  - mcp/: 1→3 files (transport, adapter)
  - stream/json_repair extracted from turn.rs

DRY:
  - Pattern constants (STUB_PATTERNS etc) in guard/patterns shared with subagent
  - 3 near-identical background spawners → 1 generic + thin wrappers
  - Shared spawn_subagent_with_drain() extracted
  - Shared create_session() in main
  - write_osc52 deduplicated

Bug fixes:
  - archive_message(): sess.db → db (wrong variable name)
  - execute_one_tool(): wrong parameter name
  - check_credential_read() function was missing (restored from test expectations)
2026-07-17 09:08:41 +07:00

227 lines
8.9 KiB
Rust

//! Static language server definitions and core types.
//!
//! Defines the set of supported LSP servers, their install tiers, and the
//! result/enum types used across the provisioner.
/// Optional progress callback type (non-owning, caller ensures liveness
/// for the duration of the provisioning call).
/// Intended to be hooked up to a UI toast / status-bar mechanism.
pub type ProgressFn<'a> = Option<&'a dyn Fn(&str)>;
/// Result of attempting to make a single language server available.
///
/// The caller should switch on this variant: `AlreadyAvailable` and
/// Installed both mean the binary can be launched; Failed means we
/// gave up and the user needs to install manually (see `manual_instructions`).
#[derive(Debug, Clone)]
pub enum ProvisionResult {
/// Binary was already on PATH — no install was needed.
AlreadyAvailable {
server_name: String,
language: String,
binary_path: String,
},
/// Provisioner successfully installed the binary during this run.
Installed {
server_name: String,
language: String,
binary_path: String,
},
/// Every install tier failed. Tells the user how to install by hand.
Failed {
language: String,
server_name: String,
reason: String,
},
}
/// Sentinel command names used by `provision_single` to detect "download"
/// tiers (which are dispatched to `download_*` helpers rather than
/// `run_command`). Kept as constants so `supported_servers` stays readable.
pub(super) const DOWNLOAD_RUST_BIN: &str = "__download_rust_analyzer__";
pub(super) const DOWNLOAD_JDTLS: &str = "__download_jdtls__";
/// Static description of a single language server: how to detect it,
/// what file extensions it handles, and how to install it.
#[derive(Debug, Clone)]
pub struct LanguageServerDef {
/// Human-readable server name (e.g. "rust-analyzer").
pub name: String,
/// LSP language identifier (e.g. "rust").
pub language: String,
/// File extensions this server handles (with leading dot).
pub extensions: Vec<String>,
/// Candidate binary names — the provisioner accepts whichever appears on PATH.
pub binary_names: Vec<String>,
/// Install strategies, tried in order until one succeeds.
pub install_tiers: Vec<InstallTier>,
}
/// A single install attempt: a command (plus args) gated by a prerequisite.
///
/// `requires` lists binaries that must already be on PATH for this tier
/// to be considered. If any required binary is missing, the tier is
/// skipped (not attempted) so we don't produce misleading failures
/// like "rustup: command not found" when the real fix was to install
/// rustup first.
#[derive(Debug, Clone)]
pub struct InstallTier {
/// Short human-readable label, e.g. "rustup component".
pub label: String,
/// Binaries that must be available before this tier is attempted.
pub requires: Vec<String>,
/// Command to run.
pub command: String,
/// Arguments to pass to the command.
pub args: Vec<String>,
}
/// Return the static set of supported language servers.
///
/// The order is significant: it determines provisioning order and
/// the order results appear in `provision_all_with_progress()`. Tier 1 paths are
/// the canonical/idiomatic install for each ecosystem; later tiers
/// are fallbacks for hosts that lack the primary tooling.
///
/// Why hard-coded rather than loaded from settings: the set is small,
/// changes rarely, and bundling it lets the provisioner run before any
/// user config has been read (e.g. on first launch).
pub fn supported_servers() -> Vec<LanguageServerDef> {
vec![
LanguageServerDef {
name: "rust-analyzer".to_string(),
language: "rust".to_string(),
extensions: vec![".rs".to_string()],
binary_names: vec!["rust-analyzer".to_string()],
install_tiers: vec![
InstallTier {
label: "rustup component".to_string(),
requires: vec!["rustup".to_string()],
command: "rustup".to_string(),
args: vec![
"component".to_string(),
"add".to_string(),
"rust-analyzer".to_string(),
],
},
InstallTier {
label: "pacman".to_string(),
requires: vec!["pacman".to_string()],
command: "pacman".to_string(),
args: vec![
"-S".to_string(),
"--noconfirm".to_string(),
"--needed".to_string(),
"rust-analyzer".to_string(),
],
},
InstallTier {
label: "brew".to_string(),
requires: vec!["brew".to_string()],
command: "brew".to_string(),
args: vec!["install".to_string(), "rust-analyzer".to_string()],
},
InstallTier {
label: "cargo install".to_string(),
requires: vec!["cargo".to_string()],
command: "cargo".to_string(),
args: vec![
"install".to_string(),
"--locked".to_string(),
"rust-analyzer".to_string(),
],
},
InstallTier {
label: "download prebuilt".to_string(),
requires: vec!["curl".to_string(), "tar".to_string()],
command: DOWNLOAD_RUST_BIN.to_string(),
args: vec![],
},
],
},
LanguageServerDef {
name: "typescript-language-server".to_string(),
language: "typescript".to_string(),
extensions: vec![
".ts".to_string(),
".tsx".to_string(),
".js".to_string(),
".jsx".to_string(),
],
binary_names: vec!["typescript-language-server".to_string()],
install_tiers: vec![InstallTier {
label: "npm global".to_string(),
requires: vec!["npm".to_string()],
command: "npm".to_string(),
args: vec![
"install".to_string(),
"-g".to_string(),
"typescript".to_string(),
"typescript-language-server".to_string(),
],
}],
},
LanguageServerDef {
name: "gopls".to_string(),
language: "go".to_string(),
extensions: vec![".go".to_string()],
binary_names: vec!["gopls".to_string()],
install_tiers: vec![InstallTier {
label: "go install".to_string(),
requires: vec!["go".to_string()],
command: "go".to_string(),
args: vec![
"install".to_string(),
"golang.org/x/tools/gopls@latest".to_string(),
],
}],
},
LanguageServerDef {
name: "jdtls".to_string(),
language: "java".to_string(),
extensions: vec![".java".to_string()],
binary_names: vec![
"jdtls".to_string(),
"eclipse-jdt-ls".to_string(),
"jdtls-launcher".to_string(),
],
install_tiers: vec![
InstallTier {
label: "pacman".to_string(),
requires: vec!["java".to_string(), "pacman".to_string()],
command: "pacman".to_string(),
args: vec![
"-S".to_string(),
"--noconfirm".to_string(),
"--needed".to_string(),
"eclipse-jdt-ls".to_string(),
],
},
InstallTier {
label: "apt".to_string(),
requires: vec!["java".to_string(), "apt".to_string()],
command: "sudo".to_string(),
args: vec![
"apt".to_string(),
"install".to_string(),
"-y".to_string(),
"eclipse-jdt-ls".to_string(),
],
},
InstallTier {
label: "brew".to_string(),
requires: vec!["java".to_string(), "brew".to_string()],
command: "brew".to_string(),
args: vec!["install".to_string(), "jdtls".to_string()],
},
InstallTier {
label: "download from eclipse".to_string(),
requires: vec!["java".to_string(), "curl".to_string(), "tar".to_string()],
command: DOWNLOAD_JDTLS.to_string(),
args: vec![],
},
],
},
]
}