Skip to content

feat(lsp): add web worker language servers as defaults#2531

Open
bajrangCoder wants to merge 7 commits into
mainfrom
worker-lsp-defaults
Open

feat(lsp): add web worker language servers as defaults#2531
bajrangCoder wants to merge 7 commits into
mainfrom
worker-lsp-defaults

Conversation

@bajrangCoder

Copy link
Copy Markdown
Member

Summary

Add bundled Web Worker-based language servers as the default LSP experience for users.

HTML, CSS, JSON, JavaScript, and TypeScript now work without requiring Alpine, STDIO processes, manual installation, WebSocket URLs, or launcher bridges. Existing STDIO servers remain available as optional alternatives for advanced users who wants full workspace level stdio based lsp.

Changes

  • Add a built-in Web Worker LSP runtime
  • Enable Web Worker servers by default for:
    • HTML
    • CSS, SCSS, and Less
    • JSON and JSONC
    • JavaScript, JSX, TypeScript, and TSX
  • Keep equivalent STDIO servers available but disabled by default
  • Support arbitrary document URIs, including Android SAF and content:// locations
  • Add HTML embedded-language support for CSS and JavaScript/TypeScript
  • Add JSON schema discovery and configuration support
  • Add TypeScript library loading and nested file resolution
  • Preserve Markdown formatting in TypeScript completion and signature-help documentation
  • Correctly dispose workers when:
    • A server is disabled
    • The last associated editor is closed
    • A custom server is removed
  • Avoid starting workers when their LSP servers are disabled

@bajrangCoder
bajrangCoder marked this pull request as ready for review July 23, 2026 16:29
@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR ships a complete Web Worker LSP runtime for HTML, CSS, JSON, and TypeScript/JavaScript — enabling zero-setup language intelligence in Acode without Alpine, STDIO processes, or network bridges. The STDIO servers are preserved but renamed (e.g. html-stdio) and disabled by default.

  • Adds four new language-service workers (html, css, json, typescript) backed by vscode-*-languageservice and the TypeScript compiler API; the HTML worker lazily spawns a nested TypeScript worker for embedded JS regions.
  • Introduces WorkerTransport (host side) and protocol.ts (worker side) as a shared RPC/lifecycle framework, and upgrades LspClientManager with disposeServer() + AbortController-based cancellation to close the previously-reported pending-init race.
  • One defect stands out: formatSettings in typescript.worker.ts dereferences its argument unconditionally, but the Acode client never sends formattingOptions in textDocument/codeAction requests, causing a TypeError on every code-action call to the TypeScript worker.

Confidence Score: 4/5

Safe to merge except for the code-action crash in the TypeScript worker.

The TypeScript worker unconditionally reads options.tabSize in formatSettings, but textDocument/codeAction requests from the Acode client never include a formattingOptions field, so every code-action invocation throws a TypeError. All other worker lifecycle, transport, disposal, and abort-cancellation logic looks sound.

src/cm/lsp/workers/typescript.worker.ts — the formatSettings function and its call site in codeActions.

Important Files Changed

