summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2025-08-09 11:04:58 -0500
committerGitHub <[email protected]>2025-08-09 11:04:58 -0500
commit1954b59167d0c743efa2fb3a0a47e57a025b4221 (patch)
tree6a4f4f4c061145ed357c2c262ff59ccc3c8dba34
parente2fac991dc292053e835fc1dd7c25aaf025240f1 (diff)
downloadopencode-1954b59167d0c743efa2fb3a0a47e57a025b4221.tar.gz
opencode-1954b59167d0c743efa2fb3a0a47e57a025b4221.zip
feat: eslint lsp (#1744)
-rw-r--r--packages/opencode/src/lsp/server.ts60
-rw-r--r--packages/opencode/src/tool/edit.ts1
-rw-r--r--packages/web/src/content/docs/docs/lsp.mdx7
3 files changed, 65 insertions, 3 deletions
diff --git a/packages/opencode/src/lsp/server.ts b/packages/opencode/src/lsp/server.ts
index f4648f0c2..cf78fe7bf 100644
--- a/packages/opencode/src/lsp/server.ts
+++ b/packages/opencode/src/lsp/server.ts
@@ -65,6 +65,66 @@ export namespace LSPServer {
},
}
+ export const ESLint: Info = {
+ id: "eslint",
+ root: NearestRoot([
+ "eslint.config.js",
+ "eslint.config.mjs",
+ "eslint.config.cjs",
+ "eslint.config.ts",
+ "eslint.config.mts",
+ "eslint.config.cts",
+ ".eslintrc.js",
+ ".eslintrc.cjs",
+ ".eslintrc.yaml",
+ ".eslintrc.yml",
+ ".eslintrc.json",
+ "package.json",
+ ]),
+ extensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"],
+ async spawn(app, root) {
+ const eslint = await Bun.resolve("eslint", app.path.cwd).catch(() => {})
+ if (!eslint) return
+ const serverPath = path.join(Global.Path.bin, "vscode-eslint", "server", "out", "eslintServer.js")
+ if (!(await Bun.file(serverPath).exists())) {
+ log.info("downloading and building VS Code ESLint server")
+ const response = await fetch("https://github.com/microsoft/vscode-eslint/archive/refs/heads/main.zip")
+ if (!response.ok) return
+
+ const zipPath = path.join(Global.Path.bin, "vscode-eslint.zip")
+ await Bun.file(zipPath).write(response)
+
+ await $`unzip -o -q ${zipPath}`.cwd(Global.Path.bin).nothrow()
+ await fs.rm(zipPath, { force: true })
+
+ const extractedPath = path.join(Global.Path.bin, "vscode-eslint-main")
+ const finalPath = path.join(Global.Path.bin, "vscode-eslint")
+
+ if (await Bun.file(finalPath).exists()) {
+ await fs.rm(finalPath, { force: true, recursive: true })
+ }
+ await fs.rename(extractedPath, finalPath)
+
+ await $`npm install`.cwd(finalPath).quiet()
+ await $`npm run compile`.cwd(finalPath).quiet()
+
+ log.info("installed VS Code ESLint server", { serverPath })
+ }
+
+ const proc = spawn(BunProc.which(), ["--max-old-space-size=8192", serverPath, "--stdio"], {
+ cwd: root,
+ env: {
+ ...process.env,
+ BUN_BE_BUN: "1",
+ },
+ })
+
+ return {
+ process: proc,
+ }
+ },
+ }
+
export const Gopls: Info = {
id: "golang",
root: async (file, app) => {
diff --git a/packages/opencode/src/tool/edit.ts b/packages/opencode/src/tool/edit.ts
index fbda9e4d1..d3883b539 100644
--- a/packages/opencode/src/tool/edit.ts
+++ b/packages/opencode/src/tool/edit.ts
@@ -111,6 +111,7 @@ export const EditTool = Tool.define("edit", {
continue
}
output += `\n<project_diagnostics>\n${file}\n${issues
+ // TODO: may want to make more leniant for eslint
.filter((item) => item.severity === 1)
.map(LSP.Diagnostic.pretty)
.join("\n")}\n</project_diagnostics>\n`
diff --git a/packages/web/src/content/docs/docs/lsp.mdx b/packages/web/src/content/docs/docs/lsp.mdx
index 4783683bb..76edad3ee 100644
--- a/packages/web/src/content/docs/docs/lsp.mdx
+++ b/packages/web/src/content/docs/docs/lsp.mdx
@@ -11,9 +11,10 @@ opencode integrates with your Language Server Protocol (LSP) to help the LLM int
opencode comes with several built-in LSP servers for popular languages:
-| LSP Server | Extensions | Requirements |
+| LSP Server | Extensions | Requirements |
| ---------- | -------------------------------------------- | ----------------------------------- |
| typescript | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `typescript` dependency in project |
+| eslint | .ts, .tsx, .js, .jsx, .mjs, .cjs, .mts, .cts | `eslint` dependency in project |
| gopls | .go | `go` command available |
| ruby-lsp | .rb, .rake, .gemspec, .ru | `ruby` and `gem` commands available |
| pyright | .py, .pyi | `pyright` dependency installed |
@@ -41,7 +42,7 @@ You can customize LSP servers through the `lsp` section in your opencode config.
```json title="opencode.json"
{
"$schema": "https://opencode.ai/config.json",
- "lsp": { }
+ "lsp": {}
}
```
@@ -49,7 +50,7 @@ Each LSP server supports the following:
| Property | Type | Description |
| ---------------- | -------- | ------------------------------------------------- |
-| `disabled` | boolean | Set this to `true` to disable the LSP server |
+| `disabled` | boolean | Set this to `true` to disable the LSP server |
| `command` | string[] | The command to start the LSP server |
| `extensions` | string[] | File extensions this LSP server should handle |
| `env` | object | Environment variables to set when starting server |