Files

1 line
27 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{"repo": "aiqinxuancai/aria2fast", "files": {"Aria2Fast/Service/AiProtocolType.cs": {"05c4bca24e45972e0b7f6e8f01451b213f469a82": {"t": 1785746188.8558493, "n": 12477, "h": "1a5017e0c46ad8ba", "c": "using System;\nusing System.Collections.Generic;\n\nnamespace Aria2Fast.Service\n{\n /// <summary>\n /// AI 接口协议类型\n /// </summary>\n public enum AiProtocolType\n {\n /// <summary>\n /// OpenAI Chat Completions (/v1/chat/completions),兼容绝大多数中转/第三方服务,支持函数调用\n /// </summary>\n OpenAIChatCompletions,\n\n /// <summary>\n /// OpenAI Responses (/v1/responses)\n /// </summary>\n OpenAIResponses,\n\n /// <summary>\n /// Anthropic Claude (Messages API, /v1/messages)\n /// </summary>\n Claude,\n\n /// <summary>\n /// Google Gemini (generateContent)\n /// </summary>\n Gemini\n }\n\n /// <summary>\n /// 协议相关的元数据与 URL 组合逻辑\n /// </summary>\n public static class AiProtocol\n {\n public sealed class ProtocolOption\n {\n public AiProtocolType Type { get; init; }\n public string DisplayName { get; init; } = string.Empty;\n public string DefaultBaseUrl { get; init; } = string.Empty;\n public string DefaultModel { get; init; } = string.Empty;\n }\n\n /// <summary>\n /// 协议下拉框选项(顺序即展示顺序)\n /// </summary>\n public static IReadOnlyList<ProtocolOption> Options { get; } = new[]\n {\n new ProtocolOption\n {\n Type = AiProtocolType.OpenAIChatCompletions,\n DisplayName = \"OpenAI - Chat Completions\",\n DefaultBaseUrl = \"https://api.openai.com\",\n DefaultModel = \"gpt-5.5\"\n },\n new ProtocolOption\n {\n Type = AiProtocolType.OpenAIResponses,\n DisplayName = \"OpenAI - Responses\",\n DefaultBaseUrl = \"https://api.openai.com\",\n DefaultModel = \"gpt-5.5\"\n },\n new ProtocolOption\n {\n Type = AiProtocolType.Claude,\n DisplayName = \"Claude (Anthropic)\",\n DefaultBaseUrl = \"https://api.anthropic.com\",\n DefaultModel = \"claude-sonnet-4-6\"\n },\n new ProtocolOption\n {\n Type = AiProtocolType.Gemini,\n DisplayName = \"Gemini (Google)\",\n DefaultBaseUrl = \"https://generativelanguage.googleapis.com\",\n DefaultModel = \"gemini-3-flash-preview\"\n }\n };\n\n public static string GetDisplayName(AiProtocolType type)\n {\n foreach (var option in Options)\n {\n if (option.Type == type)\n {\n return option.DisplayName;\n }\n }\n return type.ToString();\n }\n\n public static ProtocolOption GetOption(AiProtocolType type)\n {\n foreach (var option in Options)\n {\n if (option.Type == type)\n {\n return option;\n }\n }\n return Options[0];\n }\n\n /// <summary>\n /// 预设平台配置(用于模态弹窗一键填入)\n /// </summary>\n public sealed class Preset\n {\n public string DisplayName { get; init; } = string.Empty;\n public AiProtocolType Protocol { get; init; }\n public string BaseUrl { get; init; } = string.Empty;\n public string ModelName { get; init; } = string.Empty;\n }\n\n /// <summary>\n /// 主流平台预设(含各家最新主流模型与官方地址,数据截至 2026-06)\n /// </summary>\n public static IReadOnlyList<Preset> Presets { get; } = new[]\n {\n new Preset\n {\n DisplayName = \"DeepSeek - deepseek-v4-flash\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.deepseek.com\",\n ModelName = \"deepseek-v4-flash\"\n },\n new Preset\n {\n DisplayName = \"DeepSeek - deepseek-v4-pro\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.deepseek.com\",\n ModelName = \"deepseek-v4-pro\"\n },\n new Preset\n {\n DisplayName = \"通义千问 Qwen - qwen3-max\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n ModelName = \"qwen3-max\"\n },\n new Preset\n {\n DisplayName = \"通义千问 Qwen - qwen-plus\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n ModelName = \"qwen-plus\"\n },\n new Preset\n {\n DisplayName = \"智谱 GLM - glm-4.6\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://open.bigmodel.cn/api/paas/v4\",\n ModelName = \"glm-4.6\"\n },\n new Preset\n {\n DisplayName = \"智谱 GLM - glm-4.7-flash\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://open.bigmodel.cn/api/paas/v4\",\n ModelName = \"glm-4.7-flash\"\n },\n new Preset\n {\n DisplayName = \"MiniMax - MiniMax-M2.1\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.minimaxi.com/v1\",\n ModelName = \"MiniMax-M2.1\"\n },\n new Preset\n {\n DisplayName = \"Kimi (Moonshot) - kimi-k2.6\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.moonshot.cn/v1\",\n ModelName = \"kimi-k2.6\"\n },\n new Preset\n {\n DisplayName = \"火山方舟 Doubao - doubao-seed-1.6\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://ark.cn-beijing.volces.com/api/v3\",\n ModelName = \"doubao-seed-1-6-250615\"\n },\n new Preset\n {\n DisplayName = \"OpenAI - gpt-5.5\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.openai.com\",\n ModelName = \"gpt-5.5\"\n },\n new Preset\n {\n DisplayName = \"OpenAI - gpt-4o-mini\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.openai.com\",\n ModelName = \"gpt-4o-mini\"\n },\n new Preset\n {\n DisplayName = \"Claude - claude-opus-4-8\",\n Protocol = AiProtocolType.Claude,\n BaseUrl = \"https://api.anthropic.com\",\n ModelName = \"claude-opus-4-8\"\n },\n new Preset\n {\n DisplayName = \"Claude - claude-sonnet-4-6\",\n Protocol = AiProtocolType.Claude,\n BaseUrl = \"https://api.anthropic.com\",\n ModelName = \"claude-sonnet-4-6\"\n },\n new Preset\n {\n DisplayName = \"Gemini - gemini-3-flash-preview\",\n Protocol = AiProtocolType.Gemini,\n BaseUrl = \"https://generativelanguage.googleapis.com\",\n ModelName = \"gemini-3-flash-preview\"\n },\n new Preset\n {\n DisplayName = \"Gemini - gemini-3-pro-preview\",\n Protocol = AiProtocolType.Gemini,\n BaseUrl = \"https://generativelanguage.googleapis.com\",\n ModelName = \"gemini-3-pro-preview\"\n },\n new Preset\n {\n DisplayName = \"Gemini - gemini-2.5-flash(稳定)\",\n Protocol = AiProtocolType.Gemini,\n BaseUrl = \"https://generativelanguage.googleapis.com\",\n ModelName = \"gemini-2.5-flash\"\n },\n new Preset\n {\n DisplayName = \"OpenRouter - deepseek-v4\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://openrouter.ai/api/v1\",\n ModelName = \"deepseek/deepseek-v4\"\n },\n new Preset\n {\n DisplayName = \"硅基流动 SiliconFlow - DeepSeek-V3.2\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.siliconflow.cn/v1\",\n ModelName = \"deepseek-ai/DeepSeek-V3.2-Exp\"\n },\n new Preset\n {\n DisplayName = \"Aihubmix(中转)- gpt-5.5\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://aihubmix.com\",\n ModelName = \"gpt-5.5\"\n }\n };\n\n /// <summary>\n /// 去掉结尾的 \"/\",并补全协议头\n /// </summary>\n public static string NormalizeBaseUrl(string baseUrl)\n {\n var url = (baseUrl ?? string.Empty).Trim();\n if (string.IsNullOrEmpty(url))\n {\n return string.Empty;\n }\n\n if (!url.StartsWith(\"http://\", StringComparison.OrdinalIgnoreCase)\n && !url.StartsWith(\"https://\", StringComparison.OrdinalIgnoreCase))\n {\n url = \"https://\" + url;\n }\n\n return url.TrimEnd('/');\n }\n\n /// <summary>\n /// 根据协议类型与 baseUrl、模型名,组合出真实的请求地址(用于界面预览与实际请求)\n /// </summary>\n public static string BuildRequestUrl(AiProtocolType type, string baseUrl, string model)\n {\n var root = NormalizeBaseUrl(baseUrl);\n if (string.IsNullOrEmpty(root))\n {\n return string.Empty;\n }\n\n switch (type)\n {\n case AiProtocolType.OpenAIChatCompletions:\n return CombineOpenAiPath(root, \"chat/completions\");\n case AiProtocolType.OpenAIResponses:\n return CombineOpenAiPath(root, \"responses\");\n case AiProtocolType.Claude:\n return CombineClaudePath(root);\n case AiProtocolType.Gemini:\n var modelName = string.IsNullOrWhiteSpace(model) ? \"{model}\" : model.Trim();\n return CombineGeminiPath(root, modelName);\n default:\n return root;\n }\n }\n\n /// <summary>\n /// OpenAI 协议:若 baseUrl 未包含版本段(/v1 等),自动补 /v1\n /// </summary>\n private static string CombineOpenAiPath(string root, string suffix)\n {\n if (EndsWithVersionSegment(root))\n {\n return $\"{root}/{suffix}\";\n }\n return $\"{root}/v1/{suffix}\";\n }\n\n private static string CombineClaudePath(string root)\n {\n if (EndsWithVersionSegment(root))\n {\n return $\"{root}/messages\";\n }\n return $\"{root}/v1/messages\";\n }\n\n private static string CombineGeminiPath(string root, string model)\n {\n // 形如 https://host/v1beta/models/{model}:generateContent\n if (root.EndsWith(\"/v1beta\", StringComparison.OrdinalIgnoreCase)\n || root.EndsWith(\"/v1\", StringComparison.OrdinalIgnoreCase))\n {\n return $\"{root}/models/{model}:generateContent\";\n }\n return $\"{root}/v1beta/models/{model}:generateContent\";\n }\n\n /// <summary>\n /// 判断 baseUrl 是否已经以版本段结尾(避免重复拼接 /v1)\n /// </summary>\n private static bool EndsWithVersionSegment(string root)\n {\n var lastSegment = root;\n var slashIndex = root.LastIndexOf('/');\n if (slashIndex >= 0 && slashIndex < root.Length - 1)\n {\n lastSegment = root.Substring(slashIndex + 1);\n }\n\n if (string.IsNullOrEmpty(lastSegment))\n {\n return false;\n }\n\n // v1, v1beta, v2, beta 等\n if (lastSegment.StartsWith(\"v\", StringComparison.OrdinalIgnoreCase)\n && lastSegment.Length > 1\n && char.IsDigit(lastSegment[1]))\n {\n return true;\n }\n\n return lastSegment.Equals(\"beta\", StringComparison.OrdinalIgnoreCase);\n }\n }\n}\n"}, "cba1d8c712e4355a9205db444a90d75b67e590cb": {"t": 1785760465.3672872, "n": 12477, "h": "1a5017e0c46ad8ba", "c": "using System;\nusing System.Collections.Generic;\n\nnamespace Aria2Fast.Service\n{\n /// <summary>\n /// AI 接口协议类型\n /// </summary>\n public enum AiProtocolType\n {\n /// <summary>\n /// OpenAI Chat Completions (/v1/chat/completions),兼容绝大多数中转/第三方服务,支持函数调用\n /// </summary>\n OpenAIChatCompletions,\n\n /// <summary>\n /// OpenAI Responses (/v1/responses)\n /// </summary>\n OpenAIResponses,\n\n /// <summary>\n /// Anthropic Claude (Messages API, /v1/messages)\n /// </summary>\n Claude,\n\n /// <summary>\n /// Google Gemini (generateContent)\n /// </summary>\n Gemini\n }\n\n /// <summary>\n /// 协议相关的元数据与 URL 组合逻辑\n /// </summary>\n public static class AiProtocol\n {\n public sealed class ProtocolOption\n {\n public AiProtocolType Type { get; init; }\n public string DisplayName { get; init; } = string.Empty;\n public string DefaultBaseUrl { get; init; } = string.Empty;\n public string DefaultModel { get; init; } = string.Empty;\n }\n\n /// <summary>\n /// 协议下拉框选项(顺序即展示顺序)\n /// </summary>\n public static IReadOnlyList<ProtocolOption> Options { get; } = new[]\n {\n new ProtocolOption\n {\n Type = AiProtocolType.OpenAIChatCompletions,\n DisplayName = \"OpenAI - Chat Completions\",\n DefaultBaseUrl = \"https://api.openai.com\",\n DefaultModel = \"gpt-5.5\"\n },\n new ProtocolOption\n {\n Type = AiProtocolType.OpenAIResponses,\n DisplayName = \"OpenAI - Responses\",\n DefaultBaseUrl = \"https://api.openai.com\",\n DefaultModel = \"gpt-5.5\"\n },\n new ProtocolOption\n {\n Type = AiProtocolType.Claude,\n DisplayName = \"Claude (Anthropic)\",\n DefaultBaseUrl = \"https://api.anthropic.com\",\n DefaultModel = \"claude-sonnet-4-6\"\n },\n new ProtocolOption\n {\n Type = AiProtocolType.Gemini,\n DisplayName = \"Gemini (Google)\",\n DefaultBaseUrl = \"https://generativelanguage.googleapis.com\",\n DefaultModel = \"gemini-3-flash-preview\"\n }\n };\n\n public static string GetDisplayName(AiProtocolType type)\n {\n foreach (var option in Options)\n {\n if (option.Type == type)\n {\n return option.DisplayName;\n }\n }\n return type.ToString();\n }\n\n public static ProtocolOption GetOption(AiProtocolType type)\n {\n foreach (var option in Options)\n {\n if (option.Type == type)\n {\n return option;\n }\n }\n return Options[0];\n }\n\n /// <summary>\n /// 预设平台配置(用于模态弹窗一键填入)\n /// </summary>\n public sealed class Preset\n {\n public string DisplayName { get; init; } = string.Empty;\n public AiProtocolType Protocol { get; init; }\n public string BaseUrl { get; init; } = string.Empty;\n public string ModelName { get; init; } = string.Empty;\n }\n\n /// <summary>\n /// 主流平台预设(含各家最新主流模型与官方地址,数据截至 2026-06)\n /// </summary>\n public static IReadOnlyList<Preset> Presets { get; } = new[]\n {\n new Preset\n {\n DisplayName = \"DeepSeek - deepseek-v4-flash\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.deepseek.com\",\n ModelName = \"deepseek-v4-flash\"\n },\n new Preset\n {\n DisplayName = \"DeepSeek - deepseek-v4-pro\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.deepseek.com\",\n ModelName = \"deepseek-v4-pro\"\n },\n new Preset\n {\n DisplayName = \"通义千问 Qwen - qwen3-max\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n ModelName = \"qwen3-max\"\n },\n new Preset\n {\n DisplayName = \"通义千问 Qwen - qwen-plus\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://dashscope.aliyuncs.com/compatible-mode/v1\",\n ModelName = \"qwen-plus\"\n },\n new Preset\n {\n DisplayName = \"智谱 GLM - glm-4.6\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://open.bigmodel.cn/api/paas/v4\",\n ModelName = \"glm-4.6\"\n },\n new Preset\n {\n DisplayName = \"智谱 GLM - glm-4.7-flash\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://open.bigmodel.cn/api/paas/v4\",\n ModelName = \"glm-4.7-flash\"\n },\n new Preset\n {\n DisplayName = \"MiniMax - MiniMax-M2.1\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.minimaxi.com/v1\",\n ModelName = \"MiniMax-M2.1\"\n },\n new Preset\n {\n DisplayName = \"Kimi (Moonshot) - kimi-k2.6\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.moonshot.cn/v1\",\n ModelName = \"kimi-k2.6\"\n },\n new Preset\n {\n DisplayName = \"火山方舟 Doubao - doubao-seed-1.6\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://ark.cn-beijing.volces.com/api/v3\",\n ModelName = \"doubao-seed-1-6-250615\"\n },\n new Preset\n {\n DisplayName = \"OpenAI - gpt-5.5\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.openai.com\",\n ModelName = \"gpt-5.5\"\n },\n new Preset\n {\n DisplayName = \"OpenAI - gpt-4o-mini\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.openai.com\",\n ModelName = \"gpt-4o-mini\"\n },\n new Preset\n {\n DisplayName = \"Claude - claude-opus-4-8\",\n Protocol = AiProtocolType.Claude,\n BaseUrl = \"https://api.anthropic.com\",\n ModelName = \"claude-opus-4-8\"\n },\n new Preset\n {\n DisplayName = \"Claude - claude-sonnet-4-6\",\n Protocol = AiProtocolType.Claude,\n BaseUrl = \"https://api.anthropic.com\",\n ModelName = \"claude-sonnet-4-6\"\n },\n new Preset\n {\n DisplayName = \"Gemini - gemini-3-flash-preview\",\n Protocol = AiProtocolType.Gemini,\n BaseUrl = \"https://generativelanguage.googleapis.com\",\n ModelName = \"gemini-3-flash-preview\"\n },\n new Preset\n {\n DisplayName = \"Gemini - gemini-3-pro-preview\",\n Protocol = AiProtocolType.Gemini,\n BaseUrl = \"https://generativelanguage.googleapis.com\",\n ModelName = \"gemini-3-pro-preview\"\n },\n new Preset\n {\n DisplayName = \"Gemini - gemini-2.5-flash(稳定)\",\n Protocol = AiProtocolType.Gemini,\n BaseUrl = \"https://generativelanguage.googleapis.com\",\n ModelName = \"gemini-2.5-flash\"\n },\n new Preset\n {\n DisplayName = \"OpenRouter - deepseek-v4\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://openrouter.ai/api/v1\",\n ModelName = \"deepseek/deepseek-v4\"\n },\n new Preset\n {\n DisplayName = \"硅基流动 SiliconFlow - DeepSeek-V3.2\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://api.siliconflow.cn/v1\",\n ModelName = \"deepseek-ai/DeepSeek-V3.2-Exp\"\n },\n new Preset\n {\n DisplayName = \"Aihubmix(中转)- gpt-5.5\",\n Protocol = AiProtocolType.OpenAIChatCompletions,\n BaseUrl = \"https://aihubmix.com\",\n ModelName = \"gpt-5.5\"\n }\n };\n\n /// <summary>\n /// 去掉结尾的 \"/\",并补全协议头\n /// </summary>\n public static string NormalizeBaseUrl(string baseUrl)\n {\n var url = (baseUrl ?? string.Empty).Trim();\n if (string.IsNullOrEmpty(url))\n {\n return string.Empty;\n }\n\n if (!url.StartsWith(\"http://\", StringComparison.OrdinalIgnoreCase)\n && !url.StartsWith(\"https://\", StringComparison.OrdinalIgnoreCase))\n {\n url = \"https://\" + url;\n }\n\n return url.TrimEnd('/');\n }\n\n /// <summary>\n /// 根据协议类型与 baseUrl、模型名,组合出真实的请求地址(用于界面预览与实际请求)\n /// </summary>\n public static string BuildRequestUrl(AiProtocolType type, string baseUrl, string model)\n {\n var root = NormalizeBaseUrl(baseUrl);\n if (string.IsNullOrEmpty(root))\n {\n return string.Empty;\n }\n\n switch (type)\n {\n case AiProtocolType.OpenAIChatCompletions:\n return CombineOpenAiPath(root, \"chat/completions\");\n case AiProtocolType.OpenAIResponses:\n return CombineOpenAiPath(root, \"responses\");\n case AiProtocolType.Claude:\n return CombineClaudePath(root);\n case AiProtocolType.Gemini:\n var modelName = string.IsNullOrWhiteSpace(model) ? \"{model}\" : model.Trim();\n return CombineGeminiPath(root, modelName);\n default:\n return root;\n }\n }\n\n /// <summary>\n /// OpenAI 协议:若 baseUrl 未包含版本段(/v1 等),自动补 /v1\n /// </summary>\n private static string CombineOpenAiPath(string root, string suffix)\n {\n if (EndsWithVersionSegment(root))\n {\n return $\"{root}/{suffix}\";\n }\n return $\"{root}/v1/{suffix}\";\n }\n\n private static string CombineClaudePath(string root)\n {\n if (EndsWithVersionSegment(root))\n {\n return $\"{root}/messages\";\n }\n return $\"{root}/v1/messages\";\n }\n\n private static string CombineGeminiPath(string root, string model)\n {\n // 形如 https://host/v1beta/models/{model}:generateContent\n if (root.EndsWith(\"/v1beta\", StringComparison.OrdinalIgnoreCase)\n || root.EndsWith(\"/v1\", StringComparison.OrdinalIgnoreCase))\n {\n return $\"{root}/models/{model}:generateContent\";\n }\n return $\"{root}/v1beta/models/{model}:generateContent\";\n }\n\n /// <summary>\n /// 判断 baseUrl 是否已经以版本段结尾(避免重复拼接 /v1)\n /// </summary>\n private static bool EndsWithVersionSegment(string root)\n {\n var lastSegment = root;\n var slashIndex = root.LastIndexOf('/');\n if (slashIndex >= 0 && slashIndex < root.Length - 1)\n {\n lastSegment = root.Substring(slashIndex + 1);\n }\n\n if (string.IsNullOrEmpty(lastSegment))\n {\n return false;\n }\n\n // v1, v1beta, v2, beta 等\n if (lastSegment.StartsWith(\"v\", StringComparison.OrdinalIgnoreCase)\n && lastSegment.Length > 1\n && char.IsDigit(lastSegment[1]))\n {\n return true;\n }\n\n return lastSegment.Equals(\"beta\", StringComparison.OrdinalIgnoreCase);\n }\n }\n}\n"}}}}