Filename Overview
src/cm/lsp/workers/typescript.worker.ts New 976-line TypeScript language service worker with a P1 bug: formatSettings crashes with TypeError on every textDocument/codeAction request because the client never sends formattingOptions.
src/cm/lsp/workers/protocol.ts New shared worker protocol/lifecycle module; handles JSON-RPC dispatch, document sync, and validation scheduling. Minor: cancelled request ids can accumulate in cancelledRequests when early error paths skip the delete call.
src/cm/lsp/workerTransport.ts New host-side transport layer wrapping a Web Worker; correctly handles startup timeout, post-ready crash via failTransport, host-request fan-out, and graceful disposal.
src/cm/lsp/workers/nestedLspClient.ts New client for the HTML→TypeScript nested worker; correctly handles post-ready crashes via closedError + fail() which rejects all pending requests and blocks future ones.
src/cm/lsp/clientManager.ts Adds disposeServer and upgrades #pendingClients to carry AbortController/signal, fixing the previously-flagged race where a server being disabled during init left a live client behind.
src/cm/lsp/workers/html.worker.ts New HTML language service worker with embedded CSS/JSON/JS support via nested TypeScript worker; correctly implements dispose() to terminate the nested worker.
src/cm/lsp/workers/css.worker.ts New CSS/SCSS/Less language service worker with caching of parsed stylesheets per document version; clean and complete.
src/cm/lsp/runtimes/webWorker.ts New web-worker runtime provider; sets priority 100 so it beats Alpine/WebSocket providers and correctly delegates readFile to the host's filesystem.
src/cm/lsp/servers/web.ts Adds three new web-worker-backed server definitions (html, css, json) enabled by default; renames STDIO servers to -stdio suffix and disables them.
src/cm/lsp/servers/javascript.ts Adds web-worker TypeScript server; renames existing Alpine STDIO server to typescript-stdio and disables it.

Sequence Diagram

sequenceDiagram
    participant Host as Main Thread (Acode)
    participant WT as WorkerTransport
    participant HW as HTML Worker
    participant NLC as NestedLspClient
    participant TW as TypeScript Worker

    Host->>WT: new Worker("build/htmlLspWorker.js")
    Host->>HW: "postMessage({kind:"configure", serverId, rootUri})"
    HW-->>Host: "postMessage({kind:"ready"})"
    WT->>Host: ready promise resolves

    Host->>HW: LSP initialize request (JSON-RPC string)
    HW-->>Host: initialize response

    Note over HW,TW: Lazy TypeScript nested worker init (on first JS request)
    HW->>NLC: new NestedLspClient("typescriptLspWorker.js")
    NLC->>TW: new Worker(url)
    NLC->>TW: "postMessage({kind:"configure", serverId, rootUri})"
    TW-->>NLC: "postMessage({kind:"ready"})"
    NLC->>TW: initialize request
    TW-->>NLC: initialize response
    NLC->>TW: initialized notification

    Host->>HW: textDocument/codeAction (JS embedded region)
    HW->>NLC: request(method, params, jsDocument)
    NLC->>TW: textDocument/codeAction (params without options)
    Note over TW: formatSettings(undefined) throws TypeError

    Note over Host,WT: Graceful shutdown
    Host->>HW: shutdown + exit notifications
    HW->>NLC: "dispose() -> typescriptClient.dispose()"
    NLC->>TW: worker.terminate()
    HW->>HW: workerScope.close()
    WT->>WT: "dispose() -> worker.terminate()"
Loading

Comments Outside Diff (1)

  1. src/cm/lsp/workers/typescript.worker.ts, line 1040-1048 (link)

    P1 textDocument/codeAction crashes — formatSettings receives undefined

    The client's textDocument/codeAction request (in codeActions.ts) sends { textDocument, range, context } — it never includes formattingOptions. At runtime request.options is therefore undefined, and formatSettings(undefined) immediately throws TypeError: Cannot read properties of undefined (reading 'tabSize'). Every code action request to the TypeScript web-worker will fail with an uncaught exception.

    The same problem affects the HTML worker path that delegates JS code actions via requestTypeScript(method, params, javascript) — the forwarded params also lack an options field.

Reviews (5): Last reviewed commit: "fix" | Re-trigger Greptile

Comment thread src/cm/lsp/clientManager.ts
@bajrangCoder

This comment was marked as outdated.

@bajrangCoder

Copy link
Copy Markdown
Member Author

@greptile

Comment thread src/cm/lsp/workers/nestedLspClient.ts Outdated
Comment thread src/cm/lsp/workers/protocol.ts
@bajrangCoder

This comment was marked as outdated.

Comment thread src/cm/lsp/workerTransport.ts
@bajrangCoder

This comment was marked as outdated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant