Merge branch 'feat/plugins' into dev/plugin-deploy

fix/switch-strategy-clean-param
zxhlyh 1 year ago
commit da8e1ded55

@ -72,6 +72,7 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
const [inModelList, setInModelList] = useState(false) const [inModelList, setInModelList] = useState(false)
const invalidateInstalledPluginList = useInvalidateInstalledPluginList() const invalidateInstalledPluginList = useInvalidateInstalledPluginList()
const handleOpenModal = useModelModalHandler() const handleOpenModal = useModelModalHandler()
useEffect(() => { useEffect(() => {
(async () => { (async () => {
if (modelId && currentProvider) { if (modelId && currentProvider) {
@ -96,11 +97,8 @@ const AgentModelTrigger: FC<AgentModelTriggerProps> = ({
catch (error) { catch (error) {
// pass // pass
} }
setIsPluginChecked(true)
}
else {
setIsPluginChecked(true)
} }
setIsPluginChecked(true)
})() })()
}, [providerName, modelId, currentProvider]) }, [providerName, modelId, currentProvider])

@ -119,7 +119,7 @@ const ToolSelector: FC<Props> = ({
}, },
} }
onSelect(toolValue) onSelect(toolValue)
setIsShowChooseTool(false) // setIsShowChooseTool(false)
} }
const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { const handleDescriptionChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {

@ -130,11 +130,15 @@ const PluginItem: FC<Props> = ({
packageName={name} packageName={name}
packageNameClassName='w-auto max-w-[150px]' packageNameClassName='w-auto max-w-[150px]'
/> />
<div className='mx-2 text-text-quaternary system-xs-regular'>·</div> {category === PluginType.extension && (
<div className='flex text-text-tertiary system-xs-regular space-x-1'> <>
<RiLoginCircleLine className='w-4 h-4' /> <div className='mx-2 text-text-quaternary system-xs-regular'>·</div>
<span>{t('plugin.endpointsEnabled', { num: endpoints_active })}</span> <div className='flex text-text-tertiary system-xs-regular space-x-1'>
</div> <RiLoginCircleLine className='w-4 h-4' />
<span>{t('plugin.endpointsEnabled', { num: endpoints_active })}</span>
</div>
</>
)}
</div> </div>
<div className='flex items-center'> <div className='flex items-center'>
@ -154,7 +158,7 @@ const PluginItem: FC<Props> = ({
&& <> && <>
<a href={`${MARKETPLACE_URL_PREFIX}/plugins/${author}/${name}`} target='_blank' className='flex items-center gap-0.5'> <a href={`${MARKETPLACE_URL_PREFIX}/plugins/${author}/${name}`} target='_blank' className='flex items-center gap-0.5'>
<div className='text-text-tertiary system-2xs-medium-uppercase'>{t('plugin.from')} <span className='text-text-secondary'>marketplace</span></div> <div className='text-text-tertiary system-2xs-medium-uppercase'>{t('plugin.from')} <span className='text-text-secondary'>marketplace</span></div>
<RiArrowRightUpLine className='w-3 h-3' /> <RiArrowRightUpLine className='w-3 h-3 text-text-tertiary' />
</a> </a>
</> </>
} }

@ -35,7 +35,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
const buildInTools = useStore(s => s.buildInTools) const buildInTools = useStore(s => s.buildInTools)
const customTools = useStore(s => s.customTools) const customTools = useStore(s => s.customTools)
const workflowTools = useStore(s => s.workflowTools) const workflowTools = useStore(s => s.workflowTools)
const { data: agentStrategies } = useStrategyProviders() const { data: strategyProviders } = useStrategyProviders()
const needWarningNodes = useMemo(() => { const needWarningNodes = useMemo(() => {
const list = [] const list = []
@ -62,12 +62,14 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
if (node.data.type === BlockEnum.Agent) { if (node.data.type === BlockEnum.Agent) {
const data = node.data as AgentNodeType const data = node.data as AgentNodeType
const provider = agentStrategies?.find(s => s.plugin_unique_identifier === data.plugin_unique_identifier) const isReadyForCheckValid = !!strategyProviders
const provider = strategyProviders?.find(provider => provider.declaration.identity.name === data.agent_strategy_provider_name)
const strategy = provider?.declaration.strategies?.find(s => s.identity.name === data.agent_strategy_name) const strategy = provider?.declaration.strategies?.find(s => s.identity.name === data.agent_strategy_name)
moreDataForCheckValid = { moreDataForCheckValid = {
provider, provider,
strategy, strategy,
language, language,
isReadyForCheckValid,
} }
} }
@ -106,7 +108,7 @@ export const useChecklist = (nodes: Node[], edges: Edge[]) => {
} }
return list return list
}, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, agentStrategies]) }, [nodes, edges, isChatMode, buildInTools, customTools, workflowTools, language, nodesExtraData, t, strategyProviders])
return needWarningNodes return needWarningNodes
} }

