|
|
@@ -192,6 +192,36 @@ const parseOptionalObjectJson = (jsonString, label) => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+const buildChannelAffinityRulePayload = ({
|
|
|
+ values,
|
|
|
+ isEdit,
|
|
|
+ editingRuleId,
|
|
|
+ rulesLength,
|
|
|
+ modelRegex,
|
|
|
+ pathRegex,
|
|
|
+ keySources,
|
|
|
+ userAgentInclude,
|
|
|
+ paramOverrideTemplate,
|
|
|
+}) => ({
|
|
|
+ id: isEdit ? editingRuleId : rulesLength,
|
|
|
+ name: (values?.name || '').trim(),
|
|
|
+ model_regex: modelRegex,
|
|
|
+ path_regex: pathRegex,
|
|
|
+ key_sources: keySources,
|
|
|
+ value_regex: (values?.value_regex || '').trim(),
|
|
|
+ ttl_seconds: Number(values?.ttl_seconds || 0),
|
|
|
+ include_using_group: !!values?.include_using_group,
|
|
|
+ include_model_name: !!values?.include_model_name,
|
|
|
+ include_rule_name: !!values?.include_rule_name,
|
|
|
+ skip_retry_on_failure: !!values?.skip_retry_on_failure,
|
|
|
+ ...(userAgentInclude.length > 0
|
|
|
+ ? { user_agent_include: userAgentInclude }
|
|
|
+ : {}),
|
|
|
+ ...(paramOverrideTemplate
|
|
|
+ ? { param_override_template: paramOverrideTemplate }
|
|
|
+ : {}),
|
|
|
+});
|
|
|
+
|
|
|
export default function SettingsChannelAffinity(props) {
|
|
|
const { t } = useTranslation();
|
|
|
const { Text } = Typography;
|
|
|
@@ -456,14 +486,12 @@ export default function SettingsChannelAffinity(props) {
|
|
|
const templates = [
|
|
|
CHANNEL_AFFINITY_RULE_TEMPLATES.codexCli,
|
|
|
CHANNEL_AFFINITY_RULE_TEMPLATES.claudeCli,
|
|
|
- ].map(
|
|
|
- (tpl) => {
|
|
|
- const baseTemplate = cloneChannelAffinityTemplate(tpl);
|
|
|
- const name = makeUniqueName(existingNames, tpl.name);
|
|
|
- existingNames.add(name);
|
|
|
- return { ...baseTemplate, name };
|
|
|
- },
|
|
|
- );
|
|
|
+ ].map((tpl) => {
|
|
|
+ const baseTemplate = cloneChannelAffinityTemplate(tpl);
|
|
|
+ const name = makeUniqueName(existingNames, tpl.name);
|
|
|
+ existingNames.add(name);
|
|
|
+ return { ...baseTemplate, name };
|
|
|
+ });
|
|
|
|
|
|
const next = [...(rules || []), ...templates].map((r, idx) => ({
|
|
|
...(r || {}),
|
|
|
@@ -716,27 +744,17 @@ export default function SettingsChannelAffinity(props) {
|
|
|
return showError(t(paramTemplateValidation.message));
|
|
|
}
|
|
|
|
|
|
- const rulePayload = {
|
|
|
- id: isEdit ? editingRule.id : rules.length,
|
|
|
- name: (values.name || '').trim(),
|
|
|
- model_regex: modelRegex,
|
|
|
- path_regex: normalizeStringList(values.path_regex_text),
|
|
|
- key_sources: keySourcesValidation.value,
|
|
|
- value_regex: (values.value_regex || '').trim(),
|
|
|
- ttl_seconds: Number(values.ttl_seconds || 0),
|
|
|
- include_using_group: !!values.include_using_group,
|
|
|
- include_model_name: !!values.include_model_name,
|
|
|
- include_rule_name: !!values.include_rule_name,
|
|
|
- ...(values.skip_retry_on_failure
|
|
|
- ? { skip_retry_on_failure: true }
|
|
|
- : {}),
|
|
|
- ...(userAgentInclude.length > 0
|
|
|
- ? { user_agent_include: userAgentInclude }
|
|
|
- : {}),
|
|
|
- ...(paramTemplateValidation.value
|
|
|
- ? { param_override_template: paramTemplateValidation.value }
|
|
|
- : {}),
|
|
|
- };
|
|
|
+ const rulePayload = buildChannelAffinityRulePayload({
|
|
|
+ values,
|
|
|
+ isEdit,
|
|
|
+ editingRuleId: editingRule?.id,
|
|
|
+ rulesLength: rules.length,
|
|
|
+ modelRegex,
|
|
|
+ pathRegex: normalizeStringList(values.path_regex_text),
|
|
|
+ keySources: keySourcesValidation.value,
|
|
|
+ userAgentInclude,
|
|
|
+ paramOverrideTemplate: paramTemplateValidation.value,
|
|
|
+ });
|
|
|
|
|
|
if (!rulePayload.name) return showError(t('名称不能为空'));
|
|
|
|
|
|
@@ -1273,9 +1291,7 @@ export default function SettingsChannelAffinity(props) {
|
|
|
label={t('作用域:包含模型名称')}
|
|
|
/>
|
|
|
<Text type='tertiary' size='small'>
|
|
|
- {t(
|
|
|
- '开启后,模型名称会参与 cache key(不同模型隔离)。',
|
|
|
- )}
|
|
|
+ {t('开启后,模型名称会参与 cache key(不同模型隔离)。')}
|
|
|
</Text>
|
|
|
</Col>
|
|
|
<Col xs={24} sm={8}>
|