NAVIGATION
ELOWEN DOCUMENTATION

Last updated: 10 October 2026

Browse documentation · Conversation language servers
Developer reference

Conversation language servers

Conversation-owned language servers

The registry LSP plugin owns one language-server slot per durable conversation id. Automatic Write/Edit diagnostics and explicit Lsp tools use the same slot in the process executing the conversation. The existing sub-agent dispatch routes delegated turns to their runner; daemon projections and HTTP status reads do not execute those tools or acquire servers. Runner reclamation awaits BrainService.disposeChannel, including the LSP cleanup promise, before a daemon turn can take ownership of that conversation. A runner answers a release request with one of three outcomes (RunnerReleaseOutcome, src/brain/delegatedTurn.ts): released, busy while a turn runs on the channel, and failed when the channel is idle but its cleanup threw. failed preserves the runner's route and ownership, so cleanup failure cannot create a second owner, and it is never reported as a running turn. The idle route sweep treats failed like busy and asks again on a later sweep. The owner's model switch answers it with a retry message, and a daemon-side continuation or result delivery refuses with the same cause and steers nothing into the runner.

The existing lsp control adds shutdownSession(sessionId). BrainService invokes it synchronously through the already-loaded registry on the final run settlement (agent_settled, which calls onRunSettled in src/brain/persistence.ts) and from LiveSessionRegistry's disposal callback. agent_end and brain.run.beforeSettle do not release resources because a run may continue. The plugin fences late acquisition, cancels diagnostics and drains transport closure. Repeated cleanup calls join the same promise. Root or server-language replacement waits for the old transport to close; idle fallback defaults to 60 seconds with a 5-second sweep. The plugin's idleTtlMinutes setting defaults to one minute and accepts 0 to 240. Local transports own a process group so disposal kills their descendants; initialize retains the owning process watchdog for runner death. TypeScript disables its separate syntax server and uses a 1024 MiB old-space allowance, not an RSS hard limit. The plugin sets no option that disables automatic typing acquisition for JavaScript projects.