iatoolkit 2.3.2__tar.gz → 2.4.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.
- {iatoolkit-2.3.2/src/iatoolkit.egg-info → iatoolkit-2.4.0}/PKG-INFO +1 -1
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/__init__.py +1 -1
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/config/llm_capabilities.yaml +18 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/config/system_prompts_pack.yaml +16 -2
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +212 -27
- iatoolkit-2.4.0/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +62 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_proxy.py +51 -3
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/locales/en.yaml +1 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/locales/es.yaml +1 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/company_context_service.py +24 -14
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/configuration_service.py +51 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/context_builder_service.py +80 -20
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/prompt_service.py +4 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/query_service.py +16 -2
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/system_prompt_catalog.py +51 -1
- {iatoolkit-2.3.2 → iatoolkit-2.4.0/src/iatoolkit.egg-info}/PKG-INFO +1 -1
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit.egg-info/SOURCES.txt +1 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/LICENSE +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/LICENSE_COMMUNITY.md +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/pyproject.toml +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/readme.md +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/requirements.txt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/setup.cfg +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/base_company.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/cli_commands.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/exceptions.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/memory_lint_trigger.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/model_registry.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/routes.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/secret_resolver.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/session_manager.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/common/util.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/company_registry.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/config/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/core.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/call_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/google_auth_client.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/google_chat_app.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/inference_handler.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/llm_response.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/infra/redis_session_manager.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/api_key_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/database_manager.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/document_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/memory_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/models.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/profile_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/repositories/vs_repo.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/api_key_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/attachment_policy_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/auth_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/benchmark_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/branding_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/dispatcher_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/embedding_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/excel_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/file_processor_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/history_manager_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/http_tool_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/i18n_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/inference_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/jwt_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/knowledge_base_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/language_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/license_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/llm_client_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/mail_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/memory_compiler_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/memory_lint_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/memory_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/memory_wiki_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/noop_memory_lint_trigger.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/contracts.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/parsers/validator.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/pdf_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/profile_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/prompt_resource_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/sql_dataset_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/sql_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/sql_source_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/storage_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/structured_output_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/system_tools.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/tool_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/user_feedback_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/user_session_context_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/visual_kb_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/visual_tool_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/warmup_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/web_search/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/services/web_search_service.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/images/fernando.jpeg +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_filepond.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_help_content.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_history_button.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_main.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/js/chat_reload_button.js +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/chat_modal.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/chat_public.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/documents.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/landing_page.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/llm_output.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/static/styles/onboarding.css +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/chat_state_rules.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/chat_user_profile.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/core_identity.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/email_output.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/file_download_output.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/format_styles.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/html_structures.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/links_documents.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/memory_usage.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/multimodal_basics.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/output_basics.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/presentation_formatting.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/query_main.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/sql_aggregation_scope.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/sql_casting.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/sql_core.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/sql_jsonb.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/sql_rules.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/system_prompts/tool_html_passthrough.prompt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/_company_header.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/_login_widget.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/base.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/change_password.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/chat.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/chat_modals.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/error.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/forgot_password.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/home_hosted_default.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/onboarding_shell.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/pdf/base.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/pdf/letter.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/pdf/report.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/pdf/simple.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/templates/signup.html +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/__init__.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/api_key_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/base_login_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/categories_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/change_password_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/chat_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/configuration_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/connectors_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/embedding_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/forgot_password_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/help_content_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/history_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/home_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/init_context_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/llmquery_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/load_document_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/login_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/logout_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/memory_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/profile_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/prompt_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/rag_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/root_redirect_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/signup_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/static_page_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/tool_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/users_api_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit/views/verify_user_view.py +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit.egg-info/requires.txt +0 -0
- {iatoolkit-2.3.2 → iatoolkit-2.4.0}/src/iatoolkit.egg-info/top_level.txt +0 -0
|
@@ -58,6 +58,24 @@ openai_compatible:
|
|
|
58
58
|
max_file_size_mb: 0
|
|
59
59
|
max_files_per_request: 0
|
|
60
60
|
|
|
61
|
+
openrouter:
|
|
62
|
+
supports_native_files: true
|
|
63
|
+
supports_native_images: true
|
|
64
|
+
supported_mime_types:
|
|
65
|
+
- application/pdf
|
|
66
|
+
- text/plain
|
|
67
|
+
- text/csv
|
|
68
|
+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
|
|
69
|
+
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
|
|
70
|
+
- application/vnd.openxmlformats-officedocument.presentationml.presentation
|
|
71
|
+
- application/json
|
|
72
|
+
- application/xml
|
|
73
|
+
- text/xml
|
|
74
|
+
preferred_native_mime_types:
|
|
75
|
+
- application/pdf
|
|
76
|
+
max_file_size_mb: 20
|
|
77
|
+
max_files_per_request: 10
|
|
78
|
+
|
|
61
79
|
unknown:
|
|
62
80
|
supports_native_files: false
|
|
63
81
|
supports_native_images: false
|
|
@@ -2,42 +2,47 @@ version: 2
|
|
|
2
2
|
prompts:
|
|
3
3
|
- key: core_identity
|
|
4
4
|
filename: core_identity.prompt
|
|
5
|
+
section: identity
|
|
5
6
|
include:
|
|
6
7
|
execution_modes:
|
|
7
8
|
- chat
|
|
8
9
|
- agent
|
|
9
10
|
- key: chat_user_profile
|
|
10
11
|
filename: chat_user_profile.prompt
|
|
12
|
+
section: identity
|
|
11
13
|
include:
|
|
12
14
|
execution_modes:
|
|
13
15
|
- chat
|
|
14
16
|
- key: chat_state_rules
|
|
15
17
|
filename: chat_state_rules.prompt
|
|
18
|
+
section: conversation_rules
|
|
16
19
|
include:
|
|
17
20
|
execution_modes:
|
|
18
21
|
- chat
|
|
19
22
|
- key: links_documents
|
|
20
23
|
filename: links_documents.prompt
|
|
24
|
+
section: conversation_rules
|
|
21
25
|
include:
|
|
22
26
|
execution_modes:
|
|
23
27
|
- chat
|
|
24
28
|
- agent
|
|
25
29
|
- key: memory_usage
|
|
26
30
|
filename: memory_usage.prompt
|
|
31
|
+
section: conversation_rules
|
|
27
32
|
include:
|
|
28
33
|
execution_modes:
|
|
29
34
|
- chat
|
|
30
|
-
- agent
|
|
31
35
|
all_capabilities:
|
|
32
36
|
- can_use_memory
|
|
33
37
|
- key: multimodal_basics
|
|
34
38
|
filename: multimodal_basics.prompt
|
|
39
|
+
section: conversation_rules
|
|
35
40
|
include:
|
|
36
41
|
execution_modes:
|
|
37
42
|
- chat
|
|
38
|
-
- agent
|
|
39
43
|
- key: output_basics
|
|
40
44
|
filename: output_basics.prompt
|
|
45
|
+
section: output_contract
|
|
41
46
|
include:
|
|
42
47
|
execution_modes:
|
|
43
48
|
- chat
|
|
@@ -46,6 +51,7 @@ prompts:
|
|
|
46
51
|
- chat_compatible
|
|
47
52
|
- key: presentation_formatting
|
|
48
53
|
filename: presentation_formatting.prompt
|
|
54
|
+
section: output_contract
|
|
49
55
|
include:
|
|
50
56
|
execution_modes:
|
|
51
57
|
- chat
|
|
@@ -53,6 +59,7 @@ prompts:
|
|
|
53
59
|
- chat_compatible
|
|
54
60
|
- key: html_structures
|
|
55
61
|
filename: html_structures.prompt
|
|
62
|
+
section: output_contract
|
|
56
63
|
include:
|
|
57
64
|
execution_modes:
|
|
58
65
|
- chat
|
|
@@ -60,12 +67,14 @@ prompts:
|
|
|
60
67
|
- chat_compatible
|
|
61
68
|
- key: tool_html_passthrough
|
|
62
69
|
filename: tool_html_passthrough.prompt
|
|
70
|
+
section: output_contract
|
|
63
71
|
include:
|
|
64
72
|
execution_modes:
|
|
65
73
|
- chat
|
|
66
74
|
- agent
|
|
67
75
|
- key: file_download_output
|
|
68
76
|
filename: file_download_output.prompt
|
|
77
|
+
section: output_contract
|
|
69
78
|
include:
|
|
70
79
|
execution_modes:
|
|
71
80
|
- chat
|
|
@@ -74,6 +83,7 @@ prompts:
|
|
|
74
83
|
- can_generate_files
|
|
75
84
|
- key: email_output
|
|
76
85
|
filename: email_output.prompt
|
|
86
|
+
section: output_contract
|
|
77
87
|
include:
|
|
78
88
|
execution_modes:
|
|
79
89
|
- chat
|
|
@@ -82,6 +92,7 @@ prompts:
|
|
|
82
92
|
- can_send_email
|
|
83
93
|
- key: sql_core
|
|
84
94
|
filename: sql_core.prompt
|
|
95
|
+
section: data_access_rules
|
|
85
96
|
include:
|
|
86
97
|
execution_modes:
|
|
87
98
|
- chat
|
|
@@ -90,6 +101,7 @@ prompts:
|
|
|
90
101
|
- can_query_sql
|
|
91
102
|
- key: sql_jsonb
|
|
92
103
|
filename: sql_jsonb.prompt
|
|
104
|
+
section: data_access_rules
|
|
93
105
|
include:
|
|
94
106
|
execution_modes:
|
|
95
107
|
- chat
|
|
@@ -98,6 +110,7 @@ prompts:
|
|
|
98
110
|
- can_query_sql
|
|
99
111
|
- key: sql_casting
|
|
100
112
|
filename: sql_casting.prompt
|
|
113
|
+
section: data_access_rules
|
|
101
114
|
include:
|
|
102
115
|
execution_modes:
|
|
103
116
|
- chat
|
|
@@ -106,6 +119,7 @@ prompts:
|
|
|
106
119
|
- can_query_sql
|
|
107
120
|
- key: sql_aggregation_scope
|
|
108
121
|
filename: sql_aggregation_scope.prompt
|
|
122
|
+
section: data_access_rules
|
|
109
123
|
include:
|
|
110
124
|
execution_modes:
|
|
111
125
|
- chat
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
#
|
|
4
4
|
# IAToolkit is open source software.
|
|
5
5
|
|
|
6
|
+
import base64
|
|
6
7
|
import logging
|
|
8
|
+
import mimetypes
|
|
7
9
|
from typing import Any, Dict, List, Optional
|
|
8
10
|
|
|
9
11
|
from iatoolkit.common.exceptions import IAToolkitException
|
|
@@ -12,12 +14,17 @@ from iatoolkit.infra.llm_response import LLMResponse, ToolCall, Usage
|
|
|
12
14
|
|
|
13
15
|
class OpenAICompatibleChatAdapter:
|
|
14
16
|
"""
|
|
15
|
-
Adapter for
|
|
17
|
+
Adapter for Chat Completions-style providers.
|
|
16
18
|
|
|
17
|
-
This adapter
|
|
18
|
-
|
|
19
|
+
This adapter targets providers that expose a `chat.completions` compatible
|
|
20
|
+
endpoint with `messages`, `tools`, `tool_calls`, and `response_format`.
|
|
19
21
|
"""
|
|
20
22
|
|
|
23
|
+
supports_multimodal = False
|
|
24
|
+
supports_reasoning = False
|
|
25
|
+
supports_metadata = False
|
|
26
|
+
supports_parallel_tool_calls = False
|
|
27
|
+
|
|
21
28
|
def __init__(self, openai_compatible_client, provider_label: str = "OpenAI-compatible"):
|
|
22
29
|
self.client = openai_compatible_client
|
|
23
30
|
self.provider_label = provider_label
|
|
@@ -37,14 +44,10 @@ class OpenAICompatibleChatAdapter:
|
|
|
37
44
|
tool_choice = kwargs.get("tool_choice", "auto")
|
|
38
45
|
context_history = kwargs.get("context_history") or []
|
|
39
46
|
images = kwargs.get("images") or []
|
|
47
|
+
attachments = kwargs.get("attachments") or []
|
|
40
48
|
text = kwargs.get("text") or {}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
logging.warning(
|
|
44
|
-
"[%sAdapter] Images provided but these models are not multimodal. Ignoring %s images.",
|
|
45
|
-
self.provider_label,
|
|
46
|
-
len(images),
|
|
47
|
-
)
|
|
49
|
+
reasoning = kwargs.get("reasoning")
|
|
50
|
+
metadata = kwargs.get("metadata")
|
|
48
51
|
|
|
49
52
|
try:
|
|
50
53
|
messages: List[Dict[str, Any]] = []
|
|
@@ -55,6 +58,18 @@ class OpenAICompatibleChatAdapter:
|
|
|
55
58
|
current_messages = self._build_messages_from_input(input)
|
|
56
59
|
messages.extend(current_messages)
|
|
57
60
|
|
|
61
|
+
if images or attachments:
|
|
62
|
+
if self.supports_multimodal:
|
|
63
|
+
messages = self._prepare_multimodal_messages(messages, images, attachments)
|
|
64
|
+
else:
|
|
65
|
+
logging.warning(
|
|
66
|
+
"[%sAdapter] Multimodal content provided but this provider is configured as text-only. "
|
|
67
|
+
"Ignoring %s images and %s attachments.",
|
|
68
|
+
self.provider_label,
|
|
69
|
+
len(images),
|
|
70
|
+
len(attachments),
|
|
71
|
+
)
|
|
72
|
+
|
|
58
73
|
has_function_outputs = any(
|
|
59
74
|
item.get("type") == "function_call_output" for item in input
|
|
60
75
|
)
|
|
@@ -77,10 +92,25 @@ class OpenAICompatibleChatAdapter:
|
|
|
77
92
|
}
|
|
78
93
|
if tools_payload:
|
|
79
94
|
call_kwargs["tools"] = tools_payload
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if
|
|
83
|
-
call_kwargs["
|
|
95
|
+
|
|
96
|
+
tool_choice_payload = self._map_tool_choice(tool_choice, tools_payload or [])
|
|
97
|
+
if tool_choice_payload is not None:
|
|
98
|
+
call_kwargs["tool_choice"] = tool_choice_payload
|
|
99
|
+
|
|
100
|
+
response_format = self._extract_response_format(text)
|
|
101
|
+
if response_format:
|
|
102
|
+
call_kwargs["response_format"] = response_format
|
|
103
|
+
|
|
104
|
+
if self.supports_reasoning and reasoning:
|
|
105
|
+
call_kwargs["reasoning"] = reasoning
|
|
106
|
+
|
|
107
|
+
if self.supports_metadata and metadata:
|
|
108
|
+
call_kwargs["metadata"] = metadata
|
|
109
|
+
|
|
110
|
+
if self.supports_parallel_tool_calls and kwargs.get("parallel_tool_calls") is not None:
|
|
111
|
+
call_kwargs["parallel_tool_calls"] = bool(kwargs.get("parallel_tool_calls"))
|
|
112
|
+
|
|
113
|
+
self._extend_call_kwargs(call_kwargs, kwargs)
|
|
84
114
|
|
|
85
115
|
logging.debug(
|
|
86
116
|
"[%sAdapter] Calling chat.completions API with %s messages.",
|
|
@@ -100,6 +130,10 @@ class OpenAICompatibleChatAdapter:
|
|
|
100
130
|
f"{self.provider_label} error: {ex}"
|
|
101
131
|
) from ex
|
|
102
132
|
|
|
133
|
+
def _extend_call_kwargs(self, call_kwargs: Dict[str, Any], kwargs: Dict[str, Any]) -> None:
|
|
134
|
+
_ = call_kwargs
|
|
135
|
+
_ = kwargs
|
|
136
|
+
|
|
103
137
|
def _build_messages_from_input(self, input_items: List[Dict]) -> List[Dict]:
|
|
104
138
|
messages: List[Dict[str, Any]] = []
|
|
105
139
|
|
|
@@ -114,29 +148,145 @@ class OpenAICompatibleChatAdapter:
|
|
|
114
148
|
)
|
|
115
149
|
continue
|
|
116
150
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
151
|
+
tool_message: Dict[str, Any] = {
|
|
152
|
+
"role": "tool",
|
|
153
|
+
"content": output,
|
|
154
|
+
}
|
|
155
|
+
call_id = str(item.get("call_id") or "").strip()
|
|
156
|
+
if call_id:
|
|
157
|
+
tool_message["tool_call_id"] = call_id
|
|
158
|
+
messages.append(tool_message)
|
|
123
159
|
continue
|
|
124
160
|
|
|
125
|
-
role = item.get("role")
|
|
161
|
+
role = str(item.get("role") or "").strip().lower()
|
|
126
162
|
content = item.get("content")
|
|
127
163
|
|
|
128
|
-
if role == "tool":
|
|
129
|
-
logging.warning("[%sAdapter] Skipping tool-role message: %s", self.provider_label, item)
|
|
130
|
-
continue
|
|
131
|
-
|
|
132
164
|
if not role:
|
|
133
165
|
logging.warning("[%sAdapter] Skipping message without role: %s", self.provider_label, item)
|
|
134
166
|
continue
|
|
135
167
|
|
|
136
|
-
|
|
168
|
+
if role == "model":
|
|
169
|
+
role = "assistant"
|
|
170
|
+
|
|
171
|
+
message: Dict[str, Any] = {"role": role, "content": content}
|
|
172
|
+
tool_call_id = str(item.get("tool_call_id") or "").strip()
|
|
173
|
+
if role == "tool" and tool_call_id:
|
|
174
|
+
message["tool_call_id"] = tool_call_id
|
|
175
|
+
|
|
176
|
+
annotations = item.get("annotations")
|
|
177
|
+
if annotations is not None:
|
|
178
|
+
message["annotations"] = annotations
|
|
179
|
+
|
|
180
|
+
messages.append(message)
|
|
137
181
|
|
|
138
182
|
return messages
|
|
139
183
|
|
|
184
|
+
def _prepare_multimodal_messages(
|
|
185
|
+
self,
|
|
186
|
+
messages: List[Dict[str, Any]],
|
|
187
|
+
images: List[Dict],
|
|
188
|
+
attachments: List[Dict],
|
|
189
|
+
) -> List[Dict[str, Any]]:
|
|
190
|
+
target_index = None
|
|
191
|
+
for index in range(len(messages) - 1, -1, -1):
|
|
192
|
+
if messages[index].get("role") == "user":
|
|
193
|
+
target_index = index
|
|
194
|
+
break
|
|
195
|
+
|
|
196
|
+
if target_index is None:
|
|
197
|
+
return messages
|
|
198
|
+
|
|
199
|
+
target_message = dict(messages[target_index])
|
|
200
|
+
content_parts = self._coerce_content_to_parts(target_message.get("content"))
|
|
201
|
+
|
|
202
|
+
for img in images:
|
|
203
|
+
image_part = self._build_image_part(img)
|
|
204
|
+
if image_part is not None:
|
|
205
|
+
content_parts.append(image_part)
|
|
206
|
+
|
|
207
|
+
for attachment in attachments:
|
|
208
|
+
file_part = self._build_file_part(attachment)
|
|
209
|
+
if file_part is not None:
|
|
210
|
+
content_parts.append(file_part)
|
|
211
|
+
|
|
212
|
+
target_message["content"] = content_parts
|
|
213
|
+
updated_messages = list(messages)
|
|
214
|
+
updated_messages[target_index] = target_message
|
|
215
|
+
return updated_messages
|
|
216
|
+
|
|
217
|
+
@staticmethod
|
|
218
|
+
def _coerce_content_to_parts(content: Any) -> List[Dict[str, Any]]:
|
|
219
|
+
if isinstance(content, list):
|
|
220
|
+
return list(content)
|
|
221
|
+
if content in (None, ""):
|
|
222
|
+
return []
|
|
223
|
+
return [{"type": "text", "text": str(content)}]
|
|
224
|
+
|
|
225
|
+
def _build_image_part(self, image: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
226
|
+
if not isinstance(image, dict):
|
|
227
|
+
return None
|
|
228
|
+
|
|
229
|
+
filename = str(image.get("name") or image.get("filename") or "").strip()
|
|
230
|
+
mime_type = str(image.get("mime_type") or image.get("type") or "").strip().lower()
|
|
231
|
+
if not mime_type:
|
|
232
|
+
mime_type = mimetypes.guess_type(filename)[0] or "image/jpeg"
|
|
233
|
+
|
|
234
|
+
raw_url = str(image.get("url") or image.get("image_url") or "").strip()
|
|
235
|
+
if raw_url:
|
|
236
|
+
data_url = raw_url
|
|
237
|
+
else:
|
|
238
|
+
base64_data = str(image.get("base64") or image.get("content") or "").strip()
|
|
239
|
+
if not base64_data:
|
|
240
|
+
return None
|
|
241
|
+
data_url = self._to_data_url(base64_data, mime_type)
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
"type": "image_url",
|
|
245
|
+
"image_url": {
|
|
246
|
+
"url": data_url,
|
|
247
|
+
},
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
def _build_file_part(self, attachment: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
251
|
+
if not isinstance(attachment, dict):
|
|
252
|
+
return None
|
|
253
|
+
|
|
254
|
+
filename = str(attachment.get("name") or attachment.get("filename") or "attachment").strip()
|
|
255
|
+
mime_type = str(
|
|
256
|
+
attachment.get("mime_type")
|
|
257
|
+
or attachment.get("type")
|
|
258
|
+
or mimetypes.guess_type(filename)[0]
|
|
259
|
+
or "application/octet-stream"
|
|
260
|
+
).strip().lower()
|
|
261
|
+
|
|
262
|
+
raw_file_data = str(attachment.get("file_data") or attachment.get("url") or "").strip()
|
|
263
|
+
if raw_file_data:
|
|
264
|
+
file_data = raw_file_data
|
|
265
|
+
else:
|
|
266
|
+
base64_data = str(attachment.get("base64") or attachment.get("content") or "").strip()
|
|
267
|
+
if not base64_data:
|
|
268
|
+
return None
|
|
269
|
+
file_data = self._to_data_url(base64_data, mime_type)
|
|
270
|
+
|
|
271
|
+
return {
|
|
272
|
+
"type": "file",
|
|
273
|
+
"file": {
|
|
274
|
+
"filename": filename,
|
|
275
|
+
"file_data": file_data,
|
|
276
|
+
},
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@staticmethod
|
|
280
|
+
def _to_data_url(base64_data: str, mime_type: str) -> str:
|
|
281
|
+
payload = str(base64_data or "").strip()
|
|
282
|
+
if payload.lower().startswith("data:") and "," in payload:
|
|
283
|
+
return payload
|
|
284
|
+
try:
|
|
285
|
+
base64.b64decode(payload, validate=True)
|
|
286
|
+
return f"data:{mime_type};base64,{payload}"
|
|
287
|
+
except Exception:
|
|
288
|
+
return payload
|
|
289
|
+
|
|
140
290
|
def _build_tools_payload(self, tools: List[Dict]) -> Optional[List[Dict]]:
|
|
141
291
|
if not tools:
|
|
142
292
|
return None
|
|
@@ -145,7 +295,7 @@ class OpenAICompatibleChatAdapter:
|
|
|
145
295
|
|
|
146
296
|
for tool in tools:
|
|
147
297
|
if "function" in tool:
|
|
148
|
-
func_def = tool["function"]
|
|
298
|
+
func_def = dict(tool["function"] or {})
|
|
149
299
|
else:
|
|
150
300
|
func_def = {
|
|
151
301
|
"name": tool.get("name"),
|
|
@@ -172,6 +322,41 @@ class OpenAICompatibleChatAdapter:
|
|
|
172
322
|
|
|
173
323
|
return tools_payload or None
|
|
174
324
|
|
|
325
|
+
@staticmethod
|
|
326
|
+
def _map_tool_choice(
|
|
327
|
+
tool_choice: Any,
|
|
328
|
+
tools_payload: List[Dict[str, Any]],
|
|
329
|
+
) -> Optional[Dict[str, Any] | str]:
|
|
330
|
+
if tool_choice in ("", None, "auto"):
|
|
331
|
+
return None
|
|
332
|
+
|
|
333
|
+
if isinstance(tool_choice, dict):
|
|
334
|
+
return tool_choice
|
|
335
|
+
|
|
336
|
+
if tool_choice in {"none", "required"}:
|
|
337
|
+
return tool_choice
|
|
338
|
+
|
|
339
|
+
tool_names = {
|
|
340
|
+
str((tool.get("function") or {}).get("name") or "").strip()
|
|
341
|
+
for tool in (tools_payload or [])
|
|
342
|
+
if isinstance(tool, dict)
|
|
343
|
+
}
|
|
344
|
+
if str(tool_choice).strip() in tool_names:
|
|
345
|
+
return {
|
|
346
|
+
"type": "function",
|
|
347
|
+
"function": {
|
|
348
|
+
"name": str(tool_choice).strip(),
|
|
349
|
+
},
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return str(tool_choice)
|
|
353
|
+
|
|
354
|
+
@staticmethod
|
|
355
|
+
def _extract_response_format(text: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|
356
|
+
if isinstance(text, dict) and isinstance(text.get("response_format"), dict):
|
|
357
|
+
return dict(text["response_format"])
|
|
358
|
+
return None
|
|
359
|
+
|
|
175
360
|
def _map_chat_completion_response(self, response: Any) -> LLMResponse:
|
|
176
361
|
if not response.choices:
|
|
177
362
|
raise IAToolkitException(
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Copyright (c) 2024 Fernando Libedinsky
|
|
2
|
+
# Product: IAToolkit
|
|
3
|
+
#
|
|
4
|
+
# IAToolkit is open source software.
|
|
5
|
+
|
|
6
|
+
from typing import Any, Dict
|
|
7
|
+
|
|
8
|
+
from iatoolkit.infra.llm_providers.openai_compatible_chat_adapter import OpenAICompatibleChatAdapter
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OpenRouterAdapter(OpenAICompatibleChatAdapter):
|
|
12
|
+
"""OpenRouter-specific adapter built on top of the shared chat.completions core."""
|
|
13
|
+
|
|
14
|
+
supports_multimodal = True
|
|
15
|
+
supports_reasoning = False
|
|
16
|
+
supports_metadata = True
|
|
17
|
+
supports_parallel_tool_calls = True
|
|
18
|
+
|
|
19
|
+
def __init__(self, openrouter_client):
|
|
20
|
+
super().__init__(openai_compatible_client=openrouter_client, provider_label="OpenRouter")
|
|
21
|
+
|
|
22
|
+
def _extend_call_kwargs(self, call_kwargs: Dict[str, Any], kwargs: Dict[str, Any]) -> None:
|
|
23
|
+
text = kwargs.get("text") or {}
|
|
24
|
+
verbosity = text.get("verbosity") if isinstance(text, dict) else None
|
|
25
|
+
if verbosity:
|
|
26
|
+
call_kwargs["verbosity"] = verbosity
|
|
27
|
+
|
|
28
|
+
passthrough_keys = (
|
|
29
|
+
"service_tier",
|
|
30
|
+
"temperature",
|
|
31
|
+
"top_p",
|
|
32
|
+
"max_tokens",
|
|
33
|
+
"max_completion_tokens",
|
|
34
|
+
"seed",
|
|
35
|
+
"stop",
|
|
36
|
+
"stream",
|
|
37
|
+
"stream_options",
|
|
38
|
+
"modalities",
|
|
39
|
+
"user",
|
|
40
|
+
)
|
|
41
|
+
for key in passthrough_keys:
|
|
42
|
+
if kwargs.get(key) is not None:
|
|
43
|
+
call_kwargs[key] = kwargs.get(key)
|
|
44
|
+
|
|
45
|
+
extra_body = dict(call_kwargs.get("extra_body") or {})
|
|
46
|
+
|
|
47
|
+
reasoning = kwargs.get("reasoning")
|
|
48
|
+
if isinstance(reasoning, dict) and reasoning:
|
|
49
|
+
extra_body["reasoning"] = dict(reasoning)
|
|
50
|
+
|
|
51
|
+
vendor_specific_keys = (
|
|
52
|
+
"models",
|
|
53
|
+
"provider",
|
|
54
|
+
"plugins",
|
|
55
|
+
"session_id",
|
|
56
|
+
)
|
|
57
|
+
for key in vendor_specific_keys:
|
|
58
|
+
if kwargs.get(key) is not None:
|
|
59
|
+
extra_body[key] = kwargs.get(key)
|
|
60
|
+
|
|
61
|
+
if extra_body:
|
|
62
|
+
call_kwargs["extra_body"] = extra_body
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
from iatoolkit.services.configuration_service import ConfigurationService
|
|
8
8
|
from iatoolkit.infra.llm_providers.openai_adapter import OpenAIAdapter
|
|
9
9
|
from iatoolkit.infra.llm_providers.gemini_adapter import GeminiAdapter
|
|
10
|
+
from iatoolkit.infra.llm_providers.deepseek_adapter import DeepseekAdapter
|
|
10
11
|
from iatoolkit.infra.llm_providers.openai_compatible_chat_adapter import OpenAICompatibleChatAdapter
|
|
12
|
+
from iatoolkit.infra.llm_providers.openrouter_adapter import OpenRouterAdapter
|
|
11
13
|
from iatoolkit.infra.llm_providers.anthropic_adapter import AnthropicAdapter
|
|
12
14
|
from iatoolkit.common.exceptions import IAToolkitException
|
|
13
15
|
from iatoolkit.common.util import Utility
|
|
@@ -39,6 +41,7 @@ class LLMProxy:
|
|
|
39
41
|
PROVIDER_XAI = "xai"
|
|
40
42
|
PROVIDER_ANTHROPIC = "anthropic"
|
|
41
43
|
PROVIDER_OPENAI_COMPATIBLE = "openai_compatible"
|
|
44
|
+
PROVIDER_OPENROUTER = "openrouter"
|
|
42
45
|
DEFAULT_CONNECT_TIMEOUT_SECONDS = 10.0
|
|
43
46
|
DEFAULT_READ_TIMEOUT_SECONDS = 300.0
|
|
44
47
|
DEFAULT_MAX_RETRIES = 0
|
|
@@ -145,6 +148,7 @@ class LLMProxy:
|
|
|
145
148
|
client_config = self._get_client_config(company_short_name, provider)
|
|
146
149
|
api_key = client_config["api_key"]
|
|
147
150
|
base_url = client_config.get("base_url") or ""
|
|
151
|
+
default_headers = client_config.get("default_headers") or {}
|
|
148
152
|
connect_timeout_seconds = client_config["connect_timeout_seconds"]
|
|
149
153
|
read_timeout_seconds = client_config["read_timeout_seconds"]
|
|
150
154
|
max_retries = client_config["max_retries"]
|
|
@@ -152,6 +156,7 @@ class LLMProxy:
|
|
|
152
156
|
provider,
|
|
153
157
|
api_key or "",
|
|
154
158
|
base_url,
|
|
159
|
+
tuple(sorted(default_headers.items())),
|
|
155
160
|
connect_timeout_seconds,
|
|
156
161
|
read_timeout_seconds,
|
|
157
162
|
max_retries,
|
|
@@ -166,6 +171,7 @@ class LLMProxy:
|
|
|
166
171
|
provider,
|
|
167
172
|
api_key,
|
|
168
173
|
base_url=base_url,
|
|
174
|
+
default_headers=default_headers,
|
|
169
175
|
connect_timeout_seconds=connect_timeout_seconds,
|
|
170
176
|
read_timeout_seconds=read_timeout_seconds,
|
|
171
177
|
max_retries=max_retries,
|
|
@@ -177,9 +183,11 @@ class LLMProxy:
|
|
|
177
183
|
elif provider == self.PROVIDER_GEMINI:
|
|
178
184
|
adapter = GeminiAdapter(client)
|
|
179
185
|
elif provider == self.PROVIDER_DEEPSEEK:
|
|
180
|
-
adapter =
|
|
186
|
+
adapter = DeepseekAdapter(client)
|
|
181
187
|
elif provider == self.PROVIDER_OPENAI_COMPATIBLE:
|
|
182
188
|
adapter = OpenAICompatibleChatAdapter(client, provider_label="OpenAI-compatible")
|
|
189
|
+
elif provider == self.PROVIDER_OPENROUTER:
|
|
190
|
+
adapter = OpenRouterAdapter(client)
|
|
183
191
|
elif provider == self.PROVIDER_ANTHROPIC:
|
|
184
192
|
adapter = AnthropicAdapter(client)
|
|
185
193
|
else:
|
|
@@ -199,7 +207,7 @@ class LLMProxy:
|
|
|
199
207
|
) -> Dict[str, Any]:
|
|
200
208
|
effective_kwargs = dict(request_kwargs or {})
|
|
201
209
|
|
|
202
|
-
if provider
|
|
210
|
+
if provider not in {self.PROVIDER_OPENAI_COMPATIBLE, self.PROVIDER_OPENROUTER}:
|
|
203
211
|
return effective_kwargs
|
|
204
212
|
|
|
205
213
|
if provider_config.get("disable_tools") is True:
|
|
@@ -219,6 +227,7 @@ class LLMProxy:
|
|
|
219
227
|
provider: str,
|
|
220
228
|
api_key: str,
|
|
221
229
|
base_url: str = "",
|
|
230
|
+
default_headers: Dict[str, str] | None = None,
|
|
222
231
|
*,
|
|
223
232
|
connect_timeout_seconds: float | None = None,
|
|
224
233
|
read_timeout_seconds: float | None = None,
|
|
@@ -244,6 +253,7 @@ class LLMProxy:
|
|
|
244
253
|
provider,
|
|
245
254
|
api_key or "",
|
|
246
255
|
base_url or "",
|
|
256
|
+
tuple(sorted((default_headers or {}).items())),
|
|
247
257
|
connect_timeout_seconds,
|
|
248
258
|
read_timeout_seconds,
|
|
249
259
|
max_retries,
|
|
@@ -257,6 +267,7 @@ class LLMProxy:
|
|
|
257
267
|
provider,
|
|
258
268
|
api_key,
|
|
259
269
|
base_url=base_url,
|
|
270
|
+
default_headers=default_headers,
|
|
260
271
|
connect_timeout_seconds=connect_timeout_seconds,
|
|
261
272
|
read_timeout_seconds=read_timeout_seconds,
|
|
262
273
|
max_retries=max_retries,
|
|
@@ -269,6 +280,7 @@ class LLMProxy:
|
|
|
269
280
|
provider: str,
|
|
270
281
|
api_key: str,
|
|
271
282
|
base_url: str = "",
|
|
283
|
+
default_headers: Dict[str, str] | None = None,
|
|
272
284
|
*,
|
|
273
285
|
connect_timeout_seconds: float | None = None,
|
|
274
286
|
read_timeout_seconds: float | None = None,
|
|
@@ -325,6 +337,20 @@ class LLMProxy:
|
|
|
325
337
|
max_retries=max_retries,
|
|
326
338
|
)
|
|
327
339
|
|
|
340
|
+
if provider == self.PROVIDER_OPENROUTER:
|
|
341
|
+
if not base_url:
|
|
342
|
+
raise IAToolkitException(
|
|
343
|
+
IAToolkitException.ErrorType.CONFIG_ERROR,
|
|
344
|
+
"Provider 'openrouter' requires a configured base_url."
|
|
345
|
+
)
|
|
346
|
+
return OpenAI(
|
|
347
|
+
api_key=api_key,
|
|
348
|
+
base_url=base_url,
|
|
349
|
+
timeout=timeout,
|
|
350
|
+
max_retries=max_retries,
|
|
351
|
+
default_headers=default_headers or None,
|
|
352
|
+
)
|
|
353
|
+
|
|
328
354
|
if provider == self.PROVIDER_GEMINI:
|
|
329
355
|
# Example placeholder: you may already have a Gemini client factory elsewhere.
|
|
330
356
|
# Here you could create and configure the Gemini client (e.g. google.generativeai).
|
|
@@ -353,6 +379,7 @@ class LLMProxy:
|
|
|
353
379
|
return {
|
|
354
380
|
"api_key": self._get_api_key_from_config(company_short_name, provider),
|
|
355
381
|
"base_url": self._get_base_url_from_config(company_short_name, provider),
|
|
382
|
+
"default_headers": self._get_default_headers_from_config(company_short_name, provider),
|
|
356
383
|
"connect_timeout_seconds": self._resolve_provider_float(
|
|
357
384
|
provider_config,
|
|
358
385
|
("connect_timeout_seconds",),
|
|
@@ -499,7 +526,7 @@ class LLMProxy:
|
|
|
499
526
|
return api_key_value
|
|
500
527
|
|
|
501
528
|
def _get_base_url_from_config(self, company_short_name: str, provider: str) -> str:
|
|
502
|
-
if provider
|
|
529
|
+
if provider not in {self.PROVIDER_OPENAI_COMPATIBLE, self.PROVIDER_OPENROUTER}:
|
|
503
530
|
return ""
|
|
504
531
|
|
|
505
532
|
provider_config = self.configuration_service.get_llm_provider_config(company_short_name, provider) or {}
|
|
@@ -528,6 +555,27 @@ class LLMProxy:
|
|
|
528
555
|
|
|
529
556
|
return base_url
|
|
530
557
|
|
|
558
|
+
def _get_default_headers_from_config(self, company_short_name: str, provider: str) -> dict:
|
|
559
|
+
if provider != self.PROVIDER_OPENROUTER:
|
|
560
|
+
return {}
|
|
561
|
+
|
|
562
|
+
provider_config = self.configuration_service.get_llm_provider_config(company_short_name, provider) or {}
|
|
563
|
+
if not isinstance(provider_config, dict):
|
|
564
|
+
provider_config = {}
|
|
565
|
+
|
|
566
|
+
headers: dict[str, str] = {}
|
|
567
|
+
|
|
568
|
+
http_referer = str(provider_config.get("http_referer") or "").strip()
|
|
569
|
+
if http_referer:
|
|
570
|
+
headers["HTTP-Referer"] = http_referer
|
|
571
|
+
|
|
572
|
+
x_title = str(provider_config.get("x_title") or "").strip()
|
|
573
|
+
if x_title:
|
|
574
|
+
headers["X-Title"] = x_title
|
|
575
|
+
headers["X-OpenRouter-Title"] = x_title
|
|
576
|
+
|
|
577
|
+
return headers
|
|
578
|
+
|
|
531
579
|
@classmethod
|
|
532
580
|
def clear_low_level_clients_cache(cls):
|
|
533
581
|
with cls._clients_cache_lock:
|