iatoolkit 2.16.2__tar.gz → 2.17.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. {iatoolkit-2.16.2/src/iatoolkit.egg-info → iatoolkit-2.17.0}/PKG-INFO +1 -1
  2. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/__init__.py +1 -1
  3. iatoolkit-2.17.0/src/iatoolkit/infra/llm_gateway_resolver.py +164 -0
  4. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_proxy.py +66 -13
  5. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/configuration_service.py +166 -0
  6. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/login_view.py +7 -5
  7. {iatoolkit-2.16.2 → iatoolkit-2.17.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  8. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit.egg-info/SOURCES.txt +1 -0
  9. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/LICENSE +0 -0
  10. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/LICENSE_COMMUNITY.md +0 -0
  11. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/pyproject.toml +0 -0
  12. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/readme.md +0 -0
  13. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/requirements.txt +0 -0
  14. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/setup.cfg +0 -0
  15. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/base_company.py +0 -0
  16. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/cli_commands.py +0 -0
  17. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/__init__.py +0 -0
  18. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/exceptions.py +0 -0
  19. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  20. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  21. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  22. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  23. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
  24. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  25. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  26. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  27. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/model_registry.py +0 -0
  28. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/routes.py +0 -0
  29. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/secret_resolver.py +0 -0
  30. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/session_manager.py +0 -0
  31. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/common/util.py +0 -0
  32. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/company_registry.py +0 -0
  33. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/__init__.py +0 -0
  34. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  35. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  36. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  37. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  38. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  39. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  40. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  41. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  42. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  43. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  44. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  45. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  46. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  47. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  48. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  49. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  50. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  51. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  52. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  53. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  54. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  55. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  56. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  57. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  58. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  59. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/sql_rules.prompt +0 -0
  60. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  61. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  62. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  63. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/core.py +0 -0
  64. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/__init__.py +0 -0
  65. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  66. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/call_service.py +0 -0
  67. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  68. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  69. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  70. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  71. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  72. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  73. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  74. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
  75. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
  76. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  77. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/inference_handler.py +0 -0
  78. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  79. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  80. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  81. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  82. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  83. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  84. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  85. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  86. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/llm_response.py +0 -0
  87. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  88. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/locales/en.yaml +0 -0
  89. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/locales/es.yaml +0 -0
  90. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/__init__.py +0 -0
  91. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  92. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/database_manager.py +0 -0
  93. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/document_repo.py +0 -0
  94. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  95. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  96. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  97. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  98. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
  99. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/models.py +0 -0
  100. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
  101. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  102. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  103. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  104. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
  105. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/__init__.py +0 -0
  106. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/api_key_service.py +0 -0
  107. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  108. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/auth_service.py +0 -0
  109. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/benchmark_service.py +0 -0
  110. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/branding_service.py +0 -0
  111. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/company_context_service.py +0 -0
  112. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/context_builder_service.py +0 -0
  113. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
  114. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/embedding_service.py +0 -0
  115. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/excel_service.py +0 -0
  116. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/file_processor_service.py +0 -0
  117. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/history_manager_service.py +0 -0
  118. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/http_tool_service.py +0 -0
  119. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/i18n_service.py +0 -0
  120. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/inference_service.py +0 -0
  121. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/jwt_service.py +0 -0
  122. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  123. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/language_service.py +0 -0
  124. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/license_service.py +0 -0
  125. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/llm_client_service.py +0 -0
  126. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/mail_service.py +0 -0
  127. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/mcp_token_service.py +0 -0
  128. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  129. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/memory_lint_service.py +0 -0
  130. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  131. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/memory_service.py +0 -0
  132. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  133. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  134. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
  135. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
  136. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
  137. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  138. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  139. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  140. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  141. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  142. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  143. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  144. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  145. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/parsers/validator.py +0 -0
  146. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/pdf_service.py +0 -0
  147. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/profile_service.py +0 -0
  148. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  149. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/prompt_service.py +0 -0
  150. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/query_service.py +0 -0
  151. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  152. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  153. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/sql_service.py +0 -0
  154. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/sql_source_service.py +0 -0
  155. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/storage_service.py +0 -0
  156. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/structured_output_service.py +0 -0
  157. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  158. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/system_tools.py +0 -0
  159. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/telemetry_service.py +0 -0
  160. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/tool_service.py +0 -0
  161. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
  162. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
  163. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
  164. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
  165. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/warmup_service.py +0 -0
  166. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
  167. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  168. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  169. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  170. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/services/web_search_service.py +0 -0
  171. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  172. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  173. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  174. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  175. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  176. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  177. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  178. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  179. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_main.js +0 -0
  180. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  181. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  182. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  183. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  184. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
  185. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  186. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  187. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
  188. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/documents.css +0 -0
  189. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
  190. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
  191. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
  192. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/_company_header.html +0 -0
  193. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/_login_widget.html +0 -0
  194. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/account.html +0 -0
  195. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/base.html +0 -0
  196. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/change_password.html +0 -0
  197. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/chat.html +0 -0
  198. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  199. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/chat_modals.html +0 -0
  200. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/error.html +0 -0
  201. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/forgot_password.html +0 -0
  202. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  203. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  204. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
  205. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/pdf/base.html +0 -0
  206. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
  207. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/pdf/report.html +0 -0
  208. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
  209. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/templates/signup.html +0 -0
  210. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/__init__.py +0 -0
  211. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/account_view.py +0 -0
  212. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
  213. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/base_login_view.py +0 -0
  214. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/categories_api_view.py +0 -0
  215. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/change_password_view.py +0 -0
  216. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  217. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/chat_view.py +0 -0
  218. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
  219. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
  220. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
  221. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
  222. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
  223. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/history_api_view.py +0 -0
  224. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/home_view.py +0 -0
  225. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
  226. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  227. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
  228. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/logout_api_view.py +0 -0
  229. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/memory_api_view.py +0 -0
  230. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/profile_api_view.py +0 -0
  231. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
  232. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  233. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  234. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/rag_api_view.py +0 -0
  235. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
  236. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/signup_view.py +0 -0
  237. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/static_page_view.py +0 -0
  238. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/tool_api_view.py +0 -0
  239. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  240. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/users_api_view.py +0 -0
  241. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit/views/verify_user_view.py +0 -0
  242. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  243. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit.egg-info/requires.txt +0 -0
  244. {iatoolkit-2.16.2 → iatoolkit-2.17.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.16.2
3
+ Version: 2.17.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -3,7 +3,7 @@
3
3
  #
4
4
  # IAToolkit is open source software.
5
5
 
6
- __version__ = "2.16.2"
6
+ __version__ = "2.17.0"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -0,0 +1,164 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict
4
+
5
+ from iatoolkit.common.exceptions import IAToolkitException
6
+ from iatoolkit.common.interfaces.secret_provider import SecretProvider
7
+ from iatoolkit.common.secret_resolver import resolve_secret
8
+ from iatoolkit.services.configuration_service import ConfigurationService
9
+
10
+
11
+ class LLMGatewayResolver:
12
+ """Resolves optional outbound LLM gateway transport settings."""
13
+
14
+ PROVIDER_SLUGS = {
15
+ "openai": "openai",
16
+ "deepseek": "deepseek",
17
+ "anthropic": "anthropic",
18
+ "gemini": "google-ai-studio",
19
+ }
20
+ SUPPORTED_PROVIDERS = frozenset(PROVIDER_SLUGS)
21
+ CREDENTIAL_MODE_PROVIDER_KEY = "provider_key_in_request"
22
+ CREDENTIAL_MODE_CLOUDFLARE_MANAGED = "cloudflare_managed"
23
+
24
+ def __init__(self, configuration_service: ConfigurationService, secret_provider: SecretProvider):
25
+ self.configuration_service = configuration_service
26
+ self.secret_provider = secret_provider
27
+
28
+ def resolve(self, company_short_name: str, provider: str, provider_api_key: str | None) -> Dict[str, Any]:
29
+ normalized_provider = str(provider or "").strip().lower()
30
+ gateway_cfg = self.configuration_service.get_llm_gateway_config(company_short_name, normalized_provider) or {}
31
+ if not isinstance(gateway_cfg, dict) or gateway_cfg.get("enabled") is not True:
32
+ return {
33
+ "enabled": False,
34
+ "api_key": provider_api_key or "",
35
+ "base_url": "",
36
+ "default_headers": {},
37
+ }
38
+
39
+ vendor = str(gateway_cfg.get("vendor") or "").strip().lower()
40
+ if vendor != "cloudflare":
41
+ raise IAToolkitException(
42
+ IAToolkitException.ErrorType.CONFIG_ERROR,
43
+ f"Unsupported llm.gateway vendor '{vendor}'.",
44
+ )
45
+
46
+ mode = str(gateway_cfg.get("mode") or "").strip().lower()
47
+ if mode != "provider_native":
48
+ raise IAToolkitException(
49
+ IAToolkitException.ErrorType.CONFIG_ERROR,
50
+ f"Unsupported llm.gateway mode '{mode}'.",
51
+ )
52
+
53
+ provider_slug = self.PROVIDER_SLUGS.get(normalized_provider)
54
+ if not provider_slug:
55
+ return {
56
+ "enabled": False,
57
+ "api_key": provider_api_key or "",
58
+ "base_url": "",
59
+ "default_headers": {},
60
+ }
61
+
62
+ account_id = self._resolve_gateway_value(
63
+ company_short_name,
64
+ gateway_cfg,
65
+ direct_key="account_id",
66
+ secret_ref_key="account_id_secret_ref",
67
+ env_key="account_id_env",
68
+ )
69
+ gateway_id = str(gateway_cfg.get("gateway_id") or "").strip()
70
+ if not account_id or not gateway_id:
71
+ raise IAToolkitException(
72
+ IAToolkitException.ErrorType.CONFIG_ERROR,
73
+ "Cloudflare gateway requires resolved account_id and gateway_id.",
74
+ )
75
+
76
+ credential_mode = str(
77
+ gateway_cfg.get("credential_mode") or self.CREDENTIAL_MODE_PROVIDER_KEY
78
+ ).strip().lower()
79
+ authenticated_gateway = gateway_cfg.get("authenticated_gateway") is True
80
+ default_headers: dict[str, str] = {}
81
+
82
+ cloudflare_api_token = self._resolve_gateway_value(
83
+ company_short_name,
84
+ gateway_cfg,
85
+ direct_key="cloudflare_api_token",
86
+ secret_ref_key="cloudflare_api_token_secret_ref",
87
+ env_key="cloudflare_api_token_env",
88
+ )
89
+ if authenticated_gateway:
90
+ if not cloudflare_api_token:
91
+ raise IAToolkitException(
92
+ IAToolkitException.ErrorType.CONFIG_ERROR,
93
+ "Authenticated Cloudflare gateway requires a resolved cloudflare_api_token.",
94
+ )
95
+ default_headers["cf-aig-authorization"] = f"Bearer {cloudflare_api_token}"
96
+
97
+ if credential_mode == self.CREDENTIAL_MODE_PROVIDER_KEY:
98
+ if not provider_api_key:
99
+ raise IAToolkitException(
100
+ IAToolkitException.ErrorType.API_KEY,
101
+ (
102
+ f"Cloudflare gateway for provider '{normalized_provider}' requires the provider API key "
103
+ "when credential_mode is 'provider_key_in_request'."
104
+ ),
105
+ )
106
+ resolved_api_key = provider_api_key
107
+ elif credential_mode == self.CREDENTIAL_MODE_CLOUDFLARE_MANAGED:
108
+ if not authenticated_gateway:
109
+ raise IAToolkitException(
110
+ IAToolkitException.ErrorType.CONFIG_ERROR,
111
+ (
112
+ "credential_mode 'cloudflare_managed' requires "
113
+ "'authenticated_gateway: true' so requests can be authorized with Cloudflare."
114
+ ),
115
+ )
116
+ # Some SDKs insist on a non-null api_key even when upstream credentials are injected by Cloudflare.
117
+ resolved_api_key = "" if normalized_provider in {"openai", "deepseek", "gemini"} else None
118
+ else:
119
+ raise IAToolkitException(
120
+ IAToolkitException.ErrorType.CONFIG_ERROR,
121
+ f"Unsupported llm.gateway credential_mode '{credential_mode}'.",
122
+ )
123
+
124
+ byok_alias = str(gateway_cfg.get("byok_alias") or "").strip()
125
+ if byok_alias:
126
+ default_headers["cf-aig-byok-alias"] = byok_alias
127
+
128
+ return {
129
+ "enabled": True,
130
+ "api_key": resolved_api_key,
131
+ "base_url": f"https://gateway.ai.cloudflare.com/v1/{account_id}/{gateway_id}/{provider_slug}",
132
+ "default_headers": default_headers,
133
+ "vendor": vendor,
134
+ "mode": mode,
135
+ "credential_mode": credential_mode,
136
+ "authenticated_gateway": authenticated_gateway,
137
+ }
138
+
139
+ def _resolve_gateway_value(
140
+ self,
141
+ company_short_name: str,
142
+ gateway_cfg: Dict[str, Any],
143
+ *,
144
+ direct_key: str,
145
+ secret_ref_key: str,
146
+ env_key: str,
147
+ ) -> str:
148
+ direct_value = str(gateway_cfg.get(direct_key) or "").strip()
149
+ if direct_value:
150
+ return direct_value
151
+
152
+ secret_ref = str(gateway_cfg.get(secret_ref_key) or "").strip()
153
+ if secret_ref:
154
+ return str(
155
+ resolve_secret(self.secret_provider, company_short_name, secret_ref, default="") or ""
156
+ ).strip()
157
+
158
+ env_ref = str(gateway_cfg.get(env_key) or "").strip()
159
+ if env_ref:
160
+ return str(
161
+ resolve_secret(self.secret_provider, company_short_name, env_ref, default="") or ""
162
+ ).strip()
163
+
164
+ return ""
@@ -17,6 +17,7 @@ from iatoolkit.infra.llm_response import LLMResponse
17
17
  from iatoolkit.common.model_registry import ModelRegistry
18
18
  from iatoolkit.common.interfaces.secret_provider import SecretProvider
19
19
  from iatoolkit.common.secret_resolver import resolve_secret
20
+ from iatoolkit.infra.llm_gateway_resolver import LLMGatewayResolver
20
21
  from iatoolkit.services.telemetry_service import NoopTelemetryService
21
22
 
22
23
  from openai import OpenAI, Timeout # For OpenAI and xAI (OpenAI-compatible)
@@ -54,6 +55,7 @@ class LLMProxy:
54
55
  configuration_service: ConfigurationService,
55
56
  model_registry: ModelRegistry,
56
57
  secret_provider: SecretProvider,
58
+ gateway_resolver: LLMGatewayResolver | None = None,
57
59
  telemetry_service=None,
58
60
  ):
59
61
  """
@@ -64,6 +66,10 @@ class LLMProxy:
64
66
  self.configuration_service = configuration_service
65
67
  self.model_registry = model_registry
66
68
  self.secret_provider = secret_provider
69
+ self.gateway_resolver = gateway_resolver or LLMGatewayResolver(
70
+ configuration_service=configuration_service,
71
+ secret_provider=secret_provider,
72
+ )
67
73
  self._telemetry_service = telemetry_service
68
74
 
69
75
  # adapter cache by (provider, api_key, base_url)
@@ -356,7 +362,7 @@ class LLMProxy:
356
362
  def _get_or_create_client(
357
363
  self,
358
364
  provider: str,
359
- api_key: str,
365
+ api_key: str | None,
360
366
  base_url: str = "",
361
367
  default_headers: Dict[str, str] | None = None,
362
368
  *,
@@ -409,7 +415,7 @@ class LLMProxy:
409
415
  def _create_client_for_provider(
410
416
  self,
411
417
  provider: str,
412
- api_key: str,
418
+ api_key: str | None,
413
419
  base_url: str = "",
414
420
  default_headers: Dict[str, str] | None = None,
415
421
  *,
@@ -432,15 +438,22 @@ class LLMProxy:
432
438
 
433
439
  if provider == self.PROVIDER_OPENAI:
434
440
  # Standard OpenAI client for GPT models
435
- return OpenAI(api_key=api_key, timeout=timeout, max_retries=max_retries)
441
+ return OpenAI(
442
+ api_key=api_key or "",
443
+ base_url=base_url or None,
444
+ timeout=timeout,
445
+ max_retries=max_retries,
446
+ default_headers=default_headers or None,
447
+ )
436
448
 
437
449
  if provider == self.PROVIDER_XAI:
438
450
  # xAI Grok is OpenAI-compatible; we can use the OpenAI client with a different base_url.
439
451
  return OpenAI(
440
- api_key=api_key,
452
+ api_key=api_key or "",
441
453
  base_url="https://api.x.ai/v1",
442
454
  timeout=timeout,
443
455
  max_retries=max_retries,
456
+ default_headers=default_headers or None,
444
457
  )
445
458
 
446
459
  if provider == self.PROVIDER_DEEPSEEK:
@@ -449,10 +462,11 @@ class LLMProxy:
449
462
 
450
463
  # We use OpenAI client with a DeepSeek base_url:
451
464
  return OpenAI(
452
- api_key=api_key,
453
- base_url="https://api.deepseek.com",
465
+ api_key=api_key or "",
466
+ base_url=base_url or "https://api.deepseek.com",
454
467
  timeout=timeout,
455
468
  max_retries=max_retries,
469
+ default_headers=default_headers or None,
456
470
  )
457
471
 
458
472
  if provider == self.PROVIDER_OPENAI_COMPATIBLE:
@@ -462,10 +476,11 @@ class LLMProxy:
462
476
  "Provider 'openai_compatible' requires a configured base_url."
463
477
  )
464
478
  return OpenAI(
465
- api_key=api_key,
479
+ api_key=api_key or "",
466
480
  base_url=base_url,
467
481
  timeout=timeout,
468
482
  max_retries=max_retries,
483
+ default_headers=default_headers or None,
469
484
  )
470
485
 
471
486
  if provider == self.PROVIDER_OPENROUTER:
@@ -488,7 +503,14 @@ class LLMProxy:
488
503
  #
489
504
  from google.genai import Client
490
505
 
491
- return Client(api_key=api_key, http_options={'api_version': 'v1alpha'})
506
+ gemini_http_options = {"api_version": "v1alpha"}
507
+ if base_url:
508
+ gemini_http_options["base_url"] = base_url
509
+ gemini_http_options["api_version"] = "v1"
510
+ if default_headers:
511
+ gemini_http_options["headers"] = dict(default_headers)
512
+
513
+ return Client(api_key=api_key, http_options=gemini_http_options)
492
514
  if provider == self.PROVIDER_ANTHROPIC:
493
515
  try:
494
516
  from anthropic import Anthropic
@@ -498,7 +520,13 @@ class LLMProxy:
498
520
  "Anthropic SDK is not installed. Add 'anthropic' to requirements."
499
521
  ) from ex
500
522
 
501
- return Anthropic(api_key=api_key)
523
+ return Anthropic(
524
+ api_key=api_key,
525
+ base_url=base_url or None,
526
+ timeout=timeout,
527
+ max_retries=max_retries,
528
+ default_headers=default_headers or None,
529
+ )
502
530
 
503
531
  raise IAToolkitException(
504
532
  IAToolkitException.ErrorType.MODEL,
@@ -507,10 +535,31 @@ class LLMProxy:
507
535
 
508
536
  def _get_client_config(self, company_short_name: str, provider: str) -> dict:
509
537
  provider_config = self.configuration_service.get_llm_provider_config(company_short_name, provider) or {}
538
+ provider_api_key = self._get_api_key_from_config(
539
+ company_short_name,
540
+ provider,
541
+ required=False,
542
+ )
543
+ gateway_transport = self.gateway_resolver.resolve(
544
+ company_short_name=company_short_name,
545
+ provider=provider,
546
+ provider_api_key=provider_api_key,
547
+ )
548
+ if not gateway_transport.get("enabled"):
549
+ provider_api_key = provider_api_key or self._get_api_key_from_config(
550
+ company_short_name,
551
+ provider,
552
+ required=True,
553
+ )
554
+ configured_base_url = self._get_base_url_from_config(company_short_name, provider)
555
+ configured_headers = self._get_default_headers_from_config(company_short_name, provider)
556
+ effective_base_url = gateway_transport.get("base_url") or configured_base_url
557
+ effective_headers = dict(configured_headers)
558
+ effective_headers.update(gateway_transport.get("default_headers") or {})
510
559
  return {
511
- "api_key": self._get_api_key_from_config(company_short_name, provider),
512
- "base_url": self._get_base_url_from_config(company_short_name, provider),
513
- "default_headers": self._get_default_headers_from_config(company_short_name, provider),
560
+ "api_key": gateway_transport.get("api_key", provider_api_key) if gateway_transport.get("enabled") else provider_api_key,
561
+ "base_url": effective_base_url,
562
+ "default_headers": effective_headers,
514
563
  "connect_timeout_seconds": self._resolve_provider_float(
515
564
  provider_config,
516
565
  ("connect_timeout_seconds",),
@@ -604,7 +653,7 @@ class LLMProxy:
604
653
  # -------------------------------------------------------------------------
605
654
  # Configuration helpers
606
655
  # -------------------------------------------------------------------------
607
- def _get_api_key_from_config(self, company_short_name: str, provider: str) -> str:
656
+ def _get_api_key_from_config(self, company_short_name: str, provider: str, *, required: bool = True) -> str:
608
657
  """
609
658
  Read the LLM API key from company configuration and environment variables.
610
659
 
@@ -634,6 +683,8 @@ class LLMProxy:
634
683
  env_var_name = llm_config["api-key"]
635
684
 
636
685
  if not env_var_name:
686
+ if not required:
687
+ return ""
637
688
  raise IAToolkitException(
638
689
  IAToolkitException.ErrorType.API_KEY,
639
690
  f"Company '{company_short_name}' doesn't have an API key configured "
@@ -648,6 +699,8 @@ class LLMProxy:
648
699
  )
649
700
 
650
701
  if not api_key_value:
702
+ if not required:
703
+ return ""
651
704
  raise IAToolkitException(
652
705
  IAToolkitException.ErrorType.API_KEY,
653
706
  f"Environment variable '{env_var_name}' for company '{company_short_name}' "
@@ -98,6 +98,133 @@ class ConfigurationService:
98
98
  "Must be one of: ['latency', 'price', 'throughput'], or a dictionary."
99
99
  )
100
100
 
101
+ @staticmethod
102
+ def _validate_llm_gateway_entry(
103
+ add_error,
104
+ section: str,
105
+ gateway_cfg,
106
+ *,
107
+ allow_providers: bool,
108
+ require_complete_config: bool,
109
+ ) -> None:
110
+ if not isinstance(gateway_cfg, dict):
111
+ add_error(section, "Must be a dictionary.")
112
+ return
113
+
114
+ allowed_gateway_providers = {"openai", "deepseek", "anthropic", "gemini"}
115
+ allowed_gateway_modes = {"provider_native"}
116
+ allowed_gateway_vendors = {"cloudflare"}
117
+ allowed_credential_modes = {"provider_key_in_request", "cloudflare_managed"}
118
+ secret_ref_keys = (
119
+ "account_id",
120
+ "account_id_secret_ref",
121
+ "account_id_env",
122
+ "cloudflare_api_token_secret_ref",
123
+ "cloudflare_api_token_env",
124
+ )
125
+
126
+ enabled = gateway_cfg.get("enabled")
127
+ if enabled is not None and not isinstance(enabled, bool):
128
+ add_error(f"{section}.enabled", "Must be a boolean.")
129
+
130
+ vendor = gateway_cfg.get("vendor")
131
+ normalized_vendor = ""
132
+ if vendor is not None:
133
+ if not isinstance(vendor, str) or not vendor.strip():
134
+ add_error(f"{section}.vendor", "Must be a non-empty string.")
135
+ else:
136
+ normalized_vendor = vendor.strip().lower()
137
+ if normalized_vendor not in allowed_gateway_vendors:
138
+ add_error(
139
+ f"{section}.vendor",
140
+ f"Unsupported vendor '{normalized_vendor}'. Must be one of: {sorted(allowed_gateway_vendors)}.",
141
+ )
142
+
143
+ mode = gateway_cfg.get("mode")
144
+ normalized_mode = ""
145
+ if mode is not None:
146
+ if not isinstance(mode, str) or not mode.strip():
147
+ add_error(f"{section}.mode", "Must be a non-empty string.")
148
+ else:
149
+ normalized_mode = mode.strip().lower()
150
+ if normalized_mode not in allowed_gateway_modes:
151
+ add_error(
152
+ f"{section}.mode",
153
+ f"Unsupported value '{normalized_mode}'. Must be one of: {sorted(allowed_gateway_modes)}.",
154
+ )
155
+
156
+ gateway_id = gateway_cfg.get("gateway_id")
157
+ if gateway_id is not None and (not isinstance(gateway_id, str) or not gateway_id.strip()):
158
+ add_error(f"{section}.gateway_id", "Must be a non-empty string.")
159
+
160
+ byok_alias = gateway_cfg.get("byok_alias")
161
+ if byok_alias is not None and (not isinstance(byok_alias, str) or not byok_alias.strip()):
162
+ add_error(f"{section}.byok_alias", "Must be a non-empty string.")
163
+
164
+ authenticated_gateway = gateway_cfg.get("authenticated_gateway")
165
+ if authenticated_gateway is not None and not isinstance(authenticated_gateway, bool):
166
+ add_error(f"{section}.authenticated_gateway", "Must be a boolean.")
167
+
168
+ credential_mode = gateway_cfg.get("credential_mode")
169
+ if credential_mode is not None:
170
+ if not isinstance(credential_mode, str) or not credential_mode.strip():
171
+ add_error(f"{section}.credential_mode", "Must be a non-empty string.")
172
+ elif credential_mode.strip().lower() not in allowed_credential_modes:
173
+ add_error(
174
+ f"{section}.credential_mode",
175
+ "Unsupported value. Must be 'provider_key_in_request' or 'cloudflare_managed'.",
176
+ )
177
+
178
+ if allow_providers:
179
+ providers_cfg = gateway_cfg.get("providers")
180
+ if providers_cfg is not None and not isinstance(providers_cfg, dict):
181
+ add_error(f"{section}.providers", "Must be a dictionary.")
182
+ elif isinstance(providers_cfg, dict):
183
+ for provider_name, provider_gateway_cfg in providers_cfg.items():
184
+ normalized_provider_name = str(provider_name or "").strip().lower()
185
+ if normalized_provider_name not in allowed_gateway_providers:
186
+ add_error(
187
+ f"{section}.providers.{provider_name}",
188
+ (
189
+ f"Unsupported provider '{normalized_provider_name}'. "
190
+ f"Must be one of: {sorted(allowed_gateway_providers)}."
191
+ ),
192
+ )
193
+ continue
194
+ ConfigurationService._validate_llm_gateway_entry(
195
+ add_error,
196
+ f"{section}.providers.{normalized_provider_name}",
197
+ provider_gateway_cfg,
198
+ allow_providers=False,
199
+ require_complete_config=False,
200
+ )
201
+ elif "providers" in gateway_cfg:
202
+ add_error(f"{section}.providers", "Nested provider overrides are not supported here.")
203
+
204
+ is_enabled = gateway_cfg.get("enabled") is True
205
+ if require_complete_config and is_enabled and not normalized_vendor:
206
+ add_error(f"{section}.vendor", "Missing required key: 'vendor'.")
207
+ if require_complete_config and is_enabled and not normalized_mode:
208
+ add_error(f"{section}.mode", "Missing required key: 'mode'.")
209
+ if require_complete_config and is_enabled and not str(gateway_cfg.get("gateway_id") or "").strip():
210
+ add_error(f"{section}.gateway_id", "Missing required key: 'gateway_id'.")
211
+ if require_complete_config and is_enabled and not any(
212
+ str(gateway_cfg.get(key) or "").strip() for key in secret_ref_keys[:3]
213
+ ):
214
+ add_error(
215
+ f"{section}.account_id",
216
+ "One of 'account_id', 'account_id_secret_ref', or 'account_id_env' is required when enabled.",
217
+ )
218
+ if is_enabled and gateway_cfg.get("authenticated_gateway") is True:
219
+ if not any(str(gateway_cfg.get(key) or "").strip() for key in secret_ref_keys[3:]):
220
+ add_error(
221
+ f"{section}.cloudflare_api_token_secret_ref",
222
+ (
223
+ "One of 'cloudflare_api_token_secret_ref' or 'cloudflare_api_token_env' "
224
+ "is required when 'authenticated_gateway' is true."
225
+ ),
226
+ )
227
+
101
228
  def load_configuration(self, company_short_name: str):
102
229
  """
103
230
  Main entry point for configuring a company instance.
@@ -582,6 +709,16 @@ class ConfigurationService:
582
709
  "Must be an absolute HTTP or HTTPS URL.",
583
710
  )
584
711
 
712
+ gateway_cfg = config.get("llm", {}).get("gateway")
713
+ if gateway_cfg is not None:
714
+ self._validate_llm_gateway_entry(
715
+ add_error,
716
+ "llm.gateway",
717
+ gateway_cfg,
718
+ allow_providers=True,
719
+ require_complete_config=True,
720
+ )
721
+
585
722
  # 3. Embedding Provider
586
723
  if isinstance(config.get("embedding_provider"), dict):
587
724
  if not config.get("embedding_provider", {}).get("provider"):
@@ -1219,6 +1356,35 @@ class ConfigurationService:
1219
1356
  provider_cfg = providers_cfg.get(candidate)
1220
1357
  return dict(provider_cfg) if isinstance(provider_cfg, dict) else {}
1221
1358
 
1359
+ def get_llm_gateway_config(self, company_short_name: str, provider: str | None = None) -> dict:
1360
+ self._ensure_config_loaded(company_short_name)
1361
+ llm_config = self._loaded_configs[company_short_name].get("llm") or {}
1362
+ gateway_cfg = llm_config.get("gateway")
1363
+ if not isinstance(gateway_cfg, dict):
1364
+ return {}
1365
+
1366
+ resolved_gateway_cfg = {
1367
+ key: value
1368
+ for key, value in gateway_cfg.items()
1369
+ if key != "providers"
1370
+ }
1371
+
1372
+ candidate = str(provider or "").strip().lower()
1373
+ if not candidate:
1374
+ return dict(resolved_gateway_cfg)
1375
+
1376
+ provider_overrides = gateway_cfg.get("providers")
1377
+ if not isinstance(provider_overrides, dict):
1378
+ return dict(resolved_gateway_cfg)
1379
+
1380
+ provider_gateway_cfg = provider_overrides.get(candidate)
1381
+ if not isinstance(provider_gateway_cfg, dict):
1382
+ return dict(resolved_gateway_cfg)
1383
+
1384
+ merged_gateway_cfg = dict(resolved_gateway_cfg)
1385
+ merged_gateway_cfg.update(provider_gateway_cfg)
1386
+ return merged_gateway_cfg
1387
+
1222
1388
  def get_llm_telemetry_config(self, company_short_name: str) -> dict:
1223
1389
  self._ensure_config_loaded(company_short_name)
1224
1390
  llm_config = self._loaded_configs[company_short_name].get("llm") or {}
@@ -183,11 +183,7 @@ class GoogleLoginCallbackView(BaseLoginView):
183
183
  if not isinstance(pending_states, dict):
184
184
  pending_states = {}
185
185
 
186
- pending_state = pending_states.pop(state, None)
187
- if pending_states:
188
- SessionManager.set('google_oauth_states', pending_states)
189
- else:
190
- SessionManager.remove('google_oauth_states')
186
+ pending_state = pending_states.get(state)
191
187
 
192
188
  company_short_name = (pending_state or {}).get('company_short_name')
193
189
  current_lang = (pending_state or {}).get('lang') or request.args.get('lang') or 'en'
@@ -215,6 +211,12 @@ class GoogleLoginCallbackView(BaseLoginView):
215
211
  flash(self.i18n_service.t('errors.auth.google_login_failed'), 'error')
216
212
  return redirect(url_for('home', company_short_name=company_short_name, lang=current_lang))
217
213
 
214
+ pending_states.pop(state, None)
215
+ if pending_states:
216
+ SessionManager.set('google_oauth_states', pending_states)
217
+ else:
218
+ SessionManager.remove('google_oauth_states')
219
+
218
220
  redirect_uri = url_for(
219
221
  'login_google_callback',
220
222
  _external=True,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.16.2
3
+ Version: 2.17.0
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
@@ -66,6 +66,7 @@ src/iatoolkit/infra/google_chat_app.py
66
66
  src/iatoolkit/infra/inference_embeddings_client.py
67
67
  src/iatoolkit/infra/inference_handler.py
68
68
  src/iatoolkit/infra/jina_embeddings_client.py
69
+ src/iatoolkit/infra/llm_gateway_resolver.py
69
70
  src/iatoolkit/infra/llm_proxy.py
70
71
  src/iatoolkit/infra/llm_response.py
71
72
  src/iatoolkit/infra/redis_session_manager.py
File without changes
File without changes
File without changes
File without changes
File without changes