iatoolkit 2.76.1__tar.gz → 2.76.3__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 (281) hide show
  1. {iatoolkit-2.76.1/src/iatoolkit.egg-info → iatoolkit-2.76.3}/PKG-INFO +1 -1
  2. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/__init__.py +1 -1
  3. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/database_manager.py +8 -2
  4. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/history_manager_service.py +28 -1
  5. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/llm_client_service.py +9 -1
  6. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/query_service.py +8 -2
  7. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/structured_output_service.py +89 -0
  8. {iatoolkit-2.76.1 → iatoolkit-2.76.3/src/iatoolkit.egg-info}/PKG-INFO +1 -1
  9. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/LICENSE +0 -0
  10. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/LICENSE_COMMUNITY.md +0 -0
  11. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/pyproject.toml +0 -0
  12. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/readme.md +0 -0
  13. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/setup.cfg +0 -0
  14. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/base_company.py +0 -0
  15. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/cli_commands.py +0 -0
  16. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/__init__.py +0 -0
  17. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/access.py +0 -0
  18. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/bridge_validation.py +0 -0
  19. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/company_paths.py +0 -0
  20. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/exceptions.py +0 -0
  21. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/__init__.py +0 -0
  22. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/asset_storage.py +0 -0
  23. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/database_provider.py +0 -0
  24. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/history_compaction_trigger.py +0 -0
  25. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/memory_compilation_trigger.py +0 -0
  26. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/secret_provider.py +0 -0
  27. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/signup_policy_resolver.py +0 -0
  28. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/interfaces/web_search_provider.py +0 -0
  29. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/memory_tools.py +0 -0
  30. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/model_registry.py +0 -0
  31. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/routes.py +0 -0
  32. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/search_terms.py +0 -0
  33. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/secret_resolver.py +0 -0
  34. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/session_manager.py +0 -0
  35. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/text_splitter.py +0 -0
  36. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/url_safety.py +0 -0
  37. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/common/util.py +0 -0
  38. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/company_registry.py +0 -0
  39. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/__init__.py +0 -0
  40. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/llm_capabilities.yaml +0 -0
  41. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/history_compaction.prompt +0 -0
  42. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/memory_compiler.prompt +0 -0
  43. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/memory_correction.prompt +0 -0
  44. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/memory_document_ingest.prompt +0 -0
  45. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/memory_image_ingest.prompt +0 -0
  46. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/memory_meeting_ingest.prompt +0 -0
  47. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents/memory_question_review.prompt +0 -0
  48. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_agents_pack.yaml +0 -0
  49. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/channel_business_identity.prompt +0 -0
  50. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/channel_conversation_continuity.prompt +0 -0
  51. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/channel_response_style.prompt +0 -0
  52. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/chat_state_rules.prompt +0 -0
  53. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/chat_user_profile.prompt +0 -0
  54. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/core_identity.prompt +0 -0
  55. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/email_output.prompt +0 -0
  56. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/file_download_output.prompt +0 -0
  57. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/format_styles.prompt +0 -0
  58. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/html_structures.prompt +0 -0
  59. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/links_documents.prompt +0 -0
  60. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/memory_usage.prompt +0 -0
  61. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/multimodal_basics.prompt +0 -0
  62. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/output_basics.prompt +0 -0
  63. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/presentation_formatting.prompt +0 -0
  64. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/query_main.prompt +0 -0
  65. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_aggregation_scope.prompt +0 -0
  66. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_casting.prompt +0 -0
  67. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_core.prompt +0 -0
  68. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_jsonb.prompt +0 -0
  69. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_mysql_casting.prompt +0 -0
  70. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_mysql_json.prompt +0 -0
  71. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_redshift_basics.prompt +0 -0
  72. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/sql_redshift_types.prompt +0 -0
  73. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts/tool_html_passthrough.prompt +0 -0
  74. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_prompts_pack.yaml +0 -0
  75. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/config/system_tools_pack.yaml +0 -0
  76. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/core.py +0 -0
  77. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/__init__.py +0 -0
  78. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/brevo_mail_app.py +0 -0
  79. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/call_service.py +0 -0
  80. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/__init__.py +0 -0
  81. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/file_connector.py +0 -0
  82. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/file_connector_factory.py +0 -0
  83. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/google_cloud_storage_connector.py +0 -0
  84. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/google_drive_connector.py +0 -0
  85. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/local_file_connector.py +0 -0
  86. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/connectors/s3_connector.py +0 -0
  87. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/google_auth_client.py +0 -0
  88. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/google_chat_app.py +0 -0
  89. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/inference_embeddings_client.py +0 -0
  90. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/inference_handler.py +0 -0
  91. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/jina_embeddings_client.py +0 -0
  92. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_gateway_resolver.py +0 -0
  93. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/__init__.py +0 -0
  94. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/anthropic_adapter.py +0 -0
  95. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/deepseek_adapter.py +0 -0
  96. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/gemini_adapter.py +0 -0
  97. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/openai_adapter.py +0 -0
  98. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/openai_compatible_chat_adapter.py +0 -0
  99. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_providers/openrouter_adapter.py +0 -0
  100. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_proxy.py +0 -0
  101. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/llm_response.py +0 -0
  102. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/infra/redis_session_manager.py +0 -0
  103. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/locales/en.yaml +0 -0
  104. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/locales/es.yaml +0 -0
  105. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/__init__.py +0 -0
  106. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/advisory_lock.py +0 -0
  107. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/api_key_repo.py +0 -0
  108. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/bridge_repo.py +0 -0
  109. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/document_repo.py +0 -0
  110. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/env_secret_provider.py +0 -0
  111. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/filesystem_asset_repository.py +0 -0
  112. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/knowledge_wiki_repo.py +0 -0
  113. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/llm_query_repo.py +0 -0
  114. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/mcp_token_repo.py +0 -0
  115. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/memory_question_repo.py +0 -0
  116. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/memory_repo.py +0 -0
  117. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/memory_usage_repo.py +0 -0
  118. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/models.py +0 -0
  119. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/profile_repo.py +0 -0
  120. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/prompt_resource_repo.py +0 -0
  121. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/sql_dataset_repo.py +0 -0
  122. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/sql_source_repo.py +0 -0
  123. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/repositories/vs_repo.py +0 -0
  124. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/runtime_logging.py +0 -0
  125. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/__init__.py +0 -0
  126. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/api_key_service.py +0 -0
  127. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/attachment_policy_service.py +0 -0
  128. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/auth_service.py +0 -0
  129. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/branding_service.py +0 -0
  130. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/company_context_service.py +0 -0
  131. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/configuration_service.py +0 -0
  132. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/context_builder_service.py +0 -0
  133. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/dispatcher_service.py +0 -0
  134. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/embedding_service.py +0 -0
  135. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/excel_service.py +0 -0
  136. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/file_processor_service.py +0 -0
  137. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/history_compaction_service.py +0 -0
  138. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/http_tool_service.py +0 -0
  139. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/i18n_service.py +0 -0
  140. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/inference_service.py +0 -0
  141. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/jwt_service.py +0 -0
  142. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/knowledge_base_service.py +0 -0
  143. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/language_service.py +0 -0
  144. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/license_service.py +0 -0
  145. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/mail_service.py +0 -0
  146. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/markdown_wiki_service.py +0 -0
  147. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/mcp_token_service.py +0 -0
  148. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_compiler_service.py +0 -0
  149. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_lookup_policy_service.py +0 -0
  150. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_question_service.py +0 -0
  151. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_service.py +0 -0
  152. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_sources.py +0 -0
  153. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_usage_service.py +0 -0
  154. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/memory_wiki_service.py +0 -0
  155. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/noop_history_compaction_trigger.py +0 -0
  156. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/noop_memory_compilation_trigger.py +0 -0
  157. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/operator_identity_service.py +0 -0
  158. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/__init__.py +0 -0
  159. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/contracts.py +0 -0
  160. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/image_normalizer.py +0 -0
  161. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/parsing_service.py +0 -0
  162. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/pdf_ocr_detection.py +0 -0
  163. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/provider_factory.py +0 -0
  164. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/provider_resolver.py +0 -0
  165. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/providers/__init__.py +0 -0
  166. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/providers/basic_provider.py +0 -0
  167. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/providers/docling_provider.py +0 -0
  168. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/parsers/validator.py +0 -0
  169. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/pdf_service.py +0 -0
  170. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/profile_service.py +0 -0
  171. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/prompt_resource_service.py +0 -0
  172. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/prompt_service.py +0 -0
  173. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/resource_access_scope.py +0 -0
  174. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/signup_policy_resolver.py +0 -0
  175. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/sql_catalog_service.py +0 -0
  176. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/sql_dataset_service.py +0 -0
  177. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/sql_service.py +0 -0
  178. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/sql_source_service.py +0 -0
  179. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/storage_service.py +0 -0
  180. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/system_agent_catalog.py +0 -0
  181. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/system_agent_runner.py +0 -0
  182. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/system_prompt_catalog.py +0 -0
  183. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/system_tools.py +0 -0
  184. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/telemetry_service.py +0 -0
  185. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/tenant_wiki_service.py +0 -0
  186. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/tool_output_contract.py +0 -0
  187. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/tool_service.py +0 -0
  188. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/user_feedback_service.py +0 -0
  189. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/user_session_context_service.py +0 -0
  190. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/visual_kb_service.py +0 -0
  191. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/visual_tool_service.py +0 -0
  192. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/warmup_service.py +0 -0
  193. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/web_search/__init__.py +0 -0
  194. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/web_search/provider_factory.py +0 -0
  195. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/web_search/providers/__init__.py +0 -0
  196. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/web_search/providers/brave_provider.py +0 -0
  197. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/web_search_service.py +0 -0
  198. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/services/wiki_page_index_service.py +0 -0
  199. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/images/favicon.ico +0 -0
  200. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/images/favicon.png +0 -0
  201. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/images/fernando.jpeg +0 -0
  202. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/images/iatoolkit_core.png +0 -0
  203. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/images/iatoolkit_logo.png +0 -0
  204. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_feedback_button.js +0 -0
  205. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_filepond.js +0 -0
  206. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_header_navigation.js +0 -0
  207. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_help_content.js +0 -0
  208. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_history_button.js +0 -0
  209. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_logout_button.js +0 -0
  210. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_main.js +0 -0
  211. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_memory_button.js +0 -0
  212. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_model_selector.js +0 -0
  213. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_onboarding_button.js +0 -0
  214. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/js/chat_prompt_manager.js +0 -0
  215. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/account.css +0 -0
  216. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/chat_iatoolkit.css +0 -0
  217. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/chat_modal.css +0 -0
  218. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/chat_public.css +0 -0
  219. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/documents.css +0 -0
  220. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/landing_page.css +0 -0
  221. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/llm_output.css +0 -0
  222. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/onboarding.css +0 -0
  223. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/static/styles/wiki_page.css +0 -0
  224. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/_chat_header.html +0 -0
  225. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/_company_header.html +0 -0
  226. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/_login_widget.html +0 -0
  227. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/account.html +0 -0
  228. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/base.html +0 -0
  229. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/change_password.html +0 -0
  230. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/chat.html +0 -0
  231. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/chat_memory_modal.html +0 -0
  232. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/chat_modals.html +0 -0
  233. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/error.html +0 -0
  234. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/forgot_password.html +0 -0
  235. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/home_hosted_default.html +0 -0
  236. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/login_global.html +0 -0
  237. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/memory/wiki_schema.md +0 -0
  238. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/pdf/base.html +0 -0
  239. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/pdf/letter.html +0 -0
  240. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/pdf/report.html +0 -0
  241. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/pdf/simple.html +0 -0
  242. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/signup.html +0 -0
  243. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/templates/wiki_page.html +0 -0
  244. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/__init__.py +0 -0
  245. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/account_view.py +0 -0
  246. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/api_key_api_view.py +0 -0
  247. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/base_login_view.py +0 -0
  248. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/categories_api_view.py +0 -0
  249. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/change_password_view.py +0 -0
  250. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/chat_context_preview_api_view.py +0 -0
  251. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/chat_view.py +0 -0
  252. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/configuration_api_view.py +0 -0
  253. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/connectors_api_view.py +0 -0
  254. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/embedding_api_view.py +0 -0
  255. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/forgot_password_view.py +0 -0
  256. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/help_content_api_view.py +0 -0
  257. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/history_api_view.py +0 -0
  258. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/home_view.py +0 -0
  259. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/init_context_api_view.py +0 -0
  260. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/llmquery_api_view.py +0 -0
  261. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/load_document_api_view.py +0 -0
  262. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/login_view.py +0 -0
  263. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/logout_api_view.py +0 -0
  264. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/memory_api_view.py +0 -0
  265. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/profile_api_view.py +0 -0
  266. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/prompt_api_view.py +0 -0
  267. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/prompt_context_preview_api_view.py +0 -0
  268. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/prompt_resource_api_view.py +0 -0
  269. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/rag_api_view.py +0 -0
  270. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/root_redirect_view.py +0 -0
  271. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/signup_view.py +0 -0
  272. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/static_page_view.py +0 -0
  273. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/tool_api_view.py +0 -0
  274. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/user_feedback_api_view.py +0 -0
  275. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/users_api_view.py +0 -0
  276. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/verify_user_view.py +0 -0
  277. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit/views/wiki_page_view.py +0 -0
  278. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit.egg-info/SOURCES.txt +0 -0
  279. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit.egg-info/dependency_links.txt +0 -0
  280. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/src/iatoolkit.egg-info/requires.txt +0 -0
  281. {iatoolkit-2.76.1 → iatoolkit-2.76.3}/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.76.1
