omnimancer-cli 0.3.5__tar.gz → 0.3.6__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.5 → omnimancer_cli-0.3.6}/PKG-INFO +1 -1
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/engine.py +40 -9
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/env_loader.py +4 -2
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/provider_initializer.py +31 -1
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/bedrock.py +33 -12
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer_cli.egg-info/PKG-INFO +1 -1
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/pyproject.toml +1 -1
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_bedrock_provider.py +103 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/LICENSE +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/README.md +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omn_fleet_hook.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/__main__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/agent_loop.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/approval_formatter.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/approval_integration.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/approval_prompt.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/command_dispatch.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/commands.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/completion.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/display.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/dynamic_commands.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/file_mentions.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/h2l_command.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/h2l_headless.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/handlers/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/headless.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/headless_checkpoint.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/interface.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/prompt_input.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/pt_completion.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/session.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/subagent.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/system_prompts.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/tool_handler.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/turn_notify.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/cli/usage.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/approval_context.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/approval_interface.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/approval_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/config.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/file_system_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/program_executor.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/read_before_write_errors.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/status_core.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/status_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/tool_definitions.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/types.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/web_client.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/workflow_orchestrator.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent_engine.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent_managers.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent_mode_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/chat_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/config_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/config_migration.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/config_validator.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/conversation_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/fallback_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/health_monitor.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/history_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/hooks.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/mcp_integration_layer.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/models.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/prompt_enhancer.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/provider_capabilities.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/provider_registry.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/provider_resolver.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/rate_limit_fallback.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/approval_workflow.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/audit_logger.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/permission_controller.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/permission_rules.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/sandbox_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/security/security_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/core/signal_handler.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/events/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/events/emitter.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/events/jsonl_writer.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/events/schema.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/judge.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/loop.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/models.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/orchestrator.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/planner.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/prompts.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/refs.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/render.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/h2l/worker.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/mcp/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/mcp/client.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/mcp/manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/azure.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/base.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/cache_tokens.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/claude.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/claude_code.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/claude_credentials.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/cohere.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/digitalocean.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/factory.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/gemini.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/mistral.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/ollama.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/openai.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/openai_compatible.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/openrouter.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/perplexity.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/vertex.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/providers/xai.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/fleet/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/fleet/app.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/fleet/cli.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/fleet/models.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/fleet/sources.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/tui/fleet/widgets.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/ui/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/ui/cancellation_handler.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/ui/progress_indicator.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/ui/streaming_display.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/ui/turn_activity.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/utils/__init__.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/utils/error_handler.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/utils/errors.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer/utils/retry.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer_cli.egg-info/SOURCES.txt +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer_cli.egg-info/dependency_links.txt +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer_cli.egg-info/entry_points.txt +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer_cli.egg-info/requires.txt +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/omnimancer_cli.egg-info/top_level.txt +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/setup.cfg +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_approval_integration_compatibility.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_approval_preview_format.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_approval_remember.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_approval_system.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_azure_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_claude_code_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_claude_credentials.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_claude_prompt_cache.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_claude_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_cohere_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_command_approval_security.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_config_comprehensive.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_config_migration_passthrough.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_conversation_history.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_conversation_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_core_engine.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_digitalocean_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_enhanced_model_info.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_env_loader.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_error_handling_robustness.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_execution_timeout_errors.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_fallback_manager.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_fixtures.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_gemini_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_hooks.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_httpx_compatibility.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_import_validation.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_interface_smoke_tests.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_mcp_integration.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_mcp_integration_layer.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_mcp_management_commands.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_mistral_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_models.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_ollama_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_openai_compatible_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_openai_context_fit.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_openai_provider_tools.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_openai_request_timeout.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_openai_streaming.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_openrouter_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_permission_rules.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_perplexity_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_program_executor.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_aliases.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_base.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_cache_tokens.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_capability_consistency.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_discovery.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_integration.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_provider_registry.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_rate_limit_fallback.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_retry.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_security_validation.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_system_integration.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_system_prompts.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_tool_calling_integration.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_tool_handler.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_vertex_provider.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_web_request_markers.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_workflows_comprehensive.py +0 -0
- {omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/tests/test_xai_provider.py +0 -0
|
@@ -182,11 +182,12 @@ class CoreEngine:
|
|
|
182
182
|
# DigitalOcean request). Leave it unset so the user gets a
|
|
183
183
|
# clear error naming the provider.
|
|
184
184
|
self._unavailable_default_provider = config.default_provider
|
|
185
|
+
# One accurate line instead of a guess; the full
|
|
186
|
+
# explanation is built on demand by _no_provider_error.
|
|
185
187
|
logger.error(
|
|
186
|
-
"Default provider '%s' is
|
|
187
|
-
"initialize (missing or invalid API key?). Not falling "
|
|
188
|
-
"back to another provider.",
|
|
188
|
+
"Default provider '%s' is not available: %s",
|
|
189
189
|
config.default_provider,
|
|
190
|
+
self._no_provider_error(),
|
|
190
191
|
)
|
|
191
192
|
elif self.providers:
|
|
192
193
|
# No default configured — use first available provider.
|
|
@@ -306,14 +307,44 @@ class CoreEngine:
|
|
|
306
307
|
missing, rather than a generic "no provider" message.
|
|
307
308
|
"""
|
|
308
309
|
unavailable = getattr(self, "_unavailable_default_provider", None)
|
|
309
|
-
if unavailable:
|
|
310
|
+
if not unavailable:
|
|
311
|
+
return "No provider available. Please configure a provider first."
|
|
312
|
+
|
|
313
|
+
env_prefix = "OMNIMANCER_" + unavailable.upper().replace("-", "_")
|
|
314
|
+
try:
|
|
315
|
+
from .provider_resolver import effective_providers
|
|
316
|
+
|
|
317
|
+
entry = effective_providers(self.config_manager).get(unavailable)
|
|
318
|
+
except Exception as exc: # diagnostics must not raise
|
|
319
|
+
logger.debug(f"Could not inspect entry for {unavailable}: {exc}")
|
|
320
|
+
entry = None
|
|
321
|
+
|
|
322
|
+
if entry is None:
|
|
310
323
|
return (
|
|
311
|
-
f"Provider '{unavailable}' is selected
|
|
312
|
-
f"
|
|
313
|
-
f"
|
|
314
|
-
f"
|
|
324
|
+
f"Provider '{unavailable}' is selected as the default but is "
|
|
325
|
+
f"not configured: there is no entry for it and no "
|
|
326
|
+
f"{env_prefix}_API_KEY in the environment. Add it with "
|
|
327
|
+
f"'/config set-provider {unavailable}', or pick a different "
|
|
328
|
+
f"default with '/switch'."
|
|
315
329
|
)
|
|
316
|
-
|
|
330
|
+
|
|
331
|
+
if not (getattr(entry, "model", "") or "").strip():
|
|
332
|
+
return (
|
|
333
|
+
f"Provider '{unavailable}' has no model configured, so it was "
|
|
334
|
+
f"not started. Set {env_prefix}_MODEL, or run '/model' to pick "
|
|
335
|
+
f"one."
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
from .provider_initializer import ProviderInitializer
|
|
339
|
+
|
|
340
|
+
reason = ProviderInitializer.get_last_init_errors().get(unavailable)
|
|
341
|
+
if reason:
|
|
342
|
+
return f"Provider '{unavailable}' did not start: {reason}"
|
|
343
|
+
return (
|
|
344
|
+
f"Provider '{unavailable}' is configured but did not start. Check "
|
|
345
|
+
f"its credentials ('/config set-provider {unavailable}' or "
|
|
346
|
+
f"{env_prefix}_API_KEY) and try again."
|
|
347
|
+
)
|
|
317
348
|
|
|
318
349
|
# ------------------------------------------------------------------
|
|
319
350
|
# Fallback wiring
|
|
@@ -230,7 +230,7 @@ def apply_env_overrides(config: "Config") -> "Config":
|
|
|
230
230
|
model=overrides.get("model", ""),
|
|
231
231
|
)
|
|
232
232
|
effective.providers[name] = provider_config
|
|
233
|
-
logger.
|
|
233
|
+
logger.debug(f"Created provider '{name}' from environment overrides")
|
|
234
234
|
|
|
235
235
|
if "api_key" in overrides:
|
|
236
236
|
provider_config.api_key = overrides["api_key"]
|
|
@@ -241,6 +241,8 @@ def apply_env_overrides(config: "Config") -> "Config":
|
|
|
241
241
|
|
|
242
242
|
if default_override:
|
|
243
243
|
effective.default_provider = default_override
|
|
244
|
-
logger.
|
|
244
|
+
logger.debug(
|
|
245
|
+
f"Default provider overridden from environment: {default_override}"
|
|
246
|
+
)
|
|
245
247
|
|
|
246
248
|
return effective
|
|
@@ -44,6 +44,8 @@ class ProviderInitializer:
|
|
|
44
44
|
# Configuration
|
|
45
45
|
_lazy_loading_enabled: bool = True
|
|
46
46
|
_cache_enabled: bool = True
|
|
47
|
+
# provider name -> why it failed, from the most recent initialization
|
|
48
|
+
_last_init_errors: Dict[str, str] = {}
|
|
47
49
|
|
|
48
50
|
@classmethod
|
|
49
51
|
def get_provider_class(cls, provider_name: str) -> Type[BaseProvider]:
|
|
@@ -447,14 +449,35 @@ class ProviderInitializer:
|
|
|
447
449
|
provider_configs: Dictionary of provider configurations
|
|
448
450
|
config_manager: Optional config manager for API key decryption
|
|
449
451
|
|
|
452
|
+
An entry with no model id is *incomplete*, not broken: environment
|
|
453
|
+
materialized entries (``OMNIMANCER_<PROVIDER>_API_KEY`` with no
|
|
454
|
+
``_MODEL``) are legitimate when the model comes from somewhere else,
|
|
455
|
+
such as an H2L ``--high <entry>:<model>`` ref. Those are skipped
|
|
456
|
+
without an error; real failures are recorded so callers can report
|
|
457
|
+
the actual cause instead of guessing at one.
|
|
458
|
+
|
|
450
459
|
Returns:
|
|
451
460
|
Dictionary of initialized provider instances
|
|
452
461
|
"""
|
|
453
462
|
from ..providers.factory import ProviderFactory
|
|
454
463
|
|
|
455
464
|
providers = {}
|
|
465
|
+
errors: Dict[str, str] = {}
|
|
456
466
|
|
|
457
467
|
for provider_name, config in provider_configs.items():
|
|
468
|
+
if not (getattr(config, "model", "") or "").strip():
|
|
469
|
+
env_var = (
|
|
470
|
+
"OMNIMANCER_" + provider_name.upper().replace("-", "_") + "_MODEL"
|
|
471
|
+
)
|
|
472
|
+
logger.info(
|
|
473
|
+
"Provider '%s' has no model configured; not started. "
|
|
474
|
+
"Set %s or '/config set-provider %s'. Model refs that "
|
|
475
|
+
"carry their own model (H2L tiers) still work.",
|
|
476
|
+
provider_name,
|
|
477
|
+
env_var,
|
|
478
|
+
provider_name,
|
|
479
|
+
)
|
|
480
|
+
continue
|
|
458
481
|
try:
|
|
459
482
|
# Use ProviderFactory instead of direct class loading
|
|
460
483
|
provider = ProviderFactory.create_provider(
|
|
@@ -463,12 +486,19 @@ class ProviderInitializer:
|
|
|
463
486
|
providers[provider_name] = provider
|
|
464
487
|
logger.info(f"Initialized provider: {provider_name}")
|
|
465
488
|
except Exception as e:
|
|
466
|
-
|
|
489
|
+
errors[provider_name] = str(e)
|
|
490
|
+
logger.error(f"Provider '{provider_name}' did not start: {e}")
|
|
467
491
|
# Continue with other providers instead of failing completely
|
|
468
492
|
continue
|
|
469
493
|
|
|
494
|
+
cls._last_init_errors = errors
|
|
470
495
|
return providers
|
|
471
496
|
|
|
497
|
+
@classmethod
|
|
498
|
+
def get_last_init_errors(cls) -> Dict[str, str]:
|
|
499
|
+
"""Why each provider failed during the most recent initialization."""
|
|
500
|
+
return dict(getattr(cls, "_last_init_errors", {}) or {})
|
|
501
|
+
|
|
472
502
|
@classmethod
|
|
473
503
|
def preload_model_info(cls, provider_names: List[str]) -> None:
|
|
474
504
|
"""
|
|
@@ -70,6 +70,14 @@ class BedrockProvider(BaseProvider):
|
|
|
70
70
|
# AWS-specific configuration
|
|
71
71
|
self.aws_region = kwargs.get("aws_region", "us-east-1")
|
|
72
72
|
|
|
73
|
+
# Chat-completion timeout. ProviderConfig's field is `timeout`;
|
|
74
|
+
# `request_timeout` is accepted as an alias, then
|
|
75
|
+
# OMNIMANCER_REQUEST_TIMEOUT, then DEFAULT_REQUEST_TIMEOUT. A long
|
|
76
|
+
# agent turn on a large model does not fit in the old hardcoded 30s.
|
|
77
|
+
self.request_timeout = self._resolve_request_timeout(
|
|
78
|
+
kwargs.get("request_timeout") or kwargs.get("timeout")
|
|
79
|
+
)
|
|
80
|
+
|
|
73
81
|
# Standard parameters. Bedrock fronts third-party models that reject
|
|
74
82
|
# temperature/topP in inferenceConfig outright, and nothing in
|
|
75
83
|
# Omnimancer lets a user pick these values, so an unset param stays
|
|
@@ -82,6 +90,21 @@ class BedrockProvider(BaseProvider):
|
|
|
82
90
|
# Build base URL for Bedrock API key authentication
|
|
83
91
|
self.base_url = f"https://bedrock-runtime.{self.aws_region}.amazonaws.com"
|
|
84
92
|
|
|
93
|
+
def _timeout_network_error(self) -> NetworkError:
|
|
94
|
+
"""The NetworkError raised when a Converse request times out."""
|
|
95
|
+
return NetworkError(
|
|
96
|
+
f"Request to AWS Bedrock API timed out after "
|
|
97
|
+
f"{self.request_timeout:.0f}s. Raise it with this provider's "
|
|
98
|
+
f"timeout (providers.<name>.timeout in config.json) or the "
|
|
99
|
+
f"OMNIMANCER_REQUEST_TIMEOUT environment variable."
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
def _model_for_url(self) -> str:
|
|
103
|
+
"""The path segment for this model: ARNs carry an unusable prefix."""
|
|
104
|
+
if self._is_arn(self.model):
|
|
105
|
+
return self._extract_model_id_from_arn(self.model)
|
|
106
|
+
return self.model
|
|
107
|
+
|
|
85
108
|
def _is_arn(self, model_id: str) -> bool:
|
|
86
109
|
"""Check if the model ID is in ARN format."""
|
|
87
110
|
return model_id.startswith("arn:aws:bedrock:")
|
|
@@ -144,7 +167,7 @@ class BedrockProvider(BaseProvider):
|
|
|
144
167
|
request_body = self._prepare_bedrock_request(message, context)
|
|
145
168
|
|
|
146
169
|
# Build URL for the specific model
|
|
147
|
-
url = f"{self.base_url}/model/{self.
|
|
170
|
+
url = f"{self.base_url}/model/{self._model_for_url()}/converse"
|
|
148
171
|
|
|
149
172
|
# Create headers with Bearer token authentication
|
|
150
173
|
headers = {
|
|
@@ -155,14 +178,17 @@ class BedrockProvider(BaseProvider):
|
|
|
155
178
|
# Make API request
|
|
156
179
|
async with httpx.AsyncClient() as client:
|
|
157
180
|
response = await client.post(
|
|
158
|
-
url,
|
|
181
|
+
url,
|
|
182
|
+
headers=headers,
|
|
183
|
+
content=request_body,
|
|
184
|
+
timeout=self.request_timeout,
|
|
159
185
|
)
|
|
160
186
|
|
|
161
187
|
# Handle response
|
|
162
188
|
return self._handle_response(response)
|
|
163
189
|
|
|
164
190
|
except httpx.TimeoutException:
|
|
165
|
-
raise
|
|
191
|
+
raise self._timeout_network_error()
|
|
166
192
|
except httpx.RequestError as e:
|
|
167
193
|
raise NetworkError(f"Network error: {e}")
|
|
168
194
|
except Exception as e:
|
|
@@ -191,13 +217,8 @@ class BedrockProvider(BaseProvider):
|
|
|
191
217
|
message, context, available_tools
|
|
192
218
|
)
|
|
193
219
|
|
|
194
|
-
# Build URL -
|
|
195
|
-
|
|
196
|
-
# For ARN format, extract the actual model ID for the URL
|
|
197
|
-
model_for_url = self._extract_model_id_from_arn(self.model)
|
|
198
|
-
url = f"{self.base_url}/model" f"/{model_for_url}/converse"
|
|
199
|
-
else:
|
|
200
|
-
url = f"{self.base_url}/model" f"/{self.model}/converse"
|
|
220
|
+
# Build URL - an ARN model id is not usable as a path segment
|
|
221
|
+
url = f"{self.base_url}/model/{self._model_for_url()}/converse"
|
|
201
222
|
|
|
202
223
|
# Create headers with Bearer token authentication
|
|
203
224
|
headers = {
|
|
@@ -211,14 +232,14 @@ class BedrockProvider(BaseProvider):
|
|
|
211
232
|
url,
|
|
212
233
|
headers=headers,
|
|
213
234
|
content=request_body,
|
|
214
|
-
timeout=
|
|
235
|
+
timeout=self.request_timeout,
|
|
215
236
|
)
|
|
216
237
|
|
|
217
238
|
# Handle response with tool calls
|
|
218
239
|
return self._handle_response_with_tools(response)
|
|
219
240
|
|
|
220
241
|
except httpx.TimeoutException:
|
|
221
|
-
raise
|
|
242
|
+
raise self._timeout_network_error()
|
|
222
243
|
except httpx.RequestError as e:
|
|
223
244
|
raise NetworkError(f"Network error: {e}")
|
|
224
245
|
except Exception as e:
|
|
@@ -421,6 +421,86 @@ class TestBedrockProviderRequestPreparation:
|
|
|
421
421
|
# ---------------------------------------------------------------------------
|
|
422
422
|
|
|
423
423
|
|
|
424
|
+
class TestBedrockProviderRequestTimeout:
|
|
425
|
+
"""Bedrock hardcoded 30s while the base class already had the knob.
|
|
426
|
+
|
|
427
|
+
BaseProvider._resolve_request_timeout (explicit config, then
|
|
428
|
+
OMNIMANCER_REQUEST_TIMEOUT, then DEFAULT_REQUEST_TIMEOUT) existed for
|
|
429
|
+
exactly this reason: a long agent turn on a large model needs more than
|
|
430
|
+
30 seconds, and only the OpenAI family honoured it.
|
|
431
|
+
"""
|
|
432
|
+
|
|
433
|
+
@pytest.fixture(autouse=True)
|
|
434
|
+
def no_env_timeout(self, monkeypatch):
|
|
435
|
+
monkeypatch.delenv("OMNIMANCER_REQUEST_TIMEOUT", raising=False)
|
|
436
|
+
yield
|
|
437
|
+
|
|
438
|
+
def test_default_is_the_shared_default_not_thirty(self):
|
|
439
|
+
provider = BedrockProvider(api_key="k", model=_SONNET_MODEL)
|
|
440
|
+
assert provider.request_timeout == BedrockProvider.DEFAULT_REQUEST_TIMEOUT
|
|
441
|
+
assert provider.request_timeout > 30.0
|
|
442
|
+
|
|
443
|
+
def test_configured_timeout_wins(self):
|
|
444
|
+
provider = BedrockProvider(api_key="k", model=_SONNET_MODEL, timeout=600)
|
|
445
|
+
assert provider.request_timeout == 600.0
|
|
446
|
+
|
|
447
|
+
def test_env_timeout_is_honoured(self, monkeypatch):
|
|
448
|
+
monkeypatch.setenv("OMNIMANCER_REQUEST_TIMEOUT", "300")
|
|
449
|
+
provider = BedrockProvider(api_key="k", model=_SONNET_MODEL)
|
|
450
|
+
assert provider.request_timeout == 300.0
|
|
451
|
+
|
|
452
|
+
@pytest.mark.asyncio
|
|
453
|
+
async def test_send_message_uses_the_resolved_timeout(
|
|
454
|
+
self, sample_chat_context, mock_converse_response
|
|
455
|
+
):
|
|
456
|
+
provider = BedrockProvider(api_key="k", model=_SONNET_MODEL, timeout=450)
|
|
457
|
+
mock_response = MagicMock()
|
|
458
|
+
mock_response.status_code = 200
|
|
459
|
+
mock_response.json.return_value = mock_converse_response
|
|
460
|
+
|
|
461
|
+
with patch("httpx.AsyncClient") as mock_client:
|
|
462
|
+
mock_post = AsyncMock(return_value=mock_response)
|
|
463
|
+
mock_client.return_value.__aenter__.return_value.post = mock_post
|
|
464
|
+
await provider.send_message("Hello", sample_chat_context)
|
|
465
|
+
|
|
466
|
+
assert mock_post.call_args.kwargs["timeout"] == 450.0
|
|
467
|
+
|
|
468
|
+
@pytest.mark.asyncio
|
|
469
|
+
async def test_send_message_with_tools_uses_the_resolved_timeout(
|
|
470
|
+
self, sample_chat_context, sample_tools, mock_tool_response
|
|
471
|
+
):
|
|
472
|
+
provider = BedrockProvider(api_key="k", model=_SONNET_MODEL, timeout=450)
|
|
473
|
+
mock_response = MagicMock()
|
|
474
|
+
mock_response.status_code = 200
|
|
475
|
+
mock_response.json.return_value = mock_tool_response
|
|
476
|
+
|
|
477
|
+
with patch("httpx.AsyncClient") as mock_client:
|
|
478
|
+
mock_post = AsyncMock(return_value=mock_response)
|
|
479
|
+
mock_client.return_value.__aenter__.return_value.post = mock_post
|
|
480
|
+
await provider.send_message_with_tools(
|
|
481
|
+
"Hello", sample_chat_context, sample_tools
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
assert mock_post.call_args.kwargs["timeout"] == 450.0
|
|
485
|
+
|
|
486
|
+
@pytest.mark.asyncio
|
|
487
|
+
async def test_timeout_error_names_the_limit_and_the_knob(
|
|
488
|
+
self, sample_chat_context
|
|
489
|
+
):
|
|
490
|
+
"""A bare "timed out" leaves the user nothing to act on."""
|
|
491
|
+
provider = BedrockProvider(api_key="k", model=_SONNET_MODEL, timeout=45)
|
|
492
|
+
with patch("httpx.AsyncClient") as mock_client:
|
|
493
|
+
mock_client.return_value.__aenter__.return_value.post = AsyncMock(
|
|
494
|
+
side_effect=httpx.TimeoutException("too slow")
|
|
495
|
+
)
|
|
496
|
+
with pytest.raises(NetworkError) as exc:
|
|
497
|
+
await provider.send_message("Hello", sample_chat_context)
|
|
498
|
+
|
|
499
|
+
message = str(exc.value)
|
|
500
|
+
assert "45" in message
|
|
501
|
+
assert "OMNIMANCER_REQUEST_TIMEOUT" in message
|
|
502
|
+
|
|
503
|
+
|
|
424
504
|
class TestBedrockProviderARNRoutingBehaviour:
|
|
425
505
|
"""Test that ARN-format models result in correct URL construction.
|
|
426
506
|
|
|
@@ -460,6 +540,29 @@ class TestBedrockProviderARNRoutingBehaviour:
|
|
|
460
540
|
assert bare_model_id in call_url
|
|
461
541
|
assert "arn:aws:bedrock:" not in call_url
|
|
462
542
|
|
|
543
|
+
@pytest.mark.asyncio
|
|
544
|
+
async def test_send_message_uses_extracted_id_in_url_for_arn(
|
|
545
|
+
self, bedrock_provider_arn, sample_chat_context, mock_converse_response
|
|
546
|
+
):
|
|
547
|
+
"""The no-tools path must extract the ARN too.
|
|
548
|
+
|
|
549
|
+
send_message_with_tools extracted the bare model id while
|
|
550
|
+
send_message interpolated the whole ARN, so the same configured
|
|
551
|
+
model worked in agent mode and built a malformed URL in plain chat.
|
|
552
|
+
"""
|
|
553
|
+
mock_response = MagicMock()
|
|
554
|
+
mock_response.status_code = 200
|
|
555
|
+
mock_response.json.return_value = mock_converse_response
|
|
556
|
+
|
|
557
|
+
with patch("httpx.AsyncClient") as mock_client:
|
|
558
|
+
mock_post = AsyncMock(return_value=mock_response)
|
|
559
|
+
mock_client.return_value.__aenter__.return_value.post = mock_post
|
|
560
|
+
await bedrock_provider_arn.send_message("Hello", sample_chat_context)
|
|
561
|
+
|
|
562
|
+
call_url = mock_post.call_args[0][0]
|
|
563
|
+
assert _SONNET_ARN.split("/")[-1] in call_url
|
|
564
|
+
assert "arn:aws:bedrock:" not in call_url
|
|
565
|
+
|
|
463
566
|
@pytest.mark.asyncio
|
|
464
567
|
async def test_send_message_standard_model_uses_model_id_in_url(
|
|
465
568
|
self, bedrock_provider, sample_chat_context
|
|
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.5 → omnimancer_cli-0.3.6}/omnimancer/core/agent/read_before_write_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/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
|
{omnimancer_cli-0.3.5 → omnimancer_cli-0.3.6}/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.5 → omnimancer_cli-0.3.6}/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
|