mirror of
https://github.com/langgenius/dify.git
synced 2026-05-10 05:56:31 +08:00
Align human input submission payload types
This commit is contained in:
parent
94b8f8f170
commit
add9260e58
@ -6,6 +6,7 @@ import type {
|
||||
ChatConfig,
|
||||
ChatItem,
|
||||
} from '../../types'
|
||||
import type { HumanInputFieldValue } from './human-input-content/field-renderer'
|
||||
import type { AppData } from '@/models/share'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
@ -40,7 +41,7 @@ type AnswerProps = {
|
||||
noChatInput?: boolean
|
||||
switchSibling?: (siblingMessageId: string) => void
|
||||
hideAvatar?: boolean
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: any) => Promise<void>
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => Promise<void>
|
||||
}
|
||||
const Answer: FC<AnswerProps> = ({
|
||||
item,
|
||||
|
||||
@ -10,6 +10,7 @@ import type {
|
||||
OnRegenerate,
|
||||
OnSend,
|
||||
} from '../types'
|
||||
import type { HumanInputFieldValue } from './answer/human-input-content/field-renderer'
|
||||
import type { InputForm } from './type'
|
||||
import type { Emoji } from '@/app/components/tools/types'
|
||||
import type { AppData } from '@/models/share'
|
||||
@ -69,7 +70,7 @@ export type ChatProps = {
|
||||
sidebarCollapseState?: boolean
|
||||
hideAvatar?: boolean
|
||||
sendOnEnter?: boolean
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: any) => Promise<void>
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => Promise<void>
|
||||
getHumanInputNodeData?: (nodeID: string) => any
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { RefObject } from 'react'
|
||||
import type { HumanInputFieldValue } from '../../chat/answer/human-input-content/field-renderer'
|
||||
import type { ChatConfig, ChatItem, ChatItemInTree } from '../../types'
|
||||
import type { EmbeddedChatbotContextValue } from '../context'
|
||||
import type { ConversationItem } from '@/models/share'
|
||||
@ -59,7 +60,7 @@ vi.mock('../../chat', () => ({
|
||||
onSend: (message: string) => void
|
||||
onRegenerate: (chatItem: ChatItem, editedQuestion?: { message: string, files?: never[] }) => void
|
||||
switchSibling: (siblingMessageId: string) => void
|
||||
onHumanInputFormSubmit: (formToken: string, formData: Record<string, string>) => Promise<void>
|
||||
onHumanInputFormSubmit: (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => Promise<void>
|
||||
onStopResponding: () => void
|
||||
}) => (
|
||||
<div>
|
||||
@ -78,7 +79,7 @@ vi.mock('../../chat', () => ({
|
||||
<button onClick={() => switchSibling('sibling-2')}>switch sibling</button>
|
||||
<button disabled={inputDisabled}>send message</button>
|
||||
<button onClick={onStopResponding}>stop responding</button>
|
||||
<button onClick={() => onHumanInputFormSubmit('form-token', { answer: 'ok' })}>submit human input</button>
|
||||
<button onClick={() => onHumanInputFormSubmit('form-token', { inputs: { answer: 'ok' }, action: 'approve' })}>submit human input</button>
|
||||
</div>
|
||||
),
|
||||
}))
|
||||
@ -351,7 +352,7 @@ describe('EmbeddedChatbot chat-wrapper', () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'submit human input' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(submitHumanInputFormService).toHaveBeenCalledWith('form-token', { answer: 'ok' })
|
||||
expect(submitHumanInputFormService).toHaveBeenCalledWith('form-token', { inputs: { answer: 'ok' }, action: 'approve' })
|
||||
})
|
||||
expect(submitHumanInputForm).not.toHaveBeenCalled()
|
||||
})
|
||||
@ -391,7 +392,7 @@ describe('EmbeddedChatbot chat-wrapper', () => {
|
||||
fireEvent.click(screen.getByRole('button', { name: 'submit human input' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(submitHumanInputForm).toHaveBeenCalledWith('form-token', { answer: 'ok' })
|
||||
expect(submitHumanInputForm).toHaveBeenCalledWith('form-token', { inputs: { answer: 'ok' }, action: 'approve' })
|
||||
})
|
||||
expect(handleSend).toHaveBeenCalledTimes(2)
|
||||
const sendOptions = handleSend.mock.calls[0]?.[2] as { onGetSuggestedQuestions: (responseItemId: string) => void }
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { FileEntity } from '../../file-uploader/types'
|
||||
import type { HumanInputFieldValue } from '../chat/answer/human-input-content/field-renderer'
|
||||
import type {
|
||||
ChatConfig,
|
||||
ChatItem,
|
||||
@ -232,7 +233,7 @@ const ChatWrapper = () => {
|
||||
}
|
||||
}, [inputsForms.length, isMobile, currentConversationId, collapsed, allInputsHidden])
|
||||
|
||||
const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: any) => {
|
||||
const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => {
|
||||
if (isInstalledApp)
|
||||
await submitHumanInputFormService(formToken, formData)
|
||||
else
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { ChatWrapperRefType } from '../index'
|
||||
import type { HumanInputFieldValue } from '@/app/components/base/chat/chat/answer/human-input-content/field-renderer'
|
||||
import { act, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
@ -37,7 +38,7 @@ vi.mock('@/app/components/base/chat/chat', () => ({
|
||||
onSend?: (message: string, files: unknown[]) => void
|
||||
onRegenerate?: (chatItem: { id: string, parentMessageId?: string, content?: string, message_files?: unknown[] }) => void
|
||||
switchSibling?: (siblingMessageId: string) => void
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: Record<string, string>) => Promise<void>
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => Promise<void>
|
||||
onFeatureBarClick?: (state: boolean) => void
|
||||
}) => (
|
||||
<div data-testid="chat-shell">
|
||||
@ -55,7 +56,7 @@ vi.mock('@/app/components/base/chat/chat', () => ({
|
||||
regenerate-chat
|
||||
</button>
|
||||
<button type="button" onClick={() => switchSibling?.('sibling-2')}>switch-sibling</button>
|
||||
<button type="button" onClick={() => onHumanInputFormSubmit?.('token-1', { answer: 'ok' })}>submit-human-input</button>
|
||||
<button type="button" onClick={() => onHumanInputFormSubmit?.('token-1', { inputs: { answer: 'ok' }, action: 'approve' })}>submit-human-input</button>
|
||||
<button type="button" onClick={() => onFeatureBarClick?.(true)}>open-feature-panel</button>
|
||||
{chatNode}
|
||||
</div>
|
||||
@ -296,7 +297,7 @@ describe('ChatWrapper', () => {
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'submit-human-input' }))
|
||||
await waitFor(() => {
|
||||
expect(handleSubmitHumanInputForm).toHaveBeenCalledWith('token-1', { answer: 'ok' })
|
||||
expect(handleSubmitHumanInputForm).toHaveBeenCalledWith('token-1', { inputs: { answer: 'ok' }, action: 'approve' })
|
||||
})
|
||||
|
||||
const subscription = mockUseSubscription.mock.calls[0]?.[0] as (payload: { type: string }) => void
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import type { ChatWrapperRefType } from '../index'
|
||||
import type { HumanInputFieldValue } from '@/app/components/base/chat/chat/answer/human-input-content/field-renderer'
|
||||
import type { ConversationVariable } from '@/app/components/workflow/types'
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
@ -78,7 +79,7 @@ vi.mock('@/app/components/base/chat/chat', () => ({
|
||||
onSend?: (message: string, files: unknown[]) => void
|
||||
onRegenerate?: (chatItem: { id: string, parentMessageId?: string, content?: string, message_files?: unknown[] }) => void
|
||||
switchSibling?: (siblingMessageId: string) => void
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: Record<string, string>) => Promise<void>
|
||||
onHumanInputFormSubmit?: (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => Promise<void>
|
||||
onFeatureBarClick?: (state: boolean) => void
|
||||
}) => {
|
||||
mockChatRender({
|
||||
@ -101,7 +102,7 @@ vi.mock('@/app/components/base/chat/chat', () => ({
|
||||
regenerate-chat
|
||||
</button>
|
||||
<button type="button" onClick={() => switchSibling?.('sibling-2')}>switch-sibling</button>
|
||||
<button type="button" onClick={() => onHumanInputFormSubmit?.('token-1', { answer: 'ok' })}>submit-human-input</button>
|
||||
<button type="button" onClick={() => onHumanInputFormSubmit?.('token-1', { inputs: { answer: 'ok' }, action: 'approve' })}>submit-human-input</button>
|
||||
<button type="button" onClick={() => onFeatureBarClick?.(true)}>open-feature-panel</button>
|
||||
{chatNode}
|
||||
</div>
|
||||
@ -593,7 +594,7 @@ describe('debug-and-preview components', () => {
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'submit-human-input' }))
|
||||
await waitFor(() => {
|
||||
expect(handleSubmitHumanInputForm).toHaveBeenCalledWith('token-1', { answer: 'ok' })
|
||||
expect(handleSubmitHumanInputForm).toHaveBeenCalledWith('token-1', { inputs: { answer: 'ok' }, action: 'approve' })
|
||||
})
|
||||
|
||||
const stopResponding = mockUseChat.mock.calls[0]?.[3] as (taskId: string) => void
|
||||
|
||||
@ -126,10 +126,10 @@ describe('useChat', () => {
|
||||
const { result } = renderHook(() => useChat({}))
|
||||
|
||||
await act(async () => {
|
||||
await result.current.handleSubmitHumanInputForm('token-123', { field: 'value' })
|
||||
await result.current.handleSubmitHumanInputForm('token-123', { inputs: { field: 'value' }, action: 'approve' })
|
||||
})
|
||||
|
||||
expect(mockSubmitHumanInputForm).toHaveBeenCalledWith('token-123', { field: 'value' })
|
||||
expect(mockSubmitHumanInputForm).toHaveBeenCalledWith('token-123', { inputs: { field: 'value' }, action: 'approve' })
|
||||
expect(submitHumanInputForm).toBeDefined()
|
||||
})
|
||||
|
||||
|
||||
@ -228,10 +228,10 @@ describe('useChat – handleSubmitHumanInputForm', () => {
|
||||
const { result } = renderHook(() => useChat({}))
|
||||
|
||||
await act(async () => {
|
||||
await result.current.handleSubmitHumanInputForm('token-123', { field: 'value' })
|
||||
await result.current.handleSubmitHumanInputForm('token-123', { inputs: { field: 'value' }, action: 'approve' })
|
||||
})
|
||||
|
||||
expect(mockSubmitHumanInputForm).toHaveBeenCalledWith('token-123', { field: 'value' })
|
||||
expect(mockSubmitHumanInputForm).toHaveBeenCalledWith('token-123', { inputs: { field: 'value' }, action: 'approve' })
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import type { StartNodeType } from '../../nodes/start/types'
|
||||
import type { ChatWrapperRefType } from './index'
|
||||
import type { HumanInputFieldValue } from '@/app/components/base/chat/chat/answer/human-input-content/field-renderer'
|
||||
import type { ChatItem, OnSend } from '@/app/components/base/chat/types'
|
||||
import type { FileEntity } from '@/app/components/base/file-uploader/types'
|
||||
import { memo, useCallback, useEffect, useImperativeHandle, useMemo } from 'react'
|
||||
@ -129,8 +130,7 @@ const ChatWrapper = (
|
||||
})
|
||||
}, [handleSwitchSibling, appDetail])
|
||||
|
||||
const doHumanInputFormSubmit = useCallback(async (formToken: string, formData: any) => {
|
||||
// Handle human input form submission
|
||||
const doHumanInputFormSubmit = useCallback(async (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => {
|
||||
await handleSubmitHumanInputForm(formToken, formData)
|
||||
}, [handleSubmitHumanInputForm])
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { HumanInputFieldValue } from '@/app/components/base/chat/chat/answer/human-input-content/field-renderer'
|
||||
import type { InputForm } from '@/app/components/base/chat/chat/type'
|
||||
import type {
|
||||
ChatItem,
|
||||
@ -660,7 +661,7 @@ export const useChat = (
|
||||
)
|
||||
}, [threadMessages, chatTree.length, updateCurrentQAOnTree, handleResponding, formSettings?.inputsForm, handleRun, t, workflowStore, fetchInspectVars, invalidAllLastRun, config?.suggested_questions_after_answer?.enabled])
|
||||
|
||||
const handleSubmitHumanInputForm = async (formToken: string, formData: any) => {
|
||||
const handleSubmitHumanInputForm = async (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => {
|
||||
await submitHumanInputForm(formToken, formData)
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { HumanInputFieldValue } from '@/app/components/base/chat/chat/answer/human-input-content/field-renderer'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
@ -97,7 +98,7 @@ const WorkflowPreview = () => {
|
||||
}
|
||||
}, [resize, stopResizing])
|
||||
|
||||
const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: any) => {
|
||||
const handleSubmitHumanInputForm = useCallback(async (formToken: string, formData: { inputs: Record<string, HumanInputFieldValue>, action: string }) => {
|
||||
await submitHumanInputForm(formToken, formData)
|
||||
}, [])
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user