test(admin): 增加messages调度表单状态转换测试
This commit is contained in:
@@ -366,6 +366,13 @@ export type GroupPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity'
|
|||||||
|
|
||||||
export type SubscriptionType = 'standard' | 'subscription'
|
export type SubscriptionType = 'standard' | 'subscription'
|
||||||
|
|
||||||
|
export interface OpenAIMessagesDispatchModelConfig {
|
||||||
|
opus_mapped_model?: string
|
||||||
|
sonnet_mapped_model?: string
|
||||||
|
haiku_mapped_model?: string
|
||||||
|
exact_model_mappings?: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
export interface Group {
|
export interface Group {
|
||||||
id: number
|
id: number
|
||||||
name: string
|
name: string
|
||||||
@@ -388,6 +395,8 @@ export interface Group {
|
|||||||
fallback_group_id_on_invalid_request: number | null
|
fallback_group_id_on_invalid_request: number | null
|
||||||
// OpenAI Messages 调度开关(用户侧需要此字段判断是否展示 Claude Code 教程)
|
// OpenAI Messages 调度开关(用户侧需要此字段判断是否展示 Claude Code 教程)
|
||||||
allow_messages_dispatch?: boolean
|
allow_messages_dispatch?: boolean
|
||||||
|
default_mapped_model?: string
|
||||||
|
messages_dispatch_model_config?: OpenAIMessagesDispatchModelConfig
|
||||||
require_oauth_only: boolean
|
require_oauth_only: boolean
|
||||||
require_privacy_set: boolean
|
require_privacy_set: boolean
|
||||||
created_at: string
|
created_at: string
|
||||||
@@ -414,6 +423,7 @@ export interface AdminGroup extends Group {
|
|||||||
|
|
||||||
// OpenAI Messages 调度配置(仅 openai 平台使用)
|
// OpenAI Messages 调度配置(仅 openai 平台使用)
|
||||||
default_mapped_model?: string
|
default_mapped_model?: string
|
||||||
|
messages_dispatch_model_config?: OpenAIMessagesDispatchModelConfig
|
||||||
|
|
||||||
// 分组排序
|
// 分组排序
|
||||||
sort_order: number
|
sort_order: number
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createDefaultMessagesDispatchFormState,
|
||||||
|
messagesDispatchConfigToFormState,
|
||||||
|
messagesDispatchFormStateToConfig,
|
||||||
|
resetMessagesDispatchFormState,
|
||||||
|
} from "../groupsMessagesDispatch";
|
||||||
|
|
||||||
|
describe("groupsMessagesDispatch", () => {
|
||||||
|
it("returns the expected default form state", () => {
|
||||||
|
expect(createDefaultMessagesDispatchFormState()).toEqual({
|
||||||
|
allow_messages_dispatch: false,
|
||||||
|
opus_mapped_model: "gpt-5.4",
|
||||||
|
sonnet_mapped_model: "gpt-5.3-codex",
|
||||||
|
haiku_mapped_model: "gpt-5.4-mini",
|
||||||
|
exact_model_mappings: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sanitizes exact model mapping rows when converting to config", () => {
|
||||||
|
const config = messagesDispatchFormStateToConfig({
|
||||||
|
allow_messages_dispatch: true,
|
||||||
|
opus_mapped_model: " gpt-5.4 ",
|
||||||
|
sonnet_mapped_model: "gpt-5.3-codex",
|
||||||
|
haiku_mapped_model: " gpt-5.4-mini ",
|
||||||
|
exact_model_mappings: [
|
||||||
|
{
|
||||||
|
claude_model: " claude-sonnet-4-5-20250929 ",
|
||||||
|
target_model: " gpt-5.2 ",
|
||||||
|
},
|
||||||
|
{ claude_model: "", target_model: "gpt-5.4" },
|
||||||
|
{ claude_model: "claude-opus-4-6", target_model: " " },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(config).toEqual({
|
||||||
|
opus_mapped_model: "gpt-5.4",
|
||||||
|
sonnet_mapped_model: "gpt-5.3-codex",
|
||||||
|
haiku_mapped_model: "gpt-5.4-mini",
|
||||||
|
exact_model_mappings: {
|
||||||
|
"claude-sonnet-4-5-20250929": "gpt-5.2",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("hydrates form state from api config", () => {
|
||||||
|
expect(
|
||||||
|
messagesDispatchConfigToFormState({
|
||||||
|
opus_mapped_model: "gpt-5.4",
|
||||||
|
sonnet_mapped_model: "gpt-5.2",
|
||||||
|
haiku_mapped_model: "gpt-5.4-mini",
|
||||||
|
exact_model_mappings: {
|
||||||
|
"claude-opus-4-6": "gpt-5.4",
|
||||||
|
"claude-haiku-4-5-20251001": "gpt-5.4-mini",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
).toEqual({
|
||||||
|
allow_messages_dispatch: false,
|
||||||
|
opus_mapped_model: "gpt-5.4",
|
||||||
|
sonnet_mapped_model: "gpt-5.2",
|
||||||
|
haiku_mapped_model: "gpt-5.4-mini",
|
||||||
|
exact_model_mappings: [
|
||||||
|
{
|
||||||
|
claude_model: "claude-haiku-4-5-20251001",
|
||||||
|
target_model: "gpt-5.4-mini",
|
||||||
|
},
|
||||||
|
{ claude_model: "claude-opus-4-6", target_model: "gpt-5.4" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("resets mutable form state when platform switches away from openai", () => {
|
||||||
|
const state = {
|
||||||
|
allow_messages_dispatch: true,
|
||||||
|
opus_mapped_model: "gpt-5.2",
|
||||||
|
sonnet_mapped_model: "gpt-5.4",
|
||||||
|
haiku_mapped_model: "gpt-5.1",
|
||||||
|
exact_model_mappings: [
|
||||||
|
{ claude_model: "claude-opus-4-6", target_model: "gpt-5.4" },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
resetMessagesDispatchFormState(state);
|
||||||
|
|
||||||
|
expect(state).toEqual({
|
||||||
|
allow_messages_dispatch: false,
|
||||||
|
opus_mapped_model: "gpt-5.4",
|
||||||
|
sonnet_mapped_model: "gpt-5.3-codex",
|
||||||
|
haiku_mapped_model: "gpt-5.4-mini",
|
||||||
|
exact_model_mappings: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
72
frontend/src/views/admin/groupsMessagesDispatch.ts
Normal file
72
frontend/src/views/admin/groupsMessagesDispatch.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import type { OpenAIMessagesDispatchModelConfig } from "@/types";
|
||||||
|
|
||||||
|
export interface MessagesDispatchMappingRow {
|
||||||
|
claude_model: string;
|
||||||
|
target_model: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MessagesDispatchFormState {
|
||||||
|
allow_messages_dispatch: boolean;
|
||||||
|
opus_mapped_model: string;
|
||||||
|
sonnet_mapped_model: string;
|
||||||
|
haiku_mapped_model: string;
|
||||||
|
exact_model_mappings: MessagesDispatchMappingRow[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createDefaultMessagesDispatchFormState(): MessagesDispatchFormState {
|
||||||
|
return {
|
||||||
|
allow_messages_dispatch: false,
|
||||||
|
opus_mapped_model: "gpt-5.4",
|
||||||
|
sonnet_mapped_model: "gpt-5.3-codex",
|
||||||
|
haiku_mapped_model: "gpt-5.4-mini",
|
||||||
|
exact_model_mappings: [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function messagesDispatchConfigToFormState(
|
||||||
|
config?: OpenAIMessagesDispatchModelConfig | null,
|
||||||
|
): MessagesDispatchFormState {
|
||||||
|
const defaults = createDefaultMessagesDispatchFormState();
|
||||||
|
const exactMappings = Object.entries(config?.exact_model_mappings || {})
|
||||||
|
.sort(([left], [right]) => left.localeCompare(right))
|
||||||
|
.map(([claude_model, target_model]) => ({ claude_model, target_model }));
|
||||||
|
|
||||||
|
return {
|
||||||
|
allow_messages_dispatch: false,
|
||||||
|
opus_mapped_model:
|
||||||
|
config?.opus_mapped_model?.trim() || defaults.opus_mapped_model,
|
||||||
|
sonnet_mapped_model:
|
||||||
|
config?.sonnet_mapped_model?.trim() || defaults.sonnet_mapped_model,
|
||||||
|
haiku_mapped_model:
|
||||||
|
config?.haiku_mapped_model?.trim() || defaults.haiku_mapped_model,
|
||||||
|
exact_model_mappings: exactMappings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function messagesDispatchFormStateToConfig(
|
||||||
|
state: MessagesDispatchFormState,
|
||||||
|
): OpenAIMessagesDispatchModelConfig {
|
||||||
|
const exactModelMappings = Object.fromEntries(
|
||||||
|
state.exact_model_mappings
|
||||||
|
.map((row) => [row.claude_model.trim(), row.target_model.trim()] as const)
|
||||||
|
.filter(([claudeModel, targetModel]) => claudeModel && targetModel),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
opus_mapped_model: state.opus_mapped_model.trim(),
|
||||||
|
sonnet_mapped_model: state.sonnet_mapped_model.trim(),
|
||||||
|
haiku_mapped_model: state.haiku_mapped_model.trim(),
|
||||||
|
exact_model_mappings: exactModelMappings,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resetMessagesDispatchFormState(
|
||||||
|
target: MessagesDispatchFormState,
|
||||||
|
): void {
|
||||||
|
const defaults = createDefaultMessagesDispatchFormState();
|
||||||
|
target.allow_messages_dispatch = defaults.allow_messages_dispatch;
|
||||||
|
target.opus_mapped_model = defaults.opus_mapped_model;
|
||||||
|
target.sonnet_mapped_model = defaults.sonnet_mapped_model;
|
||||||
|
target.haiku_mapped_model = defaults.haiku_mapped_model;
|
||||||
|
target.exact_model_mappings = [];
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user