import type { GlobalCommand } from '@/app/workspace/[workspaceId]/providers/global-commands-provider' /** * Identifiers for all globally-available commands. * * Components must use these identifiers (via {@link createCommand}) rather than * ad-hoc ids or shortcuts to ensure a single source of truth. */ export type CommandId = | 'accept-diff-changes' | 'add-agent' | 'add-workflow' | 'goto-logs' | 'open-search' | 'open-workflow-search-replace' | 'run-workflow' | 'clear-terminal-console' | 'focus-toolbar-search' | 'fit-to-view' | 'toggle-sidebar' /** * Static metadata for a global command. * * This central registry defines the keyboard shortcut and default behavior * for whether the command is allowed inside editable elements. */ interface CommandDefinition { /** Stable identifier for the command. */ id: CommandId /** Shortcut string in the form "Mod+Shift+A", "Mod+Enter", etc. */ shortcut: string /** * Whether to allow the command inside editable elements such as inputs and * textareas. When omitted, the command provider will default to `true`. */ allowInEditable?: boolean } /** * Central mapping from command id to its definition. * * All global commands must be declared here to be usable. */ export const COMMAND_DEFINITIONS: Record = { 'accept-diff-changes': { id: 'accept-diff-changes', shortcut: 'Mod+Shift+Enter', allowInEditable: true, }, 'add-agent': { id: 'add-agent', shortcut: 'Mod+Shift+A', allowInEditable: true, }, 'add-workflow': { id: 'add-workflow', shortcut: 'Mod+Shift+P', allowInEditable: false, }, 'goto-logs': { id: 'goto-logs', shortcut: 'Mod+L', allowInEditable: true, }, 'open-search': { id: 'open-search', shortcut: 'Mod+K', allowInEditable: true, }, 'open-workflow-search-replace': { id: 'open-workflow-search-replace', shortcut: 'Mod+F', allowInEditable: true, }, 'run-workflow': { id: 'run-workflow', shortcut: 'Mod+Enter', allowInEditable: false, }, 'clear-terminal-console': { id: 'clear-terminal-console', shortcut: 'Mod+D', allowInEditable: false, }, 'focus-toolbar-search': { id: 'focus-toolbar-search', shortcut: 'Mod+Alt+F', allowInEditable: false, }, 'fit-to-view': { id: 'fit-to-view', shortcut: 'Mod+Shift+F', allowInEditable: false, }, 'toggle-sidebar': { id: 'toggle-sidebar', shortcut: 'Mod+B', allowInEditable: false, }, } /** * Input for creating a concrete command instance from the registry. */ export interface CreateCommandInput { /** Identifier of the command to materialize. */ id: CommandId /** * Handler invoked when the shortcut is matched. This is the only dynamic * part supplied by call sites. */ handler: (event: KeyboardEvent) => void /** * Optional overrides for definition defaults. Use sparingly; most behavior * should be configured in {@link COMMAND_DEFINITIONS}. */ overrides?: Pick } /** * Creates a concrete {@link GlobalCommand} from a registry definition. * * This ensures: * - Only commands declared in {@link COMMAND_DEFINITIONS} can be registered. * - Shortcut strings and ids are centralized and consistent. * * @throws Error when the `id` is not present in the registry. */ export function createCommand(input: CreateCommandInput): GlobalCommand { const definition = COMMAND_DEFINITIONS[input.id] if (!definition) { throw new Error(`Unknown global command id: ${input.id as string}`) } return { id: definition.id, shortcut: definition.shortcut, allowInEditable: input.overrides?.allowInEditable ?? definition.allowInEditable, handler: input.handler, } } /** * Convenience helper to create multiple commands from the registry in one call. * * @param inputs - List of command inputs to materialize. * @returns Array of {@link GlobalCommand} instances ready for registration. */ export function createCommands(inputs: CreateCommandInput[]): GlobalCommand[] { return inputs.map((input) => createCommand(input)) }