fix: P0+P1 security and quality fixes

P0-1: Token refresh race condition — reject all pending requests on refresh failure
P0-2: Remove X-Forwarded-For trust in rate limiting — use only ConnectInfo IP
P1-3: Template grid reactive — use useSaaSStore() hook instead of getState()
P1-4: Agent Template detail modal — show emoji, personality, soul_content, welcome_message,
      communication_style, source_id, scenarios, version
P1-5: adminRouting parse validation — type-safe llm_routing extraction from localStorage
P1-6: Remove unused @ant-design/charts dependency
P1-extra: Type addKeyMutation data parameter (replace any)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
iven
2026-03-31 09:17:04 +08:00
parent 49abd0fe89
commit 1d9283f335
7 changed files with 79 additions and 1401 deletions

View File

@@ -188,18 +188,38 @@ export default function AgentTemplates() {
>
{detailRecord && (
<Descriptions column={2} bordered size="small">
<Descriptions.Item label="图标">{detailRecord.emoji || '-'}</Descriptions.Item>
<Descriptions.Item label="名称">{detailRecord.name}</Descriptions.Item>
<Descriptions.Item label="分类">{detailRecord.category}</Descriptions.Item>
<Descriptions.Item label="模型">{detailRecord.model || '-'}</Descriptions.Item>
<Descriptions.Item label="来源">{sourceLabels[detailRecord.source]}</Descriptions.Item>
<Descriptions.Item label="可见性">{visibilityLabels[detailRecord.visibility]}</Descriptions.Item>
<Descriptions.Item label="状态">{statusLabels[detailRecord.status]}</Descriptions.Item>
<Descriptions.Item label="版本">{detailRecord.version ?? detailRecord.current_version}</Descriptions.Item>
<Descriptions.Item label="描述" span={2}>{detailRecord.description || '-'}</Descriptions.Item>
<Descriptions.Item label="人格预设">{detailRecord.personality || '-'}</Descriptions.Item>
<Descriptions.Item label="沟通风格">{detailRecord.communication_style || '-'}</Descriptions.Item>
<Descriptions.Item label="模板标识" span={2}>{detailRecord.source_id || '-'}</Descriptions.Item>
{detailRecord.welcome_message && (
<Descriptions.Item label="欢迎语" span={2}>{detailRecord.welcome_message}</Descriptions.Item>
)}
{detailRecord.scenarios && detailRecord.scenarios.length > 0 && (
<Descriptions.Item label="使用场景" span={2}>
{detailRecord.scenarios.map((s) => <Tag key={s}>{s}</Tag>)}
</Descriptions.Item>
)}
<Descriptions.Item label="系统提示词" span={2}>
<div style={{ whiteSpace: 'pre-wrap', maxHeight: 200, overflow: 'auto' }}>
{detailRecord.system_prompt || '-'}
</div>
</Descriptions.Item>
{detailRecord.soul_content && (
<Descriptions.Item label="SOUL.md 人格配置" span={2}>
<div style={{ whiteSpace: 'pre-wrap', maxHeight: 200, overflow: 'auto' }}>
{detailRecord.soul_content}
</div>
</Descriptions.Item>
)}
<Descriptions.Item label="工具" span={2}>
{detailRecord.tools?.map((t) => <Tag key={t}>{t}</Tag>) || '-'}
</Descriptions.Item>

View File

@@ -66,7 +66,7 @@ export default function Providers() {
})
const addKeyMutation = useMutation({
mutationFn: ({ providerId, data }: { providerId: string; data: any }) =>
mutationFn: ({ providerId, data }: { providerId: string; data: { key_label: string; key_value: string; priority?: number; max_rpm?: number; max_tpm?: number } }) =>
providerService.addKey(providerId, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['provider-keys', keyModalProviderId] })