omnimancer-cli 0.3.1__tar.gz → 0.3.2__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 (198) hide show
  1. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/PKG-INFO +1 -1
  2. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/web_client.py +6 -1
  3. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/bedrock.py +23 -10
  4. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/PKG-INFO +1 -1
  5. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/pyproject.toml +1 -1
  6. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_bedrock_provider.py +69 -9
  7. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/LICENSE +0 -0
  8. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/README.md +0 -0
  9. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omn_fleet_hook.py +0 -0
  10. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/__init__.py +0 -0
  11. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/__main__.py +0 -0
  12. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/__init__.py +0 -0
  13. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/agent_loop.py +0 -0
  14. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/approval_formatter.py +0 -0
  15. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/approval_integration.py +0 -0
  16. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/approval_prompt.py +0 -0
  17. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/command_dispatch.py +0 -0
  18. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/commands.py +0 -0
  19. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/completion.py +0 -0
  20. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/display.py +0 -0
  21. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/dynamic_commands.py +0 -0
  22. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/file_mentions.py +0 -0
  23. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/h2l_command.py +0 -0
  24. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/h2l_headless.py +0 -0
  25. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/handlers/__init__.py +0 -0
  26. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/headless.py +0 -0
  27. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/headless_checkpoint.py +0 -0
  28. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/interface.py +0 -0
  29. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/prompt_input.py +0 -0
  30. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/pt_completion.py +0 -0
  31. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/session.py +0 -0
  32. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/subagent.py +0 -0
  33. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/system_prompts.py +0 -0
  34. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/tool_handler.py +0 -0
  35. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/turn_notify.py +0 -0
  36. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/usage.py +0 -0
  37. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/__init__.py +0 -0
  38. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/__init__.py +0 -0
  39. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/approval_context.py +0 -0
  40. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/approval_interface.py +0 -0
  41. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/approval_manager.py +0 -0
  42. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/config.py +0 -0
  43. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/file_system_manager.py +0 -0
  44. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/program_executor.py +0 -0
  45. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/read_before_write_errors.py +0 -0
  46. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/status_core.py +0 -0
  47. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/status_manager.py +0 -0
  48. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/tool_definitions.py +0 -0
  49. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/types.py +0 -0
  50. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/workflow_orchestrator.py +0 -0
  51. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent_engine.py +0 -0
  52. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent_managers.py +0 -0
  53. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent_mode_manager.py +0 -0
  54. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/chat_manager.py +0 -0
  55. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/config_manager.py +0 -0
  56. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/config_migration.py +0 -0
  57. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/config_validator.py +0 -0
  58. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/conversation_manager.py +0 -0
  59. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/engine.py +0 -0
  60. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/env_loader.py +0 -0
  61. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/fallback_manager.py +0 -0
  62. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/health_monitor.py +0 -0
  63. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/history_manager.py +0 -0
  64. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/hooks.py +0 -0
  65. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/mcp_integration_layer.py +0 -0
  66. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/models.py +0 -0
  67. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/prompt_enhancer.py +0 -0
  68. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/provider_capabilities.py +0 -0
  69. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/provider_initializer.py +0 -0
  70. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/provider_registry.py +0 -0
  71. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/rate_limit_fallback.py +0 -0
  72. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/__init__.py +0 -0
  73. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/approval_workflow.py +0 -0
  74. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/audit_logger.py +0 -0
  75. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/permission_controller.py +0 -0
  76. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/permission_rules.py +0 -0
  77. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/sandbox_manager.py +0 -0
  78. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/security_manager.py +0 -0
  79. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/signal_handler.py +0 -0
  80. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/__init__.py +0 -0
  81. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/emitter.py +0 -0
  82. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/jsonl_writer.py +0 -0
  83. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/schema.py +0 -0
  84. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/__init__.py +0 -0
  85. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/judge.py +0 -0
  86. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/loop.py +0 -0
  87. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/models.py +0 -0
  88. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/orchestrator.py +0 -0
  89. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/planner.py +0 -0
  90. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/prompts.py +0 -0
  91. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/refs.py +0 -0
  92. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/render.py +0 -0
  93. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/worker.py +0 -0
  94. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/mcp/__init__.py +0 -0
  95. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/mcp/client.py +0 -0
  96. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/mcp/manager.py +0 -0
  97. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/__init__.py +0 -0
  98. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/azure.py +0 -0
  99. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/base.py +0 -0
  100. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/cache_tokens.py +0 -0
  101. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/claude.py +0 -0
  102. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/claude_code.py +0 -0
  103. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/claude_credentials.py +0 -0
  104. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/cohere.py +0 -0
  105. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/digitalocean.py +0 -0
  106. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/factory.py +0 -0
  107. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/gemini.py +0 -0
  108. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/mistral.py +0 -0
  109. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/ollama.py +0 -0
  110. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/openai.py +0 -0
  111. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/openai_compatible.py +0 -0
  112. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/openrouter.py +0 -0
  113. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/perplexity.py +0 -0
  114. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/vertex.py +0 -0
  115. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/xai.py +0 -0
  116. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/__init__.py +0 -0
  117. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/__init__.py +0 -0
  118. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/app.py +0 -0
  119. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/cli.py +0 -0
  120. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/models.py +0 -0
  121. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/sources.py +0 -0
  122. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/widgets.py +0 -0
  123. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/__init__.py +0 -0
  124. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/cancellation_handler.py +0 -0
  125. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/progress_indicator.py +0 -0
  126. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/streaming_display.py +0 -0
  127. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/turn_activity.py +0 -0
  128. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/__init__.py +0 -0
  129. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/error_handler.py +0 -0
  130. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/errors.py +0 -0
  131. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/retry.py +0 -0
  132. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/SOURCES.txt +0 -0
  133. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
  134. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/entry_points.txt +0 -0
  135. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/requires.txt +0 -0
  136. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/top_level.txt +0 -0
  137. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/setup.cfg +0 -0
  138. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_integration_compatibility.py +0 -0
  139. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_preview_format.py +0 -0
  140. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_remember.py +0 -0
  141. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_system.py +0 -0
  142. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_azure_provider.py +0 -0
  143. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_code_provider.py +0 -0
  144. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_credentials.py +0 -0
  145. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_prompt_cache.py +0 -0
  146. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_provider.py +0 -0
  147. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_cohere_provider.py +0 -0
  148. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_command_approval_security.py +0 -0
  149. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_config_comprehensive.py +0 -0
  150. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_config_migration_passthrough.py +0 -0
  151. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_conversation_history.py +0 -0
  152. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_conversation_manager.py +0 -0
  153. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_core_engine.py +0 -0
  154. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_digitalocean_provider.py +0 -0
  155. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_enhanced_model_info.py +0 -0
  156. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_env_loader.py +0 -0
  157. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_error_handling_robustness.py +0 -0
  158. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_execution_timeout_errors.py +0 -0
  159. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_fallback_manager.py +0 -0
  160. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_fixtures.py +0 -0
  161. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_gemini_provider.py +0 -0
  162. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_hooks.py +0 -0
  163. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_httpx_compatibility.py +0 -0
  164. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_import_validation.py +0 -0
  165. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_interface_smoke_tests.py +0 -0
  166. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mcp_integration.py +0 -0
  167. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mcp_integration_layer.py +0 -0
  168. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mcp_management_commands.py +0 -0
  169. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mistral_provider.py +0 -0
  170. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_models.py +0 -0
  171. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_ollama_provider.py +0 -0
  172. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_compatible_provider.py +0 -0
  173. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_context_fit.py +0 -0
  174. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_provider_tools.py +0 -0
  175. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_request_timeout.py +0 -0
  176. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_streaming.py +0 -0
  177. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openrouter_provider.py +0 -0
  178. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_permission_rules.py +0 -0
  179. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_perplexity_provider.py +0 -0
  180. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_program_executor.py +0 -0
  181. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_aliases.py +0 -0
  182. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_base.py +0 -0
  183. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_cache_tokens.py +0 -0
  184. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_capability_consistency.py +0 -0
  185. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_discovery.py +0 -0
  186. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_integration.py +0 -0
  187. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_registry.py +0 -0
  188. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_rate_limit_fallback.py +0 -0
  189. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_retry.py +0 -0
  190. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_security_validation.py +0 -0
  191. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_system_integration.py +0 -0
  192. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_system_prompts.py +0 -0
  193. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_tool_calling_integration.py +0 -0
  194. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_tool_handler.py +0 -0
  195. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_vertex_provider.py +0 -0
  196. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_web_request_markers.py +0 -0
  197. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_workflows_comprehensive.py +0 -0
  198. {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_xai_provider.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omnimancer-cli
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: A unified command-line interface for multiple AI language models
5
5
  Author-email: Kellan Strong <kellan@jite.ai>
6
6
  License: MIT
@@ -16,7 +16,7 @@ from urllib.parse import urljoin, urlparse
16
16
 
17
17
  import aiohttp
18
18
  import html2text
19
- from bs4 import BeautifulSoup
19
+ from bs4 import BeautifulSoup, Tag
20
20
  from readability import Document
21
21
 
22
22
  from ..security import SecurityManager
@@ -668,6 +668,9 @@ class WebClient:
668
668
  # Extract links
669
669
  links: List[Dict[str, str]] = []
670
670
  for link in soup.find_all("a", href=True):
671
+ # bs4>=4.13 types find_all() as PageElement | Tag | NavigableString
672
+ if not isinstance(link, Tag):
673
+ continue
671
674
  href = str(link["href"])
672
675
  text = link.get_text().strip()
673
676
  if href and text:
@@ -677,6 +680,8 @@ class WebClient:
677
680
  # Extract images
678
681
  images: List[Dict[str, str]] = []
679
682
  for img in soup.find_all("img", src=True):
683
+ if not isinstance(img, Tag):
684
+ continue
680
685
  src = str(img["src"])
681
686
  alt_attr = img.get("alt", "")
682
687
  alt = str(alt_attr).strip() if alt_attr else ""
@@ -488,18 +488,26 @@ class BedrockProvider(BaseProvider):
488
488
 
489
489
  def _convert_tool_to_bedrock_format(self, tool: ToolDefinition) -> Dict:
490
490
  """
491
- Convert tool definition to Bedrock format.
491
+ Convert tool definition to Bedrock Converse format.
492
+
493
+ Converse requires every entry in ``toolConfig.tools`` to set one of
494
+ toolSpec, systemTool, modelTool or cachePoint, and it nests the JSON
495
+ Schema under ``inputSchema.json``. Sending the Anthropic Messages
496
+ shape (name/description/input_schema at the top level) is a hard
497
+ ValidationException on toolConfig.tool.0.
492
498
 
493
499
  Args:
494
500
  tool: Tool definition
495
501
 
496
502
  Returns:
497
- Tool formatted for Bedrock API
503
+ Tool formatted for the Bedrock Converse API
498
504
  """
499
505
  return {
500
- "name": tool.name,
501
- "description": tool.description,
502
- "input_schema": tool.parameters,
506
+ "toolSpec": {
507
+ "name": tool.name,
508
+ "description": tool.description,
509
+ "inputSchema": {"json": tool.parameters},
510
+ }
503
511
  }
504
512
 
505
513
  def _handle_response(self, response: httpx.Response) -> ChatResponse:
@@ -587,14 +595,19 @@ class BedrockProvider(BaseProvider):
587
595
  text_content = ""
588
596
  tool_calls = []
589
597
 
598
+ # Converse tags content blocks by key, not by a "type"
599
+ # field: text is {"text": ...} and a call is
600
+ # {"toolUse": {"toolUseId", "name", "input"}}.
590
601
  for block in content_blocks:
591
- if block.get("type") == "text":
592
- text_content += block.get("text", "")
593
- elif block.get("type") == "toolUse":
602
+ if "text" in block:
603
+ text_content += block.get("text") or ""
604
+ elif "toolUse" in block:
605
+ tool_use = block.get("toolUse") or {}
594
606
  tool_calls.append(
595
607
  ToolCall(
596
- name=block.get("name", ""),
597
- arguments=block.get("input", {}),
608
+ name=tool_use.get("name", ""),
609
+ arguments=tool_use.get("input") or {},
610
+ id=tool_use.get("toolUseId"),
598
611
  )
599
612
  )
600
613
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omnimancer-cli
3
- Version: 0.3.1
3
+ Version: 0.3.2
4
4
  Summary: A unified command-line interface for multiple AI language models
5
5
  Author-email: Kellan Strong <kellan@jite.ai>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "omnimancer-cli"
7
- version = "0.3.1"
7
+ version = "0.3.2"
8
8
  description = "A unified command-line interface for multiple AI language models"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -158,17 +158,24 @@ def mock_converse_response():
158
158
 
159
159
  @pytest.fixture
160
160
  def mock_tool_response():
161
- """Create a mock Bedrock Converse API response with tool use."""
161
+ """Create a mock Bedrock Converse API response with tool use.
162
+
163
+ Converse identifies content blocks by key, not by a ``type`` field:
164
+ a text block is ``{"text": ...}`` and a tool call is
165
+ ``{"toolUse": {"toolUseId", "name", "input"}}``.
166
+ """
162
167
  return {
163
168
  "output": {
164
169
  "message": {
165
170
  "role": "assistant",
166
171
  "content": [
167
- {"type": "text", "text": "I will query the database."},
172
+ {"text": "I will query the database."},
168
173
  {
169
- "type": "toolUse",
170
- "name": "query_database",
171
- "input": {"sql": "SELECT * FROM users LIMIT 10"},
174
+ "toolUse": {
175
+ "toolUseId": "tooluse_abc123",
176
+ "name": "query_database",
177
+ "input": {"sql": "SELECT * FROM users LIMIT 10"},
178
+ }
172
179
  },
173
180
  ],
174
181
  }
@@ -320,13 +327,33 @@ class TestBedrockProviderRequestPreparation:
320
327
  assert len(body["toolConfig"]["tools"]) == 2
321
328
 
322
329
  def test_convert_tool_to_bedrock_format(self, bedrock_provider, sample_tools):
323
- """Test tool conversion to Bedrock format."""
330
+ """Tools are converted to the Converse toolSpec shape."""
324
331
  tool = sample_tools[0]
325
332
  bedrock_tool = bedrock_provider._convert_tool_to_bedrock_format(tool)
326
333
 
327
- assert bedrock_tool["name"] == "query_database"
328
- assert bedrock_tool["description"] == "Run a query against the database"
329
- assert "input_schema" in bedrock_tool
334
+ assert set(bedrock_tool) == {"toolSpec"}
335
+ spec = bedrock_tool["toolSpec"]
336
+ assert spec["name"] == "query_database"
337
+ assert spec["description"] == "Run a query against the database"
338
+ # Converse nests the JSON Schema under inputSchema.json.
339
+ assert spec["inputSchema"] == {"json": tool.parameters}
340
+
341
+ def test_every_tool_entry_is_wrapped_in_toolspec(
342
+ self, bedrock_provider, sample_chat_context, sample_tools
343
+ ):
344
+ """Reproduces the Converse ValidationException on toolConfig.tool.0.
345
+
346
+ Converse rejects any entry in ``toolConfig.tools`` that does not set
347
+ one of toolSpec, systemTool, modelTool or cachePoint.
348
+ """
349
+ body_str = bedrock_provider._prepare_bedrock_request_with_tools(
350
+ "Query the DB", sample_chat_context, sample_tools
351
+ )
352
+ body = json.loads(body_str)
353
+
354
+ allowed = {"toolSpec", "systemTool", "modelTool", "cachePoint"}
355
+ for entry in body["toolConfig"]["tools"]:
356
+ assert allowed & set(entry), f"invalid tool entry: {entry}"
330
357
 
331
358
 
332
359
  # ---------------------------------------------------------------------------
@@ -560,6 +587,39 @@ class TestBedrockProviderToolCalling:
560
587
  assert response.tool_calls is not None
561
588
  assert len(response.tool_calls) == 1
562
589
  assert response.tool_calls[0].name == "query_database"
590
+ assert response.tool_calls[0].arguments == {
591
+ "sql": "SELECT * FROM users LIMIT 10"
592
+ }
593
+ assert response.tool_calls[0].id == "tooluse_abc123"
594
+
595
+ @pytest.mark.asyncio
596
+ async def test_text_only_converse_response_still_parsed_with_tools(
597
+ self, bedrock_provider, sample_chat_context, sample_tools
598
+ ):
599
+ """A tools request answered with text only yields content, no calls."""
600
+ mock_response = MagicMock()
601
+ mock_response.status_code = 200
602
+ mock_response.json.return_value = {
603
+ "output": {
604
+ "message": {
605
+ "role": "assistant",
606
+ "content": [{"text": "No query needed."}],
607
+ }
608
+ },
609
+ "usage": {"inputTokens": 7, "outputTokens": 4},
610
+ }
611
+
612
+ with patch("httpx.AsyncClient") as mock_client:
613
+ mock_client.return_value.__aenter__.return_value.post = AsyncMock(
614
+ return_value=mock_response
615
+ )
616
+
617
+ response = await bedrock_provider.send_message_with_tools(
618
+ "Say hi", sample_chat_context, sample_tools
619
+ )
620
+
621
+ assert response.content == "No query needed."
622
+ assert response.tool_calls is None
563
623
 
564
624
  @pytest.mark.asyncio
565
625
  async def test_send_message_with_tools_authentication_error(
File without changes
File without changes
File without changes