diff --git a/packages/opencode/src/cli/error.ts b/packages/opencode/src/cli/error.ts index 1bc20de3..7c873ae5 100644 --- a/packages/opencode/src/cli/error.ts +++ b/packages/opencode/src/cli/error.ts @@ -1,3 +1,4 @@ +import { ConfigMarkdown } from "@/config/markdown" import { Config } from "../config/config" import { MCP } from "../mcp" import { UI } from "./ui" @@ -7,16 +8,22 @@ export function FormatError(input: unknown) { return `MCP server "${input.data.name}" failed. Note, opencode does not support MCP authentication yet.` if (Config.JsonError.isInstance(input)) { return ( - `Config file at ${input.data.path} is not valid JSON(C)` + (input.data.message ? `: ${input.data.message}` : "") + `Config file at ${input.data.path} is not valid JSON(C)` + + (input.data.message ? `: ${input.data.message}` : "") ) } if (Config.ConfigDirectoryTypoError.isInstance(input)) { return `Directory "${input.data.dir}" in ${input.data.path} is not valid. Use "${input.data.suggestion}" instead. This is a common typo.` } + if (ConfigMarkdown.FrontmatterError.isInstance(input)) { + return `Failed to parse frontmatter in ${input.data.path}:\n${input.data.message}` + } if (Config.InvalidError.isInstance(input)) return [ - `Config file at ${input.data.path} is invalid` + (input.data.message ? `: ${input.data.message}` : ""), - ...(input.data.issues?.map((issue) => "↳ " + issue.message + " " + issue.path.join(".")) ?? []), + `Config file at ${input.data.path} is invalid` + + (input.data.message ? `: ${input.data.message}` : ""), + ...(input.data.issues?.map((issue) => "↳ " + issue.message + " " + issue.path.join(".")) ?? + []), ].join("\n") if (UI.CancelledError.isInstance(input)) return "" diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index 12a5c162..031c4d82 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -9,7 +9,6 @@ import { Global } from "../global" import fs from "fs/promises" import { lazy } from "../util/lazy" import { NamedError } from "../util/error" -import matter from "gray-matter" import { Flag } from "../flag/flag" import { Auth } from "../auth" import { @@ -21,6 +20,7 @@ import { Instance } from "../project/instance" import { LSPServer } from "../lsp/server" import { BunProc } from "@/bun" import { Installation } from "@/installation" +import { ConfigMarkdown } from "./markdown" export namespace Config { const log = Log.create({ service: "config" }) @@ -191,8 +191,7 @@ export namespace Config { dot: true, cwd: dir, })) { - const content = await Bun.file(item).text() - const md = matter(content) + const md = await ConfigMarkdown.parse(item) if (!md.data) continue const name = (() => { @@ -231,8 +230,7 @@ export namespace Config { dot: true, cwd: dir, })) { - const content = await Bun.file(item).text() - const md = matter(content) + const md = await ConfigMarkdown.parse(item) if (!md.data) continue // Extract relative path from agent folder for nested agents @@ -274,8 +272,7 @@ export namespace Config { dot: true, cwd: dir, })) { - const content = await Bun.file(item).text() - const md = matter(content) + const md = await ConfigMarkdown.parse(item) if (!md.data) continue const config = { diff --git a/packages/opencode/src/config/markdown.ts b/packages/opencode/src/config/markdown.ts index a4dcbf5d..3e84bbf4 100644 --- a/packages/opencode/src/config/markdown.ts +++ b/packages/opencode/src/config/markdown.ts @@ -1,3 +1,7 @@ +import { NamedError } from "@/util/error" +import matter from "gray-matter" +import { z } from "zod" + export namespace ConfigMarkdown { export const FILE_REGEX = /(?