3
+ Version: 2.76.3
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.76.1"
6
+ __version__ = "2.76.3"
7
7
 
8
8
  # Expose main classes and functions at the top level of the package
9
9
 
@@ -394,11 +394,17 @@ class DatabaseManager(DatabaseProvider):
394
394
 
395
395
  # -- schema methods ----
396
396
  @staticmethod
397
- def _safe_inspector_name_list(fetcher, schema: str | None) -> list[str]:
397
+ def _safe_inspector_name_list(fetcher, schema: str | None, *, required: bool = False) -> list[str]:
398
+ """The names a listing returns. `required` (the tables) raises when it fails: an
399
+ empty answer would read as "this source has no tables" when the connection, the
400
+ schema or the user's grants are wrong. Views stay optional, as some engines
401
+ cannot list them."""
398
402
  try:
399
403
  names = fetcher(schema=schema)
400
404
  except Exception as e:
401
405
  logging.warning("Could not list schema objects for schema %s: %s", schema, e)
406
+ if required:
407
+ raise
402
408
  return []
403
409
 
404
410
  if not isinstance(names, list):
@@ -421,7 +427,7 @@ class DatabaseManager(DatabaseProvider):
421
427
  schema_objects: list[tuple[str, str]] = []
422
428
  schema_objects.extend(
423
429
  (table_name, "table")
424
- for table_name in self._safe_inspector_name_list(inspector.get_table_names, effective_schema)
430
+ for table_name in self._safe_inspector_name_list(inspector.get_table_names, effective_schema, required=True)
425
431
  )
