Files
twenty/packages/twenty-sdk/src/sdk/front-component/globals/frontComponentHostCommunicationApi.ts
T
Weiko 8580cd6f27 feat(ai): open Ask AI side panel with a preprompt in two modes (#22582)
Add the ability to open the Ask AI side panel pre-filled with a prompt
from any frontend component, with a mode to control whether the message
is sent automatically or left for the user to review.

- agentChatPrepromptState: holds the pending preprompt and its mode
(PREFILL = fill only, SEND = fill and auto-submit)
- useOpenAskAiPageWithPreprompt: seeds the new-thread draft, opens a
fresh Ask AI thread and stores the preprompt intent
- AgentChatPrepromptEffect: applies the intent once the chat editor and
send listener are mounted, either restoring the editor content or
dispatching the send event and clearing the editor

<!-- This is an auto-generated description by cubic. -->
<a
href="https://cubic.dev/pr/twentyhq/twenty/pull/22582?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>
<!-- End of auto-generated description by cubic. -->
2026-07-06 15:38:28 +00:00

127 lines
3.6 KiB
TypeScript

import {
type AppPath,
type SidePanelPages,
type EnqueueSnackbarParams,
type NavigateOptions,
} from 'twenty-shared/types';
import { type getAppPath } from 'twenty-shared/utils';
export type NavigateFunction = <T extends AppPath>(
to: T,
params?: Parameters<typeof getAppPath<T>>[1],
queryParams?: Record<string, any>,
options?: NavigateOptions,
) => Promise<void>;
export type OpenSidePanelPageParams =
| {
page: SidePanelPages.ViewRecord;
recordId: string;
objectNameSingular: string;
resetNavigationStack?: boolean;
}
| {
page: SidePanelPages.EditRichText;
recordId: string;
objectNameSingular: string;
fieldName?: string;
}
| {
page: SidePanelPages.ComposeEmail;
connectedAccountId: string;
threadId?: string;
defaultTo?: string;
defaultSubject?: string;
defaultInReplyTo?: string;
pageTitle?: string;
pageIcon?: string;
}
| {
page: SidePanelPages.ViewFrontComponent;
frontComponentId: string;
recordId?: string;
objectNameSingular?: string;
pageTitle: string;
pageIcon?: string;
resetNavigationStack?: boolean;
}
| {
page: SidePanelPages.AskAI;
pageTitle: string;
pageIcon?: string;
shouldResetSearchState?: boolean;
preprompt?: {
text: string;
mode?: 'PREFILL' | 'SEND';
};
}
| {
page: Exclude<
SidePanelPages,
| SidePanelPages.ViewRecord
| SidePanelPages.EditRichText
| SidePanelPages.ComposeEmail
| SidePanelPages.ViewFrontComponent
| SidePanelPages.AskAI
>;
pageTitle: string;
pageIcon?: string;
shouldResetSearchState?: boolean;
};
export type OpenSidePanelPageFunction = (
params: OpenSidePanelPageParams,
) => Promise<void>;
export type CommandConfirmationModalResult = 'confirm' | 'cancel';
export type CommandConfirmationModalAccent = 'default' | 'blue' | 'danger';
export type OpenCommandConfirmationModalFunction = (params: {
title: string;
subtitle: string;
confirmButtonText?: string;
confirmButtonAccent?: CommandConfirmationModalAccent;
}) => Promise<CommandConfirmationModalResult>;
export type UnmountFrontComponentFunction = () => Promise<void>;
export type EnqueueSnackbarFunction = (
params: EnqueueSnackbarParams,
) => Promise<void>;
export type CloseSidePanelFunction = () => Promise<void>;
export type UpdateProgressFunction = (progress: number) => Promise<void>;
export type RequestAccessTokenRefreshFunction = () => Promise<string>;
export type CopyToClipboardFunction = (text: string) => Promise<void>;
export type OpenCommandConfirmationModalHostFunction = (
params: Parameters<OpenCommandConfirmationModalFunction>[0],
) => Promise<void>;
export type FrontComponentHostCommunicationApiStore = {
navigate?: NavigateFunction;
requestAccessTokenRefresh?: RequestAccessTokenRefreshFunction;
openSidePanelPage?: OpenSidePanelPageFunction;
openCommandConfirmationModal?: OpenCommandConfirmationModalFunction;
unmountFrontComponent?: UnmountFrontComponentFunction;
enqueueSnackbar?: EnqueueSnackbarFunction;
closeSidePanel?: CloseSidePanelFunction;
updateProgress?: UpdateProgressFunction;
copyToClipboard?: CopyToClipboardFunction;
};
import { FRONT_COMPONENT_HOST_COMMUNICATION_API_KEY } from '../constants/front-component-host-communication-api-key';
declare global {
var frontComponentHostCommunicationApi: FrontComponentHostCommunicationApiStore;
}
globalThis[FRONT_COMPONENT_HOST_COMMUNICATION_API_KEY] ??= {};
export const frontComponentHostCommunicationApi =
globalThis.frontComponentHostCommunicationApi;