From d4347e829d844af79c522e50c2bb1b0c01cd8c81 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 7 Jan 2026 02:55:32 +0900 Subject: [PATCH] fix(auto-slash-command): load skill content via lazyContentLoader and include builtin skills --- src/hooks/auto-slash-command/executor.ts | 27 +++++++++++++++++------- src/hooks/auto-slash-command/index.ts | 15 ++++++++++--- src/index.ts | 8 +++---- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/hooks/auto-slash-command/executor.ts b/src/hooks/auto-slash-command/executor.ts index e291473..d329a30 100644 --- a/src/hooks/auto-slash-command/executor.ts +++ b/src/hooks/auto-slash-command/executor.ts @@ -10,7 +10,7 @@ import { } from "../../shared" import type { CommandFrontmatter } from "../../features/claude-code-command-loader/types" import { isMarkdownFile } from "../../shared/file-utils" -import { discoverAllSkills, type LoadedSkill } from "../../features/opencode-skill-loader" +import { discoverAllSkills, type LoadedSkill, type LazyContentLoader } from "../../features/opencode-skill-loader" import type { ParsedSlashCommand } from "./types" interface CommandScope { @@ -32,6 +32,7 @@ interface CommandInfo { metadata: CommandMetadata content?: string scope: CommandScope["type"] + lazyContentLoader?: LazyContentLoader } function discoverCommandsFromDir(commandsDir: string, scope: CommandScope["type"]): CommandInfo[] { @@ -91,10 +92,15 @@ function skillToCommandInfo(skill: LoadedSkill): CommandInfo { }, content: skill.definition.template, scope: "skill", + lazyContentLoader: skill.lazyContent, } } -async function discoverAllCommands(): Promise { +export interface ExecutorOptions { + skills?: LoadedSkill[] +} + +async function discoverAllCommands(options?: ExecutorOptions): Promise { const userCommandsDir = join(getClaudeConfigDir(), "commands") const projectCommandsDir = join(process.cwd(), ".claude", "commands") const opencodeGlobalDir = join(homedir(), ".config", "opencode", "command") @@ -105,7 +111,7 @@ async function discoverAllCommands(): Promise { const projectCommands = discoverCommandsFromDir(projectCommandsDir, "project") const opencodeProjectCommands = discoverCommandsFromDir(opencodeProjectDir, "opencode-project") - const skills = await discoverAllSkills() + const skills = options?.skills ?? await discoverAllSkills() const skillCommands = skills.map(skillToCommandInfo) return [ @@ -117,8 +123,8 @@ async function discoverAllCommands(): Promise { ] } -async function findCommand(commandName: string): Promise { - const allCommands = await discoverAllCommands() +async function findCommand(commandName: string, options?: ExecutorOptions): Promise { + const allCommands = await discoverAllCommands(options) return allCommands.find( (cmd) => cmd.name.toLowerCase() === commandName.toLowerCase() ) ?? null @@ -149,8 +155,13 @@ async function formatCommandTemplate(cmd: CommandInfo, args: string): Promise { - const command = await findCommand(parsed.command) +export async function executeSlashCommand(parsed: ParsedSlashCommand, options?: ExecutorOptions): Promise { + const command = await findCommand(parsed.command, options) if (!command) { return { diff --git a/src/hooks/auto-slash-command/index.ts b/src/hooks/auto-slash-command/index.ts index 8182a88..0b034a2 100644 --- a/src/hooks/auto-slash-command/index.ts +++ b/src/hooks/auto-slash-command/index.ts @@ -2,7 +2,7 @@ import { detectSlashCommand, extractPromptText, } from "./detector" -import { executeSlashCommand } from "./executor" +import { executeSlashCommand, type ExecutorOptions } from "./executor" import { log } from "../../shared" import { AUTO_SLASH_COMMAND_TAG_OPEN, @@ -12,6 +12,7 @@ import type { AutoSlashCommandHookInput, AutoSlashCommandHookOutput, } from "./types" +import type { LoadedSkill } from "../../features/opencode-skill-loader" export * from "./detector" export * from "./executor" @@ -20,7 +21,15 @@ export * from "./types" const sessionProcessedCommands = new Set() -export function createAutoSlashCommandHook() { +export interface AutoSlashCommandHookOptions { + skills?: LoadedSkill[] +} + +export function createAutoSlashCommandHook(options?: AutoSlashCommandHookOptions) { + const executorOptions: ExecutorOptions = { + skills: options?.skills, + } + return { "chat.message": async ( input: AutoSlashCommandHookInput, @@ -52,7 +61,7 @@ export function createAutoSlashCommandHook() { args: parsed.args, }) - const result = await executeSlashCommand(parsed) + const result = await executeSlashCommand(parsed, executorOptions) const idx = output.parts.findIndex((p) => p.type === "text" && p.text) if (idx < 0) { diff --git a/src/index.ts b/src/index.ts index df4e248..bae5d02 100644 --- a/src/index.ts +++ b/src/index.ts @@ -166,10 +166,6 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => { }) : null; - const autoSlashCommand = isHookEnabled("auto-slash-command") - ? createAutoSlashCommandHook() - : null; - const editErrorRecovery = isHookEnabled("edit-error-recovery") ? createEditErrorRecoveryHook(ctx) : null; @@ -239,6 +235,10 @@ const OhMyOpenCodePlugin: Plugin = async (ctx) => { skills: mergedSkills, }); + const autoSlashCommand = isHookEnabled("auto-slash-command") + ? createAutoSlashCommandHook({ skills: mergedSkills }) + : null; + const googleAuthHooks = pluginConfig.google_auth !== false ? await createGoogleAntigravityAuthPlugin(ctx) : null;