Merge branch 'release/v0.3.0' into develop

* release/v0.3.0: (44 commits)
  Revert "fix(web): prompt editor"
  fix(web): prompt editor
  fix(prompt-optimizer): handle escaped quotes in JSON parsing
  fix(custom-tools): remove parameter coercion in custom tool base class
  fix(core): conditionally apply thinking parameters based on model support
  refactor(custom-tools): coerce query and request body parameters to schema types
  fix(prompt-optimizer): support list content type in prompt optimizer
  refactor(memory): unify user placeholder names and harden alias sync logic
  fix(rag): replace semicolon separators with newlines in Excel parser output
  fix(web): Compatible with Windows whitespace
  fix(memory): make PgSQL the single source of truth for user entity aliases
  refactor(rag): simplify Excel parsing logic and remove redundant chunk_token_num assignment
  fix(web): Hide error message when workflow node error message equals empty string
  ci(wechat-notify): add Sourcery summary extraction with Qwen fallback
  fix(http-request,embedding,naive): tighten form-data validation, reduce truncation length to 8000, and disable chunking for Excel
  fix(web): adjust the value of End User Name
  fix(http-request): support array and file variables in form-data files upload
  fix(web): change http body key name
  fix(web): header user name
  fix(web): calculate using the filtered breadcrumbs length
  ...

# Conflicts:
#	web/src/views/UserMemoryDetail/Neo4j.tsx
#	web/src/views/UserMemoryDetail/components/EndUserProfile.tsx
#	web/src/views/UserMemoryDetail/types.ts
This commit is contained in:
Mark
2026-04-15 19:31:38 +08:00
48 changed files with 702 additions and 452 deletions

View File

@@ -12,6 +12,14 @@
font-weight: 500;
font-style: normal;
}
.breadcrumbTitle {
display: inline-block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: bottom;
}
.header :global(.ant-breadcrumb) {
line-height: 31px;
}

View File

@@ -14,7 +14,7 @@
*/
import { type FC, useRef, useState } from 'react';
import { Layout, Dropdown, Breadcrumb, Flex } from 'antd';
import { Layout, Dropdown, Breadcrumb, Flex, Tooltip } from 'antd';
import type { MenuProps, BreadcrumbProps } from 'antd';
import { useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';
@@ -77,7 +77,7 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => {
{
key: '1',
icon: <Flex align="center" justify="center" className="rb:size-10 rb:rounded-xl rb:bg-[#155EEF] rb:text-white">
{/[\u4e00-\u9fa5]/.test(user.username) ? user.username.slice(0, 2) : user.username?.[0]}
{/[\u4e00-\u9fa5]/.test(user.username) ? user.username.slice(-2) : user.username[0]}
</Flex>,
label: (<>
<div className="rb:text-[#212332] rb:leading-5">{user.username}</div>
@@ -135,28 +135,30 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => {
* - Disables navigation for the last breadcrumb item
*/
const formatBreadcrumbNames = () => {
return breadcrumbs.filter(item => item.type !== 'group').map((menu, index) => {
const filtered = breadcrumbs.filter(item => item.type !== 'group');
return filtered.map((menu, index) => {
const label = menu.i18nKey ? t(menu.i18nKey) : menu.label;
const isLast = index === filtered.length - 1;
const item: any = {
title: menu.i18nKey ? t(menu.i18nKey) : menu.label,
title: (
<Tooltip title={label} placement="bottom">
<span className={styles.breadcrumbTitle}>{label}</span>
</Tooltip>
),
};
// If it's the last item, don't set path
if (index === breadcrumbs.length - 1) {
return item;
if (!isLast) {
if ((menu as any).onClick) {
item.onClick = (e: React.MouseEvent) => {
e.preventDefault();
(menu as any).onClick(e);
};
item.href = '#';
} else if (menu.path && menu.path !== '#') {
item.path = menu.path;
}
}
// If has custom onClick, use onClick and set href to '#' to show pointer cursor
if ((menu as any).onClick) {
item.onClick = (e: React.MouseEvent) => {
e.preventDefault();
(menu as any).onClick(e);
};
item.href = '#';
} else if (menu.path && menu.path !== '#') {
// Only set path when path is not '#'
item.path = menu.path;
}
return item;
});
}
@@ -180,7 +182,7 @@ const AppHeader: FC<{source?: 'space' | 'manage';}> = ({source = 'manage'}) => {
>
<Flex align="center" className="rb:cursor-pointer rb:font-medium">
<Flex align="center" justify="center" className="rb:size-8 rb:rounded-xl rb:bg-[#155EEF] rb:text-white rb:mr-2!">
{/[\u4e00-\u9fa5]/.test(user.username) ? user.username.slice(user.username.length, -2) : user.username[0]}
{/[\u4e00-\u9fa5]/.test(user.username) ? user.username.slice(-2) : user.username[0]}
</Flex>
<span className="rb:text-[#212332] rb:text-[12px] rb:leading-4 rb:mr-1">{user.username}</span>
<div className={clsx("rb:size-3 rb:bg-cover rb:bg-[url('@/assets/images/common/arrow_up.svg')]", {