phase7: fix async-main breaking GUI task scheduling (critical); catalog corrections from live verification (24 removed, 13 param fixes)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Showing 4 changed files with +338 and −190
modified
Sources/ZyquoCloud/App/Main.swift
+12 −6
@@ -9,23 +9,29 @@ | ||
| 9 | 9 | // the production provider clients); `--load-vault` seeds the encrypted vault |
| 10 | 10 | // from environment keys; otherwise the SwiftUI app launches. |
| 11 | 11 | // |
| 12 | +// Deliberately a synchronous main: launching NSApplicationMain from an async | |
| 13 | +// main() corrupts Swift concurrency's executor setup (background tasks stop | |
| 14 | +// being scheduled), so the CLI modes drive their async work explicitly. | |
| 15 | +// | |
| 12 | 16 | |
| 13 | 17 | import Foundation |
| 14 | 18 | |
| 15 | 19 | @main |
| 16 | 20 | enum Main { |
| 17 | − static func main() async { | |
| 21 | + static func main() { | |
| 18 | 22 | let arguments = CommandLine.arguments |
| 19 | 23 | if arguments.contains("--verify") { |
| 20 | − let status = await VerifyHarness.run(arguments: arguments) | |
| 21 | − exit(status) | |
| 24 | + let semaphore = DispatchSemaphore(value: 0) | |
| 25 | + Task.detached { | |
| 26 | + let status = await VerifyHarness.run(arguments: arguments) | |
| 27 | + exit(status) | |
| 28 | + } | |
| 29 | + semaphore.wait() // exit() above is the only way out | |
| 22 | 30 | } |
| 23 | 31 | if arguments.contains("--load-vault") { |
| 24 | 32 | VerifyHarness.loadVault() |
| 25 | 33 | exit(0) |
| 26 | 34 | } |
| 27 | − await MainActor.run { | |
| 28 | − ZyquoCloudApp.main() | |
| 29 | − } | |
| 35 | + ZyquoCloudApp.main() | |
| 30 | 36 | } |
| 31 | 37 | } |
modified
Sources/ZyquoCloud/Services/ModelCatalogData.swift
+13 −184
@@ -60,7 +60,7 @@ enum ModelCatalogData { | ||
| 60 | 60 | contextWindow: 128_000, maxOutputTokens: nil, |
| 61 | 61 | capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), |
| 62 | 62 | pricing: ModelPricing(inputPerMTok: 5.00, outputPerMTok: 30.00), |
| 63 | − parameterSupport: .openAIDefault | |
| 63 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true) | |
| 64 | 64 | ), |
| 65 | 65 | // Current / recent GPT-5.x |
| 66 | 66 | AIModel( |
@@ -96,7 +96,7 @@ enum ModelCatalogData { | ||
| 96 | 96 | contextWindow: 128_000, maxOutputTokens: nil, |
| 97 | 97 | capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), |
| 98 | 98 | pricing: nil, |
| 99 | − parameterSupport: .openAIDefault | |
| 99 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true) | |
| 100 | 100 | ), |
| 101 | 101 | AIModel( |
| 102 | 102 | id: "gpt-5.2", provider: .openai, displayName: "GPT-5.2", |
@@ -110,7 +110,7 @@ enum ModelCatalogData { | ||
| 110 | 110 | contextWindow: 128_000, maxOutputTokens: 16_000, |
| 111 | 111 | capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), |
| 112 | 112 | pricing: ModelPricing(inputPerMTok: 1.75, outputPerMTok: 14.00), |
| 113 | − parameterSupport: .openAIDefault | |
| 113 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, usesMaxCompletionTokens: true) | |
| 114 | 114 | ), |
| 115 | 115 | AIModel( |
| 116 | 116 | id: "gpt-5.1", provider: .openai, displayName: "GPT-5.1", |
@@ -119,13 +119,6 @@ enum ModelCatalogData { | ||
| 119 | 119 | pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00), |
| 120 | 120 | parameterSupport: openAIReasoning |
| 121 | 121 | ), |
| 122 | − AIModel( | |
| 123 | − id: "gpt-5.1-chat-latest", provider: .openai, displayName: "GPT-5.1 Chat Latest", | |
| 124 | − contextWindow: 128_000, maxOutputTokens: 16_000, | |
| 125 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 126 | − pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00), | |
| 127 | − parameterSupport: .openAIDefault | |
| 128 | − ), | |
| 129 | 122 | AIModel( |
| 130 | 123 | id: "gpt-5", provider: .openai, displayName: "GPT-5", |
| 131 | 124 | contextWindow: 400_000, maxOutputTokens: 128_000, |
@@ -147,13 +140,6 @@ enum ModelCatalogData { | ||
| 147 | 140 | pricing: ModelPricing(inputPerMTok: 0.05, outputPerMTok: 0.40), |
| 148 | 141 | parameterSupport: openAIReasoning |
| 149 | 142 | ), |
| 150 | − AIModel( | |
| 151 | − id: "gpt-5-chat-latest", provider: .openai, displayName: "GPT-5 Chat Latest", | |
| 152 | − contextWindow: 128_000, maxOutputTokens: 16_000, | |
| 153 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 154 | − pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 10.00), | |
| 155 | − parameterSupport: .openAIDefault | |
| 156 | − ), | |
| 157 | 143 | // o-series reasoning |
| 158 | 144 | AIModel( |
| 159 | 145 | id: "o3", provider: .openai, displayName: "OpenAI o3", |
@@ -363,7 +349,7 @@ enum ModelCatalogData { | ||
| 363 | 349 | contextWindow: 1_000_000, maxOutputTokens: nil, |
| 364 | 350 | capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true), |
| 365 | 351 | pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 2.50), |
| 366 | − parameterSupport: ParameterSupport(reasoningEffort: true) | |
| 352 | + parameterSupport: ParameterSupport() | |
| 367 | 353 | ), |
| 368 | 354 | AIModel( |
| 369 | 355 | id: "grok-4.20-non-reasoning", provider: .xai, displayName: "Grok 4.20 Non-Reasoning", |
@@ -372,19 +358,12 @@ enum ModelCatalogData { | ||
| 372 | 358 | pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 2.50), |
| 373 | 359 | parameterSupport: ParameterSupport() |
| 374 | 360 | ), |
| 375 | − AIModel( | |
| 376 | − id: "grok-4.20-multi-agent", provider: .xai, displayName: "Grok 4.20 Multi-Agent", | |
| 377 | − contextWindow: 1_000_000, maxOutputTokens: nil, | |
| 378 | − capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true), | |
| 379 | − pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 2.50), | |
| 380 | − parameterSupport: ParameterSupport(reasoningEffort: true) | |
| 381 | − ), | |
| 382 | 361 | AIModel( |
| 383 | 362 | id: "grok-code-fast-1", provider: .xai, displayName: "Grok Code Fast 1", |
| 384 | 363 | contextWindow: 256_000, maxOutputTokens: nil, |
| 385 | 364 | capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true), |
| 386 | 365 | pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 2.00), |
| 387 | − parameterSupport: ParameterSupport(reasoningEffort: true), | |
| 366 | + parameterSupport: ParameterSupport(), | |
| 388 | 367 | isRecommended: true |
| 389 | 368 | ), |
| 390 | 369 | ] |
@@ -556,13 +535,6 @@ enum ModelCatalogData { | ||
| 556 | 535 | parameterSupport: ParameterSupport(reasoningEffort: true) |
| 557 | 536 | ), |
| 558 | 537 | // Preview / secondary |
| 559 | − AIModel( | |
| 560 | − id: "gemini-3-pro-preview", provider: .gemini, displayName: "Gemini 3 Pro (Preview)", | |
| 561 | − contextWindow: 1_048_576, maxOutputTokens: 65_536, | |
| 562 | − capabilities: ModelCapabilities(vision: true, tools: true, reasoning: true, jsonMode: true), | |
| 563 | − pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 12.00), | |
| 564 | − parameterSupport: ParameterSupport(reasoningEffort: true) | |
| 565 | − ), | |
| 566 | 538 | AIModel( |
| 567 | 539 | id: "gemini-3-flash-preview", provider: .gemini, displayName: "Gemini 3 Flash (Preview)", |
| 568 | 540 | contextWindow: 1_048_576, maxOutputTokens: 65_536, |
@@ -570,22 +542,6 @@ enum ModelCatalogData { | ||
| 570 | 542 | pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 3.00), |
| 571 | 543 | parameterSupport: ParameterSupport(reasoningEffort: true) |
| 572 | 544 | ), |
| 573 | − AIModel( | |
| 574 | − id: "gemini-2.0-flash", provider: .gemini, displayName: "Gemini 2.0 Flash", | |
| 575 | − contextWindow: 1_048_576, maxOutputTokens: 8_192, | |
| 576 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 577 | − pricing: ModelPricing(inputPerMTok: 0.10, outputPerMTok: 0.40), | |
| 578 | − parameterSupport: ParameterSupport(), | |
| 579 | − isLegacy: true | |
| 580 | − ), | |
| 581 | − AIModel( | |
| 582 | − id: "gemini-2.0-flash-lite", provider: .gemini, displayName: "Gemini 2.0 Flash-Lite", | |
| 583 | − contextWindow: 1_048_576, maxOutputTokens: 8_192, | |
| 584 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 585 | − pricing: ModelPricing(inputPerMTok: 0.075, outputPerMTok: 0.30), | |
| 586 | − parameterSupport: ParameterSupport(), | |
| 587 | − isLegacy: true | |
| 588 | − ), | |
| 589 | 545 | AIModel( |
| 590 | 546 | id: "gemma-4-26b-a4b-it", provider: .gemini, displayName: "Gemma 4 26B", |
| 591 | 547 | contextWindow: 262_144, maxOutputTokens: 32_768, |
@@ -751,7 +707,7 @@ enum ModelCatalogData { | ||
| 751 | 707 | contextWindow: 131_072, maxOutputTokens: nil, |
| 752 | 708 | capabilities: ModelCapabilities(vision: true, reasoning: true, jsonMode: true), |
| 753 | 709 | pricing: nil, |
| 754 | − parameterSupport: ParameterSupport() | |
| 710 | + parameterSupport: ParameterSupport(requiresStreaming: true) | |
| 755 | 711 | ), |
| 756 | 712 | // Reasoning-only |
| 757 | 713 | AIModel( |
@@ -759,7 +715,7 @@ enum ModelCatalogData { | ||
| 759 | 715 | contextWindow: 131_072, maxOutputTokens: nil, |
| 760 | 716 | capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), |
| 761 | 717 | pricing: nil, |
| 762 | − parameterSupport: ParameterSupport() | |
| 718 | + parameterSupport: ParameterSupport(requiresStreaming: true) | |
| 763 | 719 | ), |
| 764 | 720 | // Open-weights Qwen hosted on DashScope |
| 765 | 721 | AIModel( |
@@ -1031,27 +987,6 @@ enum ModelCatalogData { | ||
| 1031 | 987 | parameterSupport: .openAIDefault, |
| 1032 | 988 | isRecommended: true |
| 1033 | 989 | ), |
| 1034 | − AIModel( | |
| 1035 | − id: "deepseek-ai/DeepSeek-V3.1", provider: .together, displayName: "DeepSeek V3.1", | |
| 1036 | − contextWindow: 131_072, maxOutputTokens: nil, | |
| 1037 | − capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), | |
| 1038 | − pricing: ModelPricing(inputPerMTok: 0.60, outputPerMTok: 1.70), | |
| 1039 | − parameterSupport: .openAIDefault | |
| 1040 | − ), | |
| 1041 | − AIModel( | |
| 1042 | − id: "deepseek-ai/DeepSeek-R1-0528", provider: .together, displayName: "DeepSeek R1 0528", | |
| 1043 | − contextWindow: 163_840, maxOutputTokens: nil, | |
| 1044 | − capabilities: ModelCapabilities(reasoning: true), | |
| 1045 | − pricing: ModelPricing(inputPerMTok: 3.00, outputPerMTok: 7.00), | |
| 1046 | − parameterSupport: .openAIDefault | |
| 1047 | − ), | |
| 1048 | − AIModel( | |
| 1049 | − id: "deepseek-ai/DeepSeek-R1-Distill-Llama-70B", provider: .together, displayName: "DeepSeek R1 Distill Llama 70B", | |
| 1050 | − contextWindow: 131_072, maxOutputTokens: nil, | |
| 1051 | − capabilities: ModelCapabilities(reasoning: true), | |
| 1052 | − pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 2.00), | |
| 1053 | − parameterSupport: .openAIDefault | |
| 1054 | − ), | |
| 1055 | 990 | AIModel( |
| 1056 | 991 | id: "zai-org/GLM-5.2", provider: .together, displayName: "GLM 5.2", |
| 1057 | 992 | contextWindow: 512_000, maxOutputTokens: nil, |
@@ -1059,117 +994,33 @@ enum ModelCatalogData { | ||
| 1059 | 994 | pricing: ModelPricing(inputPerMTok: 1.40, outputPerMTok: 4.40), |
| 1060 | 995 | parameterSupport: .openAIDefault |
| 1061 | 996 | ), |
| 1062 | − AIModel( | |
| 1063 | − id: "zai-org/GLM-5.1", provider: .together, displayName: "GLM 5.1", | |
| 1064 | − contextWindow: 202_752, maxOutputTokens: nil, | |
| 1065 | − capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), | |
| 1066 | − pricing: ModelPricing(inputPerMTok: 1.40, outputPerMTok: 4.40), | |
| 1067 | − parameterSupport: .openAIDefault | |
| 1068 | − ), | |
| 1069 | − AIModel( | |
| 1070 | − id: "zai-org/GLM-5", provider: .together, displayName: "GLM 5", | |
| 1071 | − contextWindow: 202_752, maxOutputTokens: nil, | |
| 1072 | − capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), | |
| 1073 | − pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 3.20), | |
| 1074 | − parameterSupport: .openAIDefault | |
| 1075 | − ), | |
| 1076 | − AIModel( | |
| 1077 | − id: "zai-org/GLM-4.7", provider: .together, displayName: "GLM 4.7", | |
| 1078 | − contextWindow: 202_752, maxOutputTokens: nil, | |
| 1079 | − capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), | |
| 1080 | − pricing: ModelPricing(inputPerMTok: 0.45, outputPerMTok: 2.00), | |
| 1081 | − parameterSupport: .openAIDefault | |
| 1082 | − ), | |
| 1083 | 997 | AIModel( |
| 1084 | 998 | id: "Qwen/Qwen3.7-Max", provider: .together, displayName: "Qwen3.7 Max", |
| 1085 | 999 | contextWindow: 1_000_000, maxOutputTokens: nil, |
| 1086 | 1000 | capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), |
| 1087 | 1001 | pricing: ModelPricing(inputPerMTok: 1.25, outputPerMTok: 3.75), |
| 1088 | − parameterSupport: .openAIDefault | |
| 1002 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true) | |
| 1089 | 1003 | ), |
| 1090 | 1004 | AIModel( |
| 1091 | 1005 | id: "Qwen/Qwen3.7-Plus", provider: .together, displayName: "Qwen3.7 Plus", |
| 1092 | 1006 | contextWindow: 1_000_000, maxOutputTokens: nil, |
| 1093 | 1007 | capabilities: ModelCapabilities(tools: true, jsonMode: true), |
| 1094 | 1008 | pricing: ModelPricing(inputPerMTok: 0.32, outputPerMTok: 1.28), |
| 1095 | − parameterSupport: .openAIDefault | |
| 1009 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true) | |
| 1096 | 1010 | ), |
| 1097 | 1011 | AIModel( |
| 1098 | 1012 | id: "Qwen/Qwen3.6-Plus", provider: .together, displayName: "Qwen3.6 Plus", |
| 1099 | 1013 | contextWindow: 1_000_000, maxOutputTokens: nil, |
| 1100 | 1014 | capabilities: ModelCapabilities(tools: true, jsonMode: true), |
| 1101 | 1015 | pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 3.00), |
| 1102 | − parameterSupport: .openAIDefault | |
| 1103 | − ), | |
| 1104 | − AIModel( | |
| 1105 | − id: "Qwen/Qwen3.5-397B-A17B", provider: .together, displayName: "Qwen3.5 397B A17B", | |
| 1106 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1107 | − capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), | |
| 1108 | − pricing: ModelPricing(inputPerMTok: 0.60, outputPerMTok: 3.60), | |
| 1109 | − parameterSupport: .openAIDefault | |
| 1016 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true) | |
| 1110 | 1017 | ), |
| 1111 | 1018 | AIModel( |
| 1112 | 1019 | id: "Qwen/Qwen3.5-9B", provider: .together, displayName: "Qwen3.5 9B", |
| 1113 | 1020 | contextWindow: 262_144, maxOutputTokens: nil, |
| 1114 | 1021 | capabilities: ModelCapabilities(tools: true, jsonMode: true), |
| 1115 | 1022 | pricing: ModelPricing(inputPerMTok: 0.17, outputPerMTok: 0.25), |
| 1116 | − parameterSupport: .openAIDefault | |
| 1117 | − ), | |
| 1118 | − AIModel( | |
| 1119 | − id: "Qwen/Qwen3-Next-80B-A3B-Instruct", provider: .together, displayName: "Qwen3 Next 80B Instruct", | |
| 1120 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1121 | − capabilities: ModelCapabilities(tools: true, jsonMode: true), | |
| 1122 | − pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 1.50), | |
| 1123 | − parameterSupport: .openAIDefault | |
| 1124 | − ), | |
| 1125 | − AIModel( | |
| 1126 | − id: "Qwen/Qwen3-Next-80B-A3B-Thinking", provider: .together, displayName: "Qwen3 Next 80B Thinking", | |
| 1127 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1128 | − capabilities: ModelCapabilities(tools: true, reasoning: true, jsonMode: true), | |
| 1129 | − pricing: ModelPricing(inputPerMTok: 0.15, outputPerMTok: 1.50), | |
| 1130 | − parameterSupport: .openAIDefault | |
| 1131 | − ), | |
| 1132 | − AIModel( | |
| 1133 | − id: "Qwen/Qwen3-Coder-Next-FP8", provider: .together, displayName: "Qwen3 Coder Next", | |
| 1134 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1135 | − capabilities: ModelCapabilities(tools: true, jsonMode: true), | |
| 1136 | − pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 1.20), | |
| 1137 | − parameterSupport: .openAIDefault | |
| 1138 | − ), | |
| 1139 | − AIModel( | |
| 1140 | − id: "Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8", provider: .together, displayName: "Qwen3 Coder 480B", | |
| 1141 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1142 | − capabilities: ModelCapabilities(tools: true, jsonMode: true), | |
| 1143 | − pricing: ModelPricing(inputPerMTok: 2.00, outputPerMTok: 2.00), | |
| 1144 | − parameterSupport: .openAIDefault | |
| 1145 | − ), | |
| 1146 | − AIModel( | |
| 1147 | − id: "Qwen/Qwen3-VL-32B-Instruct", provider: .together, displayName: "Qwen3 VL 32B", | |
| 1148 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1149 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 1150 | − pricing: ModelPricing(inputPerMTok: 0.50, outputPerMTok: 1.50), | |
| 1151 | − parameterSupport: .openAIDefault | |
| 1152 | − ), | |
| 1153 | − AIModel( | |
| 1154 | − id: "Qwen/Qwen3-VL-8B-Instruct", provider: .together, displayName: "Qwen3 VL 8B", | |
| 1155 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1156 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 1157 | − pricing: ModelPricing(inputPerMTok: 0.18, outputPerMTok: 0.68), | |
| 1158 | − parameterSupport: .openAIDefault | |
| 1159 | − ), | |
| 1160 | − AIModel( | |
| 1161 | − id: "Qwen/QwQ-32B", provider: .together, displayName: "QwQ 32B", | |
| 1162 | − contextWindow: 131_072, maxOutputTokens: nil, | |
| 1163 | − capabilities: ModelCapabilities(reasoning: true), | |
| 1164 | − pricing: ModelPricing(inputPerMTok: 1.20, outputPerMTok: 1.20), | |
| 1165 | − parameterSupport: .openAIDefault | |
| 1166 | − ), | |
| 1167 | − AIModel( | |
| 1168 | − id: "meta-llama/Llama-4-Scout-17B-16E-Instruct", provider: .together, displayName: "Llama 4 Scout", | |
| 1169 | − contextWindow: 1_048_576, maxOutputTokens: nil, | |
| 1170 | − capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), | |
| 1171 | − pricing: ModelPricing(inputPerMTok: 0.18, outputPerMTok: 0.59), | |
| 1172 | − parameterSupport: .openAIDefault | |
| 1023 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true) | |
| 1173 | 1024 | ), |
| 1174 | 1025 | AIModel( |
| 1175 | 1026 | id: "meta-llama/Llama-3.3-70B-Instruct-Turbo", provider: .together, displayName: "Llama 3.3 70B Turbo", |
@@ -1178,13 +1029,6 @@ enum ModelCatalogData { | ||
| 1178 | 1029 | pricing: ModelPricing(inputPerMTok: 1.04, outputPerMTok: 1.04), |
| 1179 | 1030 | parameterSupport: .openAIDefault |
| 1180 | 1031 | ), |
| 1181 | − AIModel( | |
| 1182 | − id: "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", provider: .together, displayName: "Llama 3.1 8B Turbo", | |
| 1183 | − contextWindow: 131_072, maxOutputTokens: nil, | |
| 1184 | − capabilities: ModelCapabilities(tools: true, jsonMode: true), | |
| 1185 | − pricing: ModelPricing(inputPerMTok: 0.18, outputPerMTok: 0.18), | |
| 1186 | − parameterSupport: .openAIDefault | |
| 1187 | − ), | |
| 1188 | 1032 | AIModel( |
| 1189 | 1033 | id: "openai/gpt-oss-120b", provider: .together, displayName: "GPT-OSS 120B", |
| 1190 | 1034 | contextWindow: 131_072, maxOutputTokens: nil, |
@@ -1214,19 +1058,12 @@ enum ModelCatalogData { | ||
| 1214 | 1058 | pricing: ModelPricing(inputPerMTok: 0.30, outputPerMTok: 1.20), |
| 1215 | 1059 | parameterSupport: .openAIDefault |
| 1216 | 1060 | ), |
| 1217 | − AIModel( | |
| 1218 | − id: "mistralai/Ministral-3-14B-Instruct-2512", provider: .together, displayName: "Ministral 3 14B", | |
| 1219 | − contextWindow: 262_144, maxOutputTokens: nil, | |
| 1220 | − capabilities: ModelCapabilities(tools: true, jsonMode: true), | |
| 1221 | − pricing: ModelPricing(inputPerMTok: 0.20, outputPerMTok: 0.20), | |
| 1222 | − parameterSupport: .openAIDefault | |
| 1223 | − ), | |
| 1224 | 1061 | AIModel( |
| 1225 | 1062 | id: "google/gemma-4-31B-it", provider: .together, displayName: "Gemma 4 31B", |
| 1226 | 1063 | contextWindow: 262_144, maxOutputTokens: nil, |
| 1227 | 1064 | capabilities: ModelCapabilities(vision: true, tools: true, jsonMode: true), |
| 1228 | 1065 | pricing: ModelPricing(inputPerMTok: 0.39, outputPerMTok: 0.97), |
| 1229 | − parameterSupport: .openAIDefault | |
| 1066 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true) | |
| 1230 | 1067 | ), |
| 1231 | 1068 | AIModel( |
| 1232 | 1069 | id: "thinkingmachines/Inkling", provider: .together, displayName: "Inkling", |
@@ -1235,14 +1072,6 @@ enum ModelCatalogData { | ||
| 1235 | 1072 | pricing: ModelPricing(inputPerMTok: 1.00, outputPerMTok: 4.05), |
| 1236 | 1073 | parameterSupport: .openAIDefault |
| 1237 | 1074 | ), |
| 1238 | − AIModel( | |
| 1239 | − id: "mistralai/Mixtral-8x7B-Instruct-v0.1", provider: .together, displayName: "Mixtral 8x7B", | |
| 1240 | − contextWindow: 32_768, maxOutputTokens: nil, | |
| 1241 | − capabilities: ModelCapabilities(jsonMode: true), | |
| 1242 | − pricing: ModelPricing(inputPerMTok: 0.60, outputPerMTok: 0.60), | |
| 1243 | − parameterSupport: .openAIDefault, | |
| 1244 | − isLegacy: true | |
| 1245 | − ), | |
| 1246 | 1075 | ] |
| 1247 | 1076 | |
| 1248 | 1077 | // MARK: - DeepInfra |
@@ -1369,7 +1198,7 @@ enum ModelCatalogData { | ||
| 1369 | 1198 | contextWindow: 262_144, maxOutputTokens: nil, |
| 1370 | 1199 | capabilities: ModelCapabilities(tools: true, jsonMode: true), |
| 1371 | 1200 | pricing: ModelPricing(inputPerMTok: 0.45, outputPerMTok: 2.25), |
| 1372 | − parameterSupport: .openAIDefault | |
| 1201 | + parameterSupport: ParameterSupport(frequencyPenalty: true, presencePenalty: true, requiresStreaming: true) | |
| 1373 | 1202 | ), |
| 1374 | 1203 | AIModel( |
| 1375 | 1204 | id: "zai-org/GLM-5.2", provider: .deepinfra, displayName: "GLM 5.2", |
modified
docs/PROVIDERS.md
+72 −0
@@ -1634,3 +1634,75 @@ No context/pricing/capability metadata — dynamic refresh can only diff IDs; ev | ||
| 1634 | 1634 | from the built-in catalog (this document). |
| 1635 | 1635 | |
| 1636 | 1636 | --- |
| 1637 | + | |
| 1638 | +## Phase 7 verification amendments (2026-07-30) | |
| 1639 | + | |
| 1640 | +Live-key verification (Phase 7 harness) against the real APIs produced the following corrections. | |
| 1641 | +`ModelCatalogData.swift` has been updated in lockstep; the two must stay in sync. | |
| 1642 | + | |
| 1643 | +### OpenAI | |
| 1644 | + | |
| 1645 | +- **Removed** `gpt-5-chat-latest` — API returns "has been deprecated". | |
| 1646 | +- **Removed** `gpt-5.1-chat-latest` — API returns "has been deprecated". | |
| 1647 | +- `chat-latest`: parameter support corrected to `usesMaxCompletionTokens: true` — API rejects `max_tokens`. | |
| 1648 | +- `gpt-5.2-chat-latest`: parameter support corrected to `usesMaxCompletionTokens: true` — API rejects `max_tokens`. | |
| 1649 | +- `gpt-5.3-chat-latest`: parameter support corrected to `usesMaxCompletionTokens: true` — API rejects `max_tokens`. | |
| 1650 | + | |
| 1651 | +### Google Gemini | |
| 1652 | + | |
| 1653 | +- **Removed** `gemini-2.0-flash` — API: "no longer available". | |
| 1654 | +- **Removed** `gemini-2.0-flash-lite` — API: "no longer available". | |
| 1655 | +- **Removed** `gemini-3-pro-preview` — API: "no longer available" (superseded by `gemini-3.1-pro-preview`). | |
| 1656 | + | |
| 1657 | +### xAI (Grok) | |
| 1658 | + | |
| 1659 | +- `grok-4.20`: `reasoningEffort` set to `false` — API rejects the `reasoning_effort` parameter. | |
| 1660 | +- `grok-code-fast-1`: `reasoningEffort` set to `false` — API rejects the `reasoning_effort` parameter. | |
| 1661 | +- **Removed** `grok-4.20-multi-agent` — API: "Multi Agent requests are not allowed on chat completions". | |
| 1662 | + | |
| 1663 | +### Alibaba Qwen (DashScope) | |
| 1664 | + | |
| 1665 | +- `qvq-max`: `requiresStreaming: true` — non-streaming calls fail with "current user api does not support http call" / empty response; the client aggregates a stream instead. | |
| 1666 | +- `qwq-plus`: `requiresStreaming: true` — same failure mode as `qvq-max`. | |
| 1667 | +- Note: `ParameterSupport` gained a new field `requiresStreaming: Bool = false` for models that reject non-streaming calls. | |
| 1668 | + | |
| 1669 | +### Together AI | |
| 1670 | + | |
| 1671 | +- **Removed** the following non-serverless (dedicated-endpoint-only) entries, which are not callable on the serverless chat completions API: | |
| 1672 | + - `Qwen/QwQ-32B` | |
| 1673 | + - `Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8` | |
| 1674 | + - `Qwen/Qwen3-Coder-Next-FP8` | |
| 1675 | + - `Qwen/Qwen3-Next-80B-A3B-Instruct` | |
| 1676 | + - `Qwen/Qwen3-Next-80B-A3B-Thinking` | |
| 1677 | + - `Qwen/Qwen3-VL-32B-Instruct` | |
| 1678 | + - `Qwen/Qwen3-VL-8B-Instruct` | |
| 1679 | + - `Qwen/Qwen3.5-397B-A17B` | |
| 1680 | + - `deepseek-ai/DeepSeek-R1-0528` | |
| 1681 | + - `deepseek-ai/DeepSeek-R1-Distill-Llama-70B` | |
| 1682 | + - `deepseek-ai/DeepSeek-V3.1` | |
| 1683 | + - `meta-llama/Llama-4-Scout-17B-16E-Instruct` | |
| 1684 | + - `meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo` | |
| 1685 | + - `mistralai/Ministral-3-14B-Instruct-2512` | |
| 1686 | + - `mistralai/Mixtral-8x7B-Instruct-v0.1` | |
| 1687 | + - `zai-org/GLM-4.7` | |
| 1688 | + - `zai-org/GLM-5` | |
| 1689 | + - `zai-org/GLM-5.1` | |
| 1690 | +- `Qwen/Qwen3.6-Plus`: `requiresStreaming: true` — API: "This model only supports streaming". | |
| 1691 | +- `Qwen/Qwen3.7-Max`: `requiresStreaming: true` — API: "This model only supports streaming". | |
| 1692 | +- `Qwen/Qwen3.7-Plus`: `requiresStreaming: true` — API: "This model only supports streaming". | |
| 1693 | +- `Qwen/Qwen3.5-9B`: `requiresStreaming: true` — empty responses on non-streaming calls (likely same cause; to be re-verified). | |
| 1694 | +- `google/gemma-4-31B-it`: `requiresStreaming: true` — empty responses on non-streaming calls (likely same cause; to be re-verified). | |
| 1695 | +- Recommended set unaffected: none of the removed entries was `isRecommended`; `moonshotai/Kimi-K3`, `deepseek-ai/DeepSeek-V4-Pro`, and `openai/gpt-oss-120b` remain the recommended Together models. | |
| 1696 | + | |
| 1697 | +### DeepInfra | |
| 1698 | + | |
| 1699 | +- `moonshotai/Kimi-K2.5`: `requiresStreaming: true` — empty non-streaming response. | |
| 1700 | + | |
| 1701 | +### Client-side fixes discovered during verification (informational — no catalog change) | |
| 1702 | + | |
| 1703 | +- Mistral `reasoning_effort` only accepts `"high"`/`"none"` — the client now maps `low` → `none` and `medium`/`high` → `high`. | |
| 1704 | +- Mistral magistral/thinking responses return message content as arrays of chunks — the client now flattens `ThinkChunk`/`TextChunk` into text + reasoning. | |
| 1705 | +- Gemini OpenAI-compat `/models` returns IDs prefixed with `models/` — the client strips the prefix before diffing against the catalog. | |
| 1706 | +- xAI aliases `grok-4.20`, `grok-4.20-non-reasoning`, and `grok-code-fast-1` resolve on chat completions but do not appear in `/models` — the harness keeps them on an allowlist. | |
| 1707 | +- xAI and Qwen vision endpoints reject images smaller than 8px — the vision harness now uses a 64×64 test image. | |
| 1708 | +- `sonar-deep-research` (Perplexity) is skipped in the bulk sweep — it launches multi-minute agentic research runs unsuitable for automated verification. | |
added
docs/VERIFICATION.md
+241 −0
@@ -0,0 +1,241 @@ | ||
| 1 | +<!-- | |
| 2 | + VERIFICATION.md | |
| 3 | + Zyquo Cloud | |
| 4 | + Author: Simon-Pierre Boucher | |
| 5 | + Mail: contact@spboucher.ai | |
| 6 | +--> | |
| 7 | + | |
| 8 | +# API Verification Results — 2026-07-30T07:53:25Z | |
| 9 | + | |
| 10 | +**228 tests · 180 passed · 48 failed** | |
| 11 | + | |
| 12 | +| Provider | Model | Test | Result | Latency | Detail | | |
| 13 | +|---|---|---|---|---|---| | |
| 14 | +| Anthropic | `—` | models | ✅ | 1.2s | 11 live | | |
| 15 | +| Anthropic | `claude-fable-5` | chat | ✅ | 4.4s | | | |
| 16 | +| Anthropic | `claude-haiku-4-5-20251001` | chat | ✅ | 0.6s | | | |
| 17 | +| Anthropic | `claude-opus-4-1-20250805` | chat | ✅ | 1.8s | | | |
| 18 | +| Anthropic | `claude-opus-4-5-20251101` | chat | ✅ | 1.5s | | | |
| 19 | +| Anthropic | `claude-opus-4-6` | chat | ✅ | 10.2s | | | |
| 20 | +| Anthropic | `claude-opus-4-7` | chat | ✅ | 1.0s | | | |
| 21 | +| Anthropic | `claude-opus-4-8` | chat | ✅ | 1.0s | | | |
| 22 | +| Anthropic | `claude-opus-5` | chat | ✅ | 2.7s | | | |
| 23 | +| Anthropic | `claude-opus-5` | stream | ✅ | 2.4s | deltas=2 usage=true | | |
| 24 | +| Anthropic | `claude-opus-5` | vision | ✅ | 2.7s | Pink | | |
| 25 | +| Anthropic | `claude-sonnet-4-5-20250929` | chat | ✅ | 1.7s | | | |
| 26 | +| Anthropic | `claude-sonnet-4-6` | chat | ✅ | 1.1s | | | |
| 27 | +| Anthropic | `claude-sonnet-5` | chat | ✅ | 2.1s | | | |
| 28 | +| Cerebras | `—` | models | ✅ | 0.2s | 3 live | | |
| 29 | +| Cerebras | `gemma-4-31b` | chat | ✅ | 0.3s | | | |
| 30 | +| Cerebras | `gemma-4-31b` | vision | ✅ | 0.2s | Red | | |
| 31 | +| Cerebras | `gpt-oss-120b` | chat | ✅ | 0.1s | | | |
| 32 | +| Cerebras | `gpt-oss-120b` | stream | ✅ | 0.3s | deltas=2 usage=true | | |
| 33 | +| Cerebras | `zai-glm-4.7` | chat | ✅ | 0.5s | | | |
| 34 | +| DeepInfra | `—` | models | ✅ | 0.9s | 174 live | | |
| 35 | +| DeepInfra | `MiniMaxAI/MiniMax-M3` | chat | ✅ | 2.0s | | | |
| 36 | +| DeepInfra | `Qwen/Qwen3-235B-A22B-Instruct-2507` | chat | ✅ | 0.4s | | | |
| 37 | +| DeepInfra | `Qwen/Qwen3-235B-A22B-Thinking-2507` | chat | ✅ | 1.3s | | | |
| 38 | +| DeepInfra | `Qwen/Qwen3-Coder-480B-A35B-Instruct-Turbo` | chat | ✅ | 0.2s | | | |
| 39 | +| DeepInfra | `Qwen/Qwen3-VL-235B-A22B-Instruct` | chat | ✅ | 0.3s | | | |
| 40 | +| DeepInfra | `Qwen/Qwen3.5-397B-A17B` | chat | ✅ | 6.5s | | | |
| 41 | +| DeepInfra | `Qwen/Qwen3.7-Max` | chat | ✅ | 3.9s | | | |
| 42 | +| DeepInfra | `anthropic/claude-fable-5` | chat | ✅ | 2.0s | | | |
| 43 | +| DeepInfra | `anthropic/claude-fable-5` | stream | ✅ | 2.9s | deltas=4 usage=true | | |
| 44 | +| DeepInfra | `anthropic/claude-fable-5` | vision | ✅ | 3.2s | Pink | | |
| 45 | +| DeepInfra | `anthropic/claude-haiku-4-5` | chat | ✅ | 1.6s | | | |
| 46 | +| DeepInfra | `anthropic/claude-opus-4-8` | chat | ✅ | 2.9s | | | |
| 47 | +| DeepInfra | `anthropic/claude-opus-5` | chat | ✅ | 1.8s | | | |
| 48 | +| DeepInfra | `anthropic/claude-sonnet-5` | chat | ✅ | 1.5s | | | |
| 49 | +| DeepInfra | `deepseek-ai/DeepSeek-R1-0528` | chat | ✅ | 1.4s | | | |
| 50 | +| DeepInfra | `deepseek-ai/DeepSeek-V3.1` | chat | ✅ | 0.5s | | | |
| 51 | +| DeepInfra | `deepseek-ai/DeepSeek-V4-Flash` | chat | ✅ | 1.9s | | | |
| 52 | +| DeepInfra | `deepseek-ai/DeepSeek-V4-Pro` | chat | ✅ | 18.2s | | | |
| 53 | +| DeepInfra | `google/gemini-2.5-flash` | chat | ✅ | 1.3s | | | |
| 54 | +| DeepInfra | `google/gemini-2.5-pro` | chat | ✅ | 5.0s | | | |
| 55 | +| DeepInfra | `google/gemini-3.1-flash-lite` | chat | ✅ | 1.3s | | | |
| 56 | +| DeepInfra | `google/gemini-3.1-pro` | chat | ✅ | 3.8s | | | |
| 57 | +| DeepInfra | `google/gemini-3.5-flash` | chat | ✅ | 2.6s | | | |
| 58 | +| DeepInfra | `google/gemma-4-31B-it` | chat | ✅ | 38.2s | | | |
| 59 | +| DeepInfra | `meta-llama/Llama-3.3-70B-Instruct-Turbo` | chat | ✅ | 0.2s | | | |
| 60 | +| DeepInfra | `meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8` | chat | ✅ | 0.3s | | | |
| 61 | +| DeepInfra | `meta-llama/Llama-4-Scout-17B-16E-Instruct` | chat | ✅ | 0.2s | | | |
| 62 | +| DeepInfra | `meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo` | chat | ✅ | 0.3s | | | |
| 63 | +| DeepInfra | `mistralai/Mistral-Small-3.2-24B-Instruct-2506` | chat | ✅ | 0.3s | | | |
| 64 | +| DeepInfra | `moonshotai/Kimi-K2.5` | chat | ❌ | 1.9s | empty response | | |
| 65 | +| DeepInfra | `moonshotai/Kimi-K2.6` | chat | ✅ | 0.7s | | | |
| 66 | +| DeepInfra | `moonshotai/Kimi-K2.7-Code` | chat | ❌ | 0.1s | DeepInfra rate limited — please retry shortly. | | |
| 67 | +| DeepInfra | `nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B` | chat | ✅ | 1.3s | | | |
| 68 | +| DeepInfra | `openai/gpt-oss-120b` | chat | ✅ | 0.9s | | | |
| 69 | +| DeepInfra | `openai/gpt-oss-20b` | chat | ✅ | 0.4s | | | |
| 70 | +| DeepInfra | `zai-org/GLM-4.7` | chat | ✅ | 8.1s | | | |
| 71 | +| DeepInfra | `zai-org/GLM-5.2` | chat | ✅ | 1.1s | | | |
| 72 | +| DeepSeek | `—` | models | ✅ | 0.4s | 2 live | | |
| 73 | +| DeepSeek | `deepseek-v4-flash` | chat | ✅ | 1.2s | | | |
| 74 | +| DeepSeek | `deepseek-v4-flash` | stream | ✅ | 1.2s | deltas=9 usage=true | | |
| 75 | +| DeepSeek | `deepseek-v4-pro` | chat | ✅ | 1.4s | | | |
| 76 | +| Google Gemini | `—` | models | ❌ | 0.3s | catalog IDs not live: gemini-3.6-flash, gemini-3.5-flash, gemini-3.5-flash-lite, gemini-3.1-pro-preview, gemini-3.1-flash-lite, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite, gemini-pro-latest, gemini-flash-latest, gemini-flash-lite-latest, gemini-3-pro-preview, gemini-3-flash-preview, gemini-2.0-flash, gemini-2.0-flash-lite, gemma-4-26b-a4b-it, gemma-4-31b-it | | |
| 77 | +| Google Gemini | `gemini-2.0-flash` | chat | ❌ | 0.2s | Google Gemini rejected the request: This model models/gemini-2.0-flash is no longer available. Please update your code to use a newer model for the latest features and improvements. We recommend you to use the Interactions API (https://ai.google.dev/gemini-api/docs/migrate-to-interactions).. | | |
| 78 | +| Google Gemini | `gemini-2.0-flash-lite` | chat | ❌ | 0.1s | Google Gemini rejected the request: This model models/gemini-2.0-flash-lite is no longer available. Please update your code to use a newer model for the latest features and improvements. We recommend you to use the Interactions API (https://ai.google.dev/gemini-api/docs/migrate-to-interactions).. | | |
| 79 | +| Google Gemini | `gemini-2.5-flash` | chat | ✅ | 0.7s | | | |
| 80 | +| Google Gemini | `gemini-2.5-flash-lite` | chat | ✅ | 0.5s | | | |
| 81 | +| Google Gemini | `gemini-2.5-pro` | chat | ✅ | 4.2s | | | |
| 82 | +| Google Gemini | `gemini-3-flash-preview` | chat | ✅ | 1.1s | | | |
| 83 | +| Google Gemini | `gemini-3-pro-preview` | chat | ❌ | 0.1s | Google Gemini rejected the request: This model models/gemini-3-pro-preview is no longer available. Please update your code to use a newer model for the latest features and improvements. We recommend you to use the Interactions API (https://ai.google.dev/gemini-api/docs/migrate-to-interactions).. | | |
| 84 | +| Google Gemini | `gemini-3.1-flash-lite` | chat | ✅ | 0.8s | | | |
| 85 | +| Google Gemini | `gemini-3.1-pro-preview` | chat | ✅ | 2.5s | | | |
| 86 | +| Google Gemini | `gemini-3.5-flash` | chat | ✅ | 1.0s | | | |
| 87 | +| Google Gemini | `gemini-3.5-flash-lite` | chat | ✅ | 0.8s | | | |
| 88 | +| Google Gemini | `gemini-3.6-flash` | chat | ✅ | 1.3s | | | |
| 89 | +| Google Gemini | `gemini-3.6-flash` | stream | ✅ | 1.2s | deltas=1 usage=true | | |
| 90 | +| Google Gemini | `gemini-3.6-flash` | vision | ✅ | 1.5s | Pink | | |
| 91 | +| Google Gemini | `gemini-flash-latest` | chat | ✅ | 1.0s | | | |
| 92 | +| Google Gemini | `gemini-flash-lite-latest` | chat | ✅ | 0.8s | | | |
| 93 | +| Google Gemini | `gemini-pro-latest` | chat | ✅ | 2.4s | | | |
| 94 | +| Google Gemini | `gemma-4-26b-a4b-it` | chat | ✅ | 1.7s | | | |
| 95 | +| Google Gemini | `gemma-4-31b-it` | chat | ✅ | 2.1s | | | |
| 96 | +| Kimi | `—` | models | ✅ | 0.7s | 12 live | | |
| 97 | +| Kimi | `kimi-k2.5` | chat | ✅ | 3.1s | | | |
| 98 | +| Kimi | `kimi-k2.6` | chat | ✅ | 2.4s | | | |
| 99 | +| Kimi | `kimi-k2.7-code` | chat | ✅ | 2.0s | | | |
| 100 | +| Kimi | `kimi-k2.7-code` | stream | ✅ | 2.9s | deltas=9 usage=true | | |
| 101 | +| Kimi | `kimi-k2.7-code-highspeed` | chat | ✅ | 0.8s | | | |
| 102 | +| Kimi | `kimi-k3` | chat | ❌ | 10.1s | Kimi rate limited — please retry shortly. | | |
| 103 | +| Kimi | `kimi-k3` | vision | ✅ | 31.5s | Black | | |
| 104 | +| Kimi | `moonshot-v1-128k` | chat | ✅ | 0.9s | | | |
| 105 | +| Kimi | `moonshot-v1-128k-vision-preview` | chat | ✅ | 0.7s | | | |
| 106 | +| Kimi | `moonshot-v1-32k` | chat | ✅ | 0.6s | | | |
| 107 | +| Kimi | `moonshot-v1-32k-vision-preview` | chat | ✅ | 1.1s | | | |
| 108 | +| Kimi | `moonshot-v1-8k` | chat | ✅ | 0.5s | | | |
| 109 | +| Kimi | `moonshot-v1-8k-vision-preview` | chat | ✅ | 0.5s | | | |
| 110 | +| Kimi | `moonshot-v1-auto` | chat | ✅ | 0.8s | | | |
| 111 | +| Mistral | `—` | models | ✅ | 0.6s | 60 live | | |
| 112 | +| Mistral | `codestral-latest` | chat | ✅ | 0.4s | | | |
| 113 | +| Mistral | `devstral-latest` | chat | ✅ | 1.0s | | | |
| 114 | +| Mistral | `magistral-medium-latest` | chat | ❌ | 2.0s | Unexpected response from Mistral: decode failed: The data couldn’t be read because it isn’t in the correct format. | | |
| 115 | +| Mistral | `ministral-14b-latest` | chat | ✅ | 0.3s | | | |
| 116 | +| Mistral | `ministral-3b-latest` | chat | ✅ | 0.3s | | | |
| 117 | +| Mistral | `ministral-8b-latest` | chat | ✅ | 0.4s | | | |
| 118 | +| Mistral | `mistral-large-latest` | chat | ✅ | 0.4s | | | |
| 119 | +| Mistral | `mistral-large-latest` | stream | ✅ | 0.5s | deltas=3 usage=true | | |
| 120 | +| Mistral | `mistral-medium-latest` | chat | ❌ | 0.3s | Mistral rejected the request: reasoning_effort low is not supported for this model, supported values: [<ReasoningEffort.high: 'high'>, <ReasoningEffort.none: 'none'>]. | | |
| 121 | +| Mistral | `mistral-medium-latest` | vision | ❌ | 0.3s | Mistral rejected the request: reasoning_effort low is not supported for this model, supported values: [<ReasoningEffort.high: 'high'>, <ReasoningEffort.none: 'none'>]. | | |
| 122 | +| Mistral | `mistral-small-latest` | chat | ❌ | 0.3s | Mistral rejected the request: reasoning_effort='low' is not supported for this model. Must be one of (<ReasoningEffort.none: 'none'>, <ReasoningEffort.high: 'high'>). | | |
| 123 | +| Mistral | `open-mistral-nemo` | chat | ✅ | 0.3s | | | |
| 124 | +| OpenAI | `—` | models | ✅ | 0.6s | 132 live | | |
| 125 | +| OpenAI | `chat-latest` | chat | ❌ | 0.4s | OpenAI rejected the request: Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.. | | |
| 126 | +| OpenAI | `gpt-3.5-turbo` | chat | ✅ | 1.4s | | | |
| 127 | +| OpenAI | `gpt-4` | chat | ✅ | 1.1s | | | |
| 128 | +| OpenAI | `gpt-4-turbo` | chat | ✅ | 2.3s | | | |
| 129 | +| OpenAI | `gpt-4.1` | chat | ✅ | 0.6s | | | |
| 130 | +| OpenAI | `gpt-4.1-mini` | chat | ✅ | 1.7s | | | |
| 131 | +| OpenAI | `gpt-4.1-nano` | chat | ✅ | 0.5s | | | |
| 132 | +| OpenAI | `gpt-4o` | chat | ✅ | 0.4s | | | |
| 133 | +| OpenAI | `gpt-4o-mini` | chat | ✅ | 0.3s | | | |
| 134 | +| OpenAI | `gpt-5` | chat | ✅ | 1.4s | | | |
| 135 | +| OpenAI | `gpt-5-chat-latest` | chat | ❌ | 0.1s | OpenAI rejected the request: The model `gpt-5-chat-latest` has been deprecated, learn more here: https://platform.openai.com/docs/deprecations. | | |
| 136 | +| OpenAI | `gpt-5-mini` | chat | ✅ | 1.1s | | | |
| 137 | +| OpenAI | `gpt-5-nano` | chat | ✅ | 1.1s | | | |
| 138 | +| OpenAI | `gpt-5.1` | chat | ✅ | 0.9s | | | |
| 139 | +| OpenAI | `gpt-5.1-chat-latest` | chat | ❌ | 0.1s | OpenAI rejected the request: The model `gpt-5.1-chat-latest` has been deprecated, learn more here: https://platform.openai.com/docs/deprecations. | | |
| 140 | +| OpenAI | `gpt-5.2` | chat | ✅ | 1.2s | | | |
| 141 | +| OpenAI | `gpt-5.2-chat-latest` | chat | ❌ | 0.1s | OpenAI rejected the request: Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.. | | |
| 142 | +| OpenAI | `gpt-5.3-chat-latest` | chat | ❌ | 0.4s | OpenAI rejected the request: Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens' instead.. | | |
| 143 | +| OpenAI | `gpt-5.4` | chat | ✅ | 0.6s | | | |
| 144 | +| OpenAI | `gpt-5.4-mini` | chat | ✅ | 0.5s | | | |
| 145 | +| OpenAI | `gpt-5.4-nano` | chat | ✅ | 1.0s | | | |
| 146 | +| OpenAI | `gpt-5.5` | chat | ✅ | 2.2s | | | |
| 147 | +| OpenAI | `gpt-5.6-luna` | chat | ✅ | 1.3s | | | |
| 148 | +| OpenAI | `gpt-5.6-sol` | chat | ✅ | 2.3s | | | |
| 149 | +| OpenAI | `gpt-5.6-sol` | stream | ✅ | 1.0s | deltas=9 usage=true | | |
| 150 | +| OpenAI | `gpt-5.6-sol` | vision | ✅ | 3.5s | Cyan | | |
| 151 | +| OpenAI | `gpt-5.6-terra` | chat | ✅ | 1.6s | | | |
| 152 | +| OpenAI | `o1` | chat | ✅ | 1.9s | | | |
| 153 | +| OpenAI | `o3` | chat | ✅ | 0.6s | | | |
| 154 | +| OpenAI | `o3-mini` | chat | ✅ | 1.6s | | | |
| 155 | +| OpenAI | `o4-mini` | chat | ✅ | 0.7s | | | |
| 156 | +| Perplexity | `sonar` | chat | ✅ | 1.4s | | | |
| 157 | +| Perplexity | `sonar` | stream | ✅ | 1.5s | deltas=9 usage=true | | |
| 158 | +| Perplexity | `sonar-deep-research` | chat | ✅ | — | SKIPPED: multi-minute agentic research runs; verified via docs only | | |
| 159 | +| Perplexity | `sonar-pro` | chat | ✅ | 1.9s | | | |
| 160 | +| Perplexity | `sonar-reasoning-pro` | chat | ✅ | 2.8s | | | |
| 161 | +| Alibaba Qwen | `—` | models | ✅ | 1.0s | 151 live | | |
| 162 | +| Alibaba Qwen | `deepseek-v4-flash` | chat | ✅ | 1.3s | | | |
| 163 | +| Alibaba Qwen | `deepseek-v4-pro` | chat | ✅ | 1.6s | | | |
| 164 | +| Alibaba Qwen | `glm-5.2` | chat | ✅ | 2.3s | | | |
| 165 | +| Alibaba Qwen | `kimi-k2.7-code` | chat | ✅ | 1.2s | | | |
| 166 | +| Alibaba Qwen | `qvq-max` | chat | ❌ | 0.5s | Alibaba Qwen rejected the request: current user api does not support http call. | | |
| 167 | +| Alibaba Qwen | `qwen-flash` | chat | ✅ | 0.4s | | | |
| 168 | +| Alibaba Qwen | `qwen-max` | chat | ✅ | 0.5s | | | |
| 169 | +| Alibaba Qwen | `qwen-plus` | chat | ✅ | 0.7s | | | |
| 170 | +| Alibaba Qwen | `qwen-turbo` | chat | ✅ | 0.5s | | | |
| 171 | +| Alibaba Qwen | `qwen3-235b-a22b-instruct-2507` | chat | ✅ | 0.5s | | | |
| 172 | +| Alibaba Qwen | `qwen3-235b-a22b-thinking-2507` | chat | ✅ | 1.1s | | | |
| 173 | +| Alibaba Qwen | `qwen3-coder-480b-a35b-instruct` | chat | ✅ | 1.0s | | | |
| 174 | +| Alibaba Qwen | `qwen3-coder-flash` | chat | ✅ | 0.8s | | | |
| 175 | +| Alibaba Qwen | `qwen3-coder-next` | chat | ✅ | 0.7s | | | |
| 176 | +| Alibaba Qwen | `qwen3-coder-plus` | chat | ✅ | 0.8s | | | |
| 177 | +| Alibaba Qwen | `qwen3-next-80b-a3b-instruct` | chat | ✅ | 0.5s | | | |
| 178 | +| Alibaba Qwen | `qwen3-next-80b-a3b-thinking` | chat | ✅ | 1.0s | | | |
| 179 | +| Alibaba Qwen | `qwen3-vl-235b-a22b-instruct` | chat | ✅ | 0.5s | | | |
| 180 | +| Alibaba Qwen | `qwen3-vl-235b-a22b-thinking` | chat | ✅ | 102.1s | | | |
| 181 | +| Alibaba Qwen | `qwen3-vl-flash` | chat | ✅ | 0.8s | | | |
| 182 | +| Alibaba Qwen | `qwen3-vl-plus` | chat | ✅ | 0.8s | | | |
| 183 | +| Alibaba Qwen | `qwen3.5-122b-a10b` | chat | ✅ | 1.1s | | | |
| 184 | +| Alibaba Qwen | `qwen3.5-35b-a3b` | chat | ✅ | 1.3s | | | |
| 185 | +| Alibaba Qwen | `qwen3.5-397b-a17b` | chat | ✅ | 4.6s | | | |
| 186 | +| Alibaba Qwen | `qwen3.5-flash` | chat | ✅ | 1.4s | | | |
| 187 | +| Alibaba Qwen | `qwen3.5-plus` | chat | ✅ | 5.5s | | | |
| 188 | +| Alibaba Qwen | `qwen3.6-flash` | chat | ✅ | 1.8s | | | |
| 189 | +| Alibaba Qwen | `qwen3.6-plus` | chat | ✅ | 4.0s | | | |
| 190 | +| Alibaba Qwen | `qwen3.7-flash` | chat | ✅ | 1.5s | | | |
| 191 | +| Alibaba Qwen | `qwen3.7-max` | chat | ✅ | 3.4s | | | |
| 192 | +| Alibaba Qwen | `qwen3.7-max` | stream | ✅ | 5.9s | deltas=3 usage=true | | |
| 193 | +| Alibaba Qwen | `qwen3.7-plus` | chat | ✅ | 3.3s | | | |
| 194 | +| Alibaba Qwen | `qwen3.7-plus` | vision | ❌ | 1.0s | Alibaba Qwen rejected the request: <400> InternalError.Algo.InvalidParameter: The image length and width do not meet the model restrictions. [height:1 or width:1 must be larger than 10]. | | |
| 195 | +| Alibaba Qwen | `qwq-plus` | chat | ❌ | 3.8s | empty response | | |
| 196 | +| Together AI | `—` | models | ✅ | 0.4s | 270 live | | |
| 197 | +| Together AI | `MiniMaxAI/MiniMax-M3` | chat | ✅ | 1.6s | | | |
| 198 | +| Together AI | `Qwen/QwQ-32B` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model Qwen/QwQ-32B. Please visit https://api.together.ai/models/Qwen/QwQ-32B to create and start a new dedicated endpoint for the model.. | | |
| 199 | +| Together AI | `Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8` | chat | ❌ | 0.5s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8. Please visit https://api.together.ai/models/Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8 to create and start a new dedicated endpoint for the model.. | | |
| 200 | +| Together AI | `Qwen/Qwen3-Coder-Next-FP8` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-Coder-Next-FP8. Please visit https://api.together.ai/models/Qwen/Qwen3-Coder-Next-FP8 to create and start a new dedicated endpoint for the model.. | | |
| 201 | +| Together AI | `Qwen/Qwen3-Next-80B-A3B-Instruct` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-Next-80B-A3B-Instruct. Please visit https://api.together.ai/models/Qwen/Qwen3-Next-80B-A3B-Instruct to create and start a new dedicated endpoint for the model.. | | |
| 202 | +| Together AI | `Qwen/Qwen3-Next-80B-A3B-Thinking` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-Next-80B-A3B-Thinking. Please visit https://api.together.ai/models/Qwen/Qwen3-Next-80B-A3B-Thinking to create and start a new dedicated endpoint for the model.. | | |
| 203 | +| Together AI | `Qwen/Qwen3-VL-32B-Instruct` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-VL-32B-Instruct. Please visit https://api.together.ai/models/Qwen/Qwen3-VL-32B-Instruct to create and start a new dedicated endpoint for the model.. | | |
| 204 | +| Together AI | `Qwen/Qwen3-VL-32B-Instruct` | vision | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-VL-32B-Instruct. Please visit https://api.together.ai/models/Qwen/Qwen3-VL-32B-Instruct to create and start a new dedicated endpoint for the model.. | | |
| 205 | +| Together AI | `Qwen/Qwen3-VL-8B-Instruct` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3-VL-8B-Instruct. Please visit https://api.together.ai/models/Qwen/Qwen3-VL-8B-Instruct to create and start a new dedicated endpoint for the model.. | | |
| 206 | +| Together AI | `Qwen/Qwen3.5-397B-A17B` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model Qwen/Qwen3.5-397B-A17B. Please visit https://api.together.ai/models/Qwen/Qwen3.5-397B-A17B to create and start a new dedicated endpoint for the model.. | | |
| 207 | +| Together AI | `Qwen/Qwen3.5-9B` | chat | ❌ | 1.1s | empty response | | |
| 208 | +| Together AI | `Qwen/Qwen3.6-Plus` | chat | ❌ | 0.2s | Together AI rejected the request: This model only supports streaming. Set "stream": true.. | | |
| 209 | +| Together AI | `Qwen/Qwen3.7-Max` | chat | ❌ | 0.2s | Together AI rejected the request: This model only supports streaming. Set "stream": true.. | | |
| 210 | +| Together AI | `Qwen/Qwen3.7-Plus` | chat | ❌ | 0.2s | Together AI rejected the request: This model only supports streaming. Set "stream": true.. | | |
| 211 | +| Together AI | `deepseek-ai/DeepSeek-R1-0528` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model deepseek-ai/DeepSeek-R1-0528. Please visit https://api.together.ai/models/deepseek-ai/DeepSeek-R1-0528 to create and start a new dedicated endpoint for the model.. | | |
| 212 | +| Together AI | `deepseek-ai/DeepSeek-R1-Distill-Llama-70B` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model deepseek-ai/DeepSeek-R1-Distill-Llama-70B. Please visit https://api.together.ai/models/deepseek-ai/DeepSeek-R1-Distill-Llama-70B to create and start a new dedicated endpoint for the model.. | | |
| 213 | +| Together AI | `deepseek-ai/DeepSeek-V3.1` | chat | ❌ | 0.3s | Together AI rejected the request: Unable to access non-serverless model deepseek-ai/DeepSeek-V3.1. Please visit https://api.together.ai/models/deepseek-ai/DeepSeek-V3.1 to create and start a new dedicated endpoint for the model.. | | |
| 214 | +| Together AI | `deepseek-ai/DeepSeek-V4-Pro` | chat | ✅ | 1.0s | | | |
| 215 | +| Together AI | `google/gemma-4-31B-it` | chat | ❌ | 1.4s | empty response | | |
| 216 | +| Together AI | `meta-llama/Llama-3.3-70B-Instruct-Turbo` | chat | ✅ | 1.3s | | | |
| 217 | +| Together AI | `meta-llama/Llama-4-Scout-17B-16E-Instruct` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model meta-llama/Llama-4-Scout-17B-16E-Instruct. Please visit https://api.together.ai/models/meta-llama/Llama-4-Scout-17B-16E-Instruct to create and start a new dedicated endpoint for the model.. | | |
| 218 | +| Together AI | `meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo. Please visit https://api.together.ai/models/meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo to create and start a new dedicated endpoint for the model.. | | |
| 219 | +| Together AI | `mistralai/Ministral-3-14B-Instruct-2512` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model mistralai/Ministral-3-14B-Instruct-2512. Please visit https://api.together.ai/models/mistralai/Ministral-3-14B-Instruct-2512 to create and start a new dedicated endpoint for the model.. | | |
| 220 | +| Together AI | `mistralai/Mixtral-8x7B-Instruct-v0.1` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model mistralai/Mixtral-8x7B-Instruct-v0.1. Please visit https://api.together.ai/models/mistralai/Mixtral-8x7B-Instruct-v0.1 to create and start a new dedicated endpoint for the model.. | | |
| 221 | +| Together AI | `moonshotai/Kimi-K2.6` | chat | ✅ | 1.5s | | | |
| 222 | +| Together AI | `moonshotai/Kimi-K2.7-Code` | chat | ✅ | 1.0s | | | |
| 223 | +| Together AI | `moonshotai/Kimi-K3` | chat | ✅ | 2.2s | | | |
| 224 | +| Together AI | `moonshotai/Kimi-K3` | stream | ✅ | 3.4s | deltas=2 usage=true | | |
| 225 | +| Together AI | `nvidia/nemotron-3-ultra-550b-a55b` | chat | ✅ | 0.8s | | | |
| 226 | +| Together AI | `openai/gpt-oss-120b` | chat | ✅ | 0.5s | | | |
| 227 | +| Together AI | `openai/gpt-oss-20b` | chat | ✅ | 0.4s | | | |
| 228 | +| Together AI | `thinkingmachines/Inkling` | chat | ✅ | 0.5s | | | |
| 229 | +| Together AI | `zai-org/GLM-4.7` | chat | ❌ | 0.6s | Together AI rejected the request: Unable to access non-serverless model zai-org/GLM-4.7. Please visit https://api.together.ai/models/zai-org/GLM-4.7 to create and start a new dedicated endpoint for the model.. | | |
| 230 | +| Together AI | `zai-org/GLM-5` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model zai-org/GLM-5. Please visit https://api.together.ai/models/zai-org/GLM-5 to create and start a new dedicated endpoint for the model.. | | |
| 231 | +| Together AI | `zai-org/GLM-5.1` | chat | ❌ | 0.2s | Together AI rejected the request: Unable to access non-serverless model zai-org/GLM-5.1. Please visit https://api.together.ai/models/zai-org/GLM-5.1 to create and start a new dedicated endpoint for the model.. | | |
| 232 | +| Together AI | `zai-org/GLM-5.2` | chat | ✅ | 1.1s | | | |
| 233 | +| xAI | `—` | models | ❌ | 0.3s | catalog IDs not live: grok-4.20, grok-4.20-non-reasoning, grok-4.20-multi-agent, grok-code-fast-1 | | |
| 234 | +| xAI | `grok-4.20` | chat | ❌ | 0.1s | xAI rejected the request: Model grok-4.20 does not support parameter reasoningEffort.. | | |
| 235 | +| xAI | `grok-4.20-multi-agent` | chat | ❌ | 0.1s | xAI rejected the request: "Multi Agent requests are not allowed on chat completions". | | |
| 236 | +| xAI | `grok-4.20-non-reasoning` | chat | ✅ | 0.3s | | | |
| 237 | +| xAI | `grok-4.3` | chat | ✅ | 1.3s | | | |
| 238 | +| xAI | `grok-4.5` | chat | ✅ | 0.7s | | | |
| 239 | +| xAI | `grok-4.5` | stream | ✅ | 1.3s | deltas=9 usage=true | | |
| 240 | +| xAI | `grok-4.5` | vision | ❌ | 0.3s | xAI rejected the request: Image dimensions 1x1 are too small. Both width and height must be at least 8 pixels.. | | |
| 241 | +| xAI | `grok-code-fast-1` | chat | ❌ | 0.1s | xAI rejected the request: Model grok-code-fast-1 does not support parameter reasoningEffort.. | | |
| 242 | ||