@ -9,3 +9,4 @@ export * from './use-workflow-node-iteration-finished'
export * from './use-workflow-node-retry' export * from './use-workflow-node-retry'
export * from './use-workflow-text-chunk' export * from './use-workflow-text-chunk'
export * from './use-workflow-text-replace' export * from './use-workflow-text-replace'
export * from './use-workflow-agent-log'

@ -0,0 +1,50 @@
import { useCallback } from 'react'
import produce from 'immer'
import type { AgentLogResponse } from '@/types/workflow'
import { useWorkflowStore } from '@/app/components/workflow/store'
export const useWorkflowAgentLog = () => {
const workflowStore = useWorkflowStore()
const handleWorkflowAgentLog = useCallback((params: AgentLogResponse) => {
const { data } = params
const {
workflowRunningData,
setWorkflowRunningData,
} = workflowStore.getState()
setWorkflowRunningData(produce(workflowRunningData!, (draft) => {
const currentIndex = draft.tracing!.findIndex(item => item.node_id === data.node_id)
if (currentIndex > -1) {
const current = draft.tracing![currentIndex]
if (current.execution_metadata) {
if (current.execution_metadata.agent_log) {
const currentLogIndex = current.execution_metadata.agent_log.findIndex(log => log.id === data.id)
if (currentLogIndex > -1) {
current.execution_metadata.agent_log[currentLogIndex] = {
...current.execution_metadata.agent_log[currentLogIndex],
...data,
}
}
else {
current.execution_metadata.agent_log.push(data)
}
}
else {
current.execution_metadata.agent_log = [data]
}
}
else {
current.execution_metadata = {
agent_log: [data],
} as any
}
}
}))
}, [workflowStore])
return {
handleWorkflowAgentLog,
}
}

