import React from "react"; import { useTranslation } from "react-i18next"; import { isHookExecutionEvent } from "#/types/agent-server/type-guards"; import { OpenHandsEvent } from "#/types/agent-server/core"; import { GenericEventMessage } from "#/components/features/chat/generic-event-message"; import { cn } from "#/utils/utils"; import { I18nKey } from "#/i18n/declaration"; interface HookExecutionEventMessageProps { event: OpenHandsEvent; } function getHookIcon(hookType: string, blocked: boolean): string { if (blocked) { return "đĢ"; } switch (hookType) { case "PreToolUse": return "âŗ"; case "PostToolUse": return "â "; case "UserPromptSubmit": return "đ"; case "SessionStart": return "đ"; case "SessionEnd": return "đ"; case "Stop": return "âšī¸"; default: return "đ"; } } function formatHookCommand(command: string): string { // Truncate long commands for display if (command.length > 80) { return `${command.slice(0, 77)}...`; } return command; } function getStatusText(blocked: boolean, success: boolean): string { if (blocked) return "blocked"; if (success) return "ok"; return "failed"; } function getStatusClassName(blocked: boolean, success: boolean): string { if (blocked) return "bg-amber-900/50 text-amber-300"; if (success) return "bg-green-900/50 text-green-300"; return "bg-red-900/50 text-red-300"; } export function HookExecutionEventMessage({ event, }: HookExecutionEventMessageProps) { const { t } = useTranslation("openhands"); if (!isHookExecutionEvent(event)) { return null; } const icon = getHookIcon(event.hook_event_type, event.blocked); const statusText = getStatusText(event.blocked, event.success); const statusClassName = getStatusClassName(event.blocked, event.success); // Determine the overall success indicator for GenericEventMessage. // When blocked, suppress the success indicator entirely â the amber "blocked" // badge in the title is the authoritative status signal. const getSuccessStatus = (): "success" | "error" | undefined => { if (event.blocked) return undefined; return event.success ? "success" : "error"; }; const successStatus = getSuccessStatus(); const title = ( {icon} {t(I18nKey.HOOK$HOOK_LABEL)}: {event.hook_event_type} {event.tool_name && ( ({event.tool_name}) )} {statusText} ); const details = (
{formatHookCommand(event.hook_command)}
{event.stdout}
{event.stderr}