557 lines
21 KiB
JavaScript
557 lines
21 KiB
JavaScript
import {
|
||
buildApplicationPreviewFooterMessage,
|
||
buildApplicationPreviewRows,
|
||
buildLocalApplicationPreviewMessage,
|
||
normalizeApplicationPreview
|
||
} from '../../utils/expenseApplicationPreview.js'
|
||
import {
|
||
buildAiApplicationPrecheck,
|
||
buildAiApplicationSubmitConflictMessage,
|
||
isAiApplicationPrecheckBlocking
|
||
} from '../../utils/aiApplicationPrecheckModel.js'
|
||
import { fetchExpenseClaims } from '../../services/reimbursements.js'
|
||
import {
|
||
AI_APPLICATION_ACTION_SAVE_DRAFT,
|
||
AI_APPLICATION_ACTION_SUBMIT,
|
||
runAiApplicationPreviewAction
|
||
} from '../../services/aiApplicationPreviewActions.js'
|
||
import {
|
||
buildFailedInlineApplicationSubmitThinkingEvents,
|
||
buildInitialInlineApplicationSubmitThinkingEvents,
|
||
buildInlineApplicationDetailAction,
|
||
buildInlineApplicationPreview,
|
||
buildInlineApplicationPreviewActionResultText,
|
||
buildInlineApplicationSubmitPrecheckPayload,
|
||
buildInlineApplicationSubmitThinkingEvents,
|
||
completeInlineThinkingEvents,
|
||
extractInlineApplicationDraftPayload
|
||
} from './workbenchAiApplicationPreviewModel.js'
|
||
import { AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION } from './workbenchAiMessageModel.js'
|
||
import {
|
||
isOrphanInlineApplicationPreviewMessage,
|
||
resolveInlineApplicationPreviewTextAction,
|
||
resolveLatestApplicationPreviewMessage,
|
||
resolveLatestOrphanApplicationPreviewMessage
|
||
} from './workbenchAiApplicationGateModel.js'
|
||
|
||
function isApplicationPreviewEstimatePendingPreview(applicationPreview = {}) {
|
||
const fields = normalizeApplicationPreview(applicationPreview).fields || {}
|
||
return [
|
||
fields.transportPolicy,
|
||
fields.policyEstimate,
|
||
fields.transportEstimatedAmount,
|
||
fields.amount
|
||
].some((value) => /正在|查询中/.test(String(value || '')))
|
||
}
|
||
|
||
function shouldRefreshInlineApplicationPreviewEstimate(fieldKey = '') {
|
||
return ['transportMode', 'time', 'time_return', 'location', 'days'].includes(String(fieldKey || '').trim())
|
||
}
|
||
|
||
export function useWorkbenchAiApplicationPreviewFlow({
|
||
activateInlineConversation,
|
||
applicationPreviewEditor,
|
||
applicationSubmitConfirmContext,
|
||
applicationSubmitConfirmOpen,
|
||
assistantDraft,
|
||
cancelApplicationPreviewEditor,
|
||
clearAiModeFiles,
|
||
closeWorkbenchDatePicker,
|
||
commitApplicationPreviewEditor: commitBaseApplicationPreviewEditor,
|
||
conversationId,
|
||
conversationMessages,
|
||
conversationStarted,
|
||
createInlineMessage,
|
||
currentUser,
|
||
handleApplicationPreviewEditorKeydown,
|
||
inlineConversationAutoScrollPinned,
|
||
isApplicationPreviewEditing,
|
||
openApplicationPreviewEditor,
|
||
persistCurrentConversation,
|
||
pushInlineApplicationActionUserMessage,
|
||
pushInlineUserMessage,
|
||
refreshApplicationPreviewEstimate,
|
||
removeWorkbenchDateTag,
|
||
replaceInlineMessage,
|
||
resolveApplicationPreviewEditorDateMax,
|
||
resolveApplicationPreviewEditorDateMin,
|
||
resolveApplicationPreviewEditorControl,
|
||
resolveApplicationPreviewEditorOptions,
|
||
resolveInlineThinkingEvents,
|
||
resolveLatestInlineUserPrompt,
|
||
scrollInlineConversationToBottom,
|
||
sending,
|
||
toast
|
||
}) {
|
||
function isApplicationPreviewEstimatePending(message = {}) {
|
||
return Boolean(message?.applicationPreview && isApplicationPreviewEstimatePendingPreview(message.applicationPreview))
|
||
}
|
||
|
||
function canShowInlineSuggestedActions(message = {}) {
|
||
return Boolean(message?.suggestedActions?.length) && !isApplicationPreviewEstimatePending(message)
|
||
}
|
||
|
||
function isInlineSuggestedActionDisabled(action = {}, message = {}) {
|
||
const actionType = String(action?.action_type || '').trim()
|
||
return (
|
||
Boolean(action?.disabled) ||
|
||
(actionType === AI_ATTACHMENT_ASSOCIATION_CONFIRM_ACTION && sending.value) ||
|
||
(
|
||
[AI_APPLICATION_ACTION_SAVE_DRAFT, AI_APPLICATION_ACTION_SUBMIT].includes(actionType) &&
|
||
isApplicationPreviewEstimatePending(message)
|
||
)
|
||
)
|
||
}
|
||
|
||
function resolveInlineApplicationPreviewRows(message) {
|
||
return buildApplicationPreviewRows(message?.applicationPreview || {})
|
||
}
|
||
|
||
function resolveInlineApplicationPreviewMissingFields(message) {
|
||
return normalizeApplicationPreview(message?.applicationPreview || {}).missingFields || []
|
||
}
|
||
|
||
function resolveInlineApplicationPreviewEditorControl(fieldKey) {
|
||
return resolveApplicationPreviewEditorControl(fieldKey)
|
||
}
|
||
|
||
function resolveInlineApplicationPreviewEditorDateMin(message, fieldKey) {
|
||
return resolveApplicationPreviewEditorDateMin?.(message, fieldKey) || ''
|
||
}
|
||
|
||
function resolveInlineApplicationPreviewEditorDateMax(message, fieldKey) {
|
||
return resolveApplicationPreviewEditorDateMax?.(message, fieldKey) || ''
|
||
}
|
||
|
||
function buildInlineApplicationPreviewSuggestedActions(applicationPreview = {}, draftPayload = null) {
|
||
if (isApplicationPreviewEstimatePendingPreview(applicationPreview)) {
|
||
return []
|
||
}
|
||
const normalized = normalizeApplicationPreview(applicationPreview)
|
||
const actions = [{
|
||
label: '保存草稿',
|
||
description: '先保存当前申请表,后续可以继续补充或提交。',
|
||
icon: 'mdi mdi-content-save-outline',
|
||
action_type: AI_APPLICATION_ACTION_SAVE_DRAFT,
|
||
payload: { draftPayload }
|
||
}]
|
||
if (normalized.readyToSubmit) {
|
||
actions.push({
|
||
label: '直接提交',
|
||
description: '提交前先核查相同日期申请单,确认通过后进入审批流程。',
|
||
icon: 'mdi mdi-send-check-outline',
|
||
action_type: AI_APPLICATION_ACTION_SUBMIT,
|
||
payload: { draftPayload }
|
||
})
|
||
}
|
||
return actions
|
||
}
|
||
|
||
function syncInlineApplicationPreviewMessageContent(message) {
|
||
if (!message?.applicationPreview) {
|
||
return
|
||
}
|
||
const nextContent = buildLocalApplicationPreviewMessage(message.applicationPreview)
|
||
message.content = nextContent
|
||
message.text = nextContent
|
||
message.suggestedActions = buildInlineApplicationPreviewSuggestedActions(message.applicationPreview, message.draftPayload)
|
||
}
|
||
|
||
async function commitInlineApplicationPreviewEditor(message) {
|
||
const shouldLockForEstimate = shouldRefreshInlineApplicationPreviewEstimate(applicationPreviewEditor.value.fieldKey)
|
||
if (shouldLockForEstimate) {
|
||
message.suggestedActions = []
|
||
persistCurrentConversation()
|
||
}
|
||
const committed = await commitBaseApplicationPreviewEditor(message)
|
||
syncInlineApplicationPreviewMessageContent(message)
|
||
persistCurrentConversation()
|
||
return committed
|
||
}
|
||
|
||
function handleInlineApplicationPreviewEditorKeydown(event, message) {
|
||
if (event.key === 'Enter') {
|
||
event.preventDefault()
|
||
void commitInlineApplicationPreviewEditor(message)
|
||
return
|
||
}
|
||
if (event.key === 'Escape') {
|
||
event.preventDefault()
|
||
cancelApplicationPreviewEditor()
|
||
return
|
||
}
|
||
handleApplicationPreviewEditorKeydown(event, message)
|
||
}
|
||
|
||
function buildInlineApplicationPreviewFooterText(message) {
|
||
const normalized = normalizeApplicationPreview(message?.applicationPreview || {})
|
||
if (isApplicationPreviewEstimatePending(message)) {
|
||
return '费用测算正在同步,请稍等,完成后才能保存草稿或直接提交。'
|
||
}
|
||
if (normalized.validationIssues?.length || normalized.missingFields?.length) {
|
||
return buildApplicationPreviewFooterMessage(normalized)
|
||
}
|
||
return '申请核对表已补齐,费用测算已同步。你仍可点击表格继续修改;确认无误后,可以点击下方按钮保存草稿或直接提交,也可以直接回复“保存草稿”或“提交”。'
|
||
}
|
||
|
||
function buildInlineApplicationActionFailureText(error, isSubmit) {
|
||
return [
|
||
isSubmit ? '### 申请提交失败' : '### 申请草稿保存失败',
|
||
error?.message || (isSubmit ? '申请提交失败,请稍后重试。' : '申请草稿保存失败,请稍后重试。'),
|
||
'我已保留当前申请核对表,您可以修改后重试,也可以稍后再次保存。'
|
||
].join('\n\n')
|
||
}
|
||
|
||
function resolveLatestInlineApplicationPreviewMessage() {
|
||
return resolveLatestApplicationPreviewMessage(conversationMessages.value)
|
||
}
|
||
|
||
function resolveLatestOrphanInlineApplicationPreviewMessage() {
|
||
return resolveLatestOrphanApplicationPreviewMessage(conversationMessages.value)
|
||
}
|
||
|
||
function requestInlineApplicationSubmitConfirmation(targetMessage, options = {}) {
|
||
applicationSubmitConfirmContext.value = {
|
||
messageId: String(targetMessage?.id || '').trim(),
|
||
draftPayload: targetMessage?.draftPayload || options.draftPayload || null,
|
||
userText: String(options.userText || '直接提交').trim() || '直接提交'
|
||
}
|
||
applicationSubmitConfirmOpen.value = true
|
||
persistCurrentConversation()
|
||
}
|
||
|
||
function cancelInlineApplicationSubmitConfirm() {
|
||
applicationSubmitConfirmOpen.value = false
|
||
applicationSubmitConfirmContext.value = null
|
||
}
|
||
|
||
function confirmInlineApplicationSubmit() {
|
||
const context = applicationSubmitConfirmContext.value || {}
|
||
applicationSubmitConfirmOpen.value = false
|
||
applicationSubmitConfirmContext.value = null
|
||
const sourceMessage = conversationMessages.value.find((message) => message.id === context.messageId)
|
||
if (!sourceMessage?.applicationPreview) {
|
||
toast('当前申请表已变化,请重新点击直接提交。')
|
||
return
|
||
}
|
||
void executeInlineApplicationPreviewAction(AI_APPLICATION_ACTION_SUBMIT, sourceMessage, {
|
||
confirmed: true,
|
||
skipUserMessage: false,
|
||
draftPayload: context.draftPayload || null,
|
||
userText: context.userText || '直接提交'
|
||
})
|
||
}
|
||
|
||
async function runInlineApplicationSubmitPrecheck(targetMessage, pendingMessage, normalizedPreview, options = {}) {
|
||
try {
|
||
const claimsPayload = await fetchExpenseClaims({ page: 1, pageSize: 100 })
|
||
const precheck = buildAiApplicationPrecheck(normalizedPreview, {
|
||
claimsPayload: buildInlineApplicationSubmitPrecheckPayload(
|
||
claimsPayload,
|
||
targetMessage.draftPayload || options.draftPayload || null
|
||
),
|
||
currentUser: currentUser.value || {},
|
||
expenseType: 'travel'
|
||
})
|
||
const thinkingEvents = buildInlineApplicationSubmitThinkingEvents(precheck)
|
||
const blocked = isAiApplicationPrecheckBlocking(precheck)
|
||
|
||
if (blocked) {
|
||
replaceInlineMessage(
|
||
pendingMessage.id,
|
||
createInlineMessage('assistant', buildAiApplicationSubmitConflictMessage(normalizedPreview, precheck), {
|
||
id: pendingMessage.id,
|
||
stewardPlan: {
|
||
streamStatus: 'completed',
|
||
thinkingEvents
|
||
}
|
||
})
|
||
)
|
||
persistCurrentConversation()
|
||
scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
|
||
return false
|
||
}
|
||
|
||
const message = conversationMessages.value.find((item) => item.id === pendingMessage.id) || pendingMessage
|
||
message.content = '提交前核查通过,正在提交申请并进入审批流程...'
|
||
message.paragraphs = ['提交前核查通过,正在提交申请并进入审批流程...']
|
||
message.stewardPlan = {
|
||
...(message.stewardPlan || {}),
|
||
streamStatus: 'streaming',
|
||
thinkingEvents
|
||
}
|
||
scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
|
||
return true
|
||
} catch (error) {
|
||
replaceInlineMessage(
|
||
pendingMessage.id,
|
||
createInlineMessage('assistant', [
|
||
'### 提交前核查失败',
|
||
'系统未能完成相同日期申请单查询,所以本次申请没有提交。',
|
||
'请稍后重试;如果仍然失败,请先到单据中心核对是否已有同日期申请单。'
|
||
].join('\n\n'), {
|
||
id: pendingMessage.id,
|
||
stewardPlan: {
|
||
streamStatus: 'failed',
|
||
thinkingEvents: buildFailedInlineApplicationSubmitThinkingEvents(error)
|
||
}
|
||
})
|
||
)
|
||
toast('提交前核查失败,已暂停提交。')
|
||
persistCurrentConversation()
|
||
return false
|
||
}
|
||
}
|
||
|
||
async function executeInlineApplicationPreviewAction(actionType, sourceMessage = null, options = {}) {
|
||
const targetMessage = sourceMessage?.applicationPreview ? sourceMessage : resolveLatestInlineApplicationPreviewMessage()
|
||
if (!targetMessage?.applicationPreview) {
|
||
toast('当前没有可提交的申请表。')
|
||
return false
|
||
}
|
||
|
||
const normalizedPreview = normalizeApplicationPreview(targetMessage.applicationPreview)
|
||
const isSubmit = actionType === AI_APPLICATION_ACTION_SUBMIT
|
||
const userText = String(options.userText || (isSubmit ? '直接提交' : '保存草稿')).trim()
|
||
|
||
if (isSubmit && !normalizedPreview.readyToSubmit) {
|
||
if (!options.skipUserMessage) {
|
||
pushInlineApplicationActionUserMessage(userText)
|
||
}
|
||
const missingText = normalizedPreview.missingFields?.length
|
||
? `当前还缺少:${normalizedPreview.missingFields.join('、')}。`
|
||
: ''
|
||
const validationText = normalizedPreview.validationIssues?.length
|
||
? normalizedPreview.validationIssues.map((item) => item.message).join(';')
|
||
: ''
|
||
conversationMessages.value.push(createInlineMessage('assistant', [
|
||
'### 暂不能提交申请',
|
||
missingText || validationText || '当前申请表还未通过提交校验。',
|
||
'请先点击表格中的字段补充或修正,补齐后我会开放“直接提交”入口。'
|
||
].filter(Boolean).join('\n\n')))
|
||
persistCurrentConversation()
|
||
scrollInlineConversationToBottom()
|
||
return true
|
||
}
|
||
|
||
if (isSubmit && !options.confirmed) {
|
||
requestInlineApplicationSubmitConfirmation(targetMessage, { ...options, userText })
|
||
return true
|
||
}
|
||
|
||
if (!options.skipUserMessage) {
|
||
pushInlineApplicationActionUserMessage(userText)
|
||
}
|
||
|
||
sending.value = true
|
||
const pendingMessage = createInlineMessage(
|
||
'assistant',
|
||
isSubmit ? '正在提交前核查相同日期申请单...' : '正在保存申请草稿...',
|
||
{
|
||
pending: true,
|
||
stewardPlan: {
|
||
streamStatus: 'streaming',
|
||
thinkingEvents: isSubmit
|
||
? buildInitialInlineApplicationSubmitThinkingEvents()
|
||
: [
|
||
{
|
||
eventId: 'application-save-draft',
|
||
title: '保存申请草稿',
|
||
content: '正在按当前申请表内容保存草稿。',
|
||
status: 'running'
|
||
}
|
||
]
|
||
}
|
||
}
|
||
)
|
||
conversationMessages.value.push(pendingMessage)
|
||
scrollInlineConversationToBottom()
|
||
|
||
try {
|
||
if (isSubmit) {
|
||
const precheckPassed = await runInlineApplicationSubmitPrecheck(
|
||
targetMessage,
|
||
pendingMessage,
|
||
normalizedPreview,
|
||
options
|
||
)
|
||
if (!precheckPassed) {
|
||
return true
|
||
}
|
||
}
|
||
|
||
const payload = await runAiApplicationPreviewAction({
|
||
actionType,
|
||
applicationPreview: normalizedPreview,
|
||
currentUser: currentUser.value || {},
|
||
conversationId: conversationId.value,
|
||
draftPayload: targetMessage.draftPayload || options.draftPayload || null
|
||
})
|
||
const draftPayload = extractInlineApplicationDraftPayload(payload)
|
||
if (draftPayload) {
|
||
targetMessage.draftPayload = draftPayload
|
||
}
|
||
targetMessage.suggestedActions = []
|
||
replaceInlineMessage(
|
||
pendingMessage.id,
|
||
createInlineMessage('assistant', buildInlineApplicationPreviewActionResultText(actionType, payload), {
|
||
id: pendingMessage.id,
|
||
stewardPlan: {
|
||
streamStatus: 'completed',
|
||
thinkingEvents: completeInlineThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
|
||
},
|
||
suggestedActions: isSubmit ? buildInlineApplicationDetailAction(draftPayload) : []
|
||
})
|
||
)
|
||
persistCurrentConversation()
|
||
scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
|
||
return true
|
||
} catch (error) {
|
||
replaceInlineMessage(
|
||
pendingMessage.id,
|
||
createInlineMessage('assistant', buildInlineApplicationActionFailureText(error, isSubmit), {
|
||
id: pendingMessage.id,
|
||
applicationPreview: targetMessage.applicationPreview,
|
||
draftPayload: targetMessage.draftPayload || options.draftPayload || null,
|
||
suggestedActions: buildInlineApplicationPreviewSuggestedActions(
|
||
targetMessage.applicationPreview,
|
||
targetMessage.draftPayload || options.draftPayload || null
|
||
),
|
||
stewardPlan: {
|
||
streamStatus: 'failed',
|
||
thinkingEvents: resolveInlineThinkingEvents(pendingMessage).map((item) => ({
|
||
...item,
|
||
status: 'failed'
|
||
}))
|
||
}
|
||
})
|
||
)
|
||
toast(error?.message || (isSubmit ? '申请提交失败。' : '申请草稿保存失败。'))
|
||
persistCurrentConversation()
|
||
return true
|
||
} finally {
|
||
sending.value = false
|
||
scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
|
||
}
|
||
}
|
||
|
||
function handleInlineApplicationPreviewTextAction(prompt, applicationPreviewEstimatePending) {
|
||
if (applicationPreviewEstimatePending.value) {
|
||
toast('请等待费用测算完成后再继续操作。')
|
||
return true
|
||
}
|
||
const actionType = resolveInlineApplicationPreviewTextAction(prompt)
|
||
if (!actionType) {
|
||
return false
|
||
}
|
||
if (!resolveLatestInlineApplicationPreviewMessage()) {
|
||
const orphanPreviewMessage = resolveLatestOrphanInlineApplicationPreviewMessage()
|
||
if (!orphanPreviewMessage) {
|
||
return false
|
||
}
|
||
const previewSourceText = resolveLatestInlineUserPrompt()
|
||
pushInlineApplicationActionUserMessage(prompt)
|
||
toast('当前申请核对表状态不完整,我先重新生成可编辑表格。')
|
||
void startAiApplicationPreview('travel', '差旅费', previewSourceText, {
|
||
pushUserMessage: false
|
||
})
|
||
return true
|
||
}
|
||
void executeInlineApplicationPreviewAction(actionType, null, { userText: prompt })
|
||
return true
|
||
}
|
||
|
||
async function startAiApplicationPreview(expenseType, expenseTypeLabel, sourceText = '', options = {}) {
|
||
if (!conversationStarted.value) {
|
||
activateInlineConversation({ title: String(expenseTypeLabel || expenseType || '申请').trim().slice(0, 18) || '申请' })
|
||
}
|
||
const previewSourceText = String(sourceText || resolveLatestInlineUserPrompt()).trim()
|
||
assistantDraft.value = ''
|
||
removeWorkbenchDateTag()
|
||
closeWorkbenchDatePicker()
|
||
clearAiModeFiles()
|
||
if (options.pushUserMessage !== false) {
|
||
pushInlineUserMessage(options.userMessage || '确认发起出差申请')
|
||
}
|
||
|
||
const pendingMessage = createInlineMessage('assistant', '正在生成申请核对表,请稍等...', {
|
||
pending: true,
|
||
stewardPlan: {
|
||
streamStatus: 'streaming',
|
||
thinkingEvents: [
|
||
{
|
||
eventId: 'application-preview-build',
|
||
title: '整理申请表字段',
|
||
content: '正在把已识别的时间、地点、事由和差旅类型整理成可编辑表格。',
|
||
status: 'running'
|
||
},
|
||
{
|
||
eventId: 'application-preview-estimate',
|
||
title: '同步费用测算',
|
||
content: '正在刷新差旅规则和费用测算,完成后会直接展示核对表。',
|
||
status: 'pending'
|
||
}
|
||
]
|
||
}
|
||
})
|
||
conversationMessages.value.push(pendingMessage)
|
||
persistCurrentConversation()
|
||
scrollInlineConversationToBottom()
|
||
|
||
try {
|
||
const preview = await refreshApplicationPreviewEstimate(
|
||
buildInlineApplicationPreview(expenseTypeLabel || expenseType, previewSourceText, currentUser.value || {})
|
||
)
|
||
const content = buildLocalApplicationPreviewMessage(preview)
|
||
replaceInlineMessage(pendingMessage.id, createInlineMessage('assistant', content, {
|
||
id: pendingMessage.id,
|
||
applicationPreview: preview,
|
||
suggestedActions: buildInlineApplicationPreviewSuggestedActions(preview),
|
||
stewardPlan: {
|
||
streamStatus: 'completed',
|
||
thinkingEvents: completeInlineThinkingEvents(resolveInlineThinkingEvents(pendingMessage))
|
||
},
|
||
text: content
|
||
}))
|
||
} catch (error) {
|
||
replaceInlineMessage(pendingMessage.id, createInlineMessage('assistant', error?.message || '申请核对表生成失败,请稍后重试。', {
|
||
id: pendingMessage.id,
|
||
stewardPlan: {
|
||
streamStatus: 'failed',
|
||
thinkingEvents: resolveInlineThinkingEvents(pendingMessage).map((item) => ({
|
||
...item,
|
||
status: 'failed'
|
||
}))
|
||
}
|
||
}))
|
||
toast(error?.message || '申请核对表生成失败。')
|
||
} finally {
|
||
persistCurrentConversation()
|
||
scrollInlineConversationToBottom({ force: inlineConversationAutoScrollPinned.value })
|
||
}
|
||
}
|
||
|
||
return {
|
||
buildInlineApplicationPreviewFooterText,
|
||
buildInlineApplicationPreviewSuggestedActions,
|
||
canShowInlineSuggestedActions,
|
||
cancelInlineApplicationSubmitConfirm,
|
||
commitInlineApplicationPreviewEditor,
|
||
confirmInlineApplicationSubmit,
|
||
executeInlineApplicationPreviewAction,
|
||
handleInlineApplicationPreviewEditorKeydown,
|
||
handleInlineApplicationPreviewTextAction,
|
||
isApplicationPreviewEditing,
|
||
isApplicationPreviewEstimatePending,
|
||
isInlineSuggestedActionDisabled,
|
||
openApplicationPreviewEditor,
|
||
resolveApplicationPreviewEditorOptions,
|
||
resolveInlineApplicationPreviewEditorControl,
|
||
resolveInlineApplicationPreviewEditorDateMax,
|
||
resolveInlineApplicationPreviewEditorDateMin,
|
||
resolveInlineApplicationPreviewMissingFields,
|
||
resolveInlineApplicationPreviewRows,
|
||
startAiApplicationPreview
|
||
}
|
||
}
|