@ -1,4 +1,5 @@
import { import {
useWorkflowAgentLog,
useWorkflowFailed, useWorkflowFailed,
useWorkflowFinished, useWorkflowFinished,
useWorkflowNodeFinished, useWorkflowNodeFinished,
@ -24,6 +25,7 @@ export const useWorkflowRunEvent = () => {
const { handleWorkflowNodeRetry } = useWorkflowNodeRetry() const { handleWorkflowNodeRetry } = useWorkflowNodeRetry()
const { handleWorkflowTextChunk } = useWorkflowTextChunk() const { handleWorkflowTextChunk } = useWorkflowTextChunk()
const { handleWorkflowTextReplace } = useWorkflowTextReplace() const { handleWorkflowTextReplace } = useWorkflowTextReplace()
const { handleWorkflowAgentLog } = useWorkflowAgentLog()
return { return {
handleWorkflowStarted, handleWorkflowStarted,
@ -37,5 +39,6 @@ export const useWorkflowRunEvent = () => {
handleWorkflowNodeRetry, handleWorkflowNodeRetry,
handleWorkflowTextChunk, handleWorkflowTextChunk,
handleWorkflowTextReplace, handleWorkflowTextReplace,
handleWorkflowAgentLog,
} }
} }

@ -37,6 +37,7 @@ export const useWorkflowRun = () => {
handleWorkflowNodeIterationNext, handleWorkflowNodeIterationNext,
handleWorkflowNodeIterationFinished, handleWorkflowNodeIterationFinished,
handleWorkflowNodeRetry, handleWorkflowNodeRetry,
handleWorkflowAgentLog,
handleWorkflowTextChunk, handleWorkflowTextChunk,
handleWorkflowTextReplace, handleWorkflowTextReplace,
} = useWorkflowRunEvent() } = useWorkflowRunEvent()
@ -118,6 +119,7 @@ export const useWorkflowRun = () => {
onIterationNext, onIterationNext,
onIterationFinish, onIterationFinish,
onNodeRetry, onNodeRetry,
onAgentLog,
onError, onError,
...restCallback ...restCallback
} = callback || {} } = callback || {}
@ -234,6 +236,12 @@ export const useWorkflowRun = () => {
if (onNodeRetry) if (onNodeRetry)
onNodeRetry(params) onNodeRetry(params)
}, },
onAgentLog: (params) => {
handleWorkflowAgentLog(params)
if (onAgentLog)
onAgentLog(params)
},
onTextChunk: (params) => { onTextChunk: (params) => {
handleWorkflowTextChunk(params) handleWorkflowTextChunk(params)
}, },
@ -252,7 +260,7 @@ export const useWorkflowRun = () => {
...restCallback, ...restCallback,
}, },
) )
}, [store, workflowStore, doSyncWorkflowDraft, handleWorkflowStarted, handleWorkflowFinished, handleWorkflowFailed, handleWorkflowNodeStarted, handleWorkflowNodeFinished, handleWorkflowNodeIterationStarted, handleWorkflowNodeIterationNext, handleWorkflowNodeIterationFinished, handleWorkflowNodeRetry, handleWorkflowTextChunk, handleWorkflowTextReplace, pathname]) }, [store, workflowStore, doSyncWorkflowDraft, handleWorkflowStarted, handleWorkflowFinished, handleWorkflowFailed, handleWorkflowNodeStarted, handleWorkflowNodeFinished, handleWorkflowNodeIterationStarted, handleWorkflowNodeIterationNext, handleWorkflowNodeIterationFinished, handleWorkflowNodeRetry, handleWorkflowTextChunk, handleWorkflowTextReplace, handleWorkflowAgentLog, pathname])
const handleStopRun = useCallback((taskId: string) => { const handleStopRun = useCallback((taskId: string) => {
const appId = useAppStore.getState().appDetail?.id const appId = useAppStore.getState().appDetail?.id

@ -35,14 +35,22 @@ export const ModelBar: FC<ModelBarProps> = (props) => {
const { t } = useTranslation() const { t } = useTranslation()
const modelList = useAllModel() const modelList = useAllModel()
if (!('provider' in props)) { if (!('provider' in props)) {
return <ModelSelector return <Tooltip
modelList={[]} popupContent={t('workflow.nodes.agent.modelNotSelected')}
triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md' triggerMethod='hover'
defaultModel={undefined} >
showDeprecatedWarnIcon={false} <div className='relative'>
readonly <ModelSelector
deprecatedClassName='opacity-50' modelList={[]}
/> triggerClassName='bg-workflow-block-parma-bg !h-6 !rounded-md'
defaultModel={undefined}
showDeprecatedWarnIcon={false}
readonly
deprecatedClassName='opacity-50'
/>
<Indicator color={'red'} className='absolute -right-0.5 -top-0.5' />
</div>
</Tooltip>
} }
const modelInstalled = modelList?.some( const modelInstalled = modelList?.some(
provider => provider.provider === props.provider && provider.models.some(model => model.model === props.model)) provider => provider.provider === props.provider && provider.models.some(model => model.model === props.model))

@ -18,6 +18,7 @@ export const ToolIcon = memo(({ providerName }: ToolIconProps) => {
const { data: buildInTools } = useAllBuiltInTools() const { data: buildInTools } = useAllBuiltInTools()
const { data: customTools } = useAllCustomTools() const { data: customTools } = useAllCustomTools()
const { data: workflowTools } = useAllWorkflowTools() const { data: workflowTools } = useAllWorkflowTools()
const isDataReady = !!buildInTools && !!customTools && !!workflowTools
const currentProvider = useMemo(() => { const currentProvider = useMemo(() => {
const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])] const mergedTools = [...(buildInTools || []), ...(customTools || []), ...(workflowTools || [])]
return mergedTools.find((toolWithProvider) => { return mergedTools.find((toolWithProvider) => {
@ -33,10 +34,11 @@ export const ToolIcon = memo(({ providerName }: ToolIconProps) => {
return iconFromMarketPlace return iconFromMarketPlace
}, [author, currentProvider, name]) }, [author, currentProvider, name])
const status: Status = useMemo(() => { const status: Status = useMemo(() => {
if (!isDataReady) return undefined
if (!currentProvider) return 'not-installed' if (!currentProvider) return 'not-installed'
if (currentProvider.is_team_authorization === false) return 'not-authorized' if (currentProvider.is_team_authorization === false) return 'not-authorized'
return undefined return undefined
}, [currentProvider]) }, [currentProvider, isDataReady])
const indicator = status === 'not-installed' ? 'red' : status === 'not-authorized' ? 'yellow' : undefined const indicator = status === 'not-installed' ? 'red' : status === 'not-authorized' ? 'yellow' : undefined
const notSuccess = (['not-installed', 'not-authorized'] as Array<Status>).includes(status) const notSuccess = (['not-installed', 'not-authorized'] as Array<Status>).includes(status)
const { t } = useTranslation() const { t } = useTranslation()

@ -21,8 +21,15 @@ const nodeDefault: NodeDefault<AgentNodeType> = {
strategyProvider?: StrategyPluginDetail, strategyProvider?: StrategyPluginDetail,
strategy?: StrategyDetail strategy?: StrategyDetail
language: string language: string
isReadyForCheckValid: boolean
}) { }) {
const { strategy, language } = moreDataForCheckValid const { strategy, language, isReadyForCheckValid } = moreDataForCheckValid
if (!isReadyForCheckValid) {
return {
isValid: true,
errorMessage: '',
}
}
if (!strategy) { if (!strategy) {
return { return {
isValid: false, isValid: false,

@ -24,7 +24,6 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
.filter(param => param.type === FormTypeEnum.modelSelector) .filter(param => param.type === FormTypeEnum.modelSelector)
.reduce((acc, param) => { .reduce((acc, param) => {
const item = inputs.agent_parameters?.[param.name]?.value const item = inputs.agent_parameters?.[param.name]?.value
console.log({ item })
if (!item) { if (!item) {
if (param.required) { if (param.required) {
acc.push({ param: param.name }) acc.push({ param: param.name })
@ -68,20 +67,26 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
{inputs.agent_strategy_name {inputs.agent_strategy_name
? <SettingItem ? <SettingItem
label={t('workflow.nodes.agent.strategy.shortLabel')} label={t('workflow.nodes.agent.strategy.shortLabel')}
status={!currentStrategyStatus?.isExistInPlugin ? 'error' : undefined} status={
currentStrategyStatus && !currentStrategyStatus.isExistInPlugin
? 'error'
: undefined
}
tooltip={ tooltip={
!currentStrategyStatus?.isExistInPlugin ? t('workflow.nodes.agent.strategyNotInstallTooltip', { (currentStrategyStatus && !currentStrategyStatus.isExistInPlugin)
plugin: pluginDetail?.declaration.label ? t('workflow.nodes.agent.strategyNotInstallTooltip', {
? renderI18nObject(pluginDetail?.declaration.label) plugin: pluginDetail?.declaration.label
: undefined, ? renderI18nObject(pluginDetail?.declaration.label)
strategy: inputs.agent_strategy_label, : undefined,
}) : undefined strategy: inputs.agent_strategy_label,
})
: undefined
} }
> >
{inputs.agent_strategy_label} {inputs.agent_strategy_label}
</SettingItem> </SettingItem>
: <SettingItem label={t('workflow.nodes.agent.strategyNotSet')} />} : <SettingItem label={t('workflow.nodes.agent.strategyNotSet')} />}
<Group {models.length > 0 && <Group
label={<GroupLabel className='mt-1'> label={<GroupLabel className='mt-1'>
{t('workflow.nodes.agent.model')} {t('workflow.nodes.agent.model')}
</GroupLabel>} </GroupLabel>}
@ -92,7 +97,7 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
key={model.param} key={model.param}
/> />
})} })}
</Group> </Group>}
{tools.length > 0 && <Group label={<GroupLabel className='mt-1'> {tools.length > 0 && <Group label={<GroupLabel className='mt-1'>
{t('workflow.nodes.agent.toolbox')} {t('workflow.nodes.agent.toolbox')}
</GroupLabel>}> </GroupLabel>}>

@ -404,6 +404,63 @@ export const useChat = (
})) }))
} }
}, },
onAgentLog: ({ data }) => {
const currentNodeIndex = responseItem.workflowProcess!.tracing!.findIndex(item => item.node_id === data.node_id)
if (currentNodeIndex > -1) {
const current = responseItem.workflowProcess!.tracing![currentNodeIndex]
if (current.execution_metadata) {
if (current.execution_metadata.agent_log) {
const currentLogIndex = current.execution_metadata.agent_log.findIndex(log => log.id === data.id)
if (currentLogIndex > -1) {
current.execution_metadata.agent_log[currentLogIndex] = {
...current.execution_metadata.agent_log[currentLogIndex],
...data,
}
}
else {
current.execution_metadata.agent_log.push(data)
}
}
else {
current.execution_metadata.agent_log = [data]
}
}
else {
current.execution_metadata = {
agent_log: [data],
} as any
}
// if (current.agentLog) {
// const currentLogIndex = current.agentLog.findIndex(log => log.id === data.id)
// if (currentLogIndex > -1) {
// current.agentLog[currentLogIndex] = {
// ...current.agentLog[currentLogIndex],
// ...data,
// }
// }
// else {
// current.agentLog.push(data)
// }
// }
// else {
// current.agentLog = [data]
// }
responseItem.workflowProcess!.tracing[currentNodeIndex] = {
...current,
}
handleUpdateChatList(produce(chatListRef.current, (draft) => {
const currentIndex = draft.findIndex(item => item.id === responseItem.id)
draft[currentIndex] = {
...draft[currentIndex],
...responseItem,
}
}))
}
},
}, },
) )
}, [handleRun, handleResponding, handleUpdateChatList, notify, t, updateCurrentQA, config.suggested_questions_after_answer?.enabled, formSettings]) }, [handleRun, handleResponding, handleUpdateChatList, notify, t, updateCurrentQA, config.suggested_questions_after_answer?.enabled, formSettings])

