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.
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/PKG-INFO +1 -1
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/web_client.py +6 -1
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/bedrock.py +23 -10
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/PKG-INFO +1 -1
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/pyproject.toml +1 -1
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_bedrock_provider.py +69 -9
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/LICENSE +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/README.md +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omn_fleet_hook.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/__main__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/agent_loop.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/approval_formatter.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/approval_integration.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/approval_prompt.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/command_dispatch.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/commands.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/completion.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/display.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/dynamic_commands.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/file_mentions.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/h2l_command.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/h2l_headless.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/handlers/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/headless.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/headless_checkpoint.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/interface.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/prompt_input.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/pt_completion.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/session.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/subagent.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/system_prompts.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/tool_handler.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/turn_notify.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/cli/usage.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/approval_context.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/approval_interface.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/approval_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/config.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/file_system_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/program_executor.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/read_before_write_errors.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/status_core.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/status_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/tool_definitions.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/types.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/workflow_orchestrator.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent_engine.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent_managers.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent_mode_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/chat_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/config_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/config_migration.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/config_validator.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/conversation_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/engine.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/env_loader.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/fallback_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/health_monitor.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/history_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/hooks.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/mcp_integration_layer.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/models.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/prompt_enhancer.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/provider_capabilities.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/provider_initializer.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/provider_registry.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/rate_limit_fallback.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/approval_workflow.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/audit_logger.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/permission_controller.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/permission_rules.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/sandbox_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/security_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/signal_handler.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/emitter.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/jsonl_writer.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/events/schema.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/judge.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/loop.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/models.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/orchestrator.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/planner.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/prompts.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/refs.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/render.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/h2l/worker.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/mcp/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/mcp/client.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/mcp/manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/azure.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/base.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/cache_tokens.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/claude.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/claude_code.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/claude_credentials.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/cohere.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/digitalocean.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/factory.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/gemini.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/mistral.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/ollama.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/openai.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/openai_compatible.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/openrouter.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/perplexity.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/vertex.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/providers/xai.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/app.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/cli.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/models.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/sources.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/tui/fleet/widgets.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/cancellation_handler.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/progress_indicator.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/streaming_display.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/ui/turn_activity.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/__init__.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/error_handler.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/errors.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/utils/retry.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/SOURCES.txt +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/entry_points.txt +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/requires.txt +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer_cli.egg-info/top_level.txt +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/setup.cfg +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_integration_compatibility.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_preview_format.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_remember.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_system.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_azure_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_code_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_credentials.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_prompt_cache.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_claude_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_cohere_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_command_approval_security.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_config_comprehensive.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_config_migration_passthrough.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_conversation_history.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_conversation_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_core_engine.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_digitalocean_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_enhanced_model_info.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_env_loader.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_error_handling_robustness.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_execution_timeout_errors.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_fallback_manager.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_fixtures.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_gemini_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_hooks.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_httpx_compatibility.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_import_validation.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_interface_smoke_tests.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mcp_integration.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mcp_integration_layer.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mcp_management_commands.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_mistral_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_models.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_ollama_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_compatible_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_context_fit.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_provider_tools.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_request_timeout.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openai_streaming.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_openrouter_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_permission_rules.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_perplexity_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_program_executor.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_aliases.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_base.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_cache_tokens.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_capability_consistency.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_discovery.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_integration.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_provider_registry.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_rate_limit_fallback.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_retry.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_security_validation.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_system_integration.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_system_prompts.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_tool_calling_integration.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_tool_handler.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_vertex_provider.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_web_request_markers.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_workflows_comprehensive.py +0 -0
- {omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_xai_provider.py +0 -0
|
@@ -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
|
-
"
|
|
501
|
-
|
|
502
|
-
|
|
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
|
|
592
|
-
text_content += block.get("text"
|
|
593
|
-
elif
|
|
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=
|
|
597
|
-
arguments=
|
|
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
|
|
|
@@ -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
|
-
{"
|
|
172
|
+
{"text": "I will query the database."},
|
|
168
173
|
{
|
|
169
|
-
"
|
|
170
|
-
|
|
171
|
-
|
|
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
|
-
"""
|
|
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
|
|
328
|
-
|
|
329
|
-
assert "
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/read_before_write_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/agent/workflow_orchestrator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/omnimancer/core/security/permission_controller.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.3.1 → omnimancer_cli-0.3.2}/tests/test_approval_integration_compatibility.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|