mirror of
https://fastgit.cc/https://github.com/anomalyco/opencode
synced 2026-04-20 21:00:29 +08:00
refactor: split config lsp and formatter schemas (#22986)
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
- Use Bun APIs when possible, like `Bun.file()`
|
- Use Bun APIs when possible, like `Bun.file()`
|
||||||
- Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity
|
- Rely on type inference when possible; avoid explicit type annotations or interfaces unless necessary for exports or clarity
|
||||||
- Prefer functional array methods (flatMap, filter, map) over for loops; use type guards on filter to maintain type inference downstream
|
- Prefer functional array methods (flatMap, filter, map) over for loops; use type guards on filter to maintain type inference downstream
|
||||||
|
- In `src/config`, follow the existing self-export pattern at the top of the file (for example `export * as ConfigAgent from "./agent"`) when adding a new config module.
|
||||||
|
|
||||||
Reduce total variable count by inlining when a value is only used once.
|
Reduce total variable count by inlining when a value is only used once.
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ See `specs/effect/migration.md` for the compact pattern reference and examples.
|
|||||||
- Use `Effect.callback` for callback-based APIs.
|
- Use `Effect.callback` for callback-based APIs.
|
||||||
- Prefer `DateTime.nowAsDate` over `new Date(yield* Clock.currentTimeMillis)` when you need a `Date`.
|
- Prefer `DateTime.nowAsDate` over `new Date(yield* Clock.currentTimeMillis)` when you need a `Date`.
|
||||||
|
|
||||||
|
## Module conventions
|
||||||
|
|
||||||
|
- In `src/config`, follow the existing self-export pattern at the top of the file (for example `export * as ConfigAgent from "./agent"`) when adding a new config module.
|
||||||
|
|
||||||
## Schemas and errors
|
## Schemas and errors
|
||||||
|
|
||||||
- Use `Schema.Class` for multi-field data.
|
- Use `Schema.Class` for multi-field data.
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { Auth } from "../auth"
|
|||||||
import { Env } from "../env"
|
import { Env } from "../env"
|
||||||
import { applyEdits, modify } from "jsonc-parser"
|
import { applyEdits, modify } from "jsonc-parser"
|
||||||
import { Instance, type InstanceContext } from "../project/instance"
|
import { Instance, type InstanceContext } from "../project/instance"
|
||||||
import * as LSPServer from "../lsp/server"
|
|
||||||
import { InstallationLocal, InstallationVersion } from "@/installation/version"
|
import { InstallationLocal, InstallationVersion } from "@/installation/version"
|
||||||
import { existsSync } from "fs"
|
import { existsSync } from "fs"
|
||||||
import { GlobalBus } from "@/bus/global"
|
import { GlobalBus } from "@/bus/global"
|
||||||
@@ -37,6 +36,8 @@ import { ConfigPermission } from "./permission"
|
|||||||
import { ConfigProvider } from "./provider"
|
import { ConfigProvider } from "./provider"
|
||||||
import { ConfigSkills } from "./skills"
|
import { ConfigSkills } from "./skills"
|
||||||
import { ConfigPaths } from "./paths"
|
import { ConfigPaths } from "./paths"
|
||||||
|
import { ConfigFormatter } from "./formatter"
|
||||||
|
import { ConfigLSP } from "./lsp"
|
||||||
|
|
||||||
const log = Log.create({ service: "config" })
|
const log = Log.create({ service: "config" })
|
||||||
|
|
||||||
@@ -186,56 +187,8 @@ export const Info = z
|
|||||||
)
|
)
|
||||||
.optional()
|
.optional()
|
||||||
.describe("MCP (Model Context Protocol) server configurations"),
|
.describe("MCP (Model Context Protocol) server configurations"),
|
||||||
formatter: z
|
formatter: ConfigFormatter.Info.optional(),
|
||||||
.union([
|
lsp: ConfigLSP.Info.optional(),
|
||||||
z.literal(false),
|
|
||||||
z.record(
|
|
||||||
z.string(),
|
|
||||||
z.object({
|
|
||||||
disabled: z.boolean().optional(),
|
|
||||||
command: z.array(z.string()).optional(),
|
|
||||||
environment: z.record(z.string(), z.string()).optional(),
|
|
||||||
extensions: z.array(z.string()).optional(),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
.optional(),
|
|
||||||
lsp: z
|
|
||||||
.union([
|
|
||||||
z.literal(false),
|
|
||||||
z.record(
|
|
||||||
z.string(),
|
|
||||||
z.union([
|
|
||||||
z.object({
|
|
||||||
disabled: z.literal(true),
|
|
||||||
}),
|
|
||||||
z.object({
|
|
||||||
command: z.array(z.string()),
|
|
||||||
extensions: z.array(z.string()).optional(),
|
|
||||||
disabled: z.boolean().optional(),
|
|
||||||
env: z.record(z.string(), z.string()).optional(),
|
|
||||||
initialization: z.record(z.string(), z.any()).optional(),
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
])
|
|
||||||
.optional()
|
|
||||||
.refine(
|
|
||||||
(data) => {
|
|
||||||
if (!data) return true
|
|
||||||
if (typeof data === "boolean") return true
|
|
||||||
const serverIds = new Set(Object.values(LSPServer).map((s) => s.id))
|
|
||||||
|
|
||||||
return Object.entries(data).every(([id, config]) => {
|
|
||||||
if (config.disabled) return true
|
|
||||||
if (serverIds.has(id)) return true
|
|
||||||
return Boolean(config.extensions)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
{
|
|
||||||
error: "For custom LSP servers, 'extensions' array is required.",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
instructions: z.array(z.string()).optional().describe("Additional instruction files or patterns to include"),
|
instructions: z.array(z.string()).optional().describe("Additional instruction files or patterns to include"),
|
||||||
layout: Layout.optional().describe("@deprecated Always uses stretch layout."),
|
layout: Layout.optional().describe("@deprecated Always uses stretch layout."),
|
||||||
permission: ConfigPermission.Info.optional(),
|
permission: ConfigPermission.Info.optional(),
|
||||||
|
|||||||
13
packages/opencode/src/config/formatter.ts
Normal file
13
packages/opencode/src/config/formatter.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export * as ConfigFormatter from "./formatter"
|
||||||
|
|
||||||
|
import z from "zod"
|
||||||
|
|
||||||
|
export const Entry = z.object({
|
||||||
|
disabled: z.boolean().optional(),
|
||||||
|
command: z.array(z.string()).optional(),
|
||||||
|
environment: z.record(z.string(), z.string()).optional(),
|
||||||
|
extensions: z.array(z.string()).optional(),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const Info = z.union([z.literal(false), z.record(z.string(), Entry)])
|
||||||
|
export type Info = z.infer<typeof Info>
|
||||||
@@ -2,6 +2,8 @@ export * as Config from "./config"
|
|||||||
export * as ConfigAgent from "./agent"
|
export * as ConfigAgent from "./agent"
|
||||||
export * as ConfigCommand from "./command"
|
export * as ConfigCommand from "./command"
|
||||||
export * as ConfigError from "./error"
|
export * as ConfigError from "./error"
|
||||||
|
export * as ConfigFormatter from "./formatter"
|
||||||
|
export * as ConfigLSP from "./lsp"
|
||||||
export * as ConfigVariable from "./variable"
|
export * as ConfigVariable from "./variable"
|
||||||
export { ConfigManaged } from "./managed"
|
export { ConfigManaged } from "./managed"
|
||||||
export * as ConfigMarkdown from "./markdown"
|
export * as ConfigMarkdown from "./markdown"
|
||||||
|
|||||||
39
packages/opencode/src/config/lsp.ts
Normal file
39
packages/opencode/src/config/lsp.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
export * as ConfigLSP from "./lsp"
|
||||||
|
|
||||||
|
import z from "zod"
|
||||||
|
import * as LSPServer from "../lsp/server"
|
||||||
|
|
||||||
|
export const Disabled = z.object({
|
||||||
|
disabled: z.literal(true),
|
||||||
|
})
|
||||||
|
|
||||||
|
export const Entry = z.union([
|
||||||
|
Disabled,
|
||||||
|
z.object({
|
||||||
|
command: z.array(z.string()),
|
||||||
|
extensions: z.array(z.string()).optional(),
|
||||||
|
disabled: z.boolean().optional(),
|
||||||
|
env: z.record(z.string(), z.string()).optional(),
|
||||||
|
initialization: z.record(z.string(), z.any()).optional(),
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
export const Info = z
|
||||||
|
.union([z.literal(false), z.record(z.string(), Entry)])
|
||||||
|
.refine(
|
||||||
|
(data) => {
|
||||||
|
if (typeof data === "boolean") return true
|
||||||
|
const serverIds = new Set(Object.values(LSPServer).map((server) => server.id))
|
||||||
|
|
||||||
|
return Object.entries(data).every(([id, config]) => {
|
||||||
|
if (config.disabled) return true
|
||||||
|
if (serverIds.has(id)) return true
|
||||||
|
return Boolean(config.extensions)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
{
|
||||||
|
error: "For custom LSP servers, 'extensions' array is required.",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
export type Info = z.infer<typeof Info>
|
||||||
Reference in New Issue
Block a user