slash commands (#2157)

Co-authored-by: adamdotdevin <2363879+adamdottv@users.noreply.github.com>
This commit is contained in:
Dax
2025-08-22 17:04:28 -04:00
committed by GitHub
parent 74c1085103
commit 133fe41cd5
32 changed files with 874 additions and 69 deletions

View File

@@ -107,6 +107,32 @@ export namespace Config {
}
throw new InvalidError({ path: item }, { cause: parsed.error })
}
// Load command markdown files
result.command = result.command || {}
const markdownCommands = [
...(await Filesystem.globUp("command/*.md", Global.Path.config, Global.Path.config)),
...(await Filesystem.globUp(".opencode/command/*.md", app.path.cwd, app.path.root)),
]
for (const item of markdownCommands) {
const content = await Bun.file(item).text()
const md = matter(content)
if (!md.data) continue
const config = {
name: path.basename(item, ".md"),
...md.data,
template: md.content.trim(),
}
const parsed = Command.safeParse(config)
if (parsed.success) {
result.command = mergeDeep(result.command, {
[config.name]: parsed.data,
})
continue
}
throw new InvalidError({ path: item }, { cause: parsed.error })
}
// Migrate deprecated mode field to agent field
for (const [name, mode] of Object.entries(result.mode)) {
result.agent = mergeDeep(result.agent ?? {}, {
@@ -192,6 +218,14 @@ export namespace Config {
export const Permission = z.union([z.literal("ask"), z.literal("allow"), z.literal("deny")])
export type Permission = z.infer<typeof Permission>
export const Command = z.object({
template: z.string(),
description: z.string().optional(),
agent: z.string().optional(),
model: z.string().optional(),
})
export type Command = z.infer<typeof Command>
export const Agent = z
.object({
model: z.string().optional(),
@@ -305,6 +339,7 @@ export namespace Config {
theme: z.string().optional().describe("Theme name to use for the interface"),
keybinds: Keybinds.optional().describe("Custom keybind configurations"),
tui: TUI.optional().describe("TUI specific settings"),
command: z.record(z.string(), Command).optional(),
plugin: z.string().array().optional(),
snapshot: z.boolean().optional(),
share: z