fix: misc frontend fixes for agent log, login, search settings (#16137)

### What problem does this PR solve?

fix: misc frontend fixes for agent log, login, search settings
- agent-log: restore server-side pagination on export and search;
replace hardcoded labels with i18n keys; switch container to
text-text-primary
- login: validate register nickname against NICKNAME_PATTERN with
reusable setting i18n
- next-search: align llm_setting schema with chat (LlmSettingFieldSchema
+ LLMIdFormField nested, LlmSettingEnabledSchema at form
root) so the slider Switch reads the correct path; strip *Enabled flags
before submit to avoid backend "Unrecognized field name"
  errors
  - locales: add common.reset (zh/en)
  - skills/go-naming: fix relative link to rules/named.md

### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
chanx
2026-06-17 16:20:26 +08:00
committed by GitHub
parent 3247e353c7
commit 9302233b95
8 changed files with 71 additions and 35 deletions

View File

@@ -1043,11 +1043,9 @@ export const useExportAgentLog = () => {
mutationFn: async (searchParams: IAgentLogsRequest) => {
const { data } = await fetchAgentLogsByCanvasId(id as string, {
...searchParams,
page: 1,
page_size: 100000,
});
return data?.data?.sessions ?? [];
return data?.data ?? [];
},
});

View File

@@ -67,6 +67,7 @@ export default {
add: 'Add',
remove: 'Remove',
search: 'Search',
reset: 'Reset',
noDataFound: 'No data found.',
noData: 'No data available',
promptPlaceholder: `Please input or use / to quickly insert variables.`,

View File

@@ -57,6 +57,7 @@ export default {
add: '添加',
remove: '移除',
search: '搜索',
reset: '重置',
noDataFound: '没有找到数据。',
noData: '暂无数据',
bedrockCredentialsHint:

View File

@@ -20,7 +20,6 @@ import {
} from '@/interfaces/database/agent';
import { IReferenceObject } from '@/interfaces/database/chat';
import { formatDate } from '@/utils/date';
import { useQueryClient } from '@tanstack/react-query';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useParams } from 'react-router';
@@ -53,7 +52,6 @@ const AgentLogPage: React.FC = () => {
const { navigateToAgents, navigateToAgent } = useNavigatePage();
const { flowDetail: agentDetail } = useFetchDataOnMount();
const { id: canvasId } = useParams();
const queryClient = useQueryClient();
const init = {
keywords: '',
from_date: getStartOfToday(),
@@ -176,7 +174,7 @@ const AgentLogPage: React.FC = () => {
});
};
const handleSearch = () => {
const handleSearch = (overrides: Partial<typeof searchParams> = {}) => {
setSearchParams((pre) => {
return {
...pre,
@@ -187,16 +185,14 @@ const AgentLogPage: React.FC = () => {
orderby: sortConfig?.orderby || '',
desc: sortConfig?.desc as boolean,
keywords: keywords,
...overrides,
};
});
};
const handleClickSearch = () => {
setPagination({ ...pagination, current: 1 });
handleSearch();
queryClient.invalidateQueries({
queryKey: ['fetchAgentLog'],
});
setPagination((pre) => ({ ...pre, current: 1 }));
handleSearch({ page: 1, keywords });
};
useEffect(() => {
handleSearch();
@@ -232,16 +228,20 @@ const AgentLogPage: React.FC = () => {
to_date: searchParams.to_date,
orderby: searchParams.orderby,
desc: searchParams.desc,
page: pagination.current,
page_size: pagination.pageSize,
});
};
return (
<div className=" text-white">
<div className=" text-text-primary">
<PageHeader>
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink onClick={navigateToAgents}>Agent</BreadcrumbLink>
<BreadcrumbLink onClick={navigateToAgents}>
{t('flow.agent')}
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
@@ -251,21 +251,21 @@ const AgentLogPage: React.FC = () => {
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Log</BreadcrumbPage>
<BreadcrumbPage>{t('flow.log')}</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</PageHeader>
<div className="p-4">
<div className="flex justify-between items-center">
<h1 className="text-2xl font-bold mb-4">Log</h1>
<h1 className="text-2xl font-bold mb-4">{t('flow.log')}</h1>
<div className="flex justify-end space-x-2 mb-4 text-foreground">
<div className="flex items-center space-x-2">
<Button onClick={onExportClick} loading={exportLoading}>
{t('flow.export')}
</Button>
<span>ID/Title</span>
<span>{`${t('flow.id')}/${t('flow.logTitle')}`}</span>
<SearchInput
value={keywords}
onChange={(e) => {
@@ -275,7 +275,7 @@ const AgentLogPage: React.FC = () => {
></SearchInput>
</div>
<div className="flex items-center space-x-2">
<span className="whitespace-nowrap">Latest Date</span>
<span className="whitespace-nowrap">{t('flow.latestDate')}</span>
<DatePickerWithRange
required
selected={currentDate}
@@ -292,14 +292,14 @@ const AgentLogPage: React.FC = () => {
handleClickSearch();
}}
>
Search
{t('common.search')}
</button>
<button
type="button"
className="bg-transparent text-foreground px-4 py-1 rounded border"
onClick={() => handleReset()}
>
Reset
{t('common.reset')}
</button>
</div>
</div>
@@ -374,7 +374,7 @@ const AgentLogPage: React.FC = () => {
colSpan={columns.length}
className="h-24 text-center"
>
No data
{t('common.noData')}
</TableCell>
</TableRow>
)}

View File

@@ -11,6 +11,8 @@ interface ISearchParams {
to_date?: Date;
orderby?: string;
desc?: boolean;
page?: number;
page_size?: number;
}
export const useExportAgentLogToCSV = () => {
@@ -58,9 +60,12 @@ export const useExportAgentLogToCSV = () => {
to_date: searchParams.to_date,
orderby: searchParams.orderby,
desc: searchParams.desc,
page: searchParams.page,
page_size: searchParams.page_size,
});
if (allData.length === 0) {
console.log('No data to export', allData);
message.warning(t('flow.noDataToExport'));
return;
}

View File

@@ -28,6 +28,7 @@ import { cn } from '@/lib/utils';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm, UseFormReturn } from 'react-hook-form';
import { z } from 'zod';
import { NICKNAME_PATTERN } from '../user-setting/profile/constants';
import { BgSvg } from './bg';
import FlipCard3D, { FlipFaceContext } from './card';
import './index.less';
@@ -253,6 +254,9 @@ const Login = () => {
const { login: loginWithChannel, loading: loginWithChannelLoading } =
useLoginWithChannel();
const { t } = useTranslation('translation', { keyPrefix: 'login' });
const { t: tSetting } = useTranslation('translation', {
keyPrefix: 'setting',
});
const [isLoginPage, setIsLoginPage] = useState(true);
const loading =
@@ -287,7 +291,7 @@ const Login = () => {
const FormSchema = z
.object({
nickname: z.string(),
nickname: z.string().optional(),
email: z
.string()
.email()
@@ -296,12 +300,21 @@ const Login = () => {
remember: z.boolean().optional(),
})
.superRefine((data, ctx) => {
if (title === 'register' && !data.nickname) {
if (title !== 'register') return;
if (!data.nickname) {
ctx.addIssue({
path: ['nickname'],
message: 'nicknamePlaceholder',
code: z.ZodIssueCode.custom,
});
return;
}
if (!NICKNAME_PATTERN.test(data.nickname)) {
ctx.addIssue({
path: ['nickname'],
message: tSetting('usernameInvalidCharacters'),
code: z.ZodIssueCode.custom,
});
}
});
type FormValues = z.infer<typeof FormSchema>;

View File

@@ -3,8 +3,10 @@
import AvatarNameDescription from '@/components/avatar-name-description';
import { KnowledgeBaseFormField } from '@/components/knowledge-base-item';
import {
LLMIdFormField,
LlmSettingEnabledSchema,
LlmSettingFieldItems,
LlmSettingSchema,
LlmSettingFieldSchema,
} from '@/components/llm-setting-items/next';
import {
MetadataFilter,
@@ -65,10 +67,7 @@ const SearchSettingFormSchema = z
use_rerank: z.boolean(),
top_k: z.number(),
summary: z.boolean(),
llm_setting: z.object({
...LlmSettingSchema,
parameter: z.string().optional(),
}),
llm_setting: z.object({ ...LlmSettingFieldSchema, ...LLMIdFormField }),
related_search: z.boolean(),
query_mindmap: z.boolean(),
doc_ids: z.array(z.string()),
@@ -84,6 +83,7 @@ const SearchSettingFormSchema = z
.optional(),
...MetadataFilterSchema,
}),
...LlmSettingEnabledSchema,
})
.superRefine((data, ctx) => {
if (data.search_config.use_rerank && !data.search_config.rerank_id) {
@@ -144,12 +144,6 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
top_p: llm_setting?.top_p || 0,
frequency_penalty: llm_setting?.frequency_penalty || 0,
presence_penalty: llm_setting?.presence_penalty || 0,
temperatureEnabled: llm_setting?.temperature ? true : false,
topPEnabled: llm_setting?.top_p ? true : false,
presencePenaltyEnabled: llm_setting?.presence_penalty ? true : false,
frequencyPenaltyEnabled: llm_setting?.frequency_penalty
? true
: false,
},
chat_settingcross_languages: [],
highlight: false,
@@ -166,6 +160,10 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
: undefined,
},
},
temperatureEnabled: llm_setting?.temperature !== undefined,
topPEnabled: llm_setting?.top_p !== undefined,
presencePenaltyEnabled: llm_setting?.presence_penalty !== undefined,
frequencyPenaltyEnabled: llm_setting?.frequency_penalty !== undefined,
});
}, [data, search_config, llm_setting, formMethods, descriptionDefaultValue]);
@@ -259,7 +257,27 @@ const SearchSetting: React.FC<SearchSettingProps> = ({
) => {
try {
setFormSubmitLoading(true);
const { search_config, ...other_formdata } = formData;
const {
search_config,
temperatureEnabled: _temperatureEnabled,
topPEnabled: _topPEnabled,
presencePenaltyEnabled: _presencePenaltyEnabled,
frequencyPenaltyEnabled: _frequencyPenaltyEnabled,
maxTokensEnabled: _maxTokensEnabled,
...other_formdata
} = formData as IUpdateSearchProps & {
tenant_id: string;
temperatureEnabled?: boolean;
topPEnabled?: boolean;
presencePenaltyEnabled?: boolean;
frequencyPenaltyEnabled?: boolean;
maxTokensEnabled?: boolean;
};
void _temperatureEnabled;
void _topPEnabled;
void _presencePenaltyEnabled;
void _frequencyPenaltyEnabled;
void _maxTokensEnabled;
const {
llm_setting,
vector_similarity_weight,