Commit d765359f authored by IanShaw027's avatar IanShaw027
Browse files

test(admin): 增加messages调度表单状态转换测试

parent 4de4823a
...@@ -366,6 +366,13 @@ export type GroupPlatform = 'anthropic' | 'openai' | 'gemini' | 'antigravity' ...@@ -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 { ...@@ -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 { ...@@ -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
......
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: [],
});
});
});
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 = [];
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment