Skip to main content

zeph_core/agent/
lsp_commands.rs

1// SPDX-FileCopyrightText: 2026 Andrei G <bug-ops>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3
4use std::fmt::Write as _;
5use std::future::Future;
6use std::pin::Pin;
7
8use zeph_commands::{CommandError, LspAccess};
9
10use super::command_macros::delegate_cmd;
11use super::{Agent, error::AgentError};
12use crate::channel::Channel;
13
14impl<C: Channel> Agent<C> {
15    /// Channel-free version for use via [`zeph_commands::LspAccess`].
16    pub(super) async fn handle_lsp_status_as_string(&mut self) -> Result<String, AgentError> {
17        let mut out = String::new();
18
19        match self.services.session.lsp_hooks.as_ref() {
20            None => {
21                let _ = writeln!(out, "LSP context injection: disabled");
22                let _ = writeln!(out);
23                let _ = writeln!(
24                    out,
25                    "Enable with `--lsp-context` flag or set `lsp.enabled = true` in config."
26                );
27                let _ = writeln!(
28                    out,
29                    "Requires mcpls configured under [mcp.servers] (install: cargo install mcpls)."
30                );
31            }
32            Some(lsp) => {
33                let available = lsp.is_available().await;
34                let _ = writeln!(out, "LSP context injection: enabled");
35                let _ = writeln!(
36                    out,
37                    "MCP server: {} ({})",
38                    lsp.config.mcp_server_id,
39                    if available {
40                        "connected"
41                    } else {
42                        "not connected"
43                    }
44                );
45                let _ = writeln!(out, "Token budget per turn: {}", lsp.config.token_budget);
46                let _ = writeln!(out);
47                let _ = writeln!(out, "Hooks:");
48                let _ = writeln!(
49                    out,
50                    "  diagnostics-on-save: {}",
51                    if lsp.config.diagnostics.enabled {
52                        "enabled"
53                    } else {
54                        "disabled"
55                    }
56                );
57                let _ = writeln!(
58                    out,
59                    "  hover-on-read:       {}",
60                    if lsp.config.hover.enabled {
61                        "enabled"
62                    } else {
63                        "disabled"
64                    }
65                );
66                let _ = writeln!(out);
67                let stats = lsp.stats();
68                let _ = writeln!(out, "Session statistics:");
69                let _ = writeln!(
70                    out,
71                    "  diagnostics injected: {}",
72                    stats.diagnostics_injected
73                );
74                let _ = writeln!(out, "  hover injected:       {}", stats.hover_injected);
75                let _ = writeln!(
76                    out,
77                    "  notes dropped (budget): {}",
78                    stats.notes_dropped_budget
79                );
80            }
81        }
82
83        Ok(out.trim_end().to_owned())
84    }
85}
86
87impl<C: Channel + Send + 'static> LspAccess for Agent<C> {
88    // ----- /lsp -----
89
90    delegate_cmd!(lsp_status, handle_lsp_status_as_string => String);
91}