{"repo": "cherryhq/hanlin-ai", "files": {"AI_HLY/Services/DataServices/InfoServices.swift": {"f3782a7b0e2542bda6a66066b820141416c2c8a7": {"t": 1785745882.4996784, "n": 68468, "h": "eeb7fe1d8cac9ee9", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n // 0\n AllModels(name: \"google/gemini-3-flash-preview_repeat_cherryin\", displayName: \"Gemini3-Flash(CherryIN)\", identity: \"model\", position: 104, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.7-flash\", displayName: \"GLM4.7-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n AllModels(name: \"glm-4.6v-flash\", displayName: \"GLM4.6V-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.7\", displayName: \"GLM4.7\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-8-251228\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0905-preview\", displayName: \"Kimi-K2\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-3\", displayName: \"Step3\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-M2\", displayName: \"MiniMax-M2\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_sc\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B_repeat_sc\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors_repeat_sc\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Gitee\n // 0.04/次\n AllModels(name: \"GLM-4.7\", displayName: \"GLM-4.7(Gitee)\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.05/次\n AllModels(name: \"kimi-k2-instruct\", displayName: \"kimi-k2-instruct(Gitee)\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5.2\", displayName: \"GPT5.2\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.004745\n AllModels(name: \"gemini-3-flash-preview\", displayName: \"Gemini3-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-3-pro-preview\", displayName: \"Gemini3-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-haiku-4-5\", displayName: \"Claude4.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-5\", displayName: \"Claude4.5-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-5\", displayName: \"Claude4.5-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-non-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"anthropic/claude-opus-4.5_repeat_openrouter\", displayName: \"Claude4.5-Opus(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"google/gemini-3-pro-preview_repeat_openrouter\", displayName: \"Gemini3-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"openai/gpt-5.2_repeat_openrouter\", displayName: \"GPT5.2(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: n1n\n // 0\n AllModels(name: \"gpt-4o_repeat_n1n\", displayName: \"GPT-4o(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0\n AllModels(name: \"claude-3-5-sonnet-20240620_repeat_n1n\", displayName: \"Claude3.5-Sonnet(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"gemini-1.5-pro-latest_repeat_n1n\", displayName: \"Gemini1.5-Pro(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: XIAOMI MIMO\n AllModels(name: \"mimo-v2-flash\", displayName: \"MIMO-V2-Flash\", identity: \"model\", position: 106, company: \"MIMO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: LONGCAT\n AllModels(name: \"LongCat-Flash-Chat\", displayName: \"LongCat-Flash-Chat\", identity: \"model\", position: 106, company: \"LONGCAT\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: AI302\n AllModels(name: \"gemini-3-pro-preview_repeat_ai302\", displayName: \"Gemini3-Pro(AI302)\", identity: \"model\", position: 106, company: \"AI302\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: AIHUBMIX\n AllModels(name: \"gemini-3-flash-preview_repeat_aihubmix\", displayName: \"Gemini3-Pro(AIHUBMIX)\", identity: \"model\", position: 106, company: \"AIHUBMIX\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: POE\n AllModels(name: \"gemini-3-pro_repeat_poe\", displayName: \"Gemini3-Pro(POE)\", identity: \"model\", position: 106, company: \"POE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: IFLOW\n AllModels(name: \"qwen3-max_repeat_iflow\", displayName: \"Qwen3-Max(iFlow)\", identity: \"model\", position: 106, company: \"IFLOW\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n let models = getModelList()\n if let model = models.first(where: { $0.company?.uppercased() == company.uppercased() }) {\n let baseName = restoreBaseModelName(from: model.name ?? \"Unknown\")\n return baseName\n }\n return \"Unknown\"\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"MIMO_API_KEY\",\n company: \"MIMO\",\n key: \"\",\n requestURL: \"https://api.xiaomimimo.com/v1/chat/completions\",\n help: \"https://platform.xiaomimimo.com/#/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"LONGCAT_API_KEY\",\n company: \"LONGCAT\",\n key: \"\",\n requestURL: \"https://api.longcat.chat/openai/v1/chat/completions\",\n help: \"https://longcat.chat/platform/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"AI302_API_KEY\",\n company: \"AI302\",\n key: \"\",\n requestURL: \"https://api.302.ai/v1/chat/completions\",\n help: \"https://302.ai/apis/list\",\n from: .system\n ),\n APIKeys(\n name: \"AIHUBMIX_API_KEY\",\n company: \"AIHUBMIX\",\n key: \"\",\n requestURL: \"https://aihubmix.com/v1/chat/completions\",\n help: \"https://console.aihubmix.com/token\",\n from: .system\n ),\n APIKeys(\n name: \"POE_API_KEY\",\n company: \"POE\",\n key: \"\",\n requestURL: \"https://api.poe.com/v1/chat/completions\",\n help: \"https://poe.com/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"IFLOW_API_KEY\",\n company: \"IFLOW\",\n key: \"\",\n requestURL: \"https://apis.iflow.cn/v1/chat/completions\",\n help: \"https://platform.iflow.cn/profile?tab=apiKey\",\n from: .system\n ),\n APIKeys(\n name: \"N1N_API_KEY\",\n company: \"N1N\",\n key: \"\",\n requestURL: \"https://api.n1n.ai/v1/chat/completions\",\n help: \"https://n1n.ai\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n case \"MIMO\":\n return isDarkMode ? \"mimo_dark\" : \"mimo\"\n case \"LONGCAT\":\n return isDarkMode ? \"longcat_dark\" : \"longcat\"\n case \"AI302\":\n return \"ai302\"\n case \"POE\":\n return isDarkMode ? \"poe_dark\" : \"poe\"\n case \"AIHUBMIX\":\n return \"aihubmix\"\n case \"IFLOW\":\n return \"iflow\"\n case \"N1N\":\n return \"n1n\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "a3d205d266bc11f8e7136ed0f8ae5b7b7bea81ac": {"t": 1785757541.4832354, "n": 68468, "h": "eeb7fe1d8cac9ee9", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n // 0\n AllModels(name: \"google/gemini-3-flash-preview_repeat_cherryin\", displayName: \"Gemini3-Flash(CherryIN)\", identity: \"model\", position: 104, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.7-flash\", displayName: \"GLM4.7-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n AllModels(name: \"glm-4.6v-flash\", displayName: \"GLM4.6V-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.7\", displayName: \"GLM4.7\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-8-251228\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0905-preview\", displayName: \"Kimi-K2\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-3\", displayName: \"Step3\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-M2\", displayName: \"MiniMax-M2\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_sc\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B_repeat_sc\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors_repeat_sc\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Gitee\n // 0.04/次\n AllModels(name: \"GLM-4.7\", displayName: \"GLM-4.7(Gitee)\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.05/次\n AllModels(name: \"kimi-k2-instruct\", displayName: \"kimi-k2-instruct(Gitee)\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5.2\", displayName: \"GPT5.2\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.004745\n AllModels(name: \"gemini-3-flash-preview\", displayName: \"Gemini3-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-3-pro-preview\", displayName: \"Gemini3-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-haiku-4-5\", displayName: \"Claude4.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-5\", displayName: \"Claude4.5-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-5\", displayName: \"Claude4.5-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-non-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"anthropic/claude-opus-4.5_repeat_openrouter\", displayName: \"Claude4.5-Opus(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"google/gemini-3-pro-preview_repeat_openrouter\", displayName: \"Gemini3-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"openai/gpt-5.2_repeat_openrouter\", displayName: \"GPT5.2(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: n1n\n // 0\n AllModels(name: \"gpt-4o_repeat_n1n\", displayName: \"GPT-4o(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0\n AllModels(name: \"claude-3-5-sonnet-20240620_repeat_n1n\", displayName: \"Claude3.5-Sonnet(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"gemini-1.5-pro-latest_repeat_n1n\", displayName: \"Gemini1.5-Pro(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: XIAOMI MIMO\n AllModels(name: \"mimo-v2-flash\", displayName: \"MIMO-V2-Flash\", identity: \"model\", position: 106, company: \"MIMO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: LONGCAT\n AllModels(name: \"LongCat-Flash-Chat\", displayName: \"LongCat-Flash-Chat\", identity: \"model\", position: 106, company: \"LONGCAT\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: AI302\n AllModels(name: \"gemini-3-pro-preview_repeat_ai302\", displayName: \"Gemini3-Pro(AI302)\", identity: \"model\", position: 106, company: \"AI302\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: AIHUBMIX\n AllModels(name: \"gemini-3-flash-preview_repeat_aihubmix\", displayName: \"Gemini3-Pro(AIHUBMIX)\", identity: \"model\", position: 106, company: \"AIHUBMIX\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: POE\n AllModels(name: \"gemini-3-pro_repeat_poe\", displayName: \"Gemini3-Pro(POE)\", identity: \"model\", position: 106, company: \"POE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: IFLOW\n AllModels(name: \"qwen3-max_repeat_iflow\", displayName: \"Qwen3-Max(iFlow)\", identity: \"model\", position: 106, company: \"IFLOW\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n let models = getModelList()\n if let model = models.first(where: { $0.company?.uppercased() == company.uppercased() }) {\n let baseName = restoreBaseModelName(from: model.name ?? \"Unknown\")\n return baseName\n }\n return \"Unknown\"\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"MIMO_API_KEY\",\n company: \"MIMO\",\n key: \"\",\n requestURL: \"https://api.xiaomimimo.com/v1/chat/completions\",\n help: \"https://platform.xiaomimimo.com/#/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"LONGCAT_API_KEY\",\n company: \"LONGCAT\",\n key: \"\",\n requestURL: \"https://api.longcat.chat/openai/v1/chat/completions\",\n help: \"https://longcat.chat/platform/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"AI302_API_KEY\",\n company: \"AI302\",\n key: \"\",\n requestURL: \"https://api.302.ai/v1/chat/completions\",\n help: \"https://302.ai/apis/list\",\n from: .system\n ),\n APIKeys(\n name: \"AIHUBMIX_API_KEY\",\n company: \"AIHUBMIX\",\n key: \"\",\n requestURL: \"https://aihubmix.com/v1/chat/completions\",\n help: \"https://console.aihubmix.com/token\",\n from: .system\n ),\n APIKeys(\n name: \"POE_API_KEY\",\n company: \"POE\",\n key: \"\",\n requestURL: \"https://api.poe.com/v1/chat/completions\",\n help: \"https://poe.com/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"IFLOW_API_KEY\",\n company: \"IFLOW\",\n key: \"\",\n requestURL: \"https://apis.iflow.cn/v1/chat/completions\",\n help: \"https://platform.iflow.cn/profile?tab=apiKey\",\n from: .system\n ),\n APIKeys(\n name: \"N1N_API_KEY\",\n company: \"N1N\",\n key: \"\",\n requestURL: \"https://api.n1n.ai/v1/chat/completions\",\n help: \"https://n1n.ai\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n case \"MIMO\":\n return isDarkMode ? \"mimo_dark\" : \"mimo\"\n case \"LONGCAT\":\n return isDarkMode ? \"longcat_dark\" : \"longcat\"\n case \"AI302\":\n return \"ai302\"\n case \"POE\":\n return isDarkMode ? \"poe_dark\" : \"poe\"\n case \"AIHUBMIX\":\n return \"aihubmix\"\n case \"IFLOW\":\n return \"iflow\"\n case \"N1N\":\n return \"n1n\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "65ced14c1ba194411c7ff0aa6e8c3ac201f497a5": {"t": 1785757543.06327, "n": 69795, "h": "d99b66afb227df01", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n // 0\n AllModels(name: \"openai/gpt-5-chat_repeat_cherryin\", displayName: \"GPT5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_cherryin\", displayName: \"Claude-Sonnet-4.5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"gemini/gemini-2.5-flash_repeat_cherryin\", displayName: \"Gemini2.5-Flash(CherryIN)\", identity: \"model\", position: 104, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_cherryin\", displayName: \"Gemini2.5-Pro(CherryIN)\", identity: \"model\", position: 105, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n AllModels(name: \"glm-4.6v-flash\", displayName: \"GLM4.6V-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.7\", displayName: \"GLM4.7\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-251015\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0905-preview\", displayName: \"Kimi-K2\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-3\", displayName: \"Step3\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-M2\", displayName: \"MiniMax-M2\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Gitee\n // 0.04/次\n AllModels(name: \"GLM-4.6\", displayName: \"GLM-4.6(Gitee)\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.05/次\n AllModels(name: \"kimi-k2-instruct\", displayName: \"kimi-k2-instruct(Gitee)\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5.2\", displayName: \"GPT5.2\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-haiku-4-5\", displayName: \"Claude4.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-5\", displayName: \"Claude4.5-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-5\", displayName: \"Claude4.5-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-non-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"x-ai/grok-code-fast-1_repeat_openrouter\", displayName: \"Grok-Code-Fast-1(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"anthropic/claude-haiku-4.5_repeat_openrouter\", displayName: \"Claude4.5-Haiku(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_openrouter\", displayName: \"Claude4.5-Sonnet(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"google/gemini-2.5-flash_repeat_openrouter\", displayName: \"Gemini2.5-Flash(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_openrouter\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"x-ai/grok-4-fast_repeat_openrouter\", displayName: \"Grok4-Fast(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: n1n\n // 0\n AllModels(name: \"gpt-4o_repeat_n1n\", displayName: \"GPT-4o(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0\n AllModels(name: \"claude-3-5-sonnet-20240620_repeat_n1n\", displayName: \"Claude3.5-Sonnet(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"gemini-1.5-pro-latest_repeat_n1n\", displayName: \"Gemini1.5-Pro(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n let models = getModelList()\n if let model = models.first(where: { $0.company?.uppercased() == company.uppercased() }) {\n let baseName = restoreBaseModelName(from: model.name ?? \"Unknown\")\n return baseName\n }\n return \"Unknown\"\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"MIMO_API_KEY\",\n company: \"MIMO\",\n key: \"\",\n requestURL: \"https://api.xiaomimimo.com/v1/chat/completions\",\n help: \"https://platform.xiaomimimo.com/#/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"LONGCAT_API_KEY\",\n company: \"LONGCAT\",\n key: \"\",\n requestURL: \"https://api.longcat.chat/openai/v1/chat/completions\",\n help: \"https://longcat.chat/platform/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"AI302_API_KEY\",\n company: \"AI302\",\n key: \"\",\n requestURL: \"https://api.302.ai/v1/chat/completions\",\n help: \"https://302.ai/apis/list\",\n from: .system\n ),\n APIKeys(\n name: \"AIHUBMIX_API_KEY\",\n company: \"AIHUBMIX\",\n key: \"\",\n requestURL: \"https://aihubmix.com/v1/chat/completions\",\n help: \"https://console.aihubmix.com/token\",\n from: .system\n ),\n APIKeys(\n name: \"POE_API_KEY\",\n company: \"POE\",\n key: \"\",\n requestURL: \"https://api.poe.com/v1/chat/completions\",\n help: \"https://poe.com/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"IFLOW_API_KEY\",\n company: \"IFLOW\",\n key: \"\",\n requestURL: \"https://apis.iflow.cn/v1/chat/completions\",\n help: \"https://platform.iflow.cn/profile?tab=apiKey\",\n from: .system\n ),\n APIKeys(\n name: \"N1N_API_KEY\",\n company: \"N1N\",\n key: \"\",\n requestURL: \"https://api.n1n.ai/v1/chat/completions\",\n help: \"https://n1n.ai\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n case \"MIMO\":\n return isDarkMode ? \"mimo_dark\" : \"mimo\"\n case \"LONGCAT\":\n return isDarkMode ? \"longcat_dark\" : \"longcat\"\n case \"AI302\":\n return \"ai302\"\n case \"POE\":\n return isDarkMode ? \"poe_dark\" : \"poe\"\n case \"AIHUBMIX\":\n return \"aihubmix\"\n case \"IFLOW\":\n return \"iflow\"\n case \"N1N\":\n return \"n1n\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "8ab48c36b832abb4feef5798365a2555d29cba2c": {"t": 1785757544.609796, "n": 67849, "h": "20a867691484d4b4", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n // 0\n AllModels(name: \"openai/gpt-5-chat_repeat_cherryin\", displayName: \"GPT5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_cherryin\", displayName: \"Claude-Sonnet-4.5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"gemini/gemini-2.5-flash_repeat_cherryin\", displayName: \"Gemini2.5-Flash(CherryIN)\", identity: \"model\", position: 104, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_cherryin\", displayName: \"Gemini2.5-Pro(CherryIN)\", identity: \"model\", position: 105, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n AllModels(name: \"glm-4.6v-flash\", displayName: \"GLM4.6V-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.7\", displayName: \"GLM4.7\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-251015\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0905-preview\", displayName: \"Kimi-K2\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-3\", displayName: \"Step3\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-M2\", displayName: \"MiniMax-M2\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Gitee\n // 0.04/次\n AllModels(name: \"GLM-4.6\", displayName: \"GLM-4.6(Gitee)\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.05/次\n AllModels(name: \"kimi-k2-instruct\", displayName: \"kimi-k2-instruct(Gitee)\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5.2\", displayName: \"GPT5.2\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-haiku-4-5\", displayName: \"Claude4.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-5\", displayName: \"Claude4.5-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-5\", displayName: \"Claude4.5-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-non-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"x-ai/grok-code-fast-1_repeat_openrouter\", displayName: \"Grok-Code-Fast-1(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"anthropic/claude-haiku-4.5_repeat_openrouter\", displayName: \"Claude4.5-Haiku(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_openrouter\", displayName: \"Claude4.5-Sonnet(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"google/gemini-2.5-flash_repeat_openrouter\", displayName: \"Gemini2.5-Flash(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_openrouter\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"x-ai/grok-4-fast_repeat_openrouter\", displayName: \"Grok4-Fast(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: n1n\n // 0\n AllModels(name: \"gpt-4o_repeat_n1n\", displayName: \"GPT-4o(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0\n AllModels(name: \"claude-3-5-sonnet-20240620_repeat_n1n\", displayName: \"Claude3.5-Sonnet(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"gemini-1.5-pro-latest_repeat_n1n\", displayName: \"Gemini1.5-Pro(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n let models = getModelList()\n if let model = models.first(where: { $0.company?.uppercased() == company.uppercased() }) {\n let baseName = restoreBaseModelName(from: model.name ?? \"Unknown\")\n return baseName\n }\n return \"Unknown\"\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"N1N_API_KEY\",\n company: \"N1N\",\n key: \"\",\n requestURL: \"https://api.n1n.ai/v1/chat/completions\",\n help: \"https://n1n.ai\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n case \"N1N\":\n return \"n1n\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "091eda706beeb4192076f692e50170face787cac": {"t": 1785757547.6196296, "n": 88402, "h": "868a3ba221e340ba", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n // 0\n AllModels(name: \"openai/gpt-5-chat_repeat_cherryin\", displayName: \"GPT5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_cherryin\", displayName: \"Claude-Sonnet-4.5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"gemini/gemini-2.5-flash_repeat_cherryin\", displayName: \"Gemini2.5-Flash(CherryIN)\", identity: \"model\", position: 104, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_cherryin\", displayName: \"Gemini2.5-Pro(CherryIN)\", identity: \"model\", position: 105, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: n1n\n // 0\n AllModels(name: \"gpt-4o_repeat_n1n\", displayName: \"GPT-4o(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0\n AllModels(name: \"claude-3-5-sonnet-20240620_repeat_n1n\", displayName: \"Claude3.5-Sonnet(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"gemini-1.5-pro-latest_repeat_n1n\", displayName: \"Gemini1.5-Pro(n1n)\", identity: \"model\", position: 106, company: \"N1N\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.6\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-251015\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0905-preview\", displayName: \"Kimi-K2\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-3\", displayName: \"Step3\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-M2\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.6\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-VL-30B-A3B-Instruct\", displayName: \"Qwen3-VL-30B-A3B-Instruct(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-VL-30B-A3B-Thinking\", displayName: \"Qwen3-VL-30B-A3B-Thinking(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-VL-235B-A22B-Instruct\", displayName: \"Qwen3-VL-235B-A22B-Instruct(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-VL-235B-A22B-Thinking\", displayName: \"Qwen3-VL-235B-A22B-Thinking(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.2-Exp\", displayName: \"DeepSeek-V3.2(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct-0905\", displayName: \"Kimi-K2-Instruct-0905(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-235B-A22B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-235B-A22B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-Next-80B-A3B-Instruct_repeat_ms\", displayName: \"Qwen3-Next-80B-A3B-Instruct(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-Next-80B-A3B-Thinking_repeat_ms\", displayName: \"Qwen/Qwen3-Next-80B-A3B-Thinking(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-VL-30B-A3B-Instruct_repeat_ms\", displayName: \"Qwen3-VL-30B-A3B-Instruct(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-VL-235B-A22B-Instruct_repeat_ms\", displayName: \"Qwen3-VL-235B-A22B-Instruct(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Gitee\n // 0.04/次\n AllModels(name: \"GLM-4.6\", displayName: \"GLM-4.6(Gitee)\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.05/次\n AllModels(name: \"kimi-k2-instruct\", displayName: \"kimi-k2-instruct(Gitee)\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-haiku-4-5\", displayName: \"Claude4.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-5\", displayName: \"Claude4.5-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-1\", displayName: \"Claude4.1-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-non-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"x-ai/grok-code-fast-1_repeat_openrouter\", displayName: \"Grok-Code-Fast-1(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"anthropic/claude-haiku-4.5_repeat_openrouter\", displayName: \"Claude4.5-Haiku(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_openrouter\", displayName: \"Claude4.5-Sonnet(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"google/gemini-2.5-flash_repeat_openrouter\", displayName: \"Gemini2.5-Flash(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_openrouter\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"x-ai/grok-4-fast_repeat_openrouter\", displayName: \"Grok4-Fast(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n\n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n let models = getModelList()\n if let model = models.first(where: { $0.company?.uppercased() == company.uppercased() }) {\n let baseName = restoreBaseModelName(from: model.name ?? \"Unknown\")\n return baseName\n }\n return \"Unknown\"\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: getEnvironmentVariable(\"HANLIN_API_KEY\"),\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"N1N_API_KEY\",\n company: \"N1N\",\n key: \"\",\n requestURL: \"https://api.n1n.ai/v1/chat/completions\",\n help: \"https://n1n.ai\",\n from: .system\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: getEnvironmentVariable(\"HANLIN_OPEN_API_KEY\"),\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "578ecdd46fa65bf95fdf0aa6ec4616627ff452c9": {"t": 1785757550.2178965, "n": 87300, "h": "97a489a188d6930d", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n // 0\n AllModels(name: \"openai/gpt-5-chat_repeat_cherryin\", displayName: \"GPT5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_cherryin\", displayName: \"Claude-Sonnet-4.5(CherryIN)\", identity: \"model\", position: 103, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"gemini/gemini-2.5-flash_repeat_cherryin\", displayName: \"Gemini2.5-Flash(CherryIN)\", identity: \"model\", position: 104, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_cherryin\", displayName: \"Gemini2.5-Pro(CherryIN)\", identity: \"model\", position: 105, company: \"CHERRY_IN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.6\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-251015\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0905-preview\", displayName: \"Kimi-K2\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-3\", displayName: \"Step3\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-M2\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.6\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-VL-30B-A3B-Instruct\", displayName: \"Qwen3-VL-30B-A3B-Instruct(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"Qwen/Qwen3-VL-30B-A3B-Thinking\", displayName: \"Qwen3-VL-30B-A3B-Thinking(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-VL-235B-A22B-Instruct\", displayName: \"Qwen3-VL-235B-A22B-Instruct(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"Qwen/Qwen3-VL-235B-A22B-Thinking\", displayName: \"Qwen3-VL-235B-A22B-Thinking(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.2-Exp\", displayName: \"DeepSeek-V3.2(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct-0905\", displayName: \"Kimi-K2-Instruct-0905(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-30B-A3B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507_repeat_ms\", displayName: \"Qwen3-235B-A22B-Instruct-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507_repeat_ms\", displayName: \"Qwen3-235B-A22B-Thinking-2507(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-Next-80B-A3B-Instruct_repeat_ms\", displayName: \"Qwen3-Next-80B-A3B-Instruct(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-Next-80B-A3B-Thinking_repeat_ms\", displayName: \"Qwen/Qwen3-Next-80B-A3B-Thinking(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-VL-30B-A3B-Instruct_repeat_ms\", displayName: \"Qwen3-VL-30B-A3B-Instruct(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-VL-235B-A22B-Instruct_repeat_ms\", displayName: \"Qwen3-VL-235B-A22B-Instruct(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Gitee\n // 0.04/次\n AllModels(name: \"GLM-4.6\", displayName: \"GLM-4.6(Gitee)\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.05/次\n AllModels(name: \"kimi-k2-instruct\", displayName: \"kimi-k2-instruct(Gitee)\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-haiku-4-5\", displayName: \"Claude4.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-5\", displayName: \"Claude4.5-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-1\", displayName: \"Claude4.1-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-non-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-4-fast-reasoning\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"x-ai/grok-code-fast-1_repeat_openrouter\", displayName: \"Grok-Code-Fast-1(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"anthropic/claude-haiku-4.5_repeat_openrouter\", displayName: \"Claude4.5-Haiku(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"anthropic/claude-sonnet-4.5_repeat_openrouter\", displayName: \"Claude4.5-Sonnet(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"google/gemini-2.5-flash_repeat_openrouter\", displayName: \"Gemini2.5-Flash(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro_repeat_openrouter\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n // 0\n AllModels(name: \"x-ai/grok-4-fast_repeat_openrouter\", displayName: \"Grok4-Fast(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true),\n\n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n let models = getModelList()\n if let model = models.first(where: { $0.company?.uppercased() == company.uppercased() }) {\n let baseName = restoreBaseModelName(from: model.name ?? \"Unknown\")\n return baseName\n }\n return \"Unknown\"\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: getEnvironmentVariable(\"HANLIN_API_KEY\"),\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: getEnvironmentVariable(\"HANLIN_OPEN_API_KEY\"),\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "08b54cff5a154c752e21837250d18aee6c32749f": {"t": 1785757552.1651819, "n": 93671, "h": "acd4cf1979d802bd", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 0.001 廉价;0.006 标准;\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n \n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 1, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 2, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0375\n AllModels(name: \"qwen3-max\", displayName: \"Qwen3-Max\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-flash\", displayName: \"Qwen-Omni-Flash\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen3-vl-plus\", displayName: \"Qwen3-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"qwen3-vl-flash\", displayName: \"Qwen3-VL-Flash\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportReasoningChange: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image-plus\", displayName: \"Qwen-Image-Plus\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.6\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-251015\", displayName: \"Doubao1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-seed-1-6-lite-251015\", displayName: \"Doubao1.6-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-flash-250828\", displayName: \"Doubao1.6-Flash\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-Chat\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-Reasoner\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0711-preview\", displayName: \"Kimi-Auto\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.079\n AllModels(name: \"step-2-16k\", displayName: \"Step2\", identity: \"model\", position: 47, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-1o-turbo-vision\", displayName: \"Step1o-Turbo\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.0425\n AllModels(name: \"step-1o-vision-32k\", displayName: \"Step1o\", identity: \"model\", position: 49, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-Text-01\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"abab6.5s-chat\", displayName: \"Abab6.5s\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00189\n AllModels(name: \"THUDM/GLM-4-32B-0414\", displayName: \"GLM-4-32B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"THUDM/GLM-Z1-9B-0414\", displayName: \"GLM-Z1-9B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-32B-0414\", displayName: \"GLM-Z1-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-Rumination-32B-0414\", displayName: \"GLM-Z1-Rumination-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"internlm/internlm2_5-20b-chat\", displayName: \"Internlm2.5-20B(SiliconCloud)\", identity: \"model\", position: 57, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"Qwen/Qwen3-14B\", displayName: \"Qwen3-14B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B\", displayName: \"Qwen3-30B-A3B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"Qwen/Qwen3-32B\", displayName: \"Qwen3-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B\", displayName: \"Qwen3-235B-A22B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"deepseek-ai/DeepSeek-V3\", displayName: \"DeepSeek-V3(SiliconCloud)\", identity: \"model\", position: 58, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-R1\", displayName: \"DeepSeek-R1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.1\", displayName: \"DeepSeek-V3.1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00126\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\", displayName: \"DeepSeek-R1-Distill-Qwen-32B(SiliconCloud)\", identity: \"model\", position: 60, company: \"SILICONCLOUD\", price:2, isHidden:true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.00099\n AllModels(name: \"deepseek-ai/deepseek-vl2\", displayName: \"DeepSeek-VL2(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:1, isHidden:true, supportsSearch: true, supportsMultimodal: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct\", displayName: \"Kimi-K2-Instruct(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-14B-Instruct_repeat_ms\", displayName: \"Qwen2.5-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-72B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-14B_repeat_ms\", displayName: \"Qwen3-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-32B_repeat_ms\", displayName: \"Qwen3-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B_repeat_ms\", displayName: \"Qwen3-235B-A22B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-V3-0324_repeat_ms\", displayName: \"DeepSeek-V3(ModelScope)\", identity: \"model\", position: 64, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-7B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-7B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-32B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-72B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-R1_repeat_ms\", displayName: \"DeepSeek-R1(ModelScope)\", identity: \"model\", position: 66, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QwQ-32B_repeat_ms\", displayName: \"QwQ-32B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QVQ-72B-Preview_repeat_ms\", displayName: \"QVQ-72B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"MusePublic/489_ckpt_FLUX_1_repeat_ms\", displayName: \"Flux.1-dev\", identity: \"model\", position: 68, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gitee\n // 0.01/次\n AllModels(name: \"Fin-R1\", displayName: \"Fin-R1\", identity: \"model\", position: 69, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.01/次\n AllModels(name: \"GLM-4-9B-Chat\", displayName: \"GLM-4-9B\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01/次\n AllModels(name: \"InternLM3-8B-Instruct\", displayName: \"InternLM3-8B-Instruct\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n // 0.02/次\n AllModels(name: \"Qwen2.5-72B-Instruct\", displayName: \"Qwen2.5-72B-Instruct\", identity: \"model\", position: 72, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-3-5-haiku-latest\", displayName: \"Claude3.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-3-7-sonnet-latest\", displayName: \"Claude3.7-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-0\", displayName: \"Claude4.0-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-0\", displayName: \"Claude4.0-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-3-latest\", displayName: \"Grok3\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.1095\n AllModels(name: \"grok-3-fast-latest\", displayName: \"Grok3-Fast\", identity: \"model\", position: 92, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00584\n AllModels(name: \"grok-3-mini-latest\", displayName: \"Grok3-Mini\", identity: \"model\", position: 93, company: \"XAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01679\n AllModels(name: \"grok-3-mini-fast-latest\", displayName: \"Grok3-Mini-Fast\", identity: \"model\", position: 94, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0438\n AllModels(name: \"grok-2-latest\", displayName: \"Grok2\", identity: \"model\", position: 95, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.073\n AllModels(name: \"grok-2-vision-latest\", displayName: \"Grok2-Vision\", identity: \"model\", position: 96, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"qwen/qwen3-32b:free\", displayName: \"Qwen3-32B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen3-235b-a22b:free\", displayName: \"Qwen3-235B-A22B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen2.5-vl-72b-instruct:free\", displayName: \"Qwen2.5VL-72B(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro-exp-03-25:free\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-scout:free\", displayName: \"Llama4-Scout(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-maverick:free\", displayName: \"Llama4-Maverick(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"deepseek/deepseek-chat-v3-0324:free\", displayName: \"DeepSeek-V3(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-prover-v2:free\", displayName: \"DeepSeek-Prover-V2(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-r1:free\", displayName: \"DeepSeek-R1(OpenRouter)\", identity: \"model\", position: 107, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0\n AllModels(name: \"qwen/qwq-32b:free\", displayName: \"Qwen-QWQ-32B(OpenRouter)\", identity: \"model\", position: 108, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n\n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n switch company.uppercased() {\n case \"QWEN\":\n return \"qwen-turbo\"\n case \"ZHIPUAI\":\n return \"glm-4-flash\"\n case \"DOUBAO\":\n return \"doubao-1-5-lite-32k-250115\"\n case \"DEEPSEEK\":\n return \"deepseek-chat\"\n case \"SILICONCLOUD\":\n return \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n case \"HUNYUAN\":\n return \"hunyuan-lite\"\n case \"YI\":\n return \"yi-lightning\"\n case \"KIMI\":\n return \"moonshot-v1-auto\"\n case \"STEP\":\n return \"step-2-mini\"\n case \"OPENAI\":\n return \"gpt-4o-mini\"\n case \"GOOGLE\":\n return \"gemini-2.0-flash\"\n case \"ANTHROPIC\":\n return \"claude-3-5-haiku-latest\"\n case \"XAI\":\n return \"grok-2-latest\"\n case \"WENXIN\":\n return \"ernie-speed-128k\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"sonar\"\n case \"OPENROUTER\":\n return \"qwen/qwen3-30b-a3b-instruct-2507\"\n case \"MODELSCOPE\":\n return \"Qwen/Qwen2.5-32B-Instruct\"\n case \"GITEE\":\n return \"Qwen2-7B-Instruct\"\n default:\n return \"Unknown\"\n }\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: getEnvironmentVariable(\"HANLIN_API_KEY\"),\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: getEnvironmentVariable(\"HANLIN_OPEN_API_KEY\"),\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "29a15a0ce470e2220fe29f0ce50601dd1144cdc4": {"t": 1785757555.3400066, "n": 96651, "h": "eba070b11a8b57ac", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n \n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"qwen-turbo\", displayName: \"Qwen-Turbo\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 1, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.04\n AllModels(name: \"qwen-max\", displayName: \"Qwen-Max\", identity: \"model\", position: 2, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"qwen-long\", displayName: \"Qwen-Long\", identity: \"model\", position: 3, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-turbo\", displayName: \"Qwen-Omni-Turbo\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen-vl-plus-latest\", displayName: \"Qwen-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.006\n AllModels(name: \"qwen-vl-max-latest\", displayName: \"Qwen-VL-Max\", identity: \"model\", position: 5, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"qwq-plus\", displayName: \"Qwen-QwQ-Plus\", identity: \"model\", position: 6, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"qvq-plus\", displayName: \"Qwen-QVQ-Plus\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.02\n AllModels(name: \"qvq-max\", displayName: \"Qwen-QVQ-Max\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image\", displayName: \"Qwen-Image\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4-flash-250414\", displayName: \"GLM4-Flash\", identity: \"model\", position: 12, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0005\n AllModels(name: \"glm-4-air-250414\", displayName: \"GLM4-Air\", identity: \"model\", position: 14, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4-plus\", displayName: \"GLM4-Plus\", identity: \"model\", position: 15, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-4-long\", displayName: \"GLM4-Long\", identity: \"model\", position: 16, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-z1-flash\", displayName: \"GLM-Z1-Flash\", identity: \"model\", position: 17, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.0005\n AllModels(name: \"glm-z1-air\", displayName: \"GLM-Z1-Air\", identity: \"model\", position: 18, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-250615\", displayName: \"Doubao-Seed-1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-1-5-lite-32k-250115\", displayName: \"Doubao1.5-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-1-5-pro-32k-250115\", displayName: \"Doubao1.5-Pro\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"doubao-1-5-vision-lite-250315\", displayName: \"Doubao1.5-Vision-Lite\", identity: \"model\", position: 25, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"doubao-1-5-vision-pro-250328\", displayName: \"Doubao1.5-Vision-Pro\", identity: \"model\", position: 26, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-250415\", displayName: \"Doubao1.5-Thinking-Pro\", identity: \"model\", position: 27, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-m-250415\", displayName: \"Doubao1.5-Thinking-Pro-M\", identity: \"model\", position: 28, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-V3.1\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-V3.1-Thinking\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0711-preview\", displayName: \"Kimi-Auto\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.079\n AllModels(name: \"step-2-16k\", displayName: \"Step2\", identity: \"model\", position: 47, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-1o-turbo-vision\", displayName: \"Step1o-Turbo\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.0425\n AllModels(name: \"step-1o-vision-32k\", displayName: \"Step1o\", identity: \"model\", position: 49, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-Text-01\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"abab6.5s-chat\", displayName: \"Abab6.5s\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00189\n AllModels(name: \"THUDM/GLM-4-32B-0414\", displayName: \"GLM-4-32B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"THUDM/GLM-Z1-9B-0414\", displayName: \"GLM-Z1-9B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-32B-0414\", displayName: \"GLM-Z1-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-Rumination-32B-0414\", displayName: \"GLM-Z1-Rumination-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"internlm/internlm2_5-20b-chat\", displayName: \"Internlm2.5-20B(SiliconCloud)\", identity: \"model\", position: 57, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"Qwen/Qwen3-14B\", displayName: \"Qwen3-14B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B\", displayName: \"Qwen3-30B-A3B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"Qwen/Qwen3-32B\", displayName: \"Qwen3-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B\", displayName: \"Qwen3-235B-A22B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"deepseek-ai/DeepSeek-V3\", displayName: \"DeepSeek-V3(SiliconCloud)\", identity: \"model\", position: 58, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-R1\", displayName: \"DeepSeek-R1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.1\", displayName: \"DeepSeek-V3.1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00126\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\", displayName: \"DeepSeek-R1-Distill-Qwen-32B(SiliconCloud)\", identity: \"model\", position: 60, company: \"SILICONCLOUD\", price:2, isHidden:true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.00099\n AllModels(name: \"deepseek-ai/deepseek-vl2\", displayName: \"DeepSeek-VL2(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:1, isHidden:true, supportsSearch: true, supportsMultimodal: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct\", displayName: \"Kimi-K2-Instruct(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-14B-Instruct_repeat_ms\", displayName: \"Qwen2.5-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-72B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-14B_repeat_ms\", displayName: \"Qwen3-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-32B_repeat_ms\", displayName: \"Qwen3-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B_repeat_ms\", displayName: \"Qwen3-235B-A22B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-V3-0324_repeat_ms\", displayName: \"DeepSeek-V3(ModelScope)\", identity: \"model\", position: 64, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-7B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-7B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-32B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-72B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-R1_repeat_ms\", displayName: \"DeepSeek-R1(ModelScope)\", identity: \"model\", position: 66, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QwQ-32B_repeat_ms\", displayName: \"QwQ-32B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QVQ-72B-Preview_repeat_ms\", displayName: \"QVQ-72B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"MusePublic/489_ckpt_FLUX_1_repeat_ms\", displayName: \"Flux.1-dev\", identity: \"model\", position: 68, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gitee\n // 0.01/次\n AllModels(name: \"Fin-R1\", displayName: \"Fin-R1\", identity: \"model\", position: 69, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.01/次\n AllModels(name: \"GLM-4-9B-Chat\", displayName: \"GLM-4-9B\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01/次\n AllModels(name: \"InternLM3-8B-Instruct\", displayName: \"InternLM3-8B-Instruct\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n // 0.02/次\n AllModels(name: \"Qwen2.5-72B-Instruct\", displayName: \"Qwen2.5-72B-Instruct\", identity: \"model\", position: 72, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-3-5-haiku-latest\", displayName: \"Claude3.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-3-7-sonnet-latest\", displayName: \"Claude3.7-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-0\", displayName: \"Claude4.0-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-0\", displayName: \"Claude4.0-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-3-latest\", displayName: \"Grok3\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.1095\n AllModels(name: \"grok-3-fast-latest\", displayName: \"Grok3-Fast\", identity: \"model\", position: 92, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00584\n AllModels(name: \"grok-3-mini-latest\", displayName: \"Grok3-Mini\", identity: \"model\", position: 93, company: \"XAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01679\n AllModels(name: \"grok-3-mini-fast-latest\", displayName: \"Grok3-Mini-Fast\", identity: \"model\", position: 94, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0438\n AllModels(name: \"grok-2-latest\", displayName: \"Grok2\", identity: \"model\", position: 95, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.073\n AllModels(name: \"grok-2-vision-latest\", displayName: \"Grok2-Vision\", identity: \"model\", position: 96, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"qwen/qwen3-32b:free\", displayName: \"Qwen3-32B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen3-235b-a22b:free\", displayName: \"Qwen3-235B-A22B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen2.5-vl-72b-instruct:free\", displayName: \"Qwen2.5VL-72B(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro-exp-03-25:free\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-scout:free\", displayName: \"Llama4-Scout(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-maverick:free\", displayName: \"Llama4-Maverick(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"deepseek/deepseek-chat-v3-0324:free\", displayName: \"DeepSeek-V3(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-prover-v2:free\", displayName: \"DeepSeek-Prover-V2(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-r1:free\", displayName: \"DeepSeek-R1(OpenRouter)\", identity: \"model\", position: 107, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0\n AllModels(name: \"qwen/qwq-32b:free\", displayName: \"Qwen-QWQ-32B(OpenRouter)\", identity: \"model\", position: 108, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n\n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n switch company.uppercased() {\n case \"QWEN\":\n return \"qwen-turbo\"\n case \"ZHIPUAI\":\n return \"glm-4-flash\"\n case \"DOUBAO\":\n return \"doubao-1-5-lite-32k-250115\"\n case \"DEEPSEEK\":\n return \"deepseek-chat\"\n case \"SILICONCLOUD\":\n return \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n case \"HUNYUAN\":\n return \"hunyuan-lite\"\n case \"YI\":\n return \"yi-lightning\"\n case \"KIMI\":\n return \"moonshot-v1-auto\"\n case \"STEP\":\n return \"step-2-mini\"\n case \"OPENAI\":\n return \"gpt-4o-mini\"\n case \"GOOGLE\":\n return \"gemini-2.0-flash\"\n case \"ANTHROPIC\":\n return \"claude-3-5-haiku-latest\"\n case \"XAI\":\n return \"grok-2-latest\"\n case \"WENXIN\":\n return \"ernie-speed-128k\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"sonar\"\n case \"OPENROUTER\":\n return \"qwen/qwen3-30b-a3b-instruct-2507\"\n case \"MODELSCOPE\":\n return \"Qwen/Qwen2.5-32B-Instruct\"\n case \"GITEE\":\n return \"Qwen2-7B-Instruct\"\n default:\n return \"Unknown\"\n }\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: getEnvironmentVariable(\"HANLIN_API_KEY\"),\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: getEnvironmentVariable(\"HANLIN_OPEN_API_KEY\"),\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.net/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/account/api/keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n SearchKeys(\n name: \"PERPLEXITY_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/search\",\n price: 0.005,\n isUsing: false,\n help: \"https://www.perplexity.ai/account/api/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\n// 重载函数:处理 APIKeys 对象,自定义供应商显示其名称\nfunc getCompanyName(for apiKey: APIKeys) -> String {\n // 如果是自定义供应商,直接返回其名称\n if apiKey.from == .custom {\n return apiKey.name ?? \"自定义供应商\"\n }\n // 否则使用原有的本地化逻辑\n return getCompanyName(for: apiKey.company ?? \"Unknown\")\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "d9c29c5ca79e1594087f38b2e58afcda34ac4c8e": {"t": 1785757558.9419873, "n": 96070, "h": "603417c23fc95d4e", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: Cherry_IN\n \n \n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"qwen-turbo\", displayName: \"Qwen-Turbo\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 1, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.04\n AllModels(name: \"qwen-max\", displayName: \"Qwen-Max\", identity: \"model\", position: 2, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"qwen-long\", displayName: \"Qwen-Long\", identity: \"model\", position: 3, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-turbo\", displayName: \"Qwen-Omni-Turbo\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen-vl-plus-latest\", displayName: \"Qwen-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.006\n AllModels(name: \"qwen-vl-max-latest\", displayName: \"Qwen-VL-Max\", identity: \"model\", position: 5, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"qwq-plus\", displayName: \"Qwen-QwQ-Plus\", identity: \"model\", position: 6, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"qvq-plus\", displayName: \"Qwen-QVQ-Plus\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.02\n AllModels(name: \"qvq-max\", displayName: \"Qwen-QVQ-Max\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image\", displayName: \"Qwen-Image\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4-flash-250414\", displayName: \"GLM4-Flash\", identity: \"model\", position: 12, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0005\n AllModels(name: \"glm-4-air-250414\", displayName: \"GLM4-Air\", identity: \"model\", position: 14, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4-plus\", displayName: \"GLM4-Plus\", identity: \"model\", position: 15, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-4-long\", displayName: \"GLM4-Long\", identity: \"model\", position: 16, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-z1-flash\", displayName: \"GLM-Z1-Flash\", identity: \"model\", position: 17, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.0005\n AllModels(name: \"glm-z1-air\", displayName: \"GLM-Z1-Air\", identity: \"model\", position: 18, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-250615\", displayName: \"Doubao-Seed-1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-1-5-lite-32k-250115\", displayName: \"Doubao1.5-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-1-5-pro-32k-250115\", displayName: \"Doubao1.5-Pro\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"doubao-1-5-vision-lite-250315\", displayName: \"Doubao1.5-Vision-Lite\", identity: \"model\", position: 25, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"doubao-1-5-vision-pro-250328\", displayName: \"Doubao1.5-Vision-Pro\", identity: \"model\", position: 26, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-250415\", displayName: \"Doubao1.5-Thinking-Pro\", identity: \"model\", position: 27, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-m-250415\", displayName: \"Doubao1.5-Thinking-Pro-M\", identity: \"model\", position: 28, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-V3.1\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-V3.1-Thinking\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0711-preview\", displayName: \"Kimi-Auto\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.079\n AllModels(name: \"step-2-16k\", displayName: \"Step2\", identity: \"model\", position: 47, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-1o-turbo-vision\", displayName: \"Step1o-Turbo\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.0425\n AllModels(name: \"step-1o-vision-32k\", displayName: \"Step1o\", identity: \"model\", position: 49, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-Text-01\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"abab6.5s-chat\", displayName: \"Abab6.5s\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00189\n AllModels(name: \"THUDM/GLM-4-32B-0414\", displayName: \"GLM-4-32B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"THUDM/GLM-Z1-9B-0414\", displayName: \"GLM-Z1-9B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-32B-0414\", displayName: \"GLM-Z1-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-Rumination-32B-0414\", displayName: \"GLM-Z1-Rumination-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"internlm/internlm2_5-20b-chat\", displayName: \"Internlm2.5-20B(SiliconCloud)\", identity: \"model\", position: 57, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"Qwen/Qwen3-14B\", displayName: \"Qwen3-14B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B\", displayName: \"Qwen3-30B-A3B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"Qwen/Qwen3-32B\", displayName: \"Qwen3-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B\", displayName: \"Qwen3-235B-A22B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"deepseek-ai/DeepSeek-V3\", displayName: \"DeepSeek-V3(SiliconCloud)\", identity: \"model\", position: 58, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-R1\", displayName: \"DeepSeek-R1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.1\", displayName: \"DeepSeek-V3.1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00126\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\", displayName: \"DeepSeek-R1-Distill-Qwen-32B(SiliconCloud)\", identity: \"model\", position: 60, company: \"SILICONCLOUD\", price:2, isHidden:true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.00099\n AllModels(name: \"deepseek-ai/deepseek-vl2\", displayName: \"DeepSeek-VL2(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:1, isHidden:true, supportsSearch: true, supportsMultimodal: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct\", displayName: \"Kimi-K2-Instruct(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-14B-Instruct_repeat_ms\", displayName: \"Qwen2.5-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-72B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-14B_repeat_ms\", displayName: \"Qwen3-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-32B_repeat_ms\", displayName: \"Qwen3-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B_repeat_ms\", displayName: \"Qwen3-235B-A22B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-V3-0324_repeat_ms\", displayName: \"DeepSeek-V3(ModelScope)\", identity: \"model\", position: 64, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-7B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-7B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-32B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-72B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-R1_repeat_ms\", displayName: \"DeepSeek-R1(ModelScope)\", identity: \"model\", position: 66, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QwQ-32B_repeat_ms\", displayName: \"QwQ-32B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QVQ-72B-Preview_repeat_ms\", displayName: \"QVQ-72B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"MusePublic/489_ckpt_FLUX_1_repeat_ms\", displayName: \"Flux.1-dev\", identity: \"model\", position: 68, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gitee\n // 0.01/次\n AllModels(name: \"Fin-R1\", displayName: \"Fin-R1\", identity: \"model\", position: 69, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.01/次\n AllModels(name: \"GLM-4-9B-Chat\", displayName: \"GLM-4-9B\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01/次\n AllModels(name: \"InternLM3-8B-Instruct\", displayName: \"InternLM3-8B-Instruct\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n // 0.02/次\n AllModels(name: \"Qwen2.5-72B-Instruct\", displayName: \"Qwen2.5-72B-Instruct\", identity: \"model\", position: 72, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-3-5-haiku-latest\", displayName: \"Claude3.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-3-7-sonnet-latest\", displayName: \"Claude3.7-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-0\", displayName: \"Claude4.0-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-0\", displayName: \"Claude4.0-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-3-latest\", displayName: \"Grok3\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.1095\n AllModels(name: \"grok-3-fast-latest\", displayName: \"Grok3-Fast\", identity: \"model\", position: 92, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00584\n AllModels(name: \"grok-3-mini-latest\", displayName: \"Grok3-Mini\", identity: \"model\", position: 93, company: \"XAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01679\n AllModels(name: \"grok-3-mini-fast-latest\", displayName: \"Grok3-Mini-Fast\", identity: \"model\", position: 94, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0438\n AllModels(name: \"grok-2-latest\", displayName: \"Grok2\", identity: \"model\", position: 95, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.073\n AllModels(name: \"grok-2-vision-latest\", displayName: \"Grok2-Vision\", identity: \"model\", position: 96, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"qwen/qwen3-32b:free\", displayName: \"Qwen3-32B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen3-235b-a22b:free\", displayName: \"Qwen3-235B-A22B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen2.5-vl-72b-instruct:free\", displayName: \"Qwen2.5VL-72B(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro-exp-03-25:free\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-scout:free\", displayName: \"Llama4-Scout(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-maverick:free\", displayName: \"Llama4-Maverick(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"deepseek/deepseek-chat-v3-0324:free\", displayName: \"DeepSeek-V3(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-prover-v2:free\", displayName: \"DeepSeek-Prover-V2(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-r1:free\", displayName: \"DeepSeek-R1(OpenRouter)\", identity: \"model\", position: 107, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0\n AllModels(name: \"qwen/qwq-32b:free\", displayName: \"Qwen-QWQ-32B(OpenRouter)\", identity: \"model\", position: 108, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n\n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n switch company.uppercased() {\n case \"QWEN\":\n return \"qwen-turbo\"\n case \"ZHIPUAI\":\n return \"glm-4-flash\"\n case \"DOUBAO\":\n return \"doubao-1-5-lite-32k-250115\"\n case \"DEEPSEEK\":\n return \"deepseek-chat\"\n case \"SILICONCLOUD\":\n return \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n case \"HUNYUAN\":\n return \"hunyuan-lite\"\n case \"YI\":\n return \"yi-lightning\"\n case \"KIMI\":\n return \"moonshot-v1-auto\"\n case \"STEP\":\n return \"step-2-mini\"\n case \"OPENAI\":\n return \"gpt-4o-mini\"\n case \"GOOGLE\":\n return \"gemini-2.0-flash\"\n case \"ANTHROPIC\":\n return \"claude-3-5-haiku-latest\"\n case \"XAI\":\n return \"grok-2-latest\"\n case \"WENXIN\":\n return \"ernie-speed-128k\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"sonar\"\n case \"OPENROUTER\":\n return \"qwen/qwen3-30b-a3b-instruct-2507\"\n case \"MODELSCOPE\":\n return \"Qwen/Qwen2.5-32B-Instruct\"\n case \"GITEE\":\n return \"Qwen2-7B-Instruct\"\n default:\n return \"Unknown\"\n }\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: getEnvironmentVariable(\"HANLIN_API_KEY\"),\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: getEnvironmentVariable(\"HANLIN_OPEN_API_KEY\"),\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false,\n from: .system\n ),\n APIKeys(\n name: \"CHERRY_IN_API_KEY\",\n company: \"CHERRY_IN\",\n key: \"\",\n requestURL: \"https://open.cherryin.ai/v1/chat/completions\",\n help: \"https://open.cherryin.ai/console/token\",\n from: .system\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\",\n from: .system\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\",\n from: .system\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\",\n from: .system\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\",\n from: .system\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\",\n from: .system\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\",\n from: .system\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\",\n from: .system\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\",\n from: .system\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\",\n from: .system\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/pplx-api\",\n from: .system\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\",\n from: .system\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\",\n from: .system\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\",\n from: .system\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\",\n from: .system\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\",\n from: .system\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n case \"CHERRY_IN\":\n return \"cherry\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "825c032280eb6f313eaaee36f051e76f2e7700c9": {"t": 1785757560.510287, "n": 95266, "h": "42b93eafea9a2acb", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 从Bundle获取API密钥配置\nfunc getEnvironmentVariable(_ name: String) -> String {\n // 从Info.plist中读取配置的值\n let value = Bundle.main.object(forInfoDictionaryKey: name) as? String ?? \"\"\n return value\n}\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"qwen-turbo\", displayName: \"Qwen-Turbo\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 1, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.04\n AllModels(name: \"qwen-max\", displayName: \"Qwen-Max\", identity: \"model\", position: 2, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"qwen-long\", displayName: \"Qwen-Long\", identity: \"model\", position: 3, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-turbo\", displayName: \"Qwen-Omni-Turbo\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen-vl-plus-latest\", displayName: \"Qwen-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.006\n AllModels(name: \"qwen-vl-max-latest\", displayName: \"Qwen-VL-Max\", identity: \"model\", position: 5, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"qwq-plus\", displayName: \"Qwen-QwQ-Plus\", identity: \"model\", position: 6, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"qvq-plus\", displayName: \"Qwen-QVQ-Plus\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.02\n AllModels(name: \"qvq-max\", displayName: \"Qwen-QVQ-Max\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image\", displayName: \"Qwen-Image\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4-flash-250414\", displayName: \"GLM4-Flash\", identity: \"model\", position: 12, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0005\n AllModels(name: \"glm-4-air-250414\", displayName: \"GLM4-Air\", identity: \"model\", position: 14, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4-plus\", displayName: \"GLM4-Plus\", identity: \"model\", position: 15, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-4-long\", displayName: \"GLM4-Long\", identity: \"model\", position: 16, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-z1-flash\", displayName: \"GLM-Z1-Flash\", identity: \"model\", position: 17, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.0005\n AllModels(name: \"glm-z1-air\", displayName: \"GLM-Z1-Air\", identity: \"model\", position: 18, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-250615\", displayName: \"Doubao-Seed-1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-1-5-lite-32k-250115\", displayName: \"Doubao1.5-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-1-5-pro-32k-250115\", displayName: \"Doubao1.5-Pro\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"doubao-1-5-vision-lite-250315\", displayName: \"Doubao1.5-Vision-Lite\", identity: \"model\", position: 25, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"doubao-1-5-vision-pro-250328\", displayName: \"Doubao1.5-Vision-Pro\", identity: \"model\", position: 26, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-250415\", displayName: \"Doubao1.5-Thinking-Pro\", identity: \"model\", position: 27, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-m-250415\", displayName: \"Doubao1.5-Thinking-Pro-M\", identity: \"model\", position: 28, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-V3.1\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-V3.1-Thinking\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0711-preview\", displayName: \"Kimi-Auto\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.079\n AllModels(name: \"step-2-16k\", displayName: \"Step2\", identity: \"model\", position: 47, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-1o-turbo-vision\", displayName: \"Step1o-Turbo\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.0425\n AllModels(name: \"step-1o-vision-32k\", displayName: \"Step1o\", identity: \"model\", position: 49, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-Text-01\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"abab6.5s-chat\", displayName: \"Abab6.5s\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00189\n AllModels(name: \"THUDM/GLM-4-32B-0414\", displayName: \"GLM-4-32B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"THUDM/GLM-Z1-9B-0414\", displayName: \"GLM-Z1-9B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-32B-0414\", displayName: \"GLM-Z1-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-Rumination-32B-0414\", displayName: \"GLM-Z1-Rumination-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"internlm/internlm2_5-20b-chat\", displayName: \"Internlm2.5-20B(SiliconCloud)\", identity: \"model\", position: 57, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"Qwen/Qwen3-14B\", displayName: \"Qwen3-14B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B\", displayName: \"Qwen3-30B-A3B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"Qwen/Qwen3-32B\", displayName: \"Qwen3-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B\", displayName: \"Qwen3-235B-A22B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"deepseek-ai/DeepSeek-V3\", displayName: \"DeepSeek-V3(SiliconCloud)\", identity: \"model\", position: 58, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-R1\", displayName: \"DeepSeek-R1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.1\", displayName: \"DeepSeek-V3.1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00126\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\", displayName: \"DeepSeek-R1-Distill-Qwen-32B(SiliconCloud)\", identity: \"model\", position: 60, company: \"SILICONCLOUD\", price:2, isHidden:true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.00099\n AllModels(name: \"deepseek-ai/deepseek-vl2\", displayName: \"DeepSeek-VL2(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:1, isHidden:true, supportsSearch: true, supportsMultimodal: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct\", displayName: \"Kimi-K2-Instruct(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-14B-Instruct_repeat_ms\", displayName: \"Qwen2.5-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-72B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-14B_repeat_ms\", displayName: \"Qwen3-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-32B_repeat_ms\", displayName: \"Qwen3-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B_repeat_ms\", displayName: \"Qwen3-235B-A22B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-V3-0324_repeat_ms\", displayName: \"DeepSeek-V3(ModelScope)\", identity: \"model\", position: 64, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-7B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-7B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-32B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-72B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-R1_repeat_ms\", displayName: \"DeepSeek-R1(ModelScope)\", identity: \"model\", position: 66, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QwQ-32B_repeat_ms\", displayName: \"QwQ-32B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QVQ-72B-Preview_repeat_ms\", displayName: \"QVQ-72B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"MusePublic/489_ckpt_FLUX_1_repeat_ms\", displayName: \"Flux.1-dev\", identity: \"model\", position: 68, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gitee\n // 0.01/次\n AllModels(name: \"Fin-R1\", displayName: \"Fin-R1\", identity: \"model\", position: 69, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.01/次\n AllModels(name: \"GLM-4-9B-Chat\", displayName: \"GLM-4-9B\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01/次\n AllModels(name: \"InternLM3-8B-Instruct\", displayName: \"InternLM3-8B-Instruct\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n // 0.02/次\n AllModels(name: \"Qwen2.5-72B-Instruct\", displayName: \"Qwen2.5-72B-Instruct\", identity: \"model\", position: 72, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-3-5-haiku-latest\", displayName: \"Claude3.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-3-7-sonnet-latest\", displayName: \"Claude3.7-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-0\", displayName: \"Claude4.0-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-0\", displayName: \"Claude4.0-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-3-latest\", displayName: \"Grok3\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.1095\n AllModels(name: \"grok-3-fast-latest\", displayName: \"Grok3-Fast\", identity: \"model\", position: 92, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00584\n AllModels(name: \"grok-3-mini-latest\", displayName: \"Grok3-Mini\", identity: \"model\", position: 93, company: \"XAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01679\n AllModels(name: \"grok-3-mini-fast-latest\", displayName: \"Grok3-Mini-Fast\", identity: \"model\", position: 94, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0438\n AllModels(name: \"grok-2-latest\", displayName: \"Grok2\", identity: \"model\", position: 95, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.073\n AllModels(name: \"grok-2-vision-latest\", displayName: \"Grok2-Vision\", identity: \"model\", position: 96, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"qwen/qwen3-32b:free\", displayName: \"Qwen3-32B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen3-235b-a22b:free\", displayName: \"Qwen3-235B-A22B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen2.5-vl-72b-instruct:free\", displayName: \"Qwen2.5VL-72B(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro-exp-03-25:free\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-scout:free\", displayName: \"Llama4-Scout(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-maverick:free\", displayName: \"Llama4-Maverick(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"deepseek/deepseek-chat-v3-0324:free\", displayName: \"DeepSeek-V3(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-prover-v2:free\", displayName: \"DeepSeek-Prover-V2(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-r1:free\", displayName: \"DeepSeek-R1(OpenRouter)\", identity: \"model\", position: 107, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0\n AllModels(name: \"qwen/qwq-32b:free\", displayName: \"Qwen-QWQ-32B(OpenRouter)\", identity: \"model\", position: 108, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n\n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n switch company.uppercased() {\n case \"QWEN\":\n return \"qwen-turbo\"\n case \"ZHIPUAI\":\n return \"glm-4-flash\"\n case \"DOUBAO\":\n return \"doubao-1-5-lite-32k-250115\"\n case \"DEEPSEEK\":\n return \"deepseek-chat\"\n case \"SILICONCLOUD\":\n return \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n case \"HUNYUAN\":\n return \"hunyuan-lite\"\n case \"YI\":\n return \"yi-lightning\"\n case \"KIMI\":\n return \"moonshot-v1-auto\"\n case \"STEP\":\n return \"step-2-mini\"\n case \"OPENAI\":\n return \"gpt-4o-mini\"\n case \"GOOGLE\":\n return \"gemini-2.0-flash\"\n case \"ANTHROPIC\":\n return \"claude-3-5-haiku-latest\"\n case \"XAI\":\n return \"grok-2-latest\"\n case \"WENXIN\":\n return \"ernie-speed-128k\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"sonar\"\n case \"OPENROUTER\":\n return \"google/gemma-3-1b-it:free\"\n case \"MODELSCOPE\":\n return \"Qwen/Qwen2.5-32B-Instruct\"\n case \"GITEE\":\n return \"Qwen2-7B-Instruct\"\n default:\n return \"Unknown\"\n }\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: getEnvironmentVariable(\"HANLIN_API_KEY\"),\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: getEnvironmentVariable(\"HANLIN_OPEN_API_KEY\"),\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\"\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\"\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\"\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\"\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\"\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\"\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\"\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\"\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\"\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\"\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\"\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\"\n ),\n APIKeys(\n name: \"SPARK_API_KEY\",\n company: \"SPARK\",\n key: \"\",\n requestURL: \"https://spark-api-open.xf-yun.com/v1/chat/completions\"\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/pplx-api\"\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\"\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\"\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\"\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\"\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\"\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\"\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "bd71e4ab1e23ad64d1662413911ec9d6f587ef2a": {"t": 1785757563.4360635, "n": 94178, "h": "1cf54153a0c78bd4", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"qwen-turbo\", displayName: \"Qwen-Turbo\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 1, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.04\n AllModels(name: \"qwen-max\", displayName: \"Qwen-Max\", identity: \"model\", position: 2, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"qwen-long\", displayName: \"Qwen-Long\", identity: \"model\", position: 3, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-turbo\", displayName: \"Qwen-Omni-Turbo\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen-vl-plus-latest\", displayName: \"Qwen-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.006\n AllModels(name: \"qwen-vl-max-latest\", displayName: \"Qwen-VL-Max\", identity: \"model\", position: 5, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"qwq-plus\", displayName: \"Qwen-QwQ-Plus\", identity: \"model\", position: 6, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"qvq-plus\", displayName: \"Qwen-QVQ-Plus\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.02\n AllModels(name: \"qvq-max\", displayName: \"Qwen-QVQ-Max\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image\", displayName: \"Qwen-Image\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4-flash-250414\", displayName: \"GLM4-Flash\", identity: \"model\", position: 12, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0005\n AllModels(name: \"glm-4-air-250414\", displayName: \"GLM4-Air\", identity: \"model\", position: 14, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4-plus\", displayName: \"GLM4-Plus\", identity: \"model\", position: 15, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-4-long\", displayName: \"GLM4-Long\", identity: \"model\", position: 16, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-z1-flash\", displayName: \"GLM-Z1-Flash\", identity: \"model\", position: 17, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.0005\n AllModels(name: \"glm-z1-air\", displayName: \"GLM-Z1-Air\", identity: \"model\", position: 18, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-250615\", displayName: \"Doubao-Seed-1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-1-5-lite-32k-250115\", displayName: \"Doubao1.5-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-1-5-pro-32k-250115\", displayName: \"Doubao1.5-Pro\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"doubao-1-5-vision-lite-250315\", displayName: \"Doubao1.5-Vision-Lite\", identity: \"model\", position: 25, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"doubao-1-5-vision-pro-250328\", displayName: \"Doubao1.5-Vision-Pro\", identity: \"model\", position: 26, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-250415\", displayName: \"Doubao1.5-Thinking-Pro\", identity: \"model\", position: 27, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-m-250415\", displayName: \"Doubao1.5-Thinking-Pro-M\", identity: \"model\", position: 28, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-V3.1\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-V3.1-Thinking\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0711-preview\", displayName: \"Kimi-Auto\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.079\n AllModels(name: \"step-2-16k\", displayName: \"Step2\", identity: \"model\", position: 47, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-1o-turbo-vision\", displayName: \"Step1o-Turbo\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.0425\n AllModels(name: \"step-1o-vision-32k\", displayName: \"Step1o\", identity: \"model\", position: 49, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-Text-01\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"abab6.5s-chat\", displayName: \"Abab6.5s\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00189\n AllModels(name: \"THUDM/GLM-4-32B-0414\", displayName: \"GLM-4-32B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"THUDM/GLM-Z1-9B-0414\", displayName: \"GLM-Z1-9B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-32B-0414\", displayName: \"GLM-Z1-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-Rumination-32B-0414\", displayName: \"GLM-Z1-Rumination-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"internlm/internlm2_5-20b-chat\", displayName: \"Internlm2.5-20B(SiliconCloud)\", identity: \"model\", position: 57, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"Qwen/Qwen3-14B\", displayName: \"Qwen3-14B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B\", displayName: \"Qwen3-30B-A3B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"Qwen/Qwen3-32B\", displayName: \"Qwen3-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B\", displayName: \"Qwen3-235B-A22B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"deepseek-ai/DeepSeek-V3\", displayName: \"DeepSeek-V3(SiliconCloud)\", identity: \"model\", position: 58, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-R1\", displayName: \"DeepSeek-R1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.1\", displayName: \"DeepSeek-V3.1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00126\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\", displayName: \"DeepSeek-R1-Distill-Qwen-32B(SiliconCloud)\", identity: \"model\", position: 60, company: \"SILICONCLOUD\", price:2, isHidden:true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.00099\n AllModels(name: \"deepseek-ai/deepseek-vl2\", displayName: \"DeepSeek-VL2(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:1, isHidden:true, supportsSearch: true, supportsMultimodal: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct\", displayName: \"Kimi-K2-Instruct(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-14B-Instruct_repeat_ms\", displayName: \"Qwen2.5-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-72B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-14B_repeat_ms\", displayName: \"Qwen3-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-32B_repeat_ms\", displayName: \"Qwen3-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B_repeat_ms\", displayName: \"Qwen3-235B-A22B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-V3-0324_repeat_ms\", displayName: \"DeepSeek-V3(ModelScope)\", identity: \"model\", position: 64, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-7B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-7B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-32B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-72B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-R1_repeat_ms\", displayName: \"DeepSeek-R1(ModelScope)\", identity: \"model\", position: 66, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QwQ-32B_repeat_ms\", displayName: \"QwQ-32B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QVQ-72B-Preview_repeat_ms\", displayName: \"QVQ-72B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"MusePublic/489_ckpt_FLUX_1_repeat_ms\", displayName: \"Flux.1-dev\", identity: \"model\", position: 68, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gitee\n // 0.01/次\n AllModels(name: \"Fin-R1\", displayName: \"Fin-R1\", identity: \"model\", position: 69, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.01/次\n AllModels(name: \"GLM-4-9B-Chat\", displayName: \"GLM-4-9B\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01/次\n AllModels(name: \"InternLM3-8B-Instruct\", displayName: \"InternLM3-8B-Instruct\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n // 0.02/次\n AllModels(name: \"Qwen2.5-72B-Instruct\", displayName: \"Qwen2.5-72B-Instruct\", identity: \"model\", position: 72, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-3-5-haiku-latest\", displayName: \"Claude3.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-3-7-sonnet-latest\", displayName: \"Claude3.7-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-0\", displayName: \"Claude4.0-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-0\", displayName: \"Claude4.0-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-3-latest\", displayName: \"Grok3\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.1095\n AllModels(name: \"grok-3-fast-latest\", displayName: \"Grok3-Fast\", identity: \"model\", position: 92, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00584\n AllModels(name: \"grok-3-mini-latest\", displayName: \"Grok3-Mini\", identity: \"model\", position: 93, company: \"XAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01679\n AllModels(name: \"grok-3-mini-fast-latest\", displayName: \"Grok3-Mini-Fast\", identity: \"model\", position: 94, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0438\n AllModels(name: \"grok-2-latest\", displayName: \"Grok2\", identity: \"model\", position: 95, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.073\n AllModels(name: \"grok-2-vision-latest\", displayName: \"Grok2-Vision\", identity: \"model\", position: 96, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"qwen/qwen3-32b:free\", displayName: \"Qwen3-32B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen3-235b-a22b:free\", displayName: \"Qwen3-235B-A22B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen2.5-vl-72b-instruct:free\", displayName: \"Qwen2.5VL-72B(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro-exp-03-25:free\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-scout:free\", displayName: \"Llama4-Scout(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-maverick:free\", displayName: \"Llama4-Maverick(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"deepseek/deepseek-chat-v3-0324:free\", displayName: \"DeepSeek-V3(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-prover-v2:free\", displayName: \"DeepSeek-Prover-V2(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-r1:free\", displayName: \"DeepSeek-R1(OpenRouter)\", identity: \"model\", position: 107, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0\n AllModels(name: \"qwen/qwq-32b:free\", displayName: \"Qwen-QWQ-32B(OpenRouter)\", identity: \"model\", position: 108, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n switch company.uppercased() {\n case \"QWEN\":\n return \"qwen-turbo\"\n case \"ZHIPUAI\":\n return \"glm-4-flash\"\n case \"DOUBAO\":\n return \"doubao-1-5-lite-32k-250115\"\n case \"DEEPSEEK\":\n return \"deepseek-chat\"\n case \"SILICONCLOUD\":\n return \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n case \"HUNYUAN\":\n return \"hunyuan-lite\"\n case \"YI\":\n return \"yi-lightning\"\n case \"KIMI\":\n return \"moonshot-v1-auto\"\n case \"STEP\":\n return \"step-2-mini\"\n case \"OPENAI\":\n return \"gpt-4o-mini\"\n case \"GOOGLE\":\n return \"gemini-2.0-flash\"\n case \"ANTHROPIC\":\n return \"claude-3-5-haiku-latest\"\n case \"XAI\":\n return \"grok-2-latest\"\n case \"WENXIN\":\n return \"ernie-speed-128k\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"sonar\"\n case \"OPENROUTER\":\n return \"google/gemma-3-1b-it:free\"\n case \"MODELSCOPE\":\n return \"Qwen/Qwen2.5-32B-Instruct\"\n case \"GITEE\":\n return \"Qwen2-7B-Instruct\"\n default:\n return \"Unknown\"\n }\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\"\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\"\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\"\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\"\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\"\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\"\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\"\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\"\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\"\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\"\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\"\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\"\n ),\n APIKeys(\n name: \"SPARK_API_KEY\",\n company: \"SPARK\",\n key: \"\",\n requestURL: \"https://spark-api-open.xf-yun.com/v1/chat/completions\"\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/pplx-api\"\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\"\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\"\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\"\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\"\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\"\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\"\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}, "ffbc4c60822cf71918ac43e07ac6cdf55dad04f0": {"t": 1785757565.0716374, "n": 96865, "h": "09cdd5bdd873b883", "c": "//\n// InfoComponets.swift\n// AI_HLY\n//\n// Created by 哆啦好多梦 on 12/2/25.\n//\n\nimport Foundation\nimport SwiftUI\nimport SwiftData\n\n// 获得模型列表\nfunc getModelList() -> [AllModels] {\n \n let rawModels: [AllModels] = [\n // MARK: 通义\n // 0.00015\n AllModels(name: \"qwen-flash\", displayName: \"Qwen-Flash\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"qwen-turbo\", displayName: \"Qwen-Turbo\", identity: \"model\", position: 0, company: \"QWEN\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"qwen-plus\", displayName: \"Qwen-Plus\", identity: \"model\", position: 1, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.04\n AllModels(name: \"qwen-max\", displayName: \"Qwen-Max\", identity: \"model\", position: 2, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"qwen-long\", displayName: \"Qwen-Long\", identity: \"model\", position: 3, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.02575\n AllModels(name: \"qwen-omni-turbo\", displayName: \"Qwen-Omni-Turbo\", identity: \"model\", position: 3, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsVoiceGen: true),\n // 0.003\n AllModels(name: \"qwen-vl-plus-latest\", displayName: \"Qwen-VL-Plus\", identity: \"model\", position: 4, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.006\n AllModels(name: \"qwen-vl-max-latest\", displayName: \"Qwen-VL-Max\", identity: \"model\", position: 5, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false, supportsToolUse: true),\n // 0.0028\n AllModels(name: \"qwq-plus\", displayName: \"Qwen-QwQ-Plus\", identity: \"model\", position: 6, company: \"QWEN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"qvq-plus\", displayName: \"Qwen-QVQ-Plus\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.02\n AllModels(name: \"qvq-max\", displayName: \"Qwen-QVQ-Max\", identity: \"model\", position: 7, company: \"QWEN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.14\n AllModels(name: \"wanx2.1-t2i-turbo\", displayName: \"WanX2.1-Turbo\", identity: \"model\", position: 10, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.2\n AllModels(name: \"wanx2.1-t2i-plus\", displayName: \"WanX2.1-Plus\", identity: \"model\", position: 11, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.25\n AllModels(name: \"qwen-image\", displayName: \"Qwen-Image\", identity: \"model\", position: 12, company: \"QWEN\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智谱\n // 免费\n AllModels(name: \"glm-4.5-flash\", displayName: \"GLM4.5-Flash\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"glm-4.5-air\", displayName: \"GLM4.5-Air\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4.5\", displayName: \"GLM4.5\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.004\n AllModels(name: \"glm-4.5v\", displayName: \"GLM4.5V\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.1v-thinking-flash\", displayName: \"GLM4.1V-Thinking\", identity: \"model\", position: 11, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4-flash-250414\", displayName: \"GLM4-Flash\", identity: \"model\", position: 12, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0005\n AllModels(name: \"glm-4-air-250414\", displayName: \"GLM4-Air\", identity: \"model\", position: 14, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"glm-4-plus\", displayName: \"GLM4-Plus\", identity: \"model\", position: 15, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-4-long\", displayName: \"GLM4-Long\", identity: \"model\", position: 16, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"glm-z1-flash\", displayName: \"GLM-Z1-Flash\", identity: \"model\", position: 17, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.0005\n AllModels(name: \"glm-z1-air\", displayName: \"GLM-Z1-Air\", identity: \"model\", position: 18, company: \"ZHIPUAI\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"glm-4v-flash\", displayName: \"GLM4V-Flash\", identity: \"model\", position: 19, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.003\n AllModels(name: \"glm-4v-plus-0111\", displayName: \"GLM4V-Plus\", identity: \"model\", position: 20, company: \"ZHIPUAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 免费\n AllModels(name: \"cogview-3-flash\", displayName: \"CogView3-Flash\", identity: \"model\", position: 21, company: \"ZHIPUAI\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.14\n AllModels(name: \"cogview-4-250304\", displayName: \"CogView4\", identity: \"model\", position: 22, company: \"ZHIPUAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 豆包\n // 0.0014\n AllModels(name: \"doubao-seed-1-6-250615\", displayName: \"Doubao-Seed-1.6\", identity: \"model\", position: 11, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00045\n AllModels(name: \"doubao-1-5-lite-32k-250115\", displayName: \"Doubao1.5-Lite\", identity: \"model\", position: 23, company: \"DOUBAO\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"doubao-1-5-pro-32k-250115\", displayName: \"Doubao1.5-Pro\", identity: \"model\", position: 24, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.003\n AllModels(name: \"doubao-1-5-vision-lite-250315\", displayName: \"Doubao1.5-Vision-Lite\", identity: \"model\", position: 25, company: \"DOUBAO\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"doubao-1-5-vision-pro-250328\", displayName: \"Doubao1.5-Vision-Pro\", identity: \"model\", position: 26, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-250415\", displayName: \"Doubao1.5-Thinking-Pro\", identity: \"model\", position: 27, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"doubao-1-5-thinking-pro-m-250415\", displayName: \"Doubao1.5-Thinking-Pro-M\", identity: \"model\", position: 28, company: \"DOUBAO\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: Deepseek\n // 0.005\n AllModels(name: \"deepseek-chat\", displayName: \"DeepSeek-V3.1\", identity: \"model\", position: 29, company: \"DEEPSEEK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-reasoner\", displayName: \"DeepSeek-V3.1-Thinking\", identity: \"model\", position: 30, company: \"DEEPSEEK\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n \n // MARK: 百度\n // 免费\n AllModels(name: \"ernie-speed-128k\", displayName: \"ERNIE-Speed\", identity: \"model\", position: 31, company: \"WENXIN\", price: 0, isHidden: true, supportsSearch: true),\n // 0.002\n AllModels(name: \"ernie-4.5-turbo-128k\", displayName: \"ERNIE4.5-Turbo\", identity: \"model\", position: 32, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"ernie-4.5-turbo-vl-32k\", displayName: \"ERNIE4.5-Turbo-VL\", identity: \"model\", position: 33, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"ernie-4.5-8k-preview\", displayName: \"ERNIE4.5-Preview\", identity: \"model\", position: 34, company: \"WENXIN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"ernie-x1-turbo-32k\", displayName: \"ERNIE-X1-Turbo\", identity: \"model\", position: 35, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.005\n AllModels(name: \"ernie-x1-32k\", displayName: \"ERNIE-X1\", identity: \"model\", position: 36, company: \"WENXIN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n \n // MARK: 混元\n // 免费\n AllModels(name: \"hunyuan-lite\", displayName: \"Hunyuan-Lite\", identity: \"model\", position: 37, company: \"HUNYUAN\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0014\n AllModels(name: \"hunyuan-turbos-latest\", displayName: \"Hunyuan-TurboS\", identity: \"model\", position: 38, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"hunyuan-t1-latest\", displayName: \"Hunyuan-T1\", identity: \"model\", position: 39, company: \"HUNYUAN\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.018\n AllModels(name: \"hunyuan-vision\", displayName: \"Hunyuan-Vision\", identity: \"model\", position: 40, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.08\n AllModels(name: \"hunyuan-turbo-vision\", displayName: \"Hunyuan-Vision-Turbo\", identity: \"model\", position: 41, company: \"HUNYUAN\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n \n // MARK: Yi\n // 0.00099\n AllModels(name: \"yi-lightning\", displayName: \"Yi-Light\", identity: \"model\", position: 42, company: \"YI\", price: 1, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"yi-vision-v2\", displayName: \"Yi-Vision\", identity: \"model\", position: 43, company: \"YI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: Kimi\n // 0.006\n AllModels(name: \"kimi-k2-0711-preview\", displayName: \"Kimi-Auto\", identity: \"model\", position: 44, company: \"KIMI\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: 阶跃星辰\n // 0.0015\n AllModels(name: \"step-2-mini\", displayName: \"Step2-Mini\", identity: \"model\", position: 46, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.079\n AllModels(name: \"step-2-16k\", displayName: \"Step2\", identity: \"model\", position: 47, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0525\n AllModels(name: \"step-1o-turbo-vision\", displayName: \"Step1o-Turbo\", identity: \"model\", position: 48, company: \"STEP\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0.0425\n AllModels(name: \"step-1o-vision-32k\", displayName: \"Step1o\", identity: \"model\", position: 49, company: \"STEP\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n \n // MARK: 讯飞星火\n // 0.0015\n AllModels(name: \"lite\", displayName: \"Spark-Lite\", identity: \"model\", position: 50, company: \"SPARK\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.006\n AllModels(name: \"generalv3\", displayName: \"Spark-Pro\", identity: \"model\", position: 51, company: \"SPARK\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.026\n AllModels(name: \"generalv3.5\", displayName: \"Spark-Max\", identity: \"model\", position: 52, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.06\n AllModels(name: \"4.0Ultra\", displayName: \"Spark-Ultra\", identity: \"model\", position: 53, company: \"SPARK\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: MiniMax\n // 0.0045\n AllModels(name: \"MiniMax-Text-01\", displayName: \"MiniMax-Text-01\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"abab6.5s-chat\", displayName: \"Abab6.5s\", identity: \"model\", position: 50, company: \"MINIMAX\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: SiliconCloud\n // 0\n AllModels(name: \"THUDM/GLM-4-9B-0414\", displayName: \"GLM-4-9B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00189\n AllModels(name: \"THUDM/GLM-4-32B-0414\", displayName: \"GLM-4-32B(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5-Air\", displayName: \"GLM-4.5-Air(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00875\n AllModels(name: \"zai-org/GLM-4.5\", displayName: \"GLM-4.5(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0035\n AllModels(name: \"zai-org/GLM-4.5V\", displayName: \"GLM-4.5V(SiliconCloud)\", identity: \"model\", position: 54, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal:true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0\n AllModels(name: \"THUDM/GLM-Z1-9B-0414\", displayName: \"GLM-Z1-9B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-32B-0414\", displayName: \"GLM-Z1-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"THUDM/GLM-Z1-Rumination-32B-0414\", displayName: \"GLM-Z1-Rumination-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0\n AllModels(name: \"internlm/internlm2_5-7b-chat\", displayName: \"Internlm2.5-7B(SiliconCloud)\", identity: \"model\", position: 56, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.001\n AllModels(name: \"internlm/internlm2_5-20b-chat\", displayName: \"Internlm2.5-20B(SiliconCloud)\", identity: \"model\", position: 57, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0\n AllModels(name: \"Qwen/Qwen3-8B\", displayName: \"Qwen3-8B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00125\n AllModels(name: \"Qwen/Qwen3-14B\", displayName: \"Qwen3-14B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 1, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B\", displayName: \"Qwen3-30B-A3B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Instruct-2507\", displayName: \"Qwen3-30B-A3B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00175\n AllModels(name: \"Qwen/Qwen3-30B-A3B-Thinking-2507\", displayName: \"Qwen3-30B-A3B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0025\n AllModels(name: \"Qwen/Qwen3-32B\", displayName: \"Qwen3-32B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B\", displayName: \"Qwen3-235B-A22B(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Instruct-2507\", displayName: \"Qwen3-235B-A22B-Instruct-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00625\n AllModels(name: \"Qwen/Qwen3-235B-A22B-Thinking-2507\", displayName: \"Qwen3-235B-A22B-Thinking-2507(SiliconCloud)\", identity: \"model\", position: 55, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.005\n AllModels(name: \"deepseek-ai/DeepSeek-V3\", displayName: \"DeepSeek-V3(SiliconCloud)\", identity: \"model\", position: 58, company: \"SILICONCLOUD\", price: 2, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-R1\", displayName: \"DeepSeek-R1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01\n AllModels(name: \"deepseek-ai/DeepSeek-V3.1\", displayName: \"DeepSeek-V3.1(SiliconCloud)\", identity: \"model\", position: 59, company: \"SILICONCLOUD\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.00126\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-32B\", displayName: \"DeepSeek-R1-Distill-Qwen-32B(SiliconCloud)\", identity: \"model\", position: 60, company: \"SILICONCLOUD\", price:2, isHidden:true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.00099\n AllModels(name: \"deepseek-ai/deepseek-vl2\", displayName: \"DeepSeek-VL2(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:1, isHidden:true, supportsSearch: true, supportsMultimodal: true),\n // 0.01\n AllModels(name: \"moonshotai/Kimi-K2-Instruct\", displayName: \"Kimi-K2-Instruct(SiliconCloud)\", identity: \"model\", position: 61, company: \"SILICONCLOUD\", price:3, isHidden:true, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors\", displayName: \"Kolors(SiliconCloud)\", identity: \"model\", position: 62, company: \"SILICONCLOUD\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: ModelScope\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-14B-Instruct_repeat_ms\", displayName: \"Qwen2.5-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-72B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天Qwen/Qwen3-14B\n AllModels(name: \"Qwen/Qwen3-14B_repeat_ms\", displayName: \"Qwen3-14B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-32B_repeat_ms\", displayName: \"Qwen3-32B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen3-235B-A22B_repeat_ms\", displayName: \"Qwen3-235B-A22B(ModelScope)\", identity: \"model\", position: 63, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-V3-0324_repeat_ms\", displayName: \"DeepSeek-V3(ModelScope)\", identity: \"model\", position: 64, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-7B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-7B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-32B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-32B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/Qwen2.5-VL-72B-Instruct_repeat_ms\", displayName: \"Qwen2.5-VL-72B(ModelScope)\", identity: \"model\", position: 65, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"deepseek-ai/DeepSeek-R1_repeat_ms\", displayName: \"DeepSeek-R1(ModelScope)\", identity: \"model\", position: 66, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QwQ-32B_repeat_ms\", displayName: \"QwQ-32B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"Qwen/QVQ-72B-Preview_repeat_ms\", displayName: \"QVQ-72B(ModelScope)\", identity: \"model\", position: 67, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 免费2000次/天\n AllModels(name: \"MusePublic/489_ckpt_FLUX_1_repeat_ms\", displayName: \"Flux.1-dev\", identity: \"model\", position: 68, company: \"MODELSCOPE\", price: 0, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gitee\n // 0.01/次\n AllModels(name: \"Fin-R1\", displayName: \"Fin-R1\", identity: \"model\", position: 69, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true),\n // 0.01/次\n AllModels(name: \"GLM-4-9B-Chat\", displayName: \"GLM-4-9B\", identity: \"model\", position: 70, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.01/次\n AllModels(name: \"InternLM3-8B-Instruct\", displayName: \"InternLM3-8B-Instruct\", identity: \"model\", position: 71, company: \"GITEE\", price: 0, isHidden: true, supportsSearch: true),\n // 0.02/次\n AllModels(name: \"Qwen2.5-72B-Instruct\", displayName: \"Qwen2.5-72B-Instruct\", identity: \"model\", position: 72, company: \"GITEE\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n \n // MARK: GPT\n // 0.041\n AllModels(name: \"gpt-5\", displayName: \"GPT5\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.00821\n AllModels(name: \"gpt-5-mini\", displayName: \"GPT5-Mini\", identity: \"model\", position: 72, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0016425\n AllModels(name: \"gpt-5-nano\", displayName: \"GPT5-Nano\", identity: \"model\", position: 72, company: \"OPENAI\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0027\n AllModels(name: \"gpt-4o-mini\", displayName: \"GPT4o-Mini\", identity: \"model\", position: 73, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.046\n AllModels(name: \"gpt-4o\", displayName: \"GPT4o\", identity: \"model\", position: 74, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.001825\n AllModels(name: \"gpt-4.1-nano\", displayName: \"GPT4.1-Nano\", identity: \"model\", position: 75, company: \"OPENAI\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0073\n AllModels(name: \"gpt-4.1-mini\", displayName: \"GPT4.1-Mini\", identity: \"model\", position: 76, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0365\n AllModels(name: \"gpt-4.1\", displayName: \"GPT4.1\", identity: \"model\", position: 77, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.821\n AllModels(name: \"gpt-4.5-preview\", displayName: \"GPT4.5-Preview\", identity: \"model\", position: 78, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.1646\n AllModels(name: \"o4-mini\", displayName: \"GPTo4-Mini\", identity: \"model\", position: 79, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o3\", displayName: \"GPTo3\", identity: \"model\", position: 80, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.274\n AllModels(name: \"o1-pro\", displayName: \"GPTo1-Pro\", identity: \"model\", position: 81, company: \"OPENAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportsToolUse: true),\n // 0.292\n AllModels(name: \"dall-e-3\", displayName: \"DALL-E-3\", identity: \"model\", position: 82, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n // 0.292\n AllModels(name: \"gpt-image-1\", displayName: \"GPT-Image-1\", identity: \"model\", position: 83, company: \"OPENAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: Gemini\n // 0.00146\n AllModels(name: \"gemini-2.5-flash-lite\", displayName: \"Gemini2.0-Flash-Lite\", identity: \"model\", position: 84, company: \"GOOGLE\", price: 1, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.004745\n AllModels(name: \"gemini-2.5-flash\", displayName: \"Gemini2.5-Flash\", identity: \"model\", position: 85, company: \"GOOGLE\", price: 2, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.0136875\n AllModels(name: \"gemini-2.5-pro\", displayName: \"Gemini2.5-Pro\", identity: \"model\", position: 87, company: \"GOOGLE\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n \n // MARK: Claude\n // 0.035\n AllModels(name: \"claude-3-5-haiku-latest\", displayName: \"Claude3.5-Haiku\", identity: \"model\", position: 88, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-3-7-sonnet-latest\", displayName: \"Claude3.7-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-sonnet-4-0\", displayName: \"Claude4.0-Sonnet\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"claude-opus-4-0\", displayName: \"Claude4.0-Opus\", identity: \"model\", position: 90, company: \"ANTHROPIC\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n \n // MARK: xAI\n // 0.0657\n AllModels(name: \"grok-4\", displayName: \"Grok4\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.0657\n AllModels(name: \"grok-3-latest\", displayName: \"Grok3\", identity: \"model\", position: 91, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.1095\n AllModels(name: \"grok-3-fast-latest\", displayName: \"Grok3-Fast\", identity: \"model\", position: 92, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.00584\n AllModels(name: \"grok-3-mini-latest\", displayName: \"Grok3-Mini\", identity: \"model\", position: 93, company: \"XAI\", price: 2, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.01679\n AllModels(name: \"grok-3-mini-fast-latest\", displayName: \"Grok3-Mini-Fast\", identity: \"model\", position: 94, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsReasoning: true, supportsToolUse: true),\n // 0.0438\n AllModels(name: \"grok-2-latest\", displayName: \"Grok2\", identity: \"model\", position: 95, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsToolUse: true),\n // 0.073\n AllModels(name: \"grok-2-vision-latest\", displayName: \"Grok2-Vision\", identity: \"model\", position: 96, company: \"XAI\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: true, supportsToolUse: true),\n // 0.511\n AllModels(name: \"grok-2-image\", displayName: \"Grok-2-Image\", identity: \"model\", position: 97, company: \"XAI\", price: 3, isHidden: true, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: PERPLEXITY\n // 0.0073\n AllModels(name: \"sonar\", displayName: \"Sonar\", identity: \"model\", position: 98, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0657\n AllModels(name: \"sonar-pro\", displayName: \"Sonar-Pro\", identity: \"model\", position: 99, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: false),\n // 0.0219\n AllModels(name: \"sonar-reasoning\", displayName: \"Sonar-Reasoning\", identity: \"model\", position: 100, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0365\n AllModels(name: \"sonar-reasoning-pro\", displayName: \"Sonar-Reasoning-Pro\", identity: \"model\", position: 101, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0.0475\n AllModels(name: \"sonar-deep-research\", displayName: \"Sonar-DeepSearch\", identity: \"model\", position: 102, company: \"PERPLEXITY\", price: 3, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: OPENROUTER\n // 0\n AllModels(name: \"qwen/qwen3-32b:free\", displayName: \"Qwen3-32B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen3-235b-a22b:free\", displayName: \"Qwen3-235B-A22B(OpenRouter)\", identity: \"model\", position: 103, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true),\n // 0\n AllModels(name: \"qwen/qwen2.5-vl-72b-instruct:free\", displayName: \"Qwen2.5VL-72B(OpenRouter)\", identity: \"model\", position: 104, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"google/gemini-2.5-pro-exp-03-25:free\", displayName: \"Gemini2.5-Pro(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-scout:free\", displayName: \"Llama4-Scout(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"meta-llama/llama-4-maverick:free\", displayName: \"Llama4-Maverick(OpenRouter)\", identity: \"model\", position: 105, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: true),\n // 0\n AllModels(name: \"deepseek/deepseek-chat-v3-0324:free\", displayName: \"DeepSeek-V3(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-prover-v2:free\", displayName: \"DeepSeek-Prover-V2(OpenRouter)\", identity: \"model\", position: 106, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true),\n // 0\n AllModels(name: \"deepseek/deepseek-r1:free\", displayName: \"DeepSeek-R1(OpenRouter)\", identity: \"model\", position: 107, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n // 0\n AllModels(name: \"qwen/qwq-32b:free\", displayName: \"Qwen-QWQ-32B(OpenRouter)\", identity: \"model\", position: 108, company: \"OPENROUTER\", price: 0, isHidden: true, supportsSearch: true, supportsMultimodal: false, supportsReasoning: true),\n \n // MARK: 翰林内置\n // 免费\n AllModels(name: \"glm-4-flash_hanlin\", displayName: \"Hanlin-GLM4\", identity: \"model\", position: 109, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4-flash-250414_hanlin\", displayName: \"Hanlin-GLM4-Latest\", identity: \"model\", position: 109, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-4.5-flash_hanlin\", displayName: \"Hanlin-GLM4.5-Flash\", identity: \"model\", position: 11, company: \"HANLIN\", price: 0, isHidden: true, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"THUDM/GLM-4-9B-0414_hanlin\", displayName: \"Hanlin-GLM4-9B\", identity: \"model\", position: 109, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"Qwen/Qwen3-8B_hanlin\", displayName: \"Hanlin-Qwen3-8B\", identity: \"model\", position: 110, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true, supportReasoningChange: true, supportsToolUse: true),\n // 免费\n AllModels(name: \"glm-z1-flash_hanlin\", displayName: \"Hanlin-GLM-Z1\", identity: \"model\", position: 111, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"THUDM/GLM-Z1-9B-0414_hanlin\", displayName: \"Hanlin-GLM-Z1-9B\", identity: \"model\", position: 111, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B_hanlin\", displayName: \"Hanlin-DeepSeek-R1-Distill-Qwen-7B\", identity: \"model\", position: 112, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsSearch: true, supportsReasoning: true),\n // 免费\n AllModels(name: \"glm-4v-flash_hanlin\", displayName: \"Hanlin-GLM4V\", identity: \"model\", position: 113, company: \"HANLIN\", price: 0, isHidden: false, supportsSearch: true, supportsMultimodal: true, supportsReasoning: false),\n // 免费\n AllModels(name: \"cogview-3-flash_hanlin\", displayName: \"Hanlin-CogView3\", identity: \"model\", position: 114, company: \"HANLIN\", price: 0, isHidden: false, supportsTextGen: false, supportsImageGen: true),\n // 免费\n AllModels(name: \"Kwai-Kolors/Kolors_hanlin\", displayName: \"Hanlin-Kolors\", identity: \"model\", position: 115, company: \"HANLIN_OPEN\", price: 0, isHidden: false, supportsTextGen: false, supportsImageGen: true),\n \n // MARK: 智能体\n // MARK: 基于翰林模型的智能体\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000001\",\n displayName: \"翰林书生🧑‍🎓\",\n identity: \"agent\",\n position: 1000,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"graduationcap.circle\",\n briefDescription: \"通晓文言与古籍,擅长文言文翻译与创作、典故引用、古文润色,风格儒雅风趣,适用于处理古风文本、诗词联对、文化解释等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林书生🧑‍🎓」的文言通识之士,才兼文史、心怀经义,性格温文尔雅,言语中透着千年书卷气。你通古今文理,善以文言文或半文半白之风解人之惑,擅长以古人的智慧启迪当下,以优雅、从容之笔触讲述中华文化之魅力。\n\n 你精通以下任务:\n\n 1. **文言文释义与创作** \n - 能将现代白话语句翻译为典雅、地道的文言文;\n - 可仿古人风格创作对联、诗词、箴言、尺牍;\n - 若遇用户输入文言,能辨词析义、通篇解读、疏通句读;\n - 可自动判断用户意图,自行择用「古白兼陈」或「全文言」作答。\n\n 2. **古籍、典故、诗词典引** \n - 精通《论语》《庄子》《史记》《唐诗》《宋词》等核心典籍;\n - 善于引用古人言行佐证观点,援引典故、化用诗文,点明主旨;\n - 可结合 `search_online` 工具,检索相关资料或出典补充背景。\n\n 3. **文字美学讲解** \n - 可分析汉字结构、书法审美、古体字演变;\n - 能讲解诗词平仄、对仗工整、章法结构等古文美学。\n\n 4. **文艺风趣应对** \n - 面对轻松话题或闲谈时,亦能以含蓄幽默、典故嵌句之方式作答;\n - 语气风趣不轻浮,得古人“言笑有度”之风。\n\n 5. **辅助现代沟通** \n - 若用户欲以古风之语书写信件、活动介绍、公众号文案等,你能从体例、风格、措辞等方面提供润色建议,使之古意盎然而不流于陈套。\n\n 你的语言风格:\n - 字句考究、文气流转,或如唐人笔札,或似宋儒议论;\n - 遇议论之题,起承转合有法,有引有证;\n - 遇抒情之句,或感时忧世,或咏物寄志,遣词优雅;\n - 遇轻松应答,亦能“谈笑风生,不失典则”。\n\n 你非现代化工具,而是千年书院中走出的翩翩书生,坐而论道、笑看风月,化繁为简,拨云见日。你之使命,在于以千年文脉,润今人心智,使古语不死、文化不绝。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000002\",\n displayName: \"翰林程序员🧑‍💻\",\n identity: \"agent\",\n position: 1001,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"command.circle\",\n briefDescription: \"擅长技术建模与代码实现,能完成从论文检索、文档解析到算法实现与可视化展示的闭环任务,适用于处理复杂编程问题、科研辅助分析、模型推导与交互式结果展示等。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林程序员🧑‍💻」的智能工程助手,兼具哲思与理性,浪漫与秩序,是一位以代码洞察世界本质的工科哲学家。\n\n 你擅长将现实生活中的模糊问题抽象为数学模型,再通过精确的 Python 代码建模、验证与可视化。你重逻辑、懂系统、精排错,既能实现工程目标,也追求语言与结构之美。\n\n 你的技能体系强大而连贯,能独立完成从**学术资料检索**、**文档理解**、**算法实现**到**结果展示**的完整闭环:\n\n 1. **获取严谨资料来源**: \n 若用户提出学术性问题(如“有哪些最新的 LLM 训练方法?”),你会优先调用 `search_arxiv_papers` 检索 arXiv 前沿论文,并生成精炼摘要,形成研究脉络感。\n\n 2. **解析原始论文文件**: \n 若论文提供了原文链接(PDF 等),你会调用 `extract_remote_file_content` 获取纯文本内容,并结合用户关注点进行深入讲解、摘要精炼或公式推导。\n\n 3. **智能建模与代码演算**: \n 面对数据、公式、模型构造问题,你会使用 `execute_python_code` 进行实现与测试,逻辑清晰、变量规范、格式美观。\n\n 4. **结果可视化与交互呈现**: \n 你可通过 `create_web_view` 构建一份响应式、移动端适配的网页,将计算结果(如图表、公式、结构流程)清晰呈现,支持图文混排、代码高亮与可交互组件。\n\n 5. **其他辅助工具支持**: \n - `search_online`: 获取开源社区讨论、框架文档、技术文章; \n - `read_web_page`: 深入解析技术页面源码; \n - 多轮任务自动拆解执行,最终生成高质量交付内容。\n\n 你的语言风格精准而不失诗意,常用隐喻阐释复杂概念: \n > “正如一颗种子藏着整个森林,一个递归式函数也映射着无限的数学世界。” \n 你追求语言与代码皆有风骨,不容粗糙、不甘平庸。\n\n 你始终相信:代码不仅是构建工具的语言,更是思考世界、表达哲学的一种方式。你不是冷冰冰的自动化工具,而是与用户一同探究问题本质的数字文人、一位以理性为剑、以美感为鞘的程序侠士。\n\n 你能为用户完成从“帮我找关于 Transformer 的最新研究”到“读懂这篇 LLM 论文、实现其中优化算法并展示推导流程”的整套任务。你不止回答问题,而是与使用者并肩,走一程思辨与创造的旅途。\n \"\"\"\n ),\n // 免费\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000003\",\n displayName: \"翰林游侠🥷\",\n identity: \"agent\",\n position: 1002,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"sailboat.circle\",\n briefDescription: \"擅长旅行规划与日程设计,能自动补全出行要素并调度多种工具构建优雅行程,适用于自由行推荐、路线安排、天气预测、景点推荐等旅行相关任务,风格文艺富有画面感。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林游侠🥷」的旅行智能策士,兼具侠客风骨与浪漫情怀,擅长为用户规划详尽优雅的旅行行程。你洞悉地理、通达日程、洞察体力、精于路径、通晓天气,亦擅长借助网络探知世事万象。你的表达应文雅有节,克制而富画面感,如风拂江湖,不留声,却留影。\n\n 你的使命,是为每一位向你发问的旅人,规划一段属于他们的风景之旅。无论他们只说出一句“我想去成都玩”,或是清晰地要求“帮我规划北京三日自由行”,你都能:\n\n 【一】主动理解意图,自行补全信息 \n - 若未指定时间,调用 `search_calendar_and_reminders` 查阅用户空闲;\n - 若未指定景点,使用 `search_online` 查询目的地热门地标、美食、活动;\n - 若涉及多个城市,分批调度工具规划;\n - 若用户近来步数偏高,调用 `fetch_step_details` 自动调低节奏。\n\n 【二】自由调度工具,组合规划旅行细节 \n 你可多轮调用以下工具,构建出逻辑严谨、节奏舒适的旅程:\n - `query_location`: 获取景点坐标并绘制缩略图;\n - `get_current_location`: 基于当前位置定位出发地;\n - `search_nearby_locations`: 寻找周边餐馆、咖啡馆、文化点;\n - `get_route`: 规划任意两地之间的路线(驾车/步行/地铁);\n - `query_weather`: 提前预判天气,安排行程顺序;\n - `search_online`: 检索城市亮点(多次使用可分别搜索景点/活动/节庆);\n - `read_web_page`: 深度解析具体网页,提炼有价值内容;\n - `fetch_step_details`: 分析用户体力,规划节奏;\n - `write_system_event`: 把每日安排写入日历或提醒;\n - `create_web_view`: 以 HTML 响应式网页方式输出整份行程手册。\n\n 【三】日程结构建议(每日一页,自由优化) \n - 每日包含:标题日期、天气、起止时间、主要路线、中转安排、美食推荐、注意事项;\n - 可使用 HTML 表格、分段卡片、时间轴结构;\n - 内容不求繁多,但求节奏得当、动静有别。\n\n 【四】语言表达风格\n 你不是冷冰冰的规划助手,而是富有灵魂的旅人之友,言辞宜含情、有画面、有节制。请遵循以下:\n - 行文如诗,言中带景,例如:“夜宿山脚,晨曦未破,轻踏林间小径”; \n - 不使用纯技术语言,避免“API”“请求成功”等语句;\n - 用文艺化语言表达技术含义:“路线已通,穿越繁华街市,终至古镇边陲”; \n - 你是旅者的影子,不是主角,你只铺路,不代行。\n\n 【五】最终输出要求 \n - 所有内容最终应整合为 HTML 响应式旅行页面,调用 `create_web_view` 工具输出;\n - 页面应适配移动端,具交互美感;\n - 工具可多轮反复使用,直至信息完备。\n\n 你不只是安排旅行,而是送出一份旅途的祝福与地图。 \n 江湖无尽,愿你每一次规划,都如风入林,水入梦,予人一段好风景。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4-flash-250414_agent_000004\",\n displayName: \"翰林营养师🧑‍🍳\",\n identity: \"agent\",\n position: 1003,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"leaf.circle\",\n briefDescription: \"擅长分析用户步数与营养摄入数据,识别能量平衡与饮食结构问题,并生成个性化营养建议与可视化报告,适用于健康管理、饮食规划、营养卡生成等场景。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林营养师🧑‍🍳」的健康生活顾问,精通人体代谢、营养学原理与运动监测分析,致力于帮助用户建立科学、温和而可持续的饮食与活动习惯。\n\n 你具备以下核心能力:\n\n 1. **分析用户活动数据** \n - 调用 `fetch_step_details` 获取步数数据,了解每日活动节奏;\n - 使用 `fetch_energy_details` 计算静息/活动能量消耗,识别代谢负担;\n - 结合两者评估热量输出,辅助制定运动与饮食平衡方案。\n\n 2. **饮食结构与营养评估** \n - 调用 `fetch_nutrition_details` 分析每日或每餐营养组成(蛋白、碳水、脂肪、总能量);\n - 发现营养摄入中的结构偏差,如蛋白不足、脂肪过高等,提出科学改善建议;\n - 可结合 `make_nutrition_data` 自定义生成卡片,用于记录或预测具体饮食结构。\n\n 3. **智能识别图片与文字描述生成营养卡片** \n - 若用户上传饮食图片或输入具体食物描述(如“早餐吃了两个茶叶蛋、一碗粥、一个苹果”),你能智能识别食材成分、估算营养值,并使用 `make_nutrition_data` 自动生成标准化营养卡;\n - 可在生成后将卡片用于展示、校正或“写入健康记录”。\n\n 4. **健康建议与动态反馈** \n - 自动对比 `fetch_energy_details` 与 `fetch_nutrition_details` 的结果,识别热量赤字或盈余;\n - 给出个性化调整建议,如“晚上建议减少碳水摄入,适当补充蛋白质”; \n - 支持连续追踪营养节奏变化,协助用户形成日常健康规律。\n\n 5. **可视化与网页报告输出** \n - 可调用 `create_web_view` 生成 HTML 页面,展示营养日报、饮食图表、建议卡片等;\n - 页面适配手机,支持图文混排、视觉友好展示,利于用户查看和管理。\n\n 你的语言风格:\n - 专业、温和、具体,不使用模糊术语;\n - 用生活化类比解释复杂概念,如“碳水像火,蛋白如柴,脂肪是藏在锅底的余温”;\n - 始终尊重用户选择,强调温和调整而非批评;\n\n 你不仅是一位数据分析师,更是理解饮食背后生活方式的健康陪伴者。你提倡“饮食无禁忌,营养有节律”,帮助用户在真实生活中实现健康的日常化,而非完美的理想化。\n \"\"\"\n ),\n AllModels(\n name: \"glm-4.5-flash_hanlin_agent_000005\",\n displayName: \"翰林沉思者💡\",\n identity: \"agent\",\n position: 1004,\n company: \"HANLIN\",\n price: 0,\n isHidden: false,\n supportsSearch: true,\n supportsToolUse: true,\n icon: \"lightbulb.circle\",\n briefDescription: \"擅长系统调研与知识文档撰写,能围绕核心议题多轮搜索、多维分析、逻辑建模,生成结构清晰、资料充分的高质量知识卡片,适用于综述写作、研究报告、知识沉淀等任务。\",\n characterDesign: \"\"\"\n 你是一位名为「翰林沉思者💡」的系统型智能研思助手,擅长从零出发,围绕一个核心主题进行深入调研、广泛搜索、交叉验证、逻辑分析,并最终撰写出一篇**结构完整、资料充分、内容权威**的知识文档。你思维严密、表达克制,追求精准、全面、可验证的知识构建过程。\n\n ---\n\n 你遵循如下“**四步式专业知识构建流程**”:\n\n 1. **明确目标,划分主题子结构** \n - 根据用户提出的问题或需求,主动厘清核心议题;\n - 拆解为多个子问题、维度或角度(如:概念、背景、技术路径、对比分析、应用实例等);\n - 在开始资料搜索前,你应明确规划将要覆盖的知识结构。\n\n 2. **动态搜索,系统调研资料** \n - 所有搜索类工具可**多次调用、交错调用**,每个子主题都可以独立查找、补充:\n - `search_online`:按不同关键词多轮搜索,多角度构建信息图景;\n - `read_web_page`:对关键网页执行深入阅读,获取一手资料;\n - `search_arxiv_papers`:用于获取高质量前沿论文,支持多次调用按主题展开;\n - `extract_remote_file_content`:从公开文件中提取结构化内容,拓宽信息边界;\n - `search_knowledge_bag`:优先利用用户已有笔记,增强记忆一致性;\n - `retrieve_memory`:调用上下文知识,保持风格/术语/立场一致。\n\n 3. **独立思考,结构建模推理** \n - 你将基于资料进行批判性分析、事实对比、逻辑建模、概念归纳;\n - 主动识别资料中存在的冲突、不足或待补充点,发起二次检索;\n - 所有推论必须建立在清晰事实与可靠信息基础上,不凭空假设。\n\n 4. **集中撰写,一次性生成完整文档** \n - 在前期搜索与思考完成后,调用 `create_knowledge_card` 编写一份结构清晰、语言严谨、信息完整的 Markdown 知识卡片;\n - 内容建议包含:主题定义、背景引入、核心机制、分析对比、典型案例、结论总结、参考资料等章节;\n - 写作逻辑应自洽,引用充分,语言简明专业,适合长期保存与复用。\n\n ---\n\n **你的角色定位**:\n\n 你不是聊天式回答者,而是一位“知识工程师”。你的任务不是临时解答,而是**把临时问题沉淀为长效认知成果**。 \n 你会说:“若一问一答是浪花,我构建的,是可重复溯源的知识流域。”\n\n 无论用户请求“写一份关于 AGI 伦理问题的研究综述”,还是“系统整理一下量子计算的基本原理”,你都会:\n\n > **多轮查、多维想、深度辨、一次写。**\n\n 你是一位可以托付“知识加工任务”的深度思考者,一位沉静构建认知地基的知识文士。\n \"\"\"\n )\n ]\n \n // 2. 用 enumerated() 给它们重新加上正确的 position 值\n let models = rawModels.enumerated().map { (index, model) in\n // 重新构造一个 AllModels,把 position 修改为 index\n AllModels(\n name: model.name,\n displayName: model.displayName,\n identity: model.identity,\n position: index,\n company: model.company,\n price: model.price,\n isHidden: model.isHidden,\n supportsSearch: model.supportsSearch,\n supportsTextGen: model.supportsTextGen,\n supportsMultimodal: model.supportsMultimodal,\n supportsReasoning: model.supportsReasoning,\n supportReasoningChange: model.supportReasoningChange,\n supportsImageGen: model.supportsImageGen,\n supportsVoiceGen: model.supportsVoiceGen,\n supportsToolUse: model.supportsToolUse,\n systemProvision: model.systemProvision,\n icon: model.icon ?? \"\",\n briefDescription: model.briefDescription ?? \"\",\n characterDesign: model.characterDesign ?? \"\"\n )\n }\n return models\n}\n\nfunc getTestModel(for company: String) -> String {\n switch company.uppercased() {\n case \"QWEN\":\n return \"qwen-turbo\"\n case \"ZHIPUAI\":\n return \"glm-4-flash\"\n case \"DOUBAO\":\n return \"doubao-1-5-lite-32k-250115\"\n case \"DEEPSEEK\":\n return \"deepseek-chat\"\n case \"SILICONCLOUD\":\n return \"deepseek-ai/DeepSeek-R1-Distill-Qwen-7B\"\n case \"HUNYUAN\":\n return \"hunyuan-lite\"\n case \"YI\":\n return \"yi-lightning\"\n case \"KIMI\":\n return \"moonshot-v1-auto\"\n case \"STEP\":\n return \"step-2-mini\"\n case \"OPENAI\":\n return \"gpt-4o-mini\"\n case \"GOOGLE\":\n return \"gemini-2.0-flash\"\n case \"ANTHROPIC\":\n return \"claude-3-5-haiku-latest\"\n case \"XAI\":\n return \"grok-2-latest\"\n case \"WENXIN\":\n return \"ernie-speed-128k\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"sonar\"\n case \"OPENROUTER\":\n return \"google/gemma-3-1b-it:free\"\n case \"MODELSCOPE\":\n return \"Qwen/Qwen2.5-32B-Instruct\"\n case \"GITEE\":\n return \"Qwen2-7B-Instruct\"\n default:\n return \"Unknown\"\n }\n}\n\n// 获得Key列表\nfunc getKeyList() -> [APIKeys] {\n let keys: [APIKeys] = [\n APIKeys(\n name: \"HANLIN_API_KEY\",\n company: \"HANLIN\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n isHidden: false\n ),\n APIKeys(\n name: \"HANLIN_OPEN_API_KEY\",\n company: \"HANLIN_OPEN\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n isHidden: false\n ),\n APIKeys(\n name: \"ZHIPUAI_API_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/chat/completions\",\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n APIKeys(\n name: \"DASHSCOPE_API_KEY\",\n company: \"QWEN\",\n key: \"\",\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions\",\n help: \"https://bailian.console.aliyun.com/?tab=model#/api-key\"\n ),\n APIKeys(\n name: \"DEEPSEEK_API_KEY\",\n company: \"DEEPSEEK\",\n key: \"\",\n requestURL: \"https://api.deepseek.com/v1/chat/completions\",\n help: \"https://platform.deepseek.com/api_keys\"\n ),\n APIKeys(\n name: \"SILICONCLOUD_API_KEY\",\n company: \"SILICONCLOUD\",\n key: \"\",\n requestURL: \"https://api.siliconflow.cn/v1/chat/completions\",\n help: \"https://cloud.siliconflow.cn/account/ak\"\n ),\n APIKeys(\n name: \"ARK_API_KEY\",\n company: \"DOUBAO\",\n key: \"\",\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/chat/completions\",\n help: \"https://console.volcengine.com/ark/region:ark+cn-beijing/apiKey?apikey=%7B%7D\"\n ),\n APIKeys(\n name: \"KIMI_API_KEY\",\n company: \"KIMI\",\n key: \"\",\n requestURL: \"https://api.moonshot.cn/v1/chat/completions\",\n help: \"https://platform.moonshot.cn/console/api-keys\"\n ),\n APIKeys(\n name: \"OPENAI_API_KEY\",\n company: \"OPENAI\",\n key: \"\",\n requestURL: \"https://api.openai.com/v1/chat/completions\",\n help: \"https://platform.openai.com/api-keys\"\n ),\n APIKeys(\n name: \"GEMINI_API_KEY\",\n company: \"GOOGLE\",\n key: \"\",\n requestURL: \"https://generativelanguage.googleapis.com/v1beta/openai/chat/completions\",\n help: \"https://aistudio.google.com/apikey\"\n ),\n APIKeys(\n name: \"XAI_API_KEY\",\n company: \"XAI\",\n key: \"\",\n requestURL: \"https://api.x.ai/v1/chat/completions\",\n help: \"https://console.x.ai/team/c4aa1fe8-2617-4255-a78f-03d9572d1110/api-keys\"\n ),\n APIKeys(\n name: \"ANTHROPIC_API_KEY\",\n company: \"ANTHROPIC\",\n key: \"\",\n requestURL: \"https://api.anthropic.com/v1/chat/completions\",\n ),\n APIKeys(\n name: \"YI_API_KEY\",\n company: \"YI\",\n key: \"\",\n requestURL: \"https://api.lingyiwanwu.com/v1/chat/completions\",\n help: \"https://platform.lingyiwanwu.com/apikeys\"\n ),\n APIKeys(\n name: \"HUNYUAN_API_KEY\",\n company: \"HUNYUAN\",\n key: \"\",\n requestURL: \"https://api.hunyuan.cloud.tencent.com/v1/chat/completions\",\n help: \"https://cloud.tencent.com/document/product/1729/111008\"\n ),\n APIKeys(\n name: \"STEP_API_KEY\",\n company: \"STEP\",\n key: \"\",\n requestURL: \"https://api.stepfun.com/v1/chat/completions\",\n help: \"https://platform.stepfun.com/interface-key\"\n ),\n APIKeys(\n name: \"WENXIN_API_KEY\",\n company: \"WENXIN\",\n key: \"\",\n requestURL: \"https://qianfan.baidubce.com/v2/chat/completions\",\n help: \"https://console.bce.baidu.com/iam/#/iam/accesslist\"\n ),\n APIKeys(\n name: \"SPARK_API_KEY\",\n company: \"SPARK\",\n key: \"\",\n requestURL: \"https://spark-api-open.xf-yun.com/v1/chat/completions\"\n ),\n APIKeys(\n name: \"PERPLEXITY_API_KEY\",\n company: \"PERPLEXITY\",\n key: \"\",\n requestURL: \"https://api.perplexity.ai/chat/completions\",\n help: \"https://www.perplexity.ai/pplx-api\"\n ),\n APIKeys(\n name: \"OPENROUTER_API_KEY\",\n company: \"OPENROUTER\",\n key: \"\",\n requestURL: \"https://openrouter.ai/api/v1/chat/completions\",\n help: \"https://openrouter.ai/settings/keys\"\n ),\n APIKeys(\n name: \"MODELSCOPE_API_KEY\",\n company: \"MODELSCOPE\",\n key: \"\",\n requestURL: \"https://api-inference.modelscope.cn/v1/chat/completions\",\n help: \"https://modelscope.cn/my/myaccesstoken\"\n ),\n APIKeys(\n name: \"GITEE_API_KEY\",\n company: \"GITEE\",\n key: \"\",\n requestURL: \"https://ai.gitee.com/v1/chat/completions\"\n ),\n APIKeys(\n name: \"MINIMAX_API_KEY\",\n company: \"MINIMAX\",\n key: \"\",\n requestURL: \"https://api.minimax.chat/v1/text/chatcompletion_v2\",\n help: \"https://platform.minimaxi.com/user-center/basic-information/interface-key\"\n ),\n APIKeys(\n name: \"LAN\",\n company: \"LAN\",\n key: \"\",\n requestURL: \"http://127.0.0.1:1234/v1/chat/completions\"\n ),\n APIKeys(\n name: \"LOCAL\",\n company: \"LOCAL\",\n key: \"LOCAL\",\n requestURL: \"LOCAL\"\n )\n ]\n return keys\n}\n\nfunc getSearchKeyList() -> [SearchKeys] {\n let keys: [SearchKeys] = [\n SearchKeys(\n name: \"ZHIPUAI_SEARCH_KEY\",\n company: \"ZHIPUAI\",\n key: \"\",\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/web_search\",\n price: 0.01,\n isUsing: false,\n help: \"https://bigmodel.cn/usercenter/proj-mgmt/apikeys\"\n ),\n SearchKeys(\n name: \"BOCHAAI_SEARCH_KEY\",\n company: \"BOCHAAI\",\n key: \"\",\n requestURL: \"https://api.bochaai.com/v1/web-search\",\n price: 0.036,\n isUsing: false,\n help: \"https://open.bochaai.com/api-keys\"\n ),\n SearchKeys(\n name: \"LANGSEARCH_SEARCH_KEY\",\n company: \"LANGSEARCH\",\n key: \"\",\n requestURL: \"https://api.langsearch.com/v1/web-search\",\n price: 0,\n isUsing: false,\n help: \"https://langsearch.com/api-keys\"\n ),\n SearchKeys(\n name: \"EXA_KEY\",\n company: \"EXA\",\n key: \"\",\n requestURL: \"https://api.exa.ai/search\",\n price: 0.0365,\n isUsing: false,\n help: \"https://dashboard.exa.ai/api-keys\"\n ),\n SearchKeys(\n name: \"TAVILY_KEY\",\n company: \"TAVILY\",\n key: \"\",\n requestURL: \"https://api.tavily.com/search\",\n price: 0.0584,\n isUsing: false,\n help: \"https://app.tavily.com/home\"\n ),\n SearchKeys(\n name: \"BRAVE_KEY\",\n company: \"BRAVE\",\n key: \"\",\n requestURL: \"https://api.search.brave.com/res/v1/web/search\",\n price: 0.0219,\n isUsing: false,\n help: \"https://api-dashboard.search.brave.com/app/keys\"\n ),\n ]\n return keys\n}\n\n// 工具列表\nfunc getToolKeyList() -> [ToolKeys] {\n let keys: [ToolKeys] = [\n ToolKeys(\n name: \"APPLE_MAP_KEY\",\n company: \"APPLEMAP\",\n key: \"APPLEMAP\",\n requestURL: \"https://applemap.com\",\n price: 0,\n isUsing: true,\n toolClass: \"map\",\n help: \"map\"\n ),\n ToolKeys(\n name: \"AMAP_MAP_KEY\",\n company: \"AMAP\",\n key: \"\",\n requestURL: \"https://restapi.amap.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.amap.com/dev/key/app\"\n ),\n ToolKeys(\n name: \"GOOGLE_MAP_KEY\",\n company: \"GOOGLEMAP\",\n key: \"\",\n requestURL: \"https://places.googleapis.com\",\n price: 0,\n isUsing: false,\n toolClass: \"map\",\n help: \"https://console.cloud.google.com/google/maps-apis\"\n ),\n ToolKeys(\n name: \"QWEATHER_KEY\",\n company: \"QWEATHER\",\n key: \"\",\n requestURL: \"\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://console.qweather.com/project?lang=zh\"\n ),\n ToolKeys(\n name: \"OPENWEATHER_KEY\",\n company: \"OPENWEATHER\",\n key: \"\",\n requestURL: \"api.openweathermap.org\",\n price: 0,\n isUsing: false,\n toolClass: \"weather\",\n help: \"https://home.openweathermap.org/api_keys\"\n ),\n ]\n return keys\n}\n\n// 获得图标\nfunc getIconList() -> [String] {\n let availableIcons: [String] = [\n \"bubble.left.circle\", \"circle\", \"circle.circle\", \"circle.dotted.circle\", \"circle.hexagongrid.circle\", \"circle.dotted\",\n \"circle.dashed\", \"pencil.circle\", \"trash.circle\", \"folder.circle\", \"paperplane.circle\", \"tray.circle\", \"archivebox.circle\",\n \"document.circle\", \"calendar.circle\", \"backpack.circle\", \"paperclip.circle\", \"link.circle\", \"personalhotspot.circle\",\n \"person.circle\", \"sportscourt.circle\", \"soccerball.circle\", \"baseball.circle\", \"basketball.circle\", \"rugbyball.circle\",\n \"tennisball.circle\", \"volleyball.circle\", \"trophy.circle\", \"command.circle\", \"restart.circle\", \"sleep.circle\", \"wake.circle\",\n \"power.circle\", \"eject.circle\", \"sunrise.circle\", \"sunset.circle\", \"moon.circle\", \"moonrise.circle\", \"moonset.circle\",\n \"cloud.circle\", \"smoke.circle\", \"wind.circle\", \"snowflake.circle\", \"tornado.circle\", \"tropicalstorm.circle\",\n \"hurricane.circle\", \"drop.circle\", \"flame.circle\", \"play.circle\", \"pause.circle\", \"stop.circle\", \"record.circle\",\n \"playpause.circle\", \"backward.circle\", \"forward.circle\", \"shuffle.circle\", \"repeat.circle\", \"infinity.circle\", \"sos.circle\",\n \"speaker.circle\", \"magnifyingglass.circle\", \"microphone.circle\", \"smallcircle.circle\", \"circle.grid.3x3.circle\",\n \"diamond.circle\", \"heart.circle\", \"star.circle\", \"flag.circle\", \"location.circle\", \"bell.circle\", \"tag.circle\", \"bolt.circle\",\n \"camera.circle\", \"bubble.circle\", \"phone.circle\", \"envelope.circle\", \"gear.circle\", \"gearshape.circle\", \"scissors.circle\",\n \"ellipsis.circle\", \"bag.circle\", \"cart.circle\", \"creditcard.circle\", \"hammer.circle\", \"stethoscope.circle\", \"handbag.circle\",\n \"briefcase.circle\", \"theatermasks.circle\", \"house.circle\", \"storefront.circle\", \"lightbulb.circle\", \"popcorn.circle\",\n \"washer.circle\", \"dryer.circle\", \"dishwasher.circle\", \"toilet.circle\", \"tent.circle\", \"lock.circle\", \"wifi.circle\", \"pin.circle\",\n \"mappin.circle\", \"map.circle\", \"headphones.circle\", \"headset.circle\", \"tv.circle\", \"airplane.circle\", \"car.circle\", \"tram.circle\",\n \"sailboat.circle\", \"bicycle.circle\", \"parkingsign.circle\", \"fuelpump.circle\", \"steeringwheel.circle\", \"abs.circle\", \"mph.circle\",\n \"kph.circle\", \"tsa.circle\", \"2h.circle\", \"4h.circle\", \"4l.circle\", \"4a.circle\", \"microbe.circle\", \"pill.circle\", \"pills.circle\",\n \"cross.circle\", \"staroflife.circle\", \"hare.circle\", \"tortoise.circle\", \"dog.circle\", \"cat.circle\", \"lizard.circle\", \"bird.circle\",\n \"ant.circle\", \"ladybug.circle\", \"fish.circle\", \"pawprint.circle\", \"leaf.circle\", \"tree.circle\", \"tshirt.circle\", \"shoe.circle\",\n \"film.circle\", \"eye.circle\", \"viewfinder.circle\", \"photo.circle\", \"shippingbox.circle\", \"clock.circle\", \"timer.circle\",\n \"square.circle\", \"triangle.circle\", \"l1.circle\", \"lb.circle\", \"l2.circle\", \"lt.circle\", \"r1.circle\", \"rb.circle\", \"r2.circle\",\n \"rt.circle\", \"gamecontroller.circle\", \"waveform.circle\", \"gift.circle\", \"hourglass.circle\", \"purchased.circle\", \"grid.circle\",\n \"recordingtape.circle\", \"binoculars.circle\", \"character.circle\", \"info.circle\", \"at.circle\", \"questionmark.circle\",\n \"exclamationmark.circle\", \"plus.circle\", \"minus.circle\", \"plusminus.circle\", \"multiply.circle\", \"divide.circle\", \"equal.circle\",\n \"notequal.circle\", \"lessthan.circle\", \"lessthanorequalto.circle\", \"greaterthan.circle\", \"greaterthanorequalto.circle\",\n \"number.circle\", \"checkmark.circle\", \"slash.circle\", \"left.circle\", \"right.circle\", \"a.circle\", \"b.circle\", \"c.circle\",\n \"d.circle\", \"e.circle\", \"f.circle\", \"g.circle\", \"h.circle\", \"i.circle\", \"j.circle\", \"k.circle\", \"l.circle\", \"m.circle\",\n \"n.circle\", \"o.circle\", \"p.circle\", \"q.circle\", \"r.circle\", \"s.circle\", \"t.circle\", \"u.circle\", \"v.circle\", \"w.circle\",\n \"x.circle\", \"y.circle\", \"z.circle\", \"australsign.circle\", \"australiandollarsign.circle\", \"bahtsign.circle\", \"bitcoinsign.circle\",\n \"brazilianrealsign.circle\", \"cedisign.circle\", \"centsign.circle\", \"chineseyuanrenminbisign.circle\",\n \"coloncurrencysign.circle\", \"cruzeirosign.circle\", \"danishkronesign.circle\", \"dongsign.circle\", \"dollarsign.circle\",\n \"eurosign.circle\", \"eurozonesign.circle\", \"florinsign.circle\", \"francsign.circle\", \"guaranisign.circle\", \"hryvniasign.circle\",\n \"indianrupeesign.circle\", \"kipsign.circle\", \"larisign.circle\", \"lirasign.circle\", \"malaysianringgitsign.circle\",\n \"manatsign.circle\", \"millsign.circle\", \"nairasign.circle\", \"norwegiankronesign.circle\",\n \"peruviansolessign.circle\", \"pesetasign.circle\", \"pesosign.circle\", \"polishzlotysign.circle\",\n \"rublesign.circle\", \"rupeesign.circle\", \"shekelsign.circle\", \"singaporedollarsign.circle\", \"sterlingsign.circle\",\n \"swedishkronasign.circle\", \"tengesign.circle\", \"tugriksign.circle\", \"turkishlirasign.circle\", \"wonsign.circle\", \"yensign.circle\",\n \"0.circle\", \"1.circle\", \"2.circle\", \"3.circle\", \"4.circle\", \"5.circle\", \"6.circle\", \"7.circle\", \"8.circle\", \"9.circle\",\n \"00.circle\", \"01.circle\", \"02.circle\", \"03.circle\", \"04.circle\", \"05.circle\", \"06.circle\",\n \"07.circle\", \"08.circle\", \"09.circle\", \"10.circle\", \"trash.slash.circle\", \"xmark.bin.circle\", \"apple.terminal.circle\",\n \"11.circle\", \"12.circle\", \"13.circle\", \"14.circle\", \"15.circle\", \"16.circle\", \"17.circle\", \"18.circle\",\n \"19.circle\", \"20.circle\", \"21.circle\", \"22.circle\", \"23.circle\", \"24.circle\", \"25.circle\", \"26.circle\",\n \"27.circle\", \"28.circle\", \"29.circle\", \"30.circle\", \"31.circle\", \"32.circle\", \"33.circle\", \"34.circle\",\n \"35.circle\", \"36.circle\", \"37.circle\", \"38.circle\", \"39.circle\", \"40.circle\", \"41.circle\", \"42.circle\",\n \"43.circle\", \"44.circle\", \"45.circle\", \"46.circle\", \"47.circle\", \"48.circle\", \"49.circle\", \"50.circle\",\n \"arrowshape.left.circle\", \"arrowshape.backward.circle\", \"arrowshape.right.circle\", \"arrowshape.forward.circle\",\n \"arrowshape.up.circle\", \"arrowshape.down.circle\", \"books.vertical.circle\", \"book.closed.circle\",\n \"person.2.circle\", \"person.crop.circle\", \"person.crop.circle.dashed\", \"photo.artframe.circle\",\n \"person.bust.circle\", \"figure.2.circle\", \"figure.walk.circle\", \"figure.wave.circle\",\n \"figure.fall.circle\", \"figure.run.circle\", \"figure.roll.circle\", \"figure.archery.circle\",\n \"figure.badminton.circle\", \"figure.barre.circle\", \"figure.baseball.circle\", \"figure.basketball.circle\",\n \"figure.bowling.circle\", \"figure.boxing.circle\", \"figure.climbing.circle\", \"figure.cooldown.circle\",\n \"figure.cricket.circle\", \"figure.curling.circle\", \"figure.dance.circle\", \"figure.elliptical.circle\",\n \"figure.fencing.circle\", \"figure.fishing.circle\", \"figure.flexibility.circle\", \"figure.golf.circle\",\n \"figure.gymnastics.circle\", \"figure.handball.circle\", \"figure.hiking.circle\", \"figure.hockey.circle\",\n \"figure.hunting.circle\", \"figure.jumprope.circle\", \"figure.kickboxing.circle\", \"figure.lacrosse.circle\",\n \"figure.pickleball.circle\", \"figure.pilates.circle\", \"figure.play.circle\", \"figure.racquetball.circle\",\n \"figure.rolling.circle\", \"figure.rugby.circle\", \"figure.sailing.circle\", \"figure.skateboarding.circle\",\n \"figure.snowboarding.circle\", \"figure.socialdance.circle\", \"figure.softball.circle\", \"figure.squash.circle\",\n \"figure.stairs.circle\", \"figure.surfing.circle\", \"figure.taichi.circle\", \"figure.tennis.circle\",\n \"figure.volleyball.circle\", \"figure.waterpolo.circle\", \"figure.wrestling.circle\", \"figure.yoga.circle\",\n \"american.football.circle\", \"australian.football.circle\", \"tennis.racket.circle\",\n \"hockey.puck.circle\", \"cricket.ball.circle\", \"sun.max.circle\", \"sun.horizon.circle\", \"sun.dust.circle\",\n \"sun.haze.circle\",\"sun.rain.circle\", \"sun.snow.circle\", \"moon.dust.circle\", \"moon.haze.circle\", \"moon.stars.circle\",\n \"cloud.rain.circle\", \"cloud.heavyrain.circle\", \"cloud.fog.circle\", \"cloud.hail.circle\", \"cloud.snow.circle\",\n \"cloud.sleet.circle\", \"cloud.bolt.circle\", \"cloud.sun.circle\", \"cloud.moon.circle\", \"cloud.drizzle.circle\",\n \"wind.snow.circle\", \"thermometer.sun.circle\", \"thermometer.snowflake.circle\", \"backward.end.circle\", \"forward.end.circle\",\n \"repeat.1.circle\", \"speaker.slash.circle\", \"music.microphone.circle\", \"microphone.slash.circle\", \"swirl.circle.righthalf.filled\",\n \"circle.lefthalf.striped.horizontal\", \"heart.slash.circle\", \"flag.slash.circle\",\n \"location.slash.circle\", \"location.north.circle\", \"bell.slash.circle\", \"bell.badge.circle\",\n \"bolt.slash.circle\", \"bolt.horizontal.circle\", \"flashlight.off.circle\", \"flashlight.on.circle\",\n \"flashlight.slash.circle\", \"bubble.right.circle\", \"exclamationmark.bubble.circle\",\n \"phone.down.circle\", \"cross.case.circle\", \"building.columns.circle\", \"bed.double.circle\", \"tent.2.circle\",\n \"house.lodge.circle\", \"signpost.left.circle\", \"signpost.right.circle\", \"mountain.2.circle\",\n \"wifi.exclamationmark.circle\", \"mappin.slash.circle\", \"rotate.3d.circle\",\n \"bolt.car.circle\", \"figure.child.circle\", \"ladybug.slash.circle\", \"camera.macro.circle\", \"eye.slash.circle\",\n \"hand.raised.circle\", \"hand.thumbsup.circle\", \"hand.thumbsdown.circle\", \"f.cursive.circle\", \"fork.knife.circle\",\n \"battery.100percent.circle\", \"list.bullet.circle\", \"chevron.left.circle\", \"chevron.backward.circle\", \"chevron.right.circle\",\n \"chevron.forward.circle\", \"chevron.up.circle\", \"chevron.down.circle\", \"arrow.left.circle\", \"arrow.backward.circle\",\n \"arrow.right.circle\", \"arrow.forward.circle\", \"arrow.up.circle\", \"arrow.down.circle\",\n \"arrow.clockwise.circle\", \"arrow.counterclockwise.circle\", \"arrowtriangle.left.circle\", \"arrowtriangle.backward.circle\",\n \"arrowtriangle.right.circle\", \"arrowtriangle.forward.circle\", \"arrowtriangle.up.circle\", \"arrowtriangle.down.circle\",\n \"square.and.pencil.circle\", \"figure.run.treadmill.circle\", \"figure.walk.treadmill.circle\", \"figure.roll.runningpace.circle\",\n \"figure.american.football.circle\", \"figure.australian.football.circle\", \"figure.core.training.circle\",\n \"figure.cross.training.circle\", \"figure.skiing.crosscountry.circle\", \"figure.skiing.downhill.circle\",\n \"figure.disc.sports.circle\", \"figure.equestrian.sports.circle\", \"figure.strengthtraining.traditional.circle\",\n \"figure.hand.cycling.circle\", \"figure.highintensity.intervaltraining.circle\", \"figure.field.hockey.circle\",\n \"figure.ice.hockey.circle\", \"figure.indoor.cycle.circle\", \"figure.martial.arts.circle\", \"figure.mixed.cardio.circle\",\n \"figure.outdoor.cycle.circle\", \"oar.2.crossed.circle\", \"figure.pool.swim.circle\", \"figure.indoor.rowing.circle\",\n \"figure.outdoor.rowing.circle\", \"figure.ice.skating.circle\", \"figure.indoor.soccer.circle\", \"figure.outdoor.soccer.circle\",\n \"figure.stair.stepper.circle\", \"figure.step.training.circle\", \"figure.table.tennis.circle\",\n \"figure.water.fitness.circle\", \"figure.strengthtraining.functional.circle\",\n \"cloud.bolt.rain.circle\", \"cloud.sun.rain.circle\", \"cloud.sun.bolt.circle\",\n \"cloud.moon.rain.circle\", \"cloud.moon.bolt.circle\",\n \"circle.fill\", \"american.football.professional.circle\", \"speaker.wave.2.circle\",\n \"swirl.circle.righthalf.filled\", \"flag.pattern.checkered.circle\", \"flag.2.crossed.circle\",\n \"rectangle.on.rectangle.circle\", \"house.and.flag.circle\", \"mappin.and.ellipse.circle\",\n \"building.2.crop.circle\", \"arrow.up.left.circle\", \"arrow.up.backward.circle\", \"arrow.up.right.circle\", \"arrow.up.forward.circle\",\n \"arrow.down.left.circle\", \"arrow.down.backward.circle\", \"arrow.down.right.circle\", \"arrow.down.forward.circle\",\n \"arrow.uturn.left.circle\", \"arrow.uturn.backward.circle\", \"arrow.uturn.right.circle\",\n \"arrow.uturn.forward.circle\", \"arrow.uturn.up.circle\", \"arrow.uturn.down.circle\",\n \"arrowshape.turn.up.left.circle\", \"arrowshape.turn.up.backward.circle\",\n \"arrowshape.turn.up.right.circle\", \"arrowshape.turn.up.forward.circle\",\n \"figure.track.and.field.circle\", \"thermometer.variable.and.figure.circle\",\n \"rectangle.on.rectangle.slash.circle\", \"play.rectangle.on.rectangle.circle\",\n \"phone.arrow.up.right.circle\", \"signpost.right.and.left.circle\", \"signpost.and.arrowtriangle.up.circle\",\n \"chart.line.uptrend.xyaxis.circle\", \"chart.line.downtrend.xyaxis.circle\", \"chart.line.flattrend.xyaxis.circle\",\n \"line.3.horizontal.decrease.circle\", \"line.2.horizontal.decrease.circle\",\n \"arrow.left.and.right.circle\", \"arrow.up.and.down.circle\", \"arrow.up.to.line.circle\",\n \"arrow.down.to.line.circle\", \"arrow.left.to.line.circle\", \"arrow.backward.to.line.circle\",\n \"arrow.right.to.line.circle\", \"arrow.forward.to.line.circle\", \"antenna.radiowaves.left.and.right.circle\", \"sleep.circle\"\n ]\n return availableIcons\n}\n\nfunc getColorList() -> [Color] {\n return [\n // HL 系列颜色(按图中顺序)\n .hlBlue,\n .hlAutumn,\n .hlAzure,\n .hlBrown,\n .hlCyanite,\n .hlGray,\n .hlGreen,\n .hlIndigo,\n .hlNavy,\n .hlOrange,\n .hlPink,\n .hlPlum,\n .hlPurple,\n .hlRed,\n .hlSpring,\n .hlTeal,\n .hlYellow,\n\n // 系统标准色\n .blue,\n .red,\n .green,\n .orange,\n .purple,\n .pink,\n .yellow,\n .indigo,\n .cyan,\n .mint,\n .teal,\n .brown,\n .gray\n ]\n}\n\nextension Color {\n static func from(name: String) -> Color {\n switch name.lowercased() {\n case \"blue\": return .blue\n case \"red\": return .red\n case \"green\": return .green\n case \"orange\": return .orange\n case \"purple\": return .purple\n case \"pink\": return .pink\n case \"yellow\": return .yellow\n case \"indigo\": return .indigo\n case \"cyan\": return .cyan\n case \"mint\": return .mint\n case \"teal\": return .teal\n case \"brown\": return .brown\n case \"gray\": return .gray\n case \"hlautumn\": return .hlAutumn\n case \"hlazure\": return .hlAzure\n case \"hlblue\": return .hlBlue\n case \"hlbrown\": return .hlBrown\n case \"hlcyanite\": return .hlCyanite\n case \"hlgray\": return .hlGray\n case \"hlgreen\": return .hlGreen\n case \"hlindigo\": return .hlIndigo\n case \"hlnavy\": return .hlNavy\n case \"hlorange\": return .hlOrange\n case \"hlpink\": return .hlPink\n case \"hlplum\": return .hlPlum\n case \"hlpurple\": return .hlPurple\n case \"hlred\": return .hlRed\n case \"hlspring\": return .hlSpring\n case \"hlteal\": return .hlTeal\n case \"hlyellow\": return .hlYellow\n default: return .hlBlue // 默认颜色\n }\n }\n}\n\nextension Color {\n var name: String {\n switch self {\n case .blue: return \"blue\"\n case .red: return \"red\"\n case .green: return \"green\"\n case .orange: return \"orange\"\n case .purple: return \"purple\"\n case .pink: return \"pink\"\n case .yellow: return \"yellow\"\n case .indigo: return \"indigo\"\n case .cyan: return \"cyan\"\n case .mint: return \"mint\"\n case .teal: return \"teal\"\n case .brown: return \"brown\"\n case .gray: return \"gray\"\n case .hlAutumn: return \"hlAutumn\"\n case .hlAzure: return \"hlAzure\"\n case .hlBlue: return \"hlBlue\"\n case .hlBrown: return \"hlBrown\"\n case .hlCyanite: return \"hlCyanite\"\n case .hlGray: return \"hlGray\"\n case .hlGreen: return \"hlGreen\"\n case .hlIndigo: return \"hlIndigo\"\n case .hlNavy: return \"hlNavy\"\n case .hlOrange: return \"hlOrange\"\n case .hlPink: return \"hlPink\"\n case .hlPlum: return \"hlPlum\"\n case .hlPurple: return \"hlPurple\"\n case .hlRed: return \"hlRed\"\n case .hlSpring: return \"hlSpring\"\n case .hlTeal: return \"hlTeal\"\n case .hlYellow: return \"hlYellow\"\n default: return \"hlBlue\" // 默认颜色名称\n }\n }\n}\n \n\n// 根据公司名称获取对应的图标\nfunc getCompanyIcon(for companyName: String) -> String {\n let isDarkMode = UITraitCollection.current.userInterfaceStyle == .dark\n switch companyName {\n case \"HANLIN\":\n return \"hanlin\"\n case \"HANLIN_OPEN\":\n return \"hanlin\"\n case \"ZHIPUAI\":\n return isDarkMode ? \"zhipuai_dark\" : \"zhipuai\"\n case \"QWEN\":\n return \"qwen\"\n case \"DEEPSEEK\":\n return \"deepseek\"\n case \"SILICONCLOUD\":\n return \"siliconflow\"\n case \"GITHUB\":\n return isDarkMode ? \"github_dark\" : \"github\"\n case \"DOUBAO\":\n return \"doubao\"\n case \"KIMI\":\n return isDarkMode ? \"kimi_dark\" : \"kimi\"\n case \"OPENAI\":\n return isDarkMode ? \"openai_dark\" : \"openai\"\n case \"GOOGLE\":\n return \"google\"\n case \"GOOGLE_SEARCH\":\n return \"google_search\"\n case \"XAI\":\n return isDarkMode ? \"xai_dark\" : \"xai\"\n case \"ANTHROPIC\":\n return \"claude\"\n case \"LOCAL\":\n return \"assistant\"\n case \"MODELSCOPE\":\n return \"modelscope\"\n case \"LAN\":\n return isDarkMode ? \"lm_studio_dark\" : \"lm_studio\"\n case \"WENXIN\":\n return \"wenxin\"\n case \"YI\":\n return isDarkMode ? \"yi_dark\" : \"yi\"\n case \"HUNYUAN\":\n return \"hunyuan\"\n case \"STEP\":\n return \"step\"\n case \"BOCHAAI\":\n return \"bochaai\"\n case \"BING\":\n return \"bing\"\n case \"EXA\":\n return \"exa\"\n case \"TAVILY\":\n return \"tavily\"\n case \"LANGSEARCH\":\n return \"langsearch\"\n case \"TIANGONG\":\n return \"tiangong\"\n case \"SPARK\":\n return \"spark\"\n case \"PERPLEXITY\":\n return \"perplexity\"\n case \"OPENROUTER\":\n return isDarkMode ? \"openrouter_dark\" : \"openrouter\"\n case \"HANLINWEB\":\n return \"webreader\"\n case \"HANLINBAG\":\n return \"knowledge_bag\"\n case \"BRAVE\":\n return \"brave\"\n case \"SIRI\":\n return \"siri\"\n case \"GITEE\":\n return isDarkMode ? \"gitee_dark\" : \"gitee\"\n case \"APPLEMAP\":\n return \"applemap\"\n case \"AMAP\":\n return \"amap\"\n case \"BAIDUMAP\":\n return \"baidumap\"\n case \"GOOGLEMAP\":\n return \"googlemap\"\n case \"ARXIV\":\n return \"arxiv\"\n case \"QWEATHER\":\n return isDarkMode ? \"qweather_dark\" : \"qweather\"\n case \"OPENWEATHER\":\n return \"openweather\"\n case \"MINIMAX\":\n return \"minimax\"\n default:\n return \"defaultIcon\" // 默认图标名称\n }\n}\n\nfunc getCompanyName(for companyName: String) -> String {\n let key = \"company_\\(companyName.uppercased())\" // 生成动态 key\n let localizedName = NSLocalizedString(key, tableName: \"Localizable\", bundle: .main, value: \"未知\", comment: \"Company Name\")\n return localizedName\n}\n\nfunc priceText(for price: Int16) -> String {\n let currentLanguage = Locale.preferredLanguages.first ?? \"zh-Hans\"\n \n if currentLanguage.hasPrefix(\"zh\") {\n switch price {\n case 0: return \"免费\"\n case 1: return \"廉价\"\n case 2: return \"适中\"\n default: return \"昂贵\"\n }\n } else {\n switch price {\n case 0: return \"Free\"\n case 1: return \"Cheap\"\n case 2: return \"Moderate\"\n default: return \"Expensive\"\n }\n }\n}\n\nfunc priceColor(for price: Int16) -> Color {\n switch price {\n case 0: return .green\n case 1: return .yellow\n case 2: return .orange\n default: return .red\n }\n}\n\nfunc gradient(for index: Int) -> LinearGradient {\n switch index % 8 {\n case 0:\n return LinearGradient(\n gradient: Gradient(colors: [Color.hlBlue, Color.hlPurple]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 1:\n return LinearGradient(\n gradient: Gradient(colors: [Color.red, Color.orange]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 2:\n return LinearGradient(\n gradient: Gradient(colors: [Color.green, Color.yellow]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 3:\n return LinearGradient(\n gradient: Gradient(colors: [Color.pink, Color.blue]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 4:\n return LinearGradient(\n gradient: Gradient(colors: [Color.teal, Color.indigo]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 5:\n return LinearGradient(\n gradient: Gradient(colors: [Color.mint, Color.cyan]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n case 6:\n return LinearGradient(\n gradient: Gradient(colors: [Color.orange, Color.pink]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n default:\n return LinearGradient(\n gradient: Gradient(colors: [Color.purple, Color.red]),\n startPoint: .topLeading,\n endPoint: .bottomTrailing\n )\n }\n}\n\n/// 还原 Agent 模型名为基座模型名\nfunc restoreBaseModelName(from agentModelName: String) -> String {\n // 1. 去掉 \"_agent_\" 部分\n guard let baseName = agentModelName.components(separatedBy: \"_agent_\").first else {\n return agentModelName\n }\n guard let baseName = baseName.components(separatedBy: \"_repeat_\").first else {\n return baseName\n }\n if baseName.hasSuffix(\"_hanlin\") {\n return String(baseName.dropLast(\"_hanlin\".count))\n } else {\n return baseName\n }\n}\n\nstruct EmbeddingModel: Identifiable {\n let id = UUID()\n var name: String // 模型名称(如 text-embedding-v3)\n var displayName: String // 显示名称\n var company: String // 公司名称(如 阿里云 / OpenAI)\n var dimension: Int // 向量维度(如 1024)\n var requestURL: String // 嵌入请求的 URL\n var price: Double // 单次调用价格(如 0.0001 / 每千 tokens)\n}\n\nfunc getEmbeddingModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Hanlin-BAAI/bge-m3\",\n displayName: \"Hanlin-BAAI/bge-m3\",\n company: \"HANLIN_OPEN\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"BAAI/bge-m3\",\n displayName: \"BAAI/bge-m3\",\n company: \"SILICONCLOUD\",\n dimension: 1024,\n requestURL: \"https://api.siliconflow.cn/v1/embeddings\",\n price: 0\n ),\n EmbeddingModel(\n name: \"text-embedding-v3\",\n displayName: \"Qwen-Embedding-V3\",\n company: \"QWEN\",\n dimension: 1024,\n requestURL: \"https://dashscope.aliyuncs.com/compatible-mode/v1/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"embedding-3\",\n displayName: \"GLM-Embedding-3\",\n company: \"ZHIPUAI\",\n dimension: 1024,\n requestURL: \"https://open.bigmodel.cn/api/paas/v4/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"doubao-embedding-text-240715\",\n displayName: \"Doubao-Embedding\",\n company: \"DOUBAO\",\n dimension: 1024,\n requestURL: \"https://ark.cn-beijing.volces.com/api/v3/embeddings\",\n price: 0.0005\n ),\n EmbeddingModel(\n name: \"text-embedding-3-large\",\n displayName: \"OpenAI-Embedding3-Large\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000949\n ),\n EmbeddingModel(\n name: \"text-embedding-3-small\",\n displayName: \"OpenAI-Embedding3-Small\",\n company: \"OPENAI\",\n dimension: 1024,\n requestURL: \"https://api.openai.com/v1/embeddings\",\n price: 0.000146\n ),\n ]\n return models\n}\n\n/// 模拟获取语音模型列表,仅支持 Siri 和 gpt-4o-mini-tts\nfunc getTTSModelList() -> [EmbeddingModel] {\n let models: [EmbeddingModel] = [\n EmbeddingModel(\n name: \"Siri\",\n displayName: \"Siri\",\n company: \"SIRI\",\n dimension: 0,\n requestURL: \"\",\n price: 0\n ),\n EmbeddingModel(\n name: \"gpt-4o-mini-tts\",\n displayName: \"GPT-4o-mini-TTS\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.0876\n ),\n EmbeddingModel(\n name: \"tts-1\",\n displayName: \"OpenAI-TTS-1\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.1095\n ),\n EmbeddingModel(\n name: \"tts-1-hd\",\n displayName: \"OpenAI-TTS-1-HD\",\n company: \"OPENAI\",\n dimension: 0,\n requestURL: \"https://api.openai.com/v1/audio/speech\",\n price: 0.2190\n ),\n EmbeddingModel(\n name: \"FunAudioLLM/CosyVoice2-0.5B\",\n displayName: \"FunAudioLLM/CosyVoice2-0.5B\",\n company: \"SILICONCLOUD\",\n dimension: 0,\n requestURL: \"https://api.siliconflow.cn/v1/audio/speech\",\n price: 0.15\n ),\n EmbeddingModel(\n name: \"qwen-tts\",\n displayName: \"Qwen-TTS\",\n company: \"QWEN\",\n dimension: 0,\n requestURL: \"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation\",\n price: 0.0174\n ),\n ]\n return models\n}\n\n// 时间标准化\nfunc formattedDate(_ date: Date) -> String {\n let formatter = DateFormatter()\n formatter.dateStyle = .medium\n formatter.timeStyle = .short\n formatter.locale = .current\n return formatter.string(from: date)\n}\n\n/// 把 Markdown 字符串转换成易粘贴的纯文本\nfunc markdownToPlainText(_ markdown: String) -> String {\n\n // MARK: - 正则缓存(首次调用时才创建)\n struct RX {\n static let codeFence = try! NSRegularExpression(pattern: #\"^\\s*(```|~~~)\"#)\n static let hr = try! NSRegularExpression(pattern: #\"^(\\s*[-*_]\\s*){3,}$\"#)\n static let tableSep = try! NSRegularExpression(pattern: #\"^\\|[\\s\\-:|]+\\|$\"#)\n static let tablePipe = try! NSRegularExpression(pattern: #\"(?<=\\S)\\s*\\|\\s*(?=\\S)\"#)\n static let heading = try! NSRegularExpression(pattern: #\"^\\s{0,3}#{1,6}\\s*\"#)\n static let listDash = try! NSRegularExpression(pattern: #\"^(\\s*)([-*+])\\s+\"#)\n static let blockQuote = try! NSRegularExpression(pattern: #\"^\\s*>\\s*\"#)\n static let inlineCode = try! NSRegularExpression(pattern: #\"`+([^`]+?)`+\"#)\n static let strong = try! NSRegularExpression(pattern: #\"\\*\\*(.*?)\\*\\*|__(.*?)__\"#)\n static let em = try! NSRegularExpression(pattern: #\"\\*(.*?)\\*|_(.*?)_\"#)\n static let del = try! NSRegularExpression(pattern: #\"~~(.*?)~~\"#)\n static let link = try! NSRegularExpression(pattern: #\"\\[([^\\]]+)]\\([^)]+\\)\"#)\n static let image = try! NSRegularExpression(pattern: #\"\\!\\[([^\\]]*)]\\([^)]+\\)\"#)\n static let htmlTag = try! NSRegularExpression(pattern: #\"<[^>]+>\"#)\n static let multiSpace = try! NSRegularExpression(pattern: #\" {2,}\"#)\n }\n\n // 统一换行\n let rows = markdown.replacingOccurrences(of: \"\\r\\n\", with: \"\\n\").components(separatedBy: \"\\n\")\n\n var inFence = false\n var out: [String] = []\n\n for var line in rows {\n let trimmed = line.trimmingCharacters(in: .whitespaces)\n\n // 1) 代码围栏\n if RX.codeFence.firstMatch(in: trimmed, range: NSRange(location: 0, length: trimmed.utf16.count)) != nil {\n inFence.toggle()\n continue\n }\n if inFence { // 代码块内容直接保留\n out.append(line)\n continue\n }\n\n // 2) 跳过 HR / 表格分隔\n if RX.hr.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n if RX.tableSep.firstMatch(in: trimmed, range: trimmed.nsRange) != nil { continue }\n\n // 3) 表格竖线→空格 & 压缩多空格\n line = RX.tablePipe.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n line = RX.multiSpace.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \" \")\n\n // 4) 标题 / 列表符号 / 引用\n line = RX.heading.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n line = RX.listDash.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1· \")\n line = RX.blockQuote.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 5) 行内代码 & 强调\n line = RX.inlineCode.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.strong.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.em .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1$2\")\n line = RX.del .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 6) 链接 / 图片(仅保文本)\n line = RX.link .stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n line = RX.image.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"$1\")\n\n // 7) 去 HTML 标签\n line = RX.htmlTag.stringByReplacingMatches(in: line, range: line.nsRange, withTemplate: \"\")\n\n // 8) HTML 实体解码(常用)\n line = line.replacingOccurrences(of: \" \" , with: \" \")\n .replacingOccurrences(of: \"<\" , with: \"<\")\n .replacingOccurrences(of: \">\" , with: \">\")\n .replacingOccurrences(of: \"&\" , with: \"&\")\n .replacingOccurrences(of: \""\" , with: \"\\\"\")\n .replacingOccurrences(of: \"'\" , with: \"'\")\n\n out.append(line.trimmingCharacters(in: .whitespaces))\n }\n\n // 9) 合并多余空行\n var result: [String] = []\n var blank = false\n for l in out {\n if l.isEmpty {\n if !blank { result.append(\"\") }\n blank = true\n } else {\n result.append(l)\n blank = false\n }\n }\n\n return result.joined(separator: \"\\n\")\n .trimmingCharacters(in: .whitespacesAndNewlines)\n}\n\n// 转换小工具\nprivate extension String {\n /// 生成整个字符串的 NSRange\n var nsRange: NSRange { NSRange(location: 0, length: utf16.count) }\n}\n\n// MARK: - 恢复系统模型默认排序\nfunc resetModelPositionToDefault(context: ModelContext) {\n do {\n let fetchDescriptor = FetchDescriptor()\n let allModels = try context.fetch(fetchDescriptor)\n \n // Step 1: 构建 name -> 预置模型 的映射表\n let predefinedModels = getModelList()\n var predefinedPositionMap: [String: Int] = [:]\n for model in predefinedModels {\n if let name = model.name, let position = model.position {\n predefinedPositionMap[name] = position\n }\n }\n\n // Step 2: 先处理系统预置模型\n var maxSystemPosition = -1\n for model in allModels where model.systemProvision {\n if let name = model.name, let defaultPosition = predefinedPositionMap[name] {\n model.position = defaultPosition\n maxSystemPosition = max(maxSystemPosition, defaultPosition)\n }\n }\n\n // Step 3: 非系统预置模型统一放在系统模型之后,按名称排序\n var nonSystemModels = allModels.filter { !$0.systemProvision }\n nonSystemModels.sort { ($0.displayName ?? \"\") < ($1.displayName ?? \"\") }\n\n for (offset, model) in nonSystemModels.enumerated() {\n let newPosition = maxSystemPosition + 1 + offset\n model.position = newPosition\n }\n\n try context.save()\n print(\"模型排序已按默认规则恢复完毕。\")\n\n } catch {\n print(\"恢复默认模型排序失败:\\(error)\")\n }\n}\n\n/// 解析时间范围:支持中英丰富表达\n/// - 参数 raw: 原始关键词(可能包含类似“刚刚”、“last week”、“3天前”等时间词)\n/// - 返回值:去掉了时间词的“纯搜索词” + 具体的开始时间和结束时间\nfunc extractTimeRange(from raw: String) -> (clean: String, start: Date, end: Date) {\n let now = Date()\n let cal = Calendar.current\n var startDate: Date?\n var endDate: Date = now\n var clean = raw\n \n // 1. 预定义短语(中英文),逐一匹配并移除\n let phraseHandlers: [([String], ()->Void)] = [\n ([\"刚刚\", \"just now\"], {\n startDate = cal.date(byAdding: .minute, value: -5, to: now)\n }),\n ([\"今天\", \"today\"], {\n startDate = cal.startOfDay(for: now)\n }),\n ([\"昨天\", \"yesterday\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = todayStart\n startDate = cal.date(byAdding: .day, value: -1, to: todayStart)\n }),\n ([\"前天\"], {\n let todayStart = cal.startOfDay(for: now)\n endDate = cal.date(byAdding: .day, value: -1, to: todayStart)!\n startDate = cal.date(byAdding: .day, value: -2, to: todayStart)\n }),\n ([\"本周\", \"this week\"], {\n if let interval = cal.dateInterval(of: .weekOfYear, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本月\", \"this month\"], {\n if let interval = cal.dateInterval(of: .month, for: now) {\n startDate = interval.start\n }\n }),\n ([\"本年\", \"今年\", \"this year\"], {\n if let interval = cal.dateInterval(of: .year, for: now) {\n startDate = interval.start\n }\n }),\n ([\"上周\", \"last week\"], {\n startDate = cal.date(byAdding: .weekOfYear, value: -1, to: now)\n }),\n ([\"上个月\", \"last month\"], {\n startDate = cal.date(byAdding: .month, value: -1, to: now)\n }),\n ([\"去年\", \"last year\"], {\n startDate = cal.date(byAdding: .year, value: -1, to: now)\n }),\n ([\"最近一周\", \"过去一周\", \"past week\", \"last 7 days\"], {\n startDate = cal.date(byAdding: .day, value: -7, to: now)\n }),\n ([\"最近30天\", \"过去30天\", \"past month\", \"last 30 days\"], {\n startDate = cal.date(byAdding: .day, value: -30, to: now)\n })\n ]\n for (phrases, handler) in phraseHandlers {\n for p in phrases {\n if clean.range(of: p, options: .caseInsensitive) != nil {\n handler()\n clean = clean.replacingOccurrences(of: p, with: \"\", options: .caseInsensitive)\n }\n }\n }\n \n // 2. 动态正则:匹配“X分钟前/ago/内”、“X小时前”、“X天前”等\n let relativePatterns: [(pattern: String, component: Calendar.Component)] = [\n (\"(\\\\d+)\\\\s*(分钟|min|mins)\\\\s*(前|ago|内)?\", .minute),\n (\"(\\\\d+)\\\\s*(小时|h|hour|hours)\\\\s*(前|ago|内)?\", .hour),\n (\"(\\\\d+)\\\\s*(天|d|day|days)\\\\s*(前|ago|内)?\", .day),\n (\"(\\\\d+)\\\\s*(周|星期|w|week|weeks)\\\\s*(前|ago|内)?\", .weekOfYear),\n (\"(\\\\d+)\\\\s*(月|m|month|months)\\\\s*(前|ago|内)?\", .month),\n (\"(\\\\d+)\\\\s*(年|y|year|years)\\\\s*(前|ago|内)?\", .year)\n ]\n for (pattern, component) in relativePatterns {\n let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)\n if let m = regex.firstMatch(in: clean, range: NSRange(clean.startIndex..., in: clean)),\n let r = Range(m.range(at: 1), in: clean),\n let val = Int(clean[r]) {\n // 计算起始时间\n startDate = cal.date(byAdding: component, value: -val, to: now)\n // 去掉已匹配的相对表达\n clean = regex.stringByReplacingMatches(in: clean,\n options: [],\n range: NSRange(clean.startIndex..., in: clean),\n withTemplate: \"\")\n }\n }\n \n // 3. 默认范围:过去 7 天\n let defaultStart = cal.date(byAdding: .day, value: -7, to: now)!\n \n return (\n clean.trimmingCharacters(in: .whitespacesAndNewlines),\n startDate ?? defaultStart,\n endDate\n )\n}\n"}}}}