codex-lens: ship default LSP config and fix entrypoint

This commit is contained in:
catlog22
2026-03-05 14:27:16 +08:00
parent 1fb49c0e39
commit 6341ed43e1
5 changed files with 221 additions and 16 deletions

View File

@@ -0,0 +1,88 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"version": "1.0.0",
"description": "Default language server configuration for codex-lens standalone LSP client",
"servers": [
{
"languageId": "python",
"displayName": "Pyright",
"extensions": ["py", "pyi"],
"command": ["pyright-langserver", "--stdio"],
"enabled": true,
"initializationOptions": {
"pythonPath": "",
"pythonPlatform": "",
"pythonVersion": "3.13"
},
"settings": {
"python.analysis": {
"typeCheckingMode": "standard",
"diagnosticMode": "workspace",
"exclude": ["**/node_modules", "**/__pycache__", "build", "dist"],
"include": ["src/**", "tests/**"],
"stubPath": "typings"
}
}
},
{
"languageId": "typescript",
"displayName": "TypeScript Language Server",
"extensions": ["ts", "tsx"],
"command": ["typescript-language-server", "--stdio"],
"enabled": true,
"initializationOptions": {},
"settings": {}
},
{
"languageId": "javascript",
"displayName": "TypeScript Language Server (for JS)",
"extensions": ["js", "jsx", "mjs", "cjs"],
"command": ["typescript-language-server", "--stdio"],
"enabled": true,
"initializationOptions": {},
"settings": {}
},
{
"languageId": "go",
"displayName": "Gopls",
"extensions": ["go"],
"command": ["gopls", "serve"],
"enabled": true,
"initializationOptions": {},
"settings": {}
},
{
"languageId": "rust",
"displayName": "Rust Analyzer",
"extensions": ["rs"],
"command": ["rust-analyzer"],
"enabled": false,
"initializationOptions": {},
"settings": {}
},
{
"languageId": "c",
"displayName": "Clangd",
"extensions": ["c", "h"],
"command": ["clangd"],
"enabled": false,
"initializationOptions": {},
"settings": {}
},
{
"languageId": "cpp",
"displayName": "Clangd",
"extensions": ["cpp", "hpp", "cc", "cxx"],
"command": ["clangd"],
"enabled": false,
"initializationOptions": {},
"settings": {}
}
],
"defaults": {
"rootDir": ".",
"timeout": 30000,
"restartInterval": 5000,
"maxRestarts": 3
}
}

View File

@@ -14,6 +14,7 @@ Features:
from __future__ import annotations
import asyncio
import importlib.resources as resources
import json
import logging
import os
@@ -117,7 +118,6 @@ class StandaloneLspManager:
1. Explicit config_file parameter
2. {workspace_root}/lsp-servers.json
3. {workspace_root}/.codexlens/lsp-servers.json
4. Package default (codexlens/lsp-servers.json)
"""
search_paths = []
@@ -127,7 +127,6 @@ class StandaloneLspManager:
search_paths.extend([
self.workspace_root / self.DEFAULT_CONFIG_FILE,
self.workspace_root / ".codexlens" / self.DEFAULT_CONFIG_FILE,
Path(__file__).parent.parent.parent.parent / self.DEFAULT_CONFIG_FILE, # package root
])
for path in search_paths:
@@ -135,21 +134,73 @@ class StandaloneLspManager:
return path
return None
def _load_builtin_config(self) -> Optional[dict[str, Any]]:
"""Load the built-in default lsp-servers.json shipped with the package."""
try:
text = (
resources.files("codexlens.lsp")
.joinpath(self.DEFAULT_CONFIG_FILE)
.read_text(encoding="utf-8")
)
except Exception as exc:
logger.error(
"Failed to load built-in %s template from package: %s",
self.DEFAULT_CONFIG_FILE,
exc,
)
return None
try:
return json.loads(text)
except Exception as exc:
logger.error(
"Built-in %s template shipped with the package is invalid JSON: %s",
self.DEFAULT_CONFIG_FILE,
exc,
)
return None
def _load_config(self) -> None:
"""Load language server configuration from JSON file."""
self._configs.clear()
self._extension_map.clear()
config_path = self._find_config_file()
if not config_path:
logger.warning(f"No {self.DEFAULT_CONFIG_FILE} found, using empty config")
return
try:
with open(config_path, "r", encoding="utf-8") as f:
data = json.load(f)
except Exception as e:
logger.error(f"Failed to load config from {config_path}: {e}")
return
data = self._load_builtin_config()
if data is None:
logger.warning(
"No %s found and built-in defaults could not be loaded; using empty config",
self.DEFAULT_CONFIG_FILE,
)
return
root_config_path = self.workspace_root / self.DEFAULT_CONFIG_FILE
codexlens_config_path = (
self.workspace_root / ".codexlens" / self.DEFAULT_CONFIG_FILE
)
logger.info(
"No %s found at %s or %s; using built-in defaults shipped with codex-lens. "
"To customize, copy the template to one of those locations and restart. "
"Language servers are spawned on-demand when first needed. "
"Ensure the language server commands in the config are installed and on PATH.",
self.DEFAULT_CONFIG_FILE,
root_config_path,
codexlens_config_path,
)
config_source = "built-in defaults"
else:
try:
with open(config_path, "r", encoding="utf-8") as f:
data = json.load(f)
except Exception as e:
logger.error(f"Failed to load config from {config_path}: {e}")
return
config_source = str(config_path)
# Parse defaults
defaults = data.get("defaults", {})
@@ -186,7 +237,11 @@ class StandaloneLspManager:
for ext in config.extensions:
self._extension_map[ext.lower()] = language_id
logger.info(f"Loaded {len(self._configs)} language server configs from {config_path}")
logger.info(
"Loaded %d language server configs from %s",
len(self._configs),
config_source,
)
def get_language_id(self, file_path: str) -> Optional[str]:
"""Get language ID for a file based on extension.