Files
oh-my-openagent/src/hooks/auto-slash-command/index.ts

92 lines
2.6 KiB
TypeScript

import {
detectSlashCommand,
extractPromptText,
} from "./detector"
import { executeSlashCommand, type ExecutorOptions } from "./executor"
import { log } from "../../shared"
import {
AUTO_SLASH_COMMAND_TAG_OPEN,
AUTO_SLASH_COMMAND_TAG_CLOSE,
} from "./constants"
import type {
AutoSlashCommandHookInput,
AutoSlashCommandHookOutput,
} from "./types"
import type { LoadedSkill } from "../../features/opencode-skill-loader"
export * from "./detector"
export * from "./executor"
export * from "./constants"
export * from "./types"
const sessionProcessedCommands = new Set<string>()
export interface AutoSlashCommandHookOptions {
skills?: LoadedSkill[]
}
export function createAutoSlashCommandHook(options?: AutoSlashCommandHookOptions) {
const executorOptions: ExecutorOptions = {
skills: options?.skills,
}
return {
"chat.message": async (
input: AutoSlashCommandHookInput,
output: AutoSlashCommandHookOutput
): Promise<void> => {
const promptText = extractPromptText(output.parts)
if (
promptText.includes(AUTO_SLASH_COMMAND_TAG_OPEN) ||
promptText.includes(AUTO_SLASH_COMMAND_TAG_CLOSE)
) {
return
}
const parsed = detectSlashCommand(promptText)
if (!parsed) {
return
}
const commandKey = `${input.sessionID}:${input.messageID}:${parsed.command}`
if (sessionProcessedCommands.has(commandKey)) {
return
}
sessionProcessedCommands.add(commandKey)
log(`[auto-slash-command] Detected: /${parsed.command}`, {
sessionID: input.sessionID,
args: parsed.args,
})
const result = await executeSlashCommand(parsed, executorOptions)
const idx = output.parts.findIndex((p) => p.type === "text" && p.text)
if (idx < 0) {
return
}
if (result.success && result.replacementText) {
const taggedContent = `${AUTO_SLASH_COMMAND_TAG_OPEN}\n${result.replacementText}\n${AUTO_SLASH_COMMAND_TAG_CLOSE}`
output.parts[idx].text = taggedContent
log(`[auto-slash-command] Replaced message with command template`, {
sessionID: input.sessionID,
command: parsed.command,
})
} else {
const errorMessage = `${AUTO_SLASH_COMMAND_TAG_OPEN}\n[AUTO-SLASH-COMMAND ERROR]\n${result.error}\n\nOriginal input: ${parsed.raw}\n${AUTO_SLASH_COMMAND_TAG_CLOSE}`
output.parts[idx].text = errorMessage
log(`[auto-slash-command] Command not found, showing error`, {
sessionID: input.sessionID,
command: parsed.command,
error: result.error,
})
}
},
}
}