π File detail
services/lsp/config.ts
π§© .tsπ 80 linesπΎ 2,857 bytesπ text
β Back to All Filesπ― Use case
This file lives under βservices/β, which covers long-lived services (LSP, MCP, OAuth, tool execution, memory, compaction, voice, settings sync, β¦). On the API surface it exposes getAllLspServers β mainly functions, hooks, or classes. It composes internal code from types and utils (relative imports).
Generated from folder role, exports, dependency roots, and inline comments β not hand-reviewed for every path.
π§ Inline summary
import type { PluginError } from '../../types/plugin.js' import { logForDebugging } from '../../utils/debug.js' import { errorMessage, toError } from '../../utils/errors.js' import { logError } from '../../utils/log.js' import { getPluginLspServers } from '../../utils/plugins/lspPluginIntegration.js'
π€ Exports (heuristic)
getAllLspServers
π₯οΈ Source preview
import type { PluginError } from '../../types/plugin.js'
import { logForDebugging } from '../../utils/debug.js'
import { errorMessage, toError } from '../../utils/errors.js'
import { logError } from '../../utils/log.js'
import { getPluginLspServers } from '../../utils/plugins/lspPluginIntegration.js'
import { loadAllPluginsCacheOnly } from '../../utils/plugins/pluginLoader.js'
import type { ScopedLspServerConfig } from './types.js'
/**
* Get all configured LSP servers from plugins.
* LSP servers are only supported via plugins, not user/project settings.
*
* @returns Object containing servers configuration keyed by scoped server name
*/
export async function getAllLspServers(): Promise<{
servers: Record<string, ScopedLspServerConfig>
}> {
const allServers: Record<string, ScopedLspServerConfig> = {}
try {
// Get all enabled plugins
const { enabled: plugins } = await loadAllPluginsCacheOnly()
// Load LSP servers from each plugin in parallel.
// Each plugin is independent β results are merged in original order so
// Object.assign collision precedence (later plugins win) is preserved.
const results = await Promise.all(
plugins.map(async plugin => {
const errors: PluginError[] = []
try {
const scopedServers = await getPluginLspServers(plugin, errors)
return { plugin, scopedServers, errors }
} catch (e) {
// Defensive: if one plugin throws, don't lose results from the
// others. The previous serial loop implicitly tolerated this.
logForDebugging(
`Failed to load LSP servers for plugin ${plugin.name}: ${e}`,
{ level: 'error' },
)
return { plugin, scopedServers: undefined, errors }
}
}),
)
for (const { plugin, scopedServers, errors } of results) {
const serverCount = scopedServers ? Object.keys(scopedServers).length : 0
if (serverCount > 0) {
// Merge into all servers (already scoped by getPluginLspServers)
Object.assign(allServers, scopedServers)
logForDebugging(
`Loaded ${serverCount} LSP server(s) from plugin: ${plugin.name}`,
)
}
// Log any errors encountered
if (errors.length > 0) {
logForDebugging(
`${errors.length} error(s) loading LSP servers from plugin: ${plugin.name}`,
)
}
}
logForDebugging(
`Total LSP servers loaded: ${Object.keys(allServers).length}`,
)
} catch (error) {
// Log error for monitoring production issues.
// LSP is optional, so we don't throw - but we need visibility
// into why plugin loading fails to improve the feature.
logError(toError(error))
logForDebugging(`Error loading LSP servers: ${errorMessage(error)}`)
}
return {
servers: allServers,
}
}