Files

1 line
18 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": "438417623wq/yuan-ai", "files": {"lib/src/models.dart": {"551d3481bce98047122dc3e6cadb79917005c420": {"t": 1785745908.0193753, "n": 16935, "h": "9b2ed05f1335068b", "c": "import 'package:flutter/material.dart';\n\nenum ChatRole { user, assistant, system }\n\nclass ChatMessage {\n const ChatMessage({\n required this.role,\n required this.text,\n required this.time,\n });\n\n final ChatRole role;\n final String text;\n final String time;\n\n Map<String, dynamic> toJson() {\n return <String, dynamic>{'role': role.name, 'text': text, 'time': time};\n }\n\n static ChatMessage fromJson(Map<String, dynamic> json) {\n final roleName = (json['role'] ?? 'assistant').toString();\n final role = ChatRole.values.firstWhere(\n (value) => value.name == roleName,\n orElse: () => ChatRole.assistant,\n );\n return ChatMessage(\n role: role,\n text: (json['text'] ?? '').toString(),\n time: (json['time'] ?? '').toString(),\n );\n }\n}\n\nclass ModelProvider {\n const ModelProvider({\n required this.id,\n required this.name,\n required this.color,\n required this.icon,\n });\n\n final String id;\n final String name;\n final Color color;\n final String icon;\n}\n\nclass ProviderConfig {\n const ProviderConfig({\n this.baseUrl = '',\n this.apiPath = '',\n this.modelListPath = '',\n this.apiKey = '',\n this.extraHeaders = const {},\n this.model = '',\n this.availableModels = const [],\n this.improveNetworkCompatibility = false,\n this.reasoningEffort = 'very_high',\n });\n\n final String baseUrl;\n final String apiPath;\n final String modelListPath;\n final String apiKey;\n final Map<String, String> extraHeaders;\n final String model;\n final List<String> availableModels;\n final bool improveNetworkCompatibility;\n final String reasoningEffort;\n\n ProviderConfig copyWith({\n String? baseUrl,\n String? apiPath,\n String? modelListPath,\n String? apiKey,\n Map<String, String>? extraHeaders,\n String? model,\n List<String>? availableModels,\n bool? improveNetworkCompatibility,\n String? reasoningEffort,\n }) {\n return ProviderConfig(\n baseUrl: baseUrl ?? this.baseUrl,\n apiPath: apiPath ?? this.apiPath,\n modelListPath: modelListPath ?? this.modelListPath,\n apiKey: apiKey ?? this.apiKey,\n extraHeaders: extraHeaders ?? this.extraHeaders,\n model: model ?? this.model,\n availableModels: availableModels ?? this.availableModels,\n improveNetworkCompatibility:\n improveNetworkCompatibility ?? this.improveNetworkCompatibility,\n reasoningEffort: reasoningEffort ?? this.reasoningEffort,\n );\n }\n\n Map<String, dynamic> toJson() {\n return <String, dynamic>{\n 'baseUrl': baseUrl,\n 'apiPath': apiPath,\n 'modelListPath': modelListPath,\n 'apiKey': apiKey,\n 'extraHeaders': extraHeaders,\n 'model': model,\n 'availableModels': availableModels,\n 'improveNetworkCompatibility': improveNetworkCompatibility,\n 'reasoningEffort': reasoningEffort,\n };\n }\n\n static ProviderConfig fromJson(Map<String, dynamic> json) {\n final rawModels = json['availableModels'];\n final rawHeaders = json['extraHeaders'];\n return ProviderConfig(\n baseUrl: (json['baseUrl'] ?? '').toString(),\n apiPath: (json['apiPath'] ?? '').toString(),\n modelListPath: (json['modelListPath'] ?? '').toString(),\n apiKey: (json['apiKey'] ?? '').toString(),\n extraHeaders: rawHeaders is Map\n ? rawHeaders.map(\n (key, value) => MapEntry(key.toString(), value.toString()),\n )\n : const {},\n model: (json['model'] ?? '').toString(),\n availableModels: rawModels is List\n ? rawModels.map((item) => item.toString()).toList()\n : const [],\n improveNetworkCompatibility: json['improveNetworkCompatibility'] == true,\n reasoningEffort: (json['reasoningEffort'] ?? 'very_high').toString(),\n );\n }\n}\n\nclass ApiConnectionProfile {\n const ApiConnectionProfile({\n required this.id,\n required this.name,\n required this.providerId,\n required this.baseUrl,\n this.apiPath = '',\n this.modelListPath = '',\n required this.apiKey,\n this.extraHeaders = const {},\n required this.model,\n this.availableModels = const [],\n this.improveNetworkCompatibility = false,\n this.modelDisplayName = '',\n this.modelType = 'chat',\n this.inputModes = const ['text'],\n this.outputModes = const ['text'],\n this.capabilityTools = false,\n this.capabilityReasoning = false,\n this.reasoningEffort = 'very_high',\n });\n\n final String id;\n final String name;\n final String providerId;\n final String baseUrl;\n final String apiPath;\n final String modelListPath;\n final String apiKey;\n final Map<String, String> extraHeaders;\n final String model;\n final List<String> availableModels;\n final bool improveNetworkCompatibility;\n final String modelDisplayName;\n final String modelType;\n final List<String> inputModes;\n final List<String> outputModes;\n final bool capabilityTools;\n final bool capabilityReasoning;\n final String reasoningEffort;\n\n ProviderConfig toConfig() {\n return ProviderConfig(\n baseUrl: baseUrl,\n apiPath: apiPath,\n modelListPath: modelListPath,\n apiKey: apiKey,\n extraHeaders: extraHeaders,\n model: model,\n availableModels: availableModels,\n improveNetworkCompatibility: improveNetworkCompatibility,\n reasoningEffort: reasoningEffort,\n );\n }\n\n ApiConnectionProfile copyWith({\n String? id,\n String? name,\n String? providerId,\n String? baseUrl,\n String? apiPath,\n String? modelListPath,\n String? apiKey,\n Map<String, String>? extraHeaders,\n String? model,\n List<String>? availableModels,\n bool? improveNetworkCompatibility,\n String? modelDisplayName,\n String? modelType,\n List<String>? inputModes,\n List<String>? outputModes,\n bool? capabilityTools,\n bool? capabilityReasoning,\n String? reasoningEffort,\n }) {\n return ApiConnectionProfile(\n id: id ?? this.id,\n name: name ?? this.name,\n providerId: providerId ?? this.providerId,\n baseUrl: baseUrl ?? this.baseUrl,\n apiPath: apiPath ?? this.apiPath,\n modelListPath: modelListPath ?? this.modelListPath,\n apiKey: apiKey ?? this.apiKey,\n extraHeaders: extraHeaders ?? this.extraHeaders,\n model: model ?? this.model,\n availableModels: availableModels ?? this.availableModels,\n improveNetworkCompatibility:\n improveNetworkCompatibility ?? this.improveNetworkCompatibility,\n modelDisplayName: modelDisplayName ?? this.modelDisplayName,\n modelType: modelType ?? this.modelType,\n inputModes: inputModes ?? this.inputModes,\n outputModes: outputModes ?? this.outputModes,\n capabilityTools: capabilityTools ?? this.capabilityTools,\n capabilityReasoning: capabilityReasoning ?? this.capabilityReasoning,\n reasoningEffort: reasoningEffort ?? this.reasoningEffort,\n );\n }\n\n Map<String, dynamic> toJson() {\n return <String, dynamic>{\n 'id': id,\n 'name': name,\n 'providerId': providerId,\n 'baseUrl': baseUrl,\n 'apiPath': apiPath,\n 'modelListPath': modelListPath,\n 'apiKey': apiKey,\n 'extraHeaders': extraHeaders,\n 'model': model,\n 'availableModels': availableModels,\n 'improveNetworkCompatibility': improveNetworkCompatibility,\n 'modelDisplayName': modelDisplayName,\n 'modelType': modelType,\n 'inputModes': inputModes,\n 'outputModes': outputModes,\n 'capabilityTools': capabilityTools,\n 'capabilityReasoning': capabilityReasoning,\n 'reasoningEffort': reasoningEffort,\n };\n }\n\n static ApiConnectionProfile fromJson(Map<String, dynamic> json) {\n final rawModels = json['availableModels'];\n final rawHeaders = json['extraHeaders'];\n final rawInputModes = json['inputModes'];\n final rawOutputModes = json['outputModes'];\n final parsedInputModes = rawInputModes is List\n ? rawInputModes.map((item) => item.toString()).toList()\n : const <String>[];\n final parsedOutputModes = rawOutputModes is List\n ? rawOutputModes.map((item) => item.toString()).toList()\n : const <String>[];\n return ApiConnectionProfile(\n id: (json['id'] ?? '').toString(),\n name: (json['name'] ?? '').toString(),\n providerId: (json['providerId'] ?? 'openai').toString(),\n baseUrl: (json['baseUrl'] ?? '').toString(),\n apiPath: (json['apiPath'] ?? '').toString(),\n modelListPath: (json['modelListPath'] ?? '').toString(),\n apiKey: (json['apiKey'] ?? '').toString(),\n extraHeaders: rawHeaders is Map\n ? rawHeaders.map(\n (key, value) => MapEntry(key.toString(), value.toString()),\n )\n : const {},\n model: (json['model'] ?? '').toString(),\n availableModels: rawModels is List\n ? rawModels.map((item) => item.toString()).toList()\n : const [],\n improveNetworkCompatibility: json['improveNetworkCompatibility'] == true,\n modelDisplayName: (json['modelDisplayName'] ?? '').toString(),\n modelType: (json['modelType'] ?? 'chat').toString(),\n inputModes: parsedInputModes.isEmpty ? const ['text'] : parsedInputModes,\n outputModes: parsedOutputModes.isEmpty\n ? const ['text']\n : parsedOutputModes,\n capabilityTools: json['capabilityTools'] == true,\n capabilityReasoning: json['capabilityReasoning'] == true,\n reasoningEffort: (json['reasoningEffort'] ?? 'very_high').toString(),\n );\n }\n}\n\nclass ProjectFileSnippet {\n const ProjectFileSnippet({\n required this.path,\n required this.absolutePath,\n required this.preview,\n required this.sizeBytes,\n required this.isBinary,\n });\n\n final String path;\n final String absolutePath;\n final String preview;\n final int sizeBytes;\n final bool isBinary;\n}\n\nclass ProviderGuide {\n const ProviderGuide({\n required this.baseUrl,\n required this.auth,\n required this.modelListPath,\n required this.docsUrl,\n required this.note,\n this.supportsAutoFetch = true,\n });\n\n final String baseUrl;\n final String auth;\n final String modelListPath;\n final String docsUrl;\n final String note;\n final bool supportsAutoFetch;\n}\n\nconst List<ModelProvider> kProviders = [\n ModelProvider(\n id: 'openai',\n name: 'OpenAI',\n color: Color(0xFF111111),\n icon: 'OA',\n ),\n ModelProvider(\n id: 'openai_responses',\n name: 'OpenAI (Responses)',\n color: Color(0xFF202020),\n icon: 'OR',\n ),\n ModelProvider(\n id: 'gemini',\n name: 'Gemini',\n color: Color(0xFF2D7FF9),\n icon: 'GM',\n ),\n ModelProvider(\n id: 'claude',\n name: 'Claude',\n color: Color(0xFFDE8454),\n icon: 'CL',\n ),\n ModelProvider(\n id: 'deepseek',\n name: 'DeepSeek',\n color: Color(0xFF4C6DF6),\n icon: 'DS',\n ),\n ModelProvider(\n id: 'siliconflow',\n name: '硅基流动',\n color: Color(0xFF6D35FF),\n icon: 'SF',\n ),\n ModelProvider(\n id: 'openrouter',\n name: 'OpenRouter',\n color: Color(0xFF111111),\n icon: 'OR',\n ),\n ModelProvider(\n id: 'ollama',\n name: 'Ollama',\n color: Color(0xFFE8E8ED),\n icon: 'OL',\n ),\n ModelProvider(\n id: 'lmstudio',\n name: 'LM Studio',\n color: Color(0xFF4B41D4),\n icon: 'LM',\n ),\n ModelProvider(\n id: 'azure_openai',\n name: 'Azure OpenAI',\n color: Color(0xFF111111),\n icon: 'AZ',\n ),\n ModelProvider(id: 'groq', name: 'Groq', color: Color(0xFF111111), icon: 'GQ'),\n ModelProvider(id: 'xai', name: 'xAI', color: Color(0xFF111111), icon: 'XI'),\n ModelProvider(\n id: 'mistral',\n name: 'Mistral AI',\n color: Color(0xFFF2A53B),\n icon: 'MS',\n ),\n ModelProvider(\n id: 'perplexity',\n name: 'Perplexity',\n color: Color(0xFF111111),\n icon: 'PP',\n ),\n ModelProvider(\n id: 'volcano',\n name: '火山引擎',\n color: Color(0xFF4C6DF6),\n icon: 'VE',\n ),\n ModelProvider(\n id: 'chatglm',\n name: '智谱 BigModel',\n color: Color(0xFF4C6DF6),\n icon: 'GL',\n ),\n ModelProvider(id: 'custom', name: '自定义', color: Color(0xFF355273), icon: '自'),\n];\n\nconst Map<String, ProviderGuide> kProviderGuides = {\n 'openai': ProviderGuide(\n baseUrl: 'https://api.openai.com/v1',\n auth: 'Authorization: Bearer <OPENAI_API_KEY>',\n modelListPath: '/models',\n docsUrl: 'https://platform.openai.com/docs/api-reference/models/list',\n note: '官方模型列表接口 GET /v1/models;建议优先使用 Responses API 完成对话调用。',\n ),\n 'openai_responses': ProviderGuide(\n baseUrl: 'https://api.openai.com/v1',\n auth: 'Authorization: Bearer <OPENAI_API_KEY>',\n modelListPath: '/models',\n docsUrl: 'https://platform.openai.com/docs/api-reference/models/list',\n note: '同 OpenAI,适合以 Responses API 为主的接入方式。',\n ),\n 'gemini': ProviderGuide(\n baseUrl: 'https://generativelanguage.googleapis.com/v1beta',\n auth: 'x-goog-api-key: <GEMINI_API_KEY>',\n modelListPath: 'GET /models (Header 或 ?key=)',\n docsUrl: 'https://ai.google.dev/gemini-api/docs/models',\n note: '模型列表返回字段常见为 models[].name,例如 models/gemini-2.5-pro。',\n ),\n 'claude': ProviderGuide(\n baseUrl: 'https://api.anthropic.com',\n auth: 'x-api-key + anthropic-version',\n modelListPath: '/v1/models',\n docsUrl: 'https://docs.anthropic.com/en/api/models-list',\n note: 'Anthropic 原生 API 要求 anthropic-version 请求头,模型列表为 GET /v1/models。',\n ),\n 'deepseek': ProviderGuide(\n baseUrl: 'https://api.deepseek.com',\n auth: 'Authorization: Bearer <DEEPSEEK_API_KEY>',\n modelListPath: '/models',\n docsUrl: 'https://api-docs.deepseek.com/api/list-models',\n note: '兼容 OpenAI 协议;官方同时说明 /v1 仅是兼容层,与模型版本无关。',\n ),\n 'siliconflow': ProviderGuide(\n baseUrl: 'https://api.siliconflow.cn/v1',\n auth: 'Authorization: Bearer <SILICONFLOW_API_KEY>',\n modelListPath: '/models',\n docsUrl:\n 'https://docs.siliconflow.cn/en/api-reference/models/get-model-list',\n note: '支持 type/sub_type 过滤模型。',\n ),\n 'openrouter': ProviderGuide(\n baseUrl: 'https://openrouter.ai/api/v1',\n auth: 'Authorization: Bearer <OPENROUTER_API_KEY>',\n modelListPath: '/models',\n docsUrl: 'https://openrouter.ai/docs/api-reference/models/get-models',\n note: '可选 HTTP-Referer 与 X-Title 请求头用于应用归属与统计。',\n ),\n 'ollama': ProviderGuide(\n baseUrl: 'http://localhost:11434/api',\n auth: '本地默认无需鉴权;云端可 Bearer',\n modelListPath: '/tags',\n docsUrl: 'https://docs.ollama.com/api/tags',\n note: '本地常用 /api/tags 获取模型列表。',\n ),\n 'lmstudio': ProviderGuide(\n baseUrl: 'http://localhost:1234/v1',\n auth: '通常可用任意占位 key(如 lm-studio)',\n modelListPath: '/models',\n docsUrl: 'https://lmstudio.ai/docs/app/api/openai-compat',\n note: 'OpenAI 兼容接口,支持 /v1/models。',\n ),\n 'azure_openai': ProviderGuide(\n baseUrl: 'https://<resource>.openai.azure.com',\n auth: 'api-key: <AZURE_OPENAI_KEY>',\n modelListPath: '/openai/v1/models?api-version=preview',\n docsUrl:\n 'https://learn.microsoft.com/en-us/azure/foundry/openai/reference-preview',\n note: '官方预览文档包含 GET /openai/v1/models;聊天调用常用 deployment-name。',\n ),\n 'groq': ProviderGuide(\n baseUrl: 'https://api.groq.com/openai/v1',\n auth: 'Authorization: Bearer <GROQ_API_KEY>',\n modelListPath: '/models',\n docsUrl: 'https://console.groq.com/docs/api-reference',\n note: 'OpenAI 兼容接口;模型列表走 /openai/v1/models。',\n ),\n 'xai': ProviderGuide(\n baseUrl: 'https://api.x.ai',\n auth: 'Authorization: Bearer <XAI_API_KEY>',\n modelListPath: '/v1/models',\n docsUrl: 'https://docs.x.ai/developers/api-reference/models',\n note: '官方全局入口为 api.x.ai,鉴权使用 Bearer Token。',\n ),\n 'mistral': ProviderGuide(\n baseUrl: 'https://api.mistral.ai/v1',\n auth: 'Authorization: Bearer <MISTRAL_API_KEY>',\n modelListPath: '/models',\n docsUrl: 'https://docs.mistral.ai/api/endpoint/models',\n note: '官方模型列表接口为 GET /v1/models。',\n ),\n 'perplexity': ProviderGuide(\n baseUrl: 'https://api.perplexity.ai',\n auth: 'Authorization: Bearer <PERPLEXITY_API_KEY>',\n modelListPath: '建议按文档模型页手动选择',\n docsUrl: 'https://docs.perplexity.ai/docs/agent-api/openai-compatibility',\n note: '官方同时给出 OpenAI 兼容方式,基地址在不同 API 版本文档中可能不同(v1/v2)。',\n supportsAutoFetch: false,\n ),\n 'volcano': ProviderGuide(\n baseUrl: 'https://ark.cn-beijing.volces.com/api/v3',\n auth: 'Authorization: Bearer <ARK_API_KEY>',\n modelListPath: '控制台模型列表 / 固定 Model ID',\n docsUrl: 'https://www.volcengine.com/docs/82379/1338552',\n note: '火山方舟支持 API Key + Response API;模型 ID 通常从控制台获取。',\n supportsAutoFetch: false,\n ),\n 'chatglm': ProviderGuide(\n baseUrl: 'https://open.bigmodel.cn/api/paas/v4',\n auth: 'Authorization: Bearer <BIGMODEL_API_KEY>',\n modelListPath: '模型概览页 / 固定 Model ID',\n docsUrl: 'https://docs.bigmodel.cn/api-reference',\n note: '智谱 BigModel 文档提供统一鉴权与接口说明,模型通常按文档/控制台选择。',\n supportsAutoFetch: false,\n ),\n 'custom': ProviderGuide(\n baseUrl: '',\n auth: '按目标平台要求配置',\n modelListPath: '按目标平台定义',\n docsUrl: 'https://platform.openai.com/docs/api-reference/models/list',\n note: '自定义供应商可按 OpenAI 兼容模式接入。',\n supportsAutoFetch: false,\n ),\n};\n"}}}}