diff --git a/packages/opencode/src/config/lsp.ts b/packages/opencode/src/config/lsp.ts index accfbee3b2..ea7328a809 100644 --- a/packages/opencode/src/config/lsp.ts +++ b/packages/opencode/src/config/lsp.ts @@ -1,13 +1,11 @@ export * as ConfigLSP from "./lsp" import { Schema } from "effect" -import { zod } from "@opencode-ai/core/effect-zod" -import { withStatics } from "@opencode-ai/core/schema" import * as LSPServer from "../lsp/server" export const Disabled = Schema.Struct({ disabled: Schema.Literal(true), -}).pipe(withStatics((s) => ({ zod: zod(s) }))) +}).pipe((schema) => schema) export const Entry = Schema.Union([ Disabled, @@ -18,7 +16,7 @@ export const Entry = Schema.Union([ env: Schema.optional(Schema.Record(Schema.String, Schema.String)), initialization: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)), }), -]).pipe(withStatics((s) => ({ zod: zod(s) }))) +]).pipe((schema) => schema) /** * For custom (non-builtin) LSP server entries, `extensions` is required so the @@ -40,6 +38,6 @@ export const requiresExtensionsForCustomServers = Schema.makeFilter< export const Info = Schema.Union([Schema.Boolean, Schema.Record(Schema.String, Entry)]) .check(requiresExtensionsForCustomServers) - .pipe(withStatics((s) => ({ zod: zod(s) }))) + .pipe((schema) => schema) export type Info = Schema.Schema.Type diff --git a/packages/opencode/test/config/lsp.test.ts b/packages/opencode/test/config/lsp.test.ts index 1d24fe124d..ff0048a190 100644 --- a/packages/opencode/test/config/lsp.test.ts +++ b/packages/opencode/test/config/lsp.test.ts @@ -7,10 +7,6 @@ import { ConfigLSP } from "../../src/config/lsp" // the server should attach to. Builtin server IDs and explicitly disabled // entries are exempt. // -// Both validation paths must honor this rule: -// - `Schema.decodeUnknownSync(ConfigLSP.Info)` (Effect layer) -// - `ConfigLSP.Info.zod.parse(...)` (derived Zod) -// // `typescript` is a builtin server id (see src/lsp/server.ts). describe("ConfigLSP.Info refinement", () => { const decodeEffect = Schema.decodeUnknownSync(ConfigLSP.Info) @@ -19,14 +15,11 @@ describe("ConfigLSP.Info refinement", () => { test("true and false pass (top-level toggle)", () => { expect(decodeEffect(true)).toBe(true) expect(decodeEffect(false)).toBe(false) - expect(ConfigLSP.Info.zod.parse(true)).toBe(true) - expect(ConfigLSP.Info.zod.parse(false)).toBe(false) }) test("builtin server with no extensions passes", () => { const input = { typescript: { command: ["typescript-language-server", "--stdio"] } } expect(decodeEffect(input)).toEqual(input) - expect(ConfigLSP.Info.zod.parse(input)).toEqual(input) }) test("custom server WITH extensions passes", () => { @@ -34,13 +27,11 @@ describe("ConfigLSP.Info refinement", () => { "my-lsp": { command: ["my-lsp-bin"], extensions: [".ml"] }, } expect(decodeEffect(input)).toEqual(input) - expect(ConfigLSP.Info.zod.parse(input)).toEqual(input) }) test("disabled custom server passes (no extensions needed)", () => { const input = { "my-lsp": { disabled: true as const } } expect(decodeEffect(input)).toEqual(input) - expect(ConfigLSP.Info.zod.parse(input)).toEqual(input) }) test("mix of builtin and custom with extensions passes", () => { @@ -49,7 +40,6 @@ describe("ConfigLSP.Info refinement", () => { "my-lsp": { command: ["my-lsp-bin"], extensions: [".ml"] }, } expect(decodeEffect(input)).toEqual(input) - expect(ConfigLSP.Info.zod.parse(input)).toEqual(input) }) }) @@ -60,19 +50,12 @@ describe("ConfigLSP.Info refinement", () => { expect(() => decodeEffect({ "my-lsp": { command: ["my-lsp-bin"] } })).toThrow(expectedMessage) }) - test("custom server WITHOUT extensions fails via derived Zod", () => { - const result = ConfigLSP.Info.zod.safeParse({ "my-lsp": { command: ["my-lsp-bin"] } }) - expect(result.success).toBe(false) - expect(result.error!.issues.some((i) => i.message === expectedMessage)).toBe(true) - }) - test("custom server with empty extensions array fails (extensions must be non-empty-truthy)", () => { // Boolean(['']) is true, so a non-empty array of strings is fine. // Boolean([]) is also true in JS, so empty arrays are accepted by the // refinement. This test documents current behavior. const input = { "my-lsp": { command: ["my-lsp-bin"], extensions: [] } } expect(decodeEffect(input)).toEqual(input) - expect(ConfigLSP.Info.zod.parse(input)).toEqual(input) }) test("custom server without extensions mixed with a valid builtin still fails", () => { @@ -81,7 +64,6 @@ describe("ConfigLSP.Info refinement", () => { "my-lsp": { command: ["my-lsp-bin"] }, } expect(() => decodeEffect(input)).toThrow(expectedMessage) - expect(ConfigLSP.Info.zod.safeParse(input).success).toBe(false) }) }) })