feat(dispatch): wire marketplace plugin commands into slash command dispatch

Connect the existing plugin loader infrastructure to both slash command
dispatch paths (executor and slashcommand tool), enabling namespaced
commands like /daplug:run-prompt to resolve and execute.

- Add plugin discovery to executor.ts discoverAllCommands()
- Add plugin discovery to command-discovery.ts discoverCommandsSync()
- Add "plugin" to CommandScope type
- Remove blanket colon-rejection error (replaced with standard not-found)
- Update slash command regex to accept namespaced commands
- Thread claude_code.plugins config toggle through dispatch chain
- Add unit tests for plugin command discovery and dispatch

Closes #2019

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
Gershom Rogers
2026-02-21 10:05:50 -05:00
parent 111ae5ea5a
commit 6dd8d60d49
14 changed files with 461 additions and 14 deletions
+15 -3
View File
@@ -1,5 +1,5 @@
import type { AvailableSkill } from "../../agents/dynamic-agent-prompt-builder"
import type { HookName } from "../../config"
import type { HookName, OhMyOpenCodeConfig } from "../../config"
import type { LoadedSkill } from "../../features/opencode-skill-loader/types"
import type { PluginContext } from "../types"
@@ -13,12 +13,20 @@ export type SkillHooks = {
export function createSkillHooks(args: {
ctx: PluginContext
pluginConfig: OhMyOpenCodeConfig
isHookEnabled: (hookName: HookName) => boolean
safeHookEnabled: boolean
mergedSkills: LoadedSkill[]
availableSkills: AvailableSkill[]
}): SkillHooks {
const { ctx, isHookEnabled, safeHookEnabled, mergedSkills, availableSkills } = args
const {
ctx,
pluginConfig,
isHookEnabled,
safeHookEnabled,
mergedSkills,
availableSkills,
} = args
const safeHook = <T>(hookName: HookName, factory: () => T): T | null =>
safeCreateHook(hookName, factory, { enabled: safeHookEnabled })
@@ -30,7 +38,11 @@ export function createSkillHooks(args: {
const autoSlashCommand = isHookEnabled("auto-slash-command")
? safeHook("auto-slash-command", () =>
createAutoSlashCommandHook({ skills: mergedSkills }))
createAutoSlashCommandHook({
skills: mergedSkills,
pluginsEnabled: pluginConfig.claude_code?.plugins ?? true,
enabledPluginsOverride: pluginConfig.claude_code?.plugins_override,
}))
: null
return { categorySkillReminder, autoSlashCommand }