Merge branch "main" into feat/plugins

This commit is contained in:
Yi
2024-12-05 15:08:09 +08:00
71 changed files with 1619 additions and 1068 deletions

View File

@ -29,6 +29,7 @@ import { useAppContext } from '@/context/app-context'
import { ModelFeatureEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useFeatures } from '@/app/components/base/features/hooks'
import type { InputForm } from '@/app/components/base/chat/chat/type'
import { getLastAnswer } from '@/app/components/base/chat/utils'
interface ChatItemProps {
modelAndParameter: ModelAndParameter
@ -101,7 +102,7 @@ const ChatItem: FC<ChatItemProps> = ({
query: message,
inputs,
model_config: configData,
parent_message_id: chatListRef.current.at(-1)?.id || null,
parent_message_id: getLastAnswer(chatListRef.current)?.id || null,
}
if ((config.file_upload as any).enabled && files?.length && supportVision)

View File

@ -84,7 +84,7 @@ const FileImageItem = ({
className='absolute bottom-0.5 right-0.5 flex items-center justify-center w-6 h-6 rounded-lg bg-components-actionbar-bg shadow-md'
onClick={(e) => {
e.stopPropagation()
downloadFile(url || '', name)
downloadFile(url || base64Url || '', name)
}}
>
<RiDownloadLine className='w-4 h-4 text-text-tertiary' />

View File

@ -80,7 +80,7 @@ const FileItem = ({
}
</div>
{
showDownloadAction && (
showDownloadAction && url && (
<ActionButton
size='m'
className='hidden group-hover/file-item:flex absolute -right-1 -top-1'

View File

@ -53,8 +53,7 @@ const ImageGallery: FC<Props> = ({
imagePreviewUrl && (
<ImagePreview
url={imagePreviewUrl}
onCancel={() => setImagePreviewUrl('')}
/>
onCancel={() => setImagePreviewUrl('')} title={''} />
)
}
</div>

View File

@ -9,7 +9,6 @@ import RemarkGfm from 'remark-gfm'
import RehypeRaw from 'rehype-raw'
import SyntaxHighlighter from 'react-syntax-highlighter'
import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs'
import type { RefObject } from 'react'
import { Component, createContext, memo, useContext, useEffect, useMemo, useRef, useState } from 'react'
import cn from '@/utils/classnames'
import CopyBtn from '@/app/components/base/copy-btn'
@ -78,28 +77,6 @@ export function PreCode(props: { children: any }) {
)
}
const useLazyLoad = (ref: RefObject<Element>): boolean => {
const [isIntersecting, setIntersecting] = useState<boolean>(false)
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
setIntersecting(true)
observer.disconnect()
}
})
if (ref.current)
observer.observe(ref.current)
return () => {
observer.disconnect()
}
}, [ref])
return isIntersecting
}
const PreContext = createContext({
// if children not in PreContext, just leave inline true
inline: true,
@ -138,7 +115,7 @@ const CodeBlock: Components['code'] = memo(({ className, children, ...props }) =
try {
return JSON.parse(String(children).replace(/\n$/, ''))
}
catch { }
catch (error) { }
}
return JSON.parse('{"title":{"text":"ECharts error - Wrong JSON format."}}')
}, [language, children])
@ -167,7 +144,7 @@ const CodeBlock: Components['code'] = memo(({ className, children, ...props }) =
else {
return (
<SyntaxHighlighter
{...props}
{...props as any}
style={atelierHeathLight}
customStyle={{
paddingLeft: 12,
@ -274,7 +251,7 @@ export function Markdown(props: { content: string; className?: string }) {
() => {
return (tree) => {
const iterate = (node: any) => {
if (node.type === 'element' && !node.properties?.src && node.properties?.ref && node.properties.ref.startsWith('{') && node.properties.ref.endsWith('}'))
if (node.type === 'element' && node.properties?.ref)
delete node.properties.ref
if (node.children)

View File

@ -0,0 +1,47 @@
import type { ComponentProps, FC } from 'react'
import classNames from '@/utils/classnames'
type SkeletonProps = ComponentProps<'div'>
export const SkeletonContanier: FC<SkeletonProps> = (props) => {
const { className, children, ...rest } = props
return (
<div className={classNames('flex flex-col gap-1', className)} {...rest}>
{children}
</div>
)
}
export const SkeletonRow: FC<SkeletonProps> = (props) => {
const { className, children, ...rest } = props
return (
<div className={classNames('flex items-center gap-2', className)} {...rest}>
{children}
</div>
)
}
export const SkeletonRectangle: FC<SkeletonProps> = (props) => {
const { className, children, ...rest } = props
return (
<div className={classNames('h-2 rounded-sm opacity-20 bg-text-tertiary my-1', className)} {...rest}>
{children}
</div>
)
}
export const SkeletonPoint: FC = () =>
<div className='text-text-quaternary text-xs font-medium'>·</div>
/** Usage
* <SkeletonContanier>
* <SkeletonRow>
* <SkeletonRectangle className="w-96" />
* <SkeletonPoint />
* <SkeletonRectangle className="w-96" />
* </SkeletonRow>
* <SkeletonRow>
* <SkeletonRectangle className="w-96" />
* </SkeletonRow>
* <SkeletonRow>
*/

View File

@ -30,7 +30,9 @@ const nodeDefault: NodeDefault<AssignerNodeType> = {
errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t('workflow.nodes.assigner.assignedVariable') })
if (!errorMessages && value.operation !== WriteMode.clear) {
if (value.operation === WriteMode.set) {
if (value.operation === WriteMode.set || value.operation === WriteMode.increment
|| value.operation === WriteMode.decrement || value.operation === WriteMode.multiply
|| value.operation === WriteMode.divide) {
if (!value.value && typeof value.value !== 'number')
errorMessages = t(`${i18nPrefix}.fieldRequired`, { field: t('workflow.nodes.assigner.variable') })
}

View File

@ -33,7 +33,7 @@ const NodeVariableItem = ({
const { t } = useTranslation()
return (
<div className={cn(
'relative flex items-center p-[3px] pl-[5px] gap-1 self-stretch rounded-md bg-workflow-block-param-bg',
'relative flex items-center p-[3px] pl-[5px] gap-1 self-stretch rounded-md bg-workflow-block-parma-bg',
showBorder && '!bg-black/[0.02]',
className,
)}>

View File

@ -97,8 +97,9 @@ const ChatVariableModal = ({
return objectPlaceholder
}, [type])
const getObjectValue = useCallback(() => {
if (!chatVar)
if (!chatVar || Object.keys(chatVar.value).length === 0)
return [DEFAULT_OBJECT_VALUE]
return Object.keys(chatVar.value).map((key) => {
return {
key,