/** * The action registry: everything a person can do from the keyboard, the ⌘K * menu, menus and the desktop menu bar. Each action is defined once here, with * its name, keys and availability, so every surface shows and runs it the same * way. See docs/command-menu-and-shortcuts.md. */ import { type LucideIcon } from "lucide-react"; import type { SessionListRow } from "../../../session-list-model.js"; import type { ActionSurface, Chord, ChordPlatform } from "./chords.js"; import type { ChatOperations } from "./chat-operations.js"; export type ActionGroup = "chat" | "navigate" | "view" | "help"; /** Where the desktop menu bar shows an action. */ export type DesktopMenuPlacement = "file" | "view" | "go" | "chat" | "help"; /** A workspace someone can switch to, in the workspace picker's order. */ export type WorkspaceChoice = { id: string; name: string; /** The workspace's organization, by name. */ organization: string; /** A Personal workspace, private to its owner. */ personal: boolean; }; export type ActionEnv = { workspaceId: string; subjectId: string; surface: ActionSurface; platform: ChordPlatform; /** The chat on screen, if any. */ currentChat: SessionListRow | null; ops: ChatOperations; /** Whether the sidebar's chat list is part of this surface. */ chatList: boolean; /** Whether chats have the right-hand workspace panel on this surface. */ workspacePanel: boolean; /** Every workspace open to the person, in the workspace picker's order. */ workspaces: readonly WorkspaceChoice[]; /** Whether the person may fork the chat on screen. */ canForkCurrentChat: boolean; newChat(): void; /** Opens a chat; one in another workspace switches to that workspace. */ openChat(chatId: string, workspaceId?: string): void; openWorkspace(workspaceId: string): void; /** The ⌘K menu, listing workspaces to switch to. */ openWorkspacePicker(): void; openInbox(): void; toggleSidebar(): void; toggleWorkspacePanel(): void; findInChat(): void; searchMessages(query?: string): void; renameCurrentChat(): void; /** Asks the chat on screen to fork from its latest message. */ forkCurrentChat(): void; openCommandMenu(): void; openShortcutSheet(): void; /** Back to the most recently viewed other chat (a quick Control+Tab). */ switchToRecentChat(): void; /** Chats in sidebar order, and the pinned ones in their order. */ sidebarOrder(): readonly string[]; pinnedOrder(): readonly string[]; }; export type AppAction = { id: string; /** Plain words; chat actions may read the chat (Pin or Unpin). */ title: string | ((env: ActionEnv, chat: SessionListRow | null) => string); group: ActionGroup; icon: LucideIcon; /** A different icon for some chats (Unpin for a pinned chat). */ iconFor?: (chat: SessionListRow | null) => LucideIcon; /** Extra words the ⌘K menu matches, e.g. "share" for Copy link. */ keywords?: readonly string[]; chords?: readonly Chord[]; /** The cheat sheet's own key text when one action has many chords (⌘1 to ⌘9). */ chordSummary?: (platform: ChordPlatform) => string; /** Acts on a chat: the current one, or the one a menu or ⌘K row points at. */ forChat?: boolean; /** Listed in the ⌘K menu (some exist only as keys). Default true. */ inCommandMenu?: boolean; /** * Opens a dialog of its own. From ⌘K it runs once the menu has handed focus * back, so the new dialog returns focus to the same place when it closes. */ opensDialog?: boolean; /** Offered in ⌘K before anything is typed. */ suggested?: boolean; /** The desktop menu bar section, when it appears there. */ desktopMenu?: DesktopMenuPlacement; available(env: ActionEnv, chat: SessionListRow | null): boolean; run(env: ActionEnv, chat: SessionListRow | null, chord?: Chord): void | Promise; }; export declare function actionTitle(action: AppAction, env: ActionEnv, chat: SessionListRow | null): string; export declare function actionIcon(action: AppAction, chat: SessionListRow | null): LucideIcon; /** The previous or next workspace in the picker's order, wrapping around. */ export declare function stepWorkspace(workspaces: readonly Pick[], currentId: string, direction: 1 | -1): string | null; /** * Every action, built on first use. The icons come from chunks the router * shares with other routes; reading them while this module loads can see them * before they exist, depending on which route a visitor opens first. */ export declare function appActions(): readonly AppAction[]; export declare function findAction(id: string): AppAction | undefined;