|
@@ -31,8 +31,10 @@
|
|
|
<Toolbar
|
|
<Toolbar
|
|
|
@create:node="handleNodeCreate"
|
|
@create:node="handleNodeCreate"
|
|
|
@run="handleRunAgent"
|
|
@run="handleRunAgent"
|
|
|
|
|
+ @chat="handleOpenWorkflowChat"
|
|
|
:env-vars="workflow?.env_variables || []"
|
|
:env-vars="workflow?.env_variables || []"
|
|
|
:run-nodes="toolbarRunNodes"
|
|
:run-nodes="toolbarRunNodes"
|
|
|
|
|
+ :can-chat="canRunWorkflowChat"
|
|
|
@change-env-vars="handleChangeEnvVars"
|
|
@change-env-vars="handleChangeEnvVars"
|
|
|
/>
|
|
/>
|
|
|
</Workflow>
|
|
</Workflow>
|
|
@@ -46,6 +48,20 @@
|
|
|
:initial-tab="runWorkflowInitialTab"
|
|
:initial-tab="runWorkflowInitialTab"
|
|
|
@run-started="handleWorkflowRunStarted"
|
|
@run-started="handleWorkflowRunStarted"
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <ChatDrawer
|
|
|
|
|
+ v-model:visible="workflowChatVisible"
|
|
|
|
|
+ :workflow="workflow"
|
|
|
|
|
+ :start-node="workflowChatStartNode"
|
|
|
|
|
+ :visible-variables="workflowChatVisibleVariables"
|
|
|
|
|
+ :input-values="workflowChatInputValues"
|
|
|
|
|
+ :json-drafts="workflowChatJsonDrafts"
|
|
|
|
|
+ :validation-errors="workflowChatValidationErrors"
|
|
|
|
|
+ :base-params="workflowChatBaseParams"
|
|
|
|
|
+ :is-running="workflowChatRunning"
|
|
|
|
|
+ @validate-send="handleWorkflowChatValidateSend"
|
|
|
|
|
+ @run-started="handleWorkflowChatRunStarted"
|
|
|
|
|
+ @cancel="handleWorkflowChatCancel"
|
|
|
|
|
+ />
|
|
|
<Setter
|
|
<Setter
|
|
|
:id="nodeID"
|
|
:id="nodeID"
|
|
|
:workflow="workflow"
|
|
:workflow="workflow"
|
|
@@ -106,8 +122,10 @@
|
|
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
|
import { agent } from '@repo/api-service'
|
|
import { agent } from '@repo/api-service'
|
|
|
|
|
+import { cloneDeep, isEqual } from 'lodash-es'
|
|
|
|
|
|
|
|
import RunWorkflow from '@/features/RunWorkflow/index.vue'
|
|
import RunWorkflow from '@/features/RunWorkflow/index.vue'
|
|
|
|
|
+import ChatDrawer from '@/features/ChatDrawer/index.vue'
|
|
|
import NodeLibary from '@/features/nodeLibary/index.vue'
|
|
import NodeLibary from '@/features/nodeLibary/index.vue'
|
|
|
import Toolbar from '@/features/toolbar/index.vue'
|
|
import Toolbar from '@/features/toolbar/index.vue'
|
|
|
import Setter from '@/features/setter/index.vue'
|
|
import Setter from '@/features/setter/index.vue'
|
|
@@ -115,9 +133,9 @@ import { nodeMap } from '@/nodes'
|
|
|
import { getNodeDisplayName } from '@/nodes/i18n'
|
|
import { getNodeDisplayName } from '@/nodes/i18n'
|
|
|
import { useI18n } from '@/composables/useI18n'
|
|
import { useI18n } from '@/composables/useI18n'
|
|
|
import { useRunnerStore } from '@/store/modules/runner.store'
|
|
import { useRunnerStore } from '@/store/modules/runner.store'
|
|
|
|
|
+import { buildExecuteParams, createEmptyValue } from '@/features/RunWorkflow/utils'
|
|
|
import { Workflow, useDragAndDrop } from '@repo/workflow'
|
|
import { Workflow, useDragAndDrop } from '@repo/workflow'
|
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
|
-import { isEqual } from 'lodash-es'
|
|
|
|
|
import { Icon } from '@repo/ui'
|
|
import { Icon } from '@repo/ui'
|
|
|
|
|
|
|
|
import type {
|
|
import type {
|
|
@@ -128,6 +146,7 @@ import type {
|
|
|
IWorkflowNode,
|
|
IWorkflowNode,
|
|
|
XYPosition
|
|
XYPosition
|
|
|
} from '@repo/workflow'
|
|
} from '@repo/workflow'
|
|
|
|
|
+import type { StartVariable } from '@/nodes/src/start'
|
|
|
|
|
|
|
|
interface Props {
|
|
interface Props {
|
|
|
workflow: IWorkflow
|
|
workflow: IWorkflow
|
|
@@ -175,6 +194,11 @@ const closeRunWorkflowOnSubmit = ref(false)
|
|
|
const runWorkflowInputOnly = ref(false)
|
|
const runWorkflowInputOnly = ref(false)
|
|
|
const runWorkflowNodeId = ref('')
|
|
const runWorkflowNodeId = ref('')
|
|
|
const runWorkflowInitialTab = ref<'input' | 'trigger' | 'result' | 'detail' | 'trace'>('input')
|
|
const runWorkflowInitialTab = ref<'input' | 'trigger' | 'result' | 'detail' | 'trace'>('input')
|
|
|
|
|
+const workflowChatVisible = ref(false)
|
|
|
|
|
+const workflowChatInputValues = ref<Record<string, any>>({})
|
|
|
|
|
+const workflowChatJsonDrafts = ref<Record<string, string>>({})
|
|
|
|
|
+const workflowChatValidationErrors = ref<Record<string, string>>({})
|
|
|
|
|
+const workflowChatBaseParams = ref<Record<string, any>>({})
|
|
|
const setterVisible = ref(false)
|
|
const setterVisible = ref(false)
|
|
|
const nodeID = ref('')
|
|
const nodeID = ref('')
|
|
|
const setterActiveTab = ref<'setting' | 'last-run'>('setting')
|
|
const setterActiveTab = ref<'setting' | 'last-run'>('setting')
|
|
@@ -387,6 +411,34 @@ const getNodeTypeById = (id?: string) => {
|
|
|
return (node as any)?.nodeType || (node as any)?.data?.nodeType || ''
|
|
return (node as any)?.nodeType || (node as any)?.data?.nodeType || ''
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+const getStartVariables = (node?: IWorkflowNode | null): StartVariable[] => {
|
|
|
|
|
+ const variables = (node as any)?.data?.variables
|
|
|
|
|
+ return Array.isArray(variables) ? variables : []
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const workflowChatStartNode = computed<IWorkflowNode | null>(() => {
|
|
|
|
|
+ return (
|
|
|
|
|
+ (props.workflow?.nodes || []).find((node) => {
|
|
|
|
|
+ const nodeType = (node as any)?.nodeType || (node as any)?.data?.nodeType
|
|
|
|
|
+ return nodeType === 'start'
|
|
|
|
|
+ }) || null
|
|
|
|
|
+ )
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+const workflowChatStartVariables = computed<StartVariable[]>(() =>
|
|
|
|
|
+ getStartVariables(workflowChatStartNode.value)
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+const workflowChatVisibleVariables = computed(() =>
|
|
|
|
|
+ workflowChatStartVariables.value.filter((item) => !item.is_hide)
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
|
|
+const canRunWorkflowChat = computed(() => !!workflowChatStartNode.value)
|
|
|
|
|
+
|
|
|
|
|
+const workflowChatRunning = computed(
|
|
|
|
|
+ () => runnerStore.status === 'connecting' || runnerStore.status === 'running'
|
|
|
|
|
+)
|
|
|
|
|
+
|
|
|
const nodeLibaryParentType = computed(() => getNodeTypeById(peddingHandlePayload.value?.parentId))
|
|
const nodeLibaryParentType = computed(() => getNodeTypeById(peddingHandlePayload.value?.parentId))
|
|
|
|
|
|
|
|
const toolbarRunNodes = computed(() => {
|
|
const toolbarRunNodes = computed(() => {
|
|
@@ -611,6 +663,96 @@ const handleRunAgent = (id?: string) => {
|
|
|
handleRunNode(targetNode.id)
|
|
handleRunNode(targetNode.id)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function formatJsonDraft(value: unknown, fallback = '{}') {
|
|
|
|
|
+ if (value === undefined || value === null || value === '') return fallback
|
|
|
|
|
+ try {
|
|
|
|
|
+ return JSON.stringify(value, null, 2)
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ return fallback
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function resetWorkflowChatValidation() {
|
|
|
|
|
+ workflowChatValidationErrors.value = {}
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function initializeWorkflowChatInputValues() {
|
|
|
|
|
+ const values: Record<string, any> = {}
|
|
|
|
|
+ const drafts: Record<string, string> = {}
|
|
|
|
|
+
|
|
|
|
|
+ workflowChatStartVariables.value.forEach((variable) => {
|
|
|
|
|
+ const initialValue = cloneDeep(
|
|
|
|
|
+ variable.default_value !== undefined
|
|
|
|
|
+ ? variable.default_value
|
|
|
|
|
+ : createEmptyValue(variable.formType)
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ if (variable.formType === 'json_object') {
|
|
|
|
|
+ values[variable.name] =
|
|
|
|
|
+ initialValue && typeof initialValue === 'object' && !Array.isArray(initialValue)
|
|
|
|
|
+ ? initialValue
|
|
|
|
|
+ : {}
|
|
|
|
|
+ drafts[variable.name] = formatJsonDraft(values[variable.name], '{}')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ values[variable.name] = initialValue
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ workflowChatInputValues.value = values
|
|
|
|
|
+ workflowChatJsonDrafts.value = drafts
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const buildWorkflowChatParams = () => {
|
|
|
|
|
+ const params = buildExecuteParams({
|
|
|
|
|
+ startVariables: workflowChatStartVariables.value,
|
|
|
|
|
+ inputValues: workflowChatInputValues.value,
|
|
|
|
|
+ jsonDrafts: workflowChatJsonDrafts.value,
|
|
|
|
|
+ validationErrors: workflowChatValidationErrors.value,
|
|
|
|
|
+ translateFieldRequired: (name) =>
|
|
|
|
|
+ t('pages.runWorkflow.fieldRequired', {
|
|
|
|
|
+ name
|
|
|
|
|
+ }),
|
|
|
|
|
+ translateInvalidJson: () => t('pages.runWorkflow.invalidJson'),
|
|
|
|
|
+ translateFieldTooLong: (name, max) =>
|
|
|
|
|
+ t('pages.runWorkflow.fieldTooLong', {
|
|
|
|
|
+ name,
|
|
|
|
|
+ max
|
|
|
|
|
+ })
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ if (!params) {
|
|
|
|
|
+ ElMessage.warning(t('pages.runWorkflow.inputPanel.completeRequired'))
|
|
|
|
|
+ return false
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return params
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleOpenWorkflowChat = () => {
|
|
|
|
|
+ if (!workflowChatStartNode.value) {
|
|
|
|
|
+ ElMessage.warning(t('pages.nodeView.messages.missingTrigger'))
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ initializeWorkflowChatInputValues()
|
|
|
|
|
+ resetWorkflowChatValidation()
|
|
|
|
|
+ workflowChatBaseParams.value = {}
|
|
|
|
|
+ workflowChatVisible.value = true
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleWorkflowChatValidateSend = (done: (params: Record<string, any> | false) => void) => {
|
|
|
|
|
+ done(buildWorkflowChatParams())
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleWorkflowChatRunStarted = (id: string) => {
|
|
|
|
|
+ runWorkflowNodeId.value = id
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const handleWorkflowChatCancel = () => {
|
|
|
|
|
+ runnerStore.stopRunner()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
const createStickyNoteNode = (position: XYPosition = { x: 600, y: 300 }) => {
|
|
const createStickyNoteNode = (position: XYPosition = { x: 600, y: 300 }) => {
|
|
|
props.workflow?.nodes.push({
|
|
props.workflow?.nodes.push({
|
|
|
appAgentId: props.workflow.id,
|
|
appAgentId: props.workflow.id,
|