426
432
  schema_objects.extend(
427
433
  (view_name, "view")
@@ -68,6 +68,11 @@ class HistoryManagerService:
68
68
  #: one a follow-up ("of those...") refers to; with two, one turn of 80k of
69
69
  #: results kept a compacted history at 130k.
70
70
  KEEP_TOOL_OUTPUT_TURNS = 1
71
+ #: ...unless what that turn carries for its tools (outputs, arguments and
72
+ #: reasoning) passes this: a turn of eight SQL rounds left 142k tokens for a
73
+ #: follow-up answered from the conversation in 5 seconds. Its answer stays,
74
+ #: and the model can call the tools again.
75
+ MAX_KEPT_TOOL_PAYLOAD_CHARS = 40000
71
76
  #: What is kept of a cut output: its beginning, enough to remember its shape.
72
77
  TRIMMED_TOOL_OUTPUT_CHARS = 1500
73
78
  TRIMMED_TOOL_OUTPUT_MARKER = "[tool output trimmed"
@@ -405,9 +410,13 @@ class HistoryManagerService:
405
410
  then stays the same from turn to turn, which is what a prompt cache reuses.
406
411
  """
407
412
  turn_starts = cls.turn_starts(context_history)
408
- if len(turn_starts) <= cls.KEEP_TOOL_OUTPUT_TURNS:
413
+ if len(turn_starts) < cls.KEEP_TOOL_OUTPUT_TURNS or not turn_starts:
409
414
  return
410
415
  boundary = turn_starts[-cls.KEEP_TOOL_OUTPUT_TURNS]
416
+ kept_payload = cls._tool_payload_chars(context_history[boundary:])
417
+ if kept_payload > cls.MAX_KEPT_TOOL_PAYLOAD_CHARS:
418
+ logging.info(f"Last turn carries {kept_payload} characters for its tools: cut as an older turn.")
419
+ boundary = len(context_history)
411
420
  tool_names = {}
412
421
  for message in context_history[:boundary]:
413
422
  if not isinstance(message, dict):
@@ -438,6 +447,24 @@ class HistoryManagerService:
438
447
  f"Call {tool} again if you need all of it.]"
439
448
  )
440
449
 
450
+ @staticmethod
451
+ def _tool_payload_chars(messages: list) -> int:
452
+ """Characters of tool outputs, tool call arguments and reasoning in these messages."""
453
+ total = 0
454
+ for message in messages:
455
+ if not isinstance(message, dict):
456
+ continue
457
+ if message.get("type") == "function_call_output" and isinstance(message.get("output"), str):
458
+ total += len(message["output"])
459
+ total += len(str(message.get("reasoning_content") or ""))
460
+ if message.get("reasoning_details"):
461
+ total += len(json.dumps(message["reasoning_details"], default=str))
462
+ for call in message.get("tool_calls") or []:
463
+ function = call.get("function") if isinstance(call, dict) else None
464
+ if isinstance(function, dict) and isinstance(function.get("arguments"), str):
465
+ total += len(function["arguments"])
466
+ return total
467
+
441
468
  def _cap_stored_history(self, company_short_name: str, model: Optional[str], context_history: list):
442
469
  """Keeps the stored history under STORED_HISTORY_MAX_BUDGETS budgets, whole turns at a time."""
443
470
  cap = self.context_budget_tokens(company_short_name, model) * self.STORED_HISTORY_MAX_BUDGETS
@@ -1327,6 +1327,9 @@ class llmClient:
1327
1327
  response_mode = str(response_contract.get("response_mode") or "chat_compatible").strip().lower()
1328
1328
  provider = str(response_contract.get("provider") or "").strip().lower()
1329
1329
  allow_additional_property_repair = provider in {"deepseek", "openai_compatible"}
1330
+ # In strict mode the provider got every optional field as nullable
1331
+ # (StructuredOutputService.to_strict_schema): a null there means absent.
1332
+ drop_optional_nulls = schema_mode == "strict"
1330
1333
  candidates: list[Any] = []
1331
1334
  seen: set[str] = set()
1332
1335
 
@@ -1354,7 +1357,9 @@ class llmClient:
1354
1357
  _add_candidate(decoded_response.get("output_text"))
1355
1358
 
1356
1359
  evaluations = [
1357
- StructuredOutputService.evaluate_output(raw_output=candidate, schema=schema)
1360
+ StructuredOutputService.evaluate_output(
1361
+ raw_output=candidate, schema=schema, drop_optional_nulls=drop_optional_nulls,
1362
+ )
1358
1363
  for candidate in candidates
1359
1364
  ]
1360
1365
  repaired_evaluations = []
@@ -1363,6 +1368,7 @@ class llmClient:
1363
1368
  StructuredOutputService.evaluate_output(
1364
1369
  raw_output=candidate,
1365
1370
  schema=schema,
1371
+ drop_optional_nulls=drop_optional_nulls,
1366
1372
  drop_additional_properties=True,
1367
1373
  )
1368
1374
  for candidate in candidates
@@ -1372,6 +1378,7 @@ class llmClient:
1372
1378
  StructuredOutputService.evaluate_output(
1373
1379
  raw_output=decoded_response.get("output_text"),
1374
1380
  schema=schema,
1381
+ drop_optional_nulls=drop_optional_nulls,
1375
1382
  )
1376
1383
  ]
1377
1384
  if allow_additional_property_repair:
@@ -1379,6 +1386,7 @@ class llmClient:
1379
1386
  StructuredOutputService.evaluate_output(
1380
1387
  raw_output=decoded_response.get("output_text"),
1381
1388
  schema=schema,
1389
+ drop_optional_nulls=drop_optional_nulls,
1382
1390
  drop_additional_properties=True,
1383
1391
  )
1384
1392
  )
@@ -16,6 +16,7 @@ from iatoolkit.services.attachment_policy_service import AttachmentPolicyService
16
16
  from iatoolkit.services.memory_lookup_policy_service import MemoryLookupPolicyService
17
17
  from iatoolkit.services.telemetry_service import NoopTelemetryService
18
18
  from iatoolkit.services.prompt_service import PromptService
19
+ from iatoolkit.services.structured_output_service import StructuredOutputService
19
20
  from iatoolkit.common.model_registry import ModelRegistry
20
21
  from iatoolkit.common.exceptions import IAToolkitException
21
22
  from injector import inject
@@ -844,12 +845,17 @@ class QueryService:
844
845
 
845
846
  provider = self._get_provider(company_short_name, model)
846
847
  schema_mode = str(contract.get("schema_mode") or "best_effort").strip().lower()
848
+ # Strict structured outputs only accept closed objects with every property
849
+ # required; a schema written with optional fields would get a 400. The
850
+ # provider gets that shape (optional fields nullable) and the answer is
851
+ # mapped back to the stored schema when it is validated.
852
+ provider_schema = StructuredOutputService.to_strict_schema(schema) if schema_mode == "strict" else schema
847
853
  if provider in ("openai", "xai"):
848
854
  return {
849
855
  "format": {
850
856
  "type": "json_schema",
851
857
  "name": self._sanitize_schema_name(contract.get("prompt_name") or "prompt_output"),
852
- "schema": schema,
858
+ "schema": provider_schema,
853
859
  "strict": schema_mode == "strict",
854
860
  }
855
861
  }
@@ -878,7 +884,7 @@ class QueryService:
878
884
  "json_schema": {
879
885
  "name": self._sanitize_schema_name(contract.get("prompt_name") or "prompt_output"),
880
886
  "strict": schema_mode == "strict",
881
- "schema": schema,
887
+ "schema": provider_schema,
882
888
  },
883
889
  }
884
890
  }
@@ -5,6 +5,7 @@
5
5
 
6
6
  from __future__ import annotations
7
7
 
8
+ import copy
8
9
  import html
9
10
  import json
10
11
  import re
@@ -129,6 +130,7 @@ class StructuredOutputService:
129
130
  schema: dict | None,
130
131
  *,
131
132
  drop_additional_properties: bool = False,
133
+ drop_optional_nulls: bool = False,
132
134
  ) -> dict:
133
135
  if not schema:
134
136
  return {
@@ -151,6 +153,7 @@ class StructuredOutputService:
151
153
  candidate,
152
154
  schema,
153
155
  drop_additional_properties=drop_additional_properties,
156
+ drop_optional_nulls=drop_optional_nulls,
154
157
  )
155
158
  errors = cls.validate_instance(candidate, schema, path="$")
156
159
  return {
@@ -282,6 +285,7 @@ class StructuredOutputService:
282
285
  schema: dict | None,
283
286
  *,
284
287
  drop_additional_properties: bool = False,
288
+ drop_optional_nulls: bool = False,
285
289
  ) -> Any:
286
290
  if not isinstance(schema, dict):
287
291
  return instance
@@ -303,19 +307,32 @@ class StructuredOutputService:
303
307
  additional = schema.get("additionalProperties", True)
304
308
  normalized_object: dict[str, Any] = {}
305
309
 
310
+ required = set(schema.get("required") or []) if isinstance(schema.get("required"), list) else set()
306
311
  for key, value in instance.items():
307
312
  child_schema = properties.get(key)
313
+ if (
314
+ drop_optional_nulls
315
+ and value is None
316
+ and key not in required
317
+ and isinstance(child_schema, dict)
318
+ and not cls._schema_allows_null(child_schema)
319
+ ):
320
+ # A strict provider schema made this optional field nullable
321
+ # (see to_strict_schema); absent is what the contract means.
322
+ continue
308
323
  if isinstance(child_schema, dict):
309
324
  normalized_object[key] = cls.normalize_instance(
310
325
  value,
311
326
  child_schema,
312
327
  drop_additional_properties=drop_additional_properties,
328
+ drop_optional_nulls=drop_optional_nulls,
313
329
  )
314
330
  elif isinstance(additional, dict):
315
331
  normalized_object[key] = cls.normalize_instance(
316
332
  value,
317
333
  additional,
318
334
  drop_additional_properties=drop_additional_properties,
335
+ drop_optional_nulls=drop_optional_nulls,
319
336
  )
320
337
  elif additional is False and drop_additional_properties:
321
338
  continue
@@ -333,6 +350,7 @@ class StructuredOutputService:
333
350
  item,
334
351
  item_schema,
335
352
  drop_additional_properties=drop_additional_properties,
353
+ drop_optional_nulls=drop_optional_nulls,
336
354
  )
337
355
  for item in instance
338
356
  ]
@@ -503,6 +521,77 @@ class StructuredOutputService:
503
521
 
504
522
  return count
505
523
 
524
+ @classmethod
525
+ def to_strict_schema(cls, schema: dict | None) -> dict | None:
526
+ """The schema in the shape strict structured outputs accept (OpenAI and
527
+ the providers that follow it): every object closed with
528
+ additionalProperties false and every property required, the optional
529
+ ones made nullable. Same meaning: an optional field comes back null
530
+ instead of absent, and normalize_instance(drop_optional_nulls=True)
531
+ turns it back into absent before validating against the original.
532
+ Returns a copy; the stored schema is never changed.
533
+ """
534
+ if not isinstance(schema, dict):
535
+ return schema
536
+ return cls._strict_node(copy.deepcopy(schema))
537
+
538
+ @classmethod
539
+ def _strict_node(cls, node: dict) -> dict:
540
+ if cls._is_type(node.get("type"), "object") or isinstance(node.get("properties"), dict):
541
+ properties = node.get("properties") if isinstance(node.get("properties"), dict) else {}
542
+ required = set(node.get("required") or []) if isinstance(node.get("required"), list) else set()
543
+ for key, child in list(properties.items()):
544
+ if not isinstance(child, dict):
545
+ continue
546
+ child = cls._strict_node(child)
547
+ if key not in required:
548
+ child = cls._nullable(child)
549
+ properties[key] = child
550
+ node["properties"] = properties
551
+ node["required"] = list(properties.keys())
552
+ # A map (additionalProperties as a schema) cannot be expressed in
553
+ # strict mode; it is left as written and the provider decides.
554
+ if not isinstance(node.get("additionalProperties"), dict):
555
+ node["additionalProperties"] = False
556
+
557
+ items = node.get("items")
558
+ if isinstance(items, dict):
559
+ node["items"] = cls._strict_node(items)
560
+ for key in ("anyOf", "oneOf"):
561
+ if isinstance(node.get(key), list):
562
+ node[key] = [cls._strict_node(item) if isinstance(item, dict) else item for item in node[key]]
563
+ return node
564
+
565
+ @classmethod
566
+ def _nullable(cls, node: dict) -> dict:
567
+ if cls._schema_allows_null(node):
568
+ return node
569
+ schema_type = node.get("type")
570
+ if isinstance(schema_type, str):
571
+ node["type"] = [schema_type, "null"]
572
+ elif isinstance(schema_type, list):
573
+ node["type"] = [*schema_type, "null"]
574
+ else:
575
+ for key in ("anyOf", "oneOf"):
576
+ if isinstance(node.get(key), list):
577
+ node[key] = [*node[key], {"type": "null"}]
578
+ break
579
+ if isinstance(node.get("enum"), list) and None not in node["enum"]:
580
+ node["enum"] = [*node["enum"], None]
581
+ return node
582
+
583
+ @classmethod
584
+ def _schema_allows_null(cls, schema: dict) -> bool:
585
+ if bool(schema.get("nullable", False)) or cls._allows_null(schema.get("type")):
586
+ return True
587
+ for key in ("anyOf", "oneOf"):
588
+ options = schema.get(key)
589
+ if isinstance(options, list) and any(
590
+ isinstance(option, dict) and cls._allows_null(option.get("type")) for option in options
591
+ ):
592
+ return True
593
+ return False
594
+
506
595
  @classmethod
507
596
  def _allows_null(cls, schema_type: Any) -> bool:
508
597
  if isinstance(schema_type, list):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iatoolkit
3
- Version: 2.76.1
3
+ Version: 2.76.3
4
4
  Summary: IAToolkit
5
5
  Author: Fernando Libedinsky
6
6
  License-Expression: MIT
File without changes
File without changes
File without changes
File without changes