diff --git a/src/iac_code/config.py b/src/iac_code/config.py index a8112423..6d9de595 100644 --- a/src/iac_code/config.py +++ b/src/iac_code/config.py @@ -16,7 +16,7 @@ import yaml # Default LLM model used when no model is saved in settings -DEFAULT_MODEL = "qwen3.6-plus" +DEFAULT_MODEL = "qwen3.7-max" # Configuration directory _CONFIG_DIR_NAME = ".iac-code" diff --git a/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po b/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po index f1354a05..f5c2913b 100644 --- a/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po +++ b/src/iac_code/i18n/locales/de/LC_MESSAGES/messages.po @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: iac-code 0.2.0\n" +"Project-Id-Version: iac-code 0.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 15:23+0800\n" +"POT-Creation-Date: 2026-05-21 09:26+0800\n" "PO-Revision-Date: 2026-05-13 00:00+0000\n" "Last-Translator: \n" "Language: de\n" @@ -659,7 +659,7 @@ msgstr "{status}: {provider} / {model}" msgid "Alibaba Cloud" msgstr "Alibaba Cloud" -#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:423 +#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:426 msgid "ZhiPu AI" msgstr "ZhiPu AI" @@ -671,7 +671,7 @@ msgstr "Kimi" msgid "MiniMax" msgstr "MiniMax" -#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:425 +#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:428 msgid "Volcengine" msgstr "Volcengine" @@ -679,27 +679,27 @@ msgstr "Volcengine" msgid "SiliconFlow" msgstr "SiliconFlow" -#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:416 +#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:419 msgid "DeepSeek" msgstr "DeepSeek" -#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:414 +#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:417 msgid "OpenAI" msgstr "OpenAI" -#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:415 +#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:418 msgid "Anthropic" msgstr "Anthropic" -#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:418 +#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:421 msgid "Google Gemini" msgstr "Google Gemini" -#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:431 +#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:434 msgid "Azure OpenAI" msgstr "Azure OpenAI" -#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:430 +#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:433 msgid "OpenRouter" msgstr "OpenRouter" @@ -983,79 +983,79 @@ msgstr "" " Base URL korrekt ist (aktuell: {base_url}). Viele OpenAI-kompatible " "Endpunkte erfordern ein /v1-Suffix (z. B. {base_url}/v1)." -#: src/iac_code/providers/registry.py:412 +#: src/iac_code/providers/registry.py:415 msgid "Alibaba Cloud Bailian" msgstr "Alibaba Cloud Bailian" -#: src/iac_code/providers/registry.py:413 +#: src/iac_code/providers/registry.py:416 msgid "Alibaba Cloud Bailian Token Plan" msgstr "Alibaba Cloud Bailian Token Plan" -#: src/iac_code/providers/registry.py:417 +#: src/iac_code/providers/registry.py:420 msgid "OpenAPI Compatible" msgstr "OpenAPI-kompatibel" -#: src/iac_code/providers/registry.py:419 +#: src/iac_code/providers/registry.py:422 msgid "Kimi (China)" msgstr "Kimi (China)" -#: src/iac_code/providers/registry.py:420 +#: src/iac_code/providers/registry.py:423 msgid "Kimi (International)" msgstr "Kimi (International)" -#: src/iac_code/providers/registry.py:421 +#: src/iac_code/providers/registry.py:424 msgid "MiniMax (China)" msgstr "MiniMax (China)" -#: src/iac_code/providers/registry.py:422 +#: src/iac_code/providers/registry.py:425 msgid "MiniMax (International)" msgstr "MiniMax (International)" -#: src/iac_code/providers/registry.py:424 +#: src/iac_code/providers/registry.py:427 msgid "ZhiPu AI (International)" msgstr "ZhiPu AI (International)" -#: src/iac_code/providers/registry.py:426 +#: src/iac_code/providers/registry.py:429 msgid "SiliconFlow (China)" msgstr "SiliconFlow (China)" -#: src/iac_code/providers/registry.py:427 +#: src/iac_code/providers/registry.py:430 msgid "SiliconFlow (International)" msgstr "SiliconFlow (International)" -#: src/iac_code/providers/registry.py:428 +#: src/iac_code/providers/registry.py:431 msgid "Ollama (Local)" msgstr "Ollama (Lokal)" -#: src/iac_code/providers/registry.py:429 +#: src/iac_code/providers/registry.py:432 msgid "LM Studio (Local)" msgstr "LM Studio (Lokal)" -#: src/iac_code/providers/registry.py:432 +#: src/iac_code/providers/registry.py:435 msgid "ModelScope" msgstr "ModelScope" -#: src/iac_code/providers/registry.py:433 +#: src/iac_code/providers/registry.py:436 msgid "Alibaba Cloud CodingPlan" msgstr "Alibaba Cloud CodingPlan" -#: src/iac_code/providers/registry.py:434 +#: src/iac_code/providers/registry.py:437 msgid "Alibaba Cloud CodingPlan (International)" msgstr "Alibaba Cloud CodingPlan (International)" -#: src/iac_code/providers/registry.py:435 +#: src/iac_code/providers/registry.py:438 msgid "ZhiPu AI CodingPlan" msgstr "ZhiPu AI CodingPlan" -#: src/iac_code/providers/registry.py:436 +#: src/iac_code/providers/registry.py:439 msgid "ZhiPu AI CodingPlan (International)" msgstr "ZhiPu AI CodingPlan (International)" -#: src/iac_code/providers/registry.py:437 +#: src/iac_code/providers/registry.py:440 msgid "Volcengine CodingPlan" msgstr "Volcengine CodingPlan" -#: src/iac_code/providers/registry.py:438 +#: src/iac_code/providers/registry.py:441 msgid "Anthropic Compatible" msgstr "Anthropic-kompatibel" @@ -1359,7 +1359,7 @@ msgstr "CloudAPI" msgid "Calling {action}..." msgstr "{action} wird aufgerufen …" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:373 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:385 #: src/iac_code/tools/cloud/base_api.py:123 msgid "Call succeeded" msgstr "Aufruf erfolgreich" @@ -1519,11 +1519,11 @@ msgstr "IMPORT ABGESCHLOSSEN" msgid "IMPORT_FAILED" msgstr "IMPORT FEHLGESCHLAGEN" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:165 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:170 msgid "Aliyun API" msgstr "Aliyun API" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:372 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:384 #, python-brace-format msgid "Call succeeded (RequestId: {request_id})" msgstr "Aufruf erfolgreich (RequestId: {request_id})" diff --git a/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po b/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po index 306cad3b..cfb5b121 100644 --- a/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po +++ b/src/iac_code/i18n/locales/es/LC_MESSAGES/messages.po @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: iac-code 0.2.0\n" +"Project-Id-Version: iac-code 0.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 15:23+0800\n" +"POT-Creation-Date: 2026-05-21 09:26+0800\n" "PO-Revision-Date: 2026-05-13 00:00+0000\n" "Last-Translator: \n" "Language: es\n" @@ -660,7 +660,7 @@ msgstr "{status}: {provider} / {model}" msgid "Alibaba Cloud" msgstr "Alibaba Cloud" -#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:423 +#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:426 msgid "ZhiPu AI" msgstr "ZhiPu AI" @@ -672,7 +672,7 @@ msgstr "Kimi" msgid "MiniMax" msgstr "MiniMax" -#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:425 +#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:428 msgid "Volcengine" msgstr "Volcengine" @@ -680,27 +680,27 @@ msgstr "Volcengine" msgid "SiliconFlow" msgstr "SiliconFlow" -#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:416 +#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:419 msgid "DeepSeek" msgstr "DeepSeek" -#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:414 +#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:417 msgid "OpenAI" msgstr "OpenAI" -#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:415 +#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:418 msgid "Anthropic" msgstr "Anthropic" -#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:418 +#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:421 msgid "Google Gemini" msgstr "Google Gemini" -#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:431 +#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:434 msgid "Azure OpenAI" msgstr "Azure OpenAI" -#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:430 +#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:433 msgid "OpenRouter" msgstr "OpenRouter" @@ -984,79 +984,79 @@ msgstr "" " correcta (actual: {base_url}). Muchos endpoints compatibles con OpenAI " "requieren el sufijo /v1 (p. ej., {base_url}/v1)." -#: src/iac_code/providers/registry.py:412 +#: src/iac_code/providers/registry.py:415 msgid "Alibaba Cloud Bailian" msgstr "Alibaba Cloud Bailian" -#: src/iac_code/providers/registry.py:413 +#: src/iac_code/providers/registry.py:416 msgid "Alibaba Cloud Bailian Token Plan" msgstr "Alibaba Cloud Bailian Token Plan" -#: src/iac_code/providers/registry.py:417 +#: src/iac_code/providers/registry.py:420 msgid "OpenAPI Compatible" msgstr "Compatible con OpenAPI" -#: src/iac_code/providers/registry.py:419 +#: src/iac_code/providers/registry.py:422 msgid "Kimi (China)" msgstr "Kimi (China)" -#: src/iac_code/providers/registry.py:420 +#: src/iac_code/providers/registry.py:423 msgid "Kimi (International)" msgstr "Kimi (Internacional)" -#: src/iac_code/providers/registry.py:421 +#: src/iac_code/providers/registry.py:424 msgid "MiniMax (China)" msgstr "MiniMax (China)" -#: src/iac_code/providers/registry.py:422 +#: src/iac_code/providers/registry.py:425 msgid "MiniMax (International)" msgstr "MiniMax (Internacional)" -#: src/iac_code/providers/registry.py:424 +#: src/iac_code/providers/registry.py:427 msgid "ZhiPu AI (International)" msgstr "ZhiPu AI (Internacional)" -#: src/iac_code/providers/registry.py:426 +#: src/iac_code/providers/registry.py:429 msgid "SiliconFlow (China)" msgstr "SiliconFlow (China)" -#: src/iac_code/providers/registry.py:427 +#: src/iac_code/providers/registry.py:430 msgid "SiliconFlow (International)" msgstr "SiliconFlow (Internacional)" -#: src/iac_code/providers/registry.py:428 +#: src/iac_code/providers/registry.py:431 msgid "Ollama (Local)" msgstr "Ollama (Local)" -#: src/iac_code/providers/registry.py:429 +#: src/iac_code/providers/registry.py:432 msgid "LM Studio (Local)" msgstr "LM Studio (Local)" -#: src/iac_code/providers/registry.py:432 +#: src/iac_code/providers/registry.py:435 msgid "ModelScope" msgstr "ModelScope" -#: src/iac_code/providers/registry.py:433 +#: src/iac_code/providers/registry.py:436 msgid "Alibaba Cloud CodingPlan" msgstr "Alibaba Cloud CodingPlan" -#: src/iac_code/providers/registry.py:434 +#: src/iac_code/providers/registry.py:437 msgid "Alibaba Cloud CodingPlan (International)" msgstr "Alibaba Cloud CodingPlan (Internacional)" -#: src/iac_code/providers/registry.py:435 +#: src/iac_code/providers/registry.py:438 msgid "ZhiPu AI CodingPlan" msgstr "ZhiPu AI CodingPlan" -#: src/iac_code/providers/registry.py:436 +#: src/iac_code/providers/registry.py:439 msgid "ZhiPu AI CodingPlan (International)" msgstr "ZhiPu AI CodingPlan (Internacional)" -#: src/iac_code/providers/registry.py:437 +#: src/iac_code/providers/registry.py:440 msgid "Volcengine CodingPlan" msgstr "Volcengine CodingPlan" -#: src/iac_code/providers/registry.py:438 +#: src/iac_code/providers/registry.py:441 msgid "Anthropic Compatible" msgstr "Compatible con Anthropic" @@ -1359,7 +1359,7 @@ msgstr "CloudAPI" msgid "Calling {action}..." msgstr "Llamando a {action}..." -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:373 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:385 #: src/iac_code/tools/cloud/base_api.py:123 msgid "Call succeeded" msgstr "Llamada correcta" @@ -1519,11 +1519,11 @@ msgstr "Importación completada" msgid "IMPORT_FAILED" msgstr "Importación fallida" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:165 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:170 msgid "Aliyun API" msgstr "Aliyun API" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:372 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:384 #, python-brace-format msgid "Call succeeded (RequestId: {request_id})" msgstr "Llamada correcta (RequestId: {request_id})" diff --git a/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.po b/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.po index 32e2441a..9f760c5a 100644 --- a/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.po +++ b/src/iac_code/i18n/locales/fr/LC_MESSAGES/messages.po @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: iac-code 0.2.0\n" +"Project-Id-Version: iac-code 0.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 15:23+0800\n" +"POT-Creation-Date: 2026-05-21 09:26+0800\n" "PO-Revision-Date: 2026-05-13 00:00+0000\n" "Last-Translator: \n" "Language: fr\n" @@ -656,7 +656,7 @@ msgstr "{status} : {provider} / {model}" msgid "Alibaba Cloud" msgstr "Alibaba Cloud" -#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:423 +#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:426 msgid "ZhiPu AI" msgstr "ZhiPu AI" @@ -668,7 +668,7 @@ msgstr "Kimi" msgid "MiniMax" msgstr "MiniMax" -#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:425 +#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:428 msgid "Volcengine" msgstr "Volcengine" @@ -676,27 +676,27 @@ msgstr "Volcengine" msgid "SiliconFlow" msgstr "SiliconFlow" -#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:416 +#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:419 msgid "DeepSeek" msgstr "DeepSeek" -#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:414 +#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:417 msgid "OpenAI" msgstr "OpenAI" -#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:415 +#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:418 msgid "Anthropic" msgstr "Anthropic" -#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:418 +#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:421 msgid "Google Gemini" msgstr "Google Gemini" -#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:431 +#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:434 msgid "Azure OpenAI" msgstr "Azure OpenAI" -#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:430 +#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:433 msgid "OpenRouter" msgstr "OpenRouter" @@ -984,79 +984,79 @@ msgstr "" " correcte (actuelle : {base_url}). De nombreux points de terminaison " "compatibles OpenAI exigent le suffixe /v1 (p. ex. {base_url}/v1)." -#: src/iac_code/providers/registry.py:412 +#: src/iac_code/providers/registry.py:415 msgid "Alibaba Cloud Bailian" msgstr "Alibaba Cloud Bailian" -#: src/iac_code/providers/registry.py:413 +#: src/iac_code/providers/registry.py:416 msgid "Alibaba Cloud Bailian Token Plan" msgstr "Alibaba Cloud Bailian Token Plan" -#: src/iac_code/providers/registry.py:417 +#: src/iac_code/providers/registry.py:420 msgid "OpenAPI Compatible" msgstr "Compatible OpenAPI" -#: src/iac_code/providers/registry.py:419 +#: src/iac_code/providers/registry.py:422 msgid "Kimi (China)" msgstr "Kimi (Chine)" -#: src/iac_code/providers/registry.py:420 +#: src/iac_code/providers/registry.py:423 msgid "Kimi (International)" msgstr "Kimi (International)" -#: src/iac_code/providers/registry.py:421 +#: src/iac_code/providers/registry.py:424 msgid "MiniMax (China)" msgstr "MiniMax (Chine)" -#: src/iac_code/providers/registry.py:422 +#: src/iac_code/providers/registry.py:425 msgid "MiniMax (International)" msgstr "MiniMax (International)" -#: src/iac_code/providers/registry.py:424 +#: src/iac_code/providers/registry.py:427 msgid "ZhiPu AI (International)" msgstr "ZhiPu AI (International)" -#: src/iac_code/providers/registry.py:426 +#: src/iac_code/providers/registry.py:429 msgid "SiliconFlow (China)" msgstr "SiliconFlow (Chine)" -#: src/iac_code/providers/registry.py:427 +#: src/iac_code/providers/registry.py:430 msgid "SiliconFlow (International)" msgstr "SiliconFlow (International)" -#: src/iac_code/providers/registry.py:428 +#: src/iac_code/providers/registry.py:431 msgid "Ollama (Local)" msgstr "Ollama (Local)" -#: src/iac_code/providers/registry.py:429 +#: src/iac_code/providers/registry.py:432 msgid "LM Studio (Local)" msgstr "LM Studio (Local)" -#: src/iac_code/providers/registry.py:432 +#: src/iac_code/providers/registry.py:435 msgid "ModelScope" msgstr "ModelScope" -#: src/iac_code/providers/registry.py:433 +#: src/iac_code/providers/registry.py:436 msgid "Alibaba Cloud CodingPlan" msgstr "Alibaba Cloud CodingPlan" -#: src/iac_code/providers/registry.py:434 +#: src/iac_code/providers/registry.py:437 msgid "Alibaba Cloud CodingPlan (International)" msgstr "Alibaba Cloud CodingPlan (International)" -#: src/iac_code/providers/registry.py:435 +#: src/iac_code/providers/registry.py:438 msgid "ZhiPu AI CodingPlan" msgstr "ZhiPu AI CodingPlan" -#: src/iac_code/providers/registry.py:436 +#: src/iac_code/providers/registry.py:439 msgid "ZhiPu AI CodingPlan (International)" msgstr "ZhiPu AI CodingPlan (International)" -#: src/iac_code/providers/registry.py:437 +#: src/iac_code/providers/registry.py:440 msgid "Volcengine CodingPlan" msgstr "Volcengine CodingPlan" -#: src/iac_code/providers/registry.py:438 +#: src/iac_code/providers/registry.py:441 msgid "Anthropic Compatible" msgstr "Compatible Anthropic" @@ -1360,7 +1360,7 @@ msgstr "CloudAPI" msgid "Calling {action}..." msgstr "Appel de {action}…" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:373 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:385 #: src/iac_code/tools/cloud/base_api.py:123 msgid "Call succeeded" msgstr "Appel réussi" @@ -1520,11 +1520,11 @@ msgstr "IMPORT TERMINÉ" msgid "IMPORT_FAILED" msgstr "ÉCHEC DE L’IMPORT" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:165 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:170 msgid "Aliyun API" msgstr "Aliyun API" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:372 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:384 #, python-brace-format msgid "Call succeeded (RequestId: {request_id})" msgstr "Appel réussi (RequestId : {request_id})" diff --git a/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.po b/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.po index d0884a53..71461d5a 100644 --- a/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.po +++ b/src/iac_code/i18n/locales/ja/LC_MESSAGES/messages.po @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: iac-code 0.2.0\n" +"Project-Id-Version: iac-code 0.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 15:23+0800\n" +"POT-Creation-Date: 2026-05-21 09:26+0800\n" "PO-Revision-Date: 2026-05-13 00:00+0000\n" "Last-Translator: \n" "Language: ja\n" @@ -639,7 +639,7 @@ msgstr "{status}:{provider} / {model}" msgid "Alibaba Cloud" msgstr "Alibaba Cloud" -#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:423 +#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:426 msgid "ZhiPu AI" msgstr "ZhiPu AI" @@ -651,7 +651,7 @@ msgstr "Kimi" msgid "MiniMax" msgstr "MiniMax" -#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:425 +#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:428 msgid "Volcengine" msgstr "Volcengine" @@ -659,27 +659,27 @@ msgstr "Volcengine" msgid "SiliconFlow" msgstr "SiliconFlow" -#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:416 +#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:419 msgid "DeepSeek" msgstr "DeepSeek" -#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:414 +#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:417 msgid "OpenAI" msgstr "OpenAI" -#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:415 +#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:418 msgid "Anthropic" msgstr "Anthropic" -#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:418 +#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:421 msgid "Google Gemini" msgstr "Google Gemini" -#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:431 +#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:434 msgid "Azure OpenAI" msgstr "Azure OpenAI" -#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:430 +#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:433 msgid "OpenRouter" msgstr "OpenRouter" @@ -957,79 +957,79 @@ msgstr "" "API から無効な応答が返りました。API Base URL が正しいか確認してください(現在:{base_url})。 多くの OpenAI " "互換エンドポイントでは /v1 接尾辞が必要です(例:{base_url}/v1)。" -#: src/iac_code/providers/registry.py:412 +#: src/iac_code/providers/registry.py:415 msgid "Alibaba Cloud Bailian" msgstr "Alibaba Cloud 百錬" -#: src/iac_code/providers/registry.py:413 +#: src/iac_code/providers/registry.py:416 msgid "Alibaba Cloud Bailian Token Plan" msgstr "Alibaba Cloud 百錬 Token Plan" -#: src/iac_code/providers/registry.py:417 +#: src/iac_code/providers/registry.py:420 msgid "OpenAPI Compatible" msgstr "OpenAPI 互換" -#: src/iac_code/providers/registry.py:419 +#: src/iac_code/providers/registry.py:422 msgid "Kimi (China)" msgstr "Kimi(中国版)" -#: src/iac_code/providers/registry.py:420 +#: src/iac_code/providers/registry.py:423 msgid "Kimi (International)" msgstr "Kimi(国際版)" -#: src/iac_code/providers/registry.py:421 +#: src/iac_code/providers/registry.py:424 msgid "MiniMax (China)" msgstr "MiniMax(中国版)" -#: src/iac_code/providers/registry.py:422 +#: src/iac_code/providers/registry.py:425 msgid "MiniMax (International)" msgstr "MiniMax(国際版)" -#: src/iac_code/providers/registry.py:424 +#: src/iac_code/providers/registry.py:427 msgid "ZhiPu AI (International)" msgstr "ZhiPu AI(国際版)" -#: src/iac_code/providers/registry.py:426 +#: src/iac_code/providers/registry.py:429 msgid "SiliconFlow (China)" msgstr "SiliconFlow(中国版)" -#: src/iac_code/providers/registry.py:427 +#: src/iac_code/providers/registry.py:430 msgid "SiliconFlow (International)" msgstr "SiliconFlow(国際版)" -#: src/iac_code/providers/registry.py:428 +#: src/iac_code/providers/registry.py:431 msgid "Ollama (Local)" msgstr "Ollama(ローカル)" -#: src/iac_code/providers/registry.py:429 +#: src/iac_code/providers/registry.py:432 msgid "LM Studio (Local)" msgstr "LM Studio(ローカル)" -#: src/iac_code/providers/registry.py:432 +#: src/iac_code/providers/registry.py:435 msgid "ModelScope" msgstr "ModelScope" -#: src/iac_code/providers/registry.py:433 +#: src/iac_code/providers/registry.py:436 msgid "Alibaba Cloud CodingPlan" msgstr "Alibaba Cloud CodingPlan" -#: src/iac_code/providers/registry.py:434 +#: src/iac_code/providers/registry.py:437 msgid "Alibaba Cloud CodingPlan (International)" msgstr "Alibaba Cloud CodingPlan(国際版)" -#: src/iac_code/providers/registry.py:435 +#: src/iac_code/providers/registry.py:438 msgid "ZhiPu AI CodingPlan" msgstr "ZhiPu AI CodingPlan" -#: src/iac_code/providers/registry.py:436 +#: src/iac_code/providers/registry.py:439 msgid "ZhiPu AI CodingPlan (International)" msgstr "ZhiPu AI CodingPlan(国際版)" -#: src/iac_code/providers/registry.py:437 +#: src/iac_code/providers/registry.py:440 msgid "Volcengine CodingPlan" msgstr "Volcengine CodingPlan" -#: src/iac_code/providers/registry.py:438 +#: src/iac_code/providers/registry.py:441 msgid "Anthropic Compatible" msgstr "Anthropic 互換" @@ -1329,7 +1329,7 @@ msgstr "CloudAPI" msgid "Calling {action}..." msgstr "{action} を呼び出しています…" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:373 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:385 #: src/iac_code/tools/cloud/base_api.py:123 msgid "Call succeeded" msgstr "呼び出しに成功しました" @@ -1489,11 +1489,11 @@ msgstr "インポート完了" msgid "IMPORT_FAILED" msgstr "インポート失敗" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:165 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:170 msgid "Aliyun API" msgstr "Aliyun API" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:372 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:384 #, python-brace-format msgid "Call succeeded (RequestId: {request_id})" msgstr "呼び出しに成功しました(RequestId: {request_id})" diff --git a/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.po b/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.po index 13d17439..d2e1c3e9 100644 --- a/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.po +++ b/src/iac_code/i18n/locales/pt/LC_MESSAGES/messages.po @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: iac-code 0.2.0\n" +"Project-Id-Version: iac-code 0.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 15:23+0800\n" +"POT-Creation-Date: 2026-05-21 09:26+0800\n" "PO-Revision-Date: 2026-05-13 00:00+0000\n" "Last-Translator: \n" "Language: pt\n" @@ -653,7 +653,7 @@ msgstr "{status}: {provider} / {model}" msgid "Alibaba Cloud" msgstr "Alibaba Cloud" -#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:423 +#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:426 msgid "ZhiPu AI" msgstr "ZhiPu AI" @@ -665,7 +665,7 @@ msgstr "Kimi" msgid "MiniMax" msgstr "MiniMax" -#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:425 +#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:428 msgid "Volcengine" msgstr "Volcengine" @@ -673,27 +673,27 @@ msgstr "Volcengine" msgid "SiliconFlow" msgstr "SiliconFlow" -#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:416 +#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:419 msgid "DeepSeek" msgstr "DeepSeek" -#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:414 +#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:417 msgid "OpenAI" msgstr "OpenAI" -#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:415 +#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:418 msgid "Anthropic" msgstr "Anthropic" -#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:418 +#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:421 msgid "Google Gemini" msgstr "Google Gemini" -#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:431 +#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:434 msgid "Azure OpenAI" msgstr "Azure OpenAI" -#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:430 +#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:433 msgid "OpenRouter" msgstr "OpenRouter" @@ -975,79 +975,79 @@ msgstr "" "correta (atual: {base_url}). Muitos endpoints compatíveis com OpenAI " "exigem o sufixo /v1 (por exemplo, {base_url}/v1)." -#: src/iac_code/providers/registry.py:412 +#: src/iac_code/providers/registry.py:415 msgid "Alibaba Cloud Bailian" msgstr "Alibaba Cloud Bailian" -#: src/iac_code/providers/registry.py:413 +#: src/iac_code/providers/registry.py:416 msgid "Alibaba Cloud Bailian Token Plan" msgstr "Alibaba Cloud Bailian Token Plan" -#: src/iac_code/providers/registry.py:417 +#: src/iac_code/providers/registry.py:420 msgid "OpenAPI Compatible" msgstr "Compatível com OpenAPI" -#: src/iac_code/providers/registry.py:419 +#: src/iac_code/providers/registry.py:422 msgid "Kimi (China)" msgstr "Kimi (China)" -#: src/iac_code/providers/registry.py:420 +#: src/iac_code/providers/registry.py:423 msgid "Kimi (International)" msgstr "Kimi (Internacional)" -#: src/iac_code/providers/registry.py:421 +#: src/iac_code/providers/registry.py:424 msgid "MiniMax (China)" msgstr "MiniMax (China)" -#: src/iac_code/providers/registry.py:422 +#: src/iac_code/providers/registry.py:425 msgid "MiniMax (International)" msgstr "MiniMax (Internacional)" -#: src/iac_code/providers/registry.py:424 +#: src/iac_code/providers/registry.py:427 msgid "ZhiPu AI (International)" msgstr "ZhiPu AI (Internacional)" -#: src/iac_code/providers/registry.py:426 +#: src/iac_code/providers/registry.py:429 msgid "SiliconFlow (China)" msgstr "SiliconFlow (China)" -#: src/iac_code/providers/registry.py:427 +#: src/iac_code/providers/registry.py:430 msgid "SiliconFlow (International)" msgstr "SiliconFlow (Internacional)" -#: src/iac_code/providers/registry.py:428 +#: src/iac_code/providers/registry.py:431 msgid "Ollama (Local)" msgstr "Ollama (Local)" -#: src/iac_code/providers/registry.py:429 +#: src/iac_code/providers/registry.py:432 msgid "LM Studio (Local)" msgstr "LM Studio (Local)" -#: src/iac_code/providers/registry.py:432 +#: src/iac_code/providers/registry.py:435 msgid "ModelScope" msgstr "ModelScope" -#: src/iac_code/providers/registry.py:433 +#: src/iac_code/providers/registry.py:436 msgid "Alibaba Cloud CodingPlan" msgstr "Alibaba Cloud CodingPlan" -#: src/iac_code/providers/registry.py:434 +#: src/iac_code/providers/registry.py:437 msgid "Alibaba Cloud CodingPlan (International)" msgstr "Alibaba Cloud CodingPlan (Internacional)" -#: src/iac_code/providers/registry.py:435 +#: src/iac_code/providers/registry.py:438 msgid "ZhiPu AI CodingPlan" msgstr "ZhiPu AI CodingPlan" -#: src/iac_code/providers/registry.py:436 +#: src/iac_code/providers/registry.py:439 msgid "ZhiPu AI CodingPlan (International)" msgstr "ZhiPu AI CodingPlan (Internacional)" -#: src/iac_code/providers/registry.py:437 +#: src/iac_code/providers/registry.py:440 msgid "Volcengine CodingPlan" msgstr "Volcengine CodingPlan" -#: src/iac_code/providers/registry.py:438 +#: src/iac_code/providers/registry.py:441 msgid "Anthropic Compatible" msgstr "Compatível com Anthropic" @@ -1349,7 +1349,7 @@ msgstr "API na nuvem" msgid "Calling {action}..." msgstr "Chamando {action}..." -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:373 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:385 #: src/iac_code/tools/cloud/base_api.py:123 msgid "Call succeeded" msgstr "Chamada bem-sucedida" @@ -1509,11 +1509,11 @@ msgstr "Importação concluída" msgid "IMPORT_FAILED" msgstr "Falha na importação" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:165 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:170 msgid "Aliyun API" msgstr "Aliyun API" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:372 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:384 #, python-brace-format msgid "Call succeeded (RequestId: {request_id})" msgstr "Chamada bem-sucedida (RequestId: {request_id})" diff --git a/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.po b/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.po index 4bf7273c..56ae66f4 100644 --- a/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.po +++ b/src/iac_code/i18n/locales/zh/LC_MESSAGES/messages.po @@ -4,9 +4,9 @@ # msgid "" msgstr "" -"Project-Id-Version: iac-code 0.2.0\n" +"Project-Id-Version: iac-code 0.2.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-05-20 15:23+0800\n" +"POT-Creation-Date: 2026-05-21 09:26+0800\n" "PO-Revision-Date: 2026-04-02 00:00+0000\n" "Last-Translator: \n" "Language: zh\n" @@ -635,7 +635,7 @@ msgstr "{status}:{provider} / {model}" msgid "Alibaba Cloud" msgstr "阿里云" -#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:423 +#: src/iac_code/commands/auth.py:798 src/iac_code/providers/registry.py:426 msgid "ZhiPu AI" msgstr "智谱 AI" @@ -647,7 +647,7 @@ msgstr "Kimi" msgid "MiniMax" msgstr "MiniMax" -#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:425 +#: src/iac_code/commands/auth.py:801 src/iac_code/providers/registry.py:428 msgid "Volcengine" msgstr "火山引擎" @@ -655,27 +655,27 @@ msgstr "火山引擎" msgid "SiliconFlow" msgstr "硅基流动" -#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:416 +#: src/iac_code/commands/auth.py:803 src/iac_code/providers/registry.py:419 msgid "DeepSeek" msgstr "DeepSeek" -#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:414 +#: src/iac_code/commands/auth.py:804 src/iac_code/providers/registry.py:417 msgid "OpenAI" msgstr "OpenAI" -#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:415 +#: src/iac_code/commands/auth.py:805 src/iac_code/providers/registry.py:418 msgid "Anthropic" msgstr "Anthropic" -#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:418 +#: src/iac_code/commands/auth.py:806 src/iac_code/providers/registry.py:421 msgid "Google Gemini" msgstr "Google Gemini" -#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:431 +#: src/iac_code/commands/auth.py:807 src/iac_code/providers/registry.py:434 msgid "Azure OpenAI" msgstr "Azure OpenAI" -#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:430 +#: src/iac_code/commands/auth.py:808 src/iac_code/providers/registry.py:433 msgid "OpenRouter" msgstr "OpenRouter" @@ -947,79 +947,79 @@ msgstr "" "API 返回了无效响应。请检查您的 API Base URL 是否正确(当前:{base_url})。许多 OpenAI 兼容端点需要 /v1 " "后缀(如 {base_url}/v1)。" -#: src/iac_code/providers/registry.py:412 +#: src/iac_code/providers/registry.py:415 msgid "Alibaba Cloud Bailian" msgstr "阿里云百炼" -#: src/iac_code/providers/registry.py:413 +#: src/iac_code/providers/registry.py:416 msgid "Alibaba Cloud Bailian Token Plan" msgstr "阿里云百炼 Token Plan" -#: src/iac_code/providers/registry.py:417 +#: src/iac_code/providers/registry.py:420 msgid "OpenAPI Compatible" msgstr "OpenAPI 兼容" -#: src/iac_code/providers/registry.py:419 +#: src/iac_code/providers/registry.py:422 msgid "Kimi (China)" msgstr "Kimi(中国版)" -#: src/iac_code/providers/registry.py:420 +#: src/iac_code/providers/registry.py:423 msgid "Kimi (International)" msgstr "Kimi(国际版)" -#: src/iac_code/providers/registry.py:421 +#: src/iac_code/providers/registry.py:424 msgid "MiniMax (China)" msgstr "MiniMax(中国版)" -#: src/iac_code/providers/registry.py:422 +#: src/iac_code/providers/registry.py:425 msgid "MiniMax (International)" msgstr "MiniMax(国际版)" -#: src/iac_code/providers/registry.py:424 +#: src/iac_code/providers/registry.py:427 msgid "ZhiPu AI (International)" msgstr "智谱 AI(国际版)" -#: src/iac_code/providers/registry.py:426 +#: src/iac_code/providers/registry.py:429 msgid "SiliconFlow (China)" msgstr "硅基流动(中国版)" -#: src/iac_code/providers/registry.py:427 +#: src/iac_code/providers/registry.py:430 msgid "SiliconFlow (International)" msgstr "硅基流动(国际版)" -#: src/iac_code/providers/registry.py:428 +#: src/iac_code/providers/registry.py:431 msgid "Ollama (Local)" msgstr "Ollama(本地)" -#: src/iac_code/providers/registry.py:429 +#: src/iac_code/providers/registry.py:432 msgid "LM Studio (Local)" msgstr "LM Studio(本地)" -#: src/iac_code/providers/registry.py:432 +#: src/iac_code/providers/registry.py:435 msgid "ModelScope" msgstr "魔搭" -#: src/iac_code/providers/registry.py:433 +#: src/iac_code/providers/registry.py:436 msgid "Alibaba Cloud CodingPlan" msgstr "阿里云编程计划" -#: src/iac_code/providers/registry.py:434 +#: src/iac_code/providers/registry.py:437 msgid "Alibaba Cloud CodingPlan (International)" msgstr "阿里云编程计划(国际版)" -#: src/iac_code/providers/registry.py:435 +#: src/iac_code/providers/registry.py:438 msgid "ZhiPu AI CodingPlan" msgstr "智谱 AI 编程计划" -#: src/iac_code/providers/registry.py:436 +#: src/iac_code/providers/registry.py:439 msgid "ZhiPu AI CodingPlan (International)" msgstr "智谱 AI 编程计划(国际版)" -#: src/iac_code/providers/registry.py:437 +#: src/iac_code/providers/registry.py:440 msgid "Volcengine CodingPlan" msgstr "火山引擎编程计划" -#: src/iac_code/providers/registry.py:438 +#: src/iac_code/providers/registry.py:441 msgid "Anthropic Compatible" msgstr "Anthropic 兼容" @@ -1316,7 +1316,7 @@ msgstr "云API" msgid "Calling {action}..." msgstr "正在调用 {action}..." -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:373 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:385 #: src/iac_code/tools/cloud/base_api.py:123 msgid "Call succeeded" msgstr "调用成功" @@ -1476,11 +1476,11 @@ msgstr "导入完成" msgid "IMPORT_FAILED" msgstr "导入失败" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:165 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:170 msgid "Aliyun API" msgstr "阿里云 API" -#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:372 +#: src/iac_code/tools/cloud/aliyun/aliyun_api.py:384 #, python-brace-format msgid "Call succeeded (RequestId: {request_id})" msgstr "调用成功(RequestId: {request_id})" diff --git a/src/iac_code/providers/registry.py b/src/iac_code/providers/registry.py index d458d0a8..e35ff070 100644 --- a/src/iac_code/providers/registry.py +++ b/src/iac_code/providers/registry.py @@ -45,7 +45,8 @@ def model_ids(self) -> list[str]: provider_class="iac_code.providers.dashscope_provider.DashScopeProvider", base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", models=[ - ModelEntry("qwen3.6-plus", is_default=True, support_multimodal=True), + ModelEntry("qwen3.7-max", is_default=True, support_multimodal=True), + ModelEntry("qwen3.6-plus", support_multimodal=True), ModelEntry("qwen3.6-max-preview"), ModelEntry("qwen3-max"), ModelEntry("qwen3.5-plus", support_multimodal=True), @@ -148,8 +149,10 @@ def model_ids(self) -> list[str]: provider_class="iac_code.providers.gemini_provider.GeminiProvider", base_url="https://generativelanguage.googleapis.com/v1beta/openai", models=[ - ModelEntry("gemini-3.1-pro-preview", is_default=True, support_multimodal=True), + ModelEntry("gemini-3.5-flash", is_default=True, support_multimodal=True), + ModelEntry("gemini-3.1-pro-preview", support_multimodal=True), ModelEntry("gemini-3-flash-preview", support_multimodal=True), + ModelEntry("gemini-3.1-flash-lite", support_multimodal=True), ModelEntry("gemini-3.1-flash-lite-preview", support_multimodal=True), ModelEntry("gemini-2.5-pro", support_multimodal=True), ModelEntry("gemini-2.5-flash", support_multimodal=True), diff --git a/src/iac_code/providers/thinking.py b/src/iac_code/providers/thinking.py index 62b0ce3d..6c0eb710 100644 --- a/src/iac_code/providers/thinking.py +++ b/src/iac_code/providers/thinking.py @@ -130,6 +130,7 @@ def effort_range(self) -> tuple[EffortLevel, EffortLevel] | None: "deepseek-v4-flash": ThinkingSpec(ThinkingFamily.OPENAI, _DEEPSEEK_EFFORTS, EffortLevel.HIGH), }, "dashscope": { + "qwen3.7-max": ThinkingSpec(ThinkingFamily.DASHSCOPE), "qwen3.6-max-preview": ThinkingSpec(ThinkingFamily.DASHSCOPE), "qwen3.6-plus": ThinkingSpec(ThinkingFamily.DASHSCOPE), "qwen3.5-plus": ThinkingSpec(ThinkingFamily.DASHSCOPE), @@ -147,8 +148,11 @@ def effort_range(self) -> tuple[EffortLevel, EffortLevel] | None: "MiniMax-M2.5": ThinkingSpec(ThinkingFamily.DASHSCOPE), }, "gemini": { + "gemini-3.5-flash": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), "gemini-3.1-pro-preview": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), "gemini-3-flash-preview": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), + "gemini-3.1-flash-lite": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), + "gemini-3.1-flash-lite-preview": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), "gemini-2.5-pro": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), "gemini-2.5-flash": ThinkingSpec(ThinkingFamily.GEMINI, _GEMINI_EFFORTS, EffortLevel.MEDIUM), }, diff --git a/src/iac_code/tools/cloud/aliyun/aliyun_api.py b/src/iac_code/tools/cloud/aliyun/aliyun_api.py index 8044b982..a098b48c 100644 --- a/src/iac_code/tools/cloud/aliyun/aliyun_api.py +++ b/src/iac_code/tools/cloud/aliyun/aliyun_api.py @@ -54,6 +54,11 @@ def _load_endpoints() -> dict[str, Any]: _ENDPOINTS: dict[str, Any] = _load_endpoints() +# Case-insensitive lookup tables for product codes (built once at module load) +_VERSION_MAP_LOWER: dict[str, str] = {k.lower(): v for k, v in VERSION_MAP.items()} +_PRODUCT_CANONICAL: dict[str, str] = {k.lower(): k for k in VERSION_MAP} +_ENDPOINTS_CANONICAL: dict[str, str] = {k.lower(): k for k in _ENDPOINTS} + # Cache for Location service discovered endpoints _endpoint_cache: dict[tuple[str, str], str | None] = {} @@ -232,6 +237,9 @@ def _resolve_version(self, input: dict) -> str: product = input.get("product", "") if product in VERSION_MAP: return VERSION_MAP[product] + version = _VERSION_MAP_LOWER.get(product.lower()) + if version: + return version raise ValueError( f"No built-in version for product '{product}'. Please provide an explicit 'version' parameter." ) @@ -241,7 +249,11 @@ def _get_endpoint(product: str, region_id: str = "") -> str | None: """Resolve endpoint from endpoints.yml. Returns None if not found.""" config = _ENDPOINTS.get(product) if config is None: - return None + canonical = _ENDPOINTS_CANONICAL.get(product.lower()) + if canonical: + config = _ENDPOINTS[canonical] + else: + return None # Global central endpoint (all regions) if "endpoint" in config: return config["endpoint"] @@ -374,6 +386,7 @@ def _summarize_success_result(self, action: str, result: dict) -> str: async def execute(self, *, tool_input: dict[str, Any], context: ToolContext) -> ToolResult: product = tool_input.get("product", "") + product = _PRODUCT_CANONICAL.get(product.lower(), product) action = tool_input.get("action", "") params = tool_input.get("params") or {} region = self._resolve_region(tool_input) @@ -385,6 +398,12 @@ async def execute(self, *, tool_input: dict[str, Any], context: ToolContext) -> params["TemplateBody"] = Path(template_url).read_text() del params["TemplateURL"] + # Pre-call hooks (e.g. resource type validation) + from iac_code.tools.cloud.aliyun.api_hooks import run_hooks + + if hook_result := run_hooks(product, action, params): + return hook_result + try: version = self._resolve_version(tool_input) except ValueError as e: diff --git a/src/iac_code/tools/cloud/aliyun/api_hooks.py b/src/iac_code/tools/cloud/aliyun/api_hooks.py new file mode 100644 index 00000000..f3174f56 --- /dev/null +++ b/src/iac_code/tools/cloud/aliyun/api_hooks.py @@ -0,0 +1,49 @@ +"""Pre-call hooks for AliyunApi with decorator registration and auto-discovery.""" + +from __future__ import annotations + +import importlib +import pkgutil +from pathlib import Path +from typing import Any, Callable + +from iac_code.tools.base import ToolResult + +HookFn = Callable[[str, str, dict[str, Any]], ToolResult | None] + +_hooks: dict[tuple[str, str], list[HookFn]] = {} +_loaded = False + + +def before_call(product: str, action: str): + """Decorator to register a pre-call hook for (product, action).""" + + def decorator(fn: HookFn) -> HookFn: + _hooks.setdefault((product, action), []).append(fn) + return fn + + return decorator + + +def run_hooks(product: str, action: str, params: dict[str, Any]) -> ToolResult | None: + """Execute registered hooks for (product, action). Returns first non-None result.""" + _ensure_loaded() + for hook in _hooks.get((product, action), []): + result = hook(product, action, params) + if result is not None: + return result + return None + + +def _ensure_loaded() -> None: + """Auto-import all modules under hooks/ directory once.""" + global _loaded + if _loaded: + return + _loaded = True + hooks_dir = Path(__file__).parent / "hooks" + if not hooks_dir.is_dir(): + return + package = "iac_code.tools.cloud.aliyun.hooks" + for info in pkgutil.iter_modules([str(hooks_dir)]): + importlib.import_module(f"{package}.{info.name}") diff --git a/src/iac_code/tools/cloud/aliyun/hooks/__init__.py b/src/iac_code/tools/cloud/aliyun/hooks/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/iac_code/tools/cloud/aliyun/hooks/ros_validate.py b/src/iac_code/tools/cloud/aliyun/hooks/ros_validate.py new file mode 100644 index 00000000..9997cb2f --- /dev/null +++ b/src/iac_code/tools/cloud/aliyun/hooks/ros_validate.py @@ -0,0 +1,57 @@ +"""Pre-call hook: validate ROS template resource types before ValidateTemplate API call.""" + +from __future__ import annotations + +import json +from typing import Any + +import yaml + +from iac_code.tools.base import ToolResult +from iac_code.tools.cloud.aliyun.api_hooks import before_call + +_RESOURCE_TYPE_CORRECTIONS: dict[str, str] = { + "ALIYUN::VPC::VPC": "ALIYUN::ECS::VPC", + "ALIYUN::VPC::VSwitch": "ALIYUN::ECS::VSwitch", +} + + +def _parse_template(template_body: str) -> dict | None: + try: + data = yaml.safe_load(template_body) + except Exception: + try: + data = json.loads(template_body) + except Exception: + return None + return data if isinstance(data, dict) else None + + +def _find_wrong_resource_types(template_data: dict) -> dict[str, str]: + """Return {wrong_type: correct_type} for all incorrect resource types found.""" + resources = template_data.get("Resources", {}) + if not isinstance(resources, dict): + return {} + found: dict[str, str] = {} + for resource in resources.values(): + if not isinstance(resource, dict): + continue + rtype = resource.get("Type", "") + if rtype in _RESOURCE_TYPE_CORRECTIONS: + found[rtype] = _RESOURCE_TYPE_CORRECTIONS[rtype] + return found + + +@before_call("ros", "ValidateTemplate") +def check_resource_types(product: str, action: str, params: dict[str, Any]) -> ToolResult | None: + template_body = params.get("TemplateBody", "") + if not template_body: + return None + template_data = _parse_template(template_body) + if template_data is None: + return None + wrong_types = _find_wrong_resource_types(template_data) + if not wrong_types: + return None + corrections = "\n".join(f" {wrong} -> {correct}" for wrong, correct in wrong_types.items()) + return ToolResult.error(f"Template contains incorrect resource types. Please fix before validation:\n{corrections}") diff --git a/tests/tools/cloud/aliyun/test_aliyun_api.py b/tests/tools/cloud/aliyun/test_aliyun_api.py index da1bc4f7..62c2f664 100644 --- a/tests/tools/cloud/aliyun/test_aliyun_api.py +++ b/tests/tools/cloud/aliyun/test_aliyun_api.py @@ -112,6 +112,18 @@ def test_unknown_product_without_version_raises(self, api: AliyunApi) -> None: with pytest.raises(ValueError, match="unknown-product"): api._resolve_version({"product": "unknown-product"}) + def test_case_insensitive_ros(self, api: AliyunApi) -> None: + assert api._resolve_version({"product": "ROS"}) == "2019-09-10" + assert api._resolve_version({"product": "Ros"}) == "2019-09-10" + + def test_case_insensitive_ecs(self, api: AliyunApi) -> None: + assert api._resolve_version({"product": "ECS"}) == "2014-05-26" + + def test_case_insensitive_preserves_mixed_case(self, api: AliyunApi) -> None: + assert api._resolve_version({"product": "IaCService"}) == "2021-08-06" + assert api._resolve_version({"product": "iacservice"}) == "2021-08-06" + assert api._resolve_version({"product": "IACSERVICE"}) == "2021-08-06" + class TestAliyunApiEndpoint: def test_central_only(self, api: AliyunApi) -> None: @@ -152,6 +164,11 @@ def test_unknown_product_returns_none(self, api: AliyunApi) -> None: assert api._get_endpoint("unknown", "cn-hangzhou") is None assert api._get_endpoint("unknown") is None + def test_case_insensitive_endpoint(self, api: AliyunApi) -> None: + assert api._get_endpoint("ROS") == "ros.aliyuncs.com" + assert api._get_endpoint("Ros", "cn-hangzhou") == "ros.aliyuncs.com" + assert api._get_endpoint("ECS", "cn-beijing") == "ecs.cn-beijing.aliyuncs.com" + def test_fallback(self, api: AliyunApi) -> None: assert api._get_endpoint_fallback("unknown", "cn-hangzhou") == "unknown.cn-hangzhou.aliyuncs.com" assert api._get_endpoint_fallback("unknown") == "unknown.aliyuncs.com" @@ -399,6 +416,75 @@ async def test_params_serialized_in_request(self, api: AliyunApi, context: ToolC assert request.query["DryRun"] == "true" +class TestAliyunApiProductNormalization: + @pytest.mark.asyncio + async def test_uppercase_product_works(self, api: AliyunApi, context: ToolContext, mock_credentials) -> None: + mock_client = MagicMock() + mock_client.call_api.return_value = {"body": {"Instances": []}} + + with patch("iac_code.tools.cloud.aliyun.aliyun_api.OpenApiClient", return_value=mock_client): + result = await api.execute( + tool_input={"product": "ROS", "action": "ListStacks", "region_id": "cn-hangzhou"}, + context=context, + ) + assert result.is_error is False + + +class TestAliyunApiHooks: + @pytest.mark.asyncio + async def test_hook_blocks_validate_with_wrong_resource_types( + self, api: AliyunApi, context: ToolContext, mock_credentials + ) -> None: + template = json.dumps( + { + "ROSTemplateFormatVersion": "2015-09-01", + "Resources": { + "Vpc": {"Type": "ALIYUN::VPC::VPC", "Properties": {}}, + "VSwitch": {"Type": "ALIYUN::VPC::VSwitch", "Properties": {}}, + }, + } + ) + result = await api.execute( + tool_input={ + "product": "ros", + "action": "ValidateTemplate", + "params": {"TemplateBody": template}, + "region_id": "cn-hangzhou", + }, + context=context, + ) + assert result.is_error is True + assert "ALIYUN::ECS::VPC" in result.content + assert "ALIYUN::ECS::VSwitch" in result.content + + @pytest.mark.asyncio + async def test_hook_passes_correct_resource_types( + self, api: AliyunApi, context: ToolContext, mock_credentials + ) -> None: + template = json.dumps( + { + "ROSTemplateFormatVersion": "2015-09-01", + "Resources": { + "Vpc": {"Type": "ALIYUN::ECS::VPC", "Properties": {}}, + }, + } + ) + mock_client = MagicMock() + mock_client.call_api.return_value = {"body": {"Description": "Valid"}} + + with patch("iac_code.tools.cloud.aliyun.aliyun_api.OpenApiClient", return_value=mock_client): + result = await api.execute( + tool_input={ + "product": "ros", + "action": "ValidateTemplate", + "params": {"TemplateBody": template}, + "region_id": "cn-hangzhou", + }, + context=context, + ) + assert result.is_error is False + + class TestAliyunApiBuildConfig: def test_ak_mode(self) -> None: credential = AliyunCredential(