Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 59 additions & 6 deletions packages/opencode/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { BunProc } from "@/bun"
import { Installation } from "@/installation"
import { ConfigMarkdown } from "./markdown"
import { existsSync } from "fs"
import { Bus } from "@/bus"
import { TuiEvent } from "@/cli/cmd/tui/event"

export namespace Config {
const log = Log.create({ service: "config" })
Expand Down Expand Up @@ -218,8 +220,25 @@ export namespace Config {
dot: true,
cwd: dir,
})) {
const md = await ConfigMarkdown.parse(item)
if (!md.data) continue
const md = await ConfigMarkdown.parse(item).catch((err) => {
if (!ConfigMarkdown.FrontmatterError.isInstance(err)) {
log.error("failed to load command", { path: item, error: err })
return undefined
}
log.error("failed to parse command frontmatter", {
path: err.data.path,
message: err.data.message,
})
const relativePath = path.relative(dir, item)
Bus.publish(TuiEvent.ToastShow, {
title: "Command Error",
message: `Failed to parse ${relativePath}: ${err.data.message.split(":")[0]}`,
variant: "error",
duration: 8000,
})
return undefined
})
if (!md?.data) continue

const name = (() => {
const patterns = ["/.opencode/command/", "/command/"]
Expand Down Expand Up @@ -257,8 +276,25 @@ export namespace Config {
dot: true,
cwd: dir,
})) {
const md = await ConfigMarkdown.parse(item)
if (!md.data) continue
const md = await ConfigMarkdown.parse(item).catch((err) => {
if (!ConfigMarkdown.FrontmatterError.isInstance(err)) {
log.error("failed to load agent", { path: item, error: err })
return undefined
}
log.error("failed to parse agent frontmatter", {
path: err.data.path,
message: err.data.message,
})
const relativePath = path.relative(dir, item)
Bus.publish(TuiEvent.ToastShow, {
title: "Agent Error",
message: `Failed to parse ${relativePath}: ${err.data.message.split(":")[0]}`,
variant: "error",
duration: 8000,
})
return undefined
})
if (!md?.data) continue

// Extract relative path from agent folder for nested agents
let agentName = path.basename(item, ".md")
Expand Down Expand Up @@ -299,8 +335,25 @@ export namespace Config {
dot: true,
cwd: dir,
})) {
const md = await ConfigMarkdown.parse(item)
if (!md.data) continue
const md = await ConfigMarkdown.parse(item).catch((err) => {
if (!ConfigMarkdown.FrontmatterError.isInstance(err)) {
log.error("failed to load mode", { path: item, error: err })
return undefined
}
log.error("failed to parse mode frontmatter", {
path: err.data.path,
message: err.data.message,
})
const relativePath = path.relative(dir, item)
Bus.publish(TuiEvent.ToastShow, {
title: "Mode Error",
message: `Failed to parse ${relativePath}: ${err.data.message.split(":")[0]}`,
variant: "error",
duration: 8000,
})
return undefined
})
if (!md?.data) continue

const config = {
name: path.basename(item, ".md"),
Expand Down
23 changes: 22 additions & 1 deletion packages/opencode/src/skill/skill.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import z from "zod"
import path from "path"
import { Config } from "../config/config"
import { Instance } from "../project/instance"
import { NamedError } from "@opencode-ai/util/error"
Expand All @@ -8,6 +9,8 @@ import { Global } from "@/global"
import { Filesystem } from "@/util/filesystem"
import { exists } from "fs/promises"
import { Flag } from "@/flag/flag"
import { Bus } from "@/bus"
import { TuiEvent } from "@/cli/cmd/tui/event"

export namespace Skill {
const log = Log.create({ service: "skill" })
Expand Down Expand Up @@ -43,7 +46,25 @@ export namespace Skill {
const skills: Record<string, Info> = {}

const addSkill = async (match: string) => {
const md = await ConfigMarkdown.parse(match)
const md = await ConfigMarkdown.parse(match).catch((err) => {
if (!ConfigMarkdown.FrontmatterError.isInstance(err)) {
log.error("failed to load skill", { path: match, error: err })
return undefined
}
log.error("failed to parse skill frontmatter", {
path: err.data.path,
message: err.data.message,
})
const relativePath = path.relative(Instance.directory, match)
Bus.publish(TuiEvent.ToastShow, {
title: "Skill Error",
message: `Failed to parse ${relativePath}: ${err.data.message.split(":")[0]}`,
variant: "error",
duration: 8000,
})
return undefined
})

if (!md) {
return
}
Expand Down