Skip to content

feat(agent): add lsp diagnostics and semantic rename tools - #345

Merged
fcoury merged 1 commit into
mainfrom
fcoury/agent-lsp
Aug 27, 2026
Merged

feat(agent): add lsp diagnostics and semantic rename tools#345
fcoury merged 1 commit into
mainfrom
fcoury/agent-lsp

Conversation

@fcoury-oai

Copy link
Copy Markdown
Collaborator

The Agent needs structured language-server results to inspect errors and rename symbols across files while preserving unsaved work. This adds access to Red's existing language servers without opening editor dialogs or moving focus.

  • Add lsp_status and lsp_diagnostics for server capabilities and filtered, paginated diagnostics from a file, open buffers, or known workspace reports. Collection continues when diagnostic display is disabled; responses distinguish provisional, stale, unversioned, and absent reports instead of claiming the project is clean.
  • Add lsp_prepare_rename, lsp_preview_rename, and lsp_apply_edit. Previews return a bounded diff and an expiring plan tied to the active turn and server. Applying rechecks buffer revisions, unopened-file snapshots, and workspace access policy, then changes buffers with Agent attribution and one undo transaction per file. It never saves files.
  • Keep requests asynchronous and reject cancelled, stale, or foreign-session results. Reject unsafe targets and file create/rename/delete operations before changing text.

Start a new Agent conversation after upgrading; resumed conversations retain their previous tool list. General symbol queries, code actions, and formatting tools remain follow-up work. The tool contracts and limits are documented in docs/AGENT_WORKFLOW.md.

How to Test

  1. Run cargo test --all-features --test lsp_lazy agent_lsp_. The new tests cover cross-file rename with unsaved text, Unicode positions, diagnostic filtering and pagination, push-only servers, and rejected edits. In particular, agent_lsp_preview_rejects_changed_buffers_and_restarted_servers must reject both stale-buffer and server-restart cases without changing text; agent_lsp_queries_allow_typing_and_reject_late_results checks responsiveness and late responses.
  2. Build with cargo build --bin red. With an authenticated Codex app-server and a configured rust-analyzer or typescript-language-server, open a disposable project containing Account.id references in two files, an unrelated Other.id field, and an intentional type error. Start a fresh conversation with :AgentNew, then open the composer with :Agent.
  3. Ask: “Read both files, inspect LSP status and diagnostics, prepare and preview renaming Account.id to account_id, then apply the rename without saving.” Expect the intentional error to be reported, only Account.id references to change, both buffers to remain unsaved, and disk contents to remain unchanged. The Agent should state the diagnostic freshness limits and that the edits are unsaved.
  4. Undo once in each changed file. Each file should return to its state before the rename without a save.

Validated at 9a3a803d: Clippy with all targets/features and warnings denied, formatting, and live Rust and TypeScript Agent workflows passed. Both live runs preserved Other.id and disk contents; manual per-file undo also passed.

The remaining suite passed with 3,532 tests passed, 2 ignored, and 1 excluded using:

RUST_TEST_THREADS=2 cargo test --all-targets --all-features -- --skip dot_repeats_linewise_paste_and_visual_block_insert

The unfiltered suite aborts in editing::dot_repeats_linewise_paste_and_visual_block_insert, which uses a 2 MiB thread stack. The same crash reproduced on untouched main at 5862875e using a fresh, separate target directory. This PR does not change that guard.

@fcoury
fcoury merged commit b9fc1ff into main Aug 27, 2026
12 checks passed
@fcoury
fcoury deleted the fcoury/agent-lsp branch August 27, 2026 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants