refactor(daemon): require explicit serverId on all daemon ops

Move all server matching logic to the extension/CLI side. The daemon no
longer calls pickServer() — it receives an explicit serverId (or
serverIds[] for diagnostics) and uses it directly for cache lookup and
server spawning.

Key changes:
- request op requires serverId: string
- diagnostics op requires serverIds: string[] — daemon fans out in
  parallel via Promise.allSettled and returns grouped map
- formatDiagnostics() handles grouped results with per-server headers
  when multiple servers contribute (single-server omits header)
- CLI picks servers locally before calling daemon helpers
- New pickDiagnosticServers() in extension returns all available,
  non-disabled servers matching the file extension

This makes multi-server diagnostics (e.g., typescript-language-server +
oxlint) work naturally — the extension decides which servers to query,
the daemon just executes.
This commit is contained in:
2026-05-04 07:39:03 -04:00
parent d24e2e94f4
commit b9808a8b1f
5 changed files with 117 additions and 41 deletions

View File

@@ -22,6 +22,7 @@ function unwrap(resp: DaemonResponse): unknown {
// daemon injects textDocument.uri from `file`, so callers omit it.
export async function daemonRequest(
file: string,
serverId: string,
method: string,
params: Record<string, unknown>,
): Promise<unknown> {
@@ -29,6 +30,7 @@ export async function daemonRequest(
await sendOnce({
op: "request",
file,
serverId,
method,
params,
launch: buildLaunchContext(),
@@ -38,14 +40,18 @@ export async function daemonRequest(
// Wait For Diagnostics - Diagnostics arrive as a notification, not a
// response, so the daemon has a dedicated op that awaits the next publish.
// Accepts an array of server IDs; daemon fans out in parallel and returns
// a grouped map: { [serverId]: { uri, diagnostics[] } }.
export async function daemonDiagnostics(
file: string,
serverIds: string[],
timeoutMs = 1500,
): Promise<unknown> {
return unwrap(
await sendOnce({
op: "diagnostics",
file,
serverIds,
timeoutMs,
launch: buildLaunchContext(),
}),