summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorLuke Parker <[email protected]>2026-04-27 15:39:36 +1000
committerGitHub <[email protected]>2026-04-27 05:39:36 +0000
commit8718b98ee1e7c114fa2d2055295d39d01b70b6f4 (patch)
tree1b9f47b302cb090afbaf63967847e40bc71445a0
parentc8b2f987f97482dc54c34f32b5b3eb111a1db67c (diff)
downloadopencode-8718b98ee1e7c114fa2d2055295d39d01b70b6f4.tar.gz
opencode-8718b98ee1e7c114fa2d2055295d39d01b70b6f4.zip
fix: pass workspace symbol query to experimental LSP tool (#24576)
-rw-r--r--packages/opencode/src/tool/lsp.ts7
-rw-r--r--packages/opencode/src/tool/lsp.txt7
-rw-r--r--packages/opencode/test/tool/__snapshots__/parameters.test.ts.snap4
-rw-r--r--packages/opencode/test/tool/lsp.test.ts26
4 files changed, 40 insertions, 4 deletions
diff --git a/packages/opencode/src/tool/lsp.ts b/packages/opencode/src/tool/lsp.ts
index bb3b50344..ac13cfb43 100644
--- a/packages/opencode/src/tool/lsp.ts
+++ b/packages/opencode/src/tool/lsp.ts
@@ -29,6 +29,9 @@ export const Parameters = Schema.Struct({
character: Schema.Number.check(Schema.isInt())
.check(Schema.isGreaterThanOrEqualTo(1))
.annotate({ description: "The character offset (1-based, as shown in editors)" }),
+ query: Schema.optional(Schema.String).annotate({
+ description: "Search query for workspaceSymbol. Empty string requests all symbols.",
+ }),
})
export const LspTool = Tool.define(
@@ -40,7 +43,7 @@ export const LspTool = Tool.define(
description: DESCRIPTION,
parameters: Parameters,
execute: (
- args: { operation: (typeof operations)[number]; filePath: string; line: number; character: number },
+ args: Schema.Schema.Type<typeof Parameters>,
ctx: Tool.Context,
) =>
Effect.gen(function* () {
@@ -89,7 +92,7 @@ export const LspTool = Tool.define(
case "documentSymbol":
return lsp.documentSymbol(uri)
case "workspaceSymbol":
- return lsp.workspaceSymbol("")
+ return lsp.workspaceSymbol(args.query ?? "")
case "goToImplementation":
return lsp.implementation(position)
case "prepareCallHierarchy":
diff --git a/packages/opencode/src/tool/lsp.txt b/packages/opencode/src/tool/lsp.txt
index 5a50a571b..85db65c17 100644
--- a/packages/opencode/src/tool/lsp.txt
+++ b/packages/opencode/src/tool/lsp.txt
@@ -5,7 +5,7 @@ Supported operations:
- findReferences: Find all references to a symbol
- hover: Get hover information (documentation, type info) for a symbol
- documentSymbol: Get all symbols (functions, classes, variables) in a document
-- workspaceSymbol: Search for symbols across the entire workspace
+- workspaceSymbol: List project-wide symbols matching a query string
- goToImplementation: Find implementations of an interface or abstract method
- prepareCallHierarchy: Get call hierarchy item at a position (functions/methods)
- incomingCalls: Find all functions/methods that call the function at a position
@@ -16,4 +16,9 @@ All operations require:
- line: The line number (1-based, as shown in editors)
- character: The character offset (1-based, as shown in editors)
+workspaceSymbol also accepts:
+- query: A query string to filter symbols by. Empty string requests all symbols.
+
+For workspaceSymbol, filePath is not sent in the LSP workspace/symbol request. It is used by opencode to select and start the matching LSP server.
+
Note: LSP servers must be configured for the file type. If no server is available, an error will be returned.
diff --git a/packages/opencode/test/tool/__snapshots__/parameters.test.ts.snap b/packages/opencode/test/tool/__snapshots__/parameters.test.ts.snap
index eb3fe6cce..b20665b34 100644
--- a/packages/opencode/test/tool/__snapshots__/parameters.test.ts.snap
+++ b/packages/opencode/test/tool/__snapshots__/parameters.test.ts.snap
@@ -209,6 +209,10 @@ exports[`tool parameters JSON Schema (wire shape) lsp 1`] = `
],
"type": "string",
},
+ "query": {
+ "description": "Search query for workspaceSymbol. Empty string requests all symbols.",
+ "type": "string",
+ },
},
"required": [
"operation",
diff --git a/packages/opencode/test/tool/lsp.test.ts b/packages/opencode/test/tool/lsp.test.ts
index b7a52da19..502ea30a0 100644
--- a/packages/opencode/test/tool/lsp.test.ts
+++ b/packages/opencode/test/tool/lsp.test.ts
@@ -28,6 +28,8 @@ const ctx = {
ask: () => Effect.void,
}
+const workspaceSymbolQueries: string[] = []
+
const lsp = Layer.succeed(
LSP.Service,
LSP.Service.of({
@@ -41,7 +43,11 @@ const lsp = Layer.succeed(
references: () => Effect.succeed([]),
implementation: () => Effect.succeed([]),
documentSymbol: () => Effect.succeed([]),
- workspaceSymbol: () => Effect.succeed([]),
+ workspaceSymbol: (query) =>
+ Effect.sync(() => {
+ workspaceSymbolQueries.push(query)
+ return []
+ }),
prepareCallHierarchy: () => Effect.succeed([]),
incomingCalls: () => Effect.succeed([]),
outgoingCalls: () => Effect.succeed([]),
@@ -142,6 +148,7 @@ describe("tool.lsp", () => {
provideTmpdirInstance(
(dir) =>
Effect.gen(function* () {
+ workspaceSymbolQueries.length = 0
const file = path.join(dir, "test.ts")
yield* put(file)
@@ -158,5 +165,22 @@ describe("tool.lsp", () => {
{ git: true },
),
)
+
+ it.live("passes workspaceSymbol query to LSP", () =>
+ provideTmpdirInstance(
+ (dir) =>
+ Effect.gen(function* () {
+ workspaceSymbolQueries.length = 0
+ const file = path.join(dir, "test.ts")
+ yield* put(file)
+
+ yield* run({ operation: "workspaceSymbol", filePath: file, line: 3, character: 7, query: "TestSymbol" })
+ yield* run({ operation: "workspaceSymbol", filePath: file, line: 3, character: 7 })
+
+ expect(workspaceSymbolQueries).toEqual(["TestSymbol", ""])
+ }),
+ { git: true },
+ ),
+ )
})
})