/************************************************************************* * Copyright 2023 Adobe * All Rights Reserved. * * NOTICE: Adobe permits you to use, modify, and distribute this file in * accordance with the terms of the Adobe license agreement accompanying * it. If you have received this file from a source other than Adobe, * then your use, modification, or distribution of it requires the prior * written permission of Adobe. **************************************************************************/ /** * Internal APIs, meant to be used by Unified Shell only. * @packageDocumentation * @module ai */ import type { AppParent } from './appapi'; import EventEmitter from './src/EventEmitter'; import type { JSONValue } from './JSONValue'; import type { JSX } from 'react'; export interface Prompt { icon: JSX.Element; label: string; name: string; } export interface Source { citationNumber?: number; commentedQuery?: string; commented_query?: string; endIndex: number; startIndex: number; title?: string; url: string; } export interface MultimodalElementItem { alttext: string; caption?: string; height: number; id: string; imgUrl?: string; thumbnailHeight: number; thumbnailUrl: string; thumbnailWidth: number; title: string; transcript?: string; type: string; url: string; videoUrl?: string; width: number; } export interface MultimodalElements { elements: MultimodalElementItem[]; } /** * A reference to a file that has already been uploaded by the host solution. * No file content is transferred through this API - the AI Assistant resolves * the file using the artifactId. */ export interface AIAttachment { /** * The id of the previously-uploaded artifact. */ artifactId: string; /** * The MIME type of the file (e.g. "image/png", "application/pdf"). */ contentType: string; /** * The display name of the file. */ name: string; } export interface ToastOptions { actionLabel?: string; placement?: 'top start' | 'top' | 'top end' | 'bottom start' | 'bottom' | 'bottom end'; variant?: 'positive' | 'info' | 'error' | 'neutral' | 'negative' | 'success'; shouldCloseOnAction?: boolean; timeout?: number; onClose?: () => void; onAction?: () => void; } export interface SuccessResponse { answer: string; chatId: string; confidence?: { confidenceLevel?: 'low' | 'high'; confidenceIndicators?: { lowOosConfidenceDetected?: boolean; insufficientContentDetected?: boolean; }; }; customData?: Record; gsdisplayconfig?: any; interactionId: string; internalErrorCode?: string; prompts: Prompt[]; date: Date | null; sources: Source[]; promptSuggestions: string[]; clarifications?: { label: string; value: string; }[]; promptSuggestionsWithPlaceholders?: QuerySuggestion[]; reportingDataDefinition?: any; usageInsights: string; visualizations: any[]; capability: string; request: { message: string; }; uiComponent?: any; multimodalElements?: MultimodalElements; } export interface TemplatePlaceholder { length: number; rawPlaceholder?: string; raw_placeholder?: string; placeholderText?: string; placeholder_text?: string; placeholderType?: string; placeholder_type?: string; displayAttribute?: string; display_attribute?: string; startPosition?: number; start_position?: number; } export interface QuerySuggestion { suggestion: string; tags: Record; placeholders: TemplatePlaceholder[]; itemId?: string; item_id?: string; id?: string; } export interface UserActionResponse { action: string; data?: any; } export interface SystemResponse { message: string; } export interface ErrorResponse { chatId?: string; error: boolean; date: Date | null; interactionId?: string; internalErrorCode?: string; message?: string; requestId?: string; status: number; uiComponent: any; } export type Response = SuccessResponse | UserActionResponse | SystemResponse | ErrorResponse; export declare enum AIMessageType { BUTTON_ACTIVE = "BUTTON_ACTIVE", BUTTON_VISIBLE = "BUTTON_VISIBLE", CLOSE = "CLOSE", CONTEXT = "CONTEXT", ENABLE_ASSISTANT = "ENABLE_ASSISTANT", ERROR = "ERROR", LINK = "LINK", MESSAGE_SUBMISSION = "MESSAGE_SUBMISSION", OPEN = "OPEN", QUERY = "QUERY", RESPONSE = "RESPONSE", SET_FORM_FACTOR = "SET_FORM_FACTOR", SET_USER_PERMISSION = "SET_USER_PERMISSION", TOGGLE_EXPANSION = "TOGGLE_EXPANSION", USER_ACTION = "USER_ACTION" } export declare enum FormFactor { COMPACT = "compact", STANDARD = "standard", EXPANDED = "expanded" } export declare enum Modality { FULLSCREEN = "fullscreen", RAIL = "rail" } export interface AIMessagePayload { /** * References to files that have already been uploaded by the host solution, * to include as context for the message. */ attachments?: AIAttachment[]; /** * The active state of the button. */ buttonActive?: boolean; /** * The visibility of the button. */ buttonVisible?: boolean; /** * The context for the AI chat. */ context?: AIContext; /** * The payload data of the custom event. */ conversationId?: string; /** * The id of the conversation to open */ data?: any; /** * Freeform identifier for where the chat-open call originated (e.g. from * {@link AIApi.openChat}'s {@link OpenChatProps.entryPoint}). */ entryPoint?: string; /** * The form factor of the device. */ formFactor?: FormFactor; /** * Whether the user has permission to use the AI Assistant. */ hasPermission?: boolean; /** * The id of the custom event. */ id?: string; /** * Whether the AI panel is open or closed. */ isOpen?: boolean; /** * The modality of the AI chat. */ modality?: Modality; /** * The permissions required to enable the AI UI. */ permissions?: string[]; /** * The query that was sent to the AI. */ query?: string; /** * The response from the AI. */ response?: Response; /** * Whether the query should automatically be submitted. */ shouldSubmit?: boolean; /** * When true, the client requested a new conversation (e.g. from {@link AIApi.openChat}). */ newConversation?: boolean; /** * The type of message. */ type: AIMessageType; } export interface AIContext { /** * Catch all for now. */ [key: string]: any; } /** * A resource the user is currently focused on within the host application, * used to give the AI Assistant structured context about the active workspace. */ export interface FocusedResource { /** * A short description of the resource. */ description?: string; /** * The unique id of the resource (e.g. "p-1"). */ id: string; /** * The human-readable name of the resource (e.g. "New Customer Journey", "Data View"). */ name?: string; /** * The type of the resource (e.g. "data_view", "journey", "schema"). */ type?: string; /** * The URI of the resource. */ uri?: string; } /** * Structured context describing what the user is currently doing in the host * application. Set via {@link AIApi.setClientContext}. */ export interface ClientContext { /** * A short description of the current application. */ appDescription?: string; /** * The resources the user is currently focused on (max 10). This is intended to be * high level focused resources only, i.e. a journey if the user is on a journey detail * page, but do not list all journeys if the user is on a journey browse page. */ focusedResources?: FocusedResource[]; /** * A fallback name for the current application, used only when Unified Shell * cannot resolve a name from documentation sources or the shell's own * solution registry. */ name?: string; /** * A short description of the current page. */ pageDescription?: string; /** * When true, signals that the agent should prioritize WebMCP (client-side) * tools over server-side MCP tools while operating on this page. Set this * explicitly and only on the pages where it applies — Unified Shell does * not apply it globally or infer it from any other context field. */ preferWebMcpTools?: boolean; } /** * Identity information about the application the user is currently in, * resolved by Unified Shell. */ export interface ClientContextApplication { /** * A short description of what the user is currently doing, as set via * {@link AIApi.setClientContext}. */ description?: string; /** * The Agent Orchestrator application id for the current application. Always * resolves to a value, falling back to the app's own appId when no explicit * AI application id is configured. */ id: string; /** * The human-readable name of the current application. */ name?: string; /** * The parent product grouping for the current application (e.g. "AEP"). */ parent?: AppParent; } export interface ClientContextView { /** * Page description of the current view. */ description?: string; /** Page title */ title?: string; /** Page URL */ url?: string; } /** * Structured client context returned by {@link AIApi.getClientContext}, * combining Unified Shell's own knowledge of the current application with * the context set via {@link AIApi.setClientContext}. */ export interface ClientContextSnapshot { /** * Identity information about the current application. */ application: ClientContextApplication; /** * The resources the user is currently focused on. */ focusedResources?: FocusedResource[]; /** * When true, the agent should prioritize WebMCP (client-side) tools over * server-side MCP tools while operating on this page, as set via * {@link AIApi.setClientContext}. */ preferWebMcpTools?: boolean; /** * The current page view context of the application. This is more * specific than application. */ view: ClientContextView; } /** * This is the application id sent to the Agent Orchestrator. */ export declare enum AIApplicationId { AEM = "aem", AEP = "aep", ARION = "arion", BEYOND = "cja", CATALYZE = "catalyze", CJA = "cja", CJM = "cjm", DATACOLLECTION = "datacollection", EXPERIMENTATIONACCELERATOR = "experimentation_agent", GENSTUDIO = "genstudio", IVO = "ivo-ui", MARKETOENGAGE = "marketoengage", SAPPHIRE = "sapphire", TARGET = "target", WORKFRONT = "workfront" } export interface AppContext { /** * Whether the AI/Coworker rail is enabled for the current app and context, i.e. * whether `ai.openChat` will actually surface a panel. Mirrors the shell's own * rail-render gate (`isAIRailEnabled && !disabledTab`). May be `undefined` when * served by an older shell that does not yet report it. */ isAIRailEnabled?: boolean; /** * Whether Coworker is enabled for the current org/context (the `shell-coworker-enabled` * or `coworker-incubator-enabled` flag). Lets a host app choose the correct fallback * destination when no rail is available. May be `undefined` on an older shell. */ isCoworkerEnabled?: boolean; mainAppAgentApplicationId?: AIApplicationId; mainAppId: string; mainAppRoot: string; } /** * Options to open the AI chat side rail. * @param conversationId - The id of the conversation to open * @param query - The query to send to the AI * @param shouldSubmit - Whether to submit the query automatically */ export interface OpenChatProps { /** * Custom app context that host app can pass in when the chat is open. * This is an alternative way to pass in app context in comparison to Interframe's APP_CONTEXT request. */ appContext?: JSONValue; /** * References to files that the host solution has already uploaded, to pre-fill * as context for the first message. */ attachments?: AIAttachment[]; /** * The id of the conversation to open. If not provided, it will be added to the existing * conversation, if there is one. If there is no existing conversation, a new one will be created. * Takes precedence over newConversation. If both are passed in, the conversationId will be used. */ conversationId?: string; /** * Freeform identifier for where this chat-open call originated, e.g. a host app * name or surface such as `"home-widget"`. Lets success/latency metrics be sliced * by entry point, in addition to destination app. */ entryPoint?: string; /** * Whether the AI chat should open in fullscreen or rail modality. * @default Modality.RAIL */ modality?: Modality; /** * When set, generates a new thread for the message. Does not work in conjunction with conversationId. * If both are passed in, the conversationId will be used. */ newConversation?: boolean; /** * The query to submit or populate the prompt area with. */ query?: string; /** * Whether to submit the query automatically. * @default true */ shouldSubmit?: boolean; } interface AIMessageEvent { BUTTON_ACTIVE: AIMessagePayload; BUTTON_VISIBLE: AIMessagePayload; CLOSE: AIMessagePayload; CONTEXT: AIMessagePayload; ENABLE_ASSISTANT: AIMessagePayload; ERROR: AIMessagePayload; LINK: AIMessagePayload; MESSAGE_SUBMISSION: AIMessagePayload; OPEN: AIMessagePayload; QUERY: AIMessagePayload; RESPONSE: AIMessagePayload; SET_USER_PERMISSION: AIMessagePayload; TOGGLE_EXPANSION: AIMessagePayload & { isExpanded: boolean; }; USER_ACTION: AIMessagePayload; } export interface AIApi extends EventEmitter { /** * Requests the appid and approot from the application. This is used to * asynchronously request the appid and approot on-demand. * * ***Example:*** * * ```typescript * ai.appContext(); * ``` */ appContext: () => Promise; /** * Sets the context for the AI chat. This can be called unlimited times to * ensure the context has the correct information. This value will be fetched * on every request for context by the AI chat UI when a user submits a query. * Please make sure to keep this value up-to-date when any context values * change within the application. * ***Example:*** * * ```typescript * ai.context = {...}; * ``` */ context?: AIContext; /** * Closes the chat side rail. * * ***Example:*** * * ```typescript * ai.closeChat(); * ``` */ closeChat: () => void; /** * Asynchronously requests the structured client context from Unified Shell. * `application` is resolved by Unified Shell itself (documentation sources, * the shell's solution registry, and, as a last resort, the `name`/`description` * last passed to {@link AIApi.setClientContext}). `focusedResources` is the * value last passed to {@link AIApi.setClientContext}, shared across every * solution/iframe on the page. * * ***Example:*** * * ```typescript * const context = await ai.getClientContext(); * ``` */ getClientContext: () => Promise; /** * Requests the documentation sources object from the configuration object. * * ***Example:*** * * ```typescript * ai.getDocumentationSources(); * ``` */ getDocumentationSources: () => Promise>>; /** * Requests the context from the application. This is used to asynchronously * request the context on-demand. * * ***Example:*** * * ```typescript * ai.onContextRequest(async () => ({...})); * ``` */ onContextRequest: (callback: () => Promise) => void; /** * Opens the chat side rail with optional query, submit behavior, or conversation to load. * backward-compatible signatures: * - ai.openChat(query?: string, shouldSubmit?: boolean): void; * - ai.openChat(props: OpenChatProps): void; * * ***Example:*** * * ```typescript * ai.openChat('How do I create a new project?'); * ai.openChat('How do I create a new project?', false); * ai.openChat({ query: 'How do I create a new project?' }); * ai.openChat({ query: 'How do I create a new project?', shouldSubmit: false }); * ai.openChat({ conversationId: 'conv-123' }); * ai.openChat({ conversationId: 'conv-123', query: 'How do I create a new project?' }); * ai.openChat({ query: 'Hello', newConversation: true }); * ai.openChat({ appContext: { data: { ... } } }); * ai.openChat({ attachments: [{ artifactId: 'art-123', contentType: 'application/pdf', name: 'report.pdf' }], query: 'Summarize this file' }); * ``` */ openChat(query?: string, shouldSubmit?: boolean): void; openChat(props: OpenChatProps): void; /** * Send a message to the AI chat. * * ***Example:*** * * ```typescript * ai.sendMessage({type: AIMessageType.ACTION_COMPLETE}); * ``` */ sendMessage: (payload: AIMessagePayload) => void; /** * Sets the structured client context for the AI chat. The value is stored at * the shell level and shared across every solution/iframe on the page, so a * subsequent {@link AIApi.getClientContext} (from any frame) returns it. This * can be called unlimited times to keep the context up-to-date; keep it * current whenever the focused resources change. * * ***Example:*** * * ```typescript * ai.setClientContext({ * focusedResources: [{type: 'project', id: 'p-1', name: 'Acquisition'}] * }); * ``` */ setClientContext: (context: ClientContext) => void; /** * Adds a button to the not provisioned dialog that calls a callback function when pressed. * Designed to be used by Workfront to launch their review agreement dialog. * @param callback Function to be called on button click */ setProvisioningButton: (callback: () => void) => void; /** * Sets the user has permission flag for the given application, org, and sandbox. * @param hasPermission Whether the user has permission to use the AI Assistant feature. */ setUserPermission: (hasPermission: boolean) => void; /** * Send a message to Unified Shell to show the Assistant. This includes * permissions that Unified Shell will validate to determine for access. * * ***Example:*** * * ```typescript * ai.showAssistant(['permission1', 'permission2']); * ``` */ showAssistant: (permissions: string[]) => void; /** * Sends a message to Unified Shell to show a toast message. * * ***Example:*** * * ```typescript * ai.showToast('Hello, world!', {position: 'bottom center', variant: 'success'}); * ``` */ showToast: (message: string, options: ToastOptions) => void; /** * Sends a message to Unified Shell to change the active status of the Assistant button. * * ***Example:*** * * ```typescript * ai.toggleButtonActive(false); * ``` */ toggleButtonActive: (active: boolean) => void; /** * Sends a message to Unified Shell to show the Assistant button. * * ***Example:*** * * ```typescript * ai.toggleButtonVisible(true); * ``` */ toggleButtonVisible: (visible: boolean) => void; /** * Sends a message to Unified Shell to toggle the AI panel expansion. * * ***Example to expand the panel:*** * * ```typescript * ai.toggleExpansion(true); * ``` */ toggleExpansion: (isExpanded: boolean) => void; /** * Sends a message to Unified Shell to toggle the AI panel open or closed. * * ***Example to close the panel:*** * * ```typescript * ai.togglePanel(false); * ``` * * ***Example to open the panel:*** * * ```typescript * ai.togglePanel(true); * ``` */ togglePanel: (isOpen: boolean) => void; } declare const ai: AIApi; export default ai;