import React from "react"; import { Bot, Home, Keyboard, KeyRound, ListTodo, PanelsTopLeft, Search, Settings, ShieldCheck, Sparkles, Wrench, Zap, } from "lucide-react"; import { I18nKey } from "#/i18n/declaration"; import { automationListPath, getInterfaceCopy, hasAutomationInterface, } from "#/manifests/automation-interface"; import { getLockedCloudHost } from "#/api/agent-server-config"; import { LOCKED_CLOUD_SETTINGS_NAV_PATH } from "#/constants/settings-nav"; const ICON_SIZE = 18; export const COMMAND_MENU_ROUTE = { conversations: "/conversations", customize: "/customize", automations: automationListPath(), mcp: "/mcp", settings: "/settings", agentSettings: "/settings/agents", llmSettings: "/settings/llm", condenserSettings: "/settings/condenser", verificationSettings: "/settings/verification", appSettings: "/settings/app", secretsSettings: "/settings/secrets", } as const; export type CommandMenuGroupId = "navigation" | "settings" | "actions"; export type CommandMenuItemId = | "new-chat" | "customize" | "automations" | "mcp" | "settings" | "agent-settings" | "llm-settings" | "condenser-settings" | "verification-settings" | "app-settings" | "secrets-settings" | "toggle-sidebar"; export interface CommandMenuItemDefinition { id: CommandMenuItemId; group: CommandMenuGroupId; /** Absent on an item whose copy a manifest owns, which sets the literal. */ titleKey?: I18nKey; descriptionKey?: I18nKey; keywordsKey?: I18nKey; /** Literal copy, for an item a manifest owns. */ title?: string; description?: string; keywords?: string; icon: React.ReactElement; to?: string; perform?: () => void; } /** * An item's copy: its literal when a manifest owns the item, its translation * otherwise. */ export function commandMenuItemCopy( literal: string | undefined, key: I18nKey | undefined, translate: (key: I18nKey) => string, ): string { if (literal !== undefined) return literal; return key === undefined ? "" : translate(key); } export const COMMAND_MENU_GROUP_LABELS: Record = { navigation: I18nKey.COMMAND_MENU$GROUP_NAVIGATION, settings: I18nKey.COMMAND_MENU$GROUP_SETTINGS, actions: I18nKey.COMMAND_MENU$GROUP_ACTIONS, }; export const COMMAND_MENU_GROUP_ORDER: CommandMenuGroupId[] = [ "navigation", "settings", "actions", ]; export const createCommandMenuItems = ({ toggleSidebar, }: { toggleSidebar: () => void; }): CommandMenuItemDefinition[] => { const items: CommandMenuItemDefinition[] = [ { id: "new-chat", group: "navigation", titleKey: I18nKey.COMMAND_MENU$NEW_CHAT_TITLE, descriptionKey: I18nKey.COMMAND_MENU$NEW_CHAT_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$NEW_CHAT_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.conversations, }, { id: "customize", group: "navigation", titleKey: I18nKey.COMMAND_MENU$CUSTOMIZE_TITLE, descriptionKey: I18nKey.COMMAND_MENU$CUSTOMIZE_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$CUSTOMIZE_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.customize, }, // The automation interface owns this entry's copy, so an absent manifest // leaves the command menu without it rather than with host copy. ...(hasAutomationInterface() ? [ { id: "automations" as const, group: "navigation" as const, title: getInterfaceCopy().commandMenuTitle, description: getInterfaceCopy().commandMenuDescription, keywords: getInterfaceCopy().commandMenuKeywords, icon: , to: COMMAND_MENU_ROUTE.automations, }, ] : []), { id: "mcp", group: "navigation", titleKey: I18nKey.COMMAND_MENU$MCP_TITLE, descriptionKey: I18nKey.COMMAND_MENU$MCP_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$MCP_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.mcp, }, { id: "settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.settings, }, { id: "agent-settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$AGENT_SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$AGENT_SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$AGENT_SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.agentSettings, }, { id: "llm-settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$LLM_SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$LLM_SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$LLM_SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.llmSettings, }, { id: "condenser-settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$CONDENSER_SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$CONDENSER_SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$CONDENSER_SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.condenserSettings, }, { id: "verification-settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$VERIFICATION_SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$VERIFICATION_SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$VERIFICATION_SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.verificationSettings, }, { id: "app-settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$APP_SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$APP_SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$APP_SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.appSettings, }, { id: "secrets-settings", group: "settings", titleKey: I18nKey.COMMAND_MENU$SECRETS_SETTINGS_TITLE, descriptionKey: I18nKey.COMMAND_MENU$SECRETS_SETTINGS_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$SECRETS_SETTINGS_KEYWORDS, icon: , to: COMMAND_MENU_ROUTE.secretsSettings, }, { id: "toggle-sidebar", group: "actions", titleKey: I18nKey.COMMAND_MENU$TOGGLE_SIDEBAR_TITLE, descriptionKey: I18nKey.COMMAND_MENU$TOGGLE_SIDEBAR_DESCRIPTION, keywordsKey: I18nKey.COMMAND_MENU$TOGGLE_SIDEBAR_KEYWORDS, icon: , perform: toggleSidebar, }, ]; // Locked-to-Cloud (SaaS / self-hosted OHE) lists only the Application page; // the OHE settings shell owns the rest (OHE-3168). const isLockedToCloud = getLockedCloudHost() !== null; return items.filter( (item) => !isLockedToCloud || item.group !== "settings" || item.to === COMMAND_MENU_ROUTE.settings || item.to === LOCKED_CLOUD_SETTINGS_NAV_PATH, ); };