- Add 'Additional Workspace Folders' section to project configuration docs
- Add cross-reference note to TypeScript LS settings section
- Include configuration example and usage notes
The TypeScript language server was initialized with a single workspace folder,
so tsserver could not discover references across sibling packages in a monorepo.
This adds an `additional_workspace_folders` setting in
`ls_specific_settings` that accepts a list of directory paths.
Each folder is registered as an LSP workspace folder during initialization,
and a representative .ts file is opened from each to trigger tsserver project
loading. This enables `find_referencing_symbols` and `request_references` to
return results from across package boundaries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per the LSP spec, Content-Type is optional and defaults to
application/vscode-jsonrpc; charset=utf-8 (the exact value we were
sending). Spec-compliant servers behave identically with or without it.
In practice some servers have stricter parsers. Notably, Godot's
GDScript LSP (LSPeer::handle_data in
modules/gdscript/language_server/gdscript_language_protocol.cpp)
extracts the body length via header.substr(16).to_int() and silently
drops messages that contain any header beyond Content-Length.
Sending only Content-Length is interoperable across the spec-compliant
servers we use today and unblocks Godot's LSP. Also tightens the type
signature of create_message from tuple[bytes, bytes, bytes] to
tuple[bytes, bytes] now that there is no Content-Type element.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per the LSP spec, Content-Type is optional and defaults to
application/vscode-jsonrpc; charset=utf-8 (the exact value we were
sending). Spec-compliant servers behave identically with or without it.
In practice some servers have stricter parsers. Notably, Godot's
GDScript LSP (LSPeer::handle_data in
modules/gdscript/language_server/gdscript_language_protocol.cpp)
extracts the body length via header.substr(16).to_int() and silently
drops messages that contain any header beyond Content-Length.
Sending only Content-Length is interoperable across the spec-compliant
servers we use today and unblocks Godot's LSP. Also tightens the type
signature of create_message from tuple[bytes, bytes, bytes] to
tuple[bytes, bytes] now that there is no Content-Type element.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Apply common functionality already used in JetBrainsFindDeclarationTool
* Remove location-based tool (counteracts Serena's principle to eschew line numbers)
* Apply renaming to use "find declaration" instead of "find defining symbol"
* Breaking change: Projects (project.yml) can no longer override `base_modes`.
Instead, they can define `added_modes` to add modes on top of base and default modes.
This allows `base_modes` to be fully applied for the computation of the base toolset
as they are no longer dynamic.
* Serena's default configuration now uses `interactive` and `editing` as `base_modes`
instead of as `default_modes`.
* Fix: send languageId 'typescriptreact' / 'javascriptreact' for .tsx / .jsx
Without this, .tsx files are opened with languageId 'typescript', so
tsserver parses JSX as syntax errors and recovers by truncating the
enclosing symbol's range at the first multi-line JSX expression. The
resulting symptoms:
- find_symbol(name, include_body=True) on a React component returns a
body that ends mid-component, hiding everything below.
- The same component shows up as multiple Method-kind symbols (one per
call site) plus a separately-tracked Constant for the definition,
because tsserver mistakes JSX-tag tokens for member access.
Reproducer (before fix, real-world TSX file):
SidebarPDF range = [11:1-25:207] (truncated at first JSX, line 25)
After fix:
SidebarPDF range = [11:1-281:2] (full body)
The base SolidLanguageServer._get_language_id_for_file is explicitly
designed for this — its docstring says "Override in subclasses to
return file-specific language IDs." This change just exercises that
hook for the React file extensions.
Adds a regression test + jsx_component.tsx fixture covering the same
arrow-function-with-multi-line-JSX-ternary pattern that triggers the
truncation in real codebases (see oraios/serena#1029 for an earlier
report whose root cause was not identified).
* Skip and warn on malformed project configs at startup
`SerenaConfig.from_config_file` iterates the `projects:` list in
`serena_config.yml` and calls `ProjectConfig.load(path)` with no
exception handling. A single malformed `.serena/project.yml`
(missing required key, bad language string, YAML syntax error,
etc.) raises out of the master loader and aborts MCP server
startup before any client handshake or tool registration. Other
projects in the list — even ones that would load cleanly — become
unreachable.
This matches the failure mode behind #997: the schema-migration
shim closed the *cause*, but the surrounding loader still has no
isolation, so the next class of `project.yml` malformation will
take the server down again.
Wrap the `ProjectConfig.load(path)` call in the master loop with
a narrow try/except that logs a warning and continues, matching
the existing skip-with-warning pattern used a few lines above for
inaccessible paths and missing project.yml files. One bad project
becomes one skipped project, not a server-down event.
A new test under `TestSerenaConfigFromConfigFileRobustness`
registers two projects (one healthy, one with invalid YAML),
asserts that `from_config_file` returns successfully, that only
the healthy project ends up registered, and that a warning naming
the bad path is logged.
---------
Co-authored-by: Michael Panchenko <35432522+MischaPanch@users.noreply.github.com>