@ -1,4 +1,7 @@
import { useState } from 'react' import {
useMemo,
useState,
} from 'react'
import { import {
RiArrowRightSLine, RiArrowRightSLine,
RiListView, RiListView,
@ -9,6 +12,9 @@ import type { AgentLogItemWithChildren } from '@/types/workflow'
import NodeStatusIcon from '@/app/components/workflow/nodes/_base/components/node-status-icon' import NodeStatusIcon from '@/app/components/workflow/nodes/_base/components/node-status-icon'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor' import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types' import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import BlockIcon from '@/app/components/workflow/block-icon'
import { BlockEnum } from '@/app/components/workflow/types'
import useGetIcon from '@/app/components/plugins/install-plugin/base/use-get-icon'
type AgentLogItemProps = { type AgentLogItemProps = {
item: AgentLogItemWithChildren item: AgentLogItemWithChildren
@ -26,6 +32,26 @@ const AgentLogItem = ({
metadata, metadata,
} = item } = item
const [expanded, setExpanded] = useState(false) const [expanded, setExpanded] = useState(false)
const { getIconUrl } = useGetIcon()
const toolIcon = useMemo(() => {
const icon = metadata?.icon
if (icon) {
if (icon.includes('http'))
return icon
return getIconUrl(icon)
}
return ''
}, [getIconUrl, metadata?.icon])
const mergeStatus = useMemo(() => {
if (status === 'start')
return 'running'
return status
}, [status])
return ( return (
<div className='bg-background-default border-[0.5px] border-components-panel-border rounded-[10px]'> <div className='bg-background-default border-[0.5px] border-components-panel-border rounded-[10px]'>
@ -41,7 +67,11 @@ const AgentLogItem = ({
? <RiArrowRightSLine className='shrink-0 w-4 h-4 rotate-90 text-text-quaternary' /> ? <RiArrowRightSLine className='shrink-0 w-4 h-4 rotate-90 text-text-quaternary' />
: <RiArrowRightSLine className='shrink-0 w-4 h-4 text-text-quaternary' /> : <RiArrowRightSLine className='shrink-0 w-4 h-4 text-text-quaternary' />
} }
<div className='shrink-0 mr-1.5 w-5 h-5'></div> <BlockIcon
className='shrink-0 mr-1.5'
type={toolIcon ? BlockEnum.Tool : BlockEnum.Agent}
toolIcon={toolIcon}
/>
<div <div
className='grow system-sm-semibold-uppercase text-text-secondary truncate' className='grow system-sm-semibold-uppercase text-text-secondary truncate'
title={label} title={label}
@ -53,7 +83,7 @@ const AgentLogItem = ({
<div className='shrink-0 mr-2 system-xs-regular text-text-tertiary'>{metadata?.elapsed_time?.toFixed(3)}s</div> <div className='shrink-0 mr-2 system-xs-regular text-text-tertiary'>{metadata?.elapsed_time?.toFixed(3)}s</div>
) )
} }
<NodeStatusIcon status={status} /> <NodeStatusIcon status={mergeStatus} />
</div> </div>
{ {
expanded && ( expanded && (

@ -14,21 +14,29 @@ const AgentLogTrigger = ({
onShowAgentOrToolLog, onShowAgentOrToolLog,
}: AgentLogTriggerProps) => { }: AgentLogTriggerProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const { agentLog } = nodeInfo const { agentLog, execution_metadata } = nodeInfo
const agentStrategy = execution_metadata?.tool_info?.agent_strategy
return ( return (
<div className='bg-components-button-tertiary-bg rounded-[10px]'> <div
className='bg-components-button-tertiary-bg rounded-[10px] cursor-pointer'
onClick={() => {
onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren)
}}
>
<div className='flex items-center px-3 pt-2 system-2xs-medium-uppercase text-text-tertiary'> <div className='flex items-center px-3 pt-2 system-2xs-medium-uppercase text-text-tertiary'>
{t('workflow.nodes.agent.strategy.label')} {t('workflow.nodes.agent.strategy.label')}
</div> </div>
<div className='flex items-center pl-3 pt-1 pr-2 pb-1.5'> <div className='flex items-center pl-3 pt-1 pr-2 pb-1.5'>
<div className='shrink-0 w-5 h-5'></div> {
<div className='grow mx-0.5 px-1 system-xs-medium text-text-secondary'></div> agentStrategy && (
<div className='grow system-xs-medium text-text-secondary'>
{agentStrategy}
</div>
)
}
<div <div
className='shrink-0 flex items-center px-[1px] system-xs-regular-uppercase text-text-tertiary cursor-pointer' className='shrink-0 flex items-center px-[1px] system-xs-regular-uppercase text-text-tertiary cursor-pointer'
onClick={() => {
onShowAgentOrToolLog({ id: nodeInfo.id, children: agentLog || [] } as AgentLogItemWithChildren)
}}
> >
{t('runLog.detail')} {t('runLog.detail')}
<RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' /> <RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' />

@ -735,6 +735,7 @@ const translation = {
strategyNotSet: 'Agentic strategy Not Set', strategyNotSet: 'Agentic strategy Not Set',
tools: 'Tools', tools: 'Tools',
maxIterations: 'Max Iterations', maxIterations: 'Max Iterations',
modelNotSelected: 'Model not selected',
modelNotInstallTooltip: 'This model is not installed', modelNotInstallTooltip: 'This model is not installed',
toolNotInstallTooltip: '{{tool}} is not installed', toolNotInstallTooltip: '{{tool}} is not installed',
toolNotAuthorizedTooltip: '{{tool}} Not Authorized', toolNotAuthorizedTooltip: '{{tool}} Not Authorized',

@ -736,6 +736,7 @@ const translation = {
tools: '工具', tools: '工具',
maxIterations: '最大迭代次数', maxIterations: '最大迭代次数',
modelNotInstallTooltip: '此模型未安装', modelNotInstallTooltip: '此模型未安装',
modelNotSelected: '未选择模型',
toolNotInstallTooltip: '{{tool}} 未安装', toolNotInstallTooltip: '{{tool}} 未安装',
toolNotAuthorizedTooltip: '{{tool}} 未授权', toolNotAuthorizedTooltip: '{{tool}} 未授权',
strategyNotInstallTooltip: '{{strategy}} 未安装', strategyNotInstallTooltip: '{{strategy}} 未安装',

@ -4,6 +4,7 @@ import Toast from '@/app/components/base/toast'
import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/base/chat/chat/type' import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/base/chat/chat/type'
import type { VisionFile } from '@/types/app' import type { VisionFile } from '@/types/app'
import type { import type {
AgentLogResponse,
IterationFinishedResponse, IterationFinishedResponse,
IterationNextResponse, IterationNextResponse,
IterationStartedResponse, IterationStartedResponse,
@ -53,6 +54,7 @@ export type IOnTextChunk = (textChunk: TextChunkResponse) => void
export type IOnTTSChunk = (messageId: string, audioStr: string, audioType?: string) => void export type IOnTTSChunk = (messageId: string, audioStr: string, audioType?: string) => void
export type IOnTTSEnd = (messageId: string, audioStr: string, audioType?: string) => void export type IOnTTSEnd = (messageId: string, audioStr: string, audioType?: string) => void
export type IOnTextReplace = (textReplace: TextReplaceResponse) => void export type IOnTextReplace = (textReplace: TextReplaceResponse) => void
export type IOnAgentLog = (agentLog: AgentLogResponse) => void
export type IOtherOptions = { export type IOtherOptions = {
isPublicAPI?: boolean isPublicAPI?: boolean
@ -84,6 +86,7 @@ export type IOtherOptions = {
onTTSChunk?: IOnTTSChunk onTTSChunk?: IOnTTSChunk
onTTSEnd?: IOnTTSEnd onTTSEnd?: IOnTTSEnd
onTextReplace?: IOnTextReplace onTextReplace?: IOnTextReplace
onAgentLog?: IOnAgentLog
} }
function unicodeToChar(text: string) { function unicodeToChar(text: string) {
@ -129,6 +132,7 @@ const handleStream = (
onTTSChunk?: IOnTTSChunk, onTTSChunk?: IOnTTSChunk,
onTTSEnd?: IOnTTSEnd, onTTSEnd?: IOnTTSEnd,
onTextReplace?: IOnTextReplace, onTextReplace?: IOnTextReplace,
onAgentLog?: IOnAgentLog,
) => { ) => {
if (!response.ok) if (!response.ok)
throw new Error('Network response was not ok') throw new Error('Network response was not ok')
@ -229,6 +233,9 @@ const handleStream = (
else if (bufferObj.event === 'text_replace') { else if (bufferObj.event === 'text_replace') {
onTextReplace?.(bufferObj as TextReplaceResponse) onTextReplace?.(bufferObj as TextReplaceResponse)
} }
else if (bufferObj.event === 'agent_log') {
onAgentLog?.(bufferObj as AgentLogResponse)
}
else if (bufferObj.event === 'tts_message') { else if (bufferObj.event === 'tts_message') {
onTTSChunk?.(bufferObj.message_id, bufferObj.audio, bufferObj.audio_type) onTTSChunk?.(bufferObj.message_id, bufferObj.audio, bufferObj.audio_type)
} }
@ -322,6 +329,7 @@ export const ssePost = (
onTTSChunk, onTTSChunk,
onTTSEnd, onTTSEnd,
onTextReplace, onTextReplace,
onAgentLog,
onError, onError,
getAbortController, getAbortController,
} = otherOptions } = otherOptions
@ -392,7 +400,7 @@ export const ssePost = (
return return
} }
onData?.(str, isFirstMessage, moreInfo) onData?.(str, isFirstMessage, moreInfo)
}, onCompleted, onThought, onMessageEnd, onMessageReplace, onFile, onWorkflowStarted, onWorkflowFinished, onNodeStarted, onNodeFinished, onIterationStart, onIterationNext, onIterationFinish, onNodeRetry, onParallelBranchStarted, onParallelBranchFinished, onTextChunk, onTTSChunk, onTTSEnd, onTextReplace) }, onCompleted, onThought, onMessageEnd, onMessageReplace, onFile, onWorkflowStarted, onWorkflowFinished, onNodeStarted, onNodeFinished, onIterationStart, onIterationNext, onIterationFinish, onNodeRetry, onParallelBranchStarted, onParallelBranchFinished, onTextChunk, onTTSChunk, onTTSEnd, onTextReplace, onAgentLog)
}).catch((e) => { }).catch((e) => {
if (e.toString() !== 'AbortError: The user aborted a request.' && !e.toString().errorMessage.includes('TypeError: Cannot assign to read only property')) if (e.toString() !== 'AbortError: The user aborted a request.' && !e.toString().errorMessage.includes('TypeError: Cannot assign to read only property'))
Toast.notify({ type: 'error', message: e }) Toast.notify({ type: 'error', message: e })

@ -6,6 +6,7 @@ import type { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/
export type AgentLogItem = { export type AgentLogItem = {
node_execution_id: string, node_execution_id: string,
id: string, id: string,
node_id: string,
parent_id?: string, parent_id?: string,
label: string, label: string,
data: object, // debug data data: object, // debug data
@ -14,6 +15,7 @@ export type AgentLogItem = {
metadata?: { metadata?: {
elapsed_time?: number elapsed_time?: number
provider?: string provider?: string
icon?: string
}, },
} }
@ -51,6 +53,10 @@ export type NodeTracing = {
iteration_duration_map?: IterationDurationMap iteration_duration_map?: IterationDurationMap
error_strategy?: ErrorHandleTypeEnum error_strategy?: ErrorHandleTypeEnum
agent_log?: AgentLogItem[] agent_log?: AgentLogItem[]
tool_info?: {
agent_strategy?: string
icon?: string
}
} }
metadata: { metadata: {
iterator_length: number iterator_length: number
@ -230,6 +236,12 @@ export type TextReplaceResponse = {
} }
} }
export type AgentLogResponse = {
task_id: string
event: string
data: AgentLogItemWithChildren
}
export type WorkflowRunHistory = { export type WorkflowRunHistory = {
id: string id: string
sequence_number: number sequence_number: number

Loading…
Cancel
Save