1 line
27 KiB
JSON
1 line
27 KiB
JSON
{"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"}}}} |