feat: support show global vars

This commit is contained in:
Joel 2025-10-21 17:59:25 +08:00
parent 2793ede875
commit 04b55177b5
9 changed files with 108 additions and 22 deletions

View File

@ -3,6 +3,7 @@
import type { ReactNode } from 'react'
import React, { createContext, useContext, useEffect, useState } from 'react'
import { usePathname } from 'next/navigation'
import { isInWorkflowPage } from '../workflow/constants'
/**
* Interface for the GotoAnything context
@ -50,7 +51,7 @@ export const GotoAnythingProvider: React.FC<GotoAnythingProviderProps> = ({ chil
}
// Workflow pages: /app/[appId]/workflow or /workflow/[token] (shared)
const isWorkflow = /^\/app\/[^/]+\/workflow$/.test(pathname) || /^\/workflow\/[^/]+$/.test(pathname)
const isWorkflow = isInWorkflowPage()
// RAG Pipeline pages: /datasets/[datasetId]/pipeline
const isRagPipeline = /^\/datasets\/[^/]+\/pipeline$/.test(pathname)

View File

@ -35,7 +35,12 @@ export const NODE_LAYOUT_HORIZONTAL_PADDING = 60
export const NODE_LAYOUT_VERTICAL_PADDING = 60
export const NODE_LAYOUT_MIN_DISTANCE = 100
export const isInWorkflowPage = () => {
const pathname = globalThis.location.pathname
return /^\/app\/[^/]+\/workflow$/.test(pathname) || /^\/workflow\/[^/]+$/.test(pathname)
}
export const getGlobalVars = (isChatMode: boolean): Var[] => {
const isInWorkflow = isInWorkflowPage()
const vars: Var[] = [
...(isChatMode ? [
{
@ -63,6 +68,12 @@ export const getGlobalVars = (isChatMode: boolean): Var[] => {
variable: 'sys.workflow_run_id',
type: VarType.string,
},
...(isInWorkflow ? [
{
variable: 'sys.trigger_timestamp',
type: VarType.string,
},
] : []),
]
return vars
}

View File

@ -11,7 +11,7 @@ const GlobalVariableButton = ({ disabled }: { disabled: boolean }) => {
}
return (
<Button className='p-2' disabled={disabled} onClick={handleClick}>
<Button className='p-2' disabled={disabled} onClick={handleClick} variant='ghost'>
<GlobalVariable className='h-4 w-4 text-components-button-secondary-text' />
</Button>
)

View File

@ -20,6 +20,7 @@ import EnvButton from './env-button'
import VersionHistoryButton from './version-history-button'
import { useInputFieldPanel } from '@/app/components/rag-pipeline/hooks'
import ScrollToSelectedNodeButton from './scroll-to-selected-node-button'
import GlobalVariableButton from './global-variable-button'
export type HeaderInNormalProps = {
components?: {
@ -72,9 +73,10 @@ const HeaderInNormal = ({
{components?.left}
<Divider type='vertical' className='mx-auto h-3.5' />
<RunAndHistory {...runAndHistoryProps} />
<div className='cursor-pointer rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs backdrop-blur-[10px]'>
<div className='shrink-0 cursor-pointer rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs backdrop-blur-[10px]'>
{components?.chatVariableTrigger}
<EnvButton disabled={nodesReadOnly} />
<GlobalVariableButton disabled={nodesReadOnly} />
</div>
{components?.middle}
<VersionHistoryButton onClick={onStartRestoring} />

View File

@ -8,16 +8,53 @@ import Item from './item'
import { useStore } from '@/app/components/workflow/store'
import cn from '@/utils/classnames'
import { useTranslation } from 'react-i18next'
import { useIsChatMode } from '../../hooks'
import { isInWorkflowPage } from '../../constants'
const Panel = () => {
const { t } = useTranslation()
const isChatMode = useIsChatMode()
const setShowPanel = useStore(s => s.setShowGlobalVariablePanel)
const isWorkflowPage = isInWorkflowPage()
const globalVariableList: GlobalVariable[] = [
{
...(isChatMode ? [{
name: 'conversation_id',
value_type: 'string',
description: 'conversation id',
value_type: 'string' as const,
description: t('workflow.globalVar.fieldsDescription.conversationId'),
},
{
name: 'dialog_count',
value_type: 'number' as const,
description: t('workflow.globalVar.fieldsDescription.dialogCount'),
}] : []),
{
name: 'user_id',
value_type: 'string',
description: t('workflow.globalVar.fieldsDescription.userId'),
},
{
name: 'app_id',
value_type: 'string',
description: t('workflow.globalVar.fieldsDescription.appId'),
},
{
name: 'workflow_id',
value_type: 'string',
description: t('workflow.globalVar.fieldsDescription.workflowId'),
},
{
name: 'workflow_run_id',
value_type: 'string',
description: t('workflow.globalVar.fieldsDescription.workflowRunId'),
},
// is workflow
...(isWorkflowPage ? [{
name: 'trigger_timestamp',
value_type: 'string' as const,
description: t('workflow.globalVar.fieldsDescription.triggerTimestamp'),
}] : []),
]
return (
@ -27,7 +64,7 @@ const Panel = () => {
)}
>
<div className='system-xl-semibold flex shrink-0 items-center justify-between p-4 pb-0 text-text-primary'>
Global Variables(Current not show)
{t('workflow.globalVar.title')}
<div className='flex items-center'>
<div
className='flex h-6 w-6 cursor-pointer items-center justify-center'
@ -37,9 +74,9 @@ const Panel = () => {
</div>
</div>
</div>
<div className='system-sm-regular shrink-0 px-4 py-1 text-text-tertiary'>...</div>
<div className='system-sm-regular shrink-0 px-4 py-1 text-text-tertiary'>{t('workflow.globalVar.description')}</div>
<div className='grow overflow-y-auto rounded-b-2xl px-4'>
<div className='mt-4 grow overflow-y-auto rounded-b-2xl px-4'>
{globalVariableList.map(item => (
<Item
key={item.name}

View File

@ -1,6 +1,7 @@
import { memo } from 'react'
import { capitalize } from 'lodash-es'
import { Env } from '@/app/components/base/icons/src/vender/line/others'
import { GlobalVariable as GlobalVariableIcon } from '@/app/components/base/icons/src/vender/line/others'
import type { GlobalVariable } from '@/app/components/workflow/types'
import cn from '@/utils/classnames'
@ -17,12 +18,15 @@ const Item = ({
)}>
<div className='flex items-center justify-between'>
<div className='flex grow items-center gap-1'>
<Env className='h-4 w-4 text-util-colors-violet-violet-600' />
<div className='system-sm-medium text-text-primary'>{payload.name}</div>
<GlobalVariableIcon className='h-4 w-4 text-util-colors-orange-orange-600' />
<div className='system-sm-medium text-text-primary'>
<span className='text-text-tertiary'>sys.</span>
{payload.name}
</div>
<div className='system-xs-medium text-text-tertiary'>{capitalize(payload.value_type)}</div>
</div>
</div>
<div className='system-xs-regular truncate text-text-tertiary'>{payload.description}</div>
<div className='system-xs-regular mt-1.5 truncate text-text-tertiary'>{payload.description}</div>
</div>
)
}

View File

@ -20,7 +20,12 @@ export const createChatVariableSlice: StateCreator<ChatVariableSliceShape> = (se
return ({
showChatVariablePanel: false,
setShowChatVariablePanel: showChatVariablePanel => set(() => ({ showChatVariablePanel })),
setShowChatVariablePanel: showChatVariablePanel => set(() => {
if (showChatVariablePanel)
return { ...hideAllPanel, showChatVariablePanel: true }
else
return { showChatVariablePanel: false }
}),
showGlobalVariablePanel: false,
setShowGlobalVariablePanel: showGlobalVariablePanel => set(() => {
if (showGlobalVariablePanel)

View File

@ -10,11 +10,24 @@ export type EnvVariableSliceShape = {
setEnvSecrets: (envSecrets: Record<string, string>) => void
}
export const createEnvVariableSlice: StateCreator<EnvVariableSliceShape> = set => ({
showEnvPanel: false,
setShowEnvPanel: showEnvPanel => set(() => ({ showEnvPanel })),
environmentVariables: [],
setEnvironmentVariables: environmentVariables => set(() => ({ environmentVariables })),
envSecrets: {},
setEnvSecrets: envSecrets => set(() => ({ envSecrets })),
})
export const createEnvVariableSlice: StateCreator<EnvVariableSliceShape> = (set) => {
const hideAllPanel = {
showDebugAndPreviewPanel: false,
showEnvPanel: false,
showChatVariablePanel: false,
showGlobalVariablePanel: false,
}
return ({
showEnvPanel: false,
setShowEnvPanel: showEnvPanel => set(() => {
if (showEnvPanel)
return { ...hideAllPanel, showEnvPanel: true }
else
return { showEnvPanel: false }
}),
environmentVariables: [],
setEnvironmentVariables: environmentVariables => set(() => ({ environmentVariables })),
envSecrets: {},
setEnvSecrets: envSecrets => set(() => ({ envSecrets })),
})
}

View File

@ -146,6 +146,19 @@ const translation = {
export: 'Export DSL with secret values ',
},
},
globalVar: {
title: 'System Variables',
description: 'System variables are global variables that can be referenced by any node without wiring when the type is correct, such as end-user ID and workflow ID.',
fieldsDescription: {
conversationId: 'Conversation ID',
dialogCount: 'Conversation Count',
userId: 'User ID',
triggerTimestamp: 'Application trigger time',
appId: 'Application ID',
workflowId: 'Workflow ID',
workflowRunId: 'Workflow run ID',
},
},
sidebar: {
exportWarning: 'Export Current Saved Version',
exportWarningDesc: 'This will export the current saved version of your workflow. If you have unsaved changes in the editor, please save them first by using the export option in the workflow canvas.',