This commit is contained in:
2026-07-09 07:25:14 +02:00
parent 230e828b81
commit a930537207
19 changed files with 762 additions and 2 deletions
+1
View File
@@ -434,6 +434,7 @@ mod tests {
spawner: None,
job_board: None,
context_reporter: None,
diagnostics: None,
}
}
@@ -72,6 +72,8 @@ pub struct StepContext {
/// Present in subagent sessions: reports read files to this session's job on the parent
/// board. `None` for root sessions (nothing to report to).
pub context_reporter: Option<Arc<dyn ContextReporter>>,
/// Language-server diagnostics source shared by the session's edit/write tool calls.
pub diagnostics: Option<Arc<dyn crate::lsp::DiagnosticsSource>>,
}
struct FlushTracker {
@@ -522,6 +524,7 @@ impl<'a> Run<'a> {
metadata: metadata_sink,
spawner: self.ctx.spawner.clone(),
context_reporter: self.ctx.context_reporter.clone(),
diagnostics: self.ctx.diagnostics.clone(),
};
let result = tokio::select! {
+1
View File
@@ -3,6 +3,7 @@ pub mod config;
pub mod engine;
pub mod event;
pub mod llm;
pub mod lsp;
pub mod permission;
pub mod store;
pub mod tool;
+46
View File
@@ -0,0 +1,46 @@
//! Seam trait for language-server diagnostics, implemented by `harness-lsp` and consumed by
//! the edit/write tools. Kept in core so `harness-tools` never links the LSP crate directly.
//! See `docs/09-integrations.md`.
use std::path::Path;
use std::time::Duration;
use async_trait::async_trait;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Severity {
Error,
Warning,
Info,
Hint,
}
/// One diagnostic reported by a language server. Line/character are 1-based for display.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Diagnostic {
pub line: u32,
pub character: u32,
pub severity: Severity,
pub message: String,
pub source: Option<String>,
}
impl Diagnostic {
/// `{file}: L{line}: {message}` — the one-line form appended to tool output.
pub fn display_line(&self, file: &str) -> String {
format!("{file}: L{}: {}", self.line, self.message)
}
}
/// A source of file diagnostics (an LSP pool). All methods are best-effort: failures are
/// swallowed (logged) so a broken language server never fails a tool call.
#[async_trait]
pub trait DiagnosticsSource: Send + Sync {
/// Ensure a server for `path`'s language is running and told about the file's current
/// contents (spawn-if-needed + didOpen/didChange).
async fn touch(&self, path: &Path);
/// Diagnostics for `path`, waiting up to `wait` for the server to (re)publish after a
/// change. Returns whatever is known on timeout.
async fn diagnostics(&self, path: &Path, wait: Duration) -> Vec<Diagnostic>;
}
+3
View File
@@ -195,6 +195,9 @@ pub struct ToolCtx {
pub spawner: Option<Arc<dyn SubagentSpawner>>,
/// Present in subagent sessions: lets the read tool report files to the job board.
pub context_reporter: Option<Arc<dyn ContextReporter>>,
/// Language-server diagnostics source (edit/write surface errors after a change). `None`
/// disables LSP integration.
pub diagnostics: Option<Arc<dyn crate::lsp::DiagnosticsSource>>,
}
#[derive(Debug)]